browser_bookmarksProperties.js
Go to the documentation of this file.
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is mozilla.org code.
15  *
16  * The Initial Developer of the Original Code is
17  * Mozilla Corporation.
18  * Portions created by the Initial Developer are Copyright (C) 2009
19  * the Initial Developer. All Rights Reserved.
20  *
21  * Contributor(s):
22  * Marco Bonardo <mak77@bonardo.net>
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37 
42 const Cc = Components.classes;
43 const Ci = Components.interfaces;
44 
45 // DOM ids of Places sidebar trees.
46 const SIDEBAR_HISTORY_TREE_ID = "historyTree";
47 const SIDEBAR_BOOKMARKS_TREE_ID = "bookmarks-view";
48 
49 const SIDEBAR_HISTORY_ID = "viewHistorySidebar";
50 const SIDEBAR_BOOKMARKS_ID = "viewBookmarksSidebar";
51 
52 // For history sidebar.
53 const SIDEBAR_HISTORY_BYLASTVISITED_VIEW = "bylastvisited";
56 const SIDEBAR_HISTORY_BYSITE_VIEW = "bysite";
57 const SIDEBAR_HISTORY_BYDATEANDSITE_VIEW = "bydateandsite";
58 
59 // Action to execute on the current node.
60 const ACTION_EDIT = 0;
61 const ACTION_ADD = 1;
62 
63 // If action is ACTION_ADD, set type to one of those, to define what do you
64 // want to create.
65 const TYPE_FOLDER = 0;
66 const TYPE_BOOKMARK = 1;
67 
68 const TEST_URL = "http://www.mozilla.org/";
69 
70 const DIALOG_URL = "chrome://browser/content/places/bookmarkProperties.xul";
71 const DIALOG_URL_MINIMAL_UI = "chrome://browser/content/places/bookmarkProperties2.xul";
72 
73 var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
74  getService(Ci.nsIWindowMediator);
75 var win = wm.getMostRecentWindow("navigator:browser");
76 var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
77  getService(Ci.nsIWindowWatcher);
78 
79 function add_visit(aURI, aDate) {
80  var visitId = PlacesUtils.history
81  .addVisit(aURI,
82  aDate,
83  null, // no referrer
84  PlacesUtils.history.TRANSITION_TYPED,
85  false, // not redirect
86  0);
87  return visitId;
88 }
89 
90 function add_bookmark(aURI) {
91  var bId = PlacesUtils.bookmarks
92  .insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
93  aURI,
94  PlacesUtils.bookmarks.DEFAULT_INDEX,
95  "bookmark/" + aURI.spec);
96  return bId;
97 }
98 
99 // Each test is an obj w/ a desc property and run method.
100 var gTests = [];
102 
103 //------------------------------------------------------------------------------
104 // TEST SKELETON: use this template to add new tests.
105 /*
106 gTests.push({
107  desc: "Bug Description",
108  sidebar: SIDEBAR_BOOKMARKS_ID, // See SIDEBAR_ constants above.
109  action: ACTION_EDIT, // See ACTION_ constants above.
110  itemType: null, // See TYPE_ constants above, required for ACTION_ADD, only for Bookmarks sidebar.
111  historyView: SIDEBAR_HISTORY_BYLASTVISITED_VIEW, // See constants above, only for History sidebar.
112  window: null, // Will contain handle of dialog window
113 
114  setup: function() {
115  // Setup everything needed for this test, runs before everything else.
116  },
117 
118  selectNode: function(tree) {
119  // Select the node to edit or to add to, runs when sidebar tree is visible.
120  },
121 
122  run: function() {
123  // Actual test, runs when dialog is open.
124  },
125 
126  finish: function() {
127  // Close window, toggle sidebar and goto next test.
128  this.window.document.documentElement.cancelDialog();
129  toggleSidebar(this.sidebar, false);
130  runNextTest();
131  },
132 
133  cleanup: function() {
134  // Undo everything added during setup, runs after dialog has been closed.
135  }
136 });
137 */
138 
139 //------------------------------------------------------------------------------
140 // Bug 479348 - Properties on a root should be read-only
141 
142 gTests.push({
143  desc: "Bug 479348 - Properties on a root should be read-only",
145  action: ACTION_EDIT,
146  itemType: null,
147  window: null,
148 
149  setup: function() {
150  // Nothing to do.
151  },
152 
153  selectNode: function(tree) {
154  // Select Unfiled Bookmarks root.
155  var itemId = PlacesUIUtils.leftPaneQueries["UnfiledBookmarks"];
156  tree.selectItems([itemId]);
157  this.selectedNode = tree.selectedNode;
158  },
159 
160  run: function() {
161  // Check that the dialog is read-only.
162  ok(this.window.BookmarkPropertiesPanel._readOnly, "Dialog is read-only");
163 
164  // Check that accept button is disabled
165  var acceptButton = this.window.document.documentElement.getButton("accept");
166  ok(acceptButton.disabled, "Accept button is disabled");
167 
168  // Check that name picker is read only
169  var namepicker = this.window.document.getElementById("editBMPanel_namePicker");
170  ok(namepicker.readOnly, "Name field is disabled");
171  is(namepicker.value,
172  PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId),
173  "Node title is correct");
174  // Blur the field and ensure root's name has not been changed.
175  this.window.gEditItemOverlay.onNamePickerChange();
176  is(namepicker.value,
177  PlacesUtils.bookmarks.getItemTitle(PlacesUtils.unfiledBookmarksFolderId),
178  "Root title is correct");
179  // Check the shortcut's title.
180  is(PlacesUtils.bookmarks.getItemTitle(this.selectedNode.itemId), null,
181  "Shortcut title is null");
182  this.finish();
183  },
184 
185  finish: function() {
186  this.window.document.documentElement.cancelDialog();
187  toggleSidebar(this.sidebar, false);
188  runNextTest();
189  },
190 
191  cleanup: function() {
192  // Nothing to do.
193  }
194 });
195 
196 //------------------------------------------------------------------------------
197 // Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog
198 
199 gTests.push({
200  desc: "Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog",
202  action: ACTION_EDIT,
203  itemType: null,
204  window: null,
205  _itemId: null,
206 
207  setup: function() {
208  // Add a bookmark in unsorted bookmarks folder.
209  this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
210  ok(this._itemId > 0, "Correctly added a bookmark");
211  // Add a tag to this bookmark.
212  PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
213  ["testTag"]);
214  var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
215  is(tags[0], "testTag", "Correctly added a tag");
216  },
217 
218  selectNode: function(tree) {
219  tree.selectItems([this._itemId]);
220  is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
221  },
222 
223  run: function() {
224  // open tags autocomplete and press enter
225  var tagsField = this.window.document.getElementById("editBMPanel_tagsField");
226  var self = this;
227 
228  var windowObserver = {
229  observe: function(aSubject, aTopic, aData) {
230  if (aTopic === "domwindowclosed" &&
231  aSubject.QueryInterface(Ci.nsIDOMWindow).location == DIALOG_URL) {
232  ww.unregisterNotification(this);
233  tagsField.popup.removeEventListener("popuphidden", popupListener, true);
234  ok(false, "Dialog window should not be closed by pressing Enter on the autocomplete popup");
235  self.finish();
236  }
237  }
238  };
239 
240  var popupListener = {
241  handleEvent: function(aEvent) {
242  switch (aEvent.type) {
243  case "popuphidden":
244  // Everything worked fine, we can stop observing the window.
245  ww.unregisterNotification(windowObserver);
246  tagsField.popup.removeEventListener("popuphidden", this, true);
247  self.window.document.documentElement.cancelDialog();
248  self.finish();
249  break;
250  case "popupshown":
251  tagsField.popup.removeEventListener("popupshown", this, true);
252  // In case this test fails the window will close, we should mark the
253  // failure and continue, to avoid timing out.
254  ww.registerNotification(windowObserver);
255  var tree = tagsField.popup.tree;
256  // Focus and select first result.
257  isnot(tree, null, "Autocomplete results tree exists");
258  is(tree.view.rowCount, 1, "We have 1 autocomplete result");
259  tagsField.popup.selectedIndex = 0;
260  is(tree.view.selection.count, 1,
261  "We have selected a tag from the autocomplete popup");
262  info("About to focus the autocomplete results tree");
263  tree.focus();
264  EventUtils.synthesizeKey("VK_RETURN", {}, self.window);
265  break;
266  default:
267  ok(false, "unknown event: " + aEvent.type);
268  return;
269  }
270  }
271  };
272  tagsField.popup.addEventListener("popupshown", popupListener, true);
273  tagsField.popup.addEventListener("popuphidden", popupListener, true);
274 
275  // Open tags autocomplete popup.
276  info("About to focus the tagsField");
277  tagsField.focus();
278  tagsField.value = "";
279  EventUtils.synthesizeKey("t", {}, this.window);
280  },
281 
282  finish: function() {
283  toggleSidebar(this.sidebar, false);
284  runNextTest();
285  },
286 
287  cleanup: function() {
288  // Check tags have not changed.
289  var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
290  is(tags[0], "testTag", "Tag on node has not changed");
291 
292  // Cleanup.
293  PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL), ["testTag"]);
294  PlacesUtils.bookmarks.removeItem(this._itemId);
295  }
296 });
297 
298 //------------------------------------------------------------------------------
299 // Bug 475529 - Add button in new folder dialog not default anymore
300 
301 gTests.push({
302  desc: "Bug 475529 - Add button in new folder dialog not default anymore",
304  action: ACTION_ADD,
305  itemType: TYPE_FOLDER,
306  window: null,
307  _itemId: null,
308 
309  setup: function() {
310  // Nothing to do.
311  },
312 
313  selectNode: function(tree) {
314  // Select Unfiled Bookmarks root.
315  var itemId = PlacesUIUtils.leftPaneQueries["UnfiledBookmarks"];
316  tree.selectItems([itemId]);
317  this.selectedNode = tree.selectedNode;
318  },
319 
320  run: function() {
321  this._itemId = this.window.gEditItemOverlay._itemId;
322  // Change folder name
323  var namePicker = this.window.document.getElementById("editBMPanel_namePicker");
324  var userEnteredName = this.window.document.getElementById("editBMPanel_userEnteredName");
325  var self = this;
326  this.window.addEventListener("unload", function(event) {
327  this.window.removeEventListener("unload", arguments.callee, false);
328  executeSoon(function() {
329  self.finish();
330  });
331  }, false);
332  namePicker.value = "n";
333  userEnteredName.label = "n";
334  info("About to focus the namePicker field");
335  namePicker.focus();
336  EventUtils.synthesizeKey("VK_RETURN", {}, this.window);
337  },
338 
339  finish: function() {
340  // Window is already closed.
341  toggleSidebar(this.sidebar, false);
342  runNextTest();
343  },
344 
345  cleanup: function() {
346  // Check that folder name has been changed.
347  is(PlacesUtils.bookmarks.getItemTitle(this._itemId), "n",
348  "Folder name has been edited");
349 
350  // Cleanup.
351  PlacesUtils.bookmarks.removeItem(this._itemId);
352  }
353 });
354 
355 //------------------------------------------------------------------------------
356 // Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel
357 
358 gTests.push({
359  desc: "Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel",
361  action: ACTION_EDIT,
362  itemType: null,
363  window: null,
364  _itemId: null,
365 
366  setup: function() {
367  // Add a bookmark in unsorted bookmarks folder.
368  this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
369  ok(this._itemId > 0, "Correctly added a bookmark");
370  // Add a tag to this bookmark.
371  PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
372  ["testTag"]);
373  var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
374  is(tags[0], "testTag", "Correctly added a tag");
375  },
376 
377  selectNode: function(tree) {
378  tree.selectItems([this._itemId]);
379  is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
380  },
381 
382  run: function() {
383  // open tags autocomplete and press enter
384  var tagsField = this.window.document.getElementById("editBMPanel_tagsField");
385  var self = this;
386 
387  var windowObserver = {
388  observe: function(aSubject, aTopic, aData) {
389  if (aTopic === "domwindowclosed" &&
390  aSubject.QueryInterface(Ci.nsIDOMWindow).location == DIALOG_URL) {
391  ww.unregisterNotification(this);
392  tagsField.popup.removeEventListener("popuphidden", popupListener, true);
393  ok(false, "Dialog window should not be closed by pressing Escape on the autocomplete popup");
394  self.finish();
395  }
396  }
397  };
398 
399  var popupListener = {
400  handleEvent: function(aEvent) {
401  switch (aEvent.type) {
402  case "popuphidden":
403  // Everything worked fine, we can stop observing the window.
404  ww.unregisterNotification(windowObserver);
405  tagsField.popup.removeEventListener("popuphidden", this, true);
406  self.window.document.documentElement.cancelDialog();
407  self.finish();
408  break;
409  case "popupshown":
410  tagsField.popup.removeEventListener("popupshown", this, true);
411  // In case this test fails the window will close, we should mark the
412  // failure and continue, to avoid timing out.
413  ww.registerNotification(windowObserver);
414  var tree = tagsField.popup.tree;
415  // Focus and select first result.
416  isnot(tree, null, "Autocomplete results tree exists");
417  is(tree.view.rowCount, 1, "We have 1 autocomplete result");
418  tagsField.popup.selectedIndex = 0;
419  is(tree.view.selection.count, 1,
420  "We have selected a tag from the autocomplete popup");
421  info("About to focus the autocomplete results tree");
422  tree.focus();
423  EventUtils.synthesizeKey("VK_ESCAPE", {}, self.window);
424  break;
425  default:
426  ok(false, "unknown event: " + aEvent.type);
427  return;
428  }
429  }
430  };
431  tagsField.popup.addEventListener("popupshown", popupListener, true);
432  tagsField.popup.addEventListener("popuphidden", popupListener, true);
433 
434  // Open tags autocomplete popup.
435  info("About to focus the tagsField");
436  tagsField.focus();
437  tagsField.value = "";
438  EventUtils.synthesizeKey("t", {}, this.window);
439  },
440 
441  finish: function() {
442  toggleSidebar(this.sidebar, false);
443  runNextTest();
444  },
445 
446  cleanup: function() {
447  // Check tags have not changed.
448  var tags = PlacesUtils.tagging.getTagsForURI(PlacesUtils._uri(TEST_URL), {});
449  is(tags[0], "testTag", "Tag on node has not changed");
450 
451  // Cleanup.
452  PlacesUtils.tagging.untagURI(PlacesUtils._uri(TEST_URL),
453  ["testTag"]);
454  PlacesUtils.bookmarks.removeItem(this._itemId);
455  }
456 });
457 
458 //------------------------------------------------------------------------------
459 // Bug 491269 - Test that editing folder name in bookmarks properties dialog does not accept the dialog
460 
461 gTests.push({
462  desc: " Bug 491269 - Test that editing folder name in bookmarks properties dialog does not accept the dialog",
464  action: ACTION_ADD,
466  window: null,
467 
468  setup: function() {
469  // Add a visit.
470  add_visit(PlacesUtils._uri(TEST_URL), Date.now() * 1000);
471  // Sanity check.
472  var gh = PlacesUtils.history.QueryInterface(Ci.nsIGlobalHistory2);
473  ok(gh.isVisited(PlacesUtils._uri(TEST_URL)), TEST_URL + " is a visited url.");
474  },
475 
476  selectNode: function(tree) {
477  var visitNode = tree.view.nodeForTreeIndex(0);
478  tree.selectNode(visitNode);
479  is(tree.selectedNode.uri, TEST_URL, "The correct visit has been selected");
480  is(tree.selectedNode.itemId, -1, "The selected node is not bookmarked");
481  },
482 
483  run: function() {
484  // Open folder selector.
485  var foldersExpander = this.window.document.getElementById("editBMPanel_foldersExpander");
486  var folderTree = this.window.document.getElementById("editBMPanel_folderTree");
487  var self = this;
488 
489  var windowObserver = {
490  observe: function(aSubject, aTopic, aData) {
491  if (aTopic === "domwindowclosed" &&
492  aSubject.QueryInterface(Ci.nsIDOMWindow).location == DIALOG_URL_MINIMAL_UI) {
493  ww.unregisterNotification(this);
494  ok(self._cleanShutdown,
495  "Dialog window should not be closed by pressing ESC in folder name textbox");
496  self.finish();
497  }
498  }
499  };
500  ww.registerNotification(windowObserver);
501 
502  folderTree.addEventListener("DOMAttrModified", function onDOMAttrModified(event) {
503  if (event.attrName != "place")
504  return;
505  folderTree.removeEventListener("DOMAttrModified", arguments.callee, false);
506  executeSoon(function () {
507  // Create a new folder.
508  var newFolderButton = self.window.document.getElementById("editBMPanel_newFolderButton");
509  newFolderButton.doCommand();
510  ok(folderTree.hasAttribute("editing"),
511  "We are editing new folder name in folder tree");
512 
513  // Press Escape to discard editing new folder name.
514  EventUtils.synthesizeKey("VK_ESCAPE", {}, self.window);
515  ok(!folderTree.hasAttribute("editing"),
516  "We have finished editing folder name in folder tree");
517  self._cleanShutdown = true;
518  self.window.document.documentElement.cancelDialog();
519  });
520  }, false);
521  foldersExpander.doCommand();
522  },
523 
524  finish: function() {
525  toggleSidebar(this.sidebar, false);
526  runNextTest();
527  },
528 
529  cleanup: function() {
530  var bh = PlacesUtils.history.QueryInterface(Ci.nsIBrowserHistory);
531  bh.removeAllPages();
532  }
533 });
534 
535 //------------------------------------------------------------------------------
536 
537 function test() {
539  // Sanity checks.
540  ok(PlacesUtils, "PlacesUtils in context");
541  ok(PlacesUIUtils, "PlacesUIUtils in context");
542 
543  // kick off tests
544  runNextTest();
545 }
546 
547 function runNextTest() {
548  // Cleanup from previous test.
549  if (gCurrentTest) {
550  gCurrentTest.cleanup();
551  info("End of test: " + gCurrentTest.desc);
552  gCurrentTest = null;
553  executeSoon(runNextTest);
554  return;
555  }
556 
557  if (gTests.length > 0) {
558  // Goto next tests.
559  gCurrentTest = gTests.shift();
560  info("Start of test: " + gCurrentTest.desc);
561  gCurrentTest.setup();
563  }
564  else {
565  // Finished all tests.
566  finish();
567  }
568 }
569 
575  var sidebar = document.getElementById("sidebar");
576  sidebar.addEventListener("load", function() {
577  sidebar.removeEventListener("load", arguments.callee, true);
578  // Need to executeSoon since the tree is initialized on sidebar load.
579  executeSoon(open_properties_dialog);
580  }, true);
581  toggleSidebar(gCurrentTest.sidebar, true);
582 }
583 
585  var sidebar = document.getElementById("sidebar");
586 
587  // If this is history sidebar, set the required view.
588  if (gCurrentTest.sidebar == SIDEBAR_HISTORY_ID)
589  sidebar.contentDocument.getElementById(gCurrentTest.historyView).doCommand();
590 
591  // Get sidebar's Places tree.
592  var sidebarTreeID = gCurrentTest.sidebar == SIDEBAR_BOOKMARKS_ID ?
595  var tree = sidebar.contentDocument.getElementById(sidebarTreeID);
596  ok(tree, "Sidebar tree has been loaded");
597 
598  // Ask current test to select the node to edit.
599  gCurrentTest.selectNode(tree);
600  ok(tree.selectedNode,
601  "We have a places node selected: " + tree.selectedNode.title);
602 
603  // Wait for the Properties dialog.
604  var windowObserver = {
605  observe: function(aSubject, aTopic, aData) {
606  if (aTopic === "domwindowopened") {
607  ww.unregisterNotification(this);
608  var win = aSubject.QueryInterface(Ci.nsIDOMWindow);
609  win.addEventListener("focus", function(event) {
610  win.removeEventListener("focus", arguments.callee, false);
611  // Windows has been loaded, execute our test now.
612  executeSoon(function () {
613  // Ensure overlay is loaded
614  ok(win.gEditItemOverlay._initialized, "EditItemOverlay is initialized");
615  gCurrentTest.window = win;
616  try {
617  gCurrentTest.run();
618  } catch (ex) {
619  ok(false, "An error occured during test run: " + ex.message);
620  }
621  });
622  }, false);
623  }
624  }
625  };
626  ww.registerNotification(windowObserver);
627 
628  var command = null;
629  switch(gCurrentTest.action) {
630  case ACTION_EDIT:
631  command = "placesCmd_show:info";
632  break;
633  case ACTION_ADD:
634  if (gCurrentTest.sidebar == SIDEBAR_BOOKMARKS_ID) {
635  if (gCurrentTest.itemType == TYPE_FOLDER)
636  command = "placesCmd_new:folder";
637  else if (gCurrentTest.itemType == TYPE_BOOKMARK)
638  command = "placesCmd_new:bookmark";
639  else
640  ok(false, "You didn't set a valid itemType for adding an item");
641  }
642  else
643  command = "placesCmd_createBookmark";
644  break;
645  default:
646  ok(false, "You didn't set a valid action for this test");
647  }
648  // Ensure command is enabled for this node.
649  ok(tree.controller.isCommandEnabled(command),
650  " command '" + command + "' on current selected node is enabled");
651 
652  // This will open the dialog.
653  tree.controller.doCommand(command);
654 }
var PlacesUIUtils
Definition: utils.js:85
const SIDEBAR_HISTORY_BYSITE_VIEW
function add_visit(aURI, aDate)
const SIDEBAR_HISTORY_BYDATE_VIEW
function setup()
function open_properties_dialog()
function test()
function execute_test_in_sidebar()
var event
const SIDEBAR_HISTORY_BYMOSTVISITED_VIEW
const SIDEBAR_HISTORY_BYLASTVISITED_VIEW
getService(Ci.sbIFaceplateManager)
let window
const SIDEBAR_HISTORY_ID
waitForExplicitFinish()
return null
Definition: FeedWriter.js:1143
const SIDEBAR_BOOKMARKS_ID
function cleanup()
return!aWindow arguments!aWindow arguments[0]
const SIDEBAR_HISTORY_BYDATEANDSITE_VIEW
const SIDEBAR_BOOKMARKS_TREE_ID
function runNextTest()
const TYPE_BOOKMARK
const SIDEBAR_HISTORY_TREE_ID
_updateTextAndScrollDataForFrame aData
function add_bookmark(aURI)
sbDeviceFirmwareAutoCheckForUpdate prototype observe
const DIALOG_URL_MINIMAL_UI