fix usage of openerTabId in openURL + cosmetics (#859)
* fix usage of openerTabId in openURL + cosmetics * fixups * fixup
This commit is contained in:
parent
8380a674b9
commit
df8c258c84
|
@ -1,7 +1,7 @@
|
||||||
/* global download prefs openURL FIREFOX CHROME VIVALDI
|
/* global download prefs openURL FIREFOX CHROME VIVALDI
|
||||||
debounce URLS ignoreChromeError getTab
|
debounce URLS ignoreChromeError getTab
|
||||||
styleManager msg navigatorUtil iconUtil workerUtil contentScripts sync
|
styleManager msg navigatorUtil iconUtil workerUtil contentScripts sync
|
||||||
findExistTab createTab activateTab isTabReplaceable getActiveTab */
|
findExistingTab createTab activateTab isTabReplaceable getActiveTab */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -437,7 +437,7 @@ function openManage({options = false, search} = {}) {
|
||||||
if (options) {
|
if (options) {
|
||||||
url += '#stylus-options';
|
url += '#stylus-options';
|
||||||
}
|
}
|
||||||
return findExistTab({
|
return findExistingTab({
|
||||||
url,
|
url,
|
||||||
currentWindow: null,
|
currentWindow: null,
|
||||||
ignoreHash: true,
|
ignoreHash: true,
|
||||||
|
|
|
@ -97,9 +97,13 @@ const createTab = promisify(chrome.tabs.create.bind(chrome.tabs));
|
||||||
const queryTabs = promisify(chrome.tabs.query.bind(chrome.tabs));
|
const queryTabs = promisify(chrome.tabs.query.bind(chrome.tabs));
|
||||||
const updateTab = promisify(chrome.tabs.update.bind(chrome.tabs));
|
const updateTab = promisify(chrome.tabs.update.bind(chrome.tabs));
|
||||||
const moveTabs = promisify(chrome.tabs.move.bind(chrome.tabs));
|
const moveTabs = promisify(chrome.tabs.move.bind(chrome.tabs));
|
||||||
// FIXME: is it possible that chrome.windows is undefined?
|
|
||||||
const updateWindow = promisify(chrome.windows.update.bind(chrome.windows));
|
// Android doesn't have chrome.windows
|
||||||
const createWindow = promisify(chrome.windows.create.bind(chrome.windows));
|
const updateWindow = chrome.windows && promisify(chrome.windows.update.bind(chrome.windows));
|
||||||
|
const createWindow = chrome.windows && promisify(chrome.windows.create.bind(chrome.windows));
|
||||||
|
// FF57+ supports openerTabId, but not in Android
|
||||||
|
// (detecting FF57 by the feature it added, not navigator.ua which may be spoofed in about:config)
|
||||||
|
const openerTabIdSupported = (!FIREFOX || window.AbortController) && chrome.windows != null;
|
||||||
|
|
||||||
function getTab(id) {
|
function getTab(id) {
|
||||||
return new Promise(resolve =>
|
return new Promise(resolve =>
|
||||||
|
@ -210,7 +214,7 @@ function urlToMatchPattern(url, ignoreSearch) {
|
||||||
return `${url.protocol}//${url.hostname}/${url.pathname}${url.search}`;
|
return `${url.protocol}//${url.hostname}/${url.pathname}${url.search}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findExistTab({url, currentWindow, ignoreHash = true, ignoreSearch = false}) {
|
function findExistingTab({url, currentWindow, ignoreHash = true, ignoreSearch = false}) {
|
||||||
url = new URL(url);
|
url = new URL(url);
|
||||||
return queryTabs({url: urlToMatchPattern(url, ignoreSearch), currentWindow})
|
return queryTabs({url: urlToMatchPattern(url, ignoreSearch), currentWindow})
|
||||||
// FIXME: is tab.url always normalized?
|
// FIXME: is tab.url always normalized?
|
||||||
|
@ -232,65 +236,53 @@ function findExistTab({url, currentWindow, ignoreHash = true, ignoreSearch = fal
|
||||||
/**
|
/**
|
||||||
* Opens a tab or activates an existing one,
|
* Opens a tab or activates an existing one,
|
||||||
* reuses the New Tab page or about:blank if it's focused now
|
* reuses the New Tab page or about:blank if it's focused now
|
||||||
* @param {Object} params
|
* @param {Object} _
|
||||||
* or just a string e.g. openURL('foo')
|
* @param {string} _.url - if relative, it's auto-expanded to the full extension URL
|
||||||
* @param {string} params.url
|
* @param {number} [_.index] move the tab to this index in the tab strip, -1 = last
|
||||||
* if relative, it's auto-expanded to the full extension URL
|
* @param {number} [_.openerTabId] defaults to the active tab
|
||||||
* @param {number} [params.index]
|
* @param {Boolean} [_.active=true] `true` to activate the tab
|
||||||
* move the tab to this index in the tab strip, -1 = last
|
* @param {Boolean|null} [_.currentWindow=true] `null` to check all windows
|
||||||
* @param {Boolean} [params.active]
|
* @param {Boolean} [_.newWindow=false] `true` to open a new window
|
||||||
* true to activate the tab (this is the default value in the extensions API),
|
* @param {chrome.windows.CreateData} [_.windowPosition] options for chrome.windows.create
|
||||||
* false to open in background
|
* @returns {Promise<chrome.tabs.Tab>} Promise -> opened/activated tab
|
||||||
* @param {?Boolean} [params.currentWindow]
|
|
||||||
* pass null to check all windows
|
|
||||||
* @param {any} [params.message]
|
|
||||||
* JSONifiable data to be sent to the tab via sendMessage()
|
|
||||||
* @returns {Promise<Tab>} Promise that resolves to the opened/activated tab
|
|
||||||
*/
|
*/
|
||||||
function openURL(options) {
|
function openURL({
|
||||||
if (typeof options === 'string') {
|
|
||||||
options = {url: options};
|
|
||||||
}
|
|
||||||
let {
|
|
||||||
url,
|
url,
|
||||||
index,
|
index,
|
||||||
active,
|
openerTabId,
|
||||||
|
active = true,
|
||||||
currentWindow = true,
|
currentWindow = true,
|
||||||
newWindow = false,
|
newWindow = false,
|
||||||
windowPosition
|
windowPosition,
|
||||||
} = options;
|
}) {
|
||||||
|
|
||||||
if (!url.includes('://')) {
|
if (!url.includes('://')) {
|
||||||
url = chrome.runtime.getURL(url);
|
url = chrome.runtime.getURL(url);
|
||||||
}
|
}
|
||||||
return findExistTab({url, currentWindow}).then(tab => {
|
return findExistingTab({url, currentWindow}).then(tab => {
|
||||||
if (tab) {
|
if (tab) {
|
||||||
// update url if only hash is different?
|
return activateTab(tab, {
|
||||||
// we can't update URL if !url.includes('#') since it refreshes the page
|
index,
|
||||||
// FIXME: should we move the tab (i.e. specifying index)?
|
openerTabId,
|
||||||
if (tab.url !== url && tab.url.split('#')[0] === url.split('#')[0] &&
|
// when hash is different we can only set `url` if it has # otherwise the tab would reload
|
||||||
url.includes('#')) {
|
url: url !== tab.url && url.includes('#') ? url : undefined,
|
||||||
return activateTab(tab, {url, index});
|
});
|
||||||
}
|
}
|
||||||
return activateTab(tab, {index});
|
if (newWindow && createWindow) {
|
||||||
|
return createWindow(Object.assign({url}, windowPosition))
|
||||||
|
.then(wnd => wnd.tabs[0]);
|
||||||
}
|
}
|
||||||
if (newWindow) {
|
return getActiveTab().then((activeTab = {url: ''}) =>
|
||||||
return createWindow(Object.assign({url}, windowPosition));
|
isTabReplaceable(activeTab, url) ?
|
||||||
}
|
activateTab(activeTab, {url, openerTabId}) : // not moving the tab
|
||||||
return getActiveTab().then(tab => {
|
createTabWithOpener(activeTab, {url, index, active}));
|
||||||
if (isTabReplaceable(tab, url)) {
|
});
|
||||||
// don't move the tab in this case
|
function createTabWithOpener(openerTab, options) {
|
||||||
return activateTab(tab, {url});
|
const id = openerTabId == null ? openerTab.id : openerTabId;
|
||||||
}
|
if (id != null && !openerTab.incognito && openerTabIdSupported) {
|
||||||
const options = {url, index, active};
|
options.openerTabId = id;
|
||||||
// FF57+ supports openerTabId, but not in Android (indicated by the absence of chrome.windows)
|
|
||||||
// FIXME: is it safe to assume that the current tab is the opener?
|
|
||||||
if (tab && !tab.incognito && (!FIREFOX || FIREFOX >= 57 && chrome.windows)) {
|
|
||||||
options.openerTabId = tab.id;
|
|
||||||
}
|
}
|
||||||
return createTab(options);
|
return createTab(options);
|
||||||
});
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace empty tab (NTP or about:blank)
|
// replace empty tab (NTP or about:blank)
|
||||||
|
@ -307,14 +299,17 @@ function isTabReplaceable(tab, newUrl) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function activateTab(tab, {url, index} = {}) {
|
function activateTab(tab, {url, index, openerTabId} = {}) {
|
||||||
const options = {active: true};
|
const options = {active: true};
|
||||||
if (url) {
|
if (url) {
|
||||||
options.url = url;
|
options.url = url;
|
||||||
}
|
}
|
||||||
|
if (openerTabId != null && openerTabIdSupported) {
|
||||||
|
options.openerTabId = openerTabId;
|
||||||
|
}
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
updateTab(tab.id, options),
|
updateTab(tab.id, options),
|
||||||
updateWindow(tab.windowId, {focused: true}),
|
updateWindow && updateWindow(tab.windowId, {focused: true}),
|
||||||
index != null && moveTabs(tab.id, {index})
|
index != null && moveTabs(tab.id, {index})
|
||||||
])
|
])
|
||||||
.then(() => tab);
|
.then(() => tab);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user