Search code examples
javascriptfunctionrecursionfirefox-addonbookmarks

Firefox bookmarks exploration not going past first level with Javascript


I've written some code to explore my Firefox bookmarks but I only get the first level of bookmarks (i.e. I don't get the links in the folders).

e.g.

  • Search_engines /

    • yahoo.com
  • google.com

In this example I have only access to Search_engines and google.com not yahoo.com

My function being recursive I don't know why this happens.

my code :

function browse_bookmark_node(bookmark_node, array)
{
    // We explore the bookmarks with this function     
   // iterate over the immediate children of this folder
   for (var i = 0; i < bookmark_node.childCount; i ++) {
       var node = bookmark_node.getChild(i);
       if (node.type ==0) {
          // the node is a link so we add it to the array
          array.push(node.title); 
       } else if (node.type ==6) {
          // the node is a folder so we explore it
          browse_bookmark_node(node, array);
       }
   }
}

function wrapper_browse_bookmark_node(bookmark_node) {
   // We use this function to wrapp the function browse_bookmark_node and keep track of the links
   var array = [];
   browse_bookmark_node(bookmark_node, array);
   return array;
}

// All the code following is used to access firefox bookmarks and works fine
var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"]
                               .getService(Components.interfaces.nsINavHistoryService);
var options = historyService.getNewQueryOptions();
var query = historyService.getNewQuery();

var bookmarksService = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"]
                                 .getService(Components.interfaces.nsINavBookmarksService);
var bookmarksMenuFolder = bookmarksService.bookmarksMenuFolder;

query.setFolders([bookmarksMenuFolder], 1);

var result = historyService.executeQuery(query, options);
var rootNode = result.root;
rootNode.containerOpen = true;

// The function call to explore the bookmarks
var links_array = wrapper_browse_bookmark_node(rootNode);

// close a container after using it!
rootNode.containerOpen = false;

Solution

  • One obvious mistake is using toolbarFolder as a starting point - that's only the bookmarks toolbar. If you want all bookmarks (meaning bookmarks menu, bookmarks toolbar and unsorted bookmarks) you need to change query parameters:

    query.setFolders([
        bookmarksService.bookmarksMenuFolder,
        bookmarksService.toolbarFolder,
        bookmarksService.unfiledBookmarksFolder
    ], 3);
    

    The other issue is getting childCount property on a nsINavHistoryResultNode object - there is no such property. Before you can access properties of nsINavHistoryContainerResultNode you need to call QueryInterface, either explicitly or implicitly (via instanceof). So I would write:

    } else if (node.type == 6 && node instanceof Components.interfaces.nsINavHistoryContainerResultNode) {
        var oldOpen = node.containerOpen;
        node.containerOpen = true;
        browse_bookmark_node(node, array);
        node.containerOpen = oldOpen;
    }