2020-02-23 15:43:26 +00:00
|
|
|
/* global navigatorUtil */
|
|
|
|
/* exported tabManager */
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const tabManager = (() => {
|
|
|
|
const listeners = [];
|
|
|
|
const cache = new Map();
|
|
|
|
chrome.tabs.onRemoved.addListener(tabId => cache.delete(tabId));
|
|
|
|
chrome.tabs.onReplaced.addListener((added, removed) => cache.delete(removed));
|
|
|
|
navigatorUtil.onUrlChange(({tabId, frameId, url}) => {
|
|
|
|
if (frameId) return;
|
|
|
|
const oldUrl = tabManager.get(tabId, 'url');
|
|
|
|
tabManager.set(tabId, 'url', url);
|
|
|
|
for (const fn of listeners) {
|
|
|
|
try {
|
|
|
|
fn({tabId, url, oldUrl});
|
|
|
|
} catch (err) {
|
|
|
|
console.error(err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return {
|
|
|
|
onUpdate(fn) {
|
|
|
|
listeners.push(fn);
|
|
|
|
},
|
2020-02-24 23:16:45 +00:00
|
|
|
get(tabId, ...keys) {
|
|
|
|
return keys.reduce((meta, key) => meta && meta[key], cache.get(tabId));
|
2020-02-23 15:43:26 +00:00
|
|
|
},
|
2020-02-24 23:16:45 +00:00
|
|
|
/**
|
|
|
|
* number of keys is arbitrary, last arg is value, `undefined` will delete the last key from meta
|
|
|
|
* (tabId, 'foo', 123) will set tabId's meta to {foo: 123},
|
|
|
|
* (tabId, 'foo', 'bar', 'etc', 123) will set tabId's meta to {foo: {bar: {etc: 123}}}
|
|
|
|
*/
|
|
|
|
set(tabId, ...args) {
|
2020-02-23 15:43:26 +00:00
|
|
|
let meta = cache.get(tabId);
|
|
|
|
if (!meta) {
|
|
|
|
meta = {};
|
|
|
|
cache.set(tabId, meta);
|
|
|
|
}
|
2020-02-24 23:16:45 +00:00
|
|
|
const value = args.pop();
|
|
|
|
const lastKey = args.pop();
|
|
|
|
for (const key of args) meta = meta[key] || (meta[key] = {});
|
|
|
|
if (value === undefined) {
|
|
|
|
delete meta[lastKey];
|
|
|
|
} else {
|
|
|
|
meta[lastKey] = value;
|
|
|
|
}
|
2020-02-23 15:43:26 +00:00
|
|
|
},
|
|
|
|
list() {
|
|
|
|
return cache.keys();
|
|
|
|
},
|
|
|
|
};
|
|
|
|
})();
|