Files
tubestation/waterfox/browser/components/sidebar/common/unique-id.js
2025-11-06 14:13:52 +00:00

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;
}