Closed Bug 606465 Opened 14 years ago Closed 12 years ago

unable to delete addressbooks implemented as non+c++ components

Categories

(MailNews Core :: Address Book, defect)

defect
Not set
major

Tracking

(Not tracked)

RESOLVED WORKSFORME

People

(Reporter: WSourdeau, Unassigned)

Details

User-Agent:       Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.62 Safari/534.3
Build Identifier: Mozilla/5.0 (X11; U; Linux i686 (x86_64); fr; rv:1.9.2.4) Gecko/20100608 Lightning/1.0b2.102i Thunderbird/3.1 XPCOMViewer/0.9.

When attempting to delete such an addressbook, one gets the following error message:

Erreur : uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIAbManager.deleteAddressBook]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: chrome://messenger/content/addressbook/abCommon.js :: AbDeleteDirectory :: line 233"  data: no]


Here is a mail exchange with Mark Banner on that matter:


1) Wolfgang -> Mark

Hi Mark,


As discussed yesterday, here is my email with the details on how to reproduce the problem, how the CardDAV addressbook module works and my steps to deduce where the issue occurs...

CardDAV address books are implemented to behave like LDAP address books. Here is the code for the SCCreateCardDAVDirectoryMethod, in chrome/content/sogo-connector/addressbook/folder-handling.js:

function SCCreateCardDAVDirectory(description, url) {
    let abMgr = Components.classes["@mozilla.org/abmanager;1"]
                          .getService(Components.interfaces.nsIAbManager);
    let prefId = abMgr.newAddressBook(description, url.replace(/^http/, "carddav"), 0);

    return SCGetDirectoryFromURI("moz-abdavdirectory://" + prefId);
}

The "description" and "url" parameters are both string parameters. A call in this function results in an entry similar to this one in prefs.js:

user_pref("ldap_2.servers.Partage.description", "Partage");
user_pref("ldap_2.servers.Partage.filename", "ldap-26.mab");
user_pref("ldap_2.servers.Partage.uri", "carddavs://inverse.ca/SOGo/dav/hsimpson/Contacts/public/");

The "http" protocol prefix is replaced with "carddav" in order to make Thunderbird invoke the  "@mozilla.org/addressbook/directory-factory;1?name=carddav" factory service when instantiating those address books.

As you can see in js/CardDAVDirectory.js, the CardDAVDirectory class implements the following interfaces: nsIRDFResource, nsIRDFNode, nsIAbDirectory, nsISecurityCheckedComponent, nsIClassInfo and nsISupports. I guess a few of them might be useless but I have tried implemented all the ones that were requested via QueryInterface at some point during the running of Thunderbird in order to try solving  my problem.

All of this works quite well: addressbooks can be created, cards can be searched and displayed on the proper URL. If you want to test the feature, you can use "http://sogo-demo.inverse.ca/SOGo/dav/sogo1/Contacts/public/" with "sogo1" as value for both the username and password. Once an address book is created, you can however not delete it, which is the issue I am trying to solve...

When deleting an address book with the "Delete" button of the address book window, the following chain of methods is invoked: SCAbDeleteDirectory (addressbook.groupdav.overlay.js), AbDeleteDirectory, "@mozilla.org/abmanager;1".deleteAddressbook -> nsAbManager::DeleteAddressBook (nsAbManager.cpp), nsAbBSManager::DeleteDirectory (nsAbBSDirectory.cpp).
>From that method, NS_ERROR_FAILURE is returned via this code:

NS_IMETHODIMP nsAbBSDirectory::DeleteDirectory(nsIAbDirectory *directory)
{
  NS_ENSURE_ARG_POINTER(directory);

  nsresult rv = EnsureInitialized();
  NS_ENSURE_SUCCESS(rv, rv);

  DIR_Server *server = nsnull;
  mServers.Get(directory, &server);

  if (!server)
    return NS_ERROR_FAILURE;


And this is where I am stuck because I don't have enough knowledge to examine the XPCom components at stake with gdb. Basically, my question here is to know how and why the carddav directories are not included in the mServers hash while they have a proper entry in prefs.js... One of my hypothesis was that the "carddav" protocol was not defined and so I have implemented a corresponding nsINetworkProtocol object but without success...


2) Mark -> Wolfgang


Hi Wolfgang,

I've had a dig around, and I've had a look around and I can see where the problem is.

nsAbBSDirectory keeps a hash of the DIR_Server objects with the address of the nsIAbDirectory instances as the keys. Unfortunately this key mechanism is also the downfall for SoGo connector.

From what I can tell the javascript CardDAVDirectory instances that you have are being wrapped by xpconnect as they come across the javascript to cpp boundary. This is then causing different addresses for what is probably the same CardDAVDirectory instance. So when nsAbBSDirectory comes to look up the server to delete it, it fails as the key is different.

If you put debug in on the following:

http://hg.mozilla.org/comm-central/annotate/860cdad7425a/mailnews/addrbook/src/nsAbBSDirectory.cpp#l115
http://hg.mozilla.org/comm-central/annotate/860cdad7425a/mailnews/addrbook/src/nsAbBSDirectory.cpp#l295

Then you should be able to see that happening.

So therefore nsAbBSDirectory doesn't really support javascript instances at the moment. With regards to a possibly solution, it would seem that replacing mServers in nsAbBSDirectory would be the way to go.

nsAbBSDirectory::HasDirectory may be the only perf-critical function, though it is hard to tell - I believe the only RDF usage we have left for the address book is the list of address books in the address book window (all the menus etc are js generated). So if that function isn't called a lot per address book / mailing list, then we may be able to get away with replacing the hash with some different lookup system, or a different key.

Hopefully this helps you understand what's going on, and maybe gives you some pointers as well.


Reproducible: Always
Wolfgang, so did you do what I suggested re putting debug in?
Product: Thunderbird → MailNews Core
QA Contact: address-book → address-book
"From what I can tell the javascript CardDAVDirectory instances that you have
are being wrapped by xpconnect as they come across the javascript to cpp
boundary. This is then causing different addresses for what is probably the
same CardDAVDirectory instance. So when nsAbBSDirectory comes to look up the
server to delete it, it fails as the key is different."

This sound vaguely familiar with my experience with EWS. One of the main things that SkinkGlue accomplishes, is that it creates a clean C++ base object so that these duplicate issues do not appear.
I came across this code in calRecurrenceInfo.js which I presume is trying to solve this problem:


257         // Because xpcom objects can be wrapped in various ways, testing for
258         // mere == sometimes returns false even when it should be true.  Use
259         // the interface pointer returned by sip to avoid that problem.
260         var sip1 = Components.classes["@mozilla.org/supports-interface-pointer;1"]
261                             .createInstance(Components.interfaces.nsISupportsInterfacePointer);
262         sip1.data = aItem;
This problem seems to be fixed (in tb 10). I am thus closing this bugreport.
Status: UNCONFIRMED → RESOLVED
Closed: 12 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.