Places (bookmarks & history system) - API changes

Talk about add-ons and extension development.
Post Reply
User avatar
Ken Saunders
Posts: 1008
Joined: March 14th, 2005, 2:52 pm
Location: Mozillaopolis
Contact:

Places (bookmarks & history system) - API changes

Post by Ken Saunders »

Hi All,
I Just wanted to repost something that I came across that might affect some of you.

Ken


Heads up: add-ons using Places (bookmarks & history system) - API changes!
http://groups.google.com/group/mozilla. ... 8c19eb027#


Marco Bonardo
Jan 24, 5:17 pm
(Please followup-to mozilla.dev.extensions)

Dear add-ons developers,
as part of our goal to make history and bookmarks asynchronous, we are
starting removing some APIs, that in the last years have been replaced
by new asynchronous ones.
We are currently removing the last uses in the tests harness, but we are
not too far from the target. Current goal is Firefox21.

The work is tracked in https://bugzilla.mozilla.org/show_bug.cgi?id=834457

The following APIs will be removed:

(replaced by mozIAsyncFavicons)
nsIFaviconService::setFaviconUrlForPage
nsIFaviconService::setFaviconData
nsIFaviconService::getFaviconData
nsIFaviconService::getFaviconForPage
nsIFaviconService::setAndLoadFaviconForPage
nsIFaviconService::getFaviconImageForPage
nsIFaviconService::getFaviconDataAsDataURL

(replaced by mozIAsyncLivemarks)
nsILivemarkService::*
PlacesUtils.itemIsLivemark
PlacesUtils.nodeIsLivemarkContainer
PlacesUtils.nodeIsLivemarkItem

(remove only third argument)
PlacesUIUtils.showBookmarkDialog

(no more implemented by Places, use mozIAsyncHistory)
nsIGlobalHistory2::addURI
nsIGlobalHistory2::isVisited
nsIGlobalHistory2::setPageTitle

In addition to this, if current issues will be solved soon, the
following will also be removed:

nsINavHistoryObserver::OnBeforeDeleteURI
nsINavBookmarkObserver::OnBeforeItemRemoved

Please let me know if you have doubts, or part of these changes should
be blocked for major problems, or there's some use-case you need that is
not well-covered by the new APIs.

Cheers,
Marco
DAC324
Posts: 183
Joined: October 19th, 2007, 1:54 am

Re: Places (bookmarks & history system) - API changes

Post by DAC324 »

Dear Ken, dear all,

thank you very much for that information. Please allow me one question:

If I happen to have all required parameters, such as title, parentId, index and feedURI, available as single variables, how do I get them into a mozILivemarkInfo object as required now by addLivemark()?

Update: Seems that it should be something like

Code: Select all

PlacesUtils.livemarks.addLivemark ({ 
                                                            parentId: aParentId,
                                                            index: aIndex, 
                                                            feedURI: aFeedURI,
                                                            siteURI: aSiteURI,
                                                            title: aName,
                                                             });


But: The older functions like PlacesUtils.livemarks.createLivemarkFolderOnly used to return an Id while PlacesUtils.livemarks.addLivemark is void (does not return anything).

What about that Id? Gen I get it somewhere else?

Thank you very much in advance and kind regards,

DAC324
lithopsian
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Re: Places (bookmarks & history system) - API changes

Post by lithopsian »

Places API is now async. addLivemark accepts a callback which will be given the ID when it is available, pretty much instantly as far as you are concerned but actually after a millisecond or two without blocking the main thread.

The callback is the second parameter, after the object you show, and it is a function that will be called with a status code and a livemark object. The livemark object has an id property.

There was no documentation when this change qwas made to the API and I don't think there is any now. The interface is called mozIAsyncLivemarks and you can see the definition here:
http://mxr.mozilla.org/mozilla-central/ ... rks.idl#31
DAC324
Posts: 183
Joined: October 19th, 2007, 1:54 am

Re: Places (bookmarks & history system) - API changes

Post by DAC324 »

Dear lithopsian,
lithopsian wrote:Places API is now async. addLivemark accepts a callback which will be given the ID when it is available, pretty much instantly as far as you are concerned but actually after a millisecond or two without blocking the main thread.

The callback is the second parameter, after the object you show, and it is a function that will be called with a status code and a livemark object. The livemark object has an id property.

Thank you very much for this information, which is consistent with what I already found out by myself. Unfortunately, it seems that I am missing something important, however.

I have defined a function which should be called as a callback function. This function simply should log the information it got into a logfile:

Code: Select all

        function completed (aStatus, aLivemark){
            MyProgIO.log ("Status: " + aStatus + "Id: " + aLivemark.id);
        };

In order to be on the safe side, I call addlivemarks() using a try...catch construction:

Code: Select all

        try {
            PlacesUtils.livemarks.addLivemark ({
                                                            parentId: aParentId,
                                                            index: aIndex, 
                                                            feedURI: aFeedURI,
                                                            siteURI: aSiteURI,
                                                            title: aName
                                                             }, completed);
                                                             
            }
            catch(e) {
                    MyProgIO.log("Failed to add livemark " + aName + ": " + e + e.message);
            }                                                 

Unfortunately, the function completed() does not seem to either get called or to do anything. The expected "Status:..." entry does not appear in the logfile.

Kind regards,

DAC324
Last edited by DAC324 on September 20th, 2013, 4:26 pm, edited 1 time in total.
lithopsian
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Re: Places (bookmarks & history system) - API changes

Post by lithopsian »

Slight clarification: the mozILivemarkCallback is an OBJECT, which has a single property onCompletion, which is a function accepting two parameters.
DAC324
Posts: 183
Joined: October 19th, 2007, 1:54 am

Re: Places (bookmarks & history system) - API changes

Post by DAC324 »

Hello lithopsian,

thank you once again. But how can I access this callback object properly?
I just want to get the ID of the newly created livemark.

Seems that I now solved it:

Code: Select all

  createLivemarkFolderOnly: function(aParentId, aName, aSiteURI, aFeedURI, aIndex) {

        var completed = this;
       
        completed.onCompletion = function (aStatus, aLivemark){
              MyProgIO.log("Livemark Id: " + aLivemark.id);
              receivedIds.push(aLivemark.id);
        };

        if (aParentId < 1 || !aFeedURI)
          throw Cr.NS_ERROR_INVALID_ARG;

        // Don't add livemarks to livemarks
        if (PlacesUtils.annotations.itemHasAnnotation(aParentId, SyncPlacesBookmarks.SP_LMANNO_FEEDURI))
          throw Cr.NS_ERROR_INVALID_ARG;
        try {
            PlacesUtils.livemarks.addLivemark ({
                                                            parentId: aParentId,
                                                            index: aIndex, 
                                                            feedURI: aFeedURI,
                                                            siteURI: aSiteURI,
                                                            title: aName,
                                                             }, completed);
            }
            catch(e) {
                    MyProgIO.log("Failed to add livemark " + aName + ": " + e + e.message);
            }                                                 
  }


Kind regards,

DAC324
Last edited by DAC324 on September 26th, 2013, 7:01 am, edited 1 time in total.
DAC324
Posts: 183
Joined: October 19th, 2007, 1:54 am

Re: Places (bookmarks & history system) - API changes

Post by DAC324 »

Hello all,

one interesting thing is that PlacesUtils.livemarks.addLivemark() is not fully finished when my function createLivemarkFolderOnly() returns. The callback component executes later on only.
Here is how the log looks like:
Thursday, 26. September 2013 14:13:50 Trying to add livemark heise online News, http://heise.de.feedsportal.com/c/35207 ... /index.rss, http://heise.de.feedsportal.com/c/35207 ... /index.rss, 10
Thursday, 26. September 2013 14:13:50 Livemark Folder Id: 0
Thursday, 26. September 2013 14:13:52 Trying to add livemark Caschys Blog, http://stadt-bremerhaven.de/, http://feeds.feedburner.com/stadt-breme ... format=xml, 11
Thursday, 26. September 2013 14:13:52 Livemark Folder Id: 0
[...]
Thursday, 26. September 2013 14:13:52 Livemark Id from callback: 1515
Thursday, 26. September 2013 14:13:52 Livemark Id from callback: 1516


Now I added the handling of the ID given back into the callback function (see previous posting). So far, this seems to work now.

Kind regards,
DAC324
Last edited by DAC324 on September 26th, 2013, 7:05 am, edited 1 time in total.
lithopsian
Posts: 3664
Joined: September 15th, 2010, 9:03 am

Re: Places (bookmarks & history system) - API changes

Post by lithopsian »

The whole point of a callback is that it gets called back. Later! With a callback function this is enforced because you must pass a function and it will get called later.

A callback object is simply an object that contains a function, or at least a property which points to a function. In this case, a rather redundant object since there is only one function, but such a callback object could contain multiple function (methods in class-language-speak) as well as configuration data properties.

It is not necessary to have the object include self-creation and initialisation code as yours does, although this could be done if the function is different in different circumstances. It is certainly not acceptable for such constructor code to try and access the results of the callback, because they don't exist until the function his called back. Later!

So a callback object is simply:

Code: Select all

{onCompletion: function()
    {
        ...
        some callback code which has access to the livemark ID
        ...
    }
}


You won't find any Mozilla documentation explaining this because it is an inherent part of javascript. Find a javascript tutorial if you need to learn about the language itself. Or just peek into an addon that uses livemarks.

The inlined anonymous function I assigned to the onCompletion property in this example could equally be a named function external to the callback object. In fact if the callback is to be used very frequently this is probably desirable to eliminate frequent creation of functions which is a relatively expensive operation. For really advanced usage, the callback method could be prototyped and then instantiated with small differences for each use, although I'm not sure what the small differences might be in this case since it is just an object with a single method.
Last edited by lithopsian on September 26th, 2013, 8:46 am, edited 1 time in total.
DAC324
Posts: 183
Joined: October 19th, 2007, 1:54 am

Re: Places (bookmarks & history system) - API changes

Post by DAC324 »

Dear lithopsian,

thank you very much. Coming from other languages, I first had to adapt to syntax constraints mainly. The tutorials in the net are mainly referring to callback functions only. So I had to read a lot before I could identify information useful for callback objects.

It seems that I now solved most of the understanding part :-)

Thank you once again,
DAC324
Post Reply