96 lines
3.1 KiB
JavaScript
96 lines
3.1 KiB
JavaScript
'use strict';
|
|
|
|
// eslint-disable-next-line no-unused-expressions
|
|
self.INJECTED !== 1 && (() => {
|
|
|
|
//#region for content scripts and our extension pages
|
|
|
|
if (!((window.browser || {}).runtime || {}).sendMessage) {
|
|
/* Auto-promisifier with a fallback to direct call on signature error.
|
|
The fallback isn't used now since we call all synchronous methods via `chrome` */
|
|
const directEvents = ['addListener', 'removeListener', 'hasListener', 'hasListeners'];
|
|
// generated by tools/chrome-api-no-cb.js
|
|
const directMethods = {
|
|
alarms: ['create'],
|
|
extension: ['getBackgroundPage', 'getExtensionTabs', 'getURL', 'getViews', 'setUpdateUrlData'],
|
|
i18n: ['getMessage', 'getUILanguage'],
|
|
identity: ['getRedirectURL'],
|
|
runtime: ['connect', 'connectNative', 'getManifest', 'getURL', 'reload', 'restart'],
|
|
tabs: ['connect'],
|
|
};
|
|
const promisify = function (fn, ...args) {
|
|
let res;
|
|
try {
|
|
let resolve, reject;
|
|
/* Some callbacks have 2 parameters so we're resolving as an array in that case.
|
|
For example, chrome.runtime.requestUpdateCheck and chrome.webRequest.onAuthRequired */
|
|
args.push((...results) =>
|
|
chrome.runtime.lastError ?
|
|
reject(new Error(chrome.runtime.lastError.message)) :
|
|
resolve(results.length <= 1 ? results[0] : results));
|
|
fn.apply(this, args);
|
|
res = new Promise((...rr) => ([resolve, reject] = rr));
|
|
} catch (err) {
|
|
if (!err.message.includes('No matching signature')) {
|
|
throw err;
|
|
}
|
|
args.pop();
|
|
res = fn.apply(this, args);
|
|
}
|
|
return res;
|
|
};
|
|
const proxify = (src, srcName, target, key) => {
|
|
let res = src[key];
|
|
if (res && typeof res === 'object') {
|
|
res = createProxy(res, key); // eslint-disable-line no-use-before-define
|
|
} else if (typeof res === 'function') {
|
|
res = (directMethods[srcName] || directEvents).includes(key)
|
|
? res.bind(src)
|
|
: promisify.bind(src, res);
|
|
}
|
|
target[key] = res;
|
|
return res;
|
|
};
|
|
const createProxy = (src, srcName) =>
|
|
new Proxy({}, {
|
|
get(target, key) {
|
|
return target[key] || proxify(src, srcName, target, key);
|
|
},
|
|
});
|
|
window.browser = createProxy(chrome);
|
|
}
|
|
|
|
//#endregion
|
|
|
|
if (!chrome.tabs) return;
|
|
|
|
//#region for our extension pages
|
|
|
|
for (const storage of ['localStorage', 'sessionStorage']) {
|
|
try {
|
|
window[storage]._access_check = 1;
|
|
delete window[storage]._access_check;
|
|
} catch (err) {
|
|
Object.defineProperty(window, storage, {value: {}});
|
|
}
|
|
}
|
|
|
|
if (!(new URLSearchParams({foo: 1})).get('foo')) {
|
|
// TODO: remove when minimum_chrome_version >= 61
|
|
window.URLSearchParams = class extends URLSearchParams {
|
|
constructor(init) {
|
|
if (init && typeof init === 'object') {
|
|
super();
|
|
for (const [key, val] of Object.entries(init)) {
|
|
this.set(key, val);
|
|
}
|
|
} else {
|
|
super(...arguments);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
//#endregion
|
|
})();
|