Bug 909102 - Fix middle-clicking on a folder in the left panel of the Library (to open all items within the folder). r=mak
authorMark Banner <standard8@mozilla.com>
Thu, 02 Mar 2017 11:34:43 +0000
changeset 346180 15fa3319c37f5ad0fcdf7bf4dbb8d3d60fafc740
parent 346179 cf95c2d49e1ca52fdddb86a808682a4b675c0eae
child 346181 9055693f792d975268d8175244eecd17456f2e8d
push id31459
push usercbook@mozilla.com
push dateTue, 07 Mar 2017 14:05:14 +0000
treeherdermozilla-central@1fb56ba248d5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs909102
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 909102 - Fix middle-clicking on a folder in the left panel of the Library (to open all items within the folder). r=mak MozReview-Commit-ID: 75Z8wOynfQh
browser/components/places/content/places.js
browser/components/places/tests/browser/browser.ini
browser/components/places/tests/browser/browser_library_left_pane_middleclick.js
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -308,17 +308,17 @@ var PlacesOrganizer = {
 
     let node = this._places.selectedNode;
     if (node) {
       let middleClick = aEvent.button == 1 && aEvent.detail == 1;
       if (middleClick && PlacesUtils.nodeIsContainer(node)) {
         // The command execution function will take care of seeing if the
         // selection is a folder or a different container type, and will
         // load its contents in tabs.
-        PlacesUIUtils.openContainerNodeInTabs(selectedNode, aEvent, this._places);
+        PlacesUIUtils.openContainerNodeInTabs(node, aEvent, this._places);
       }
     }
   },
 
   /**
    * Handle focus changes on the places list and the current content view.
    */
   updateDetailsPane: function PO_updateDetailsPane() {
--- a/browser/components/places/tests/browser/browser.ini
+++ b/browser/components/places/tests/browser/browser.ini
@@ -34,16 +34,17 @@ support-files =
 [browser_drag_bookmarks_on_toolbar.js]
 [browser_forgetthissite_single.js]
 [browser_history_sidebar_search.js]
 [browser_library_batch_delete.js]
 [browser_library_commands.js]
 [browser_library_downloads.js]
 [browser_library_infoBox.js]
 [browser_library_left_pane_fixnames.js]
+[browser_library_left_pane_middleclick.js]
 [browser_library_left_pane_select_hierarchy.js]
 [browser_library_middleclick.js]
 [browser_library_open_leak.js]
 [browser_library_openFlatContainer.js]
 [browser_library_panel_leak.js]
 [browser_library_search.js]
 [browser_library_views_liveupdate.js]
 [browser_markPageAsFollowedLink.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/places/tests/browser/browser_library_left_pane_middleclick.js
@@ -0,0 +1,196 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+ /**
+ * Tests middle-clicking items in the Library.
+ */
+
+const ENABLE_HISTORY_PREF = "places.history.enabled";
+
+var gLibrary = null;
+var gTests = [];
+var gCurrentTest = null;
+
+// Listener for TabOpen and tabs progress.
+var gTabsListener = {
+  _loadedURIs: [],
+  _openTabsCount: 0,
+
+  handleEvent(aEvent) {
+    if (aEvent.type != "TabOpen")
+      return;
+
+    if (++this._openTabsCount == gCurrentTest.URIs.length) {
+      is(gBrowser.tabs.length, gCurrentTest.URIs.length + 1,
+         "We have opened " + gCurrentTest.URIs.length + " new tab(s)");
+    }
+
+    var tab = aEvent.target;
+    is(tab.ownerGlobal, window,
+       "Tab has been opened in current browser window");
+  },
+
+  onLocationChange(aBrowser, aWebProgress, aRequest, aLocationURI,
+                             aFlags) {
+    var spec = aLocationURI.spec;
+    ok(true, spec);
+    // When a new tab is opened, location is first set to "about:blank", so
+    // we can ignore those calls.
+    // Ignore multiple notifications for the same URI too.
+    if (spec == "about:blank" || this._loadedURIs.includes(spec))
+      return;
+
+    ok(gCurrentTest.URIs.includes(spec),
+       "Opened URI found in list: " + spec);
+
+    if (gCurrentTest.URIs.includes(spec))
+      this._loadedURIs.push(spec);
+
+    if (this._loadedURIs.length == gCurrentTest.URIs.length) {
+      // We have correctly opened all URIs.
+
+      // Reset arrays.
+      this._loadedURIs.length = 0;
+
+      this._openTabsCount = 0;
+
+      executeSoon(function() {
+        // Close all tabs.
+        while (gBrowser.tabs.length > 1)
+          gBrowser.removeCurrentTab();
+
+        // Test finished.  This will move to the next one.
+        waitForFocus(gCurrentTest.finish, gBrowser.ownerGlobal);
+      });
+    }
+  }
+}
+
+// ------------------------------------------------------------------------------
+// Open a folder in tabs.
+
+gTests.push({
+  desc: "Open a folder in tabs.",
+  URIs: ["about:buildconfig", "about:"],
+  _folderId: -1,
+
+  setup() {
+    var bs = PlacesUtils.bookmarks;
+    // Create a new folder.
+    var folderId = bs.createFolder(bs.unfiledBookmarksFolder,
+                                   "Folder",
+                                   bs.DEFAULT_INDEX);
+    this._folderId = folderId;
+
+    // Add bookmarks in folder.
+    this.URIs.forEach(function(aURI) {
+      bs.insertBookmark(folderId,
+                        PlacesUtils._uri(aURI),
+                        bs.DEFAULT_INDEX,
+                        "Title");
+    });
+
+    // Select unsorted bookmarks root in the left pane.
+    gLibrary.PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks");
+    isnot(gLibrary.PlacesOrganizer._places.selectedNode, null,
+          "We correctly have selection in the Library left pane");
+    // Get our bookmark in the right pane.
+    var folderNode = gLibrary.ContentTree.view.view.nodeForTreeIndex(0);
+    is(folderNode.title, "Folder", "Found folder in the right pane");
+  },
+
+  finish() {
+    setTimeout(runNextTest, 0);
+  },
+
+  cleanup() {
+    PlacesUtils.bookmarks.removeItem(this._folderId);
+  }
+});
+
+// ------------------------------------------------------------------------------
+
+function test() {
+  waitForExplicitFinish();
+
+  // Sanity checks.
+  ok(PlacesUtils, "PlacesUtils in context");
+  ok(PlacesUIUtils, "PlacesUIUtils in context");
+
+  // Add tabs listeners.
+  gBrowser.tabContainer.addEventListener("TabOpen", gTabsListener);
+  gBrowser.addTabsProgressListener(gTabsListener);
+
+  // Temporary disable history, so we won't record pages navigation.
+  gPrefService.setBoolPref(ENABLE_HISTORY_PREF, false);
+
+  // Open Library window.
+  openLibrary(function(library) {
+    gLibrary = library;
+    // Kick off tests.
+    runNextTest();
+  });
+}
+
+function runNextTest() {
+  // Cleanup from previous test.
+  if (gCurrentTest)
+    gCurrentTest.cleanup();
+
+  if (gTests.length > 0) {
+    // Goto next test.
+    gCurrentTest = gTests.shift();
+    info("Start of test: " + gCurrentTest.desc);
+    // Test setup will set Library so that the bookmark to be opened is the
+    // first node in the content (right pane) tree.
+    gCurrentTest.setup();
+
+    gLibrary.focus();
+    waitForFocus(function() {
+      // Open the "Other Bookmarks" folder.
+      gLibrary.PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks");
+      gLibrary.PlacesOrganizer._places.selectedNode.containerOpen = true;
+      // Now middle-click on the bookmark contained with it.
+      let bookmarkedNode = gLibrary.PlacesOrganizer._places.selectedNode.getChild(0);
+      mouseEventOnCell(gLibrary.PlacesOrganizer._places,
+        gLibrary.PlacesOrganizer._places.view.treeIndexForNode(bookmarkedNode),
+        0,
+        { button: 1 });
+    }, gLibrary);
+  } else {
+    // No more tests.
+
+    // We must close "Other Bookmarks" ready for other tests.
+    gLibrary.PlacesOrganizer.selectLeftPaneQuery("UnfiledBookmarks");
+    gLibrary.PlacesOrganizer._places.selectedNode.containerOpen = false;
+
+    // Close Library window.
+    gLibrary.close();
+
+    // Remove tabs listeners.
+    gBrowser.tabContainer.removeEventListener("TabOpen", gTabsListener);
+    gBrowser.removeTabsProgressListener(gTabsListener);
+
+    // Restore history.
+    try {
+      gPrefService.clearUserPref(ENABLE_HISTORY_PREF);
+    } catch (ex) {}
+
+    finish();
+  }
+}
+
+function mouseEventOnCell(aTree, aRowIndex, aColumnIndex, aEventDetails) {
+  var selection = aTree.view.selection;
+  selection.select(aRowIndex);
+  aTree.treeBoxObject.ensureRowIsVisible(aRowIndex);
+  var column = aTree.columns[aColumnIndex];
+
+  // get cell coordinates
+  var rect = aTree.treeBoxObject.getCoordsForCellItem(aRowIndex, column, "text");
+
+  EventUtils.synthesizeMouse(aTree.body, rect.x, rect.y,
+                             aEventDetails, gLibrary);
+}