+++ /dev/null
-(function (global, factory) {
- if (typeof define === "function" && define.amd) {
- define("webextension-polyfill", ["module"], factory);
- } else if (typeof exports !== "undefined") {
- factory(module);
- } else {
- var mod = {
- exports: {}
- };
- factory(mod);
- global.browser = mod.exports;
- }
-})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (module) {
- /* webextension-polyfill - v0.7.0 - Tue Nov 10 2020 20:24:04 */
-
- /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
-
- /* vim: set sts=2 sw=2 et tw=80: */
-
- /* 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";
-
- if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.prototype) {
- const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received.";
- const SEND_RESPONSE_DEPRECATION_WARNING = "Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)"; // Wrapping the bulk of this polyfill in a one-time-use function is a minor
- // optimization for Firefox. Since Spidermonkey does not fully parse the
- // contents of a function until the first time it's called, and since it will
- // never actually need to be called, this allows the polyfill to be included
- // in Firefox nearly for free.
-
- const wrapAPIs = extensionAPIs => {
- // NOTE: apiMetadata is associated to the content of the api-metadata.json file
- // at build time by replacing the following "include" with the content of the
- // JSON file.
- const apiMetadata = {
- "alarms": {
- "clear": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "clearAll": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "get": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getAll": {
- "minArgs": 0,
- "maxArgs": 0
- }
- },
- "bookmarks": {
- "create": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "get": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getChildren": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getRecent": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getSubTree": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getTree": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "move": {
- "minArgs": 2,
- "maxArgs": 2
- },
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeTree": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "search": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "update": {
- "minArgs": 2,
- "maxArgs": 2
- }
- },
- "browserAction": {
- "disable": {
- "minArgs": 0,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "enable": {
- "minArgs": 0,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "getBadgeBackgroundColor": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getBadgeText": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getPopup": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getTitle": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "openPopup": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "setBadgeBackgroundColor": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "setBadgeText": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "setIcon": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "setPopup": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "setTitle": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- }
- },
- "browsingData": {
- "remove": {
- "minArgs": 2,
- "maxArgs": 2
- },
- "removeCache": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeCookies": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeDownloads": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeFormData": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeHistory": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeLocalStorage": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removePasswords": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removePluginData": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "settings": {
- "minArgs": 0,
- "maxArgs": 0
- }
- },
- "commands": {
- "getAll": {
- "minArgs": 0,
- "maxArgs": 0
- }
- },
- "contextMenus": {
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeAll": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "update": {
- "minArgs": 2,
- "maxArgs": 2
- }
- },
- "cookies": {
- "get": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getAll": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getAllCookieStores": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "set": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "devtools": {
- "inspectedWindow": {
- "eval": {
- "minArgs": 1,
- "maxArgs": 2,
- "singleCallbackArg": false
- }
- },
- "panels": {
- "create": {
- "minArgs": 3,
- "maxArgs": 3,
- "singleCallbackArg": true
- },
- "elements": {
- "createSidebarPane": {
- "minArgs": 1,
- "maxArgs": 1
- }
- }
- }
- },
- "downloads": {
- "cancel": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "download": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "erase": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getFileIcon": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "open": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "pause": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeFile": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "resume": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "search": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "show": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- }
- },
- "extension": {
- "isAllowedFileSchemeAccess": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "isAllowedIncognitoAccess": {
- "minArgs": 0,
- "maxArgs": 0
- }
- },
- "history": {
- "addUrl": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "deleteAll": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "deleteRange": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "deleteUrl": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getVisits": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "search": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "i18n": {
- "detectLanguage": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getAcceptLanguages": {
- "minArgs": 0,
- "maxArgs": 0
- }
- },
- "identity": {
- "launchWebAuthFlow": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "idle": {
- "queryState": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "management": {
- "get": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getAll": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "getSelf": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "setEnabled": {
- "minArgs": 2,
- "maxArgs": 2
- },
- "uninstallSelf": {
- "minArgs": 0,
- "maxArgs": 1
- }
- },
- "notifications": {
- "clear": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "create": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "getAll": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "getPermissionLevel": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "update": {
- "minArgs": 2,
- "maxArgs": 2
- }
- },
- "pageAction": {
- "getPopup": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getTitle": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "hide": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "setIcon": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "setPopup": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "setTitle": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- },
- "show": {
- "minArgs": 1,
- "maxArgs": 1,
- "fallbackToNoCallback": true
- }
- },
- "permissions": {
- "contains": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getAll": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "request": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "runtime": {
- "getBackgroundPage": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "getPlatformInfo": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "openOptionsPage": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "requestUpdateCheck": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "sendMessage": {
- "minArgs": 1,
- "maxArgs": 3
- },
- "sendNativeMessage": {
- "minArgs": 2,
- "maxArgs": 2
- },
- "setUninstallURL": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "sessions": {
- "getDevices": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getRecentlyClosed": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "restore": {
- "minArgs": 0,
- "maxArgs": 1
- }
- },
- "storage": {
- "local": {
- "clear": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "get": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getBytesInUse": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "set": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "managed": {
- "get": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getBytesInUse": {
- "minArgs": 0,
- "maxArgs": 1
- }
- },
- "sync": {
- "clear": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "get": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getBytesInUse": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "set": {
- "minArgs": 1,
- "maxArgs": 1
- }
- }
- },
- "tabs": {
- "captureVisibleTab": {
- "minArgs": 0,
- "maxArgs": 2
- },
- "create": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "detectLanguage": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "discard": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "duplicate": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "executeScript": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "get": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getCurrent": {
- "minArgs": 0,
- "maxArgs": 0
- },
- "getZoom": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getZoomSettings": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "goBack": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "goForward": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "highlight": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "insertCSS": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "move": {
- "minArgs": 2,
- "maxArgs": 2
- },
- "query": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "reload": {
- "minArgs": 0,
- "maxArgs": 2
- },
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "removeCSS": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "sendMessage": {
- "minArgs": 2,
- "maxArgs": 3
- },
- "setZoom": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "setZoomSettings": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "update": {
- "minArgs": 1,
- "maxArgs": 2
- }
- },
- "topSites": {
- "get": {
- "minArgs": 0,
- "maxArgs": 0
- }
- },
- "webNavigation": {
- "getAllFrames": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "getFrame": {
- "minArgs": 1,
- "maxArgs": 1
- }
- },
- "webRequest": {
- "handlerBehaviorChanged": {
- "minArgs": 0,
- "maxArgs": 0
- }
- },
- "windows": {
- "create": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "get": {
- "minArgs": 1,
- "maxArgs": 2
- },
- "getAll": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getCurrent": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "getLastFocused": {
- "minArgs": 0,
- "maxArgs": 1
- },
- "remove": {
- "minArgs": 1,
- "maxArgs": 1
- },
- "update": {
- "minArgs": 2,
- "maxArgs": 2
- }
- }
- };
-
- if (Object.keys(apiMetadata).length === 0) {
- throw new Error("api-metadata.json has not been included in browser-polyfill");
- }
- /**
- * A WeakMap subclass which creates and stores a value for any key which does
- * not exist when accessed, but behaves exactly as an ordinary WeakMap
- * otherwise.
- *
- * @param {function} createItem
- * A function which will be called in order to create the value for any
- * key which does not exist, the first time it is accessed. The
- * function receives, as its only argument, the key being created.
- */
-
-
- class DefaultWeakMap extends WeakMap {
- constructor(createItem, items = undefined) {
- super(items);
- this.createItem = createItem;
- }
-
- get(key) {
- if (!this.has(key)) {
- this.set(key, this.createItem(key));
- }
-
- return super.get(key);
- }
-
- }
- /**
- * Returns true if the given object is an object with a `then` method, and can
- * therefore be assumed to behave as a Promise.
- *
- * @param {*} value The value to test.
- * @returns {boolean} True if the value is thenable.
- */
-
-
- const isThenable = value => {
- return value && typeof value === "object" && typeof value.then === "function";
- };
- /**
- * Creates and returns a function which, when called, will resolve or reject
- * the given promise based on how it is called:
- *
- * - If, when called, `chrome.runtime.lastError` contains a non-null object,
- * the promise is rejected with that value.
- * - If the function is called with exactly one argument, the promise is
- * resolved to that value.
- * - Otherwise, the promise is resolved to an array containing all of the
- * function's arguments.
- *
- * @param {object} promise
- * An object containing the resolution and rejection functions of a
- * promise.
- * @param {function} promise.resolve
- * The promise's resolution function.
- * @param {function} promise.rejection
- * The promise's rejection function.
- * @param {object} metadata
- * Metadata about the wrapped method which has created the callback.
- * @param {integer} metadata.maxResolvedArgs
- * The maximum number of arguments which may be passed to the
- * callback created by the wrapped async function.
- *
- * @returns {function}
- * The generated callback function.
- */
-
-
- const makeCallback = (promise, metadata) => {
- return (...callbackArgs) => {
- if (extensionAPIs.runtime.lastError) {
- promise.reject(extensionAPIs.runtime.lastError);
- } else if (metadata.singleCallbackArg || callbackArgs.length <= 1 && metadata.singleCallbackArg !== false) {
- promise.resolve(callbackArgs[0]);
- } else {
- promise.resolve(callbackArgs);
- }
- };
- };
-
- const pluralizeArguments = numArgs => numArgs == 1 ? "argument" : "arguments";
- /**
- * Creates a wrapper function for a method with the given name and metadata.
- *
- * @param {string} name
- * The name of the method which is being wrapped.
- * @param {object} metadata
- * Metadata about the method being wrapped.
- * @param {integer} metadata.minArgs
- * The minimum number of arguments which must be passed to the
- * function. If called with fewer than this number of arguments, the
- * wrapper will raise an exception.
- * @param {integer} metadata.maxArgs
- * The maximum number of arguments which may be passed to the
- * function. If called with more than this number of arguments, the
- * wrapper will raise an exception.
- * @param {integer} metadata.maxResolvedArgs
- * The maximum number of arguments which may be passed to the
- * callback created by the wrapped async function.
- *
- * @returns {function(object, ...*)}
- * The generated wrapper function.
- */
-
-
- const wrapAsyncFunction = (name, metadata) => {
- return function asyncFunctionWrapper(target, ...args) {
- if (args.length < metadata.minArgs) {
- throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
- }
-
- if (args.length > metadata.maxArgs) {
- throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
- }
-
- return new Promise((resolve, reject) => {
- if (metadata.fallbackToNoCallback) {
- // This API method has currently no callback on Chrome, but it return a promise on Firefox,
- // and so the polyfill will try to call it with a callback first, and it will fallback
- // to not passing the callback if the first call fails.
- try {
- target[name](...args, makeCallback({
- resolve,
- reject
- }, metadata));
- } catch (cbError) {
- console.warn(`${name} API method doesn't seem to support the callback parameter, ` + "falling back to call it without a callback: ", cbError);
- target[name](...args); // Update the API method metadata, so that the next API calls will not try to
- // use the unsupported callback anymore.
-
- metadata.fallbackToNoCallback = false;
- metadata.noCallback = true;
- resolve();
- }
- } else if (metadata.noCallback) {
- target[name](...args);
- resolve();
- } else {
- target[name](...args, makeCallback({
- resolve,
- reject
- }, metadata));
- }
- });
- };
- };
- /**
- * Wraps an existing method of the target object, so that calls to it are
- * intercepted by the given wrapper function. The wrapper function receives,
- * as its first argument, the original `target` object, followed by each of
- * the arguments passed to the original method.
- *
- * @param {object} target
- * The original target object that the wrapped method belongs to.
- * @param {function} method
- * The method being wrapped. This is used as the target of the Proxy
- * object which is created to wrap the method.
- * @param {function} wrapper
- * The wrapper function which is called in place of a direct invocation
- * of the wrapped method.
- *
- * @returns {Proxy<function>}
- * A Proxy object for the given method, which invokes the given wrapper
- * method in its place.
- */
-
-
- const wrapMethod = (target, method, wrapper) => {
- return new Proxy(method, {
- apply(targetMethod, thisObj, args) {
- return wrapper.call(thisObj, target, ...args);
- }
-
- });
- };
-
- let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);
- /**
- * Wraps an object in a Proxy which intercepts and wraps certain methods
- * based on the given `wrappers` and `metadata` objects.
- *
- * @param {object} target
- * The target object to wrap.
- *
- * @param {object} [wrappers = {}]
- * An object tree containing wrapper functions for special cases. Any
- * function present in this object tree is called in place of the
- * method in the same location in the `target` object tree. These
- * wrapper methods are invoked as described in {@see wrapMethod}.
- *
- * @param {object} [metadata = {}]
- * An object tree containing metadata used to automatically generate
- * Promise-based wrapper functions for asynchronous. Any function in
- * the `target` object tree which has a corresponding metadata object
- * in the same location in the `metadata` tree is replaced with an
- * automatically-generated wrapper function, as described in
- * {@see wrapAsyncFunction}
- *
- * @returns {Proxy<object>}
- */
-
- const wrapObject = (target, wrappers = {}, metadata = {}) => {
- let cache = Object.create(null);
- let handlers = {
- has(proxyTarget, prop) {
- return prop in target || prop in cache;
- },
-
- get(proxyTarget, prop, receiver) {
- if (prop in cache) {
- return cache[prop];
- }
-
- if (!(prop in target)) {
- return undefined;
- }
-
- let value = target[prop];
-
- if (typeof value === "function") {
- // This is a method on the underlying object. Check if we need to do
- // any wrapping.
- if (typeof wrappers[prop] === "function") {
- // We have a special-case wrapper for this method.
- value = wrapMethod(target, target[prop], wrappers[prop]);
- } else if (hasOwnProperty(metadata, prop)) {
- // This is an async method that we have metadata for. Create a
- // Promise wrapper for it.
- let wrapper = wrapAsyncFunction(prop, metadata[prop]);
- value = wrapMethod(target, target[prop], wrapper);
- } else {
- // This is a method that we don't know or care about. Return the
- // original method, bound to the underlying object.
- value = value.bind(target);
- }
- } else if (typeof value === "object" && value !== null && (hasOwnProperty(wrappers, prop) || hasOwnProperty(metadata, prop))) {
- // This is an object that we need to do some wrapping for the children
- // of. Create a sub-object wrapper for it with the appropriate child
- // metadata.
- value = wrapObject(value, wrappers[prop], metadata[prop]);
- } else if (hasOwnProperty(metadata, "*")) {
- // Wrap all properties in * namespace.
- value = wrapObject(value, wrappers[prop], metadata["*"]);
- } else {
- // We don't need to do any wrapping for this property,
- // so just forward all access to the underlying object.
- Object.defineProperty(cache, prop, {
- configurable: true,
- enumerable: true,
-
- get() {
- return target[prop];
- },
-
- set(value) {
- target[prop] = value;
- }
-
- });
- return value;
- }
-
- cache[prop] = value;
- return value;
- },
-
- set(proxyTarget, prop, value, receiver) {
- if (prop in cache) {
- cache[prop] = value;
- } else {
- target[prop] = value;
- }
-
- return true;
- },
-
- defineProperty(proxyTarget, prop, desc) {
- return Reflect.defineProperty(cache, prop, desc);
- },
-
- deleteProperty(proxyTarget, prop) {
- return Reflect.deleteProperty(cache, prop);
- }
-
- }; // Per contract of the Proxy API, the "get" proxy handler must return the
- // original value of the target if that value is declared read-only and
- // non-configurable. For this reason, we create an object with the
- // prototype set to `target` instead of using `target` directly.
- // Otherwise we cannot return a custom object for APIs that
- // are declared read-only and non-configurable, such as `chrome.devtools`.
- //
- // The proxy handlers themselves will still use the original `target`
- // instead of the `proxyTarget`, so that the methods and properties are
- // dereferenced via the original targets.
-
- let proxyTarget = Object.create(target);
- return new Proxy(proxyTarget, handlers);
- };
- /**
- * Creates a set of wrapper functions for an event object, which handles
- * wrapping of listener functions that those messages are passed.
- *
- * A single wrapper is created for each listener function, and stored in a
- * map. Subsequent calls to `addListener`, `hasListener`, or `removeListener`
- * retrieve the original wrapper, so that attempts to remove a
- * previously-added listener work as expected.
- *
- * @param {DefaultWeakMap<function, function>} wrapperMap
- * A DefaultWeakMap object which will create the appropriate wrapper
- * for a given listener function when one does not exist, and retrieve
- * an existing one when it does.
- *
- * @returns {object}
- */
-
-
- const wrapEvent = wrapperMap => ({
- addListener(target, listener, ...args) {
- target.addListener(wrapperMap.get(listener), ...args);
- },
-
- hasListener(target, listener) {
- return target.hasListener(wrapperMap.get(listener));
- },
-
- removeListener(target, listener) {
- target.removeListener(wrapperMap.get(listener));
- }
-
- }); // Keep track if the deprecation warning has been logged at least once.
-
-
- let loggedSendResponseDeprecationWarning = false;
- const onMessageWrappers = new DefaultWeakMap(listener => {
- if (typeof listener !== "function") {
- return listener;
- }
- /**
- * Wraps a message listener function so that it may send responses based on
- * its return value, rather than by returning a sentinel value and calling a
- * callback. If the listener function returns a Promise, the response is
- * sent when the promise either resolves or rejects.
- *
- * @param {*} message
- * The message sent by the other end of the channel.
- * @param {object} sender
- * Details about the sender of the message.
- * @param {function(*)} sendResponse
- * A callback which, when called with an arbitrary argument, sends
- * that value as a response.
- * @returns {boolean}
- * True if the wrapped listener returned a Promise, which will later
- * yield a response. False otherwise.
- */
-
-
- return function onMessage(message, sender, sendResponse) {
- let didCallSendResponse = false;
- let wrappedSendResponse;
- let sendResponsePromise = new Promise(resolve => {
- wrappedSendResponse = function (response) {
- if (!loggedSendResponseDeprecationWarning) {
- console.warn(SEND_RESPONSE_DEPRECATION_WARNING, new Error().stack);
- loggedSendResponseDeprecationWarning = true;
- }
-
- didCallSendResponse = true;
- resolve(response);
- };
- });
- let result;
-
- try {
- result = listener(message, sender, wrappedSendResponse);
- } catch (err) {
- result = Promise.reject(err);
- }
-
- const isResultThenable = result !== true && isThenable(result); // If the listener didn't returned true or a Promise, or called
- // wrappedSendResponse synchronously, we can exit earlier
- // because there will be no response sent from this listener.
-
- if (result !== true && !isResultThenable && !didCallSendResponse) {
- return false;
- } // A small helper to send the message if the promise resolves
- // and an error if the promise rejects (a wrapped sendMessage has
- // to translate the message into a resolved promise or a rejected
- // promise).
-
-
- const sendPromisedResult = promise => {
- promise.then(msg => {
- // send the message value.
- sendResponse(msg);
- }, error => {
- // Send a JSON representation of the error if the rejected value
- // is an instance of error, or the object itself otherwise.
- let message;
-
- if (error && (error instanceof Error || typeof error.message === "string")) {
- message = error.message;
- } else {
- message = "An unexpected error occurred";
- }
-
- sendResponse({
- __mozWebExtensionPolyfillReject__: true,
- message
- });
- }).catch(err => {
- // Print an error on the console if unable to send the response.
- console.error("Failed to send onMessage rejected reply", err);
- });
- }; // If the listener returned a Promise, send the resolved value as a
- // result, otherwise wait the promise related to the wrappedSendResponse
- // callback to resolve and send it as a response.
-
-
- if (isResultThenable) {
- sendPromisedResult(result);
- } else {
- sendPromisedResult(sendResponsePromise);
- } // Let Chrome know that the listener is replying.
-
-
- return true;
- };
- });
-
- const wrappedSendMessageCallback = ({
- reject,
- resolve
- }, reply) => {
- if (extensionAPIs.runtime.lastError) {
- // Detect when none of the listeners replied to the sendMessage call and resolve
- // the promise to undefined as in Firefox.
- // See https://github.com/mozilla/webextension-polyfill/issues/130
- if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {
- resolve();
- } else {
- reject(extensionAPIs.runtime.lastError);
- }
- } else if (reply && reply.__mozWebExtensionPolyfillReject__) {
- // Convert back the JSON representation of the error into
- // an Error instance.
- reject(new Error(reply.message));
- } else {
- resolve(reply);
- }
- };
-
- const wrappedSendMessage = (name, metadata, apiNamespaceObj, ...args) => {
- if (args.length < metadata.minArgs) {
- throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
- }
-
- if (args.length > metadata.maxArgs) {
- throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
- }
-
- return new Promise((resolve, reject) => {
- const wrappedCb = wrappedSendMessageCallback.bind(null, {
- resolve,
- reject
- });
- args.push(wrappedCb);
- apiNamespaceObj.sendMessage(...args);
- });
- };
-
- const staticWrappers = {
- runtime: {
- onMessage: wrapEvent(onMessageWrappers),
- onMessageExternal: wrapEvent(onMessageWrappers),
- sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
- minArgs: 1,
- maxArgs: 3
- })
- },
- tabs: {
- sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
- minArgs: 2,
- maxArgs: 3
- })
- }
- };
- const settingMetadata = {
- clear: {
- minArgs: 1,
- maxArgs: 1
- },
- get: {
- minArgs: 1,
- maxArgs: 1
- },
- set: {
- minArgs: 1,
- maxArgs: 1
- }
- };
- apiMetadata.privacy = {
- network: {
- "*": settingMetadata
- },
- services: {
- "*": settingMetadata
- },
- websites: {
- "*": settingMetadata
- }
- };
- return wrapObject(extensionAPIs, staticWrappers, apiMetadata);
- };
-
- if (typeof chrome != "object" || !chrome || !chrome.runtime || !chrome.runtime.id) {
- throw new Error("This script should only be loaded in a browser extension.");
- } // The build process adds a UMD wrapper around this file, which makes the
- // `module` variable available.
-
-
- module.exports = wrapAPIs(chrome);
- } else {
- module.exports = browser;
- }
-});
-//# sourceMappingURL=browser-polyfill.js.map