182 lines
4.6 KiB
JavaScript
182 lines
4.6 KiB
JavaScript
/*
|
|
# 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/.
|
|
*/
|
|
'use strict';
|
|
|
|
import {
|
|
log as internalLogger,
|
|
configs,
|
|
wait,
|
|
} from './common.js';
|
|
import * as ApiTabs from './api-tabs.js';
|
|
import * as Constants from './constants.js';
|
|
import * as TabsStore from './tabs-store.js';
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
function log(...args) {
|
|
internalLogger('common/unique-id', ...args);
|
|
}
|
|
|
|
//===================================================================
|
|
// Unique Tab ID
|
|
//===================================================================
|
|
|
|
// for generated IDs
|
|
const kID_ADJECTIVES = `
|
|
Agile
|
|
Breezy
|
|
Cheerful
|
|
Dapper
|
|
Edgy
|
|
Feisty
|
|
Gutsy
|
|
Hoary
|
|
Intrepid
|
|
Jaunty
|
|
Karmic
|
|
Lucid
|
|
Marveric
|
|
Natty
|
|
Oneiric
|
|
Precise
|
|
Quantal
|
|
Raring
|
|
Saucy
|
|
Trusty
|
|
Utopic
|
|
Vivid
|
|
Warty
|
|
Xenial
|
|
Yakkety
|
|
Zesty
|
|
`.toLowerCase().trim().split(/\s+/);
|
|
|
|
const kID_NOUNS = `
|
|
Alpaca
|
|
Badger
|
|
Cat
|
|
Drake
|
|
Eft
|
|
Fawn
|
|
Gibbon
|
|
Heron
|
|
Ibis
|
|
Jackalope
|
|
Koala
|
|
Lynx
|
|
Meerkat
|
|
Narwhal
|
|
Ocelot
|
|
Pangolin
|
|
Quetzal
|
|
Ringtail
|
|
Salamander
|
|
Tahr
|
|
Unicorn
|
|
Vervet
|
|
Werwolf
|
|
Xerus
|
|
Yak
|
|
Zapus
|
|
`.toLowerCase().trim().split(/\s+/);
|
|
|
|
let mReadyToDetectDuplicatedTab = false;
|
|
|
|
export function readyToDetectDuplicatedTab() {
|
|
mReadyToDetectDuplicatedTab = true;
|
|
}
|
|
|
|
export async function request(tabOrId, options = {}) {
|
|
if (typeof options != 'object')
|
|
options = {};
|
|
|
|
let tab = tabOrId;
|
|
if (typeof tabOrId == 'number')
|
|
tab = TabsStore.tabs.get(tabOrId);
|
|
|
|
if (TabsStore.getCurrentWindowId()) {
|
|
return browser.runtime.sendMessage({
|
|
type: Constants.kCOMMAND_REQUEST_UNIQUE_ID,
|
|
tabId: tab.id
|
|
}).catch(ApiTabs.createErrorHandler());
|
|
}
|
|
|
|
let originalId = null;
|
|
let originalTabId = null;
|
|
let duplicated = false;
|
|
if (!options.forceNew) {
|
|
// https://github.com/piroor/treestyletab/issues/2845
|
|
// This delay may break initial restoration of tabs, so we should
|
|
// ignore it until all restoration processes are finished.
|
|
if (mReadyToDetectDuplicatedTab &&
|
|
configs.delayForDuplicatedTabDetection > 0)
|
|
await wait(configs.delayForDuplicatedTabDetection);
|
|
|
|
let oldId = await browser.sessions.getTabValue(tab.id, Constants.kPERSISTENT_ID).catch(ApiTabs.createErrorHandler());
|
|
if (oldId && !oldId.tabId) // ignore broken information!
|
|
oldId = null;
|
|
|
|
if (oldId) {
|
|
// If the tab detected from stored tabId is different, it is duplicated tab.
|
|
try {
|
|
const tabWithOldId = TabsStore.tabs.get(oldId.tabId);
|
|
if (!tabWithOldId)
|
|
throw new Error(`Invalid tab ID: ${oldId.tabId}`);
|
|
originalId = (tabWithOldId.$TST.uniqueId || await tabWithOldId.$TST.promisedUniqueId).id;
|
|
duplicated = tab && tabWithOldId.id != tab.id && originalId == oldId.id;
|
|
if (duplicated)
|
|
originalTabId = oldId.tabId;
|
|
else
|
|
throw new Error(`Invalid tab ID: ${oldId.tabId}`);
|
|
}
|
|
catch(e) {
|
|
ApiTabs.handleMissingTabError(e);
|
|
// It fails if the tab doesn't exist.
|
|
// There is no live tab for the tabId, thus
|
|
// this seems to be a tab restored from session.
|
|
// We need to update the related tab id.
|
|
browser.sessions.setTabValue(tab.id, Constants.kPERSISTENT_ID, {
|
|
id: oldId.id,
|
|
tabId: tab.id
|
|
}).catch(ApiTabs.createErrorSuppressor());
|
|
return {
|
|
id: oldId.id,
|
|
originalId: null,
|
|
originalTabId: oldId.tabId,
|
|
restored: true
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
const id = `tab-${generate()}`;
|
|
// tabId is for detecttion of duplicated tabs
|
|
await browser.sessions.setTabValue(tab.id, Constants.kPERSISTENT_ID, { id, tabId: tab.id }).catch(ApiTabs.createErrorSuppressor());
|
|
return { id, originalId, originalTabId, duplicated };
|
|
}
|
|
|
|
function generate() {
|
|
const adjective = kID_ADJECTIVES[Math.floor(Math.random() * kID_ADJECTIVES.length)];
|
|
const noun = kID_NOUNS[Math.floor(Math.random() * kID_NOUNS.length)];
|
|
const randomValue = Math.floor(Math.random() * 1000);
|
|
return `${adjective}-${noun}-${Date.now()}-${randomValue}`;
|
|
}
|
|
|
|
export async function getFromTabs(tabs) {
|
|
return Promise.all(tabs.map(tab =>
|
|
browser.sessions.getTabValue(tab.id, Constants.kPERSISTENT_ID).catch(ApiTabs.createErrorHandler())
|
|
));
|
|
}
|
|
|
|
export async function ensureWindowId(windowId) {
|
|
const storedUniqueId = await browser.sessions.getWindowValue(windowId, 'uniqueId').catch(_ => null);
|
|
if (storedUniqueId)
|
|
return storedUniqueId;
|
|
|
|
const uniqueId = `window-${generate()}`;
|
|
await browser.sessions.setWindowValue(windowId, 'uniqueId', uniqueId).catch(_ => null);
|
|
return uniqueId;
|
|
}
|