b=421235, r=gavin, a1.9=dsicore. Add new bookmark roots to FUEL
authormark.finkle@gmail.com
Sun, 16 Mar 2008 07:46:13 -0700
changeset 13142 3efb247eb4c71f20cae63a115672a520616545a2
parent 13141 991ba8cf49057d2f6f52abee014bf400e2224423
child 13143 56b3af45a98cc703416b4aa252dd458dbdb0c21e
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin
bugs421235
milestone1.9b5pre
b=421235, r=gavin, a1.9=dsicore. Add new bookmark roots to FUEL
browser/base/content/test/browser_getshortcutoruri.js
browser/fuel/public/fuelIApplication.idl
browser/fuel/src/fuelApplication.js
browser/fuel/test/browser_Bookmarks.js
--- a/browser/base/content/test/browser_getshortcutoruri.js
+++ b/browser/base/content/test/browser_getshortcutoruri.js
@@ -67,17 +67,17 @@ var testData = [
    new keywordResult("http://searchpostget/?search1=foo6", "search2=foo6")],
 
   // Bookmark keywords that don't take parameters should not be activated if a
   // parameter is passed (bug 420328).
   [new bmKeywordData("bmget-noparam", "http://bmget-noparam/", null, "foo7"),
    new keywordResult(null, null)],
   [new bmKeywordData("bmpost-noparam", "http://bmpost-noparam/", "not_a=param", "foo8"),
    new keywordResult(null, null)],
-  
+
   // Test escaping (%s = escaped, %S = raw)
   // UTF-8 default
   [new bmKeywordData("bmget-escaping", "http://bmget/?esc=%s&raw=%S", null, "fo"),
    new keywordResult("http://bmget/?esc=fo%C3%A9&raw=fo", null)],
   // Explicitly-defined ISO-8859-1
   [new bmKeywordData("bmget-escaping2", "http://bmget/?esc=%s&raw=%S&mozcharset=ISO-8859-1", null, "fo"),
    new keywordResult("http://bmget/?esc=fo%E9&raw=fo", null)],
 ];
@@ -103,26 +103,26 @@ function test() {
   cleanupKeywords();
 }
 
 var gBMFolder = null;
 var gAddedEngines = [];
 function setupKeywords() {
   var searchService = Cc["@mozilla.org/browser/search-service;1"].
                       getService(Ci.nsIBrowserSearchService);
-  gBMFolder = Application.bookmarks.addFolder("keyword-test");
+  gBMFolder = Application.bookmarks.menu.addFolder("keyword-test");
   for each (var item in testData) {
     var data = item[0];
     if (data instanceof bmKeywordData) {
       var bm = gBMFolder.addBookmark(data.keyword, data.uri);
       bm.keyword = data.keyword;
       if (data.postData)
         bm.annotations.set("bookmarkProperties/POSTData", data.postData, Ci.nsIAnnotationService.EXPIRE_SESSION);
     }
-    
+
     if (data instanceof searchKeywordData) {
       searchService.addEngineWithDetails(data.keyword, "", data.keyword, "", data.method, data.uri.spec);
       var addedEngine = searchService.getEngineByName(data.keyword);
       if (data.postData) {
         var [paramName, paramValue] = data.postData.split("=");
         addedEngine.addParam(paramName, paramValue, null);
       }
 
--- a/browser/fuel/public/fuelIApplication.idl
+++ b/browser/fuel/public/fuelIApplication.idl
@@ -46,34 +46,34 @@ interface fuelIEventItem : nsISupports
    * details, this is null.
    */
   readonly attribute AString data;
 
   /**
    * Cancels the event if it is cancelable.
    */
   void preventDefault();
-}; 
+};
 
 
 /**
  * Interface used as a callback for listening to events.
  */
 [scriptable, function, uuid(2dfe3a50-ab2f-11db-abbd-0800200c9a66)]
 interface fuelIEventListener : nsISupports
 {
   /**
-   * This method is called whenever an event occurs of the type for which 
+   * This method is called whenever an event occurs of the type for which
    * the fuelIEventListener interface was registered.
    *
    * @param   aEvent
    *          The fuelIEventItem associated with the event.
    */
   void handleEvent(in fuelIEventItem aEvent);
-}; 
+};
 
 
 /**
  * Interface for supporting custom events.
  */
 [scriptable, uuid(3a8ec9d0-ab19-11db-abbd-0800200c9a66)]
 interface fuelIEvents : nsISupports
 {
@@ -96,17 +96,17 @@ interface fuelIEvents : nsISupports
    * with arguments which do not identify any currently registered
    * event listener has no effect.
    * @param   aEvent
    *          The name of an event
    * @param   aListener
    *          The reference to a listener
    */
   void removeListener(in AString aEvent, in fuelIEventListener aListener);
-}; 
+};
 
 
 /**
  * Interface for simplified access to preferences. The interface has a
  * predefined root preference branch. The root branch is set based on the
  * context of the owner. For example, an extension's preferences have a root
  * of "extensions.<extensionid>.", while the application level preferences
  * have an empty root. All preference "aName" parameters used in this interface
@@ -114,44 +114,44 @@ interface fuelIEvents : nsISupports
  */
 [scriptable, uuid(ce697d40-aa5a-11db-abbd-0800200c9a66)]
 interface fuelIPreferenceBranch : nsISupports
 {
   /**
    * The name of the branch root.
    */
   readonly attribute AString root;
-  
+
   /**
    * Array of fuelIPreference listing all preferences in this branch.
    */
   readonly attribute nsIVariant all;
-  
+
   /**
    * The events object for the preferences
    * supports: "change"
    */
   readonly attribute fuelIEvents events;
-  
+
   /**
    * Check to see if a preference exists.
    * @param   aName
    *          The name of preference
    * @returns true if the preference exists, false if not
    */
   boolean has(in AString aName);
-  
+
   /**
    * Gets an object representing a preference
    * @param   aName
    *          The name of preference
    * @returns a preference object, or null if the preference does not exist
    */
   fuelIPreference get(in AString aName);
-  
+
   /**
    * Gets the value of a preference. Returns a default value if
    * the preference does not exist.
    * @param   aName
    *          The name of preference
    * @param   aDefaultValue
    *          The value to return if preference does not exist
    * @returns value of the preference or the given default value if preference
@@ -180,48 +180,48 @@ interface fuelIPreferenceBranch : nsISup
  */
 [scriptable, uuid(2C7462E2-72C2-4473-9007-0E6AE71E23CA)]
 interface fuelIPreference : nsISupports
 {
   /**
    * The name of the preference.
    */
   readonly attribute AString name;
-  
+
   /**
    * A string representing the type of preference (String, Boolean, or Number).
    */
   readonly attribute AString type;
-  
+
   /**
    * Get/Set the value of the preference.
    */
   attribute nsIVariant value;
-  
+
   /**
    * Get the locked state of the preference. Set to a boolean value to (un)lock it.
    */
   attribute boolean locked;
-  
+
   /**
    * Check if a preference has been modified by the user, or not.
    */
   readonly attribute boolean modified;
-  
+
   /**
    * The preference branch that contains this preference.
    */
   readonly attribute fuelIPreferenceBranch branch;
-  
+
   /**
    * The events object for this preference.
    * supports: "change"
    */
   readonly attribute fuelIEvents events;
-  
+
   /**
    * Resets a preference back to its default values.
    */
   void reset();
 };
 
 
 /**
@@ -260,17 +260,17 @@ interface fuelISessionStorage : nsISuppo
    * @param   aName
    *          The name of an item
    * @param   aDefaultValue
    *          The value to return if no item exists with the given name
    * @returns value of the item or the given default value if no item
    *          exists with the given name.
    */
   nsIVariant get(in AString aName, in nsIVariant aDefaultValue);
-}; 
+};
 
 
 /**
  * Interface representing an extension
  */
 [scriptable, uuid(10cee02c-f6e0-4d61-ab27-c16572b18c46)]
 interface fuelIExtension : nsISupports
 {
@@ -278,22 +278,22 @@ interface fuelIExtension : nsISupports
    * The id of the extension.
    */
   readonly attribute AString id;
 
   /**
    * The name of the extension.
    */
   readonly attribute AString name;
-  
+
   /**
    * Check if the extension is currently enabled, or not.
    */
   readonly attribute boolean enabled;
-  
+
   /**
    * The version number of the extension.
    */
   readonly attribute AString version;
 
   /**
    * Indicates whether this is the extension's first run after install
    */
@@ -310,17 +310,17 @@ interface fuelIExtension : nsISupports
    */
   readonly attribute fuelISessionStorage storage;
 
   /**
    * The events object for the extension.
    * supports: "uninstall"
    */
   readonly attribute fuelIEvents events;
-}; 
+};
 
 
 /**
  * Interface representing a list of all installed extensions
  */
 [scriptable, uuid(de281930-aa5a-11db-abbd-0800200c9a66)]
 interface fuelIExtensions : nsISupports
 {
@@ -341,17 +341,17 @@ interface fuelIExtensions : nsISupports
   /**
    * Gets a fuelIExtension object for an extension.
    * @param   aId
    *          The id of an extension
    * @returns An extension object or null if no extension exists
    *          with the given id.
    */
   fuelIExtension get(in AString aId);
-}; 
+};
 
 
 /**
  * Interface representing a collection of annotations associated
  * with a bookmark or bookmark folder.
  */
 [scriptable, uuid(335c9292-91a1-4ca0-ad0b-07d5f63ed6cd)]
 interface fuelIAnnotations : nsISupports
@@ -454,17 +454,17 @@ interface fuelIBookmark : nsISupports
    */
   readonly attribute fuelIEvents events;
 
   /**
    * Removes the item from the parent folder. Used to
    * delete a bookmark or separator
    */
   void remove();
-}; 
+};
 
 
 /**
  * Interface representing a bookmark folder. Folders
  * can hold bookmarks, separators and other folders.
  */
 [scriptable, uuid(9f42fe20-52de-4a55-8632-a459c7716aa0)]
 interface fuelIBookmarkFolder : nsISupports
@@ -536,38 +536,67 @@ interface fuelIBookmarkFolder : nsISuppo
   /**
    * Removes the folder from the parent folder.
    */
   void remove();
 };
 
 
 /**
+ * Interface representing a container for bookmark roots. Roots
+ * are the top level parents for the various types of bookmarks in the system.
+ */
+[scriptable, uuid(c9a80870-eb3c-11dc-95ff-0800200c9a66)]
+interface fuelIBookmarkRoots : nsISupports
+{
+  /**
+   * The folder for the 'bookmarks menu' root.
+   */
+  readonly attribute fuelIBookmarkFolder menu;
+
+  /**
+   * The folder for the 'personal toolbar' root.
+   */
+  readonly attribute fuelIBookmarkFolder toolbar;
+
+  /**
+   * The folder for the 'tags' root.
+   */
+  readonly attribute fuelIBookmarkFolder tags;
+
+  /**
+   * The folder for the 'unfiled bookmarks' root.
+   */
+  readonly attribute fuelIBookmarkFolder unfiled;
+};
+
+
+/**
  * Interface representing a browser window.
  */
 [scriptable, uuid(207edb28-eb5e-424e-a862-b0e97C8de866)]
 interface fuelIWindow : nsISupports
 {
   /**
    * A collection of browser tabs within the browser window.
    */
   readonly attribute nsIVariant tabs;
-  
+
   /**
    * The currently-active tab within the browser window.
    */
   readonly attribute fuelIBrowserTab activeTab;
-  
+
   /**
    * Open a new browser tab, pointing to the specified URI.
    * @param   aURI
    *          The uri to open the browser tab to
    */
   fuelIBrowserTab open(in nsIURI aURI);
-  
+
   /**
    * The events object for the browser window.
    * supports: "TabOpen", "TabClose", "TabMove", "TabSelect"
    */
   readonly attribute fuelIEvents events;
 };
 
 /**
@@ -575,63 +604,63 @@ interface fuelIWindow : nsISupports
  */
 [scriptable, uuid(3073ceff-777c-41ce-9ace-ab37268147c1)]
 interface fuelIBrowserTab : nsISupports
 {
   /**
    * The current uri of this tab.
    */
   readonly attribute nsIURI uri;
-  
+
   /**
    * The current index of this tab in the browser window.
    */
   readonly attribute PRInt32 index;
 
   /**
    * The browser window that is holding the tab.
    */
   readonly attribute fuelIWindow window;
-  
+
   /**
    * The content document of the browser tab.
    */
   readonly attribute nsIDOMHTMLDocument document;
 
   /**
    * The events object for the browser tab.
    * supports: "load"
    */
   readonly attribute fuelIEvents events;
-  
+
   /**
    * Load a new URI into this browser tab.
    * @param   aURI
    *          The uri to load into the browser tab
    */
   void load(in nsIURI aURI);
 
   /**
    * Give focus to this browser tab, and bring it to the front.
    */
   void focus();
-  
+
   /**
    * Close the browser tab. This may not actually close the tab
    * as script may abort the close operation.
    */
   void close();
-  
+
   /**
    * Moves this browser tab before another browser tab within the window.
    * @param   aBefore
    *          The tab before which the target tab will be moved
    */
   void moveBefore(in fuelIBrowserTab aBefore);
-  
+
   /**
    * Move this browser tab to the last tab within the window.
    */
   void moveToEnd();
 };
 
 
 /**
@@ -644,22 +673,22 @@ interface fuelIApplication : nsISupports
    * The id of the application.
    */
   readonly attribute AString id;
 
   /**
    * The name of the application.
    */
   readonly attribute AString name;
-  
+
   /**
    * The version number of the application.
    */
   readonly attribute AString version;
-  
+
   /**
    * The console object for the application.
    */
   readonly attribute fuelIConsole console;
 
   /**
    * The extensions object for the application. Contains a list
    * of all installed extensions.
@@ -680,21 +709,22 @@ interface fuelIApplication : nsISupports
   /**
    * The events object for the application.
    * supports: "load", "ready", "quit", "unload"
    */
   readonly attribute fuelIEvents events;
 
   /**
    * The root bookmarks object for the application.
+   * Contains all the bookmark roots in the system.
    */
-  readonly attribute fuelIBookmarkFolder bookmarks;
-  
+  readonly attribute fuelIBookmarkRoots bookmarks;
+
   /**
    * An array of browser windows within the application.
    */
   readonly attribute nsIVariant windows;
-  
+
   /**
    * The currently active browser window.
    */
   readonly attribute fuelIWindow activeWindow;
-}; 
+};
--- a/browser/fuel/src/fuelApplication.js
+++ b/browser/fuel/src/fuelApplication.js
@@ -954,19 +954,16 @@ Bookmark.prototype = {
   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmark, Ci.nsINavBookmarkObserver])
 };
 
 
 //=================================================
 // BookmarkFolder implementation
 function BookmarkFolder(aId, aParent) {
   this._id = aId;
-  if (this._id == null)
-    this._id = Utilities.bookmarks.bookmarksMenuFolder;
-
   this._parent = aParent;
 
   this._annotations = new Annotations(this._id);
   this._events = new Events();
 
   Utilities.bookmarks.addObserver(this, false);
 
   var self = this;
@@ -1117,16 +1114,63 @@ BookmarkFolder.prototype = {
       this._events.dispatch("move", aId);
     }
   },
 
   QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkFolder, Ci.nsINavBookmarkObserver])
 };
 
 //=================================================
+// BookmarkRoots implementation
+function BookmarkRoots() {
+  var self = this;
+  gShutdown.push(function() { self._shutdown(); });
+}
+
+BookmarkRoots.prototype = {
+  _shutdown : function bmr_shutdown() {
+    this._menu = null;
+    this._toolbar = null;
+    this._tags = null;
+    this._unfiled = null;
+  },
+
+  get menu() {
+    if (!this._menu)
+      this._menu = new BookmarkFolder(Utilities.bookmarks.bookmarksMenuFolder, null);
+
+    return this._menu;
+  },
+
+  get toolbar() {
+    if (!this._toolbar)
+      this._toolbar = new BookmarkFolder(Utilities.bookmarks.toolbarFolder, null);
+
+    return this._toolbar;
+  },
+
+  get tags() {
+    if (!this._tags)
+      this._tags = new BookmarkFolder(Utilities.bookmarks.tagsFolder, null);
+
+    return this._tags;
+  },
+
+  get unfiled() {
+    if (!this._unfiled)
+      this._unfiled = new BookmarkFolder(Utilities.bookmarks.unfiledBookmarksFolder, null);
+
+    return this._unfiled;
+  },
+
+  QueryInterface : XPCOMUtils.generateQI([Ci.fuelIBookmarkRoots])
+};
+
+
+//=================================================
 // Factory - Treat Application as a singleton
 // XXX This is required, because we're registered for the 'JavaScript global
 // privileged property' category, whose handler always calls createInstance.
 // See bug 386535.
 var gSingleton = null;
 var ApplicationFactory = {
   createInstance: function af_ci(aOuter, aIID) {
     if (aOuter != null)
@@ -1280,17 +1324,17 @@ Application.prototype = {
     if (this._events == null)
         this._events = new Events();
 
     return this._events;
   },
 
   get bookmarks() {
     if (this._bookmarks == null)
-      this._bookmarks = new BookmarkFolder(null, null);
+      this._bookmarks = new BookmarkRoots();
 
     return this._bookmarks;
   },
 
   get windows() {
     var win = [];
     var enum = Utilities.windowMediator.getEnumerator("navigator:browser");
 
--- a/browser/fuel/test/browser_Bookmarks.js
+++ b/browser/fuel/test/browser_Bookmarks.js
@@ -5,17 +5,50 @@ var gLastFolderAction = "";
 var gLastBookmarkAction = "";
 
 function url(spec) {
   var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
   return ios.newURI(spec, null, null);
 }
 
 function test() {
-  var root = Application.bookmarks;
+  // Some very basic tests on the tags root
+  var tags = Application.bookmarks.tags;
+  ok(tags, "Check access to bookmark tags root");
+  ok(!tags.parent, "Check tags parent (should be null)");
+
+  //----------------------------------------------
+
+  // Some very basic tests on the unfiled root
+  var unfiled = Application.bookmarks.unfiled;
+  ok(unfiled, "Check access to bookmark unfiled root");
+  ok(!unfiled.parent, "Check unfiled parent (should be null)");
+
+  //----------------------------------------------
+
+  // Some basic tests on the toolbar root
+  var toolbar = Application.bookmarks.toolbar;
+  ok(toolbar, "Check access to bookmark toolbar root");
+  ok(!toolbar.parent, "Check toolbar parent (should be null)");
+
+  var toolbarKidCount = toolbar.children.length;
+
+  // test adding folders
+  var testFolderToolbar = toolbar.addFolder("FUEL in Toolbar");
+  ok(testFolderToolbar, "Check folder creation");
+  is(testFolderToolbar.type, "folder", "Check 'folder.type' after creation");
+  ok(testFolderToolbar.parent, "Check parent after folder creation");
+
+  toolbarKidCount++;
+  is(toolbar.children.length, toolbarKidCount, "Check toolbar folder child count after adding a child folder");
+
+  //----------------------------------------------
+
+  // Main testing is done on the bookmarks menu root
+  var root = Application.bookmarks.menu;
   ok(root, "Check access to bookmark root");
   ok(!root.parent, "Check root parent (should be null)");
 
   var rootKidCount = root.children.length;
 
   // test adding folders
   var testFolder = root.addFolder("FUEL");
   ok(testFolder, "Check folder creation");