162 lines
5.5 KiB
JavaScript
162 lines
5.5 KiB
JavaScript
const identityState = {
|
|
storageArea: {
|
|
area: browser.storage.local,
|
|
|
|
getContainerStoreKey(cookieStoreId) {
|
|
const storagePrefix = "identitiesState@@_";
|
|
return `${storagePrefix}${cookieStoreId}`;
|
|
},
|
|
|
|
async get(cookieStoreId) {
|
|
const storeKey = this.getContainerStoreKey(cookieStoreId);
|
|
const storageResponse = await this.area.get([storeKey]);
|
|
if (storageResponse && storeKey in storageResponse) {
|
|
if (!storageResponse[storeKey].macAddonUUID){
|
|
storageResponse[storeKey].macAddonUUID = uuidv4();
|
|
await this.set(cookieStoreId, storageResponse[cookieStoreId]);
|
|
}
|
|
return storageResponse[storeKey];
|
|
}
|
|
// If local storage doesn't have an entry, look it up to make sure it's
|
|
// an in-use identity.
|
|
const identities = await browser.contextualIdentities.query({});
|
|
const match = identities.find(
|
|
(identity) => identity.cookieStoreId === cookieStoreId);
|
|
if (match) {
|
|
const defaultContainerState = identityState._createIdentityState();
|
|
await this.set(cookieStoreId, defaultContainerState);
|
|
return defaultContainerState;
|
|
}
|
|
throw new Error (`${cookieStoreId} not found`);
|
|
},
|
|
|
|
set(cookieStoreId, data) {
|
|
const storeKey = this.getContainerStoreKey(cookieStoreId);
|
|
return this.area.set({
|
|
[storeKey]: data
|
|
});
|
|
},
|
|
|
|
async remove(cookieStoreId) {
|
|
const storeKey = this.getContainerStoreKey(cookieStoreId);
|
|
return this.area.remove([storeKey]);
|
|
},
|
|
|
|
/*
|
|
* Looks for abandoned identity keys in local storage, and makes sure all
|
|
* identities registered in the browser are also in local storage. (this
|
|
* appears to not always be the case based on how this.get() is written)
|
|
*/
|
|
async upgradeData() {
|
|
const identitiesList = await browser.contextualIdentities.query({});
|
|
const macConfigs = await this.area.get();
|
|
for(const configKey of Object.keys(macConfigs)) {
|
|
if (configKey.includes("identitiesState@@_")) {
|
|
const cookieStoreId = String(configKey).replace(/^identitiesState@@_/, "");
|
|
const match = identitiesList.find(
|
|
localIdentity => localIdentity.cookieStoreId === cookieStoreId
|
|
);
|
|
if (cookieStoreId === "firefox-default") continue;
|
|
if (!match) {
|
|
await this.remove(cookieStoreId);
|
|
continue;
|
|
}
|
|
if (!macConfigs[configKey].macAddonUUID) {
|
|
await identityState.storageArea.get(cookieStoreId);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const identity of identitiesList) {
|
|
// ensure all identities have an entry in local storage
|
|
await identityState.addUUID(identity.cookieStoreId);
|
|
}
|
|
}
|
|
},
|
|
|
|
_createTabObject(tab) {
|
|
return Object.assign({}, tab);
|
|
},
|
|
|
|
async getCookieStoreIDuuidMap() {
|
|
const containers = {};
|
|
const identities = await browser.contextualIdentities.query({});
|
|
for(const identity of identities) {
|
|
const containerInfo = await this.storageArea.get(identity.cookieStoreId);
|
|
containers[identity.cookieStoreId] = containerInfo.macAddonUUID;
|
|
}
|
|
return containers;
|
|
},
|
|
|
|
async storeHidden(cookieStoreId, windowId) {
|
|
const containerState = await this.storageArea.get(cookieStoreId);
|
|
const tabsByContainer = await browser.tabs.query({cookieStoreId, windowId});
|
|
tabsByContainer.forEach((tab) => {
|
|
const tabObject = this._createTabObject(tab);
|
|
if (!backgroundLogic.isPermissibleURL(tab.url)) {
|
|
return;
|
|
}
|
|
// This tab is going to be closed. Let's mark this tabObject as
|
|
// non-active.
|
|
tabObject.active = false;
|
|
tabObject.hiddenState = true;
|
|
containerState.hiddenTabs.push(tabObject);
|
|
});
|
|
|
|
return this.storageArea.set(cookieStoreId, containerState);
|
|
},
|
|
|
|
async updateUUID(cookieStoreId, uuid) {
|
|
if (!cookieStoreId || !uuid) {
|
|
throw new Error ("cookieStoreId or uuid missing");
|
|
}
|
|
const containerState = await this.storageArea.get(cookieStoreId);
|
|
containerState.macAddonUUID = uuid;
|
|
await this.storageArea.set(cookieStoreId, containerState);
|
|
return uuid;
|
|
},
|
|
|
|
async addUUID(cookieStoreId) {
|
|
await this.storageArea.get(cookieStoreId);
|
|
},
|
|
|
|
async lookupMACaddonUUID(cookieStoreId) {
|
|
// This stays a lookup, because if the cookieStoreId doesn't
|
|
// exist, this.get() will create it, which is not what we want.
|
|
const cookieStoreIdKey = cookieStoreId.includes("firefox-container-") ?
|
|
cookieStoreId : "firefox-container-" + cookieStoreId;
|
|
const macConfigs = await this.storageArea.area.get();
|
|
for(const configKey of Object.keys(macConfigs)) {
|
|
if (configKey === this.getContainerStoreKey(cookieStoreIdKey)) {
|
|
return macConfigs[configKey].macAddonUUID;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
async lookupCookieStoreId(macAddonUUID) {
|
|
const macConfigs = await this.storageArea.area.get();
|
|
for(const configKey of Object.keys(macConfigs)) {
|
|
if (configKey.includes("identitiesState@@_")) {
|
|
if(macConfigs[configKey].macAddonUUID === macAddonUUID) {
|
|
return String(configKey).replace(/^identitiesState@@_/, "");
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
_createIdentityState() {
|
|
return {
|
|
hiddenTabs: [],
|
|
macAddonUUID: uuidv4()
|
|
};
|
|
},
|
|
};
|
|
|
|
function uuidv4() {
|
|
// https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
|
|
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
|
);
|
|
}
|