Bug 1214007 - Implement chrome.tabs.move. r=billm

This commit is contained in:
Andy McKay 2015-12-23 17:04:23 -08:00
Родитель 9981852508
Коммит 5847404799
4 изменённых файлов: 318 добавлений и 0 удалений

Просмотреть файл

@ -536,6 +536,82 @@ extensions.registerSchemaAPI("tabs", null, (extension, context) => {
}
return context.messenger.sendMessage(mm, message, recipient, responseCallback);
},
move: function(tabIds, moveProperties, callback) {
let index = moveProperties.index;
let tabsMoved = [];
if (!Array.isArray(tabIds)) {
tabIds = [tabIds];
}
let destinationWindow = null;
if (moveProperties.windowId !== null) {
destinationWindow = WindowManager.getWindow(moveProperties.windowId);
// Ignore invalid window.
if (!destinationWindow) {
return;
}
}
/*
Indexes are maintained on a per window basis so that a call to
move([tabA, tabB], {index: 0})
-> tabA to 0, tabB to 1 if tabA and tabB are in the same window
move([tabA, tabB], {index: 0})
-> tabA to 0, tabB to 0 if tabA and tabB are in different windows
*/
let indexMap = new Map();
for (let tabId of tabIds) {
let tab = TabManager.getTab(tabId);
// Ignore invalid tab ids.
if (!tab) {
continue;
}
// If the window is not specified, use the window from the tab.
let window = destinationWindow || tab.ownerDocument.defaultView;
let windowId = WindowManager.getId(window);
let gBrowser = window.gBrowser;
let getInsertionPoint = () => {
let point = indexMap.get(window) || index;
// If the index is -1 it should go to the end of the tabs.
if (point == -1) {
point = gBrowser.tabs.length;
}
indexMap.set(window, point + 1);
return point;
};
if (WindowManager.getId(tab.ownerDocument.defaultView) !== windowId) {
// If the window we are moving the tab in is different, then move the tab
// to the new window.
let newTab = gBrowser.addTab('about:blank');
let newBrowser = gBrowser.getBrowserForTab(newTab);
gBrowser.updateBrowserRemotenessByURL(newBrowser, tab.linkedBrowser.currentURI.spec);
newBrowser.stop();
newBrowser.docShell;
if (tab.pinned) {
gBrowser.pinTab(newTab);
}
gBrowser.moveTabTo(newTab, getInsertionPoint());
tab.parentNode._finishAnimateTabMove();
gBrowser.swapBrowsersAndCloseOther(newTab, tab);
} else {
// If the window we are moving is the same, just move the tab.
gBrowser.moveTabTo(tab, getInsertionPoint());
}
tabsMoved.push(tab);
}
if (callback) {
runSafe(context, callback, tabsMoved.map(tab => TabManager.convert(extension, tab)));
}
},
},
};
return self;

Просмотреть файл

@ -27,6 +27,8 @@ support-files =
[browser_ext_tabs_update.js]
[browser_ext_tabs_onUpdated.js]
[browser_ext_tabs_sendMessage.js]
[browser_ext_tabs_move.js]
[browser_ext_tabs_move_window.js]
[browser_ext_windows_update.js]
[browser_ext_contentscript_connect.js]
[browser_ext_tab_runtimeConnect.js]

Просмотреть файл

@ -0,0 +1,117 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* () {
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:robots");
let tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
gBrowser.selectedTab = tab1
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
var tab = tabs[0];
chrome.tabs.move(tab.id, {index: 0});
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.test.assertEq(tabs[0].url, tab.url, "should be first tab");
browser.test.notifyPass("tabs.move.single");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("tabs.move.single");
yield extension.unload();
extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
tabs.sort(function(a, b) { return a.url > b.url; });
chrome.tabs.move(tabs.map(tab => tab.id), {index: 0});
chrome.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.test.assertEq(tabs[0].url, "about:blank", "should be first tab");
browser.test.assertEq(tabs[1].url, "about:config", "should be second tab");
browser.test.assertEq(tabs[2].url, "about:robots", "should be third tab");
browser.test.notifyPass("tabs.move.multiple");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("tabs.move.multiple");
yield extension.unload();
extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
var tab = tabs[0];
// Assuming that tab.id of 12345 does not exist.
chrome.tabs.move([12345, tab.id], {index: 0});
chrome.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.test.assertEq(tabs[0].url, tab.url, "should be first tab");
browser.test.notifyPass("tabs.move.invalid");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("tabs.move.invalid");
yield extension.unload();
extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
},
background: function() {
browser.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
var tab = tabs[0];
chrome.tabs.move(tab.id, {index: -1});
chrome.tabs.query({
lastFocusedWindow: true,
}, function(tabs) {
browser.test.assertEq(tabs[2].url, tab.url, "should be last tab");
browser.test.notifyPass("tabs.move.last");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("tabs.move.last");
yield extension.unload();
yield BrowserTestUtils.removeTab(tab1);
yield BrowserTestUtils.removeTab(tab2);
});

Просмотреть файл

@ -0,0 +1,123 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
add_task(function* () {
let tab0 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.net/");
let window1 = yield BrowserTestUtils.openNewBrowserWindow();
let tab1 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
},
background: function() {
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
let destination = tabs[0];
let source = tabs[1]; // skip over about:blank in window1
chrome.tabs.move(source.id, {windowId: destination.windowId, index: 0});
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
browser.test.assertEq(tabs[0].url, "http://example.com/");
browser.test.assertEq(tabs[0].windowId, destination.windowId);
browser.test.notifyPass("tabs.move.window");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("tabs.move.window");
yield extension.unload();
for (let tab of window.gBrowser.tabs) {
yield BrowserTestUtils.removeTab(tab);
}
yield BrowserTestUtils.closeWindow(window1);
});
add_task(function* () {
let tab0 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.net/");
let window1 = yield BrowserTestUtils.openNewBrowserWindow();
let tab1 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
window1.gBrowser.pinTab(tab1);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
},
background: function() {
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
let destination = tabs[0];
let source = tabs[1]; // remember, pinning moves it to the left.
chrome.tabs.move(source.id, {windowId: destination.windowId, index: 0});
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
browser.test.assertEq(true, tabs[0].pinned);
browser.test.notifyPass("tabs.move.pin");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("tabs.move.pin");
yield extension.unload();
for (let tab of window.gBrowser.tabs) {
yield BrowserTestUtils.removeTab(tab);
}
yield BrowserTestUtils.closeWindow(window1);
});
add_task(function* () {
let window1 = yield BrowserTestUtils.openNewBrowserWindow();
let tab0 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, "http://example.net/");
let tab1 = yield BrowserTestUtils.openNewForegroundTab(window.gBrowser, "http://example.com/");
let tab2 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.net/");
let tab3 = yield BrowserTestUtils.openNewForegroundTab(window1.gBrowser, "http://example.com/");
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"permissions": ["tabs"]
},
background: function() {
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
let move1 = tabs[1];
let move3 = tabs[3];
chrome.tabs.move([move1.id, move3.id], {index: 0});
chrome.tabs.query({
url: '<all_urls>',
}, function(tabs) {
browser.test.assertEq(tabs[0].url, move1.url);
browser.test.assertEq(tabs[2].url, move3.url);
browser.test.notifyPass("tabs.move.multiple");
});
});
},
});
yield extension.startup();
yield extension.awaitFinish("tabs.move.multiple");
yield extension.unload();
for (let tab of window.gBrowser.tabs) {
yield BrowserTestUtils.removeTab(tab);
}
yield BrowserTestUtils.closeWindow(window1);
});