From 773d01a982f534a3641c2d2a353a87e759e3a38d Mon Sep 17 00:00:00 2001 From: Gerard Chanekon Date: Sun, 29 Jan 2023 15:20:28 +1100 Subject: [PATCH] Auto-renew tokens before they expire Also try to negotiate a 24-hour long token upon login to avoid having to re-authenticate too often (for example after computer has been turned off overnight) Upgrade to latest version of polyfill Improve username/password field search algorithm Fix Firefox compatibility as the badge count was not visible --- background.js | 156 ++++++++++++++++++++++++++++++------ browser-polyfill.min.js | 4 +- browser-polyfill.min.js.map | 2 +- common.js | 6 +- content.js | 29 ++++++- manifest.json | 56 ++++++------- manifestV2.json | 77 +++++++++--------- manifestV3.json | 2 +- options.js | 55 ++++++++++--- package-lock.json | 6 +- package.json | 2 +- popup.js | 37 ++++----- 12 files changed, 300 insertions(+), 132 deletions(-) diff --git a/background.js b/background.js index 2ec1da0..0837109 100644 --- a/background.js +++ b/background.js @@ -1,27 +1,37 @@ /* eslint-disable no-console */ /* global chrome */ -function storageGetterProvider(storageType) { - return function (key, defaultValue) { - return new Promise(function (resolve, reject) { - try { - chrome.storage[storageType].get([key], function (result) { - const value = result[key] || defaultValue || null; - resolve(value); - }); - } catch (error) { - reject(error); - } - }); - }; +const idealTokenTTL = '24h'; + +var tokenRenewalIntervalId; + +if (!chrome.browserAction) { + chrome.browserAction = chrome.action; } const storage = { + storageGetterProvider: (storageType) => { + return function (key, defaultValue) { + return new Promise(function (resolve, reject) { + try { + chrome.storage[storageType].get([key], function (result) { + const value = result[key] || defaultValue || null; + resolve(value); + }); + } catch (error) { + reject(error); + } + }); + }; + }, + local: { - get: storageGetterProvider('local'), + get: (key, defaultValue) => + storage.storageGetterProvider('local')(key, defaultValue), }, sync: { - get: storageGetterProvider('sync'), + get: (key, defaultValue) => + storage.storageGetterProvider('sync')(key, defaultValue), }, }; @@ -32,20 +42,24 @@ class Vault { this.base = `${this.address}/v1`; } - async request(method, endpoint) { + async request(method, endpoint, content = null) { const res = await fetch(this.base + endpoint, { method: method.toUpperCase(), headers: { 'X-Vault-Token': this.token, 'Content-Type': 'application/json', }, + body: content != null ? JSON.stringify(content) : null, }); - if (!res.ok) throw new Error(`Error calling: ${method.toUpperCase()} ${this.base}${endpoint} -> HTTP ${res.status} - ${res.statusText}`); - - const json = await res.json(); + if (!res.ok) + throw new Error( + `Error calling: ${method.toUpperCase()} ${ + this.base + }${endpoint} -> HTTP ${res.status} - ${res.statusText}` + ); - return json; + return await res.json(); } list(endpoint) { @@ -55,6 +69,10 @@ class Vault { get(endpoint) { return this.request('GET', endpoint); } + + post(endpoint, content) { + return this.request('POST', endpoint, content); + } } function storePathComponents(storePath) { @@ -64,11 +82,12 @@ function storePathComponents(storePath) { } const pathComponents = path.split('/'); const storeRoot = pathComponents[0]; - const storeSubPath = pathComponents.length > 0 ? pathComponents.slice(1).join('/') : ''; + const storeSubPath = + pathComponents.length > 0 ? pathComponents.slice(1).join('/') : ''; return { root: storeRoot, - subPath: storeSubPath + subPath: storeSubPath, }; } @@ -85,7 +104,7 @@ async function autoFillSecrets(message, sender) { const storePath = await storage.sync.get('storePath'); const storeComponents = storePathComponents(storePath); - if (!vaultAddress || !vaultAddress) return; + if (!vaultToken || !vaultAddress) return; const url = new URL(sender.tab.url); const hostname = clearHostname(url.hostname); @@ -95,7 +114,9 @@ async function autoFillSecrets(message, sender) { let loginCount = 0; for (const secret of secretList) { - const secretKeys = await vault.list(`/${storeComponents.root}/metadata/${storeComponents.subPath}/${secret}`); + const secretKeys = await vault.list( + `/${storeComponents.root}/metadata/${storeComponents.subPath}/${secret}` + ); for (const key of secretKeys.data.keys) { const pattern = new RegExp(key); const patternMatches = pattern.test(hostname); @@ -117,12 +138,97 @@ async function autoFillSecrets(message, sender) { } } if (loginCount > 0) { - chrome.action.setBadgeText({ text: '*', tabId: sender.tab.id }); + chrome.browserAction.setBadgeText({ text: '*', tabId: sender.tab.id }); + } +} + +async function renewToken(force = false) { + const vaultToken = await storage.local.get('vaultToken'); + const vaultAddress = await storage.sync.get('vaultAddress'); + + if (vaultToken) { + try { + const vault = new Vault(vaultToken, vaultAddress); + const token = await vault.get('/auth/token/lookup-self'); + + console.log( + `${new Date().toLocaleString()} Token will expire in ${ + token.data.ttl + } seconds` + ); + if (token.data.ttl > 3600) { + refreshTokenListener(1800000); + } else { + refreshTokenListener((token.data.ttl / 2) * 1000); + } + + if (force || token.data.ttl <= 60) { + console.log(`${new Date().toLocaleString()} Renewing Token...`); + const newToken = await vault.post('/auth/token/renew-self', { + increment: idealTokenTTL, + }); + console.log( + `${new Date().toLocaleString()} Token renewed. It will expire in ${ + newToken.auth.lease_duration + } seconds` + ); + } + + await chrome.browserAction.setBadgeBackgroundColor({ color: '#1c98ed' }); + } catch (e) { + console.log(e); + await chrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' }); + await chrome.browserAction.setBadgeText({ text: '!' }); + + refreshTokenListener(); + } + } +} + +function refreshTokenListener(interval = 30000) { + if (tokenRenewalIntervalId) { + clearInterval(tokenRenewalIntervalId); + } + + tokenRenewalIntervalId = setInterval(async () => { + await renewToken(); + }, interval); +} + +async function newStateHandler(newState) { + console.log(`${new Date().toLocaleString()} ${newState}`); + if (newState === 'active') { + await renewToken(false); + } + + if (newState === 'locked') { + await renewToken(true); + } +} + +function setupIdleListener() { + if (!chrome.idle.onStateChanged.hasListener(newStateHandler)) { + chrome.idle.onStateChanged.addListener(newStateHandler); } } chrome.runtime.onMessage.addListener(function (message, sender) { if (message.type === 'auto_fill_secrets') { autoFillSecrets(message, sender).catch(console.error); + setupIdleListener(); + } + + if (message.type === 'auto_renew_token') { + refreshTokenListener(); } }); + +chrome.runtime.onInstalled.addListener(() => { + refreshTokenListener(); + setupIdleListener(); +}); + +chrome.runtime.onStartup.addListener(() => { + refreshTokenListener(); + setupIdleListener(); +}); diff --git a/browser-polyfill.min.js b/browser-polyfill.min.js index ae6ca65..37f6ee9 100644 --- a/browser-polyfill.min.js +++ b/browser-polyfill.min.js @@ -1,7 +1,7 @@ -(function(a,b){if("function"==typeof define&&define.amd)define("webextension-polyfill",["module"],b);else if("undefined"!=typeof exports)b(module);else{var c={exports:{}};b(c),a.browser=c.exports}})("undefined"==typeof globalThis?"undefined"==typeof self?this:self:globalThis,function(a){"use strict";if("undefined"==typeof browser||Object.getPrototypeOf(browser)!==Object.prototype){if("object"!=typeof chrome||!chrome||!chrome.runtime||!chrome.runtime.id)throw new Error("This script should only be loaded in a browser extension.");a.exports=(a=>{const b={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:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},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:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},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:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0},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:!0},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:!0}},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:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},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(0===Object.keys(b).length)throw new Error("api-metadata.json has not been included in browser-polyfill");class c extends WeakMap{constructor(a,b=void 0){super(b),this.createItem=a}get(a){return this.has(a)||this.set(a,this.createItem(a)),super.get(a)}}const d=a=>a&&"object"==typeof a&&"function"==typeof a.then,e=(b,c)=>(...d)=>{a.runtime.lastError?b.reject(new Error(a.runtime.lastError.message)):c.singleCallbackArg||1>=d.length&&!1!==c.singleCallbackArg?b.resolve(d[0]):b.resolve(d)},f=a=>1==a?"argument":"arguments",g=(a,b)=>function(c,...d){if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((f,g)=>{if(b.fallbackToNoCallback)try{c[a](...d,e({resolve:f,reject:g},b))}catch(e){console.warn(`${a} API method doesn't seem to support the callback parameter, `+"falling back to call it without a callback: ",e),c[a](...d),b.fallbackToNoCallback=!1,b.noCallback=!0,f()}else b.noCallback?(c[a](...d),f()):c[a](...d,e({resolve:f,reject:g},b))})},h=(a,b,c)=>new Proxy(b,{apply(b,d,e){return c.call(d,a,...e)}});let i=Function.call.bind(Object.prototype.hasOwnProperty);const j=(a,b={},c={})=>{let d=Object.create(null),e=Object.create(a);return new Proxy(e,{has(b,c){return c in a||c in d},get(e,f){if(f in d)return d[f];if(!(f in a))return;let k=a[f];if("function"==typeof k){if("function"==typeof b[f])k=h(a,a[f],b[f]);else if(i(c,f)){let b=g(f,c[f]);k=h(a,a[f],b)}else k=k.bind(a);}else if("object"==typeof k&&null!==k&&(i(b,f)||i(c,f)))k=j(k,b[f],c[f]);else if(i(c,"*"))k=j(k,b[f],c["*"]);else return Object.defineProperty(d,f,{configurable:!0,enumerable:!0,get(){return a[f]},set(b){a[f]=b}}),k;return d[f]=k,k},set(b,c,e){return c in d?d[c]=e:a[c]=e,!0},defineProperty(a,b,c){return Reflect.defineProperty(d,b,c)},deleteProperty(a,b){return Reflect.deleteProperty(d,b)}})},k=a=>({addListener(b,c,...d){b.addListener(a.get(c),...d)},hasListener(b,c){return b.hasListener(a.get(c))},removeListener(b,c){b.removeListener(a.get(c))}}),l=new c(a=>"function"==typeof a?function(b){const c=j(b,{},{getContent:{minArgs:0,maxArgs:0}});a(c)}:a);let m=!1;const n=new c(a=>"function"==typeof a?function(b,c,e){let f,g,h=!1,i=new Promise(a=>{f=function(b){m||(console.warn("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)",new Error().stack),m=!0),h=!0,a(b)}});try{g=a(b,c,f)}catch(a){g=Promise.reject(a)}const j=!0!==g&&d(g);if(!0!==g&&!j&&!h)return!1;const k=a=>{a.then(a=>{e(a)},a=>{let b;b=a&&(a instanceof Error||"string"==typeof a.message)?a.message:"An unexpected error occurred",e({__mozWebExtensionPolyfillReject__:!0,message:b})}).catch(a=>{console.error("Failed to send onMessage rejected reply",a)})};return j?k(g):k(i),!0}:a),o=({reject:b,resolve:c},d)=>{a.runtime.lastError?a.runtime.lastError.message==="The message port closed before a response was received."?c():b(new Error(a.runtime.lastError.message)):d&&d.__mozWebExtensionPolyfillReject__?b(new Error(d.message)):c(d)},p=(a,b,c,...d)=>{if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((a,b)=>{const e=o.bind(null,{resolve:a,reject:b});d.push(e),c.sendMessage(...d)})},q={devtools:{network:{onRequestFinished:k(l)}},runtime:{onMessage:k(n),onMessageExternal:k(n),sendMessage:p.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:p.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},r={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return b.privacy={network:{"*":r},services:{"*":r},websites:{"*":r}},j(a,q,b)})(chrome)}else a.exports=browser}); +(function(a,b){if("function"==typeof define&&define.amd)define("webextension-polyfill",["module"],b);else if("undefined"!=typeof exports)b(module);else{var c={exports:{}};b(c),a.browser=c.exports}})("undefined"==typeof globalThis?"undefined"==typeof self?this:self:globalThis,function(a){"use strict";if(!globalThis.chrome?.runtime?.id)throw new Error("This script should only be loaded in a browser extension.");if("undefined"==typeof globalThis.browser||Object.getPrototypeOf(globalThis.browser)!==Object.prototype){a.exports=(a=>{const b={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:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},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:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},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:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0},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:!0},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:!0}},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:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},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(0===Object.keys(b).length)throw new Error("api-metadata.json has not been included in browser-polyfill");class c extends WeakMap{constructor(a,b=void 0){super(b),this.createItem=a}get(a){return this.has(a)||this.set(a,this.createItem(a)),super.get(a)}}const d=a=>a&&"object"==typeof a&&"function"==typeof a.then,e=(b,c)=>(...d)=>{a.runtime.lastError?b.reject(new Error(a.runtime.lastError.message)):c.singleCallbackArg||1>=d.length&&!1!==c.singleCallbackArg?b.resolve(d[0]):b.resolve(d)},f=a=>1==a?"argument":"arguments",g=(a,b)=>function(c,...d){if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((f,g)=>{if(b.fallbackToNoCallback)try{c[a](...d,e({resolve:f,reject:g},b))}catch(e){console.warn(`${a} API method doesn't seem to support the callback parameter, `+"falling back to call it without a callback: ",e),c[a](...d),b.fallbackToNoCallback=!1,b.noCallback=!0,f()}else b.noCallback?(c[a](...d),f()):c[a](...d,e({resolve:f,reject:g},b))})},h=(a,b,c)=>new Proxy(b,{apply(b,d,e){return c.call(d,a,...e)}});let i=Function.call.bind(Object.prototype.hasOwnProperty);const j=(a,b={},c={})=>{let d=Object.create(null),e=Object.create(a);return new Proxy(e,{has(b,c){return c in a||c in d},get(e,f){if(f in d)return d[f];if(!(f in a))return;let k=a[f];if("function"==typeof k){if("function"==typeof b[f])k=h(a,a[f],b[f]);else if(i(c,f)){let b=g(f,c[f]);k=h(a,a[f],b)}else k=k.bind(a);}else if("object"==typeof k&&null!==k&&(i(b,f)||i(c,f)))k=j(k,b[f],c[f]);else if(i(c,"*"))k=j(k,b[f],c["*"]);else return Object.defineProperty(d,f,{configurable:!0,enumerable:!0,get(){return a[f]},set(b){a[f]=b}}),k;return d[f]=k,k},set(b,c,e){return c in d?d[c]=e:a[c]=e,!0},defineProperty(a,b,c){return Reflect.defineProperty(d,b,c)},deleteProperty(a,b){return Reflect.deleteProperty(d,b)}})},k=a=>({addListener(b,c,...d){b.addListener(a.get(c),...d)},hasListener(b,c){return b.hasListener(a.get(c))},removeListener(b,c){b.removeListener(a.get(c))}}),l=new c(a=>"function"==typeof a?function(b){const c=j(b,{},{getContent:{minArgs:0,maxArgs:0}});a(c)}:a),m=new c(a=>"function"==typeof a?function(b,c,e){let f,g,h=!1,i=new Promise(a=>{f=function(b){h=!0,a(b)}});try{g=a(b,c,f)}catch(a){g=Promise.reject(a)}const j=!0!==g&&d(g);if(!0!==g&&!j&&!h)return!1;const k=a=>{a.then(a=>{e(a)},a=>{let b;b=a&&(a instanceof Error||"string"==typeof a.message)?a.message:"An unexpected error occurred",e({__mozWebExtensionPolyfillReject__:!0,message:b})}).catch(a=>{console.error("Failed to send onMessage rejected reply",a)})};return j?k(g):k(i),!0}:a),n=({reject:b,resolve:c},d)=>{a.runtime.lastError?a.runtime.lastError.message==="The message port closed before a response was received."?c():b(new Error(a.runtime.lastError.message)):d&&d.__mozWebExtensionPolyfillReject__?b(new Error(d.message)):c(d)},o=(a,b,c,...d)=>{if(d.lengthb.maxArgs)throw new Error(`Expected at most ${b.maxArgs} ${f(b.maxArgs)} for ${a}(), got ${d.length}`);return new Promise((a,b)=>{const e=n.bind(null,{resolve:a,reject:b});d.push(e),c.sendMessage(...d)})},p={devtools:{network:{onRequestFinished:k(l)}},runtime:{onMessage:k(m),onMessageExternal:k(m),sendMessage:o.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:o.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},q={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return b.privacy={network:{"*":q},services:{"*":q},websites:{"*":q}},j(a,p,b)})(chrome)}else a.exports=globalThis.browser}); //# sourceMappingURL=browser-polyfill.min.js.map -// webextension-polyfill v.0.8.0 (https://github.com/mozilla/webextension-polyfill) +// webextension-polyfill v.0.10.0 (https://github.com/mozilla/webextension-polyfill) /* 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 diff --git a/browser-polyfill.min.js.map b/browser-polyfill.min.js.map index 092ae9f..1c746fc 100644 --- a/browser-polyfill.min.js.map +++ b/browser-polyfill.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["browser-polyfill.js"],"names":["Object","extensionAPIs","apiMetadata","constructor","items","get","isThenable","value","makeCallback","promise","metadata","callbackArgs","pluralizeArguments","numArgs","wrapAsyncFunction","args","minArgs","name","length","maxArgs","target","resolve","reject","console","wrapMethod","apply","wrapper","hasOwnProperty","Function","wrapObject","wrappers","cache","has","prop","configurable","enumerable","set","defineProperty","Reflect","deleteProperty","proxyTarget","wrapEvent","wrapperMap","addListener","hasListener","removeListener","onRequestFinishedWrappers","listener","wrappedReq","getContent","loggedSendResponseDeprecationWarning","onMessageWrappers","didCallSendResponse","sendResponsePromise","wrappedSendResponse","result","Promise","isResultThenable","sendPromisedResult","msg","sendResponse","error","message","__mozWebExtensionPolyfillReject__","err","wrappedSendMessageCallback","reply","wrappedSendMessage","wrappedCb","apiNamespaceObj","staticWrappers","devtools","network","onRequestFinished","runtime","onMessage","onMessageExternal","sendMessage","tabs","settingMetadata","clear","services","websites","chrome","module","wrapAPIs"],"mappings":"gSAMA,aAEA,GAAI,WAAA,QAAA,CAAA,OAAA,EAAkCA,MAAM,CAANA,cAAAA,CAAAA,OAAAA,IAAmCA,MAAM,CAA/E,SAAA,CAA2F,CAqrCzF,GAAI,QAAA,QAAA,CAAA,MAAA,EAA6B,CAA7B,MAAA,EAAwC,CAACmF,MAAM,CAA/C,OAAA,EAA2D,CAACA,MAAM,CAANA,OAAAA,CAAhE,EAAA,CACE,KAAM,IAAA,CAAA,KAAA,CAAN,2DAAM,CAAN,CAKFC,CAAM,CAANA,OAAAA,CAAiBC,CAlrCApF,CAAa,EAAI,CAIhC,KAAMC,CAAAA,CAAW,CAAG,CAClB,OAAU,CACR,MAAS,CACP,QADO,CAAA,CAEP,QAAW,CAFJ,CADD,CAKR,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CALJ,CASR,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CATC,CAaR,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAbF,CADQ,CAmBlB,UAAa,CACX,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CADC,CAKX,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CALI,CASX,YAAe,CACb,QADa,CAAA,CAEb,QAAW,CAFE,CATJ,CAaX,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CAbF,CAiBX,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CAjBH,CAqBX,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CArBA,CAyBX,KAAQ,CACN,QADM,CAAA,CAEN,QAAW,CAFL,CAzBG,CA6BX,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CA7BC,CAiCX,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CAjCH,CAqCX,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CArCC,CAyCX,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAzCC,CAnBK,CAiElB,cAAiB,CACf,QAAW,CACT,QADS,CAAA,CAET,QAFS,CAAA,CAGT,uBAHS,CADI,CAMf,OAAU,CACR,QADQ,CAAA,CAER,QAFQ,CAAA,CAGR,uBAHQ,CANK,CAWf,wBAA2B,CACzB,QADyB,CAAA,CAEzB,QAAW,CAFc,CAXZ,CAef,aAAgB,CACd,QADc,CAAA,CAEd,QAAW,CAFG,CAfD,CAmBf,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CAnBG,CAuBf,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CAvBG,CA2Bf,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CA3BE,CA+Bf,wBAA2B,CACzB,QADyB,CAAA,CAEzB,QAFyB,CAAA,CAGzB,uBAHyB,CA/BZ,CAoCf,aAAgB,CACd,QADc,CAAA,CAEd,QAFc,CAAA,CAGd,uBAHc,CApCD,CAyCf,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CAzCI,CA6Cf,SAAY,CACV,QADU,CAAA,CAEV,QAFU,CAAA,CAGV,uBAHU,CA7CG,CAkDf,SAAY,CACV,QADU,CAAA,CAEV,QAFU,CAAA,CAGV,uBAHU,CAlDG,CAjEC,CAyHlB,aAAgB,CACd,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CADI,CAKd,YAAe,CACb,QADa,CAAA,CAEb,QAAW,CAFE,CALD,CASd,cAAiB,CACf,QADe,CAAA,CAEf,QAAW,CAFI,CATH,CAad,gBAAmB,CACjB,QADiB,CAAA,CAEjB,QAAW,CAFM,CAbL,CAiBd,eAAkB,CAChB,QADgB,CAAA,CAEhB,QAAW,CAFK,CAjBJ,CAqBd,cAAiB,CACf,QADe,CAAA,CAEf,QAAW,CAFI,CArBH,CAyBd,mBAAsB,CACpB,QADoB,CAAA,CAEpB,QAAW,CAFS,CAzBR,CA6Bd,gBAAmB,CACjB,QADiB,CAAA,CAEjB,QAAW,CAFM,CA7BL,CAiCd,iBAAoB,CAClB,QADkB,CAAA,CAElB,QAAW,CAFO,CAjCN,CAqCd,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CArCE,CAzHE,CAmKlB,SAAY,CACV,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CADA,CAnKM,CAyKlB,aAAgB,CACd,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CADI,CAKd,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CALC,CASd,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CATI,CAzKE,CAuLlB,QAAW,CACT,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CADE,CAKT,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CALD,CAST,mBAAsB,CACpB,QADoB,CAAA,CAEpB,QAAW,CAFS,CATb,CAaT,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAbD,CAiBT,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CAjBE,CAvLO,CA6MlB,SAAY,CACV,gBAAmB,CACjB,KAAQ,CACN,QADM,CAAA,CAEN,QAFM,CAAA,CAGN,oBAHM,CADS,CADT,CAQV,OAAU,CACR,OAAU,CACR,QADQ,CAAA,CAER,QAFQ,CAAA,CAGR,oBAHQ,CADF,CAMR,SAAY,CACV,kBAAqB,CACnB,QADmB,CAAA,CAEnB,QAAW,CAFQ,CADX,CANJ,CARA,CA7MM,CAmOlB,UAAa,CACX,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CADC,CAKX,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CALD,CASX,MAAS,CACP,QADO,CAAA,CAEP,QAAW,CAFJ,CATE,CAaX,YAAe,CACb,QADa,CAAA,CAEb,QAAW,CAFE,CAbJ,CAiBX,KAAQ,CACN,QADM,CAAA,CAEN,QAFM,CAAA,CAGN,uBAHM,CAjBG,CAsBX,MAAS,CACP,QADO,CAAA,CAEP,QAAW,CAFJ,CAtBE,CA0BX,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CA1BH,CA8BX,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CA9BC,CAkCX,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAlCC,CAsCX,KAAQ,CACN,QADM,CAAA,CAEN,QAFM,CAAA,CAGN,uBAHM,CAtCG,CAnOK,CA+QlB,UAAa,CACX,0BAA6B,CAC3B,QAD2B,CAAA,CAE3B,QAAW,CAFgB,CADlB,CAKX,yBAA4B,CAC1B,QAD0B,CAAA,CAE1B,QAAW,CAFe,CALjB,CA/QK,CAyRlB,QAAW,CACT,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CADD,CAKT,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CALJ,CAST,YAAe,CACb,QADa,CAAA,CAEb,QAAW,CAFE,CATN,CAaT,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CAbJ,CAiBT,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CAjBJ,CAqBT,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CArBD,CAzRO,CAmTlB,KAAQ,CACN,eAAkB,CAChB,QADgB,CAAA,CAEhB,QAAW,CAFK,CADZ,CAKN,mBAAsB,CACpB,QADoB,CAAA,CAEpB,QAAW,CAFS,CALhB,CAnTU,CA6TlB,SAAY,CACV,kBAAqB,CACnB,QADmB,CAAA,CAEnB,QAAW,CAFQ,CADX,CA7TM,CAmUlB,KAAQ,CACN,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CADR,CAnUU,CAyUlB,WAAc,CACZ,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CADK,CAKZ,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CALE,CASZ,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CATC,CAaZ,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CAbF,CAiBZ,cAAiB,CACf,QADe,CAAA,CAEf,QAAW,CAFI,CAjBL,CAzUI,CA+VlB,cAAiB,CACf,MAAS,CACP,QADO,CAAA,CAEP,QAAW,CAFJ,CADM,CAKf,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CALK,CASf,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CATK,CAaf,mBAAsB,CACpB,QADoB,CAAA,CAEpB,QAAW,CAFS,CAbP,CAiBf,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAjBK,CA/VC,CAqXlB,WAAc,CACZ,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CADA,CAKZ,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CALA,CASZ,KAAQ,CACN,QADM,CAAA,CAEN,QAFM,CAAA,CAGN,uBAHM,CATI,CAcZ,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CAdC,CAkBZ,SAAY,CACV,QADU,CAAA,CAEV,QAFU,CAAA,CAGV,uBAHU,CAlBA,CAuBZ,SAAY,CACV,QADU,CAAA,CAEV,QAFU,CAAA,CAGV,uBAHU,CAvBA,CA4BZ,KAAQ,CACN,QADM,CAAA,CAEN,QAFM,CAAA,CAGN,uBAHM,CA5BI,CArXI,CAuZlB,YAAe,CACb,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CADC,CAKb,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CALG,CASb,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CATG,CAab,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CAbE,CAvZG,CAyalB,QAAW,CACT,kBAAqB,CACnB,QADmB,CAAA,CAEnB,QAAW,CAFQ,CADZ,CAKT,gBAAmB,CACjB,QADiB,CAAA,CAEjB,QAAW,CAFM,CALV,CAST,gBAAmB,CACjB,QADiB,CAAA,CAEjB,QAAW,CAFM,CATV,CAaT,mBAAsB,CACpB,QADoB,CAAA,CAEpB,QAAW,CAFS,CAbb,CAiBT,YAAe,CACb,QADa,CAAA,CAEb,QAAW,CAFE,CAjBN,CAqBT,kBAAqB,CACnB,QADmB,CAAA,CAEnB,QAAW,CAFQ,CArBZ,CAyBT,gBAAmB,CACjB,QADiB,CAAA,CAEjB,QAAW,CAFM,CAzBV,CAzaO,CAuclB,SAAY,CACV,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CADJ,CAKV,kBAAqB,CACnB,QADmB,CAAA,CAEnB,QAAW,CAFQ,CALX,CASV,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CATD,CAvcM,CAqdlB,QAAW,CACT,MAAS,CACP,MAAS,CACP,QADO,CAAA,CAEP,QAAW,CAFJ,CADF,CAKP,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CALA,CASP,cAAiB,CACf,QADe,CAAA,CAEf,QAAW,CAFI,CATV,CAaP,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAbH,CAiBP,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CAjBA,CADA,CAuBT,QAAW,CACT,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CADE,CAKT,cAAiB,CACf,QADe,CAAA,CAEf,QAAW,CAFI,CALR,CAvBF,CAiCT,KAAQ,CACN,MAAS,CACP,QADO,CAAA,CAEP,QAAW,CAFJ,CADH,CAKN,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CALD,CASN,cAAiB,CACf,QADe,CAAA,CAEf,QAAW,CAFI,CATX,CAaN,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAbJ,CAiBN,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CAjBD,CAjCC,CArdO,CA6gBlB,KAAQ,CACN,kBAAqB,CACnB,QADmB,CAAA,CAEnB,QAAW,CAFQ,CADf,CAKN,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CALJ,CASN,eAAkB,CAChB,QADgB,CAAA,CAEhB,QAAW,CAFK,CATZ,CAaN,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CAbL,CAiBN,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CAjBP,CAqBN,cAAiB,CACf,QADe,CAAA,CAEf,QAAW,CAFI,CArBX,CAyBN,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CAzBD,CA6BN,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CA7BR,CAiCN,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CAjCL,CAqCN,gBAAmB,CACjB,QADiB,CAAA,CAEjB,QAAW,CAFM,CArCb,CAyCN,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAzCJ,CA6CN,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CA7CP,CAiDN,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CAjDP,CAqDN,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CArDP,CAyDN,KAAQ,CACN,QADM,CAAA,CAEN,QAAW,CAFL,CAzDF,CA6DN,MAAS,CACP,QADO,CAAA,CAEP,QAAW,CAFJ,CA7DH,CAiEN,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAjEJ,CAqEN,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CArEJ,CAyEN,UAAa,CACX,QADW,CAAA,CAEX,QAAW,CAFA,CAzEP,CA6EN,YAAe,CACb,QADa,CAAA,CAEb,QAAW,CAFE,CA7ET,CAiFN,QAAW,CACT,QADS,CAAA,CAET,QAAW,CAFF,CAjFL,CAqFN,gBAAmB,CACjB,QADiB,CAAA,CAEjB,QAAW,CAFM,CArFb,CAyFN,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAzFJ,CA7gBU,CA2mBlB,SAAY,CACV,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CADG,CA3mBM,CAinBlB,cAAiB,CACf,aAAgB,CACd,QADc,CAAA,CAEd,QAAW,CAFG,CADD,CAKf,SAAY,CACV,QADU,CAAA,CAEV,QAAW,CAFD,CALG,CAjnBC,CA2nBlB,WAAc,CACZ,uBAA0B,CACxB,QADwB,CAAA,CAExB,QAAW,CAFa,CADd,CA3nBI,CAioBlB,QAAW,CACT,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CADD,CAKT,IAAO,CACL,QADK,CAAA,CAEL,QAAW,CAFN,CALE,CAST,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CATD,CAaT,WAAc,CACZ,QADY,CAAA,CAEZ,QAAW,CAFC,CAbL,CAiBT,eAAkB,CAChB,QADgB,CAAA,CAEhB,QAAW,CAFK,CAjBT,CAqBT,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CArBD,CAyBT,OAAU,CACR,QADQ,CAAA,CAER,QAAW,CAFH,CAzBD,CAjoBO,CAApB,CAiqBA,GAAA,CAAIF,GAAAA,MAAM,CAANA,IAAAA,CAAAA,CAAAA,EAAAA,MAAJ,CACE,KAAM,IAAA,CAAA,KAAA,CAAN,6DAAM,CAAN,CAaF,KAAA,CAAA,CAAA,QAAA,CAAA,OAAqC,CACnCG,WAAW,CAAA,CAAA,CAAaC,CAAb,OAAA,CAAgC,CACzC,MAAA,CAAA,CADyC,CAEzC,KAAA,UAAA,CAAA,CACD,CAEDC,GAAG,CAAA,CAAA,CAAM,CAKP,MAJK,MAAA,GAAA,CAAL,CAAK,CAIL,EAHE,KAAA,GAAA,CAAA,CAAA,CAAc,KAAA,UAAA,CAAd,CAAc,CAAd,CAGF,CAAO,MAAA,GAAA,CAAP,CAAO,CACR,CAZkC,CAnrBL,KAysB1BC,CAAAA,CAAU,CAAGC,CAAK,EACfA,CAAK,EAALA,QAAS,QAAA,CAAA,CAATA,EAAP,UAA6C,QAAOA,CAAAA,CAAK,CAAZ,IA1sBf,CA4uB1BC,CAAY,CAAG,CAAA,CAAA,CAAA,CAAA,GACZ,CAAC,GAAD,CAAA,GAAqB,CACtBP,CAAa,CAAbA,OAAAA,CAAJ,SAD0B,CAExBQ,CAAO,CAAPA,MAAAA,CAAe,GAAA,CAAA,KAAA,CAAUR,CAAa,CAAbA,OAAAA,CAAAA,SAAAA,CAAzBQ,OAAe,CAAfA,CAFwB,CAGfC,CAAQ,CAARA,iBAAAA,EACCC,CAAAA,EAAAA,CAAY,CAAZA,MAAAA,EAA4BD,KAAAA,CAAQ,CADzC,iBAHmB,CAKxBD,CAAO,CAAPA,OAAAA,CAAgBE,CAAY,CAA5BF,CAA4B,CAA5BA,CALwB,CAOxBA,CAAO,CAAPA,OAAAA,CAAAA,CAAAA,CAPJ,CA7uB8B,CAyvB1BG,CAAkB,CAAIC,CAAD,EAAaA,CAAAA,EAAAA,CAAO,CAAPA,UAAO,CAA/C,WAzvBgC,CAqxB1BC,CAAiB,CAAG,CAAA,CAAA,CAAA,CAAA,GACjB,SAAA,CAAA,CAAsC,GAAtC,CAAA,CAA+C,CACpD,GAAIC,CAAI,CAAJA,MAAAA,CAAcL,CAAQ,CAA1B,OAAA,CACE,KAAM,IAAA,CAAA,KAAA,CAAW,qBAAoBA,CAAQ,CAACM,OAAQ,IAAGJ,CAAkB,CAACF,CAAQ,CAAT,OAAA,CAAmB,QAAOO,CAAK,WAAUF,CAAI,CAACG,MAAzH,EAAM,CAAN,CAGF,GAAIH,CAAI,CAAJA,MAAAA,CAAcL,CAAQ,CAA1B,OAAA,CACE,KAAM,IAAA,CAAA,KAAA,CAAW,oBAAmBA,CAAQ,CAACS,OAAQ,IAAGP,CAAkB,CAACF,CAAQ,CAAT,OAAA,CAAmB,QAAOO,CAAK,WAAUF,CAAI,CAACG,MAAxH,EAAM,CAAN,CAGF,MAAO,IAAA,CAAA,OAAA,CAAY,CAAA,CAAA,CAAA,CAAA,GAAqB,CACtC,GAAIR,CAAQ,CAAZ,oBAAA,CAIE,GAAI,CACFU,CAAM,CAANA,CAAM,CAANA,CAAa,GAAbA,CAAAA,CAAsBZ,CAAY,CAAC,CAACa,OAAD,CAACA,CAAD,CAAUC,MAAAA,CAAAA,CAAV,CAAD,CAAlCF,CAAkC,CAAlCA,CADF,CAEE,MAAA,CAAA,CAAgB,CAChBG,OAAO,CAAPA,IAAAA,CAAc,GAAEN,CAAH,8DAAC,CAAdM,8CAAAA,CAAAA,CAAAA,CADgB,CAIhBH,CAAM,CAANA,CAAM,CAANA,CAAa,GAJG,CAIhBA,CAJgB,CAQhBV,CAAQ,CAARA,oBAAAA,GARgB,CAShBA,CAAQ,CAARA,UAAAA,GATgB,CAWhBW,CAAO,EACR,CAlBH,IAmBWX,CAAAA,CAAQ,CAAZ,UAnBP,EAoBEU,CAAM,CAANA,CAAM,CAANA,CAAa,GAAbA,CAAAA,CApBF,CAqBEC,CAAO,EArBT,EAuBED,CAAM,CAANA,CAAM,CAANA,CAAa,GAAbA,CAAAA,CAAsBZ,CAAY,CAAC,CAACa,OAAD,CAACA,CAAD,CAAUC,MAAAA,CAAAA,CAAV,CAAD,CAAlCF,CAAkC,CAAlCA,CAxBJ,CAAO,CATT,CAtxB8B,CAg1B1BI,CAAU,CAAG,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GACV,GAAA,CAAA,KAAA,CAAA,CAAA,CAAkB,CACvBC,KAAK,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAA8B,CACjC,MAAOC,CAAAA,CAAO,CAAPA,IAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAA8B,GAArC,CAAOA,CACR,CAHsB,CAAlB,CAj1BuB,CAw1BhC,GAAIC,CAAAA,CAAc,CAAGC,QAAQ,CAARA,IAAAA,CAAAA,IAAAA,CAAmB5B,MAAM,CAANA,SAAAA,CAAxC,cAAqB4B,CAArB,CAx1BgC,KAi3B1BC,CAAAA,CAAU,CAAG,CAAA,CAAA,CAASC,CAAQ,CAAjB,EAAA,CAAwBpB,CAAQ,CAAhC,EAAA,GAA0C,IACvDqB,CAAAA,CAAK,CAAG/B,MAAM,CAANA,MAAAA,CAAZ,IAAYA,CAD+C,CA8FvDwC,CAAW,CAAGxC,MAAM,CAANA,MAAAA,CAAlB,CAAkBA,CA9FyC,CA+F3D,MAAO,IAAA,CAAA,KAAA,CAAP,CAAO,CA7FQ,CACbgC,GAAG,CAAA,CAAA,CAAA,CAAA,CAAoB,CACrB,MAAOC,CAAAA,CAAI,GAAJA,CAAAA,CAAAA,EAAkBA,CAAI,GAA7B,CAAA,CAFW,CAAA,CAKb5B,GAAG,CAAA,CAAA,CAAA,CAAA,CAA8B,CAC/B,GAAI4B,CAAI,GAAR,CAAA,CAAA,CACE,MAAOF,CAAAA,CAAK,CAAZ,CAAY,CAAZ,CAGF,GAAI,EAAEE,CAAI,GAAV,CAAA,CAAI,CAAJ,CACE,OAGF,GAAI1B,CAAAA,CAAK,CAAGa,CAAM,CAAlB,CAAkB,CAAlB,CAEA,GAAA,UAAI,QAAA,CAAA,CAAJ,EAIE,GAAA,UAAI,QAAOU,CAAAA,CAAQ,CAAf,CAAe,CAAnB,CAEEvB,CAAK,CAAGiB,CAAU,CAAA,CAAA,CAASJ,CAAM,CAAf,CAAe,CAAf,CAAuBU,CAAQ,CAAjDvB,CAAiD,CAA/B,CAFpB,KAGO,IAAIoB,CAAc,CAAA,CAAA,CAAlB,CAAkB,CAAlB,CAAoC,CAGzC,GAAID,CAAAA,CAAO,CAAGZ,CAAiB,CAAA,CAAA,CAAOJ,CAAQ,CAA9C,CAA8C,CAAf,CAA/B,CACAH,CAAK,CAAGiB,CAAU,CAAA,CAAA,CAASJ,CAAM,CAAf,CAAe,CAAf,CAAlBb,CAAkB,CAJb,CAAA,IAQLA,CAAAA,CAAK,CAAGA,CAAK,CAALA,IAAAA,CAARA,CAAQA,CARH,CAPT,KAiBO,IAAI,QAAA,QAAA,CAAA,CAAA,EAAA,IAA6BA,GAAAA,CAA7B,GACCoB,CAAc,CAAA,CAAA,CAAdA,CAAc,CAAdA,EACAA,CAAc,CAAA,CAAA,CAFnB,CAEmB,CAFf,CAAJ,CAMLpB,CAAK,CAAGsB,CAAU,CAAA,CAAA,CAAQC,CAAQ,CAAhB,CAAgB,CAAhB,CAAwBpB,CAAQ,CAAlDH,CAAkD,CAAhC,CANb,KAOA,IAAIoB,CAAc,CAAA,CAAA,CAAlB,GAAkB,CAAlB,CAELpB,CAAK,CAAGsB,CAAU,CAAA,CAAA,CAAQC,CAAQ,CAAhB,CAAgB,CAAhB,CAAwBpB,CAAQ,CAAlDH,GAAkD,CAAhC,CAFb,KAiBL,OAXAP,CAAAA,MAAM,CAANA,cAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAmC,CACjCkC,YADiC,GAAA,CAEjCC,UAFiC,GAAA,CAGjC9B,GAAG,EAAG,CACJ,MAAOe,CAAAA,CAAM,CAAb,CAAa,CAJkB,CAAA,CAMjCgB,GAAG,CAAA,CAAA,CAAQ,CACThB,CAAM,CAANA,CAAM,CAANA,CAAAA,CACD,CARgC,CAAnCpB,CAWA,CAAA,CAAA,CAIF,MADA+B,CAAAA,CAAK,CAALA,CAAK,CAALA,CAAAA,CACA,CAAA,CA7DW,CAAA,CAgEbK,GAAG,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAqC,CAMtC,MALIH,CAAAA,CAAI,GAAR,CAAA,CAKA,CAJEF,CAAK,CAALA,CAAK,CAALA,CAAAA,CAIF,CAFEX,CAAM,CAANA,CAAM,CAANA,CAAAA,CAEF,GAtEW,CAAA,CAyEbiB,cAAc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAA0B,CACtC,MAAOC,CAAAA,OAAO,CAAPA,cAAAA,CAAAA,CAAAA,CAAAA,CAAAA,CAAP,CAAOA,CA1EI,CAAA,CA6EbC,cAAc,CAAA,CAAA,CAAA,CAAA,CAAoB,CAChC,MAAOD,CAAAA,OAAO,CAAPA,cAAAA,CAAAA,CAAAA,CAAP,CAAOA,CACR,CA/EY,CA6FR,CA/FT,CAj3BgC,CAm+B1BG,CAAS,CAAGC,CAAU,GAAK,CAC/BC,WAAW,CAAA,CAAA,CAAA,CAAA,CAAmB,GAAnB,CAAA,CAA4B,CACrCvB,CAAM,CAANA,WAAAA,CAAmBsB,CAAU,CAAVA,GAAAA,CAAnBtB,CAAmBsB,CAAnBtB,CAA6C,GAA7CA,CAAAA,CAF6B,CAAA,CAK/BwB,WAAW,CAAA,CAAA,CAAA,CAAA,CAAmB,CAC5B,MAAOxB,CAAAA,CAAM,CAANA,WAAAA,CAAmBsB,CAAU,CAAVA,GAAAA,CAA1B,CAA0BA,CAAnBtB,CANsB,CAAA,CAS/ByB,cAAc,CAAA,CAAA,CAAA,CAAA,CAAmB,CAC/BzB,CAAM,CAANA,cAAAA,CAAsBsB,CAAU,CAAVA,GAAAA,CAAtBtB,CAAsBsB,CAAtBtB,CACD,CAX8B,CAAL,CAn+BI,CAi/B1B0B,CAAyB,CAAG,GAAA,CAAA,CAAA,CAAmBC,CAAQ,EAC3D,UAAI,QAAA,CAAA,CADuD,CAapD,SAAA,CAAA,CAAgC,CACrC,KAAMC,CAAAA,CAAU,CAAGnB,CAAU,CAAA,CAAA,CAAM,EAAN,CAAyB,CACpDoB,UAAU,CAAE,CACVjC,OAAO,CADG,CAAA,CAEVG,OAAO,CAAE,CAFC,CADwC,CAAzB,CAA7B,CAMA4B,CAAQ,CAARA,CAAQ,CAPV,CAb2D,CAEzD,CAF8B,CAj/BF,CA0gChC,GAAIG,CAAAA,CAAJ,GAAA,CA1gCgC,KA4gC1BC,CAAAA,CAAiB,CAAG,GAAA,CAAA,CAAA,CAAmBJ,CAAQ,EACnD,UAAI,QAAA,CAAA,CAD+C,CAsB5C,SAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAkD,IAGvD,CAAA,CAHuD,CAevD,CAfuD,CACnDK,CAAJ,GADuD,CAInDC,CAAmB,CAAG,GAAA,CAAA,OAAA,CAAYhC,CAAO,EAAI,CAC/CiC,CAAmB,CAAG,SAAA,CAAA,CAAmB,CACvC,CADuC,GAErC/B,OAAO,CAAPA,IAAAA,CAljC6E,wPAkjC7EA,CAAgD,GAAA,CAAA,KAAA,GAAhDA,KAAAA,CAFqC,CAGrC2B,CAAAA,GAHqC,EAKvCE,CAAAA,GALuC,CAMvC/B,CAAO,CAAPA,CAAO,CANTiC,CADF,CAA0B,CAJ6B,CAgBvD,GAAI,CACFC,CAAM,CAAGR,CAAQ,CAAA,CAAA,CAAA,CAAA,CAAjBQ,CAAiB,CADnB,CAEE,MAAA,CAAA,CAAY,CACZA,CAAM,CAAGC,OAAO,CAAPA,MAAAA,CAATD,CAASC,CACV,CAED,KAAMC,CAAAA,CAAgB,CAAGF,KAAAA,CAAAA,EAAmBjD,CAAU,CAtBC,CAsBD,CAAtD,CAKA,GAAIiD,KAAAA,CAAAA,EAAmB,CAAnBA,CAAAA,EAAwC,CAA5C,CAAA,CACE,SAOF,KAAMG,CAAAA,CAAkB,CAAIjD,CAAD,EAAa,CACtCA,CAAO,CAAPA,IAAAA,CAAakD,CAAG,EAAI,CAElBC,CAAY,CAAZA,CAAY,CAFdnD,CAAAA,CAGGoD,CAAK,EAAI,CAGV,GAAA,CAAA,CAAA,CAGEC,CANQ,CAIND,CAAK,GAAKA,CAAK,WAALA,CAAAA,KAAAA,EAAd,QACI,QAAOA,CAAAA,CAAK,CAAZ,OADK,CAJC,CAMEA,CAAK,CAAfC,OANQ,CAQRA,8BARQ,CAWVF,CAAY,CAAC,CACXG,iCADW,GAAA,CAEXD,OAAAA,CAAAA,CAFW,CAAD,CAddrD,CAAAA,EAAAA,KAAAA,CAkBSuD,CAAG,EAAI,CAEdzC,OAAO,CAAPA,KAAAA,CAAAA,yCAAAA,CAAAA,CAAAA,CApBFd,CAAAA,CApCqD,CAmCvD,CAmCA,MAPA,CAAA,CAOA,CANEiD,CAAkB,CAAlBA,CAAkB,CAMpB,CAJEA,CAAkB,CAAlBA,CAAkB,CAIpB,GAtEF,CAtBmD,CAEjD,CAFsB,CA5gCM,CA4mC1BO,CAA0B,CAAG,CAAC,CAAC3C,MAAD,CAACA,CAAD,CAASD,OAAAA,CAAAA,CAAT,CAAD,CAAA,CAAA,GAA8B,CAC3DpB,CAAa,CAAbA,OAAAA,CAAJ,SAD+D,CAKzDA,CAAa,CAAbA,OAAAA,CAAAA,SAAAA,CAAJ,OAAIA,GAznCV,yDAonCmE,CAM3DoB,CAAO,EANoD,CAQ3DC,CAAM,CAAC,GAAA,CAAA,KAAA,CAAUrB,CAAa,CAAbA,OAAAA,CAAAA,SAAAA,CAAjBqB,OAAO,CAAD,CARqD,CAUpD4C,CAAK,EAAIA,CAAK,CAAlB,iCAVwD,CAa7D5C,CAAM,CAAC,GAAA,CAAA,KAAA,CAAU4C,CAAK,CAAtB5C,OAAO,CAAD,CAbuD,CAe7DD,CAAO,CAAPA,CAAO,CAfX,CA5mCgC,CA+nC1B8C,CAAkB,CAAG,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAkC,GAAlC,CAAA,GAA8C,CACvE,GAAIpD,CAAI,CAAJA,MAAAA,CAAcL,CAAQ,CAA1B,OAAA,CACE,KAAM,IAAA,CAAA,KAAA,CAAW,qBAAoBA,CAAQ,CAACM,OAAQ,IAAGJ,CAAkB,CAACF,CAAQ,CAAT,OAAA,CAAmB,QAAOO,CAAK,WAAUF,CAAI,CAACG,MAAzH,EAAM,CAAN,CAGF,GAAIH,CAAI,CAAJA,MAAAA,CAAcL,CAAQ,CAA1B,OAAA,CACE,KAAM,IAAA,CAAA,KAAA,CAAW,oBAAmBA,CAAQ,CAACS,OAAQ,IAAGP,CAAkB,CAACF,CAAQ,CAAT,OAAA,CAAmB,QAAOO,CAAK,WAAUF,CAAI,CAACG,MAAxH,EAAM,CAAN,CAGF,MAAO,IAAA,CAAA,OAAA,CAAY,CAAA,CAAA,CAAA,CAAA,GAAqB,CACtC,KAAMkD,CAAAA,CAAS,CAAG,CAA0B,CAA1B,IAAA,CAAA,IAAA,CAAsC,CAAC/C,OAAD,CAACA,CAAD,CAAUC,MAAAA,CAAAA,CAAV,CAAtC,CAAlB,CACAP,CAAI,CAAJA,IAAAA,CAAAA,CAAAA,CAFsC,CAGtCsD,CAAe,CAAfA,WAAAA,CAA4B,GAA5BA,CAAAA,CAHF,CAAO,CATT,CA/nCgC,CA+oC1BC,CAAc,CAAG,CACrBC,QAAQ,CAAE,CACRC,OAAO,CAAE,CACPC,iBAAiB,CAAEhC,CAAS,CAAA,CAAA,CADrB,CADD,CADW,CAMrBiC,OAAO,CAAE,CACPC,SAAS,CAAElC,CAAS,CADb,CACa,CADb,CAEPmC,iBAAiB,CAAEnC,CAAS,CAFrB,CAEqB,CAFrB,CAGPoC,WAAW,CAAE,CAAkB,CAAlB,IAAA,CAAA,IAAA,CAAA,aAAA,CAA6C,CAAC7D,OAAO,CAAR,CAAA,CAAaG,OAAO,CAAE,CAAtB,CAA7C,CAHN,CANY,CAWrB2D,IAAI,CAAE,CACJD,WAAW,CAAE,CAAkB,CAAlB,IAAA,CAAA,IAAA,CAAA,aAAA,CAA6C,CAAC7D,OAAO,CAAR,CAAA,CAAaG,OAAO,CAAE,CAAtB,CAA7C,CADT,CAXe,CA/oCS,CA8pC1B4D,CAAe,CAAG,CACtBC,KAAK,CAAE,CAAChE,OAAO,CAAR,CAAA,CAAaG,OAAO,CAAE,CAAtB,CADe,CAEtBd,GAAG,CAAE,CAACW,OAAO,CAAR,CAAA,CAAaG,OAAO,CAAE,CAAtB,CAFiB,CAGtBiB,GAAG,CAAE,CAACpB,OAAO,CAAR,CAAA,CAAaG,OAAO,CAAE,CAAtB,CAHiB,CA9pCQ,CAyqChC,MANAjB,CAAAA,CAAW,CAAXA,OAAAA,CAAsB,CACpBsE,OAAO,CAAE,CAAC,IAAKO,CAAN,CADW,CAEpBE,QAAQ,CAAE,CAAC,IAAKF,CAAN,CAFU,CAGpBG,QAAQ,CAAE,CAAC,IAAKH,CAAN,CAHU,CAMtB,CAAOlD,CAAU,CAAA,CAAA,CAAA,CAAA,CAAjB,CAAiB,CAzqCnB,CAkrCiBwD,EAAjBD,MAAiBC,CA3rCnB,CAAA,IA6rCED,CAAAA,CAAM,CAANA,OAAAA,CAAAA,O","sourcesContent":["/* webextension-polyfill - v0.8.0 - Tue Apr 20 2021 11:27:38 */\n/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */\n/* vim: set sts=2 sw=2 et tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\"use strict\";\n\nif (typeof browser === \"undefined\" || Object.getPrototypeOf(browser) !== Object.prototype) {\n const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = \"The message port closed before a response was received.\";\n 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)\";\n\n // Wrapping the bulk of this polyfill in a one-time-use function is a minor\n // optimization for Firefox. Since Spidermonkey does not fully parse the\n // contents of a function until the first time it's called, and since it will\n // never actually need to be called, this allows the polyfill to be included\n // in Firefox nearly for free.\n const wrapAPIs = extensionAPIs => {\n // NOTE: apiMetadata is associated to the content of the api-metadata.json file\n // at build time by replacing the following \"include\" with the content of the\n // JSON file.\n const apiMetadata = {\n \"alarms\": {\n \"clear\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"clearAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"bookmarks\": {\n \"create\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getChildren\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getRecent\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getSubTree\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getTree\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"move\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeTree\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"search\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n },\n \"browserAction\": {\n \"disable\": {\n \"minArgs\": 0,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"enable\": {\n \"minArgs\": 0,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"getBadgeBackgroundColor\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getBadgeText\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"openPopup\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"setBadgeBackgroundColor\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setBadgeText\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setIcon\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"setPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n }\n },\n \"browsingData\": {\n \"remove\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"removeCache\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeCookies\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeDownloads\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeFormData\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeHistory\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeLocalStorage\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removePasswords\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removePluginData\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"settings\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"commands\": {\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"contextMenus\": {\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n },\n \"cookies\": {\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAllCookieStores\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"set\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"devtools\": {\n \"inspectedWindow\": {\n \"eval\": {\n \"minArgs\": 1,\n \"maxArgs\": 2,\n \"singleCallbackArg\": false\n }\n },\n \"panels\": {\n \"create\": {\n \"minArgs\": 3,\n \"maxArgs\": 3,\n \"singleCallbackArg\": true\n },\n \"elements\": {\n \"createSidebarPane\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n }\n }\n },\n \"downloads\": {\n \"cancel\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"download\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"erase\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getFileIcon\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"open\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"pause\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeFile\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"resume\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"search\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"show\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n }\n },\n \"extension\": {\n \"isAllowedFileSchemeAccess\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"isAllowedIncognitoAccess\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"history\": {\n \"addUrl\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"deleteAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"deleteRange\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"deleteUrl\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getVisits\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"search\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"i18n\": {\n \"detectLanguage\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAcceptLanguages\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"identity\": {\n \"launchWebAuthFlow\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"idle\": {\n \"queryState\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"management\": {\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getSelf\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"setEnabled\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"uninstallSelf\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n }\n },\n \"notifications\": {\n \"clear\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"create\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getPermissionLevel\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n },\n \"pageAction\": {\n \"getPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"hide\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setIcon\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"setPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"show\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n }\n },\n \"permissions\": {\n \"contains\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"request\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"runtime\": {\n \"getBackgroundPage\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getPlatformInfo\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"openOptionsPage\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"requestUpdateCheck\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"sendMessage\": {\n \"minArgs\": 1,\n \"maxArgs\": 3\n },\n \"sendNativeMessage\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"setUninstallURL\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"sessions\": {\n \"getDevices\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getRecentlyClosed\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"restore\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n }\n },\n \"storage\": {\n \"local\": {\n \"clear\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getBytesInUse\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"set\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"managed\": {\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getBytesInUse\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n }\n },\n \"sync\": {\n \"clear\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getBytesInUse\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"set\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n }\n },\n \"tabs\": {\n \"captureVisibleTab\": {\n \"minArgs\": 0,\n \"maxArgs\": 2\n },\n \"create\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"detectLanguage\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"discard\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"duplicate\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"executeScript\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getCurrent\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getZoom\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getZoomSettings\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"goBack\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"goForward\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"highlight\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"insertCSS\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"move\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"query\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"reload\": {\n \"minArgs\": 0,\n \"maxArgs\": 2\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeCSS\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"sendMessage\": {\n \"minArgs\": 2,\n \"maxArgs\": 3\n },\n \"setZoom\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"setZoomSettings\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"update\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n }\n },\n \"topSites\": {\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"webNavigation\": {\n \"getAllFrames\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getFrame\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"webRequest\": {\n \"handlerBehaviorChanged\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"windows\": {\n \"create\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getCurrent\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getLastFocused\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n }\n };\n\n if (Object.keys(apiMetadata).length === 0) {\n throw new Error(\"api-metadata.json has not been included in browser-polyfill\");\n }\n\n /**\n * A WeakMap subclass which creates and stores a value for any key which does\n * not exist when accessed, but behaves exactly as an ordinary WeakMap\n * otherwise.\n *\n * @param {function} createItem\n * A function which will be called in order to create the value for any\n * key which does not exist, the first time it is accessed. The\n * function receives, as its only argument, the key being created.\n */\n class DefaultWeakMap extends WeakMap {\n constructor(createItem, items = undefined) {\n super(items);\n this.createItem = createItem;\n }\n\n get(key) {\n if (!this.has(key)) {\n this.set(key, this.createItem(key));\n }\n\n return super.get(key);\n }\n }\n\n /**\n * Returns true if the given object is an object with a `then` method, and can\n * therefore be assumed to behave as a Promise.\n *\n * @param {*} value The value to test.\n * @returns {boolean} True if the value is thenable.\n */\n const isThenable = value => {\n return value && typeof value === \"object\" && typeof value.then === \"function\";\n };\n\n /**\n * Creates and returns a function which, when called, will resolve or reject\n * the given promise based on how it is called:\n *\n * - If, when called, `chrome.runtime.lastError` contains a non-null object,\n * the promise is rejected with that value.\n * - If the function is called with exactly one argument, the promise is\n * resolved to that value.\n * - Otherwise, the promise is resolved to an array containing all of the\n * function's arguments.\n *\n * @param {object} promise\n * An object containing the resolution and rejection functions of a\n * promise.\n * @param {function} promise.resolve\n * The promise's resolution function.\n * @param {function} promise.reject\n * The promise's rejection function.\n * @param {object} metadata\n * Metadata about the wrapped method which has created the callback.\n * @param {boolean} metadata.singleCallbackArg\n * Whether or not the promise is resolved with only the first\n * argument of the callback, alternatively an array of all the\n * callback arguments is resolved. By default, if the callback\n * function is invoked with only a single argument, that will be\n * resolved to the promise, while all arguments will be resolved as\n * an array if multiple are given.\n *\n * @returns {function}\n * The generated callback function.\n */\n const makeCallback = (promise, metadata) => {\n return (...callbackArgs) => {\n if (extensionAPIs.runtime.lastError) {\n promise.reject(new Error(extensionAPIs.runtime.lastError.message));\n } else if (metadata.singleCallbackArg ||\n (callbackArgs.length <= 1 && metadata.singleCallbackArg !== false)) {\n promise.resolve(callbackArgs[0]);\n } else {\n promise.resolve(callbackArgs);\n }\n };\n };\n\n const pluralizeArguments = (numArgs) => numArgs == 1 ? \"argument\" : \"arguments\";\n\n /**\n * Creates a wrapper function for a method with the given name and metadata.\n *\n * @param {string} name\n * The name of the method which is being wrapped.\n * @param {object} metadata\n * Metadata about the method being wrapped.\n * @param {integer} metadata.minArgs\n * The minimum number of arguments which must be passed to the\n * function. If called with fewer than this number of arguments, the\n * wrapper will raise an exception.\n * @param {integer} metadata.maxArgs\n * The maximum number of arguments which may be passed to the\n * function. If called with more than this number of arguments, the\n * wrapper will raise an exception.\n * @param {boolean} metadata.singleCallbackArg\n * Whether or not the promise is resolved with only the first\n * argument of the callback, alternatively an array of all the\n * callback arguments is resolved. By default, if the callback\n * function is invoked with only a single argument, that will be\n * resolved to the promise, while all arguments will be resolved as\n * an array if multiple are given.\n *\n * @returns {function(object, ...*)}\n * The generated wrapper function.\n */\n const wrapAsyncFunction = (name, metadata) => {\n return function asyncFunctionWrapper(target, ...args) {\n if (args.length < metadata.minArgs) {\n throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);\n }\n\n if (args.length > metadata.maxArgs) {\n throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);\n }\n\n return new Promise((resolve, reject) => {\n if (metadata.fallbackToNoCallback) {\n // This API method has currently no callback on Chrome, but it return a promise on Firefox,\n // and so the polyfill will try to call it with a callback first, and it will fallback\n // to not passing the callback if the first call fails.\n try {\n target[name](...args, makeCallback({resolve, reject}, metadata));\n } catch (cbError) {\n console.warn(`${name} API method doesn't seem to support the callback parameter, ` +\n \"falling back to call it without a callback: \", cbError);\n\n target[name](...args);\n\n // Update the API method metadata, so that the next API calls will not try to\n // use the unsupported callback anymore.\n metadata.fallbackToNoCallback = false;\n metadata.noCallback = true;\n\n resolve();\n }\n } else if (metadata.noCallback) {\n target[name](...args);\n resolve();\n } else {\n target[name](...args, makeCallback({resolve, reject}, metadata));\n }\n });\n };\n };\n\n /**\n * Wraps an existing method of the target object, so that calls to it are\n * intercepted by the given wrapper function. The wrapper function receives,\n * as its first argument, the original `target` object, followed by each of\n * the arguments passed to the original method.\n *\n * @param {object} target\n * The original target object that the wrapped method belongs to.\n * @param {function} method\n * The method being wrapped. This is used as the target of the Proxy\n * object which is created to wrap the method.\n * @param {function} wrapper\n * The wrapper function which is called in place of a direct invocation\n * of the wrapped method.\n *\n * @returns {Proxy}\n * A Proxy object for the given method, which invokes the given wrapper\n * method in its place.\n */\n const wrapMethod = (target, method, wrapper) => {\n return new Proxy(method, {\n apply(targetMethod, thisObj, args) {\n return wrapper.call(thisObj, target, ...args);\n },\n });\n };\n\n let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);\n\n /**\n * Wraps an object in a Proxy which intercepts and wraps certain methods\n * based on the given `wrappers` and `metadata` objects.\n *\n * @param {object} target\n * The target object to wrap.\n *\n * @param {object} [wrappers = {}]\n * An object tree containing wrapper functions for special cases. Any\n * function present in this object tree is called in place of the\n * method in the same location in the `target` object tree. These\n * wrapper methods are invoked as described in {@see wrapMethod}.\n *\n * @param {object} [metadata = {}]\n * An object tree containing metadata used to automatically generate\n * Promise-based wrapper functions for asynchronous. Any function in\n * the `target` object tree which has a corresponding metadata object\n * in the same location in the `metadata` tree is replaced with an\n * automatically-generated wrapper function, as described in\n * {@see wrapAsyncFunction}\n *\n * @returns {Proxy}\n */\n const wrapObject = (target, wrappers = {}, metadata = {}) => {\n let cache = Object.create(null);\n let handlers = {\n has(proxyTarget, prop) {\n return prop in target || prop in cache;\n },\n\n get(proxyTarget, prop, receiver) {\n if (prop in cache) {\n return cache[prop];\n }\n\n if (!(prop in target)) {\n return undefined;\n }\n\n let value = target[prop];\n\n if (typeof value === \"function\") {\n // This is a method on the underlying object. Check if we need to do\n // any wrapping.\n\n if (typeof wrappers[prop] === \"function\") {\n // We have a special-case wrapper for this method.\n value = wrapMethod(target, target[prop], wrappers[prop]);\n } else if (hasOwnProperty(metadata, prop)) {\n // This is an async method that we have metadata for. Create a\n // Promise wrapper for it.\n let wrapper = wrapAsyncFunction(prop, metadata[prop]);\n value = wrapMethod(target, target[prop], wrapper);\n } else {\n // This is a method that we don't know or care about. Return the\n // original method, bound to the underlying object.\n value = value.bind(target);\n }\n } else if (typeof value === \"object\" && value !== null &&\n (hasOwnProperty(wrappers, prop) ||\n hasOwnProperty(metadata, prop))) {\n // This is an object that we need to do some wrapping for the children\n // of. Create a sub-object wrapper for it with the appropriate child\n // metadata.\n value = wrapObject(value, wrappers[prop], metadata[prop]);\n } else if (hasOwnProperty(metadata, \"*\")) {\n // Wrap all properties in * namespace.\n value = wrapObject(value, wrappers[prop], metadata[\"*\"]);\n } else {\n // We don't need to do any wrapping for this property,\n // so just forward all access to the underlying object.\n Object.defineProperty(cache, prop, {\n configurable: true,\n enumerable: true,\n get() {\n return target[prop];\n },\n set(value) {\n target[prop] = value;\n },\n });\n\n return value;\n }\n\n cache[prop] = value;\n return value;\n },\n\n set(proxyTarget, prop, value, receiver) {\n if (prop in cache) {\n cache[prop] = value;\n } else {\n target[prop] = value;\n }\n return true;\n },\n\n defineProperty(proxyTarget, prop, desc) {\n return Reflect.defineProperty(cache, prop, desc);\n },\n\n deleteProperty(proxyTarget, prop) {\n return Reflect.deleteProperty(cache, prop);\n },\n };\n\n // Per contract of the Proxy API, the \"get\" proxy handler must return the\n // original value of the target if that value is declared read-only and\n // non-configurable. For this reason, we create an object with the\n // prototype set to `target` instead of using `target` directly.\n // Otherwise we cannot return a custom object for APIs that\n // are declared read-only and non-configurable, such as `chrome.devtools`.\n //\n // The proxy handlers themselves will still use the original `target`\n // instead of the `proxyTarget`, so that the methods and properties are\n // dereferenced via the original targets.\n let proxyTarget = Object.create(target);\n return new Proxy(proxyTarget, handlers);\n };\n\n /**\n * Creates a set of wrapper functions for an event object, which handles\n * wrapping of listener functions that those messages are passed.\n *\n * A single wrapper is created for each listener function, and stored in a\n * map. Subsequent calls to `addListener`, `hasListener`, or `removeListener`\n * retrieve the original wrapper, so that attempts to remove a\n * previously-added listener work as expected.\n *\n * @param {DefaultWeakMap} wrapperMap\n * A DefaultWeakMap object which will create the appropriate wrapper\n * for a given listener function when one does not exist, and retrieve\n * an existing one when it does.\n *\n * @returns {object}\n */\n const wrapEvent = wrapperMap => ({\n addListener(target, listener, ...args) {\n target.addListener(wrapperMap.get(listener), ...args);\n },\n\n hasListener(target, listener) {\n return target.hasListener(wrapperMap.get(listener));\n },\n\n removeListener(target, listener) {\n target.removeListener(wrapperMap.get(listener));\n },\n });\n\n const onRequestFinishedWrappers = new DefaultWeakMap(listener => {\n if (typeof listener !== \"function\") {\n return listener;\n }\n\n /**\n * Wraps an onRequestFinished listener function so that it will return a\n * `getContent()` property which returns a `Promise` rather than using a\n * callback API.\n *\n * @param {object} req\n * The HAR entry object representing the network request.\n */\n return function onRequestFinished(req) {\n const wrappedReq = wrapObject(req, {} /* wrappers */, {\n getContent: {\n minArgs: 0,\n maxArgs: 0,\n },\n });\n listener(wrappedReq);\n };\n });\n\n // Keep track if the deprecation warning has been logged at least once.\n let loggedSendResponseDeprecationWarning = false;\n\n const onMessageWrappers = new DefaultWeakMap(listener => {\n if (typeof listener !== \"function\") {\n return listener;\n }\n\n /**\n * Wraps a message listener function so that it may send responses based on\n * its return value, rather than by returning a sentinel value and calling a\n * callback. If the listener function returns a Promise, the response is\n * sent when the promise either resolves or rejects.\n *\n * @param {*} message\n * The message sent by the other end of the channel.\n * @param {object} sender\n * Details about the sender of the message.\n * @param {function(*)} sendResponse\n * A callback which, when called with an arbitrary argument, sends\n * that value as a response.\n * @returns {boolean}\n * True if the wrapped listener returned a Promise, which will later\n * yield a response. False otherwise.\n */\n return function onMessage(message, sender, sendResponse) {\n let didCallSendResponse = false;\n\n let wrappedSendResponse;\n let sendResponsePromise = new Promise(resolve => {\n wrappedSendResponse = function(response) {\n if (!loggedSendResponseDeprecationWarning) {\n console.warn(SEND_RESPONSE_DEPRECATION_WARNING, new Error().stack);\n loggedSendResponseDeprecationWarning = true;\n }\n didCallSendResponse = true;\n resolve(response);\n };\n });\n\n let result;\n try {\n result = listener(message, sender, wrappedSendResponse);\n } catch (err) {\n result = Promise.reject(err);\n }\n\n const isResultThenable = result !== true && isThenable(result);\n\n // If the listener didn't returned true or a Promise, or called\n // wrappedSendResponse synchronously, we can exit earlier\n // because there will be no response sent from this listener.\n if (result !== true && !isResultThenable && !didCallSendResponse) {\n return false;\n }\n\n // A small helper to send the message if the promise resolves\n // and an error if the promise rejects (a wrapped sendMessage has\n // to translate the message into a resolved promise or a rejected\n // promise).\n const sendPromisedResult = (promise) => {\n promise.then(msg => {\n // send the message value.\n sendResponse(msg);\n }, error => {\n // Send a JSON representation of the error if the rejected value\n // is an instance of error, or the object itself otherwise.\n let message;\n if (error && (error instanceof Error ||\n typeof error.message === \"string\")) {\n message = error.message;\n } else {\n message = \"An unexpected error occurred\";\n }\n\n sendResponse({\n __mozWebExtensionPolyfillReject__: true,\n message,\n });\n }).catch(err => {\n // Print an error on the console if unable to send the response.\n console.error(\"Failed to send onMessage rejected reply\", err);\n });\n };\n\n // If the listener returned a Promise, send the resolved value as a\n // result, otherwise wait the promise related to the wrappedSendResponse\n // callback to resolve and send it as a response.\n if (isResultThenable) {\n sendPromisedResult(result);\n } else {\n sendPromisedResult(sendResponsePromise);\n }\n\n // Let Chrome know that the listener is replying.\n return true;\n };\n });\n\n const wrappedSendMessageCallback = ({reject, resolve}, reply) => {\n if (extensionAPIs.runtime.lastError) {\n // Detect when none of the listeners replied to the sendMessage call and resolve\n // the promise to undefined as in Firefox.\n // See https://github.com/mozilla/webextension-polyfill/issues/130\n if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {\n resolve();\n } else {\n reject(new Error(extensionAPIs.runtime.lastError.message));\n }\n } else if (reply && reply.__mozWebExtensionPolyfillReject__) {\n // Convert back the JSON representation of the error into\n // an Error instance.\n reject(new Error(reply.message));\n } else {\n resolve(reply);\n }\n };\n\n const wrappedSendMessage = (name, metadata, apiNamespaceObj, ...args) => {\n if (args.length < metadata.minArgs) {\n throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);\n }\n\n if (args.length > metadata.maxArgs) {\n throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);\n }\n\n return new Promise((resolve, reject) => {\n const wrappedCb = wrappedSendMessageCallback.bind(null, {resolve, reject});\n args.push(wrappedCb);\n apiNamespaceObj.sendMessage(...args);\n });\n };\n\n const staticWrappers = {\n devtools: {\n network: {\n onRequestFinished: wrapEvent(onRequestFinishedWrappers),\n },\n },\n runtime: {\n onMessage: wrapEvent(onMessageWrappers),\n onMessageExternal: wrapEvent(onMessageWrappers),\n sendMessage: wrappedSendMessage.bind(null, \"sendMessage\", {minArgs: 1, maxArgs: 3}),\n },\n tabs: {\n sendMessage: wrappedSendMessage.bind(null, \"sendMessage\", {minArgs: 2, maxArgs: 3}),\n },\n };\n const settingMetadata = {\n clear: {minArgs: 1, maxArgs: 1},\n get: {minArgs: 1, maxArgs: 1},\n set: {minArgs: 1, maxArgs: 1},\n };\n apiMetadata.privacy = {\n network: {\"*\": settingMetadata},\n services: {\"*\": settingMetadata},\n websites: {\"*\": settingMetadata},\n };\n\n return wrapObject(extensionAPIs, staticWrappers, apiMetadata);\n };\n\n if (typeof chrome != \"object\" || !chrome || !chrome.runtime || !chrome.runtime.id) {\n throw new Error(\"This script should only be loaded in a browser extension.\");\n }\n\n // The build process adds a UMD wrapper around this file, which makes the\n // `module` variable available.\n module.exports = wrapAPIs(chrome);\n} else {\n module.exports = browser;\n}\n"],"file":"browser-polyfill.min.js"} +{"version":3,"file":"browser-polyfill.min.js","mappings":"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","names":["globalThis","chrome","runtime","id","Error","browser","Object","getPrototypeOf","prototype","module","exports","wrapAPIs","extensionAPIs","apiMetadata","keys","length","DefaultWeakMap","WeakMap","constructor","createItem","items","get","key","has","set","isThenable","value","then","makeCallback","promise","metadata","callbackArgs","lastError","reject","message","singleCallbackArg","resolve","pluralizeArguments","numArgs","wrapAsyncFunction","name","target","args","minArgs","maxArgs","Promise","fallbackToNoCallback","cbError","console","warn","noCallback","wrapMethod","method","wrapper","Proxy","apply","targetMethod","thisObj","call","hasOwnProperty","Function","bind","wrapObject","wrappers","cache","create","proxyTarget","prop","defineProperty","configurable","enumerable","desc","Reflect","deleteProperty","wrapEvent","wrapperMap","addListener","listener","hasListener","removeListener","onRequestFinishedWrappers","req","wrappedReq","getContent","onMessageWrappers","sender","sendResponse","wrappedSendResponse","result","didCallSendResponse","sendResponsePromise","response","err","isResultThenable","sendPromisedResult","msg","error","__mozWebExtensionPolyfillReject__","catch","wrappedSendMessageCallback","reply","wrappedSendMessage","apiNamespaceObj","wrappedCb","push","sendMessage","staticWrappers","devtools","network","onRequestFinished","onMessage","onMessageExternal","tabs","settingMetadata","clear","privacy","services","websites"],"sources":["browser-polyfill.js"],"sourcesContent":["/* webextension-polyfill - v0.10.0 - Fri Aug 12 2022 19:42:44 */\n/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */\n/* vim: set sts=2 sw=2 et tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\"use strict\";\n\nif (!globalThis.chrome?.runtime?.id) {\n throw new Error(\"This script should only be loaded in a browser extension.\");\n}\n\nif (typeof globalThis.browser === \"undefined\" || Object.getPrototypeOf(globalThis.browser) !== Object.prototype) {\n const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = \"The message port closed before a response was received.\";\n\n // Wrapping the bulk of this polyfill in a one-time-use function is a minor\n // optimization for Firefox. Since Spidermonkey does not fully parse the\n // contents of a function until the first time it's called, and since it will\n // never actually need to be called, this allows the polyfill to be included\n // in Firefox nearly for free.\n const wrapAPIs = extensionAPIs => {\n // NOTE: apiMetadata is associated to the content of the api-metadata.json file\n // at build time by replacing the following \"include\" with the content of the\n // JSON file.\n const apiMetadata = {\n \"alarms\": {\n \"clear\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"clearAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"bookmarks\": {\n \"create\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getChildren\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getRecent\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getSubTree\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getTree\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"move\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeTree\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"search\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n },\n \"browserAction\": {\n \"disable\": {\n \"minArgs\": 0,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"enable\": {\n \"minArgs\": 0,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"getBadgeBackgroundColor\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getBadgeText\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"openPopup\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"setBadgeBackgroundColor\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setBadgeText\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setIcon\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"setPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n }\n },\n \"browsingData\": {\n \"remove\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"removeCache\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeCookies\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeDownloads\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeFormData\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeHistory\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeLocalStorage\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removePasswords\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removePluginData\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"settings\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"commands\": {\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"contextMenus\": {\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n },\n \"cookies\": {\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAllCookieStores\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"set\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"devtools\": {\n \"inspectedWindow\": {\n \"eval\": {\n \"minArgs\": 1,\n \"maxArgs\": 2,\n \"singleCallbackArg\": false\n }\n },\n \"panels\": {\n \"create\": {\n \"minArgs\": 3,\n \"maxArgs\": 3,\n \"singleCallbackArg\": true\n },\n \"elements\": {\n \"createSidebarPane\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n }\n }\n },\n \"downloads\": {\n \"cancel\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"download\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"erase\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getFileIcon\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"open\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"pause\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeFile\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"resume\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"search\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"show\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n }\n },\n \"extension\": {\n \"isAllowedFileSchemeAccess\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"isAllowedIncognitoAccess\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"history\": {\n \"addUrl\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"deleteAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"deleteRange\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"deleteUrl\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getVisits\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"search\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"i18n\": {\n \"detectLanguage\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAcceptLanguages\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"identity\": {\n \"launchWebAuthFlow\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"idle\": {\n \"queryState\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"management\": {\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getSelf\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"setEnabled\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"uninstallSelf\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n }\n },\n \"notifications\": {\n \"clear\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"create\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getPermissionLevel\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n },\n \"pageAction\": {\n \"getPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"hide\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setIcon\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"setPopup\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"setTitle\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n },\n \"show\": {\n \"minArgs\": 1,\n \"maxArgs\": 1,\n \"fallbackToNoCallback\": true\n }\n },\n \"permissions\": {\n \"contains\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"request\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"runtime\": {\n \"getBackgroundPage\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getPlatformInfo\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"openOptionsPage\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"requestUpdateCheck\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"sendMessage\": {\n \"minArgs\": 1,\n \"maxArgs\": 3\n },\n \"sendNativeMessage\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"setUninstallURL\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"sessions\": {\n \"getDevices\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getRecentlyClosed\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"restore\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n }\n },\n \"storage\": {\n \"local\": {\n \"clear\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getBytesInUse\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"set\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"managed\": {\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getBytesInUse\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n }\n },\n \"sync\": {\n \"clear\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getBytesInUse\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"set\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n }\n },\n \"tabs\": {\n \"captureVisibleTab\": {\n \"minArgs\": 0,\n \"maxArgs\": 2\n },\n \"create\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"detectLanguage\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"discard\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"duplicate\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"executeScript\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getCurrent\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n },\n \"getZoom\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getZoomSettings\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"goBack\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"goForward\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"highlight\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"insertCSS\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"move\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n },\n \"query\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"reload\": {\n \"minArgs\": 0,\n \"maxArgs\": 2\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"removeCSS\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"sendMessage\": {\n \"minArgs\": 2,\n \"maxArgs\": 3\n },\n \"setZoom\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"setZoomSettings\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"update\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n }\n },\n \"topSites\": {\n \"get\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"webNavigation\": {\n \"getAllFrames\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"getFrame\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n }\n },\n \"webRequest\": {\n \"handlerBehaviorChanged\": {\n \"minArgs\": 0,\n \"maxArgs\": 0\n }\n },\n \"windows\": {\n \"create\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"get\": {\n \"minArgs\": 1,\n \"maxArgs\": 2\n },\n \"getAll\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getCurrent\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"getLastFocused\": {\n \"minArgs\": 0,\n \"maxArgs\": 1\n },\n \"remove\": {\n \"minArgs\": 1,\n \"maxArgs\": 1\n },\n \"update\": {\n \"minArgs\": 2,\n \"maxArgs\": 2\n }\n }\n };\n\n if (Object.keys(apiMetadata).length === 0) {\n throw new Error(\"api-metadata.json has not been included in browser-polyfill\");\n }\n\n /**\n * A WeakMap subclass which creates and stores a value for any key which does\n * not exist when accessed, but behaves exactly as an ordinary WeakMap\n * otherwise.\n *\n * @param {function} createItem\n * A function which will be called in order to create the value for any\n * key which does not exist, the first time it is accessed. The\n * function receives, as its only argument, the key being created.\n */\n class DefaultWeakMap extends WeakMap {\n constructor(createItem, items = undefined) {\n super(items);\n this.createItem = createItem;\n }\n\n get(key) {\n if (!this.has(key)) {\n this.set(key, this.createItem(key));\n }\n\n return super.get(key);\n }\n }\n\n /**\n * Returns true if the given object is an object with a `then` method, and can\n * therefore be assumed to behave as a Promise.\n *\n * @param {*} value The value to test.\n * @returns {boolean} True if the value is thenable.\n */\n const isThenable = value => {\n return value && typeof value === \"object\" && typeof value.then === \"function\";\n };\n\n /**\n * Creates and returns a function which, when called, will resolve or reject\n * the given promise based on how it is called:\n *\n * - If, when called, `chrome.runtime.lastError` contains a non-null object,\n * the promise is rejected with that value.\n * - If the function is called with exactly one argument, the promise is\n * resolved to that value.\n * - Otherwise, the promise is resolved to an array containing all of the\n * function's arguments.\n *\n * @param {object} promise\n * An object containing the resolution and rejection functions of a\n * promise.\n * @param {function} promise.resolve\n * The promise's resolution function.\n * @param {function} promise.reject\n * The promise's rejection function.\n * @param {object} metadata\n * Metadata about the wrapped method which has created the callback.\n * @param {boolean} metadata.singleCallbackArg\n * Whether or not the promise is resolved with only the first\n * argument of the callback, alternatively an array of all the\n * callback arguments is resolved. By default, if the callback\n * function is invoked with only a single argument, that will be\n * resolved to the promise, while all arguments will be resolved as\n * an array if multiple are given.\n *\n * @returns {function}\n * The generated callback function.\n */\n const makeCallback = (promise, metadata) => {\n return (...callbackArgs) => {\n if (extensionAPIs.runtime.lastError) {\n promise.reject(new Error(extensionAPIs.runtime.lastError.message));\n } else if (metadata.singleCallbackArg ||\n (callbackArgs.length <= 1 && metadata.singleCallbackArg !== false)) {\n promise.resolve(callbackArgs[0]);\n } else {\n promise.resolve(callbackArgs);\n }\n };\n };\n\n const pluralizeArguments = (numArgs) => numArgs == 1 ? \"argument\" : \"arguments\";\n\n /**\n * Creates a wrapper function for a method with the given name and metadata.\n *\n * @param {string} name\n * The name of the method which is being wrapped.\n * @param {object} metadata\n * Metadata about the method being wrapped.\n * @param {integer} metadata.minArgs\n * The minimum number of arguments which must be passed to the\n * function. If called with fewer than this number of arguments, the\n * wrapper will raise an exception.\n * @param {integer} metadata.maxArgs\n * The maximum number of arguments which may be passed to the\n * function. If called with more than this number of arguments, the\n * wrapper will raise an exception.\n * @param {boolean} metadata.singleCallbackArg\n * Whether or not the promise is resolved with only the first\n * argument of the callback, alternatively an array of all the\n * callback arguments is resolved. By default, if the callback\n * function is invoked with only a single argument, that will be\n * resolved to the promise, while all arguments will be resolved as\n * an array if multiple are given.\n *\n * @returns {function(object, ...*)}\n * The generated wrapper function.\n */\n const wrapAsyncFunction = (name, metadata) => {\n return function asyncFunctionWrapper(target, ...args) {\n if (args.length < metadata.minArgs) {\n throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);\n }\n\n if (args.length > metadata.maxArgs) {\n throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);\n }\n\n return new Promise((resolve, reject) => {\n if (metadata.fallbackToNoCallback) {\n // This API method has currently no callback on Chrome, but it return a promise on Firefox,\n // and so the polyfill will try to call it with a callback first, and it will fallback\n // to not passing the callback if the first call fails.\n try {\n target[name](...args, makeCallback({resolve, reject}, metadata));\n } catch (cbError) {\n console.warn(`${name} API method doesn't seem to support the callback parameter, ` +\n \"falling back to call it without a callback: \", cbError);\n\n target[name](...args);\n\n // Update the API method metadata, so that the next API calls will not try to\n // use the unsupported callback anymore.\n metadata.fallbackToNoCallback = false;\n metadata.noCallback = true;\n\n resolve();\n }\n } else if (metadata.noCallback) {\n target[name](...args);\n resolve();\n } else {\n target[name](...args, makeCallback({resolve, reject}, metadata));\n }\n });\n };\n };\n\n /**\n * Wraps an existing method of the target object, so that calls to it are\n * intercepted by the given wrapper function. The wrapper function receives,\n * as its first argument, the original `target` object, followed by each of\n * the arguments passed to the original method.\n *\n * @param {object} target\n * The original target object that the wrapped method belongs to.\n * @param {function} method\n * The method being wrapped. This is used as the target of the Proxy\n * object which is created to wrap the method.\n * @param {function} wrapper\n * The wrapper function which is called in place of a direct invocation\n * of the wrapped method.\n *\n * @returns {Proxy}\n * A Proxy object for the given method, which invokes the given wrapper\n * method in its place.\n */\n const wrapMethod = (target, method, wrapper) => {\n return new Proxy(method, {\n apply(targetMethod, thisObj, args) {\n return wrapper.call(thisObj, target, ...args);\n },\n });\n };\n\n let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);\n\n /**\n * Wraps an object in a Proxy which intercepts and wraps certain methods\n * based on the given `wrappers` and `metadata` objects.\n *\n * @param {object} target\n * The target object to wrap.\n *\n * @param {object} [wrappers = {}]\n * An object tree containing wrapper functions for special cases. Any\n * function present in this object tree is called in place of the\n * method in the same location in the `target` object tree. These\n * wrapper methods are invoked as described in {@see wrapMethod}.\n *\n * @param {object} [metadata = {}]\n * An object tree containing metadata used to automatically generate\n * Promise-based wrapper functions for asynchronous. Any function in\n * the `target` object tree which has a corresponding metadata object\n * in the same location in the `metadata` tree is replaced with an\n * automatically-generated wrapper function, as described in\n * {@see wrapAsyncFunction}\n *\n * @returns {Proxy}\n */\n const wrapObject = (target, wrappers = {}, metadata = {}) => {\n let cache = Object.create(null);\n let handlers = {\n has(proxyTarget, prop) {\n return prop in target || prop in cache;\n },\n\n get(proxyTarget, prop, receiver) {\n if (prop in cache) {\n return cache[prop];\n }\n\n if (!(prop in target)) {\n return undefined;\n }\n\n let value = target[prop];\n\n if (typeof value === \"function\") {\n // This is a method on the underlying object. Check if we need to do\n // any wrapping.\n\n if (typeof wrappers[prop] === \"function\") {\n // We have a special-case wrapper for this method.\n value = wrapMethod(target, target[prop], wrappers[prop]);\n } else if (hasOwnProperty(metadata, prop)) {\n // This is an async method that we have metadata for. Create a\n // Promise wrapper for it.\n let wrapper = wrapAsyncFunction(prop, metadata[prop]);\n value = wrapMethod(target, target[prop], wrapper);\n } else {\n // This is a method that we don't know or care about. Return the\n // original method, bound to the underlying object.\n value = value.bind(target);\n }\n } else if (typeof value === \"object\" && value !== null &&\n (hasOwnProperty(wrappers, prop) ||\n hasOwnProperty(metadata, prop))) {\n // This is an object that we need to do some wrapping for the children\n // of. Create a sub-object wrapper for it with the appropriate child\n // metadata.\n value = wrapObject(value, wrappers[prop], metadata[prop]);\n } else if (hasOwnProperty(metadata, \"*\")) {\n // Wrap all properties in * namespace.\n value = wrapObject(value, wrappers[prop], metadata[\"*\"]);\n } else {\n // We don't need to do any wrapping for this property,\n // so just forward all access to the underlying object.\n Object.defineProperty(cache, prop, {\n configurable: true,\n enumerable: true,\n get() {\n return target[prop];\n },\n set(value) {\n target[prop] = value;\n },\n });\n\n return value;\n }\n\n cache[prop] = value;\n return value;\n },\n\n set(proxyTarget, prop, value, receiver) {\n if (prop in cache) {\n cache[prop] = value;\n } else {\n target[prop] = value;\n }\n return true;\n },\n\n defineProperty(proxyTarget, prop, desc) {\n return Reflect.defineProperty(cache, prop, desc);\n },\n\n deleteProperty(proxyTarget, prop) {\n return Reflect.deleteProperty(cache, prop);\n },\n };\n\n // Per contract of the Proxy API, the \"get\" proxy handler must return the\n // original value of the target if that value is declared read-only and\n // non-configurable. For this reason, we create an object with the\n // prototype set to `target` instead of using `target` directly.\n // Otherwise we cannot return a custom object for APIs that\n // are declared read-only and non-configurable, such as `chrome.devtools`.\n //\n // The proxy handlers themselves will still use the original `target`\n // instead of the `proxyTarget`, so that the methods and properties are\n // dereferenced via the original targets.\n let proxyTarget = Object.create(target);\n return new Proxy(proxyTarget, handlers);\n };\n\n /**\n * Creates a set of wrapper functions for an event object, which handles\n * wrapping of listener functions that those messages are passed.\n *\n * A single wrapper is created for each listener function, and stored in a\n * map. Subsequent calls to `addListener`, `hasListener`, or `removeListener`\n * retrieve the original wrapper, so that attempts to remove a\n * previously-added listener work as expected.\n *\n * @param {DefaultWeakMap} wrapperMap\n * A DefaultWeakMap object which will create the appropriate wrapper\n * for a given listener function when one does not exist, and retrieve\n * an existing one when it does.\n *\n * @returns {object}\n */\n const wrapEvent = wrapperMap => ({\n addListener(target, listener, ...args) {\n target.addListener(wrapperMap.get(listener), ...args);\n },\n\n hasListener(target, listener) {\n return target.hasListener(wrapperMap.get(listener));\n },\n\n removeListener(target, listener) {\n target.removeListener(wrapperMap.get(listener));\n },\n });\n\n const onRequestFinishedWrappers = new DefaultWeakMap(listener => {\n if (typeof listener !== \"function\") {\n return listener;\n }\n\n /**\n * Wraps an onRequestFinished listener function so that it will return a\n * `getContent()` property which returns a `Promise` rather than using a\n * callback API.\n *\n * @param {object} req\n * The HAR entry object representing the network request.\n */\n return function onRequestFinished(req) {\n const wrappedReq = wrapObject(req, {} /* wrappers */, {\n getContent: {\n minArgs: 0,\n maxArgs: 0,\n },\n });\n listener(wrappedReq);\n };\n });\n\n const onMessageWrappers = new DefaultWeakMap(listener => {\n if (typeof listener !== \"function\") {\n return listener;\n }\n\n /**\n * Wraps a message listener function so that it may send responses based on\n * its return value, rather than by returning a sentinel value and calling a\n * callback. If the listener function returns a Promise, the response is\n * sent when the promise either resolves or rejects.\n *\n * @param {*} message\n * The message sent by the other end of the channel.\n * @param {object} sender\n * Details about the sender of the message.\n * @param {function(*)} sendResponse\n * A callback which, when called with an arbitrary argument, sends\n * that value as a response.\n * @returns {boolean}\n * True if the wrapped listener returned a Promise, which will later\n * yield a response. False otherwise.\n */\n return function onMessage(message, sender, sendResponse) {\n let didCallSendResponse = false;\n\n let wrappedSendResponse;\n let sendResponsePromise = new Promise(resolve => {\n wrappedSendResponse = function(response) {\n didCallSendResponse = true;\n resolve(response);\n };\n });\n\n let result;\n try {\n result = listener(message, sender, wrappedSendResponse);\n } catch (err) {\n result = Promise.reject(err);\n }\n\n const isResultThenable = result !== true && isThenable(result);\n\n // If the listener didn't returned true or a Promise, or called\n // wrappedSendResponse synchronously, we can exit earlier\n // because there will be no response sent from this listener.\n if (result !== true && !isResultThenable && !didCallSendResponse) {\n return false;\n }\n\n // A small helper to send the message if the promise resolves\n // and an error if the promise rejects (a wrapped sendMessage has\n // to translate the message into a resolved promise or a rejected\n // promise).\n const sendPromisedResult = (promise) => {\n promise.then(msg => {\n // send the message value.\n sendResponse(msg);\n }, error => {\n // Send a JSON representation of the error if the rejected value\n // is an instance of error, or the object itself otherwise.\n let message;\n if (error && (error instanceof Error ||\n typeof error.message === \"string\")) {\n message = error.message;\n } else {\n message = \"An unexpected error occurred\";\n }\n\n sendResponse({\n __mozWebExtensionPolyfillReject__: true,\n message,\n });\n }).catch(err => {\n // Print an error on the console if unable to send the response.\n console.error(\"Failed to send onMessage rejected reply\", err);\n });\n };\n\n // If the listener returned a Promise, send the resolved value as a\n // result, otherwise wait the promise related to the wrappedSendResponse\n // callback to resolve and send it as a response.\n if (isResultThenable) {\n sendPromisedResult(result);\n } else {\n sendPromisedResult(sendResponsePromise);\n }\n\n // Let Chrome know that the listener is replying.\n return true;\n };\n });\n\n const wrappedSendMessageCallback = ({reject, resolve}, reply) => {\n if (extensionAPIs.runtime.lastError) {\n // Detect when none of the listeners replied to the sendMessage call and resolve\n // the promise to undefined as in Firefox.\n // See https://github.com/mozilla/webextension-polyfill/issues/130\n if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {\n resolve();\n } else {\n reject(new Error(extensionAPIs.runtime.lastError.message));\n }\n } else if (reply && reply.__mozWebExtensionPolyfillReject__) {\n // Convert back the JSON representation of the error into\n // an Error instance.\n reject(new Error(reply.message));\n } else {\n resolve(reply);\n }\n };\n\n const wrappedSendMessage = (name, metadata, apiNamespaceObj, ...args) => {\n if (args.length < metadata.minArgs) {\n throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);\n }\n\n if (args.length > metadata.maxArgs) {\n throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);\n }\n\n return new Promise((resolve, reject) => {\n const wrappedCb = wrappedSendMessageCallback.bind(null, {resolve, reject});\n args.push(wrappedCb);\n apiNamespaceObj.sendMessage(...args);\n });\n };\n\n const staticWrappers = {\n devtools: {\n network: {\n onRequestFinished: wrapEvent(onRequestFinishedWrappers),\n },\n },\n runtime: {\n onMessage: wrapEvent(onMessageWrappers),\n onMessageExternal: wrapEvent(onMessageWrappers),\n sendMessage: wrappedSendMessage.bind(null, \"sendMessage\", {minArgs: 1, maxArgs: 3}),\n },\n tabs: {\n sendMessage: wrappedSendMessage.bind(null, \"sendMessage\", {minArgs: 2, maxArgs: 3}),\n },\n };\n const settingMetadata = {\n clear: {minArgs: 1, maxArgs: 1},\n get: {minArgs: 1, maxArgs: 1},\n set: {minArgs: 1, maxArgs: 1},\n };\n apiMetadata.privacy = {\n network: {\"*\": settingMetadata},\n services: {\"*\": settingMetadata},\n websites: {\"*\": settingMetadata},\n };\n\n return wrapObject(extensionAPIs, staticWrappers, apiMetadata);\n };\n\n // The build process adds a UMD wrapper around this file, which makes the\n // `module` variable available.\n module.exports = wrapAPIs(chrome);\n} else {\n module.exports = globalThis.browser;\n}\n"]} diff --git a/common.js b/common.js index dbde22e..3d49fc3 100644 --- a/common.js +++ b/common.js @@ -1,6 +1,6 @@ /* eslint-disable no-console */ /* eslint-disable no-unused-vars */ -/* global browser */ +/* global browser chrome */ function storePathComponents(storePath) { let path = 'secret/vaultPass'; @@ -17,3 +17,7 @@ function storePathComponents(storePath) { subPath: storeSubPath, }; } + +if (!browser.browserAction) { + browser.browserAction = chrome.browserAction ?? chrome.action; +} diff --git a/content.js b/content.js index 57879ca..68edc6a 100644 --- a/content.js +++ b/content.js @@ -51,6 +51,10 @@ function findUsernameNodeIn( 'input[id="userid"]', 'input[id="login"]', 'input[id="email"]', + 'textarea[id="username"]', + 'textarea[id="userid"]', + 'textarea[id="login"]', + 'textarea[id="email"]', '[type="email"]', '[name="user_name"]', '[name="user"]', @@ -73,7 +77,7 @@ function findUsernameNodeIn( let usernameNode = null; for (const node of allUsernameNodes) { - if (checkVisibility ? node.offsetParent : true) { + if (checkVisibility ? isVisible(node) : true) { usernameNode = node; break; } @@ -100,11 +104,30 @@ function fillIn(node, value) { node.blur(); } +function isVisible(node) { + if (!node.offsetParent) { + return false; + } + + if (node.style.display === 'none') { + return false; + } + + if (node.style.visibility === 'hidden') { + return false; + } + + const computedStyle = window.getComputedStyle(node); + const visibility = computedStyle.getPropertyValue('visibility'); + + return visibility !== 'hidden'; +} + function findPasswordInput() { // eslint-disable-next-line quotes const passwordNodes = document.querySelectorAll("input[type='password']"); for (const node of passwordNodes) { - if (node.offsetParent) return node; + if (isVisible(node)) return node; } return passwordNodes.length > 0 ? passwordNodes[0] : null; @@ -121,7 +144,7 @@ function handleFillCredits(request) { // Go completely crazy and wild guess any visible input field for the username if empty formNode // https://stackoverflow.com/a/21696585 const usernameNode = formNode - ? findUsernameNodeIn(formNode) + ? findUsernameNodeIn(formNode, true) : findUsernameNodeIn(document, true, request.isUserTriggered); if (!usernameNode) return; diff --git a/manifest.json b/manifest.json index 5912d1b..0f563b8 100644 --- a/manifest.json +++ b/manifest.json @@ -1,28 +1,28 @@ -{ - "manifest_version": 3, - "name": "VaultPass", - "description": "A Chrome extension to leverage Hashicorp Vault as Credential Storage for teams", - "version": "2.3.3", - "action": { - "default_icon": "icons/logo128.png", - "default_popup": "popup.html", - "default_title": "VaultPass" - }, - "icons": { - "48": "icons/logo48.png", - "128": "icons/logo128.png" - }, - "content_security_policy": { - "extension_pages": "script-src 'self'; object-src 'self'" - }, - "content_scripts": [ - { - "matches": [""], - "js": ["browser-polyfill.min.js", "content.js", "common.js"] - } - ], - "background": { - "service_worker": "background.js" - }, - "permissions": ["activeTab", "storage", "clipboardWrite"] -} +{ + "manifest_version": 3, + "name": "VaultPass", + "description": "A Chrome extension to leverage Hashicorp Vault as Credential Storage for teams", + "version": "2.3.3", + "action": { + "default_icon": "icons/logo128.png", + "default_popup": "popup.html", + "default_title": "VaultPass" + }, + "icons": { + "48": "icons/logo48.png", + "128": "icons/logo128.png" + }, + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'" + }, + "content_scripts": [ + { + "matches": [""], + "js": ["browser-polyfill.min.js", "content.js", "common.js"] + } + ], + "background": { + "service_worker": "background.js" + }, + "permissions": ["activeTab", "storage", "clipboardWrite", "idle"] +} diff --git a/manifestV2.json b/manifestV2.json index fd053d6..0f1e17d 100644 --- a/manifestV2.json +++ b/manifestV2.json @@ -1,38 +1,39 @@ -{ - "manifest_version": 2, - "name": "VaultPass", - "description": "A Chrome extension to leverage Hashicorp Vault as Credential Storage for teams", - "version": "2.3.3", - "browser_action": { - "default_icon": "icons/logo128.png", - "default_popup": "popup.html", - "default_title": "VaultPass" - }, - "icons": { - "48": "icons/logo48.png", - "128": "icons/logo128.png" - }, - "content_security_policy": "script-src 'self'; object-src 'self'", - "content_scripts": [ - { - "matches": [""], - "js": ["browser-polyfill.min.js", "content.js", "common.js"] - } - ], - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "permissions": [ - "activeTab", - "storage", - "clipboardWrite", - "http://*/*", - "https://*/*" - ], - "browser_specific_settings": { - "gecko": { - "id": "addon@blum.coffee" - } - } -} +{ + "manifest_version": 2, + "name": "VaultPass", + "description": "A Chrome extension to leverage Hashicorp Vault as Credential Storage for teams", + "version": "2.3.3", + "browser_action": { + "default_icon": "icons/logo128.png", + "default_popup": "popup.html", + "default_title": "VaultPass" + }, + "icons": { + "48": "icons/logo48.png", + "128": "icons/logo128.png" + }, + "content_security_policy": "script-src 'self'; object-src 'self'", + "content_scripts": [ + { + "matches": [""], + "js": ["browser-polyfill.min.js", "content.js", "common.js"] + } + ], + "background": { + "scripts": ["browser-polyfill.min.js", "background.js"], + "persistent": false + }, + "permissions": [ + "activeTab", + "storage", + "clipboardWrite", + "idle", + "http://*/*", + "https://*/*" + ], + "browser_specific_settings": { + "gecko": { + "id": "addon@blum.coffee" + } + } +} diff --git a/manifestV3.json b/manifestV3.json index 5912d1b..deb7708 100644 --- a/manifestV3.json +++ b/manifestV3.json @@ -24,5 +24,5 @@ "background": { "service_worker": "background.js" }, - "permissions": ["activeTab", "storage", "clipboardWrite"] + "permissions": ["activeTab", "storage", "clipboardWrite", "idle"] } diff --git a/options.js b/options.js index e7df53f..d8dabf2 100644 --- a/options.js +++ b/options.js @@ -80,11 +80,13 @@ async function querySecrets( } ); if (!fetchListOfSecretDirs.ok) { - const returnText = await fetchListOfSecretDirs.text(); - notify.error(`Fetching list of secret directories failed: ${returnText}`); - throw new Error( - `Fetching list of secret directories failed: ${returnText}` + const apiResponse = await fetchListOfSecretDirs.json(); + notify.error( + `Fetching secrets directories at "${storePath}" failed. ${apiResponse.errors.join( + '. ' + )}` ); + return; } let activeSecrets = (await browser.storage.sync.get('secrets')).secrets; @@ -104,6 +106,22 @@ async function logout() { document.getElementById('login').style.display = 'block'; document.getElementById('logout').style.display = 'none'; document.getElementById('secretList').innerHTML = ''; + + const vaultServerAddress = (await browser.storage.sync.get('vaultAddress')) + .vaultAddress; + const vaultToken = (await browser.storage.local.get('vaultToken')).vaultToken; + if (vaultToken) { + try { + await fetch(`${vaultServerAddress}/v1/auth/token/revoke-self`, { + method: 'POST', + 'X-Vault-Token': vaultToken, + 'Content-Type': 'application/json', + }); + } catch (err) { + notify.clear().error(err.message); + } + } + notify.clear().success('logged out', { time: 1000, removeOption: false }); await browser.storage.local.set({ vaultToken: null }); } @@ -204,7 +222,7 @@ async function authToVault( authMethod, storePath ) { - const loginToVault = await fetch( + const apiResponse = await fetch( `${vaultServer}/v1/auth/${authMethod}/login/${username}`, { method: 'POST', @@ -214,19 +232,34 @@ async function authToVault( body: JSON.stringify({ password: password }), } ); - if (!loginToVault.ok) { + if (!apiResponse.ok) { notify.error(` There was an error while calling
${vaultServer}/v1/auth/${authMethod}/login/${username}
- Please check if your username, password and mountpoints are correct. + Please check if your username, password and authentication method are correct. `); return; } - const authinfo = (await loginToVault.json()).auth; - const token = authinfo.client_token; + const authInfo = (await apiResponse.json()).auth; + const token = authInfo.client_token; await browser.storage.local.set({ vaultToken: token }); - await querySecrets(vaultServer, token, authinfo.policies, storePath); - // TODO: Use user token to generate app token with 20h validity - then use THAT token + await querySecrets(vaultServer, token, authInfo.policies, storePath); + + browser.runtime.sendMessage({ + type: 'auto_renew_token', + }); + + // If token expires in less than 24 hour, try to extend it to avoid having to re-logon too often + if (authInfo.lease_duration < 86400) { + await fetch(`${vaultServer}/v1/auth/token/renew-self`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Vault-Token': token, + }, + body: JSON.stringify({ increment: '24h' }), + }); + } } async function authButtonClick() { diff --git a/package-lock.json b/package-lock.json index f94dd46..bac229b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "webextension-polyfill": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.3.1.tgz", - "integrity": "sha512-ISB42vlgMyM7xE1u6pREeCqmmXjLsYu/nqAR8Dl/gIAnylb+KpRpvKbVkUYNFePhhXn0Obkkc3jasOII9ztUtg==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", + "integrity": "sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==", "dev": true } } diff --git a/package.json b/package.json index 50c781f..21f2a10 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,6 @@ }, "homepage": "https://github.com/mulbc/vaultPass#readme", "devDependencies": { - "webextension-polyfill": "^0.3.1" + "webextension-polyfill": "^0.10.0" } } diff --git a/popup.js b/popup.js index 169c47c..f83ae02 100644 --- a/popup.js +++ b/popup.js @@ -1,4 +1,5 @@ /* eslint-disable no-console */ +/* eslint-disable no-prototype-builtins */ /* global browser Notify storePathComponents */ const notify = new Notify(document.querySelector('#notify')); @@ -40,7 +41,7 @@ async function mainLoaded() { if (!secretList) { secretList = []; } - querySecrets(currentUrl, searchInput.value.length != 0); + await querySecrets(currentUrl, searchInput.value.length !== 0); } async function querySecrets(searchString, manualSearch) { @@ -70,12 +71,9 @@ async function querySecrets(searchString, manualSearch) { ); if (!secretsInPath.ok) { if (secretsInPath.status !== 404) { - notify.error( - `Token is not able to read ${secret}... Try re-login`, - { - removeOption: true, - } - ); + notify.error(`Unable to read ${secret}... Try re-login`, { + removeOption: true, + }); } return; } @@ -107,9 +105,12 @@ async function querySecrets(searchString, manualSearch) { await Promise.all(promises); if (matches > 0) { - browser.action.setBadgeText({ text: `${matches}`, tabId: currentTabId }); + browser.browserAction.setBadgeText({ + text: `${matches}`, + tabId: currentTabId, + }); } else { - browser.action.setBadgeText({ text: '', tabId: currentTabId }); + browser.browserAction.setBadgeText({ text: '', tabId: currentTabId }); if (!manualSearch) { notify.info('No matching key found for this page.', { removeOption: false, @@ -121,7 +122,7 @@ async function querySecrets(searchString, manualSearch) { } } } catch (err) { - browser.action.setBadgeText({ text: '', tabId: currentTabId }); + browser.browserAction.setBadgeText({ text: '', tabId: currentTabId }); notify.clear().error(err.message); } } @@ -146,15 +147,15 @@ function extractCredentialsSets(data) { username: data[key], password: data['password' + key.substring(8)], title: data.hasOwnProperty('title' + key.substring(8)) - ? data['title' + key.substring(8)] - : data.hasOwnProperty('title') - ? data['title'] - : '', + ? data['title' + key.substring(8)] + : data.hasOwnProperty('title') + ? data['title'] + : '', comment: data.hasOwnProperty('comment' + key.substring(8)) - ? data['comment' + key.substring(8)] - : data.hasOwnProperty('comment') - ? data['comment'] - : '', + ? data['comment' + key.substring(8)] + : data.hasOwnProperty('comment') + ? data['comment'] + : '', }); } }