Bug 1322408 - Use `gBrowser.loadTabs` to open all tabs when middle-clicking a client in Synced Tabs. r=markh
MozReview-Commit-ID: 6phgHjAAXUs
--- a/browser/components/syncedtabs/SyncedTabsDeckComponent.js
+++ b/browser/components/syncedtabs/SyncedTabsDeckComponent.js
@@ -47,16 +47,17 @@ function SyncedTabsDeckComponent({
this._syncedTabsListStore = listStore || new SyncedTabsListStore(SyncedTabs);
this.tabListComponent = listComponent || new TabListComponent({
window: this._window,
store: this._syncedTabsListStore,
View: TabListView,
SyncedTabs: SyncedTabs,
clipboardHelper: Cc["@mozilla.org/widget/clipboardhelper;1"]
.getService(Ci.nsIClipboardHelper),
+ getChromeWindow: this._getChromeWindow,
});
}
SyncedTabsDeckComponent.prototype = {
PANELS: {
TABS_CONTAINER: "tabs-container",
TABS_FETCHING: "tabs-fetching",
NOT_AUTHED_INFO: "notAuthedInfo",
--- a/browser/components/syncedtabs/TabListComponent.js
+++ b/browser/components/syncedtabs/TabListComponent.js
@@ -24,21 +24,23 @@ this.EXPORTED_SYMBOLS = [
* TabListComponent
*
* The purpose of this component is to compose the view, state, and actions.
* It defines high level actions that act on the state and passes them to the
* view for it to trigger during user interaction. It also subscribes the view
* to state changes so it can rerender.
*/
-function TabListComponent({window, store, View, SyncedTabs, clipboardHelper}) {
+function TabListComponent({window, store, View, SyncedTabs, clipboardHelper,
+ getChromeWindow}) {
this._window = window;
this._store = store;
this._View = View;
this._clipboardHelper = clipboardHelper;
+ this._getChromeWindow = getChromeWindow;
// used to trigger Sync from context menu
this._SyncedTabs = SyncedTabs;
}
TabListComponent.prototype = {
get container() {
return this._view.container;
},
@@ -111,27 +113,26 @@ TabListComponent.prototype = {
.catch(Cu.reportError);
},
onOpenTab(url, where, params) {
this._window.openUILinkIn(url, where, params);
BrowserUITelemetry.countSyncedTabEvent("open", "sidebar");
},
- onOpenTabs(urls, where, params) {
+ onOpenTabs(urls, where) {
if (!PlacesUIUtils.confirmOpenInTabs(urls.length, this._window)) {
return;
}
if (where == "window") {
this._window.openDialog(this._window.getBrowserURL(), "_blank",
"chrome,dialog=no,all", urls.join("|"));
} else {
- for (let url of urls) {
- this._window.openUILinkIn(url, where, params);
- }
+ let loadInBackground = where == "tabshifted" ? true : false;
+ this._getChromeWindow(this._window).gBrowser.loadTabs(urls, loadInBackground, false);
}
BrowserUITelemetry.countSyncedTabEvent("openmultiple", "sidebar");
},
onCopyTabLocation(url) {
this._clipboardHelper.copyString(url);
},
--- a/browser/components/syncedtabs/TabListView.js
+++ b/browser/components/syncedtabs/TabListView.js
@@ -284,17 +284,17 @@ TabListView.prototype = {
}
// Middle click on a client
if (itemNode.classList.contains("client")) {
let where = getChromeWindow(this._window).whereToOpenLink(event);
if (where != "current") {
const tabs = itemNode.querySelector(".item-tabs-list").childNodes;
const urls = [...tabs].map(tab => tab.dataset.url);
- this.props.onOpenTabs(urls, where, {});
+ this.props.onOpenTabs(urls, where);
}
}
if (event.target.classList.contains("item-twisty-container")
&& event.which != 2) {
this.props.onToggleBranch(itemNode.dataset.id);
return;
}
--- a/browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js
+++ b/browser/components/syncedtabs/test/xpcshell/test_TabListComponent.js
@@ -63,33 +63,41 @@ add_task(function* testInitUninit() {
"view.render is called on state change");
component.uninit();
Assert.ok(view.destroy.calledOnce, "view is destroyed on uninit");
});
add_task(function* testActions() {
let store = new SyncedTabsListStore();
+ let chromeWindowMock = {
+ gBrowser: {
+ loadTabs() {},
+ },
+ };
+ let getChromeWindowMock = sinon.stub();
+ getChromeWindowMock.returns(chromeWindowMock);
let clipboardHelperMock = {
copyString() {},
};
let windowMock = {
top: {
PlacesCommandHook: {
bookmarkLink() { return Promise.resolve(); }
},
PlacesUtils: { bookmarksMenuFolderId: "id" }
},
getBrowserURL() {},
openDialog() {},
openUILinkIn() {}
};
let component = new TabListComponent({
window: windowMock, store, View: null, SyncedTabs,
- clipboardHelper: clipboardHelperMock});
+ clipboardHelper: clipboardHelperMock,
+ getChromeWindow: getChromeWindowMock });
sinon.stub(store, "getData");
component.onFilter("query");
Assert.ok(store.getData.calledWith("query"));
sinon.stub(store, "clearFilter");
component.onClearFilter();
Assert.ok(store.clearFilter.called);
@@ -122,22 +130,23 @@ add_task(function* testActions() {
component.onBookmarkTab("uri", "title");
Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][1], "uri");
Assert.equal(windowMock.top.PlacesCommandHook.bookmarkLink.args[0][2], "title");
sinon.spy(windowMock, "openUILinkIn");
component.onOpenTab("uri", "where", "params");
Assert.ok(windowMock.openUILinkIn.calledWith("uri", "where", "params"));
- component.onOpenTabs(["uri1", "uri2"], "where", "params");
- Assert.ok(windowMock.openUILinkIn.calledWith("uri1", "where", "params"));
- Assert.ok(windowMock.openUILinkIn.calledWith("uri2", "where", "params"));
- sinon.spy(windowMock, "openDialog");
- component.onOpenTabs(["uri1", "uri2"], "window", "params");
- Assert.deepEqual(windowMock.openDialog.args[0][3], ["uri1", "uri2"].join("|"));
+ sinon.spy(chromeWindowMock.gBrowser, "loadTabs");
+ let tabsToOpen = ["uri1", "uri2"];
+ component.onOpenTabs(tabsToOpen, "where");
+ Assert.ok(getChromeWindowMock.calledWith(windowMock));
+ Assert.ok(chromeWindowMock.gBrowser.loadTabs.calledWith(tabsToOpen, false, false));
+ component.onOpenTabs(tabsToOpen, "tabshifted");
+ Assert.ok(chromeWindowMock.gBrowser.loadTabs.calledWith(tabsToOpen, true, false));
sinon.spy(clipboardHelperMock, "copyString");
component.onCopyTabLocation("uri");
Assert.ok(clipboardHelperMock.copyString.calledWith("uri"));
sinon.stub(SyncedTabs, "syncTabs");
component.onSyncRefresh();
Assert.ok(SyncedTabs.syncTabs.calledWith(true));