Bug 1480907 - Implement ability to bookmark a selection of tabs through drag and drop. r=Felipe
☠☠ backed out by ec1279ae74f3 ☠ ☠
authorJared Wein <jwein@mozilla.com>
Thu, 30 Aug 2018 21:57:03 +0000
changeset 482496 c8d6a8dca44d819667a0cacfed8f0b3f411e4bc5
parent 482495 962a34323e709b36f5e46cc89c5a603ab859b5ff
child 482497 96b5a88ac0041a1bd382a731749e1fca9aa911ed
push id232
push userfmarier@mozilla.com
push dateWed, 05 Sep 2018 20:45:54 +0000
reviewersFelipe
bugs1480907
milestone63.0a1
Bug 1480907 - Implement ability to bookmark a selection of tabs through drag and drop. r=Felipe Differential Revision: https://phabricator.services.mozilla.com/D4589
browser/base/content/tabbrowser.xml
browser/base/content/test/tabs/browser.ini
browser/base/content/test/tabs/browser_multiselect_tabs_drag_to_bookmarks_toolbar.js
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1194,36 +1194,43 @@
         event.preventDefault();
       ]]></handler>
 
       <handler event="dragstart"><![CDATA[
         var tab = this._getDragTargetTab(event, false);
         if (!tab || this._isCustomizing)
           return;
 
+        let selectedTabs = gBrowser.selectedTabs;
+        let otherSelectedTabs = selectedTabs.filter(selectedTab => selectedTab != tab);
+        let dataTransferOrderedTabs = [tab].concat(otherSelectedTabs);
+
         let dt = event.dataTransfer;
-        dt.mozSetDataAt(TAB_DROP_TYPE, tab, 0);
-        let browser = tab.linkedBrowser;
+        for (let i = 0; i < dataTransferOrderedTabs.length; i++) {
+          let dtTab = dataTransferOrderedTabs[i];
 
-        // We must not set text/x-moz-url or text/plain data here,
-        // otherwise trying to deatch the tab by dropping it on the desktop
-        // may result in an "internet shortcut"
-        dt.mozSetDataAt("text/x-moz-text-internal", browser.currentURI.spec, 0);
+          dt.mozSetDataAt(TAB_DROP_TYPE, dtTab, i);
+          let dtBrowser = dtTab.linkedBrowser;
+
+          // We must not set text/x-moz-url or text/plain data here,
+          // otherwise trying to deatch the tab by dropping it on the desktop
+          // may result in an "internet shortcut"
+          dt.mozSetDataAt("text/x-moz-text-internal", dtBrowser.currentURI.spec, i);
+        }
 
         // Set the cursor to an arrow during tab drags.
         dt.mozCursor = "default";
 
         // Set the tab as the source of the drag, which ensures we have a stable
         // node to deliver the `dragend` event.  See bug 1345473.
         dt.addElement(tab);
 
-        // Regroup all selected tabs around the dragged tab
-        // for multiple tabs dragging
         if (tab.multiselected) {
-          let selectedTabs = gBrowser.selectedTabs;
+          // Regroup all selected tabs around the dragged tab
+          // for multiple tabs dragging
           let draggedTabPos = tab._tPos;
 
           // Move left selected tabs
           let insertAtPos = draggedTabPos - 1;
           for (let i = selectedTabs.indexOf(tab) - 1; i > -1; i--) {
             let movingTab = selectedTabs[i];
             gBrowser.moveTabTo(movingTab, insertAtPos);
             insertAtPos--;
@@ -1252,16 +1259,17 @@
           canvas.style.height = "100%";
           canvas.mozOpaque = true;
         }
 
         canvas.width = 160 * scale;
         canvas.height = 90 * scale;
         let toDrag = canvas;
         let dragImageOffset = -16;
+        let browser = tab.linkedBrowser;
         if (gMultiProcessBrowser) {
           var context = canvas.getContext("2d");
           context.fillStyle = "white";
           context.fillRect(0, 0, canvas.width, canvas.height);
 
           let captureListener;
           let platform = AppConstants.platform;
           // On Windows and Mac we can update the drag image during a drag
--- a/browser/base/content/test/tabs/browser.ini
+++ b/browser/base/content/test/tabs/browser.ini
@@ -22,16 +22,17 @@ support-files =
 [browser_multiselect_tabs_active_tab_selected_by_default.js]
 [browser_multiselect_tabs_bookmark.js]
 [browser_multiselect_tabs_clear_selection_when_tab_switch.js]
 [browser_multiselect_tabs_close_other_tabs.js]
 [browser_multiselect_tabs_close_tabs_to_the_right.js]
 [browser_multiselect_tabs_close_using_shortcuts.js]
 [browser_multiselect_tabs_close.js]
 [browser_multiselect_tabs_copy_through_drag_and_drop.js]
+[browser_multiselect_tabs_drag_to_bookmarks_toolbar.js]
 [browser_multiselect_tabs_duplicate.js]
 [browser_multiselect_tabs_event.js]
 [browser_multiselect_tabs_move_to_another_window_drag.js]
 [browser_multiselect_tabs_move_to_new_window_contextmenu.js]
 [browser_multiselect_tabs_mute_unmute.js]
 [browser_multiselect_tabs_pin_unpin.js]
 [browser_multiselect_tabs_positional_attrs.js]
 [browser_multiselect_tabs_reload.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabs/browser_multiselect_tabs_drag_to_bookmarks_toolbar.js
@@ -0,0 +1,59 @@
+const PREF_MULTISELECT_TABS = "browser.tabs.multiselect";
+const PREF_ANIMATIONS_ENABLED = "toolkit.cosmeticAnimations.enabled";
+
+add_task(async function setPref() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      [PREF_MULTISELECT_TABS, true],
+      [PREF_ANIMATIONS_ENABLED, false]
+    ]
+  });
+});
+
+add_task(async function test() {
+  // Open Bookmarks Toolbar
+  let bookmarksToolbar = document.getElementById("PersonalToolbar");
+  setToolbarVisibility(bookmarksToolbar, true);
+  ok(!bookmarksToolbar.collapsed, "bookmarksToolbar should be visible now");
+
+  let tab1 = await addTab("http://mochi.test:8888/1");
+  let tab2 = await addTab("http://mochi.test:8888/2");
+  let tab3 = await addTab("http://mochi.test:8888/3");
+  let tab4 = await addTab("http://mochi.test:8888/4");
+  let tab5 = await addTab("http://mochi.test:8888/5");
+
+  is(gBrowser.multiSelectedTabsCount, 0, "Zero multiselected tabs");
+
+  await BrowserTestUtils.switchTab(gBrowser, tab2);
+  await triggerClickOn(tab1, { ctrlKey: true });
+
+  ok(tab1.multiselected, "Tab1 is multiselected");
+  ok(tab2.multiselected, "Tab2 is multiselected");
+  ok(!tab3.multiselected, "Tab3 is not multiselected");
+  ok(!tab4.multiselected, "Tab4 is not multiselected");
+  ok(!tab5.multiselected, "Tab5 is not multiselected");
+  is(gBrowser.multiSelectedTabsCount, 2, "Two multiselected tabs");
+
+  // Use getElementsByClassName so the list is live and will update as items change.
+  let currentBookmarks = bookmarksToolbar.getElementsByClassName("bookmark-item");
+  let startBookmarksLength = currentBookmarks.length;
+
+  let lastBookmark = currentBookmarks[currentBookmarks.length - 1];
+  await EventUtils.synthesizePlainDragAndDrop({srcElement: tab1, destElement: lastBookmark});
+  await TestUtils.waitForCondition(() => currentBookmarks.length == startBookmarksLength + 2,
+    "waiting for 2 bookmarks");
+  is(currentBookmarks.length, startBookmarksLength + 2, "Bookmark count should have increased by 2");
+
+  // Drag non-selection to the bookmarks toolbar
+  startBookmarksLength = currentBookmarks.length;
+  await EventUtils.synthesizePlainDragAndDrop({srcElement: tab3, destElement: lastBookmark});
+  await TestUtils.waitForCondition(() => currentBookmarks.length == startBookmarksLength + 1,
+    "waiting for 1 bookmark");
+  is(currentBookmarks.length, startBookmarksLength + 1, "Bookmark count should have increased by 1");
+
+  BrowserTestUtils.removeTab(tab1);
+  BrowserTestUtils.removeTab(tab2);
+  BrowserTestUtils.removeTab(tab3);
+  BrowserTestUtils.removeTab(tab4);
+  BrowserTestUtils.removeTab(tab5);
+});