21415 lines
1.3 MiB
21415 lines
1.3 MiB
/******/ (function() { // webpackBootstrap
|
||
/******/ var __webpack_modules__ = ({
|
||
|
||
/***/ 641:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var stringify=__webpack_require__(62520);var parse=__webpack_require__(46998);var formats=__webpack_require__(10681);module.exports={formats:formats,parse:parse,stringify:stringify};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 732:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./pow')} */module.exports=Math.pow;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 1697:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var call=Function.prototype.call;var $hasOwn=Object.prototype.hasOwnProperty;var bind=__webpack_require__(10539);/** @type {import('.')} */module.exports=bind.call(call,$hasOwn);
|
||
|
||
/***/ }),
|
||
|
||
/***/ 2301:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/* eslint no-invalid-this: 1 */var ERROR_MESSAGE='Function.prototype.bind called on incompatible ';var toStr=Object.prototype.toString;var max=Math.max;var funcType='[object Function]';var concatty=function concatty(a,b){var arr=[];for(var i=0;i<a.length;i+=1){arr[i]=a[i];}for(var j=0;j<b.length;j+=1){arr[j+a.length]=b[j];}return arr;};var slicy=function slicy(arrLike,offset){var arr=[];for(var i=offset||0,j=0;i<arrLike.length;i+=1,j+=1){arr[j]=arrLike[i];}return arr;};var joiny=function(arr,joiner){var str='';for(var i=0;i<arr.length;i+=1){str+=arr[i];if(i+1<arr.length){str+=joiner;}}return str;};module.exports=function bind(that){var target=this;if(typeof target!=='function'||toStr.apply(target)!==funcType){throw new TypeError(ERROR_MESSAGE+target);}var args=slicy(arguments,1);var bound;var binder=function(){if(this instanceof bound){var result=target.apply(this,concatty(args,arguments));if(Object(result)===result){return result;}return this;}return target.apply(that,concatty(args,arguments));};var boundLength=max(0,target.length-args.length);var boundArgs=[];for(var i=0;i<boundLength;i++){boundArgs[i]='$'+i;}bound=Function('binder','return function ('+joiny(boundArgs,',')+'){ return binder.apply(this,arguments); }')(binder);if(target.prototype){var Empty=function Empty(){};Empty.prototype=target.prototype;bound.prototype=new Empty();Empty.prototype=null;}return bound;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 4089:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./gOPD')} */module.exports=Object.getOwnPropertyDescriptor;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 5820:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./floor')} */module.exports=Math.floor;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 10539:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var implementation=__webpack_require__(2301);module.exports=Function.prototype.bind||implementation;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 10681:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
var replace=String.prototype.replace;var percentTwenties=/%20/g;var Format={RFC1738:'RFC1738',RFC3986:'RFC3986'};module.exports={'default':Format.RFC3986,formatters:{RFC1738:function(value){return replace.call(value,percentTwenties,'+');},RFC3986:function(value){return String(value);}},RFC1738:Format.RFC1738,RFC3986:Format.RFC3986};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 10818:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./round')} */module.exports=Math.round;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 10967:
|
||
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
/*
|
||
* Copyright Joyent, Inc. and other Node contributors.
|
||
*
|
||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
* copy of this software and associated documentation files (the
|
||
* "Software"), to deal in the Software without restriction, including
|
||
* without limitation the rights to use, copy, modify, merge, publish,
|
||
* distribute, sublicense, and/or sell copies of the Software, and to permit
|
||
* persons to whom the Software is furnished to do so, subject to the
|
||
* following conditions:
|
||
*
|
||
* The above copyright notice and this permission notice shall be included
|
||
* in all copies or substantial portions of the Software.
|
||
*
|
||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
*/var punycode=__webpack_require__(90791);function Url(){this.protocol=null;this.slashes=null;this.auth=null;this.host=null;this.port=null;this.hostname=null;this.hash=null;this.search=null;this.query=null;this.pathname=null;this.path=null;this.href=null;}// Reference: RFC 3986, RFC 1808, RFC 2396
|
||
/*
|
||
* define these here so at least they only have to be
|
||
* compiled once on the first module load.
|
||
*/var protocolPattern=/^([a-z0-9.+-]+:)/i,portPattern=/:[0-9]*$/,// Special case for a simple path URL
|
||
simplePathPattern=/^(\/\/?(?!\/)[^?\s]*)(\?[^\s]*)?$/,/*
|
||
* RFC 2396: characters reserved for delimiting URLs.
|
||
* We actually just auto-escape these.
|
||
*/delims=['<','>','"','`',' ','\r','\n','\t'],// RFC 2396: characters not allowed for various reasons.
|
||
unwise=['{','}','|','\\','^','`'].concat(delims),// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
||
autoEscape=['\''].concat(unwise),/*
|
||
* Characters that are never ever allowed in a hostname.
|
||
* Note that any invalid chars are also handled, but these
|
||
* are the ones that are *expected* to be seen, so we fast-path
|
||
* them.
|
||
*/nonHostChars=['%','/','?',';','#'].concat(autoEscape),hostEndingChars=['/','?','#'],hostnameMaxLen=255,hostnamePartPattern=/^[+a-z0-9A-Z_-]{0,63}$/,hostnamePartStart=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,// protocols that can allow "unsafe" and "unwise" chars.
|
||
unsafeProtocol={javascript:true,'javascript:':true},// protocols that never have a hostname.
|
||
hostlessProtocol={javascript:true,'javascript:':true},// protocols that always contain a // bit.
|
||
slashedProtocol={http:true,https:true,ftp:true,gopher:true,file:true,'http:':true,'https:':true,'ftp:':true,'gopher:':true,'file:':true},querystring=__webpack_require__(641);function urlParse(url,parseQueryString,slashesDenoteHost){if(url&&typeof url==='object'&&url instanceof Url){return url;}var u=new Url();u.parse(url,parseQueryString,slashesDenoteHost);return u;}Url.prototype.parse=function(url,parseQueryString,slashesDenoteHost){if(typeof url!=='string'){throw new TypeError("Parameter 'url' must be a string, not "+typeof url);}/*
|
||
* Copy chrome, IE, opera backslash-handling behavior.
|
||
* Back slashes before the query string get converted to forward slashes
|
||
* See: https://code.google.com/p/chromium/issues/detail?id=25916
|
||
*/var queryIndex=url.indexOf('?'),splitter=queryIndex!==-1&&queryIndex<url.indexOf('#')?'?':'#',uSplit=url.split(splitter),slashRegex=/\\/g;uSplit[0]=uSplit[0].replace(slashRegex,'/');url=uSplit.join(splitter);var rest=url;/*
|
||
* trim before proceeding.
|
||
* This is to support parse stuff like " http://foo.com \n"
|
||
*/rest=rest.trim();if(!slashesDenoteHost&&url.split('#').length===1){// Try fast path regexp
|
||
var simplePath=simplePathPattern.exec(rest);if(simplePath){this.path=rest;this.href=rest;this.pathname=simplePath[1];if(simplePath[2]){this.search=simplePath[2];if(parseQueryString){this.query=querystring.parse(this.search.substr(1));}else{this.query=this.search.substr(1);}}else if(parseQueryString){this.search='';this.query={};}return this;}}var proto=protocolPattern.exec(rest);if(proto){proto=proto[0];var lowerProto=proto.toLowerCase();this.protocol=lowerProto;rest=rest.substr(proto.length);}/*
|
||
* figure out if it's got a host
|
||
* user@server is *always* interpreted as a hostname, and url
|
||
* resolution will treat //foo/bar as host=foo,path=bar because that's
|
||
* how the browser resolves relative URLs.
|
||
*/if(slashesDenoteHost||proto||rest.match(/^\/\/[^@/]+@[^@/]+/)){var slashes=rest.substr(0,2)==='//';if(slashes&&!(proto&&hostlessProtocol[proto])){rest=rest.substr(2);this.slashes=true;}}if(!hostlessProtocol[proto]&&(slashes||proto&&!slashedProtocol[proto])){/*
|
||
* there's a hostname.
|
||
* the first instance of /, ?, ;, or # ends the host.
|
||
*
|
||
* If there is an @ in the hostname, then non-host chars *are* allowed
|
||
* to the left of the last @ sign, unless some host-ending character
|
||
* comes *before* the @-sign.
|
||
* URLs are obnoxious.
|
||
*
|
||
* ex:
|
||
* http://a@b@c/ => user:a@b host:c
|
||
* http://a@b?@c => user:a host:c path:/?@c
|
||
*//*
|
||
* v0.12 TODO(isaacs): This is not quite how Chrome does things.
|
||
* Review our test case against browsers more comprehensively.
|
||
*/// find the first instance of any hostEndingChars
|
||
var hostEnd=-1;for(var i=0;i<hostEndingChars.length;i++){var hec=rest.indexOf(hostEndingChars[i]);if(hec!==-1&&(hostEnd===-1||hec<hostEnd)){hostEnd=hec;}}/*
|
||
* at this point, either we have an explicit point where the
|
||
* auth portion cannot go past, or the last @ char is the decider.
|
||
*/var auth,atSign;if(hostEnd===-1){// atSign can be anywhere.
|
||
atSign=rest.lastIndexOf('@');}else{/*
|
||
* atSign must be in auth portion.
|
||
* http://a@b/c@d => host:b auth:a path:/c@d
|
||
*/atSign=rest.lastIndexOf('@',hostEnd);}/*
|
||
* Now we have a portion which is definitely the auth.
|
||
* Pull that off.
|
||
*/if(atSign!==-1){auth=rest.slice(0,atSign);rest=rest.slice(atSign+1);this.auth=decodeURIComponent(auth);}// the host is the remaining to the left of the first non-host char
|
||
hostEnd=-1;for(var i=0;i<nonHostChars.length;i++){var hec=rest.indexOf(nonHostChars[i]);if(hec!==-1&&(hostEnd===-1||hec<hostEnd)){hostEnd=hec;}}// if we still have not hit it, then the entire thing is a host.
|
||
if(hostEnd===-1){hostEnd=rest.length;}this.host=rest.slice(0,hostEnd);rest=rest.slice(hostEnd);// pull out port.
|
||
this.parseHost();/*
|
||
* we've indicated that there is a hostname,
|
||
* so even if it's empty, it has to be present.
|
||
*/this.hostname=this.hostname||'';/*
|
||
* if hostname begins with [ and ends with ]
|
||
* assume that it's an IPv6 address.
|
||
*/var ipv6Hostname=this.hostname[0]==='['&&this.hostname[this.hostname.length-1]===']';// validate a little.
|
||
if(!ipv6Hostname){var hostparts=this.hostname.split(/\./);for(var i=0,l=hostparts.length;i<l;i++){var part=hostparts[i];if(!part){continue;}if(!part.match(hostnamePartPattern)){var newpart='';for(var j=0,k=part.length;j<k;j++){if(part.charCodeAt(j)>127){/*
|
||
* we replace non-ASCII char with a temporary placeholder
|
||
* we need this to make sure size of hostname is not
|
||
* broken by replacing non-ASCII by nothing
|
||
*/newpart+='x';}else{newpart+=part[j];}}// we test again with ASCII char only
|
||
if(!newpart.match(hostnamePartPattern)){var validParts=hostparts.slice(0,i);var notHost=hostparts.slice(i+1);var bit=part.match(hostnamePartStart);if(bit){validParts.push(bit[1]);notHost.unshift(bit[2]);}if(notHost.length){rest='/'+notHost.join('.')+rest;}this.hostname=validParts.join('.');break;}}}}if(this.hostname.length>hostnameMaxLen){this.hostname='';}else{// hostnames are always lower case.
|
||
this.hostname=this.hostname.toLowerCase();}if(!ipv6Hostname){/*
|
||
* IDNA Support: Returns a punycoded representation of "domain".
|
||
* It only converts parts of the domain name that
|
||
* have non-ASCII characters, i.e. it doesn't matter if
|
||
* you call it with a domain that already is ASCII-only.
|
||
*/this.hostname=punycode.toASCII(this.hostname);}var p=this.port?':'+this.port:'';var h=this.hostname||'';this.host=h+p;this.href+=this.host;/*
|
||
* strip [ and ] from the hostname
|
||
* the host field still retains them, though
|
||
*/if(ipv6Hostname){this.hostname=this.hostname.substr(1,this.hostname.length-2);if(rest[0]!=='/'){rest='/'+rest;}}}/*
|
||
* now rest is set to the post-host stuff.
|
||
* chop off any delim chars.
|
||
*/if(!unsafeProtocol[lowerProto]){/*
|
||
* First, make 100% sure that any "autoEscape" chars get
|
||
* escaped, even if encodeURIComponent doesn't think they
|
||
* need to be.
|
||
*/for(var i=0,l=autoEscape.length;i<l;i++){var ae=autoEscape[i];if(rest.indexOf(ae)===-1){continue;}var esc=encodeURIComponent(ae);if(esc===ae){esc=escape(ae);}rest=rest.split(ae).join(esc);}}// chop off from the tail first.
|
||
var hash=rest.indexOf('#');if(hash!==-1){// got a fragment string.
|
||
this.hash=rest.substr(hash);rest=rest.slice(0,hash);}var qm=rest.indexOf('?');if(qm!==-1){this.search=rest.substr(qm);this.query=rest.substr(qm+1);if(parseQueryString){this.query=querystring.parse(this.query);}rest=rest.slice(0,qm);}else if(parseQueryString){// no query string, but parseQueryString still requested
|
||
this.search='';this.query={};}if(rest){this.pathname=rest;}if(slashedProtocol[lowerProto]&&this.hostname&&!this.pathname){this.pathname='/';}// to support http.request
|
||
if(this.pathname||this.search){var p=this.pathname||'';var s=this.search||'';this.path=p+s;}// finally, reconstruct the href based on what has been validated.
|
||
this.href=this.format();return this;};// format a parsed object into a url string
|
||
function urlFormat(obj){/*
|
||
* ensure it's an object, and not a string url.
|
||
* If it's an obj, this is a no-op.
|
||
* this way, you can call url_format() on strings
|
||
* to clean up potentially wonky urls.
|
||
*/if(typeof obj==='string'){obj=urlParse(obj);}if(!(obj instanceof Url)){return Url.prototype.format.call(obj);}return obj.format();}Url.prototype.format=function(){var auth=this.auth||'';if(auth){auth=encodeURIComponent(auth);auth=auth.replace(/%3A/i,':');auth+='@';}var protocol=this.protocol||'',pathname=this.pathname||'',hash=this.hash||'',host=false,query='';if(this.host){host=auth+this.host;}else if(this.hostname){host=auth+(this.hostname.indexOf(':')===-1?this.hostname:'['+this.hostname+']');if(this.port){host+=':'+this.port;}}if(this.query&&typeof this.query==='object'&&Object.keys(this.query).length){query=querystring.stringify(this.query,{arrayFormat:'repeat',addQueryPrefix:false});}var search=this.search||query&&'?'+query||'';if(protocol&&protocol.substr(-1)!==':'){protocol+=':';}/*
|
||
* only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
|
||
* unless they had them to begin with.
|
||
*/if(this.slashes||(!protocol||slashedProtocol[protocol])&&host!==false){host='//'+(host||'');if(pathname&&pathname.charAt(0)!=='/'){pathname='/'+pathname;}}else if(!host){host='';}if(hash&&hash.charAt(0)!=='#'){hash='#'+hash;}if(search&&search.charAt(0)!=='?'){search='?'+search;}pathname=pathname.replace(/[?#]/g,function(match){return encodeURIComponent(match);});search=search.replace('#','%23');return protocol+host+pathname+search+hash;};function urlResolve(source,relative){return urlParse(source,false,true).resolve(relative);}Url.prototype.resolve=function(relative){return this.resolveObject(urlParse(relative,false,true)).format();};function urlResolveObject(source,relative){if(!source){return relative;}return urlParse(source,false,true).resolveObject(relative);}Url.prototype.resolveObject=function(relative){if(typeof relative==='string'){var rel=new Url();rel.parse(relative,false,true);relative=rel;}var result=new Url();var tkeys=Object.keys(this);for(var tk=0;tk<tkeys.length;tk++){var tkey=tkeys[tk];result[tkey]=this[tkey];}/*
|
||
* hash is always overridden, no matter what.
|
||
* even href="" will remove it.
|
||
*/result.hash=relative.hash;// if the relative url is empty, then there's nothing left to do here.
|
||
if(relative.href===''){result.href=result.format();return result;}// hrefs like //foo/bar always cut to the protocol.
|
||
if(relative.slashes&&!relative.protocol){// take everything except the protocol from relative
|
||
var rkeys=Object.keys(relative);for(var rk=0;rk<rkeys.length;rk++){var rkey=rkeys[rk];if(rkey!=='protocol'){result[rkey]=relative[rkey];}}// urlParse appends trailing / to urls like http://www.example.com
|
||
if(slashedProtocol[result.protocol]&&result.hostname&&!result.pathname){result.pathname='/';result.path=result.pathname;}result.href=result.format();return result;}if(relative.protocol&&relative.protocol!==result.protocol){/*
|
||
* if it's a known url protocol, then changing
|
||
* the protocol does weird things
|
||
* first, if it's not file:, then we MUST have a host,
|
||
* and if there was a path
|
||
* to begin with, then we MUST have a path.
|
||
* if it is file:, then the host is dropped,
|
||
* because that's known to be hostless.
|
||
* anything else is assumed to be absolute.
|
||
*/if(!slashedProtocol[relative.protocol]){var keys=Object.keys(relative);for(var v=0;v<keys.length;v++){var k=keys[v];result[k]=relative[k];}result.href=result.format();return result;}result.protocol=relative.protocol;if(!relative.host&&!hostlessProtocol[relative.protocol]){var relPath=(relative.pathname||'').split('/');while(relPath.length&&!(relative.host=relPath.shift())){}if(!relative.host){relative.host='';}if(!relative.hostname){relative.hostname='';}if(relPath[0]!==''){relPath.unshift('');}if(relPath.length<2){relPath.unshift('');}result.pathname=relPath.join('/');}else{result.pathname=relative.pathname;}result.search=relative.search;result.query=relative.query;result.host=relative.host||'';result.auth=relative.auth;result.hostname=relative.hostname||relative.host;result.port=relative.port;// to support http.request
|
||
if(result.pathname||result.search){var p=result.pathname||'';var s=result.search||'';result.path=p+s;}result.slashes=result.slashes||relative.slashes;result.href=result.format();return result;}var isSourceAbs=result.pathname&&result.pathname.charAt(0)==='/',isRelAbs=relative.host||relative.pathname&&relative.pathname.charAt(0)==='/',mustEndAbs=isRelAbs||isSourceAbs||result.host&&relative.pathname,removeAllDots=mustEndAbs,srcPath=result.pathname&&result.pathname.split('/')||[],relPath=relative.pathname&&relative.pathname.split('/')||[],psychotic=result.protocol&&!slashedProtocol[result.protocol];/*
|
||
* if the url is a non-slashed url, then relative
|
||
* links like ../.. should be able
|
||
* to crawl up to the hostname, as well. This is strange.
|
||
* result.protocol has already been set by now.
|
||
* Later on, put the first path part into the host field.
|
||
*/if(psychotic){result.hostname='';result.port=null;if(result.host){if(srcPath[0]===''){srcPath[0]=result.host;}else{srcPath.unshift(result.host);}}result.host='';if(relative.protocol){relative.hostname=null;relative.port=null;if(relative.host){if(relPath[0]===''){relPath[0]=relative.host;}else{relPath.unshift(relative.host);}}relative.host=null;}mustEndAbs=mustEndAbs&&(relPath[0]===''||srcPath[0]==='');}if(isRelAbs){// it's absolute.
|
||
result.host=relative.host||relative.host===''?relative.host:result.host;result.hostname=relative.hostname||relative.hostname===''?relative.hostname:result.hostname;result.search=relative.search;result.query=relative.query;srcPath=relPath;// fall through to the dot-handling below.
|
||
}else if(relPath.length){/*
|
||
* it's relative
|
||
* throw away the existing file, and take the new path instead.
|
||
*/if(!srcPath){srcPath=[];}srcPath.pop();srcPath=srcPath.concat(relPath);result.search=relative.search;result.query=relative.query;}else if(relative.search!=null){/*
|
||
* just pull out the search.
|
||
* like href='?foo'.
|
||
* Put this after the other two cases because it simplifies the booleans
|
||
*/if(psychotic){result.host=srcPath.shift();result.hostname=result.host;/*
|
||
* occationaly the auth can get stuck only in host
|
||
* this especially happens in cases like
|
||
* url.resolveObject('mailto:local1@domain1', 'local2@domain2')
|
||
*/var authInHost=result.host&&result.host.indexOf('@')>0?result.host.split('@'):false;if(authInHost){result.auth=authInHost.shift();result.hostname=authInHost.shift();result.host=result.hostname;}}result.search=relative.search;result.query=relative.query;// to support http.request
|
||
if(result.pathname!==null||result.search!==null){result.path=(result.pathname?result.pathname:'')+(result.search?result.search:'');}result.href=result.format();return result;}if(!srcPath.length){/*
|
||
* no path at all. easy.
|
||
* we've already handled the other stuff above.
|
||
*/result.pathname=null;// to support http.request
|
||
if(result.search){result.path='/'+result.search;}else{result.path=null;}result.href=result.format();return result;}/*
|
||
* if a url ENDs in . or .., then it must get a trailing slash.
|
||
* however, if it ends in anything else non-slashy,
|
||
* then it must NOT get a trailing slash.
|
||
*/var last=srcPath.slice(-1)[0];var hasTrailingSlash=(result.host||relative.host||srcPath.length>1)&&(last==='.'||last==='..')||last==='';/*
|
||
* strip single dots, resolve double dots to parent dir
|
||
* if the path tries to go above the root, `up` ends up > 0
|
||
*/var up=0;for(var i=srcPath.length;i>=0;i--){last=srcPath[i];if(last==='.'){srcPath.splice(i,1);}else if(last==='..'){srcPath.splice(i,1);up++;}else if(up){srcPath.splice(i,1);up--;}}// if the path is allowed to go above the root, restore leading ..s
|
||
if(!mustEndAbs&&!removeAllDots){for(;up--;up){srcPath.unshift('..');}}if(mustEndAbs&&srcPath[0]!==''&&(!srcPath[0]||srcPath[0].charAt(0)!=='/')){srcPath.unshift('');}if(hasTrailingSlash&&srcPath.join('/').substr(-1)!=='/'){srcPath.push('');}var isAbsolute=srcPath[0]===''||srcPath[0]&&srcPath[0].charAt(0)==='/';// put the host back
|
||
if(psychotic){result.hostname=isAbsolute?'':srcPath.length?srcPath.shift():'';result.host=result.hostname;/*
|
||
* occationaly the auth can get stuck only in host
|
||
* this especially happens in cases like
|
||
* url.resolveObject('mailto:local1@domain1', 'local2@domain2')
|
||
*/var authInHost=result.host&&result.host.indexOf('@')>0?result.host.split('@'):false;if(authInHost){result.auth=authInHost.shift();result.hostname=authInHost.shift();result.host=result.hostname;}}mustEndAbs=mustEndAbs||result.host&&srcPath.length;if(mustEndAbs&&!isAbsolute){srcPath.unshift('');}if(srcPath.length>0){result.pathname=srcPath.join('/');}else{result.pathname=null;result.path=null;}// to support request.http
|
||
if(result.pathname!==null||result.search!==null){result.path=(result.pathname?result.pathname:'')+(result.search?result.search:'');}result.auth=relative.auth||result.auth;result.slashes=result.slashes||relative.slashes;result.href=result.format();return result;};Url.prototype.parseHost=function(){var host=this.host;var port=portPattern.exec(host);if(port){port=port[0];if(port!==':'){this.port=port.substr(1);}host=host.substr(0,host.length-port.length);}if(host){this.hostname=host;}};exports.parse=urlParse;exports.resolve=urlResolve;exports.resolveObject=urlResolveObject;exports.format=urlFormat;exports.Url=Url;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 12263:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var GetIntrinsic=__webpack_require__(35049);var callBound=__webpack_require__(95736);var inspect=__webpack_require__(73271);var $TypeError=__webpack_require__(93767);var $Map=GetIntrinsic('%Map%',true);/** @type {<K, V>(thisArg: Map<K, V>, key: K) => V} */var $mapGet=callBound('Map.prototype.get',true);/** @type {<K, V>(thisArg: Map<K, V>, key: K, value: V) => void} */var $mapSet=callBound('Map.prototype.set',true);/** @type {<K, V>(thisArg: Map<K, V>, key: K) => boolean} */var $mapHas=callBound('Map.prototype.has',true);/** @type {<K, V>(thisArg: Map<K, V>, key: K) => boolean} */var $mapDelete=callBound('Map.prototype.delete',true);/** @type {<K, V>(thisArg: Map<K, V>) => number} */var $mapSize=callBound('Map.prototype.size',true);/** @type {import('.')} */module.exports=!!$Map&&/** @type {Exclude<import('.'), false>} */function getSideChannelMap(){/** @typedef {ReturnType<typeof getSideChannelMap>} Channel *//** @typedef {Parameters<Channel['get']>[0]} K *//** @typedef {Parameters<Channel['set']>[1]} V *//** @type {Map<K, V> | undefined} */var $m;/** @type {Channel} */var channel={assert:function(key){if(!channel.has(key)){throw new $TypeError('Side channel does not contain '+inspect(key));}},'delete':function(key){if($m){var result=$mapDelete($m,key);if($mapSize($m)===0){$m=void undefined;}return result;}return false;},get:function(key){// eslint-disable-line consistent-return
|
||
if($m){return $mapGet($m,key);}},has:function(key){if($m){return $mapHas($m,key);}return false;},set:function(key,value){if(!$m){// @ts-expect-error TS can't handle narrowing a variable inside a closure
|
||
$m=new $Map();}$mapSet($m,key,value);}};// @ts-expect-error TODO: figure out why TS is erroring here
|
||
return channel;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 16019:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var origSymbol=typeof Symbol!=='undefined'&&Symbol;var hasSymbolSham=__webpack_require__(75985);/** @type {import('.')} */module.exports=function hasNativeSymbols(){if(typeof origSymbol!=='function'){return false;}if(typeof Symbol!=='function'){return false;}if(typeof origSymbol('foo')!=='symbol'){return false;}if(typeof Symbol('bar')!=='symbol'){return false;}return hasSymbolSham();};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 22060:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./Reflect.getPrototypeOf')} */module.exports=typeof Reflect!=='undefined'&&Reflect.getPrototypeOf||null;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 29382:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./range')} */module.exports=RangeError;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 29499:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var GetIntrinsic=__webpack_require__(35049);var callBound=__webpack_require__(95736);var inspect=__webpack_require__(73271);var getSideChannelMap=__webpack_require__(12263);var $TypeError=__webpack_require__(93767);var $WeakMap=GetIntrinsic('%WeakMap%',true);/** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K) => V} */var $weakMapGet=callBound('WeakMap.prototype.get',true);/** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K, value: V) => void} */var $weakMapSet=callBound('WeakMap.prototype.set',true);/** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K) => boolean} */var $weakMapHas=callBound('WeakMap.prototype.has',true);/** @type {<K extends object, V>(thisArg: WeakMap<K, V>, key: K) => boolean} */var $weakMapDelete=callBound('WeakMap.prototype.delete',true);/** @type {import('.')} */module.exports=$WeakMap?/** @type {Exclude<import('.'), false>} */function getSideChannelWeakMap(){/** @typedef {ReturnType<typeof getSideChannelWeakMap>} Channel *//** @typedef {Parameters<Channel['get']>[0]} K *//** @typedef {Parameters<Channel['set']>[1]} V *//** @type {WeakMap<K & object, V> | undefined} */var $wm;/** @type {Channel | undefined} */var $m;/** @type {Channel} */var channel={assert:function(key){if(!channel.has(key)){throw new $TypeError('Side channel does not contain '+inspect(key));}},'delete':function(key){if($WeakMap&&key&&(typeof key==='object'||typeof key==='function')){if($wm){return $weakMapDelete($wm,key);}}else if(getSideChannelMap){if($m){return $m['delete'](key);}}return false;},get:function(key){if($WeakMap&&key&&(typeof key==='object'||typeof key==='function')){if($wm){return $weakMapGet($wm,key);}}return $m&&$m.get(key);},has:function(key){if($WeakMap&&key&&(typeof key==='object'||typeof key==='function')){if($wm){return $weakMapHas($wm,key);}}return!!$m&&$m.has(key);},set:function(key,value){if($WeakMap&&key&&(typeof key==='object'||typeof key==='function')){if(!$wm){$wm=new $WeakMap();}$weakMapSet($wm,key,value);}else if(getSideChannelMap){if(!$m){$m=getSideChannelMap();}// eslint-disable-next-line no-extra-parens
|
||
/** @type {NonNullable<typeof $m>} */$m.set(key,value);}}};// @ts-expect-error TODO: figure out why this is erroring
|
||
return channel;}:getSideChannelMap;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 30708:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var callBind=__webpack_require__(77434);var gOPD=__webpack_require__(37391);var hasProtoAccessor;try{// eslint-disable-next-line no-extra-parens, no-proto
|
||
hasProtoAccessor=/** @type {{ __proto__?: typeof Array.prototype }} */[].__proto__===Array.prototype;}catch(e){if(!e||typeof e!=='object'||!('code'in e)||e.code!=='ERR_PROTO_ACCESS'){throw e;}}// eslint-disable-next-line no-extra-parens
|
||
var desc=!!hasProtoAccessor&&gOPD&&gOPD(Object.prototype,/** @type {keyof typeof Object.prototype} */'__proto__');var $Object=Object;var $getPrototypeOf=$Object.getPrototypeOf;/** @type {import('./get')} */module.exports=desc&&typeof desc.get==='function'?callBind([desc.get]):typeof $getPrototypeOf==='function'?/** @type {import('./get')} */function getDunder(value){// eslint-disable-next-line eqeqeq
|
||
return $getPrototypeOf(value==null?value:$Object(value));}:false;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 30816:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./syntax')} */module.exports=SyntaxError;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 31506:
|
||
/***/ (function(__unused_webpack_module, exports) {
|
||
|
||
"use strict";
|
||
exports.byteLength=byteLength;exports.toByteArray=toByteArray;exports.fromByteArray=fromByteArray;var lookup=[];var revLookup=[];var Arr=typeof Uint8Array!=='undefined'?Uint8Array:Array;var code='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';for(var i=0,len=code.length;i<len;++i){lookup[i]=code[i];revLookup[code.charCodeAt(i)]=i;}// Support decoding URL-safe base64 strings, as Node.js does.
|
||
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
|
||
revLookup['-'.charCodeAt(0)]=62;revLookup['_'.charCodeAt(0)]=63;function getLens(b64){var len=b64.length;if(len%4>0){throw new Error('Invalid string. Length must be a multiple of 4');}// Trim off extra bytes after placeholder bytes are found
|
||
// See: https://github.com/beatgammit/base64-js/issues/42
|
||
var validLen=b64.indexOf('=');if(validLen===-1)validLen=len;var placeHoldersLen=validLen===len?0:4-validLen%4;return[validLen,placeHoldersLen];}// base64 is 4/3 + up to two characters of the original data
|
||
function byteLength(b64){var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];return(validLen+placeHoldersLen)*3/4-placeHoldersLen;}function _byteLength(b64,validLen,placeHoldersLen){return(validLen+placeHoldersLen)*3/4-placeHoldersLen;}function toByteArray(b64){var tmp;var lens=getLens(b64);var validLen=lens[0];var placeHoldersLen=lens[1];var arr=new Arr(_byteLength(b64,validLen,placeHoldersLen));var curByte=0;// if there are placeholders, only get up to the last complete 4 chars
|
||
var len=placeHoldersLen>0?validLen-4:validLen;var i;for(i=0;i<len;i+=4){tmp=revLookup[b64.charCodeAt(i)]<<18|revLookup[b64.charCodeAt(i+1)]<<12|revLookup[b64.charCodeAt(i+2)]<<6|revLookup[b64.charCodeAt(i+3)];arr[curByte++]=tmp>>16&0xFF;arr[curByte++]=tmp>>8&0xFF;arr[curByte++]=tmp&0xFF;}if(placeHoldersLen===2){tmp=revLookup[b64.charCodeAt(i)]<<2|revLookup[b64.charCodeAt(i+1)]>>4;arr[curByte++]=tmp&0xFF;}if(placeHoldersLen===1){tmp=revLookup[b64.charCodeAt(i)]<<10|revLookup[b64.charCodeAt(i+1)]<<4|revLookup[b64.charCodeAt(i+2)]>>2;arr[curByte++]=tmp>>8&0xFF;arr[curByte++]=tmp&0xFF;}return arr;}function tripletToBase64(num){return lookup[num>>18&0x3F]+lookup[num>>12&0x3F]+lookup[num>>6&0x3F]+lookup[num&0x3F];}function encodeChunk(uint8,start,end){var tmp;var output=[];for(var i=start;i<end;i+=3){tmp=(uint8[i]<<16&0xFF0000)+(uint8[i+1]<<8&0xFF00)+(uint8[i+2]&0xFF);output.push(tripletToBase64(tmp));}return output.join('');}function fromByteArray(uint8){var tmp;var len=uint8.length;var extraBytes=len%3;// if we have 1 byte left, pad 2 bytes
|
||
var parts=[];var maxChunkLength=16383;// must be multiple of 3
|
||
// go through the array every three bytes, we'll deal with trailing stuff later
|
||
for(var i=0,len2=len-extraBytes;i<len2;i+=maxChunkLength){parts.push(encodeChunk(uint8,i,i+maxChunkLength>len2?len2:i+maxChunkLength));}// pad the end with zeros, but make sure to not forget the extra bytes
|
||
if(extraBytes===1){tmp=uint8[len-1];parts.push(lookup[tmp>>2]+lookup[tmp<<4&0x3F]+'==');}else if(extraBytes===2){tmp=(uint8[len-2]<<8)+uint8[len-1];parts.push(lookup[tmp>>10]+lookup[tmp>>4&0x3F]+lookup[tmp<<2&0x3F]+'=');}return parts.join('');}
|
||
|
||
/***/ }),
|
||
|
||
/***/ 32429:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./uri')} */module.exports=URIError;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 33556:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var $Object=__webpack_require__(85344);/** @type {import('./Object.getPrototypeOf')} */module.exports=$Object.getPrototypeOf||null;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 33968:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var reflectGetProto=__webpack_require__(22060);var originalGetProto=__webpack_require__(33556);var getDunderProto=__webpack_require__(30708);/** @type {import('.')} */module.exports=reflectGetProto?function getProto(O){// @ts-expect-error TS can't narrow inside a closure, for some reason
|
||
return reflectGetProto(O);}:originalGetProto?function getProto(O){if(!O||typeof O!=='object'&&typeof O!=='function'){throw new TypeError('getProto: not an object');}// @ts-expect-error TS can't narrow inside a closure, for some reason
|
||
return originalGetProto(O);}:getDunderProto?function getProto(O){// @ts-expect-error TS can't narrow inside a closure, for some reason
|
||
return getDunderProto(O);}:null;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 35049:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var undefined;var $Object=__webpack_require__(85344);var $Error=__webpack_require__(94067);var $EvalError=__webpack_require__(58809);var $RangeError=__webpack_require__(29382);var $ReferenceError=__webpack_require__(52166);var $SyntaxError=__webpack_require__(30816);var $TypeError=__webpack_require__(93767);var $URIError=__webpack_require__(32429);var abs=__webpack_require__(52126);var floor=__webpack_require__(5820);var max=__webpack_require__(73368);var min=__webpack_require__(60966);var pow=__webpack_require__(732);var round=__webpack_require__(10818);var sign=__webpack_require__(93425);var $Function=Function;// eslint-disable-next-line consistent-return
|
||
var getEvalledConstructor=function(expressionSyntax){try{return $Function('"use strict"; return ('+expressionSyntax+').constructor;')();}catch(e){}};var $gOPD=__webpack_require__(37391);var $defineProperty=__webpack_require__(85835);var throwTypeError=function(){throw new $TypeError();};var ThrowTypeError=$gOPD?function(){try{// eslint-disable-next-line no-unused-expressions, no-caller, no-restricted-properties
|
||
arguments.callee;// IE 8 does not throw here
|
||
return throwTypeError;}catch(calleeThrows){try{// IE 8 throws on Object.getOwnPropertyDescriptor(arguments, '')
|
||
return $gOPD(arguments,'callee').get;}catch(gOPDthrows){return throwTypeError;}}}():throwTypeError;var hasSymbols=__webpack_require__(16019)();var getProto=__webpack_require__(33968);var $ObjectGPO=__webpack_require__(33556);var $ReflectGPO=__webpack_require__(22060);var $apply=__webpack_require__(84750);var $call=__webpack_require__(51008);var needsEval={};var TypedArray=typeof Uint8Array==='undefined'||!getProto?undefined:getProto(Uint8Array);var INTRINSICS={__proto__:null,'%AggregateError%':typeof AggregateError==='undefined'?undefined:AggregateError,'%Array%':Array,'%ArrayBuffer%':typeof ArrayBuffer==='undefined'?undefined:ArrayBuffer,'%ArrayIteratorPrototype%':hasSymbols&&getProto?getProto([][Symbol.iterator]()):undefined,'%AsyncFromSyncIteratorPrototype%':undefined,'%AsyncFunction%':needsEval,'%AsyncGenerator%':needsEval,'%AsyncGeneratorFunction%':needsEval,'%AsyncIteratorPrototype%':needsEval,'%Atomics%':typeof Atomics==='undefined'?undefined:Atomics,'%BigInt%':typeof BigInt==='undefined'?undefined:BigInt,'%BigInt64Array%':typeof BigInt64Array==='undefined'?undefined:BigInt64Array,'%BigUint64Array%':typeof BigUint64Array==='undefined'?undefined:BigUint64Array,'%Boolean%':Boolean,'%DataView%':typeof DataView==='undefined'?undefined:DataView,'%Date%':Date,'%decodeURI%':decodeURI,'%decodeURIComponent%':decodeURIComponent,'%encodeURI%':encodeURI,'%encodeURIComponent%':encodeURIComponent,'%Error%':$Error,'%eval%':eval,// eslint-disable-line no-eval
|
||
'%EvalError%':$EvalError,'%Float16Array%':typeof Float16Array==='undefined'?undefined:Float16Array,'%Float32Array%':typeof Float32Array==='undefined'?undefined:Float32Array,'%Float64Array%':typeof Float64Array==='undefined'?undefined:Float64Array,'%FinalizationRegistry%':typeof FinalizationRegistry==='undefined'?undefined:FinalizationRegistry,'%Function%':$Function,'%GeneratorFunction%':needsEval,'%Int8Array%':typeof Int8Array==='undefined'?undefined:Int8Array,'%Int16Array%':typeof Int16Array==='undefined'?undefined:Int16Array,'%Int32Array%':typeof Int32Array==='undefined'?undefined:Int32Array,'%isFinite%':isFinite,'%isNaN%':isNaN,'%IteratorPrototype%':hasSymbols&&getProto?getProto(getProto([][Symbol.iterator]())):undefined,'%JSON%':typeof JSON==='object'?JSON:undefined,'%Map%':typeof Map==='undefined'?undefined:Map,'%MapIteratorPrototype%':typeof Map==='undefined'||!hasSymbols||!getProto?undefined:getProto(new Map()[Symbol.iterator]()),'%Math%':Math,'%Number%':Number,'%Object%':$Object,'%Object.getOwnPropertyDescriptor%':$gOPD,'%parseFloat%':parseFloat,'%parseInt%':parseInt,'%Promise%':typeof Promise==='undefined'?undefined:Promise,'%Proxy%':typeof Proxy==='undefined'?undefined:Proxy,'%RangeError%':$RangeError,'%ReferenceError%':$ReferenceError,'%Reflect%':typeof Reflect==='undefined'?undefined:Reflect,'%RegExp%':RegExp,'%Set%':typeof Set==='undefined'?undefined:Set,'%SetIteratorPrototype%':typeof Set==='undefined'||!hasSymbols||!getProto?undefined:getProto(new Set()[Symbol.iterator]()),'%SharedArrayBuffer%':typeof SharedArrayBuffer==='undefined'?undefined:SharedArrayBuffer,'%String%':String,'%StringIteratorPrototype%':hasSymbols&&getProto?getProto(''[Symbol.iterator]()):undefined,'%Symbol%':hasSymbols?Symbol:undefined,'%SyntaxError%':$SyntaxError,'%ThrowTypeError%':ThrowTypeError,'%TypedArray%':TypedArray,'%TypeError%':$TypeError,'%Uint8Array%':typeof Uint8Array==='undefined'?undefined:Uint8Array,'%Uint8ClampedArray%':typeof Uint8ClampedArray==='undefined'?undefined:Uint8ClampedArray,'%Uint16Array%':typeof Uint16Array==='undefined'?undefined:Uint16Array,'%Uint32Array%':typeof Uint32Array==='undefined'?undefined:Uint32Array,'%URIError%':$URIError,'%WeakMap%':typeof WeakMap==='undefined'?undefined:WeakMap,'%WeakRef%':typeof WeakRef==='undefined'?undefined:WeakRef,'%WeakSet%':typeof WeakSet==='undefined'?undefined:WeakSet,'%Function.prototype.call%':$call,'%Function.prototype.apply%':$apply,'%Object.defineProperty%':$defineProperty,'%Object.getPrototypeOf%':$ObjectGPO,'%Math.abs%':abs,'%Math.floor%':floor,'%Math.max%':max,'%Math.min%':min,'%Math.pow%':pow,'%Math.round%':round,'%Math.sign%':sign,'%Reflect.getPrototypeOf%':$ReflectGPO};if(getProto){try{null.error;// eslint-disable-line no-unused-expressions
|
||
}catch(e){// https://github.com/tc39/proposal-shadowrealm/pull/384#issuecomment-1364264229
|
||
var errorProto=getProto(getProto(e));INTRINSICS['%Error.prototype%']=errorProto;}}var doEval=function doEval(name){var value;if(name==='%AsyncFunction%'){value=getEvalledConstructor('async function () {}');}else if(name==='%GeneratorFunction%'){value=getEvalledConstructor('function* () {}');}else if(name==='%AsyncGeneratorFunction%'){value=getEvalledConstructor('async function* () {}');}else if(name==='%AsyncGenerator%'){var fn=doEval('%AsyncGeneratorFunction%');if(fn){value=fn.prototype;}}else if(name==='%AsyncIteratorPrototype%'){var gen=doEval('%AsyncGenerator%');if(gen&&getProto){value=getProto(gen.prototype);}}INTRINSICS[name]=value;return value;};var LEGACY_ALIASES={__proto__:null,'%ArrayBufferPrototype%':['ArrayBuffer','prototype'],'%ArrayPrototype%':['Array','prototype'],'%ArrayProto_entries%':['Array','prototype','entries'],'%ArrayProto_forEach%':['Array','prototype','forEach'],'%ArrayProto_keys%':['Array','prototype','keys'],'%ArrayProto_values%':['Array','prototype','values'],'%AsyncFunctionPrototype%':['AsyncFunction','prototype'],'%AsyncGenerator%':['AsyncGeneratorFunction','prototype'],'%AsyncGeneratorPrototype%':['AsyncGeneratorFunction','prototype','prototype'],'%BooleanPrototype%':['Boolean','prototype'],'%DataViewPrototype%':['DataView','prototype'],'%DatePrototype%':['Date','prototype'],'%ErrorPrototype%':['Error','prototype'],'%EvalErrorPrototype%':['EvalError','prototype'],'%Float32ArrayPrototype%':['Float32Array','prototype'],'%Float64ArrayPrototype%':['Float64Array','prototype'],'%FunctionPrototype%':['Function','prototype'],'%Generator%':['GeneratorFunction','prototype'],'%GeneratorPrototype%':['GeneratorFunction','prototype','prototype'],'%Int8ArrayPrototype%':['Int8Array','prototype'],'%Int16ArrayPrototype%':['Int16Array','prototype'],'%Int32ArrayPrototype%':['Int32Array','prototype'],'%JSONParse%':['JSON','parse'],'%JSONStringify%':['JSON','stringify'],'%MapPrototype%':['Map','prototype'],'%NumberPrototype%':['Number','prototype'],'%ObjectPrototype%':['Object','prototype'],'%ObjProto_toString%':['Object','prototype','toString'],'%ObjProto_valueOf%':['Object','prototype','valueOf'],'%PromisePrototype%':['Promise','prototype'],'%PromiseProto_then%':['Promise','prototype','then'],'%Promise_all%':['Promise','all'],'%Promise_reject%':['Promise','reject'],'%Promise_resolve%':['Promise','resolve'],'%RangeErrorPrototype%':['RangeError','prototype'],'%ReferenceErrorPrototype%':['ReferenceError','prototype'],'%RegExpPrototype%':['RegExp','prototype'],'%SetPrototype%':['Set','prototype'],'%SharedArrayBufferPrototype%':['SharedArrayBuffer','prototype'],'%StringPrototype%':['String','prototype'],'%SymbolPrototype%':['Symbol','prototype'],'%SyntaxErrorPrototype%':['SyntaxError','prototype'],'%TypedArrayPrototype%':['TypedArray','prototype'],'%TypeErrorPrototype%':['TypeError','prototype'],'%Uint8ArrayPrototype%':['Uint8Array','prototype'],'%Uint8ClampedArrayPrototype%':['Uint8ClampedArray','prototype'],'%Uint16ArrayPrototype%':['Uint16Array','prototype'],'%Uint32ArrayPrototype%':['Uint32Array','prototype'],'%URIErrorPrototype%':['URIError','prototype'],'%WeakMapPrototype%':['WeakMap','prototype'],'%WeakSetPrototype%':['WeakSet','prototype']};var bind=__webpack_require__(10539);var hasOwn=__webpack_require__(1697);var $concat=bind.call($call,Array.prototype.concat);var $spliceApply=bind.call($apply,Array.prototype.splice);var $replace=bind.call($call,String.prototype.replace);var $strSlice=bind.call($call,String.prototype.slice);var $exec=bind.call($call,RegExp.prototype.exec);/* adapted from https://github.com/lodash/lodash/blob/4.17.15/dist/lodash.js#L6735-L6744 */var rePropName=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;var reEscapeChar=/\\(\\)?/g;/** Used to match backslashes in property paths. */var stringToPath=function stringToPath(string){var first=$strSlice(string,0,1);var last=$strSlice(string,-1);if(first==='%'&&last!=='%'){throw new $SyntaxError('invalid intrinsic syntax, expected closing `%`');}else if(last==='%'&&first!=='%'){throw new $SyntaxError('invalid intrinsic syntax, expected opening `%`');}var result=[];$replace(string,rePropName,function(match,number,quote,subString){result[result.length]=quote?$replace(subString,reEscapeChar,'$1'):number||match;});return result;};/* end adaptation */var getBaseIntrinsic=function getBaseIntrinsic(name,allowMissing){var intrinsicName=name;var alias;if(hasOwn(LEGACY_ALIASES,intrinsicName)){alias=LEGACY_ALIASES[intrinsicName];intrinsicName='%'+alias[0]+'%';}if(hasOwn(INTRINSICS,intrinsicName)){var value=INTRINSICS[intrinsicName];if(value===needsEval){value=doEval(intrinsicName);}if(typeof value==='undefined'&&!allowMissing){throw new $TypeError('intrinsic '+name+' exists, but is not available. Please file an issue!');}return{alias:alias,name:intrinsicName,value:value};}throw new $SyntaxError('intrinsic '+name+' does not exist!');};module.exports=function GetIntrinsic(name,allowMissing){if(typeof name!=='string'||name.length===0){throw new $TypeError('intrinsic name must be a non-empty string');}if(arguments.length>1&&typeof allowMissing!=='boolean'){throw new $TypeError('"allowMissing" argument must be a boolean');}if($exec(/^%?[^%]*%?$/,name)===null){throw new $SyntaxError('`%` may not be present anywhere but at the beginning and end of the intrinsic name');}var parts=stringToPath(name);var intrinsicBaseName=parts.length>0?parts[0]:'';var intrinsic=getBaseIntrinsic('%'+intrinsicBaseName+'%',allowMissing);var intrinsicRealName=intrinsic.name;var value=intrinsic.value;var skipFurtherCaching=false;var alias=intrinsic.alias;if(alias){intrinsicBaseName=alias[0];$spliceApply(parts,$concat([0,1],alias));}for(var i=1,isOwn=true;i<parts.length;i+=1){var part=parts[i];var first=$strSlice(part,0,1);var last=$strSlice(part,-1);if((first==='"'||first==="'"||first==='`'||last==='"'||last==="'"||last==='`')&&first!==last){throw new $SyntaxError('property names with quotes must have matching quotes');}if(part==='constructor'||!isOwn){skipFurtherCaching=true;}intrinsicBaseName+='.'+part;intrinsicRealName='%'+intrinsicBaseName+'%';if(hasOwn(INTRINSICS,intrinsicRealName)){value=INTRINSICS[intrinsicRealName];}else if(value!=null){if(!(part in value)){if(!allowMissing){throw new $TypeError('base intrinsic for '+name+' exists, but the property is not available.');}return void undefined;}if($gOPD&&i+1>=parts.length){var desc=$gOPD(value,part);isOwn=!!desc;// By convention, when a data property is converted to an accessor
|
||
// property to emulate a data property that does not suffer from
|
||
// the override mistake, that accessor's getter is marked with
|
||
// an `originalValue` property. Here, when we detect this, we
|
||
// uphold the illusion by pretending to see that original data
|
||
// property, i.e., returning the value rather than the getter
|
||
// itself.
|
||
if(isOwn&&'get'in desc&&!('originalValue'in desc.get)){value=desc.get;}else{value=value[part];}}else{isOwn=hasOwn(value,part);value=value[part];}if(isOwn&&!skipFurtherCaching){INTRINSICS[intrinsicRealName]=value;}}}return value;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 37391:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
/** @type {import('.')} */var $gOPD=__webpack_require__(4089);if($gOPD){try{$gOPD([],'length');}catch(e){// IE 8 has a broken gOPD
|
||
$gOPD=null;}}module.exports=$gOPD;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 45202:
|
||
/***/ (function(module) {
|
||
|
||
// shim for using process in browser
|
||
var process=module.exports={};// cached from whatever global is present so that test runners that stub it
|
||
// don't break things. But we need to wrap it in a try catch in case it is
|
||
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
||
// function because try/catches deoptimize in certain engines.
|
||
var cachedSetTimeout;var cachedClearTimeout;function defaultSetTimout(){throw new Error('setTimeout has not been defined');}function defaultClearTimeout(){throw new Error('clearTimeout has not been defined');}(function(){try{if(typeof setTimeout==='function'){cachedSetTimeout=setTimeout;}else{cachedSetTimeout=defaultSetTimout;}}catch(e){cachedSetTimeout=defaultSetTimout;}try{if(typeof clearTimeout==='function'){cachedClearTimeout=clearTimeout;}else{cachedClearTimeout=defaultClearTimeout;}}catch(e){cachedClearTimeout=defaultClearTimeout;}})();function runTimeout(fun){if(cachedSetTimeout===setTimeout){//normal enviroments in sane situations
|
||
return setTimeout(fun,0);}// if setTimeout wasn't available but was latter defined
|
||
if((cachedSetTimeout===defaultSetTimout||!cachedSetTimeout)&&setTimeout){cachedSetTimeout=setTimeout;return setTimeout(fun,0);}try{// when when somebody has screwed with setTimeout but no I.E. maddness
|
||
return cachedSetTimeout(fun,0);}catch(e){try{// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
||
return cachedSetTimeout.call(null,fun,0);}catch(e){// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
|
||
return cachedSetTimeout.call(this,fun,0);}}}function runClearTimeout(marker){if(cachedClearTimeout===clearTimeout){//normal enviroments in sane situations
|
||
return clearTimeout(marker);}// if clearTimeout wasn't available but was latter defined
|
||
if((cachedClearTimeout===defaultClearTimeout||!cachedClearTimeout)&&clearTimeout){cachedClearTimeout=clearTimeout;return clearTimeout(marker);}try{// when when somebody has screwed with setTimeout but no I.E. maddness
|
||
return cachedClearTimeout(marker);}catch(e){try{// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
||
return cachedClearTimeout.call(null,marker);}catch(e){// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
|
||
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
|
||
return cachedClearTimeout.call(this,marker);}}}var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){if(!draining||!currentQueue){return;}draining=false;if(currentQueue.length){queue=currentQueue.concat(queue);}else{queueIndex=-1;}if(queue.length){drainQueue();}}function drainQueue(){if(draining){return;}var timeout=runTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){if(currentQueue){currentQueue[queueIndex].run();}}queueIndex=-1;len=queue.length;}currentQueue=null;draining=false;runClearTimeout(timeout);}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i];}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){runTimeout(drainQueue);}};// v8 likes predictible objects
|
||
function Item(fun,array){this.fun=fun;this.array=array;}Item.prototype.run=function(){this.fun.apply(null,this.array);};process.title='browser';process.browser=true;process.env={};process.argv=[];process.version='';// empty string to avoid regexp issues
|
||
process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.prependListener=noop;process.prependOnceListener=noop;process.listeners=function(name){return[];};process.binding=function(name){throw new Error('process.binding is not supported');};process.cwd=function(){return'/';};process.chdir=function(dir){throw new Error('process.chdir is not supported');};process.umask=function(){return 0;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 46998:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var utils=__webpack_require__(92972);var has=Object.prototype.hasOwnProperty;var isArray=Array.isArray;var defaults={allowDots:false,allowEmptyArrays:false,allowPrototypes:false,allowSparse:false,arrayLimit:20,charset:'utf-8',charsetSentinel:false,comma:false,decodeDotInKeys:false,decoder:utils.decode,delimiter:'&',depth:5,duplicates:'combine',ignoreQueryPrefix:false,interpretNumericEntities:false,parameterLimit:1000,parseArrays:true,plainObjects:false,strictDepth:false,strictNullHandling:false,throwOnLimitExceeded:false};var interpretNumericEntities=function(str){return str.replace(/&#(\d+);/g,function($0,numberStr){return String.fromCharCode(parseInt(numberStr,10));});};var parseArrayValue=function(val,options,currentArrayLength){if(val&&typeof val==='string'&&options.comma&&val.indexOf(',')>-1){return val.split(',');}if(options.throwOnLimitExceeded&¤tArrayLength>=options.arrayLimit){throw new RangeError('Array limit exceeded. Only '+options.arrayLimit+' element'+(options.arrayLimit===1?'':'s')+' allowed in an array.');}return val;};// This is what browsers will submit when the ✓ character occurs in an
|
||
// application/x-www-form-urlencoded body and the encoding of the page containing
|
||
// the form is iso-8859-1, or when the submitted form has an accept-charset
|
||
// attribute of iso-8859-1. Presumably also with other charsets that do not contain
|
||
// the ✓ character, such as us-ascii.
|
||
var isoSentinel='utf8=%26%2310003%3B';// encodeURIComponent('✓')
|
||
// These are the percent-encoded utf-8 octets representing a checkmark, indicating that the request actually is utf-8 encoded.
|
||
var charsetSentinel='utf8=%E2%9C%93';// encodeURIComponent('✓')
|
||
var parseValues=function parseQueryStringValues(str,options){var obj={__proto__:null};var cleanStr=options.ignoreQueryPrefix?str.replace(/^\?/,''):str;cleanStr=cleanStr.replace(/%5B/gi,'[').replace(/%5D/gi,']');var limit=options.parameterLimit===Infinity?undefined:options.parameterLimit;var parts=cleanStr.split(options.delimiter,options.throwOnLimitExceeded?limit+1:limit);if(options.throwOnLimitExceeded&&parts.length>limit){throw new RangeError('Parameter limit exceeded. Only '+limit+' parameter'+(limit===1?'':'s')+' allowed.');}var skipIndex=-1;// Keep track of where the utf8 sentinel was found
|
||
var i;var charset=options.charset;if(options.charsetSentinel){for(i=0;i<parts.length;++i){if(parts[i].indexOf('utf8=')===0){if(parts[i]===charsetSentinel){charset='utf-8';}else if(parts[i]===isoSentinel){charset='iso-8859-1';}skipIndex=i;i=parts.length;// The eslint settings do not allow break;
|
||
}}}for(i=0;i<parts.length;++i){if(i===skipIndex){continue;}var part=parts[i];var bracketEqualsPos=part.indexOf(']=');var pos=bracketEqualsPos===-1?part.indexOf('='):bracketEqualsPos+1;var key;var val;if(pos===-1){key=options.decoder(part,defaults.decoder,charset,'key');val=options.strictNullHandling?null:'';}else{key=options.decoder(part.slice(0,pos),defaults.decoder,charset,'key');val=utils.maybeMap(parseArrayValue(part.slice(pos+1),options,isArray(obj[key])?obj[key].length:0),function(encodedVal){return options.decoder(encodedVal,defaults.decoder,charset,'value');});}if(val&&options.interpretNumericEntities&&charset==='iso-8859-1'){val=interpretNumericEntities(String(val));}if(part.indexOf('[]=')>-1){val=isArray(val)?[val]:val;}var existing=has.call(obj,key);if(existing&&options.duplicates==='combine'){obj[key]=utils.combine(obj[key],val);}else if(!existing||options.duplicates==='last'){obj[key]=val;}}return obj;};var parseObject=function(chain,val,options,valuesParsed){var currentArrayLength=0;if(chain.length>0&&chain[chain.length-1]==='[]'){var parentKey=chain.slice(0,-1).join('');currentArrayLength=Array.isArray(val)&&val[parentKey]?val[parentKey].length:0;}var leaf=valuesParsed?val:parseArrayValue(val,options,currentArrayLength);for(var i=chain.length-1;i>=0;--i){var obj;var root=chain[i];if(root==='[]'&&options.parseArrays){obj=options.allowEmptyArrays&&(leaf===''||options.strictNullHandling&&leaf===null)?[]:utils.combine([],leaf);}else{obj=options.plainObjects?{__proto__:null}:{};var cleanRoot=root.charAt(0)==='['&&root.charAt(root.length-1)===']'?root.slice(1,-1):root;var decodedRoot=options.decodeDotInKeys?cleanRoot.replace(/%2E/g,'.'):cleanRoot;var index=parseInt(decodedRoot,10);if(!options.parseArrays&&decodedRoot===''){obj={0:leaf};}else if(!isNaN(index)&&root!==decodedRoot&&String(index)===decodedRoot&&index>=0&&options.parseArrays&&index<=options.arrayLimit){obj=[];obj[index]=leaf;}else if(decodedRoot!=='__proto__'){obj[decodedRoot]=leaf;}}leaf=obj;}return leaf;};var parseKeys=function parseQueryStringKeys(givenKey,val,options,valuesParsed){if(!givenKey){return;}// Transform dot notation to bracket notation
|
||
var key=options.allowDots?givenKey.replace(/\.([^.[]+)/g,'[$1]'):givenKey;// The regex chunks
|
||
var brackets=/(\[[^[\]]*])/;var child=/(\[[^[\]]*])/g;// Get the parent
|
||
var segment=options.depth>0&&brackets.exec(key);var parent=segment?key.slice(0,segment.index):key;// Stash the parent if it exists
|
||
var keys=[];if(parent){// If we aren't using plain objects, optionally prefix keys that would overwrite object prototype properties
|
||
if(!options.plainObjects&&has.call(Object.prototype,parent)){if(!options.allowPrototypes){return;}}keys.push(parent);}// Loop through children appending to the array until we hit depth
|
||
var i=0;while(options.depth>0&&(segment=child.exec(key))!==null&&i<options.depth){i+=1;if(!options.plainObjects&&has.call(Object.prototype,segment[1].slice(1,-1))){if(!options.allowPrototypes){return;}}keys.push(segment[1]);}// If there's a remainder, check strictDepth option for throw, else just add whatever is left
|
||
if(segment){if(options.strictDepth===true){throw new RangeError('Input depth exceeded depth option of '+options.depth+' and strictDepth is true');}keys.push('['+key.slice(segment.index)+']');}return parseObject(keys,val,options,valuesParsed);};var normalizeParseOptions=function normalizeParseOptions(opts){if(!opts){return defaults;}if(typeof opts.allowEmptyArrays!=='undefined'&&typeof opts.allowEmptyArrays!=='boolean'){throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');}if(typeof opts.decodeDotInKeys!=='undefined'&&typeof opts.decodeDotInKeys!=='boolean'){throw new TypeError('`decodeDotInKeys` option can only be `true` or `false`, when provided');}if(opts.decoder!==null&&typeof opts.decoder!=='undefined'&&typeof opts.decoder!=='function'){throw new TypeError('Decoder has to be a function.');}if(typeof opts.charset!=='undefined'&&opts.charset!=='utf-8'&&opts.charset!=='iso-8859-1'){throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');}if(typeof opts.throwOnLimitExceeded!=='undefined'&&typeof opts.throwOnLimitExceeded!=='boolean'){throw new TypeError('`throwOnLimitExceeded` option must be a boolean');}var charset=typeof opts.charset==='undefined'?defaults.charset:opts.charset;var duplicates=typeof opts.duplicates==='undefined'?defaults.duplicates:opts.duplicates;if(duplicates!=='combine'&&duplicates!=='first'&&duplicates!=='last'){throw new TypeError('The duplicates option must be either combine, first, or last');}var allowDots=typeof opts.allowDots==='undefined'?opts.decodeDotInKeys===true?true:defaults.allowDots:!!opts.allowDots;return{allowDots:allowDots,allowEmptyArrays:typeof opts.allowEmptyArrays==='boolean'?!!opts.allowEmptyArrays:defaults.allowEmptyArrays,allowPrototypes:typeof opts.allowPrototypes==='boolean'?opts.allowPrototypes:defaults.allowPrototypes,allowSparse:typeof opts.allowSparse==='boolean'?opts.allowSparse:defaults.allowSparse,arrayLimit:typeof opts.arrayLimit==='number'?opts.arrayLimit:defaults.arrayLimit,charset:charset,charsetSentinel:typeof opts.charsetSentinel==='boolean'?opts.charsetSentinel:defaults.charsetSentinel,comma:typeof opts.comma==='boolean'?opts.comma:defaults.comma,decodeDotInKeys:typeof opts.decodeDotInKeys==='boolean'?opts.decodeDotInKeys:defaults.decodeDotInKeys,decoder:typeof opts.decoder==='function'?opts.decoder:defaults.decoder,delimiter:typeof opts.delimiter==='string'||utils.isRegExp(opts.delimiter)?opts.delimiter:defaults.delimiter,// eslint-disable-next-line no-implicit-coercion, no-extra-parens
|
||
depth:typeof opts.depth==='number'||opts.depth===false?+opts.depth:defaults.depth,duplicates:duplicates,ignoreQueryPrefix:opts.ignoreQueryPrefix===true,interpretNumericEntities:typeof opts.interpretNumericEntities==='boolean'?opts.interpretNumericEntities:defaults.interpretNumericEntities,parameterLimit:typeof opts.parameterLimit==='number'?opts.parameterLimit:defaults.parameterLimit,parseArrays:opts.parseArrays!==false,plainObjects:typeof opts.plainObjects==='boolean'?opts.plainObjects:defaults.plainObjects,strictDepth:typeof opts.strictDepth==='boolean'?!!opts.strictDepth:defaults.strictDepth,strictNullHandling:typeof opts.strictNullHandling==='boolean'?opts.strictNullHandling:defaults.strictNullHandling,throwOnLimitExceeded:typeof opts.throwOnLimitExceeded==='boolean'?opts.throwOnLimitExceeded:false};};module.exports=function(str,opts){var options=normalizeParseOptions(opts);if(str===''||str===null||typeof str==='undefined'){return options.plainObjects?{__proto__:null}:{};}var tempObj=typeof str==='string'?parseValues(str,options):str;var obj=options.plainObjects?{__proto__:null}:{};// Iterate over the keys and setup the new object
|
||
var keys=Object.keys(tempObj);for(var i=0;i<keys.length;++i){var key=keys[i];var newObj=parseKeys(key,tempObj[key],options,typeof str==='string');obj=utils.merge(obj,newObj,options);}if(options.allowSparse===true){return obj;}return utils.compact(obj);};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 51008:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./functionCall')} */module.exports=Function.prototype.call;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 52126:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./abs')} */module.exports=Math.abs;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 52166:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./ref')} */module.exports=ReferenceError;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 58803:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
/* provided dependency */ var process = __webpack_require__(45202);
|
||
// 'path' module extracted from Node.js v8.11.1 (only the posix part)
|
||
// transplited with Babel
|
||
// Copyright Joyent, Inc. and other Node contributors.
|
||
//
|
||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||
// copy of this software and associated documentation files (the
|
||
// "Software"), to deal in the Software without restriction, including
|
||
// without limitation the rights to use, copy, modify, merge, publish,
|
||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||
// persons to whom the Software is furnished to do so, subject to the
|
||
// following conditions:
|
||
//
|
||
// The above copyright notice and this permission notice shall be included
|
||
// in all copies or substantial portions of the Software.
|
||
//
|
||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
function assertPath(path){if(typeof path!=='string'){throw new TypeError('Path must be a string. Received '+JSON.stringify(path));}}// Resolves . and .. elements in a path with directory names
|
||
function normalizeStringPosix(path,allowAboveRoot){var res='';var lastSegmentLength=0;var lastSlash=-1;var dots=0;var code;for(var i=0;i<=path.length;++i){if(i<path.length)code=path.charCodeAt(i);else if(code===47/*/*/)break;else code=47/*/*/;if(code===47/*/*/){if(lastSlash===i-1||dots===1){// NOOP
|
||
}else if(lastSlash!==i-1&&dots===2){if(res.length<2||lastSegmentLength!==2||res.charCodeAt(res.length-1)!==46/*.*/||res.charCodeAt(res.length-2)!==46/*.*/){if(res.length>2){var lastSlashIndex=res.lastIndexOf('/');if(lastSlashIndex!==res.length-1){if(lastSlashIndex===-1){res='';lastSegmentLength=0;}else{res=res.slice(0,lastSlashIndex);lastSegmentLength=res.length-1-res.lastIndexOf('/');}lastSlash=i;dots=0;continue;}}else if(res.length===2||res.length===1){res='';lastSegmentLength=0;lastSlash=i;dots=0;continue;}}if(allowAboveRoot){if(res.length>0)res+='/..';else res='..';lastSegmentLength=2;}}else{if(res.length>0)res+='/'+path.slice(lastSlash+1,i);else res=path.slice(lastSlash+1,i);lastSegmentLength=i-lastSlash-1;}lastSlash=i;dots=0;}else if(code===46/*.*/&&dots!==-1){++dots;}else{dots=-1;}}return res;}function _format(sep,pathObject){var dir=pathObject.dir||pathObject.root;var base=pathObject.base||(pathObject.name||'')+(pathObject.ext||'');if(!dir){return base;}if(dir===pathObject.root){return dir+base;}return dir+sep+base;}var posix={// path.resolve([from ...], to)
|
||
resolve:function resolve(){var resolvedPath='';var resolvedAbsolute=false;var cwd;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path;if(i>=0)path=arguments[i];else{if(cwd===undefined)cwd=process.cwd();path=cwd;}assertPath(path);// Skip empty entries
|
||
if(path.length===0){continue;}resolvedPath=path+'/'+resolvedPath;resolvedAbsolute=path.charCodeAt(0)===47/*/*/;}// At this point the path should be resolved to a full absolute path, but
|
||
// handle relative paths to be safe (might happen when process.cwd() fails)
|
||
// Normalize the path
|
||
resolvedPath=normalizeStringPosix(resolvedPath,!resolvedAbsolute);if(resolvedAbsolute){if(resolvedPath.length>0)return'/'+resolvedPath;else return'/';}else if(resolvedPath.length>0){return resolvedPath;}else{return'.';}},normalize:function normalize(path){assertPath(path);if(path.length===0)return'.';var isAbsolute=path.charCodeAt(0)===47/*/*/;var trailingSeparator=path.charCodeAt(path.length-1)===47/*/*/;// Normalize the path
|
||
path=normalizeStringPosix(path,!isAbsolute);if(path.length===0&&!isAbsolute)path='.';if(path.length>0&&trailingSeparator)path+='/';if(isAbsolute)return'/'+path;return path;},isAbsolute:function isAbsolute(path){assertPath(path);return path.length>0&&path.charCodeAt(0)===47/*/*/;},join:function join(){if(arguments.length===0)return'.';var joined;for(var i=0;i<arguments.length;++i){var arg=arguments[i];assertPath(arg);if(arg.length>0){if(joined===undefined)joined=arg;else joined+='/'+arg;}}if(joined===undefined)return'.';return posix.normalize(joined);},relative:function relative(from,to){assertPath(from);assertPath(to);if(from===to)return'';from=posix.resolve(from);to=posix.resolve(to);if(from===to)return'';// Trim any leading backslashes
|
||
var fromStart=1;for(;fromStart<from.length;++fromStart){if(from.charCodeAt(fromStart)!==47/*/*/)break;}var fromEnd=from.length;var fromLen=fromEnd-fromStart;// Trim any leading backslashes
|
||
var toStart=1;for(;toStart<to.length;++toStart){if(to.charCodeAt(toStart)!==47/*/*/)break;}var toEnd=to.length;var toLen=toEnd-toStart;// Compare paths to find the longest common path from root
|
||
var length=fromLen<toLen?fromLen:toLen;var lastCommonSep=-1;var i=0;for(;i<=length;++i){if(i===length){if(toLen>length){if(to.charCodeAt(toStart+i)===47/*/*/){// We get here if `from` is the exact base path for `to`.
|
||
// For example: from='/foo/bar'; to='/foo/bar/baz'
|
||
return to.slice(toStart+i+1);}else if(i===0){// We get here if `from` is the root
|
||
// For example: from='/'; to='/foo'
|
||
return to.slice(toStart+i);}}else if(fromLen>length){if(from.charCodeAt(fromStart+i)===47/*/*/){// We get here if `to` is the exact base path for `from`.
|
||
// For example: from='/foo/bar/baz'; to='/foo/bar'
|
||
lastCommonSep=i;}else if(i===0){// We get here if `to` is the root.
|
||
// For example: from='/foo'; to='/'
|
||
lastCommonSep=0;}}break;}var fromCode=from.charCodeAt(fromStart+i);var toCode=to.charCodeAt(toStart+i);if(fromCode!==toCode)break;else if(fromCode===47/*/*/)lastCommonSep=i;}var out='';// Generate the relative path based on the path difference between `to`
|
||
// and `from`
|
||
for(i=fromStart+lastCommonSep+1;i<=fromEnd;++i){if(i===fromEnd||from.charCodeAt(i)===47/*/*/){if(out.length===0)out+='..';else out+='/..';}}// Lastly, append the rest of the destination (`to`) path that comes after
|
||
// the common path parts
|
||
if(out.length>0)return out+to.slice(toStart+lastCommonSep);else{toStart+=lastCommonSep;if(to.charCodeAt(toStart)===47/*/*/)++toStart;return to.slice(toStart);}},_makeLong:function _makeLong(path){return path;},dirname:function dirname(path){assertPath(path);if(path.length===0)return'.';var code=path.charCodeAt(0);var hasRoot=code===47/*/*/;var end=-1;var matchedSlash=true;for(var i=path.length-1;i>=1;--i){code=path.charCodeAt(i);if(code===47/*/*/){if(!matchedSlash){end=i;break;}}else{// We saw the first non-path separator
|
||
matchedSlash=false;}}if(end===-1)return hasRoot?'/':'.';if(hasRoot&&end===1)return'//';return path.slice(0,end);},basename:function basename(path,ext){if(ext!==undefined&&typeof ext!=='string')throw new TypeError('"ext" argument must be a string');assertPath(path);var start=0;var end=-1;var matchedSlash=true;var i;if(ext!==undefined&&ext.length>0&&ext.length<=path.length){if(ext.length===path.length&&ext===path)return'';var extIdx=ext.length-1;var firstNonSlashEnd=-1;for(i=path.length-1;i>=0;--i){var code=path.charCodeAt(i);if(code===47/*/*/){// If we reached a path separator that was not part of a set of path
|
||
// separators at the end of the string, stop now
|
||
if(!matchedSlash){start=i+1;break;}}else{if(firstNonSlashEnd===-1){// We saw the first non-path separator, remember this index in case
|
||
// we need it if the extension ends up not matching
|
||
matchedSlash=false;firstNonSlashEnd=i+1;}if(extIdx>=0){// Try to match the explicit extension
|
||
if(code===ext.charCodeAt(extIdx)){if(--extIdx===-1){// We matched the extension, so mark this as the end of our path
|
||
// component
|
||
end=i;}}else{// Extension does not match, so our result is the entire path
|
||
// component
|
||
extIdx=-1;end=firstNonSlashEnd;}}}}if(start===end)end=firstNonSlashEnd;else if(end===-1)end=path.length;return path.slice(start,end);}else{for(i=path.length-1;i>=0;--i){if(path.charCodeAt(i)===47/*/*/){// If we reached a path separator that was not part of a set of path
|
||
// separators at the end of the string, stop now
|
||
if(!matchedSlash){start=i+1;break;}}else if(end===-1){// We saw the first non-path separator, mark this as the end of our
|
||
// path component
|
||
matchedSlash=false;end=i+1;}}if(end===-1)return'';return path.slice(start,end);}},extname:function extname(path){assertPath(path);var startDot=-1;var startPart=0;var end=-1;var matchedSlash=true;// Track the state of characters (if any) we see before our first dot and
|
||
// after any path separator we find
|
||
var preDotState=0;for(var i=path.length-1;i>=0;--i){var code=path.charCodeAt(i);if(code===47/*/*/){// If we reached a path separator that was not part of a set of path
|
||
// separators at the end of the string, stop now
|
||
if(!matchedSlash){startPart=i+1;break;}continue;}if(end===-1){// We saw the first non-path separator, mark this as the end of our
|
||
// extension
|
||
matchedSlash=false;end=i+1;}if(code===46/*.*/){// If this is our first dot, mark it as the start of our extension
|
||
if(startDot===-1)startDot=i;else if(preDotState!==1)preDotState=1;}else if(startDot!==-1){// We saw a non-dot and non-path separator before our dot, so we should
|
||
// have a good chance at having a non-empty extension
|
||
preDotState=-1;}}if(startDot===-1||end===-1||// We saw a non-dot character immediately before the dot
|
||
preDotState===0||// The (right-most) trimmed path component is exactly '..'
|
||
preDotState===1&&startDot===end-1&&startDot===startPart+1){return'';}return path.slice(startDot,end);},format:function format(pathObject){if(pathObject===null||typeof pathObject!=='object'){throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof pathObject);}return _format('/',pathObject);},parse:function parse(path){assertPath(path);var ret={root:'',dir:'',base:'',ext:'',name:''};if(path.length===0)return ret;var code=path.charCodeAt(0);var isAbsolute=code===47/*/*/;var start;if(isAbsolute){ret.root='/';start=1;}else{start=0;}var startDot=-1;var startPart=0;var end=-1;var matchedSlash=true;var i=path.length-1;// Track the state of characters (if any) we see before our first dot and
|
||
// after any path separator we find
|
||
var preDotState=0;// Get non-dir info
|
||
for(;i>=start;--i){code=path.charCodeAt(i);if(code===47/*/*/){// If we reached a path separator that was not part of a set of path
|
||
// separators at the end of the string, stop now
|
||
if(!matchedSlash){startPart=i+1;break;}continue;}if(end===-1){// We saw the first non-path separator, mark this as the end of our
|
||
// extension
|
||
matchedSlash=false;end=i+1;}if(code===46/*.*/){// If this is our first dot, mark it as the start of our extension
|
||
if(startDot===-1)startDot=i;else if(preDotState!==1)preDotState=1;}else if(startDot!==-1){// We saw a non-dot and non-path separator before our dot, so we should
|
||
// have a good chance at having a non-empty extension
|
||
preDotState=-1;}}if(startDot===-1||end===-1||// We saw a non-dot character immediately before the dot
|
||
preDotState===0||// The (right-most) trimmed path component is exactly '..'
|
||
preDotState===1&&startDot===end-1&&startDot===startPart+1){if(end!==-1){if(startPart===0&&isAbsolute)ret.base=ret.name=path.slice(1,end);else ret.base=ret.name=path.slice(startPart,end);}}else{if(startPart===0&&isAbsolute){ret.name=path.slice(1,startDot);ret.base=path.slice(1,end);}else{ret.name=path.slice(startPart,startDot);ret.base=path.slice(startPart,end);}ret.ext=path.slice(startDot,end);}if(startPart>0)ret.dir=path.slice(0,startPart-1);else if(isAbsolute)ret.dir='/';return ret;},sep:'/',delimiter:':',win32:null,posix:null};posix.posix=posix;module.exports=posix;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 58809:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./eval')} */module.exports=EvalError;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 60271:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var inspect=__webpack_require__(73271);var $TypeError=__webpack_require__(93767);/*
|
||
* This function traverses the list returning the node corresponding to the given key.
|
||
*
|
||
* That node is also moved to the head of the list, so that if it's accessed again we don't need to traverse the whole list.
|
||
* By doing so, all the recently used nodes can be accessed relatively quickly.
|
||
*//** @type {import('./list.d.ts').listGetNode} */// eslint-disable-next-line consistent-return
|
||
var listGetNode=function(list,key,isDelete){/** @type {typeof list | NonNullable<(typeof list)['next']>} */var prev=list;/** @type {(typeof list)['next']} */var curr;// eslint-disable-next-line eqeqeq
|
||
for(;(curr=prev.next)!=null;prev=curr){if(curr.key===key){prev.next=curr.next;if(!isDelete){// eslint-disable-next-line no-extra-parens
|
||
curr.next=/** @type {NonNullable<typeof list.next>} */list.next;list.next=curr;// eslint-disable-line no-param-reassign
|
||
}return curr;}}};/** @type {import('./list.d.ts').listGet} */var listGet=function(objects,key){if(!objects){return void undefined;}var node=listGetNode(objects,key);return node&&node.value;};/** @type {import('./list.d.ts').listSet} */var listSet=function(objects,key,value){var node=listGetNode(objects,key);if(node){node.value=value;}else{// Prepend the new node to the beginning of the list
|
||
objects.next=/** @type {import('./list.d.ts').ListNode<typeof value, typeof key>} */{// eslint-disable-line no-param-reassign, no-extra-parens
|
||
key:key,next:objects.next,value:value};}};/** @type {import('./list.d.ts').listHas} */var listHas=function(objects,key){if(!objects){return false;}return!!listGetNode(objects,key);};/** @type {import('./list.d.ts').listDelete} */// eslint-disable-next-line consistent-return
|
||
var listDelete=function(objects,key){if(objects){return listGetNode(objects,key,true);}};/** @type {import('.')} */module.exports=function getSideChannelList(){/** @typedef {ReturnType<typeof getSideChannelList>} Channel *//** @typedef {Parameters<Channel['get']>[0]} K *//** @typedef {Parameters<Channel['set']>[1]} V *//** @type {import('./list.d.ts').RootNode<V, K> | undefined} */var $o;/** @type {Channel} */var channel={assert:function(key){if(!channel.has(key)){throw new $TypeError('Side channel does not contain '+inspect(key));}},'delete':function(key){var root=$o&&$o.next;var deletedNode=listDelete($o,key);if(deletedNode&&root&&root===deletedNode){$o=void undefined;}return!!deletedNode;},get:function(key){return listGet($o,key);},has:function(key){return listHas($o,key);},set:function(key,value){if(!$o){// Initialize the linked list as an empty node, so that we don't have to special-case handling of the first node: we can always refer to it as (previous node).next, instead of something like (list).head
|
||
$o={next:void undefined};}// eslint-disable-next-line no-extra-parens
|
||
listSet(/** @type {NonNullable<typeof $o>} */$o,key,value);}};// @ts-expect-error TODO: figure out why this is erroring
|
||
return channel;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 60966:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./min')} */module.exports=Math.min;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 62520:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var getSideChannel=__webpack_require__(67124);var utils=__webpack_require__(92972);var formats=__webpack_require__(10681);var has=Object.prototype.hasOwnProperty;var arrayPrefixGenerators={brackets:function brackets(prefix){return prefix+'[]';},comma:'comma',indices:function indices(prefix,key){return prefix+'['+key+']';},repeat:function repeat(prefix){return prefix;}};var isArray=Array.isArray;var push=Array.prototype.push;var pushToArray=function(arr,valueOrArray){push.apply(arr,isArray(valueOrArray)?valueOrArray:[valueOrArray]);};var toISO=Date.prototype.toISOString;var defaultFormat=formats['default'];var defaults={addQueryPrefix:false,allowDots:false,allowEmptyArrays:false,arrayFormat:'indices',charset:'utf-8',charsetSentinel:false,commaRoundTrip:false,delimiter:'&',encode:true,encodeDotInKeys:false,encoder:utils.encode,encodeValuesOnly:false,filter:void undefined,format:defaultFormat,formatter:formats.formatters[defaultFormat],// deprecated
|
||
indices:false,serializeDate:function serializeDate(date){return toISO.call(date);},skipNulls:false,strictNullHandling:false};var isNonNullishPrimitive=function isNonNullishPrimitive(v){return typeof v==='string'||typeof v==='number'||typeof v==='boolean'||typeof v==='symbol'||typeof v==='bigint';};var sentinel={};var stringify=function stringify(object,prefix,generateArrayPrefix,commaRoundTrip,allowEmptyArrays,strictNullHandling,skipNulls,encodeDotInKeys,encoder,filter,sort,allowDots,serializeDate,format,formatter,encodeValuesOnly,charset,sideChannel){var obj=object;var tmpSc=sideChannel;var step=0;var findFlag=false;while((tmpSc=tmpSc.get(sentinel))!==void undefined&&!findFlag){// Where object last appeared in the ref tree
|
||
var pos=tmpSc.get(object);step+=1;if(typeof pos!=='undefined'){if(pos===step){throw new RangeError('Cyclic object value');}else{findFlag=true;// Break while
|
||
}}if(typeof tmpSc.get(sentinel)==='undefined'){step=0;}}if(typeof filter==='function'){obj=filter(prefix,obj);}else if(obj instanceof Date){obj=serializeDate(obj);}else if(generateArrayPrefix==='comma'&&isArray(obj)){obj=utils.maybeMap(obj,function(value){if(value instanceof Date){return serializeDate(value);}return value;});}if(obj===null){if(strictNullHandling){return encoder&&!encodeValuesOnly?encoder(prefix,defaults.encoder,charset,'key',format):prefix;}obj='';}if(isNonNullishPrimitive(obj)||utils.isBuffer(obj)){if(encoder){var keyValue=encodeValuesOnly?prefix:encoder(prefix,defaults.encoder,charset,'key',format);return[formatter(keyValue)+'='+formatter(encoder(obj,defaults.encoder,charset,'value',format))];}return[formatter(prefix)+'='+formatter(String(obj))];}var values=[];if(typeof obj==='undefined'){return values;}var objKeys;if(generateArrayPrefix==='comma'&&isArray(obj)){// we need to join elements in
|
||
if(encodeValuesOnly&&encoder){obj=utils.maybeMap(obj,encoder);}objKeys=[{value:obj.length>0?obj.join(',')||null:void undefined}];}else if(isArray(filter)){objKeys=filter;}else{var keys=Object.keys(obj);objKeys=sort?keys.sort(sort):keys;}var encodedPrefix=encodeDotInKeys?String(prefix).replace(/\./g,'%2E'):String(prefix);var adjustedPrefix=commaRoundTrip&&isArray(obj)&&obj.length===1?encodedPrefix+'[]':encodedPrefix;if(allowEmptyArrays&&isArray(obj)&&obj.length===0){return adjustedPrefix+'[]';}for(var j=0;j<objKeys.length;++j){var key=objKeys[j];var value=typeof key==='object'&&key&&typeof key.value!=='undefined'?key.value:obj[key];if(skipNulls&&value===null){continue;}var encodedKey=allowDots&&encodeDotInKeys?String(key).replace(/\./g,'%2E'):String(key);var keyPrefix=isArray(obj)?typeof generateArrayPrefix==='function'?generateArrayPrefix(adjustedPrefix,encodedKey):adjustedPrefix:adjustedPrefix+(allowDots?'.'+encodedKey:'['+encodedKey+']');sideChannel.set(object,step);var valueSideChannel=getSideChannel();valueSideChannel.set(sentinel,sideChannel);pushToArray(values,stringify(value,keyPrefix,generateArrayPrefix,commaRoundTrip,allowEmptyArrays,strictNullHandling,skipNulls,encodeDotInKeys,generateArrayPrefix==='comma'&&encodeValuesOnly&&isArray(obj)?null:encoder,filter,sort,allowDots,serializeDate,format,formatter,encodeValuesOnly,charset,valueSideChannel));}return values;};var normalizeStringifyOptions=function normalizeStringifyOptions(opts){if(!opts){return defaults;}if(typeof opts.allowEmptyArrays!=='undefined'&&typeof opts.allowEmptyArrays!=='boolean'){throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');}if(typeof opts.encodeDotInKeys!=='undefined'&&typeof opts.encodeDotInKeys!=='boolean'){throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');}if(opts.encoder!==null&&typeof opts.encoder!=='undefined'&&typeof opts.encoder!=='function'){throw new TypeError('Encoder has to be a function.');}var charset=opts.charset||defaults.charset;if(typeof opts.charset!=='undefined'&&opts.charset!=='utf-8'&&opts.charset!=='iso-8859-1'){throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');}var format=formats['default'];if(typeof opts.format!=='undefined'){if(!has.call(formats.formatters,opts.format)){throw new TypeError('Unknown format option provided.');}format=opts.format;}var formatter=formats.formatters[format];var filter=defaults.filter;if(typeof opts.filter==='function'||isArray(opts.filter)){filter=opts.filter;}var arrayFormat;if(opts.arrayFormat in arrayPrefixGenerators){arrayFormat=opts.arrayFormat;}else if('indices'in opts){arrayFormat=opts.indices?'indices':'repeat';}else{arrayFormat=defaults.arrayFormat;}if('commaRoundTrip'in opts&&typeof opts.commaRoundTrip!=='boolean'){throw new TypeError('`commaRoundTrip` must be a boolean, or absent');}var allowDots=typeof opts.allowDots==='undefined'?opts.encodeDotInKeys===true?true:defaults.allowDots:!!opts.allowDots;return{addQueryPrefix:typeof opts.addQueryPrefix==='boolean'?opts.addQueryPrefix:defaults.addQueryPrefix,allowDots:allowDots,allowEmptyArrays:typeof opts.allowEmptyArrays==='boolean'?!!opts.allowEmptyArrays:defaults.allowEmptyArrays,arrayFormat:arrayFormat,charset:charset,charsetSentinel:typeof opts.charsetSentinel==='boolean'?opts.charsetSentinel:defaults.charsetSentinel,commaRoundTrip:!!opts.commaRoundTrip,delimiter:typeof opts.delimiter==='undefined'?defaults.delimiter:opts.delimiter,encode:typeof opts.encode==='boolean'?opts.encode:defaults.encode,encodeDotInKeys:typeof opts.encodeDotInKeys==='boolean'?opts.encodeDotInKeys:defaults.encodeDotInKeys,encoder:typeof opts.encoder==='function'?opts.encoder:defaults.encoder,encodeValuesOnly:typeof opts.encodeValuesOnly==='boolean'?opts.encodeValuesOnly:defaults.encodeValuesOnly,filter:filter,format:format,formatter:formatter,serializeDate:typeof opts.serializeDate==='function'?opts.serializeDate:defaults.serializeDate,skipNulls:typeof opts.skipNulls==='boolean'?opts.skipNulls:defaults.skipNulls,sort:typeof opts.sort==='function'?opts.sort:null,strictNullHandling:typeof opts.strictNullHandling==='boolean'?opts.strictNullHandling:defaults.strictNullHandling};};module.exports=function(object,opts){var obj=object;var options=normalizeStringifyOptions(opts);var objKeys;var filter;if(typeof options.filter==='function'){filter=options.filter;obj=filter('',obj);}else if(isArray(options.filter)){filter=options.filter;objKeys=filter;}var keys=[];if(typeof obj!=='object'||obj===null){return'';}var generateArrayPrefix=arrayPrefixGenerators[options.arrayFormat];var commaRoundTrip=generateArrayPrefix==='comma'&&options.commaRoundTrip;if(!objKeys){objKeys=Object.keys(obj);}if(options.sort){objKeys.sort(options.sort);}var sideChannel=getSideChannel();for(var i=0;i<objKeys.length;++i){var key=objKeys[i];var value=obj[key];if(options.skipNulls&&value===null){continue;}pushToArray(keys,stringify(value,key,generateArrayPrefix,commaRoundTrip,options.allowEmptyArrays,options.strictNullHandling,options.skipNulls,options.encodeDotInKeys,options.encode?options.encoder:null,options.filter,options.sort,options.allowDots,options.serializeDate,options.format,options.formatter,options.encodeValuesOnly,options.charset,sideChannel));}var joined=keys.join(options.delimiter);var prefix=options.addQueryPrefix===true?'?':'';if(options.charsetSentinel){if(options.charset==='iso-8859-1'){// encodeURIComponent('✓'), the "numeric entity" representation of a checkmark
|
||
prefix+='utf8=%26%2310003%3B&';}else{// encodeURIComponent('✓')
|
||
prefix+='utf8=%E2%9C%93&';}}return joined.length>0?prefix+joined:'';};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 67124:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var $TypeError=__webpack_require__(93767);var inspect=__webpack_require__(73271);var getSideChannelList=__webpack_require__(60271);var getSideChannelMap=__webpack_require__(12263);var getSideChannelWeakMap=__webpack_require__(29499);var makeChannel=getSideChannelWeakMap||getSideChannelMap||getSideChannelList;/** @type {import('.')} */module.exports=function getSideChannel(){/** @typedef {ReturnType<typeof getSideChannel>} Channel *//** @type {Channel | undefined} */var $channelData;/** @type {Channel} */var channel={assert:function(key){if(!channel.has(key)){throw new $TypeError('Side channel does not contain '+inspect(key));}},'delete':function(key){return!!$channelData&&$channelData['delete'](key);},get:function(key){return $channelData&&$channelData.get(key);},has:function(key){return!!$channelData&&$channelData.has(key);},set:function(key,value){if(!$channelData){$channelData=makeChannel();}$channelData.set(key,value);}};// @ts-expect-error TODO: figure out why this is erroring
|
||
return channel;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 70526:
|
||
/***/ (function() {
|
||
|
||
(function(){/*
|
||
|
||
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
|
||
This code may only be used under the BSD style license found at
|
||
http://polymer.github.io/LICENSE.txt The complete set of authors may be found
|
||
at http://polymer.github.io/AUTHORS.txt The complete set of contributors may
|
||
be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by
|
||
Google as part of the polymer project is also subject to an additional IP
|
||
rights grant found at http://polymer.github.io/PATENTS.txt
|
||
*/'use strict';var n=window.Document.prototype.createElement,p=window.Document.prototype.createElementNS,aa=window.Document.prototype.importNode,ba=window.Document.prototype.prepend,ca=window.Document.prototype.append,da=window.DocumentFragment.prototype.prepend,ea=window.DocumentFragment.prototype.append,q=window.Node.prototype.cloneNode,r=window.Node.prototype.appendChild,t=window.Node.prototype.insertBefore,u=window.Node.prototype.removeChild,v=window.Node.prototype.replaceChild,w=Object.getOwnPropertyDescriptor(window.Node.prototype,"textContent"),y=window.Element.prototype.attachShadow,z=Object.getOwnPropertyDescriptor(window.Element.prototype,"innerHTML"),A=window.Element.prototype.getAttribute,B=window.Element.prototype.setAttribute,C=window.Element.prototype.removeAttribute,D=window.Element.prototype.toggleAttribute,E=window.Element.prototype.getAttributeNS,F=window.Element.prototype.setAttributeNS,G=window.Element.prototype.removeAttributeNS,H=window.Element.prototype.insertAdjacentElement,fa=window.Element.prototype.insertAdjacentHTML,ha=window.Element.prototype.prepend,ia=window.Element.prototype.append,ja=window.Element.prototype.before,ka=window.Element.prototype.after,la=window.Element.prototype.replaceWith,ma=window.Element.prototype.remove,na=window.HTMLElement,I=Object.getOwnPropertyDescriptor(window.HTMLElement.prototype,"innerHTML"),oa=window.HTMLElement.prototype.insertAdjacentElement,pa=window.HTMLElement.prototype.insertAdjacentHTML;var qa=new Set();"annotation-xml color-profile font-face font-face-src font-face-uri font-face-format font-face-name missing-glyph".split(" ").forEach(function(a){return qa.add(a);});function ra(a){var b=qa.has(a);a=/^[a-z][.0-9_a-z]*-[-.0-9_a-z]*$/.test(a);return!b&&a;}var sa=document.contains?document.contains.bind(document):document.documentElement.contains.bind(document.documentElement);function J(a){var b=a.isConnected;if(void 0!==b)return b;if(sa(a))return!0;for(;a&&!(a.__CE_isImportDocument||a instanceof Document);)a=a.parentNode||(window.ShadowRoot&&a instanceof ShadowRoot?a.host:void 0);return!(!a||!(a.__CE_isImportDocument||a instanceof Document));}function K(a){var b=a.children;if(b)return Array.prototype.slice.call(b);b=[];for(a=a.firstChild;a;a=a.nextSibling)a.nodeType===Node.ELEMENT_NODE&&b.push(a);return b;}function L(a,b){for(;b&&b!==a&&!b.nextSibling;)b=b.parentNode;return b&&b!==a?b.nextSibling:null;}function M(a,b,d){for(var f=a;f;){if(f.nodeType===Node.ELEMENT_NODE){var c=f;b(c);var e=c.localName;if("link"===e&&"import"===c.getAttribute("rel")){f=c.import;void 0===d&&(d=new Set());if(f instanceof Node&&!d.has(f))for(d.add(f),f=f.firstChild;f;f=f.nextSibling)M(f,b,d);f=L(a,c);continue;}else if("template"===e){f=L(a,c);continue;}if(c=c.__CE_shadowRoot)for(c=c.firstChild;c;c=c.nextSibling)M(c,b,d);}f=f.firstChild?f.firstChild:L(a,f);}};function N(){var a=!(null===O||void 0===O||!O.noDocumentConstructionObserver),b=!(null===O||void 0===O||!O.shadyDomFastWalk);this.m=[];this.g=[];this.j=!1;this.shadyDomFastWalk=b;this.I=!a;}function P(a,b,d,f){var c=window.ShadyDOM;if(a.shadyDomFastWalk&&c&&c.inUse){if(b.nodeType===Node.ELEMENT_NODE&&d(b),b.querySelectorAll)for(a=c.nativeMethods.querySelectorAll.call(b,"*"),b=0;b<a.length;b++)d(a[b]);}else M(b,d,f);}function ta(a,b){a.j=!0;a.m.push(b);}function ua(a,b){a.j=!0;a.g.push(b);}function Q(a,b){a.j&&P(a,b,function(d){return R(a,d);});}function R(a,b){if(a.j&&!b.__CE_patched){b.__CE_patched=!0;for(var d=0;d<a.m.length;d++)a.m[d](b);for(d=0;d<a.g.length;d++)a.g[d](b);}}function S(a,b){var d=[];P(a,b,function(c){return d.push(c);});for(b=0;b<d.length;b++){var f=d[b];1===f.__CE_state?a.connectedCallback(f):T(a,f);}}function U(a,b){var d=[];P(a,b,function(c){return d.push(c);});for(b=0;b<d.length;b++){var f=d[b];1===f.__CE_state&&a.disconnectedCallback(f);}}function V(a,b,d){d=void 0===d?{}:d;var f=d.J,c=d.upgrade||function(g){return T(a,g);},e=[];P(a,b,function(g){a.j&&R(a,g);if("link"===g.localName&&"import"===g.getAttribute("rel")){var h=g.import;h instanceof Node&&(h.__CE_isImportDocument=!0,h.__CE_registry=document.__CE_registry);h&&"complete"===h.readyState?h.__CE_documentLoadHandled=!0:g.addEventListener("load",function(){var k=g.import;if(!k.__CE_documentLoadHandled){k.__CE_documentLoadHandled=!0;var l=new Set();f&&(f.forEach(function(m){return l.add(m);}),l.delete(k));V(a,k,{J:l,upgrade:c});}});}else e.push(g);},f);for(b=0;b<e.length;b++)c(e[b]);}function T(a,b){try{var d=b.ownerDocument,f=d.__CE_registry;var c=f&&(d.defaultView||d.__CE_isImportDocument)?W(f,b.localName):void 0;if(c&&void 0===b.__CE_state){c.constructionStack.push(b);try{try{if(new c.constructorFunction()!==b)throw Error("The custom element constructor did not produce the element being upgraded.");}finally{c.constructionStack.pop();}}catch(k){throw b.__CE_state=2,k;}b.__CE_state=1;b.__CE_definition=c;if(c.attributeChangedCallback&&b.hasAttributes()){var e=c.observedAttributes;for(c=0;c<e.length;c++){var g=e[c],h=b.getAttribute(g);null!==h&&a.attributeChangedCallback(b,g,null,h,null);}}J(b)&&a.connectedCallback(b);}}catch(k){X(k);}}N.prototype.connectedCallback=function(a){var b=a.__CE_definition;if(b.connectedCallback)try{b.connectedCallback.call(a);}catch(d){X(d);}};N.prototype.disconnectedCallback=function(a){var b=a.__CE_definition;if(b.disconnectedCallback)try{b.disconnectedCallback.call(a);}catch(d){X(d);}};N.prototype.attributeChangedCallback=function(a,b,d,f,c){var e=a.__CE_definition;if(e.attributeChangedCallback&&-1<e.observedAttributes.indexOf(b))try{e.attributeChangedCallback.call(a,b,d,f,c);}catch(g){X(g);}};function va(a,b,d,f){var c=b.__CE_registry;if(c&&(null===f||"http://www.w3.org/1999/xhtml"===f)&&(c=W(c,d)))try{var e=new c.constructorFunction();if(void 0===e.__CE_state||void 0===e.__CE_definition)throw Error("Failed to construct '"+d+"': The returned value was not constructed with the HTMLElement constructor.");if("http://www.w3.org/1999/xhtml"!==e.namespaceURI)throw Error("Failed to construct '"+d+"': The constructed element's namespace must be the HTML namespace.");if(e.hasAttributes())throw Error("Failed to construct '"+d+"': The constructed element must not have any attributes.");if(null!==e.firstChild)throw Error("Failed to construct '"+d+"': The constructed element must not have any children.");if(null!==e.parentNode)throw Error("Failed to construct '"+d+"': The constructed element must not have a parent node.");if(e.ownerDocument!==b)throw Error("Failed to construct '"+d+"': The constructed element's owner document is incorrect.");if(e.localName!==d)throw Error("Failed to construct '"+d+"': The constructed element's local name is incorrect.");return e;}catch(g){return X(g),b=null===f?n.call(b,d):p.call(b,f,d),Object.setPrototypeOf(b,HTMLUnknownElement.prototype),b.__CE_state=2,b.__CE_definition=void 0,R(a,b),b;}b=null===f?n.call(b,d):p.call(b,f,d);R(a,b);return b;}function X(a){var b="",d="",f=0,c=0;a instanceof Error?(b=a.message,d=a.sourceURL||a.fileName||"",f=a.line||a.lineNumber||0,c=a.column||a.columnNumber||0):b="Uncaught "+String(a);var e=void 0;void 0===ErrorEvent.prototype.initErrorEvent?e=new ErrorEvent("error",{cancelable:!0,message:b,filename:d,lineno:f,colno:c,error:a}):(e=document.createEvent("ErrorEvent"),e.initErrorEvent("error",!1,!0,b,d,f),e.preventDefault=function(){Object.defineProperty(this,"defaultPrevented",{configurable:!0,get:function(){return!0;}});});void 0===e.error&&Object.defineProperty(e,"error",{configurable:!0,enumerable:!0,get:function(){return a;}});window.dispatchEvent(e);e.defaultPrevented||console.error(a);};function wa(){var a=this;this.g=void 0;this.F=new Promise(function(b){a.l=b;});}wa.prototype.resolve=function(a){if(this.g)throw Error("Already resolved.");this.g=a;this.l(a);};function xa(a){var b=document;this.l=void 0;this.h=a;this.g=b;V(this.h,this.g);"loading"===this.g.readyState&&(this.l=new MutationObserver(this.G.bind(this)),this.l.observe(this.g,{childList:!0,subtree:!0}));}function ya(a){a.l&&a.l.disconnect();}xa.prototype.G=function(a){var b=this.g.readyState;"interactive"!==b&&"complete"!==b||ya(this);for(b=0;b<a.length;b++)for(var d=a[b].addedNodes,f=0;f<d.length;f++)V(this.h,d[f]);};function Y(a){this.s=new Map();this.u=new Map();this.C=new Map();this.A=!1;this.B=new Map();this.o=function(b){return b();};this.i=!1;this.v=[];this.h=a;this.D=a.I?new xa(a):void 0;}Y.prototype.H=function(a,b){var d=this;if(!(b instanceof Function))throw new TypeError("Custom element constructor getters must be functions.");za(this,a);this.s.set(a,b);this.v.push(a);this.i||(this.i=!0,this.o(function(){return Aa(d);}));};Y.prototype.define=function(a,b){var d=this;if(!(b instanceof Function))throw new TypeError("Custom element constructors must be functions.");za(this,a);Ba(this,a,b);this.v.push(a);this.i||(this.i=!0,this.o(function(){return Aa(d);}));};function za(a,b){if(!ra(b))throw new SyntaxError("The element name '"+b+"' is not valid.");if(W(a,b))throw Error("A custom element with name '"+(b+"' has already been defined."));if(a.A)throw Error("A custom element is already being defined.");}function Ba(a,b,d){a.A=!0;var f;try{var c=d.prototype;if(!(c instanceof Object))throw new TypeError("The custom element constructor's prototype is not an object.");var e=function(m){var x=c[m];if(void 0!==x&&!(x instanceof Function))throw Error("The '"+m+"' callback must be a function.");return x;};var g=e("connectedCallback");var h=e("disconnectedCallback");var k=e("adoptedCallback");var l=(f=e("attributeChangedCallback"))&&d.observedAttributes||[];}catch(m){throw m;}finally{a.A=!1;}d={localName:b,constructorFunction:d,connectedCallback:g,disconnectedCallback:h,adoptedCallback:k,attributeChangedCallback:f,observedAttributes:l,constructionStack:[]};a.u.set(b,d);a.C.set(d.constructorFunction,d);return d;}Y.prototype.upgrade=function(a){V(this.h,a);};function Aa(a){if(!1!==a.i){a.i=!1;for(var b=[],d=a.v,f=new Map(),c=0;c<d.length;c++)f.set(d[c],[]);V(a.h,document,{upgrade:function(k){if(void 0===k.__CE_state){var l=k.localName,m=f.get(l);m?m.push(k):a.u.has(l)&&b.push(k);}}});for(c=0;c<b.length;c++)T(a.h,b[c]);for(c=0;c<d.length;c++){for(var e=d[c],g=f.get(e),h=0;h<g.length;h++)T(a.h,g[h]);(e=a.B.get(e))&&e.resolve(void 0);}d.length=0;}}Y.prototype.get=function(a){if(a=W(this,a))return a.constructorFunction;};Y.prototype.whenDefined=function(a){if(!ra(a))return Promise.reject(new SyntaxError("'"+a+"' is not a valid custom element name."));var b=this.B.get(a);if(b)return b.F;b=new wa();this.B.set(a,b);var d=this.u.has(a)||this.s.has(a);a=-1===this.v.indexOf(a);d&&a&&b.resolve(void 0);return b.F;};Y.prototype.polyfillWrapFlushCallback=function(a){this.D&&ya(this.D);var b=this.o;this.o=function(d){return a(function(){return b(d);});};};function W(a,b){var d=a.u.get(b);if(d)return d;if(d=a.s.get(b)){a.s.delete(b);try{return Ba(a,b,d());}catch(f){X(f);}}}Y.prototype.define=Y.prototype.define;Y.prototype.upgrade=Y.prototype.upgrade;Y.prototype.get=Y.prototype.get;Y.prototype.whenDefined=Y.prototype.whenDefined;Y.prototype.polyfillDefineLazy=Y.prototype.H;Y.prototype.polyfillWrapFlushCallback=Y.prototype.polyfillWrapFlushCallback;function Z(a,b,d){function f(c){return function(e){for(var g=[],h=0;h<arguments.length;++h)g[h]=arguments[h];h=[];for(var k=[],l=0;l<g.length;l++){var m=g[l];m instanceof Element&&J(m)&&k.push(m);if(m instanceof DocumentFragment)for(m=m.firstChild;m;m=m.nextSibling)h.push(m);else h.push(m);}c.apply(this,g);for(g=0;g<k.length;g++)U(a,k[g]);if(J(this))for(g=0;g<h.length;g++)k=h[g],k instanceof Element&&S(a,k);};}void 0!==d.prepend&&(b.prepend=f(d.prepend));void 0!==d.append&&(b.append=f(d.append));};function Ca(a){Document.prototype.createElement=function(b){return va(a,this,b,null);};Document.prototype.importNode=function(b,d){b=aa.call(this,b,!!d);this.__CE_registry?V(a,b):Q(a,b);return b;};Document.prototype.createElementNS=function(b,d){return va(a,this,d,b);};Z(a,Document.prototype,{prepend:ba,append:ca});};function Da(a){function b(f){return function(c){for(var e=[],g=0;g<arguments.length;++g)e[g]=arguments[g];g=[];for(var h=[],k=0;k<e.length;k++){var l=e[k];l instanceof Element&&J(l)&&h.push(l);if(l instanceof DocumentFragment)for(l=l.firstChild;l;l=l.nextSibling)g.push(l);else g.push(l);}f.apply(this,e);for(e=0;e<h.length;e++)U(a,h[e]);if(J(this))for(e=0;e<g.length;e++)h=g[e],h instanceof Element&&S(a,h);};}var d=Element.prototype;void 0!==ja&&(d.before=b(ja));void 0!==ka&&(d.after=b(ka));void 0!==la&&(d.replaceWith=function(f){for(var c=[],e=0;e<arguments.length;++e)c[e]=arguments[e];e=[];for(var g=[],h=0;h<c.length;h++){var k=c[h];k instanceof Element&&J(k)&&g.push(k);if(k instanceof DocumentFragment)for(k=k.firstChild;k;k=k.nextSibling)e.push(k);else e.push(k);}h=J(this);la.apply(this,c);for(c=0;c<g.length;c++)U(a,g[c]);if(h)for(U(a,this),c=0;c<e.length;c++)g=e[c],g instanceof Element&&S(a,g);});void 0!==ma&&(d.remove=function(){var f=J(this);ma.call(this);f&&U(a,this);});};function Ea(a){function b(c,e){Object.defineProperty(c,"innerHTML",{enumerable:e.enumerable,configurable:!0,get:e.get,set:function(g){var h=this,k=void 0;J(this)&&(k=[],P(a,this,function(x){x!==h&&k.push(x);}));e.set.call(this,g);if(k)for(var l=0;l<k.length;l++){var m=k[l];1===m.__CE_state&&a.disconnectedCallback(m);}this.ownerDocument.__CE_registry?V(a,this):Q(a,this);return g;}});}function d(c,e){c.insertAdjacentElement=function(g,h){var k=J(h);g=e.call(this,g,h);k&&U(a,h);J(g)&&S(a,h);return g;};}function f(c,e){function g(h,k){for(var l=[];h!==k;h=h.nextSibling)l.push(h);for(k=0;k<l.length;k++)V(a,l[k]);}c.insertAdjacentHTML=function(h,k){h=h.toLowerCase();if("beforebegin"===h){var l=this.previousSibling;e.call(this,h,k);g(l||this.parentNode.firstChild,this);}else if("afterbegin"===h)l=this.firstChild,e.call(this,h,k),g(this.firstChild,l);else if("beforeend"===h)l=this.lastChild,e.call(this,h,k),g(l||this.firstChild,null);else if("afterend"===h)l=this.nextSibling,e.call(this,h,k),g(this.nextSibling,l);else throw new SyntaxError("The value provided ("+String(h)+") is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'.");};}y&&(Element.prototype.attachShadow=function(c){c=y.call(this,c);if(a.j&&!c.__CE_patched){c.__CE_patched=!0;for(var e=0;e<a.m.length;e++)a.m[e](c);}return this.__CE_shadowRoot=c;});z&&z.get?b(Element.prototype,z):I&&I.get?b(HTMLElement.prototype,I):ua(a,function(c){b(c,{enumerable:!0,configurable:!0,get:function(){return q.call(this,!0).innerHTML;},set:function(e){var g="template"===this.localName,h=g?this.content:this,k=p.call(document,this.namespaceURI,this.localName);for(k.innerHTML=e;0<h.childNodes.length;)u.call(h,h.childNodes[0]);for(e=g?k.content:k;0<e.childNodes.length;)r.call(h,e.childNodes[0]);}});});Element.prototype.setAttribute=function(c,e){if(1!==this.__CE_state)return B.call(this,c,e);var g=A.call(this,c);B.call(this,c,e);e=A.call(this,c);a.attributeChangedCallback(this,c,g,e,null);};Element.prototype.setAttributeNS=function(c,e,g){if(1!==this.__CE_state)return F.call(this,c,e,g);var h=E.call(this,c,e);F.call(this,c,e,g);g=E.call(this,c,e);a.attributeChangedCallback(this,e,h,g,c);};Element.prototype.removeAttribute=function(c){if(1!==this.__CE_state)return C.call(this,c);var e=A.call(this,c);C.call(this,c);null!==e&&a.attributeChangedCallback(this,c,e,null,null);};D&&(Element.prototype.toggleAttribute=function(c,e){if(1!==this.__CE_state)return D.call(this,c,e);var g=A.call(this,c),h=null!==g;e=D.call(this,c,e);h!==e&&a.attributeChangedCallback(this,c,g,e?"":null,null);return e;});Element.prototype.removeAttributeNS=function(c,e){if(1!==this.__CE_state)return G.call(this,c,e);var g=E.call(this,c,e);G.call(this,c,e);var h=E.call(this,c,e);g!==h&&a.attributeChangedCallback(this,e,g,h,c);};oa?d(HTMLElement.prototype,oa):H&&d(Element.prototype,H);pa?f(HTMLElement.prototype,pa):fa&&f(Element.prototype,fa);Z(a,Element.prototype,{prepend:ha,append:ia});Da(a);};var Fa={};function Ga(a){function b(){var d=this.constructor;var f=document.__CE_registry.C.get(d);if(!f)throw Error("Failed to construct a custom element: The constructor was not registered with `customElements`.");var c=f.constructionStack;if(0===c.length)return c=n.call(document,f.localName),Object.setPrototypeOf(c,d.prototype),c.__CE_state=1,c.__CE_definition=f,R(a,c),c;var e=c.length-1,g=c[e];if(g===Fa)throw Error("Failed to construct '"+f.localName+"': This element was already constructed.");c[e]=Fa;Object.setPrototypeOf(g,d.prototype);R(a,g);return g;}b.prototype=na.prototype;Object.defineProperty(HTMLElement.prototype,"constructor",{writable:!0,configurable:!0,enumerable:!1,value:b});window.HTMLElement=b;};function Ha(a){function b(d,f){Object.defineProperty(d,"textContent",{enumerable:f.enumerable,configurable:!0,get:f.get,set:function(c){if(this.nodeType===Node.TEXT_NODE)f.set.call(this,c);else{var e=void 0;if(this.firstChild){var g=this.childNodes,h=g.length;if(0<h&&J(this)){e=Array(h);for(var k=0;k<h;k++)e[k]=g[k];}}f.set.call(this,c);if(e)for(c=0;c<e.length;c++)U(a,e[c]);}}});}Node.prototype.insertBefore=function(d,f){if(d instanceof DocumentFragment){var c=K(d);d=t.call(this,d,f);if(J(this))for(f=0;f<c.length;f++)S(a,c[f]);return d;}c=d instanceof Element&&J(d);f=t.call(this,d,f);c&&U(a,d);J(this)&&S(a,d);return f;};Node.prototype.appendChild=function(d){if(d instanceof DocumentFragment){var f=K(d);d=r.call(this,d);if(J(this))for(var c=0;c<f.length;c++)S(a,f[c]);return d;}f=d instanceof Element&&J(d);c=r.call(this,d);f&&U(a,d);J(this)&&S(a,d);return c;};Node.prototype.cloneNode=function(d){d=q.call(this,!!d);this.ownerDocument.__CE_registry?V(a,d):Q(a,d);return d;};Node.prototype.removeChild=function(d){var f=d instanceof Element&&J(d),c=u.call(this,d);f&&U(a,d);return c;};Node.prototype.replaceChild=function(d,f){if(d instanceof DocumentFragment){var c=K(d);d=v.call(this,d,f);if(J(this))for(U(a,f),f=0;f<c.length;f++)S(a,c[f]);return d;}c=d instanceof Element&&J(d);var e=v.call(this,d,f),g=J(this);g&&U(a,f);c&&U(a,d);g&&S(a,d);return e;};w&&w.get?b(Node.prototype,w):ta(a,function(d){b(d,{enumerable:!0,configurable:!0,get:function(){for(var f=[],c=this.firstChild;c;c=c.nextSibling)c.nodeType!==Node.COMMENT_NODE&&f.push(c.textContent);return f.join("");},set:function(f){for(;this.firstChild;)u.call(this,this.firstChild);null!=f&&""!==f&&r.call(this,document.createTextNode(f));}});});};var O=window.customElements;function Ia(){var a=new N();Ga(a);Ca(a);Z(a,DocumentFragment.prototype,{prepend:da,append:ea});Ha(a);Ea(a);window.CustomElementRegistry=Y;a=new Y(a);document.__CE_registry=a;Object.defineProperty(window,"customElements",{configurable:!0,enumerable:!0,value:a});}O&&!O.forcePolyfill&&"function"==typeof O.define&&"function"==typeof O.get||Ia();window.__CE_installPolyfill=Ia;}).call(self);
|
||
|
||
/***/ }),
|
||
|
||
/***/ 73271:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
var hasMap=typeof Map==='function'&&Map.prototype;var mapSizeDescriptor=Object.getOwnPropertyDescriptor&&hasMap?Object.getOwnPropertyDescriptor(Map.prototype,'size'):null;var mapSize=hasMap&&mapSizeDescriptor&&typeof mapSizeDescriptor.get==='function'?mapSizeDescriptor.get:null;var mapForEach=hasMap&&Map.prototype.forEach;var hasSet=typeof Set==='function'&&Set.prototype;var setSizeDescriptor=Object.getOwnPropertyDescriptor&&hasSet?Object.getOwnPropertyDescriptor(Set.prototype,'size'):null;var setSize=hasSet&&setSizeDescriptor&&typeof setSizeDescriptor.get==='function'?setSizeDescriptor.get:null;var setForEach=hasSet&&Set.prototype.forEach;var hasWeakMap=typeof WeakMap==='function'&&WeakMap.prototype;var weakMapHas=hasWeakMap?WeakMap.prototype.has:null;var hasWeakSet=typeof WeakSet==='function'&&WeakSet.prototype;var weakSetHas=hasWeakSet?WeakSet.prototype.has:null;var hasWeakRef=typeof WeakRef==='function'&&WeakRef.prototype;var weakRefDeref=hasWeakRef?WeakRef.prototype.deref:null;var booleanValueOf=Boolean.prototype.valueOf;var objectToString=Object.prototype.toString;var functionToString=Function.prototype.toString;var $match=String.prototype.match;var $slice=String.prototype.slice;var $replace=String.prototype.replace;var $toUpperCase=String.prototype.toUpperCase;var $toLowerCase=String.prototype.toLowerCase;var $test=RegExp.prototype.test;var $concat=Array.prototype.concat;var $join=Array.prototype.join;var $arrSlice=Array.prototype.slice;var $floor=Math.floor;var bigIntValueOf=typeof BigInt==='function'?BigInt.prototype.valueOf:null;var gOPS=Object.getOwnPropertySymbols;var symToString=typeof Symbol==='function'&&typeof Symbol.iterator==='symbol'?Symbol.prototype.toString:null;var hasShammedSymbols=typeof Symbol==='function'&&typeof Symbol.iterator==='object';// ie, `has-tostringtag/shams
|
||
var toStringTag=typeof Symbol==='function'&&Symbol.toStringTag&&(typeof Symbol.toStringTag===hasShammedSymbols?'object':'symbol')?Symbol.toStringTag:null;var isEnumerable=Object.prototype.propertyIsEnumerable;var gPO=(typeof Reflect==='function'?Reflect.getPrototypeOf:Object.getPrototypeOf)||([].__proto__===Array.prototype// eslint-disable-line no-proto
|
||
?function(O){return O.__proto__;// eslint-disable-line no-proto
|
||
}:null);function addNumericSeparator(num,str){if(num===Infinity||num===-Infinity||num!==num||num&&num>-1000&&num<1000||$test.call(/e/,str)){return str;}var sepRegex=/[0-9](?=(?:[0-9]{3})+(?![0-9]))/g;if(typeof num==='number'){var int=num<0?-$floor(-num):$floor(num);// trunc(num)
|
||
if(int!==num){var intStr=String(int);var dec=$slice.call(str,intStr.length+1);return $replace.call(intStr,sepRegex,'$&_')+'.'+$replace.call($replace.call(dec,/([0-9]{3})/g,'$&_'),/_$/,'');}}return $replace.call(str,sepRegex,'$&_');}var utilInspect=__webpack_require__(86973);var inspectCustom=utilInspect.custom;var inspectSymbol=isSymbol(inspectCustom)?inspectCustom:null;var quotes={__proto__:null,'double':'"',single:"'"};var quoteREs={__proto__:null,'double':/(["\\])/g,single:/(['\\])/g};module.exports=function inspect_(obj,options,depth,seen){var opts=options||{};if(has(opts,'quoteStyle')&&!has(quotes,opts.quoteStyle)){throw new TypeError('option "quoteStyle" must be "single" or "double"');}if(has(opts,'maxStringLength')&&(typeof opts.maxStringLength==='number'?opts.maxStringLength<0&&opts.maxStringLength!==Infinity:opts.maxStringLength!==null)){throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');}var customInspect=has(opts,'customInspect')?opts.customInspect:true;if(typeof customInspect!=='boolean'&&customInspect!=='symbol'){throw new TypeError('option "customInspect", if provided, must be `true`, `false`, or `\'symbol\'`');}if(has(opts,'indent')&&opts.indent!==null&&opts.indent!=='\t'&&!(parseInt(opts.indent,10)===opts.indent&&opts.indent>0)){throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`');}if(has(opts,'numericSeparator')&&typeof opts.numericSeparator!=='boolean'){throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');}var numericSeparator=opts.numericSeparator;if(typeof obj==='undefined'){return'undefined';}if(obj===null){return'null';}if(typeof obj==='boolean'){return obj?'true':'false';}if(typeof obj==='string'){return inspectString(obj,opts);}if(typeof obj==='number'){if(obj===0){return Infinity/obj>0?'0':'-0';}var str=String(obj);return numericSeparator?addNumericSeparator(obj,str):str;}if(typeof obj==='bigint'){var bigIntStr=String(obj)+'n';return numericSeparator?addNumericSeparator(obj,bigIntStr):bigIntStr;}var maxDepth=typeof opts.depth==='undefined'?5:opts.depth;if(typeof depth==='undefined'){depth=0;}if(depth>=maxDepth&&maxDepth>0&&typeof obj==='object'){return isArray(obj)?'[Array]':'[Object]';}var indent=getIndent(opts,depth);if(typeof seen==='undefined'){seen=[];}else if(indexOf(seen,obj)>=0){return'[Circular]';}function inspect(value,from,noIndent){if(from){seen=$arrSlice.call(seen);seen.push(from);}if(noIndent){var newOpts={depth:opts.depth};if(has(opts,'quoteStyle')){newOpts.quoteStyle=opts.quoteStyle;}return inspect_(value,newOpts,depth+1,seen);}return inspect_(value,opts,depth+1,seen);}if(typeof obj==='function'&&!isRegExp(obj)){// in older engines, regexes are callable
|
||
var name=nameOf(obj);var keys=arrObjKeys(obj,inspect);return'[Function'+(name?': '+name:' (anonymous)')+']'+(keys.length>0?' { '+$join.call(keys,', ')+' }':'');}if(isSymbol(obj)){var symString=hasShammedSymbols?$replace.call(String(obj),/^(Symbol\(.*\))_[^)]*$/,'$1'):symToString.call(obj);return typeof obj==='object'&&!hasShammedSymbols?markBoxed(symString):symString;}if(isElement(obj)){var s='<'+$toLowerCase.call(String(obj.nodeName));var attrs=obj.attributes||[];for(var i=0;i<attrs.length;i++){s+=' '+attrs[i].name+'='+wrapQuotes(quote(attrs[i].value),'double',opts);}s+='>';if(obj.childNodes&&obj.childNodes.length){s+='...';}s+='</'+$toLowerCase.call(String(obj.nodeName))+'>';return s;}if(isArray(obj)){if(obj.length===0){return'[]';}var xs=arrObjKeys(obj,inspect);if(indent&&!singleLineValues(xs)){return'['+indentedJoin(xs,indent)+']';}return'[ '+$join.call(xs,', ')+' ]';}if(isError(obj)){var parts=arrObjKeys(obj,inspect);if(!('cause'in Error.prototype)&&'cause'in obj&&!isEnumerable.call(obj,'cause')){return'{ ['+String(obj)+'] '+$join.call($concat.call('[cause]: '+inspect(obj.cause),parts),', ')+' }';}if(parts.length===0){return'['+String(obj)+']';}return'{ ['+String(obj)+'] '+$join.call(parts,', ')+' }';}if(typeof obj==='object'&&customInspect){if(inspectSymbol&&typeof obj[inspectSymbol]==='function'&&utilInspect){return utilInspect(obj,{depth:maxDepth-depth});}else if(customInspect!=='symbol'&&typeof obj.inspect==='function'){return obj.inspect();}}if(isMap(obj)){var mapParts=[];if(mapForEach){mapForEach.call(obj,function(value,key){mapParts.push(inspect(key,obj,true)+' => '+inspect(value,obj));});}return collectionOf('Map',mapSize.call(obj),mapParts,indent);}if(isSet(obj)){var setParts=[];if(setForEach){setForEach.call(obj,function(value){setParts.push(inspect(value,obj));});}return collectionOf('Set',setSize.call(obj),setParts,indent);}if(isWeakMap(obj)){return weakCollectionOf('WeakMap');}if(isWeakSet(obj)){return weakCollectionOf('WeakSet');}if(isWeakRef(obj)){return weakCollectionOf('WeakRef');}if(isNumber(obj)){return markBoxed(inspect(Number(obj)));}if(isBigInt(obj)){return markBoxed(inspect(bigIntValueOf.call(obj)));}if(isBoolean(obj)){return markBoxed(booleanValueOf.call(obj));}if(isString(obj)){return markBoxed(inspect(String(obj)));}// note: in IE 8, sometimes `global !== window` but both are the prototypes of each other
|
||
/* eslint-env browser */if(typeof window!=='undefined'&&obj===window){return'{ [object Window] }';}if(typeof globalThis!=='undefined'&&obj===globalThis||typeof __webpack_require__.g!=='undefined'&&obj===__webpack_require__.g){return'{ [object globalThis] }';}if(!isDate(obj)&&!isRegExp(obj)){var ys=arrObjKeys(obj,inspect);var isPlainObject=gPO?gPO(obj)===Object.prototype:obj instanceof Object||obj.constructor===Object;var protoTag=obj instanceof Object?'':'null prototype';var stringTag=!isPlainObject&&toStringTag&&Object(obj)===obj&&toStringTag in obj?$slice.call(toStr(obj),8,-1):protoTag?'Object':'';var constructorTag=isPlainObject||typeof obj.constructor!=='function'?'':obj.constructor.name?obj.constructor.name+' ':'';var tag=constructorTag+(stringTag||protoTag?'['+$join.call($concat.call([],stringTag||[],protoTag||[]),': ')+'] ':'');if(ys.length===0){return tag+'{}';}if(indent){return tag+'{'+indentedJoin(ys,indent)+'}';}return tag+'{ '+$join.call(ys,', ')+' }';}return String(obj);};function wrapQuotes(s,defaultStyle,opts){var style=opts.quoteStyle||defaultStyle;var quoteChar=quotes[style];return quoteChar+s+quoteChar;}function quote(s){return $replace.call(String(s),/"/g,'"');}function canTrustToString(obj){return!toStringTag||!(typeof obj==='object'&&(toStringTag in obj||typeof obj[toStringTag]!=='undefined'));}function isArray(obj){return toStr(obj)==='[object Array]'&&canTrustToString(obj);}function isDate(obj){return toStr(obj)==='[object Date]'&&canTrustToString(obj);}function isRegExp(obj){return toStr(obj)==='[object RegExp]'&&canTrustToString(obj);}function isError(obj){return toStr(obj)==='[object Error]'&&canTrustToString(obj);}function isString(obj){return toStr(obj)==='[object String]'&&canTrustToString(obj);}function isNumber(obj){return toStr(obj)==='[object Number]'&&canTrustToString(obj);}function isBoolean(obj){return toStr(obj)==='[object Boolean]'&&canTrustToString(obj);}// Symbol and BigInt do have Symbol.toStringTag by spec, so that can't be used to eliminate false positives
|
||
function isSymbol(obj){if(hasShammedSymbols){return obj&&typeof obj==='object'&&obj instanceof Symbol;}if(typeof obj==='symbol'){return true;}if(!obj||typeof obj!=='object'||!symToString){return false;}try{symToString.call(obj);return true;}catch(e){}return false;}function isBigInt(obj){if(!obj||typeof obj!=='object'||!bigIntValueOf){return false;}try{bigIntValueOf.call(obj);return true;}catch(e){}return false;}var hasOwn=Object.prototype.hasOwnProperty||function(key){return key in this;};function has(obj,key){return hasOwn.call(obj,key);}function toStr(obj){return objectToString.call(obj);}function nameOf(f){if(f.name){return f.name;}var m=$match.call(functionToString.call(f),/^function\s*([\w$]+)/);if(m){return m[1];}return null;}function indexOf(xs,x){if(xs.indexOf){return xs.indexOf(x);}for(var i=0,l=xs.length;i<l;i++){if(xs[i]===x){return i;}}return-1;}function isMap(x){if(!mapSize||!x||typeof x!=='object'){return false;}try{mapSize.call(x);try{setSize.call(x);}catch(s){return true;}return x instanceof Map;// core-js workaround, pre-v2.5.0
|
||
}catch(e){}return false;}function isWeakMap(x){if(!weakMapHas||!x||typeof x!=='object'){return false;}try{weakMapHas.call(x,weakMapHas);try{weakSetHas.call(x,weakSetHas);}catch(s){return true;}return x instanceof WeakMap;// core-js workaround, pre-v2.5.0
|
||
}catch(e){}return false;}function isWeakRef(x){if(!weakRefDeref||!x||typeof x!=='object'){return false;}try{weakRefDeref.call(x);return true;}catch(e){}return false;}function isSet(x){if(!setSize||!x||typeof x!=='object'){return false;}try{setSize.call(x);try{mapSize.call(x);}catch(m){return true;}return x instanceof Set;// core-js workaround, pre-v2.5.0
|
||
}catch(e){}return false;}function isWeakSet(x){if(!weakSetHas||!x||typeof x!=='object'){return false;}try{weakSetHas.call(x,weakSetHas);try{weakMapHas.call(x,weakMapHas);}catch(s){return true;}return x instanceof WeakSet;// core-js workaround, pre-v2.5.0
|
||
}catch(e){}return false;}function isElement(x){if(!x||typeof x!=='object'){return false;}if(typeof HTMLElement!=='undefined'&&x instanceof HTMLElement){return true;}return typeof x.nodeName==='string'&&typeof x.getAttribute==='function';}function inspectString(str,opts){if(str.length>opts.maxStringLength){var remaining=str.length-opts.maxStringLength;var trailer='... '+remaining+' more character'+(remaining>1?'s':'');return inspectString($slice.call(str,0,opts.maxStringLength),opts)+trailer;}var quoteRE=quoteREs[opts.quoteStyle||'single'];quoteRE.lastIndex=0;// eslint-disable-next-line no-control-regex
|
||
var s=$replace.call($replace.call(str,quoteRE,'\\$1'),/[\x00-\x1f]/g,lowbyte);return wrapQuotes(s,'single',opts);}function lowbyte(c){var n=c.charCodeAt(0);var x={8:'b',9:'t',10:'n',12:'f',13:'r'}[n];if(x){return'\\'+x;}return'\\x'+(n<0x10?'0':'')+$toUpperCase.call(n.toString(16));}function markBoxed(str){return'Object('+str+')';}function weakCollectionOf(type){return type+' { ? }';}function collectionOf(type,size,entries,indent){var joinedEntries=indent?indentedJoin(entries,indent):$join.call(entries,', ');return type+' ('+size+') {'+joinedEntries+'}';}function singleLineValues(xs){for(var i=0;i<xs.length;i++){if(indexOf(xs[i],'\n')>=0){return false;}}return true;}function getIndent(opts,depth){var baseIndent;if(opts.indent==='\t'){baseIndent='\t';}else if(typeof opts.indent==='number'&&opts.indent>0){baseIndent=$join.call(Array(opts.indent+1),' ');}else{return null;}return{base:baseIndent,prev:$join.call(Array(depth+1),baseIndent)};}function indentedJoin(xs,indent){if(xs.length===0){return'';}var lineJoiner='\n'+indent.prev+indent.base;return lineJoiner+$join.call(xs,','+lineJoiner)+'\n'+indent.prev;}function arrObjKeys(obj,inspect){var isArr=isArray(obj);var xs=[];if(isArr){xs.length=obj.length;for(var i=0;i<obj.length;i++){xs[i]=has(obj,i)?inspect(obj[i],obj):'';}}var syms=typeof gOPS==='function'?gOPS(obj):[];var symMap;if(hasShammedSymbols){symMap={};for(var k=0;k<syms.length;k++){symMap['$'+syms[k]]=syms[k];}}for(var key in obj){// eslint-disable-line no-restricted-syntax
|
||
if(!has(obj,key)){continue;}// eslint-disable-line no-restricted-syntax, no-continue
|
||
if(isArr&&String(Number(key))===key&&key<obj.length){continue;}// eslint-disable-line no-restricted-syntax, no-continue
|
||
if(hasShammedSymbols&&symMap['$'+key]instanceof Symbol){// this is to prevent shammed Symbols, which are stored as strings, from being included in the string key section
|
||
continue;// eslint-disable-line no-restricted-syntax, no-continue
|
||
}else if($test.call(/[^\w$]/,key)){xs.push(inspect(key,obj)+': '+inspect(obj[key],obj));}else{xs.push(key+': '+inspect(obj[key],obj));}}if(typeof gOPS==='function'){for(var j=0;j<syms.length;j++){if(isEnumerable.call(obj,syms[j])){xs.push('['+inspect(syms[j])+']: '+inspect(obj[syms[j]],obj));}}}return xs;}
|
||
|
||
/***/ }),
|
||
|
||
/***/ 73368:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./max')} */module.exports=Math.max;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 75519:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./isNaN')} */module.exports=Number.isNaN||function isNaN(a){return a!==a;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 75985:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./shams')} *//* eslint complexity: [2, 18], max-statements: [2, 33] */module.exports=function hasSymbols(){if(typeof Symbol!=='function'||typeof Object.getOwnPropertySymbols!=='function'){return false;}if(typeof Symbol.iterator==='symbol'){return true;}/** @type {{ [k in symbol]?: unknown }} */var obj={};var sym=Symbol('test');var symObj=Object(sym);if(typeof sym==='string'){return false;}if(Object.prototype.toString.call(sym)!=='[object Symbol]'){return false;}if(Object.prototype.toString.call(symObj)!=='[object Symbol]'){return false;}// temp disabled per https://github.com/ljharb/object.assign/issues/17
|
||
// if (sym instanceof Symbol) { return false; }
|
||
// temp disabled per https://github.com/WebReflection/get-own-property-symbols/issues/4
|
||
// if (!(symObj instanceof Symbol)) { return false; }
|
||
// if (typeof Symbol.prototype.toString !== 'function') { return false; }
|
||
// if (String(sym) !== Symbol.prototype.toString.call(sym)) { return false; }
|
||
var symVal=42;obj[sym]=symVal;for(var _ in obj){return false;}// eslint-disable-line no-restricted-syntax, no-unreachable-loop
|
||
if(typeof Object.keys==='function'&&Object.keys(obj).length!==0){return false;}if(typeof Object.getOwnPropertyNames==='function'&&Object.getOwnPropertyNames(obj).length!==0){return false;}var syms=Object.getOwnPropertySymbols(obj);if(syms.length!==1||syms[0]!==sym){return false;}if(!Object.prototype.propertyIsEnumerable.call(obj,sym)){return false;}if(typeof Object.getOwnPropertyDescriptor==='function'){// eslint-disable-next-line no-extra-parens
|
||
var descriptor=/** @type {PropertyDescriptor} */Object.getOwnPropertyDescriptor(obj,sym);if(descriptor.value!==symVal||descriptor.enumerable!==true){return false;}}return true;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 76244:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var bind=__webpack_require__(10539);var $apply=__webpack_require__(84750);var $call=__webpack_require__(51008);var $reflectApply=__webpack_require__(84323);/** @type {import('./actualApply')} */module.exports=$reflectApply||bind.call($call,$apply);
|
||
|
||
/***/ }),
|
||
|
||
/***/ 77434:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var bind=__webpack_require__(10539);var $TypeError=__webpack_require__(93767);var $call=__webpack_require__(51008);var $actualApply=__webpack_require__(76244);/** @type {(args: [Function, thisArg?: unknown, ...args: unknown[]]) => Function} TODO FIXME, find a way to use import('.') */module.exports=function callBindBasic(args){if(args.length<1||typeof args[0]!=='function'){throw new $TypeError('a function is required');}return $actualApply(bind,$call,args);};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 84323:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./reflectApply')} */module.exports=typeof Reflect!=='undefined'&&Reflect&&Reflect.apply;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 84750:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./functionApply')} */module.exports=Function.prototype.apply;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 85344:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('.')} */module.exports=Object;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 85835:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('.')} */var $defineProperty=Object.defineProperty||false;if($defineProperty){try{$defineProperty({},'a',{value:1});}catch(e){// IE 8 has a broken defineProperty
|
||
$defineProperty=false;}}module.exports=$defineProperty;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 86973:
|
||
/***/ (function() {
|
||
|
||
/* (ignored) */
|
||
|
||
/***/ }),
|
||
|
||
/***/ 90791:
|
||
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
|
||
|
||
"use strict";
|
||
__webpack_require__.r(__webpack_exports__);
|
||
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
||
/* harmony export */ decode: function() { return /* binding */ decode; },
|
||
/* harmony export */ encode: function() { return /* binding */ encode; },
|
||
/* harmony export */ toASCII: function() { return /* binding */ toASCII; },
|
||
/* harmony export */ toUnicode: function() { return /* binding */ toUnicode; },
|
||
/* harmony export */ ucs2decode: function() { return /* binding */ ucs2decode; },
|
||
/* harmony export */ ucs2encode: function() { return /* binding */ ucs2encode; }
|
||
/* harmony export */ });
|
||
/** Highest positive signed 32-bit float value */const maxInt=2147483647;// aka. 0x7FFFFFFF or 2^31-1
|
||
/** Bootstring parameters */const base=36;const tMin=1;const tMax=26;const skew=38;const damp=700;const initialBias=72;const initialN=128;// 0x80
|
||
const delimiter='-';// '\x2D'
|
||
/** Regular expressions */const regexPunycode=/^xn--/;const regexNonASCII=/[^\0-\x7F]/;// Note: U+007F DEL is excluded too.
|
||
const regexSeparators=/[\x2E\u3002\uFF0E\uFF61]/g;// RFC 3490 separators
|
||
/** Error messages */const errors={'overflow':'Overflow: input needs wider integers to process','not-basic':'Illegal input >= 0x80 (not a basic code point)','invalid-input':'Invalid input'};/** Convenience shortcuts */const baseMinusTMin=base-tMin;const floor=Math.floor;const stringFromCharCode=String.fromCharCode;/*--------------------------------------------------------------------------*//**
|
||
* A generic error utility function.
|
||
* @private
|
||
* @param {String} type The error type.
|
||
* @returns {Error} Throws a `RangeError` with the applicable error message.
|
||
*/function error(type){throw new RangeError(errors[type]);}/**
|
||
* A generic `Array#map` utility function.
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} callback The function that gets called for every array
|
||
* item.
|
||
* @returns {Array} A new array of values returned by the callback function.
|
||
*/function map(array,callback){const result=[];let length=array.length;while(length--){result[length]=callback(array[length]);}return result;}/**
|
||
* A simple `Array#map`-like wrapper to work with domain name strings or email
|
||
* addresses.
|
||
* @private
|
||
* @param {String} domain The domain name or email address.
|
||
* @param {Function} callback The function that gets called for every
|
||
* character.
|
||
* @returns {String} A new string of characters returned by the callback
|
||
* function.
|
||
*/function mapDomain(domain,callback){const parts=domain.split('@');let result='';if(parts.length>1){// In email addresses, only the domain name should be punycoded. Leave
|
||
// the local part (i.e. everything up to `@`) intact.
|
||
result=parts[0]+'@';domain=parts[1];}// Avoid `split(regex)` for IE8 compatibility. See #17.
|
||
domain=domain.replace(regexSeparators,'\x2E');const labels=domain.split('.');const encoded=map(labels,callback).join('.');return result+encoded;}/**
|
||
* Creates an array containing the numeric code points of each Unicode
|
||
* character in the string. While JavaScript uses UCS-2 internally,
|
||
* this function will convert a pair of surrogate halves (each of which
|
||
* UCS-2 exposes as separate characters) into a single code point,
|
||
* matching UTF-16.
|
||
* @see `punycode.ucs2.encode`
|
||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
||
* @memberOf punycode.ucs2
|
||
* @name decode
|
||
* @param {String} string The Unicode input string (UCS-2).
|
||
* @returns {Array} The new array of code points.
|
||
*/function ucs2decode(string){const output=[];let counter=0;const length=string.length;while(counter<length){const value=string.charCodeAt(counter++);if(value>=0xD800&&value<=0xDBFF&&counter<length){// It's a high surrogate, and there is a next character.
|
||
const extra=string.charCodeAt(counter++);if((extra&0xFC00)==0xDC00){// Low surrogate.
|
||
output.push(((value&0x3FF)<<10)+(extra&0x3FF)+0x10000);}else{// It's an unmatched surrogate; only append this code unit, in case the
|
||
// next code unit is the high surrogate of a surrogate pair.
|
||
output.push(value);counter--;}}else{output.push(value);}}return output;}/**
|
||
* Creates a string based on an array of numeric code points.
|
||
* @see `punycode.ucs2.decode`
|
||
* @memberOf punycode.ucs2
|
||
* @name encode
|
||
* @param {Array} codePoints The array of numeric code points.
|
||
* @returns {String} The new Unicode string (UCS-2).
|
||
*/const ucs2encode=codePoints=>String.fromCodePoint(...codePoints);/**
|
||
* Converts a basic code point into a digit/integer.
|
||
* @see `digitToBasic()`
|
||
* @private
|
||
* @param {Number} codePoint The basic numeric code point value.
|
||
* @returns {Number} The numeric value of a basic code point (for use in
|
||
* representing integers) in the range `0` to `base - 1`, or `base` if
|
||
* the code point does not represent a value.
|
||
*/const basicToDigit=function(codePoint){if(codePoint>=0x30&&codePoint<0x3A){return 26+(codePoint-0x30);}if(codePoint>=0x41&&codePoint<0x5B){return codePoint-0x41;}if(codePoint>=0x61&&codePoint<0x7B){return codePoint-0x61;}return base;};/**
|
||
* Converts a digit/integer into a basic code point.
|
||
* @see `basicToDigit()`
|
||
* @private
|
||
* @param {Number} digit The numeric value of a basic code point.
|
||
* @returns {Number} The basic code point whose value (when used for
|
||
* representing integers) is `digit`, which needs to be in the range
|
||
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
|
||
* used; else, the lowercase form is used. The behavior is undefined
|
||
* if `flag` is non-zero and `digit` has no uppercase form.
|
||
*/const digitToBasic=function(digit,flag){// 0..25 map to ASCII a..z or A..Z
|
||
// 26..35 map to ASCII 0..9
|
||
return digit+22+75*(digit<26)-((flag!=0)<<5);};/**
|
||
* Bias adaptation function as per section 3.4 of RFC 3492.
|
||
* https://tools.ietf.org/html/rfc3492#section-3.4
|
||
* @private
|
||
*/const adapt=function(delta,numPoints,firstTime){let k=0;delta=firstTime?floor(delta/damp):delta>>1;delta+=floor(delta/numPoints);for/* no initialization */(;delta>baseMinusTMin*tMax>>1;k+=base){delta=floor(delta/baseMinusTMin);}return floor(k+(baseMinusTMin+1)*delta/(delta+skew));};/**
|
||
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
|
||
* symbols.
|
||
* @memberOf punycode
|
||
* @param {String} input The Punycode string of ASCII-only symbols.
|
||
* @returns {String} The resulting string of Unicode symbols.
|
||
*/const decode=function(input){// Don't use UCS-2.
|
||
const output=[];const inputLength=input.length;let i=0;let n=initialN;let bias=initialBias;// Handle the basic code points: let `basic` be the number of input code
|
||
// points before the last delimiter, or `0` if there is none, then copy
|
||
// the first basic code points to the output.
|
||
let basic=input.lastIndexOf(delimiter);if(basic<0){basic=0;}for(let j=0;j<basic;++j){// if it's not a basic code point
|
||
if(input.charCodeAt(j)>=0x80){error('not-basic');}output.push(input.charCodeAt(j));}// Main decoding loop: start just after the last delimiter if any basic code
|
||
// points were copied; start at the beginning otherwise.
|
||
for/* no final expression */(let index=basic>0?basic+1:0;index<inputLength;){// `index` is the index of the next character to be consumed.
|
||
// Decode a generalized variable-length integer into `delta`,
|
||
// which gets added to `i`. The overflow checking is easier
|
||
// if we increase `i` as we go, then subtract off its starting
|
||
// value at the end to obtain `delta`.
|
||
const oldi=i;for/* no condition */(let w=1,k=base;;k+=base){if(index>=inputLength){error('invalid-input');}const digit=basicToDigit(input.charCodeAt(index++));if(digit>=base){error('invalid-input');}if(digit>floor((maxInt-i)/w)){error('overflow');}i+=digit*w;const t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(digit<t){break;}const baseMinusT=base-t;if(w>floor(maxInt/baseMinusT)){error('overflow');}w*=baseMinusT;}const out=output.length+1;bias=adapt(i-oldi,out,oldi==0);// `i` was supposed to wrap around from `out` to `0`,
|
||
// incrementing `n` each time, so we'll fix that now:
|
||
if(floor(i/out)>maxInt-n){error('overflow');}n+=floor(i/out);i%=out;// Insert `n` at position `i` of the output.
|
||
output.splice(i++,0,n);}return String.fromCodePoint(...output);};/**
|
||
* Converts a string of Unicode symbols (e.g. a domain name label) to a
|
||
* Punycode string of ASCII-only symbols.
|
||
* @memberOf punycode
|
||
* @param {String} input The string of Unicode symbols.
|
||
* @returns {String} The resulting Punycode string of ASCII-only symbols.
|
||
*/const encode=function(input){const output=[];// Convert the input in UCS-2 to an array of Unicode code points.
|
||
input=ucs2decode(input);// Cache the length.
|
||
const inputLength=input.length;// Initialize the state.
|
||
let n=initialN;let delta=0;let bias=initialBias;// Handle the basic code points.
|
||
for(const currentValue of input){if(currentValue<0x80){output.push(stringFromCharCode(currentValue));}}const basicLength=output.length;let handledCPCount=basicLength;// `handledCPCount` is the number of code points that have been handled;
|
||
// `basicLength` is the number of basic code points.
|
||
// Finish the basic string with a delimiter unless it's empty.
|
||
if(basicLength){output.push(delimiter);}// Main encoding loop:
|
||
while(handledCPCount<inputLength){// All non-basic code points < n have been handled already. Find the next
|
||
// larger one:
|
||
let m=maxInt;for(const currentValue of input){if(currentValue>=n&¤tValue<m){m=currentValue;}}// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
|
||
// but guard against overflow.
|
||
const handledCPCountPlusOne=handledCPCount+1;if(m-n>floor((maxInt-delta)/handledCPCountPlusOne)){error('overflow');}delta+=(m-n)*handledCPCountPlusOne;n=m;for(const currentValue of input){if(currentValue<n&&++delta>maxInt){error('overflow');}if(currentValue===n){// Represent delta as a generalized variable-length integer.
|
||
let q=delta;for/* no condition */(let k=base;;k+=base){const t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(q<t){break;}const qMinusT=q-t;const baseMinusT=base-t;output.push(stringFromCharCode(digitToBasic(t+qMinusT%baseMinusT,0)));q=floor(qMinusT/baseMinusT);}output.push(stringFromCharCode(digitToBasic(q,0)));bias=adapt(delta,handledCPCountPlusOne,handledCPCount===basicLength);delta=0;++handledCPCount;}}++delta;++n;}return output.join('');};/**
|
||
* Converts a Punycode string representing a domain name or an email address
|
||
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
|
||
* it doesn't matter if you call it on a string that has already been
|
||
* converted to Unicode.
|
||
* @memberOf punycode
|
||
* @param {String} input The Punycoded domain name or email address to
|
||
* convert to Unicode.
|
||
* @returns {String} The Unicode representation of the given Punycode
|
||
* string.
|
||
*/const toUnicode=function(input){return mapDomain(input,function(string){return regexPunycode.test(string)?decode(string.slice(4).toLowerCase()):string;});};/**
|
||
* Converts a Unicode string representing a domain name or an email address to
|
||
* Punycode. Only the non-ASCII parts of the domain name will be converted,
|
||
* i.e. it doesn't matter if you call it with a domain that's already in
|
||
* ASCII.
|
||
* @memberOf punycode
|
||
* @param {String} input The domain name or email address to convert, as a
|
||
* Unicode string.
|
||
* @returns {String} The Punycode representation of the given domain name or
|
||
* email address.
|
||
*/const toASCII=function(input){return mapDomain(input,function(string){return regexNonASCII.test(string)?'xn--'+encode(string):string;});};/*--------------------------------------------------------------------------*//** Define the public API */const punycode={/**
|
||
* A string representing the current Punycode.js version number.
|
||
* @memberOf punycode
|
||
* @type String
|
||
*/'version':'2.3.1',/**
|
||
* An object of methods to convert from JavaScript's internal character
|
||
* representation (UCS-2) to Unicode code points, and back.
|
||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
||
* @memberOf punycode
|
||
* @type Object
|
||
*/'ucs2':{'decode':ucs2decode,'encode':ucs2encode},'decode':decode,'encode':encode,'toASCII':toASCII,'toUnicode':toUnicode};/* harmony default export */ __webpack_exports__["default"] = (punycode);
|
||
|
||
/***/ }),
|
||
|
||
/***/ 92972:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var formats=__webpack_require__(10681);var has=Object.prototype.hasOwnProperty;var isArray=Array.isArray;var hexTable=function(){var array=[];for(var i=0;i<256;++i){array.push('%'+((i<16?'0':'')+i.toString(16)).toUpperCase());}return array;}();var compactQueue=function compactQueue(queue){while(queue.length>1){var item=queue.pop();var obj=item.obj[item.prop];if(isArray(obj)){var compacted=[];for(var j=0;j<obj.length;++j){if(typeof obj[j]!=='undefined'){compacted.push(obj[j]);}}item.obj[item.prop]=compacted;}}};var arrayToObject=function arrayToObject(source,options){var obj=options&&options.plainObjects?{__proto__:null}:{};for(var i=0;i<source.length;++i){if(typeof source[i]!=='undefined'){obj[i]=source[i];}}return obj;};var merge=function merge(target,source,options){/* eslint no-param-reassign: 0 */if(!source){return target;}if(typeof source!=='object'&&typeof source!=='function'){if(isArray(target)){target.push(source);}else if(target&&typeof target==='object'){if(options&&(options.plainObjects||options.allowPrototypes)||!has.call(Object.prototype,source)){target[source]=true;}}else{return[target,source];}return target;}if(!target||typeof target!=='object'){return[target].concat(source);}var mergeTarget=target;if(isArray(target)&&!isArray(source)){mergeTarget=arrayToObject(target,options);}if(isArray(target)&&isArray(source)){source.forEach(function(item,i){if(has.call(target,i)){var targetItem=target[i];if(targetItem&&typeof targetItem==='object'&&item&&typeof item==='object'){target[i]=merge(targetItem,item,options);}else{target.push(item);}}else{target[i]=item;}});return target;}return Object.keys(source).reduce(function(acc,key){var value=source[key];if(has.call(acc,key)){acc[key]=merge(acc[key],value,options);}else{acc[key]=value;}return acc;},mergeTarget);};var assign=function assignSingleSource(target,source){return Object.keys(source).reduce(function(acc,key){acc[key]=source[key];return acc;},target);};var decode=function(str,defaultDecoder,charset){var strWithoutPlus=str.replace(/\+/g,' ');if(charset==='iso-8859-1'){// unescape never throws, no try...catch needed:
|
||
return strWithoutPlus.replace(/%[0-9a-f]{2}/gi,unescape);}// utf-8
|
||
try{return decodeURIComponent(strWithoutPlus);}catch(e){return strWithoutPlus;}};var limit=1024;/* eslint operator-linebreak: [2, "before"] */var encode=function encode(str,defaultEncoder,charset,kind,format){// This code was originally written by Brian White (mscdex) for the io.js core querystring library.
|
||
// It has been adapted here for stricter adherence to RFC 3986
|
||
if(str.length===0){return str;}var string=str;if(typeof str==='symbol'){string=Symbol.prototype.toString.call(str);}else if(typeof str!=='string'){string=String(str);}if(charset==='iso-8859-1'){return escape(string).replace(/%u[0-9a-f]{4}/gi,function($0){return'%26%23'+parseInt($0.slice(2),16)+'%3B';});}var out='';for(var j=0;j<string.length;j+=limit){var segment=string.length>=limit?string.slice(j,j+limit):string;var arr=[];for(var i=0;i<segment.length;++i){var c=segment.charCodeAt(i);if(c===0x2D// -
|
||
||c===0x2E// .
|
||
||c===0x5F// _
|
||
||c===0x7E// ~
|
||
||c>=0x30&&c<=0x39// 0-9
|
||
||c>=0x41&&c<=0x5A// a-z
|
||
||c>=0x61&&c<=0x7A// A-Z
|
||
||format===formats.RFC1738&&(c===0x28||c===0x29)// ( )
|
||
){arr[arr.length]=segment.charAt(i);continue;}if(c<0x80){arr[arr.length]=hexTable[c];continue;}if(c<0x800){arr[arr.length]=hexTable[0xC0|c>>6]+hexTable[0x80|c&0x3F];continue;}if(c<0xD800||c>=0xE000){arr[arr.length]=hexTable[0xE0|c>>12]+hexTable[0x80|c>>6&0x3F]+hexTable[0x80|c&0x3F];continue;}i+=1;c=0x10000+((c&0x3FF)<<10|segment.charCodeAt(i)&0x3FF);arr[arr.length]=hexTable[0xF0|c>>18]+hexTable[0x80|c>>12&0x3F]+hexTable[0x80|c>>6&0x3F]+hexTable[0x80|c&0x3F];}out+=arr.join('');}return out;};var compact=function compact(value){var queue=[{obj:{o:value},prop:'o'}];var refs=[];for(var i=0;i<queue.length;++i){var item=queue[i];var obj=item.obj[item.prop];var keys=Object.keys(obj);for(var j=0;j<keys.length;++j){var key=keys[j];var val=obj[key];if(typeof val==='object'&&val!==null&&refs.indexOf(val)===-1){queue.push({obj:obj,prop:key});refs.push(val);}}}compactQueue(queue);return value;};var isRegExp=function isRegExp(obj){return Object.prototype.toString.call(obj)==='[object RegExp]';};var isBuffer=function isBuffer(obj){if(!obj||typeof obj!=='object'){return false;}return!!(obj.constructor&&obj.constructor.isBuffer&&obj.constructor.isBuffer(obj));};var combine=function combine(a,b){return[].concat(a,b);};var maybeMap=function maybeMap(val,fn){if(isArray(val)){var mapped=[];for(var i=0;i<val.length;i+=1){mapped.push(fn(val[i]));}return mapped;}return fn(val);};module.exports={arrayToObject:arrayToObject,assign:assign,combine:combine,compact:compact,decode:decode,encode:encode,isBuffer:isBuffer,isRegExp:isRegExp,maybeMap:maybeMap,merge:merge};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 93425:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var $isNaN=__webpack_require__(75519);/** @type {import('./sign')} */module.exports=function sign(number){if($isNaN(number)||number===0){return number;}return number<0?-1:+1;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 93767:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('./type')} */module.exports=TypeError;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 94067:
|
||
/***/ (function(module) {
|
||
|
||
"use strict";
|
||
/** @type {import('.')} */module.exports=Error;
|
||
|
||
/***/ }),
|
||
|
||
/***/ 94087:
|
||
/***/ (function(__unused_webpack_module, exports) {
|
||
|
||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */exports.read=function(buffer,offset,isLE,mLen,nBytes){var e,m;var eLen=nBytes*8-mLen-1;var eMax=(1<<eLen)-1;var eBias=eMax>>1;var nBits=-7;var i=isLE?nBytes-1:0;var d=isLE?-1:1;var s=buffer[offset+i];i+=d;e=s&(1<<-nBits)-1;s>>=-nBits;nBits+=eLen;for(;nBits>0;e=e*256+buffer[offset+i],i+=d,nBits-=8){}m=e&(1<<-nBits)-1;e>>=-nBits;nBits+=mLen;for(;nBits>0;m=m*256+buffer[offset+i],i+=d,nBits-=8){}if(e===0){e=1-eBias;}else if(e===eMax){return m?NaN:(s?-1:1)*Infinity;}else{m=m+Math.pow(2,mLen);e=e-eBias;}return(s?-1:1)*m*Math.pow(2,e-mLen);};exports.write=function(buffer,value,offset,isLE,mLen,nBytes){var e,m,c;var eLen=nBytes*8-mLen-1;var eMax=(1<<eLen)-1;var eBias=eMax>>1;var rt=mLen===23?Math.pow(2,-24)-Math.pow(2,-77):0;var i=isLE?0:nBytes-1;var d=isLE?1:-1;var s=value<0||value===0&&1/value<0?1:0;value=Math.abs(value);if(isNaN(value)||value===Infinity){m=isNaN(value)?1:0;e=eMax;}else{e=Math.floor(Math.log(value)/Math.LN2);if(value*(c=Math.pow(2,-e))<1){e--;c*=2;}if(e+eBias>=1){value+=rt/c;}else{value+=rt*Math.pow(2,1-eBias);}if(value*c>=2){e++;c/=2;}if(e+eBias>=eMax){m=0;e=eMax;}else if(e+eBias>=1){m=(value*c-1)*Math.pow(2,mLen);e=e+eBias;}else{m=value*Math.pow(2,eBias-1)*Math.pow(2,mLen);e=0;}}for(;mLen>=8;buffer[offset+i]=m&0xff,i+=d,m/=256,mLen-=8){}e=e<<mLen|m;eLen+=mLen;for(;eLen>0;buffer[offset+i]=e&0xff,i+=d,e/=256,eLen-=8){}buffer[offset+i-d]|=s*128;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 95736:
|
||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var GetIntrinsic=__webpack_require__(35049);var callBindBasic=__webpack_require__(77434);/** @type {(thisArg: string, searchString: string, position?: number) => number} */var $indexOf=callBindBasic([GetIntrinsic('%String.prototype.indexOf%')]);/** @type {import('.')} */module.exports=function callBoundIntrinsic(name,allowMissing){/* eslint no-extra-parens: 0 */var intrinsic=/** @type {(this: unknown, ...args: unknown[]) => unknown} */GetIntrinsic(name,!!allowMissing);if(typeof intrinsic==='function'&&$indexOf(name,'.prototype.')>-1){return callBindBasic(/** @type {const} */[intrinsic]);}return intrinsic;};
|
||
|
||
/***/ }),
|
||
|
||
/***/ 97763:
|
||
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
var __webpack_unused_export__;
|
||
/*!
|
||
* The buffer module from node.js, for the browser.
|
||
*
|
||
* @author Feross Aboukhadijeh <https://feross.org>
|
||
* @license MIT
|
||
*//* eslint-disable no-proto */const base64=__webpack_require__(31506);const ieee754=__webpack_require__(94087);const customInspectSymbol=typeof Symbol==='function'&&typeof Symbol['for']==='function'// eslint-disable-line dot-notation
|
||
?Symbol['for']('nodejs.util.inspect.custom')// eslint-disable-line dot-notation
|
||
:null;exports.hp=Buffer;__webpack_unused_export__=SlowBuffer;exports.IS=50;const K_MAX_LENGTH=0x7fffffff;__webpack_unused_export__=K_MAX_LENGTH;/**
|
||
* If `Buffer.TYPED_ARRAY_SUPPORT`:
|
||
* === true Use Uint8Array implementation (fastest)
|
||
* === false Print warning and recommend using `buffer` v4.x which has an Object
|
||
* implementation (most compatible, even IE6)
|
||
*
|
||
* Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
|
||
* Opera 11.6+, iOS 4.2+.
|
||
*
|
||
* We report that the browser does not support typed arrays if the are not subclassable
|
||
* using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array`
|
||
* (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support
|
||
* for __proto__ and has a buggy typed array implementation.
|
||
*/Buffer.TYPED_ARRAY_SUPPORT=typedArraySupport();if(!Buffer.TYPED_ARRAY_SUPPORT&&typeof console!=='undefined'&&typeof console.error==='function'){console.error('This browser lacks typed array (Uint8Array) support which is required by '+'`buffer` v5.x. Use `buffer` v4.x if you require old browser support.');}function typedArraySupport(){// Can typed array instances can be augmented?
|
||
try{const arr=new Uint8Array(1);const proto={foo:function(){return 42;}};Object.setPrototypeOf(proto,Uint8Array.prototype);Object.setPrototypeOf(arr,proto);return arr.foo()===42;}catch(e){return false;}}Object.defineProperty(Buffer.prototype,'parent',{enumerable:true,get:function(){if(!Buffer.isBuffer(this))return undefined;return this.buffer;}});Object.defineProperty(Buffer.prototype,'offset',{enumerable:true,get:function(){if(!Buffer.isBuffer(this))return undefined;return this.byteOffset;}});function createBuffer(length){if(length>K_MAX_LENGTH){throw new RangeError('The value "'+length+'" is invalid for option "size"');}// Return an augmented `Uint8Array` instance
|
||
const buf=new Uint8Array(length);Object.setPrototypeOf(buf,Buffer.prototype);return buf;}/**
|
||
* The Buffer constructor returns instances of `Uint8Array` that have their
|
||
* prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
|
||
* `Uint8Array`, so the returned instances will have all the node `Buffer` methods
|
||
* and the `Uint8Array` methods. Square bracket notation works as expected -- it
|
||
* returns a single octet.
|
||
*
|
||
* The `Uint8Array` prototype remains unmodified.
|
||
*/function Buffer(arg,encodingOrOffset,length){// Common case.
|
||
if(typeof arg==='number'){if(typeof encodingOrOffset==='string'){throw new TypeError('The "string" argument must be of type string. Received type number');}return allocUnsafe(arg);}return from(arg,encodingOrOffset,length);}Buffer.poolSize=8192;// not used by this implementation
|
||
function from(value,encodingOrOffset,length){if(typeof value==='string'){return fromString(value,encodingOrOffset);}if(ArrayBuffer.isView(value)){return fromArrayView(value);}if(value==null){throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, '+'or Array-like Object. Received type '+typeof value);}if(isInstance(value,ArrayBuffer)||value&&isInstance(value.buffer,ArrayBuffer)){return fromArrayBuffer(value,encodingOrOffset,length);}if(typeof SharedArrayBuffer!=='undefined'&&(isInstance(value,SharedArrayBuffer)||value&&isInstance(value.buffer,SharedArrayBuffer))){return fromArrayBuffer(value,encodingOrOffset,length);}if(typeof value==='number'){throw new TypeError('The "value" argument must not be of type number. Received type number');}const valueOf=value.valueOf&&value.valueOf();if(valueOf!=null&&valueOf!==value){return Buffer.from(valueOf,encodingOrOffset,length);}const b=fromObject(value);if(b)return b;if(typeof Symbol!=='undefined'&&Symbol.toPrimitive!=null&&typeof value[Symbol.toPrimitive]==='function'){return Buffer.from(value[Symbol.toPrimitive]('string'),encodingOrOffset,length);}throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, '+'or Array-like Object. Received type '+typeof value);}/**
|
||
* Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
|
||
* if value is a number.
|
||
* Buffer.from(str[, encoding])
|
||
* Buffer.from(array)
|
||
* Buffer.from(buffer)
|
||
* Buffer.from(arrayBuffer[, byteOffset[, length]])
|
||
**/Buffer.from=function(value,encodingOrOffset,length){return from(value,encodingOrOffset,length);};// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug:
|
||
// https://github.com/feross/buffer/pull/148
|
||
Object.setPrototypeOf(Buffer.prototype,Uint8Array.prototype);Object.setPrototypeOf(Buffer,Uint8Array);function assertSize(size){if(typeof size!=='number'){throw new TypeError('"size" argument must be of type number');}else if(size<0){throw new RangeError('The value "'+size+'" is invalid for option "size"');}}function alloc(size,fill,encoding){assertSize(size);if(size<=0){return createBuffer(size);}if(fill!==undefined){// Only pay attention to encoding if it's a string. This
|
||
// prevents accidentally sending in a number that would
|
||
// be interpreted as a start offset.
|
||
return typeof encoding==='string'?createBuffer(size).fill(fill,encoding):createBuffer(size).fill(fill);}return createBuffer(size);}/**
|
||
* Creates a new filled Buffer instance.
|
||
* alloc(size[, fill[, encoding]])
|
||
**/Buffer.alloc=function(size,fill,encoding){return alloc(size,fill,encoding);};function allocUnsafe(size){assertSize(size);return createBuffer(size<0?0:checked(size)|0);}/**
|
||
* Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
|
||
* */Buffer.allocUnsafe=function(size){return allocUnsafe(size);};/**
|
||
* Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
|
||
*/Buffer.allocUnsafeSlow=function(size){return allocUnsafe(size);};function fromString(string,encoding){if(typeof encoding!=='string'||encoding===''){encoding='utf8';}if(!Buffer.isEncoding(encoding)){throw new TypeError('Unknown encoding: '+encoding);}const length=byteLength(string,encoding)|0;let buf=createBuffer(length);const actual=buf.write(string,encoding);if(actual!==length){// Writing a hex string, for example, that contains invalid characters will
|
||
// cause everything after the first invalid character to be ignored. (e.g.
|
||
// 'abxxcd' will be treated as 'ab')
|
||
buf=buf.slice(0,actual);}return buf;}function fromArrayLike(array){const length=array.length<0?0:checked(array.length)|0;const buf=createBuffer(length);for(let i=0;i<length;i+=1){buf[i]=array[i]&255;}return buf;}function fromArrayView(arrayView){if(isInstance(arrayView,Uint8Array)){const copy=new Uint8Array(arrayView);return fromArrayBuffer(copy.buffer,copy.byteOffset,copy.byteLength);}return fromArrayLike(arrayView);}function fromArrayBuffer(array,byteOffset,length){if(byteOffset<0||array.byteLength<byteOffset){throw new RangeError('"offset" is outside of buffer bounds');}if(array.byteLength<byteOffset+(length||0)){throw new RangeError('"length" is outside of buffer bounds');}let buf;if(byteOffset===undefined&&length===undefined){buf=new Uint8Array(array);}else if(length===undefined){buf=new Uint8Array(array,byteOffset);}else{buf=new Uint8Array(array,byteOffset,length);}// Return an augmented `Uint8Array` instance
|
||
Object.setPrototypeOf(buf,Buffer.prototype);return buf;}function fromObject(obj){if(Buffer.isBuffer(obj)){const len=checked(obj.length)|0;const buf=createBuffer(len);if(buf.length===0){return buf;}obj.copy(buf,0,0,len);return buf;}if(obj.length!==undefined){if(typeof obj.length!=='number'||numberIsNaN(obj.length)){return createBuffer(0);}return fromArrayLike(obj);}if(obj.type==='Buffer'&&Array.isArray(obj.data)){return fromArrayLike(obj.data);}}function checked(length){// Note: cannot use `length < K_MAX_LENGTH` here because that fails when
|
||
// length is NaN (which is otherwise coerced to zero.)
|
||
if(length>=K_MAX_LENGTH){throw new RangeError('Attempt to allocate Buffer larger than maximum '+'size: 0x'+K_MAX_LENGTH.toString(16)+' bytes');}return length|0;}function SlowBuffer(length){if(+length!=length){// eslint-disable-line eqeqeq
|
||
length=0;}return Buffer.alloc(+length);}Buffer.isBuffer=function isBuffer(b){return b!=null&&b._isBuffer===true&&b!==Buffer.prototype;// so Buffer.isBuffer(Buffer.prototype) will be false
|
||
};Buffer.compare=function compare(a,b){if(isInstance(a,Uint8Array))a=Buffer.from(a,a.offset,a.byteLength);if(isInstance(b,Uint8Array))b=Buffer.from(b,b.offset,b.byteLength);if(!Buffer.isBuffer(a)||!Buffer.isBuffer(b)){throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');}if(a===b)return 0;let x=a.length;let y=b.length;for(let i=0,len=Math.min(x,y);i<len;++i){if(a[i]!==b[i]){x=a[i];y=b[i];break;}}if(x<y)return-1;if(y<x)return 1;return 0;};Buffer.isEncoding=function isEncoding(encoding){switch(String(encoding).toLowerCase()){case'hex':case'utf8':case'utf-8':case'ascii':case'latin1':case'binary':case'base64':case'ucs2':case'ucs-2':case'utf16le':case'utf-16le':return true;default:return false;}};Buffer.concat=function concat(list,length){if(!Array.isArray(list)){throw new TypeError('"list" argument must be an Array of Buffers');}if(list.length===0){return Buffer.alloc(0);}let i;if(length===undefined){length=0;for(i=0;i<list.length;++i){length+=list[i].length;}}const buffer=Buffer.allocUnsafe(length);let pos=0;for(i=0;i<list.length;++i){let buf=list[i];if(isInstance(buf,Uint8Array)){if(pos+buf.length>buffer.length){if(!Buffer.isBuffer(buf))buf=Buffer.from(buf);buf.copy(buffer,pos);}else{Uint8Array.prototype.set.call(buffer,buf,pos);}}else if(!Buffer.isBuffer(buf)){throw new TypeError('"list" argument must be an Array of Buffers');}else{buf.copy(buffer,pos);}pos+=buf.length;}return buffer;};function byteLength(string,encoding){if(Buffer.isBuffer(string)){return string.length;}if(ArrayBuffer.isView(string)||isInstance(string,ArrayBuffer)){return string.byteLength;}if(typeof string!=='string'){throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. '+'Received type '+typeof string);}const len=string.length;const mustMatch=arguments.length>2&&arguments[2]===true;if(!mustMatch&&len===0)return 0;// Use a for loop to avoid recursion
|
||
let loweredCase=false;for(;;){switch(encoding){case'ascii':case'latin1':case'binary':return len;case'utf8':case'utf-8':return utf8ToBytes(string).length;case'ucs2':case'ucs-2':case'utf16le':case'utf-16le':return len*2;case'hex':return len>>>1;case'base64':return base64ToBytes(string).length;default:if(loweredCase){return mustMatch?-1:utf8ToBytes(string).length;// assume utf8
|
||
}encoding=(''+encoding).toLowerCase();loweredCase=true;}}}Buffer.byteLength=byteLength;function slowToString(encoding,start,end){let loweredCase=false;// No need to verify that "this.length <= MAX_UINT32" since it's a read-only
|
||
// property of a typed array.
|
||
// This behaves neither like String nor Uint8Array in that we set start/end
|
||
// to their upper/lower bounds if the value passed is out of range.
|
||
// undefined is handled specially as per ECMA-262 6th Edition,
|
||
// Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
|
||
if(start===undefined||start<0){start=0;}// Return early if start > this.length. Done here to prevent potential uint32
|
||
// coercion fail below.
|
||
if(start>this.length){return'';}if(end===undefined||end>this.length){end=this.length;}if(end<=0){return'';}// Force coercion to uint32. This will also coerce falsey/NaN values to 0.
|
||
end>>>=0;start>>>=0;if(end<=start){return'';}if(!encoding)encoding='utf8';while(true){switch(encoding){case'hex':return hexSlice(this,start,end);case'utf8':case'utf-8':return utf8Slice(this,start,end);case'ascii':return asciiSlice(this,start,end);case'latin1':case'binary':return latin1Slice(this,start,end);case'base64':return base64Slice(this,start,end);case'ucs2':case'ucs-2':case'utf16le':case'utf-16le':return utf16leSlice(this,start,end);default:if(loweredCase)throw new TypeError('Unknown encoding: '+encoding);encoding=(encoding+'').toLowerCase();loweredCase=true;}}}// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package)
|
||
// to detect a Buffer instance. It's not possible to use `instanceof Buffer`
|
||
// reliably in a browserify context because there could be multiple different
|
||
// copies of the 'buffer' package in use. This method works even for Buffer
|
||
// instances that were created from another copy of the `buffer` package.
|
||
// See: https://github.com/feross/buffer/issues/154
|
||
Buffer.prototype._isBuffer=true;function swap(b,n,m){const i=b[n];b[n]=b[m];b[m]=i;}Buffer.prototype.swap16=function swap16(){const len=this.length;if(len%2!==0){throw new RangeError('Buffer size must be a multiple of 16-bits');}for(let i=0;i<len;i+=2){swap(this,i,i+1);}return this;};Buffer.prototype.swap32=function swap32(){const len=this.length;if(len%4!==0){throw new RangeError('Buffer size must be a multiple of 32-bits');}for(let i=0;i<len;i+=4){swap(this,i,i+3);swap(this,i+1,i+2);}return this;};Buffer.prototype.swap64=function swap64(){const len=this.length;if(len%8!==0){throw new RangeError('Buffer size must be a multiple of 64-bits');}for(let i=0;i<len;i+=8){swap(this,i,i+7);swap(this,i+1,i+6);swap(this,i+2,i+5);swap(this,i+3,i+4);}return this;};Buffer.prototype.toString=function toString(){const length=this.length;if(length===0)return'';if(arguments.length===0)return utf8Slice(this,0,length);return slowToString.apply(this,arguments);};Buffer.prototype.toLocaleString=Buffer.prototype.toString;Buffer.prototype.equals=function equals(b){if(!Buffer.isBuffer(b))throw new TypeError('Argument must be a Buffer');if(this===b)return true;return Buffer.compare(this,b)===0;};Buffer.prototype.inspect=function inspect(){let str='';const max=exports.IS;str=this.toString('hex',0,max).replace(/(.{2})/g,'$1 ').trim();if(this.length>max)str+=' ... ';return'<Buffer '+str+'>';};if(customInspectSymbol){Buffer.prototype[customInspectSymbol]=Buffer.prototype.inspect;}Buffer.prototype.compare=function compare(target,start,end,thisStart,thisEnd){if(isInstance(target,Uint8Array)){target=Buffer.from(target,target.offset,target.byteLength);}if(!Buffer.isBuffer(target)){throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. '+'Received type '+typeof target);}if(start===undefined){start=0;}if(end===undefined){end=target?target.length:0;}if(thisStart===undefined){thisStart=0;}if(thisEnd===undefined){thisEnd=this.length;}if(start<0||end>target.length||thisStart<0||thisEnd>this.length){throw new RangeError('out of range index');}if(thisStart>=thisEnd&&start>=end){return 0;}if(thisStart>=thisEnd){return-1;}if(start>=end){return 1;}start>>>=0;end>>>=0;thisStart>>>=0;thisEnd>>>=0;if(this===target)return 0;let x=thisEnd-thisStart;let y=end-start;const len=Math.min(x,y);const thisCopy=this.slice(thisStart,thisEnd);const targetCopy=target.slice(start,end);for(let i=0;i<len;++i){if(thisCopy[i]!==targetCopy[i]){x=thisCopy[i];y=targetCopy[i];break;}}if(x<y)return-1;if(y<x)return 1;return 0;};// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
|
||
// OR the last index of `val` in `buffer` at offset <= `byteOffset`.
|
||
//
|
||
// Arguments:
|
||
// - buffer - a Buffer to search
|
||
// - val - a string, Buffer, or number
|
||
// - byteOffset - an index into `buffer`; will be clamped to an int32
|
||
// - encoding - an optional encoding, relevant is val is a string
|
||
// - dir - true for indexOf, false for lastIndexOf
|
||
function bidirectionalIndexOf(buffer,val,byteOffset,encoding,dir){// Empty buffer means no match
|
||
if(buffer.length===0)return-1;// Normalize byteOffset
|
||
if(typeof byteOffset==='string'){encoding=byteOffset;byteOffset=0;}else if(byteOffset>0x7fffffff){byteOffset=0x7fffffff;}else if(byteOffset<-0x80000000){byteOffset=-0x80000000;}byteOffset=+byteOffset;// Coerce to Number.
|
||
if(numberIsNaN(byteOffset)){// byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
|
||
byteOffset=dir?0:buffer.length-1;}// Normalize byteOffset: negative offsets start from the end of the buffer
|
||
if(byteOffset<0)byteOffset=buffer.length+byteOffset;if(byteOffset>=buffer.length){if(dir)return-1;else byteOffset=buffer.length-1;}else if(byteOffset<0){if(dir)byteOffset=0;else return-1;}// Normalize val
|
||
if(typeof val==='string'){val=Buffer.from(val,encoding);}// Finally, search either indexOf (if dir is true) or lastIndexOf
|
||
if(Buffer.isBuffer(val)){// Special case: looking for empty string/buffer always fails
|
||
if(val.length===0){return-1;}return arrayIndexOf(buffer,val,byteOffset,encoding,dir);}else if(typeof val==='number'){val=val&0xFF;// Search for a byte value [0-255]
|
||
if(typeof Uint8Array.prototype.indexOf==='function'){if(dir){return Uint8Array.prototype.indexOf.call(buffer,val,byteOffset);}else{return Uint8Array.prototype.lastIndexOf.call(buffer,val,byteOffset);}}return arrayIndexOf(buffer,[val],byteOffset,encoding,dir);}throw new TypeError('val must be string, number or Buffer');}function arrayIndexOf(arr,val,byteOffset,encoding,dir){let indexSize=1;let arrLength=arr.length;let valLength=val.length;if(encoding!==undefined){encoding=String(encoding).toLowerCase();if(encoding==='ucs2'||encoding==='ucs-2'||encoding==='utf16le'||encoding==='utf-16le'){if(arr.length<2||val.length<2){return-1;}indexSize=2;arrLength/=2;valLength/=2;byteOffset/=2;}}function read(buf,i){if(indexSize===1){return buf[i];}else{return buf.readUInt16BE(i*indexSize);}}let i;if(dir){let foundIndex=-1;for(i=byteOffset;i<arrLength;i++){if(read(arr,i)===read(val,foundIndex===-1?0:i-foundIndex)){if(foundIndex===-1)foundIndex=i;if(i-foundIndex+1===valLength)return foundIndex*indexSize;}else{if(foundIndex!==-1)i-=i-foundIndex;foundIndex=-1;}}}else{if(byteOffset+valLength>arrLength)byteOffset=arrLength-valLength;for(i=byteOffset;i>=0;i--){let found=true;for(let j=0;j<valLength;j++){if(read(arr,i+j)!==read(val,j)){found=false;break;}}if(found)return i;}}return-1;}Buffer.prototype.includes=function includes(val,byteOffset,encoding){return this.indexOf(val,byteOffset,encoding)!==-1;};Buffer.prototype.indexOf=function indexOf(val,byteOffset,encoding){return bidirectionalIndexOf(this,val,byteOffset,encoding,true);};Buffer.prototype.lastIndexOf=function lastIndexOf(val,byteOffset,encoding){return bidirectionalIndexOf(this,val,byteOffset,encoding,false);};function hexWrite(buf,string,offset,length){offset=Number(offset)||0;const remaining=buf.length-offset;if(!length){length=remaining;}else{length=Number(length);if(length>remaining){length=remaining;}}const strLen=string.length;if(length>strLen/2){length=strLen/2;}let i;for(i=0;i<length;++i){const parsed=parseInt(string.substr(i*2,2),16);if(numberIsNaN(parsed))return i;buf[offset+i]=parsed;}return i;}function utf8Write(buf,string,offset,length){return blitBuffer(utf8ToBytes(string,buf.length-offset),buf,offset,length);}function asciiWrite(buf,string,offset,length){return blitBuffer(asciiToBytes(string),buf,offset,length);}function base64Write(buf,string,offset,length){return blitBuffer(base64ToBytes(string),buf,offset,length);}function ucs2Write(buf,string,offset,length){return blitBuffer(utf16leToBytes(string,buf.length-offset),buf,offset,length);}Buffer.prototype.write=function write(string,offset,length,encoding){// Buffer#write(string)
|
||
if(offset===undefined){encoding='utf8';length=this.length;offset=0;// Buffer#write(string, encoding)
|
||
}else if(length===undefined&&typeof offset==='string'){encoding=offset;length=this.length;offset=0;// Buffer#write(string, offset[, length][, encoding])
|
||
}else if(isFinite(offset)){offset=offset>>>0;if(isFinite(length)){length=length>>>0;if(encoding===undefined)encoding='utf8';}else{encoding=length;length=undefined;}}else{throw new Error('Buffer.write(string, encoding, offset[, length]) is no longer supported');}const remaining=this.length-offset;if(length===undefined||length>remaining)length=remaining;if(string.length>0&&(length<0||offset<0)||offset>this.length){throw new RangeError('Attempt to write outside buffer bounds');}if(!encoding)encoding='utf8';let loweredCase=false;for(;;){switch(encoding){case'hex':return hexWrite(this,string,offset,length);case'utf8':case'utf-8':return utf8Write(this,string,offset,length);case'ascii':case'latin1':case'binary':return asciiWrite(this,string,offset,length);case'base64':// Warning: maxLength not taken into account in base64Write
|
||
return base64Write(this,string,offset,length);case'ucs2':case'ucs-2':case'utf16le':case'utf-16le':return ucs2Write(this,string,offset,length);default:if(loweredCase)throw new TypeError('Unknown encoding: '+encoding);encoding=(''+encoding).toLowerCase();loweredCase=true;}}};Buffer.prototype.toJSON=function toJSON(){return{type:'Buffer',data:Array.prototype.slice.call(this._arr||this,0)};};function base64Slice(buf,start,end){if(start===0&&end===buf.length){return base64.fromByteArray(buf);}else{return base64.fromByteArray(buf.slice(start,end));}}function utf8Slice(buf,start,end){end=Math.min(buf.length,end);const res=[];let i=start;while(i<end){const firstByte=buf[i];let codePoint=null;let bytesPerSequence=firstByte>0xEF?4:firstByte>0xDF?3:firstByte>0xBF?2:1;if(i+bytesPerSequence<=end){let secondByte,thirdByte,fourthByte,tempCodePoint;switch(bytesPerSequence){case 1:if(firstByte<0x80){codePoint=firstByte;}break;case 2:secondByte=buf[i+1];if((secondByte&0xC0)===0x80){tempCodePoint=(firstByte&0x1F)<<0x6|secondByte&0x3F;if(tempCodePoint>0x7F){codePoint=tempCodePoint;}}break;case 3:secondByte=buf[i+1];thirdByte=buf[i+2];if((secondByte&0xC0)===0x80&&(thirdByte&0xC0)===0x80){tempCodePoint=(firstByte&0xF)<<0xC|(secondByte&0x3F)<<0x6|thirdByte&0x3F;if(tempCodePoint>0x7FF&&(tempCodePoint<0xD800||tempCodePoint>0xDFFF)){codePoint=tempCodePoint;}}break;case 4:secondByte=buf[i+1];thirdByte=buf[i+2];fourthByte=buf[i+3];if((secondByte&0xC0)===0x80&&(thirdByte&0xC0)===0x80&&(fourthByte&0xC0)===0x80){tempCodePoint=(firstByte&0xF)<<0x12|(secondByte&0x3F)<<0xC|(thirdByte&0x3F)<<0x6|fourthByte&0x3F;if(tempCodePoint>0xFFFF&&tempCodePoint<0x110000){codePoint=tempCodePoint;}}}}if(codePoint===null){// we did not generate a valid codePoint so insert a
|
||
// replacement char (U+FFFD) and advance only 1 byte
|
||
codePoint=0xFFFD;bytesPerSequence=1;}else if(codePoint>0xFFFF){// encode to utf16 (surrogate pair dance)
|
||
codePoint-=0x10000;res.push(codePoint>>>10&0x3FF|0xD800);codePoint=0xDC00|codePoint&0x3FF;}res.push(codePoint);i+=bytesPerSequence;}return decodeCodePointsArray(res);}// Based on http://stackoverflow.com/a/22747272/680742, the browser with
|
||
// the lowest limit is Chrome, with 0x10000 args.
|
||
// We go 1 magnitude less, for safety
|
||
const MAX_ARGUMENTS_LENGTH=0x1000;function decodeCodePointsArray(codePoints){const len=codePoints.length;if(len<=MAX_ARGUMENTS_LENGTH){return String.fromCharCode.apply(String,codePoints);// avoid extra slice()
|
||
}// Decode in chunks to avoid "call stack size exceeded".
|
||
let res='';let i=0;while(i<len){res+=String.fromCharCode.apply(String,codePoints.slice(i,i+=MAX_ARGUMENTS_LENGTH));}return res;}function asciiSlice(buf,start,end){let ret='';end=Math.min(buf.length,end);for(let i=start;i<end;++i){ret+=String.fromCharCode(buf[i]&0x7F);}return ret;}function latin1Slice(buf,start,end){let ret='';end=Math.min(buf.length,end);for(let i=start;i<end;++i){ret+=String.fromCharCode(buf[i]);}return ret;}function hexSlice(buf,start,end){const len=buf.length;if(!start||start<0)start=0;if(!end||end<0||end>len)end=len;let out='';for(let i=start;i<end;++i){out+=hexSliceLookupTable[buf[i]];}return out;}function utf16leSlice(buf,start,end){const bytes=buf.slice(start,end);let res='';// If bytes.length is odd, the last 8 bits must be ignored (same as node.js)
|
||
for(let i=0;i<bytes.length-1;i+=2){res+=String.fromCharCode(bytes[i]+bytes[i+1]*256);}return res;}Buffer.prototype.slice=function slice(start,end){const len=this.length;start=~~start;end=end===undefined?len:~~end;if(start<0){start+=len;if(start<0)start=0;}else if(start>len){start=len;}if(end<0){end+=len;if(end<0)end=0;}else if(end>len){end=len;}if(end<start)end=start;const newBuf=this.subarray(start,end);// Return an augmented `Uint8Array` instance
|
||
Object.setPrototypeOf(newBuf,Buffer.prototype);return newBuf;};/*
|
||
* Need to make sure that buffer isn't trying to write out of bounds.
|
||
*/function checkOffset(offset,ext,length){if(offset%1!==0||offset<0)throw new RangeError('offset is not uint');if(offset+ext>length)throw new RangeError('Trying to access beyond buffer length');}Buffer.prototype.readUintLE=Buffer.prototype.readUIntLE=function readUIntLE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);let val=this[offset];let mul=1;let i=0;while(++i<byteLength&&(mul*=0x100)){val+=this[offset+i]*mul;}return val;};Buffer.prototype.readUintBE=Buffer.prototype.readUIntBE=function readUIntBE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert){checkOffset(offset,byteLength,this.length);}let val=this[offset+--byteLength];let mul=1;while(byteLength>0&&(mul*=0x100)){val+=this[offset+--byteLength]*mul;}return val;};Buffer.prototype.readUint8=Buffer.prototype.readUInt8=function readUInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);return this[offset];};Buffer.prototype.readUint16LE=Buffer.prototype.readUInt16LE=function readUInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]|this[offset+1]<<8;};Buffer.prototype.readUint16BE=Buffer.prototype.readUInt16BE=function readUInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);return this[offset]<<8|this[offset+1];};Buffer.prototype.readUint32LE=Buffer.prototype.readUInt32LE=function readUInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return(this[offset]|this[offset+1]<<8|this[offset+2]<<16)+this[offset+3]*0x1000000;};Buffer.prototype.readUint32BE=Buffer.prototype.readUInt32BE=function readUInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]*0x1000000+(this[offset+1]<<16|this[offset+2]<<8|this[offset+3]);};Buffer.prototype.readBigUInt64LE=defineBigIntMethod(function readBigUInt64LE(offset){offset=offset>>>0;validateNumber(offset,'offset');const first=this[offset];const last=this[offset+7];if(first===undefined||last===undefined){boundsError(offset,this.length-8);}const lo=first+this[++offset]*2**8+this[++offset]*2**16+this[++offset]*2**24;const hi=this[++offset]+this[++offset]*2**8+this[++offset]*2**16+last*2**24;return BigInt(lo)+(BigInt(hi)<<BigInt(32));});Buffer.prototype.readBigUInt64BE=defineBigIntMethod(function readBigUInt64BE(offset){offset=offset>>>0;validateNumber(offset,'offset');const first=this[offset];const last=this[offset+7];if(first===undefined||last===undefined){boundsError(offset,this.length-8);}const hi=first*2**24+this[++offset]*2**16+this[++offset]*2**8+this[++offset];const lo=this[++offset]*2**24+this[++offset]*2**16+this[++offset]*2**8+last;return(BigInt(hi)<<BigInt(32))+BigInt(lo);});Buffer.prototype.readIntLE=function readIntLE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);let val=this[offset];let mul=1;let i=0;while(++i<byteLength&&(mul*=0x100)){val+=this[offset+i]*mul;}mul*=0x80;if(val>=mul)val-=Math.pow(2,8*byteLength);return val;};Buffer.prototype.readIntBE=function readIntBE(offset,byteLength,noAssert){offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert)checkOffset(offset,byteLength,this.length);let i=byteLength;let mul=1;let val=this[offset+--i];while(i>0&&(mul*=0x100)){val+=this[offset+--i]*mul;}mul*=0x80;if(val>=mul)val-=Math.pow(2,8*byteLength);return val;};Buffer.prototype.readInt8=function readInt8(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,1,this.length);if(!(this[offset]&0x80))return this[offset];return(0xff-this[offset]+1)*-1;};Buffer.prototype.readInt16LE=function readInt16LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);const val=this[offset]|this[offset+1]<<8;return val&0x8000?val|0xFFFF0000:val;};Buffer.prototype.readInt16BE=function readInt16BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,2,this.length);const val=this[offset+1]|this[offset]<<8;return val&0x8000?val|0xFFFF0000:val;};Buffer.prototype.readInt32LE=function readInt32LE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]|this[offset+1]<<8|this[offset+2]<<16|this[offset+3]<<24;};Buffer.prototype.readInt32BE=function readInt32BE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return this[offset]<<24|this[offset+1]<<16|this[offset+2]<<8|this[offset+3];};Buffer.prototype.readBigInt64LE=defineBigIntMethod(function readBigInt64LE(offset){offset=offset>>>0;validateNumber(offset,'offset');const first=this[offset];const last=this[offset+7];if(first===undefined||last===undefined){boundsError(offset,this.length-8);}const val=this[offset+4]+this[offset+5]*2**8+this[offset+6]*2**16+(last<<24);// Overflow
|
||
return(BigInt(val)<<BigInt(32))+BigInt(first+this[++offset]*2**8+this[++offset]*2**16+this[++offset]*2**24);});Buffer.prototype.readBigInt64BE=defineBigIntMethod(function readBigInt64BE(offset){offset=offset>>>0;validateNumber(offset,'offset');const first=this[offset];const last=this[offset+7];if(first===undefined||last===undefined){boundsError(offset,this.length-8);}const val=(first<<24)+// Overflow
|
||
this[++offset]*2**16+this[++offset]*2**8+this[++offset];return(BigInt(val)<<BigInt(32))+BigInt(this[++offset]*2**24+this[++offset]*2**16+this[++offset]*2**8+last);});Buffer.prototype.readFloatLE=function readFloatLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,true,23,4);};Buffer.prototype.readFloatBE=function readFloatBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,false,23,4);};Buffer.prototype.readDoubleLE=function readDoubleLE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,true,52,8);};Buffer.prototype.readDoubleBE=function readDoubleBE(offset,noAssert){offset=offset>>>0;if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,false,52,8);};function checkInt(buf,value,offset,ext,max,min){if(!Buffer.isBuffer(buf))throw new TypeError('"buffer" argument must be a Buffer instance');if(value>max||value<min)throw new RangeError('"value" argument is out of bounds');if(offset+ext>buf.length)throw new RangeError('Index out of range');}Buffer.prototype.writeUintLE=Buffer.prototype.writeUIntLE=function writeUIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert){const maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0);}let mul=1;let i=0;this[offset]=value&0xFF;while(++i<byteLength&&(mul*=0x100)){this[offset+i]=value/mul&0xFF;}return offset+byteLength;};Buffer.prototype.writeUintBE=Buffer.prototype.writeUIntBE=function writeUIntBE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;byteLength=byteLength>>>0;if(!noAssert){const maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0);}let i=byteLength-1;let mul=1;this[offset+i]=value&0xFF;while(--i>=0&&(mul*=0x100)){this[offset+i]=value/mul&0xFF;}return offset+byteLength;};Buffer.prototype.writeUint8=Buffer.prototype.writeUInt8=function writeUInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,0xff,0);this[offset]=value&0xff;return offset+1;};Buffer.prototype.writeUint16LE=Buffer.prototype.writeUInt16LE=function writeUInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,0xffff,0);this[offset]=value&0xff;this[offset+1]=value>>>8;return offset+2;};Buffer.prototype.writeUint16BE=Buffer.prototype.writeUInt16BE=function writeUInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,0xffff,0);this[offset]=value>>>8;this[offset+1]=value&0xff;return offset+2;};Buffer.prototype.writeUint32LE=Buffer.prototype.writeUInt32LE=function writeUInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,0xffffffff,0);this[offset+3]=value>>>24;this[offset+2]=value>>>16;this[offset+1]=value>>>8;this[offset]=value&0xff;return offset+4;};Buffer.prototype.writeUint32BE=Buffer.prototype.writeUInt32BE=function writeUInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,0xffffffff,0);this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&0xff;return offset+4;};function wrtBigUInt64LE(buf,value,offset,min,max){checkIntBI(value,min,max,buf,offset,7);let lo=Number(value&BigInt(0xffffffff));buf[offset++]=lo;lo=lo>>8;buf[offset++]=lo;lo=lo>>8;buf[offset++]=lo;lo=lo>>8;buf[offset++]=lo;let hi=Number(value>>BigInt(32)&BigInt(0xffffffff));buf[offset++]=hi;hi=hi>>8;buf[offset++]=hi;hi=hi>>8;buf[offset++]=hi;hi=hi>>8;buf[offset++]=hi;return offset;}function wrtBigUInt64BE(buf,value,offset,min,max){checkIntBI(value,min,max,buf,offset,7);let lo=Number(value&BigInt(0xffffffff));buf[offset+7]=lo;lo=lo>>8;buf[offset+6]=lo;lo=lo>>8;buf[offset+5]=lo;lo=lo>>8;buf[offset+4]=lo;let hi=Number(value>>BigInt(32)&BigInt(0xffffffff));buf[offset+3]=hi;hi=hi>>8;buf[offset+2]=hi;hi=hi>>8;buf[offset+1]=hi;hi=hi>>8;buf[offset]=hi;return offset+8;}Buffer.prototype.writeBigUInt64LE=defineBigIntMethod(function writeBigUInt64LE(value,offset=0){return wrtBigUInt64LE(this,value,offset,BigInt(0),BigInt('0xffffffffffffffff'));});Buffer.prototype.writeBigUInt64BE=defineBigIntMethod(function writeBigUInt64BE(value,offset=0){return wrtBigUInt64BE(this,value,offset,BigInt(0),BigInt('0xffffffffffffffff'));});Buffer.prototype.writeIntLE=function writeIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){const limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit);}let i=0;let mul=1;let sub=0;this[offset]=value&0xFF;while(++i<byteLength&&(mul*=0x100)){if(value<0&&sub===0&&this[offset+i-1]!==0){sub=1;}this[offset+i]=(value/mul>>0)-sub&0xFF;}return offset+byteLength;};Buffer.prototype.writeIntBE=function writeIntBE(value,offset,byteLength,noAssert){value=+value;offset=offset>>>0;if(!noAssert){const limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit);}let i=byteLength-1;let mul=1;let sub=0;this[offset+i]=value&0xFF;while(--i>=0&&(mul*=0x100)){if(value<0&&sub===0&&this[offset+i+1]!==0){sub=1;}this[offset+i]=(value/mul>>0)-sub&0xFF;}return offset+byteLength;};Buffer.prototype.writeInt8=function writeInt8(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,1,0x7f,-0x80);if(value<0)value=0xff+value+1;this[offset]=value&0xff;return offset+1;};Buffer.prototype.writeInt16LE=function writeInt16LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,0x7fff,-0x8000);this[offset]=value&0xff;this[offset+1]=value>>>8;return offset+2;};Buffer.prototype.writeInt16BE=function writeInt16BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,2,0x7fff,-0x8000);this[offset]=value>>>8;this[offset+1]=value&0xff;return offset+2;};Buffer.prototype.writeInt32LE=function writeInt32LE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,0x7fffffff,-0x80000000);this[offset]=value&0xff;this[offset+1]=value>>>8;this[offset+2]=value>>>16;this[offset+3]=value>>>24;return offset+4;};Buffer.prototype.writeInt32BE=function writeInt32BE(value,offset,noAssert){value=+value;offset=offset>>>0;if(!noAssert)checkInt(this,value,offset,4,0x7fffffff,-0x80000000);if(value<0)value=0xffffffff+value+1;this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&0xff;return offset+4;};Buffer.prototype.writeBigInt64LE=defineBigIntMethod(function writeBigInt64LE(value,offset=0){return wrtBigUInt64LE(this,value,offset,-BigInt('0x8000000000000000'),BigInt('0x7fffffffffffffff'));});Buffer.prototype.writeBigInt64BE=defineBigIntMethod(function writeBigInt64BE(value,offset=0){return wrtBigUInt64BE(this,value,offset,-BigInt('0x8000000000000000'),BigInt('0x7fffffffffffffff'));});function checkIEEE754(buf,value,offset,ext,max,min){if(offset+ext>buf.length)throw new RangeError('Index out of range');if(offset<0)throw new RangeError('Index out of range');}function writeFloat(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,4,3.4028234663852886e+38,-3.4028234663852886e+38);}ieee754.write(buf,value,offset,littleEndian,23,4);return offset+4;}Buffer.prototype.writeFloatLE=function writeFloatLE(value,offset,noAssert){return writeFloat(this,value,offset,true,noAssert);};Buffer.prototype.writeFloatBE=function writeFloatBE(value,offset,noAssert){return writeFloat(this,value,offset,false,noAssert);};function writeDouble(buf,value,offset,littleEndian,noAssert){value=+value;offset=offset>>>0;if(!noAssert){checkIEEE754(buf,value,offset,8,1.7976931348623157E+308,-1.7976931348623157E+308);}ieee754.write(buf,value,offset,littleEndian,52,8);return offset+8;}Buffer.prototype.writeDoubleLE=function writeDoubleLE(value,offset,noAssert){return writeDouble(this,value,offset,true,noAssert);};Buffer.prototype.writeDoubleBE=function writeDoubleBE(value,offset,noAssert){return writeDouble(this,value,offset,false,noAssert);};// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
||
Buffer.prototype.copy=function copy(target,targetStart,start,end){if(!Buffer.isBuffer(target))throw new TypeError('argument should be a Buffer');if(!start)start=0;if(!end&&end!==0)end=this.length;if(targetStart>=target.length)targetStart=target.length;if(!targetStart)targetStart=0;if(end>0&&end<start)end=start;// Copy 0 bytes; we're done
|
||
if(end===start)return 0;if(target.length===0||this.length===0)return 0;// Fatal error conditions
|
||
if(targetStart<0){throw new RangeError('targetStart out of bounds');}if(start<0||start>=this.length)throw new RangeError('Index out of range');if(end<0)throw new RangeError('sourceEnd out of bounds');// Are we oob?
|
||
if(end>this.length)end=this.length;if(target.length-targetStart<end-start){end=target.length-targetStart+start;}const len=end-start;if(this===target&&typeof Uint8Array.prototype.copyWithin==='function'){// Use built-in when available, missing from IE11
|
||
this.copyWithin(targetStart,start,end);}else{Uint8Array.prototype.set.call(target,this.subarray(start,end),targetStart);}return len;};// Usage:
|
||
// buffer.fill(number[, offset[, end]])
|
||
// buffer.fill(buffer[, offset[, end]])
|
||
// buffer.fill(string[, offset[, end]][, encoding])
|
||
Buffer.prototype.fill=function fill(val,start,end,encoding){// Handle string cases:
|
||
if(typeof val==='string'){if(typeof start==='string'){encoding=start;start=0;end=this.length;}else if(typeof end==='string'){encoding=end;end=this.length;}if(encoding!==undefined&&typeof encoding!=='string'){throw new TypeError('encoding must be a string');}if(typeof encoding==='string'&&!Buffer.isEncoding(encoding)){throw new TypeError('Unknown encoding: '+encoding);}if(val.length===1){const code=val.charCodeAt(0);if(encoding==='utf8'&&code<128||encoding==='latin1'){// Fast path: If `val` fits into a single byte, use that numeric value.
|
||
val=code;}}}else if(typeof val==='number'){val=val&255;}else if(typeof val==='boolean'){val=Number(val);}// Invalid ranges are not set to a default, so can range check early.
|
||
if(start<0||this.length<start||this.length<end){throw new RangeError('Out of range index');}if(end<=start){return this;}start=start>>>0;end=end===undefined?this.length:end>>>0;if(!val)val=0;let i;if(typeof val==='number'){for(i=start;i<end;++i){this[i]=val;}}else{const bytes=Buffer.isBuffer(val)?val:Buffer.from(val,encoding);const len=bytes.length;if(len===0){throw new TypeError('The value "'+val+'" is invalid for argument "value"');}for(i=0;i<end-start;++i){this[i+start]=bytes[i%len];}}return this;};// CUSTOM ERRORS
|
||
// =============
|
||
// Simplified versions from Node, changed for Buffer-only usage
|
||
const errors={};function E(sym,getMessage,Base){errors[sym]=class NodeError extends Base{constructor(){super();Object.defineProperty(this,'message',{value:getMessage.apply(this,arguments),writable:true,configurable:true});// Add the error code to the name to include it in the stack trace.
|
||
this.name=`${this.name} [${sym}]`;// Access the stack to generate the error message including the error code
|
||
// from the name.
|
||
this.stack;// eslint-disable-line no-unused-expressions
|
||
// Reset the name to the actual name.
|
||
delete this.name;}get code(){return sym;}set code(value){Object.defineProperty(this,'code',{configurable:true,enumerable:true,value,writable:true});}toString(){return`${this.name} [${sym}]: ${this.message}`;}};}E('ERR_BUFFER_OUT_OF_BOUNDS',function(name){if(name){return`${name} is outside of buffer bounds`;}return'Attempt to access memory outside buffer bounds';},RangeError);E('ERR_INVALID_ARG_TYPE',function(name,actual){return`The "${name}" argument must be of type number. Received type ${typeof actual}`;},TypeError);E('ERR_OUT_OF_RANGE',function(str,range,input){let msg=`The value of "${str}" is out of range.`;let received=input;if(Number.isInteger(input)&&Math.abs(input)>2**32){received=addNumericalSeparator(String(input));}else if(typeof input==='bigint'){received=String(input);if(input>BigInt(2)**BigInt(32)||input<-(BigInt(2)**BigInt(32))){received=addNumericalSeparator(received);}received+='n';}msg+=` It must be ${range}. Received ${received}`;return msg;},RangeError);function addNumericalSeparator(val){let res='';let i=val.length;const start=val[0]==='-'?1:0;for(;i>=start+4;i-=3){res=`_${val.slice(i-3,i)}${res}`;}return`${val.slice(0,i)}${res}`;}// CHECK FUNCTIONS
|
||
// ===============
|
||
function checkBounds(buf,offset,byteLength){validateNumber(offset,'offset');if(buf[offset]===undefined||buf[offset+byteLength]===undefined){boundsError(offset,buf.length-(byteLength+1));}}function checkIntBI(value,min,max,buf,offset,byteLength){if(value>max||value<min){const n=typeof min==='bigint'?'n':'';let range;if(byteLength>3){if(min===0||min===BigInt(0)){range=`>= 0${n} and < 2${n} ** ${(byteLength+1)*8}${n}`;}else{range=`>= -(2${n} ** ${(byteLength+1)*8-1}${n}) and < 2 ** `+`${(byteLength+1)*8-1}${n}`;}}else{range=`>= ${min}${n} and <= ${max}${n}`;}throw new errors.ERR_OUT_OF_RANGE('value',range,value);}checkBounds(buf,offset,byteLength);}function validateNumber(value,name){if(typeof value!=='number'){throw new errors.ERR_INVALID_ARG_TYPE(name,'number',value);}}function boundsError(value,length,type){if(Math.floor(value)!==value){validateNumber(value,type);throw new errors.ERR_OUT_OF_RANGE(type||'offset','an integer',value);}if(length<0){throw new errors.ERR_BUFFER_OUT_OF_BOUNDS();}throw new errors.ERR_OUT_OF_RANGE(type||'offset',`>= ${type?1:0} and <= ${length}`,value);}// HELPER FUNCTIONS
|
||
// ================
|
||
const INVALID_BASE64_RE=/[^+/0-9A-Za-z-_]/g;function base64clean(str){// Node takes equal signs as end of the Base64 encoding
|
||
str=str.split('=')[0];// Node strips out invalid characters like \n and \t from the string, base64-js does not
|
||
str=str.trim().replace(INVALID_BASE64_RE,'');// Node converts strings with length < 2 to ''
|
||
if(str.length<2)return'';// Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
|
||
while(str.length%4!==0){str=str+'=';}return str;}function utf8ToBytes(string,units){units=units||Infinity;let codePoint;const length=string.length;let leadSurrogate=null;const bytes=[];for(let i=0;i<length;++i){codePoint=string.charCodeAt(i);// is surrogate component
|
||
if(codePoint>0xD7FF&&codePoint<0xE000){// last char was a lead
|
||
if(!leadSurrogate){// no lead yet
|
||
if(codePoint>0xDBFF){// unexpected trail
|
||
if((units-=3)>-1)bytes.push(0xEF,0xBF,0xBD);continue;}else if(i+1===length){// unpaired lead
|
||
if((units-=3)>-1)bytes.push(0xEF,0xBF,0xBD);continue;}// valid lead
|
||
leadSurrogate=codePoint;continue;}// 2 leads in a row
|
||
if(codePoint<0xDC00){if((units-=3)>-1)bytes.push(0xEF,0xBF,0xBD);leadSurrogate=codePoint;continue;}// valid surrogate pair
|
||
codePoint=(leadSurrogate-0xD800<<10|codePoint-0xDC00)+0x10000;}else if(leadSurrogate){// valid bmp char, but last char was a lead
|
||
if((units-=3)>-1)bytes.push(0xEF,0xBF,0xBD);}leadSurrogate=null;// encode utf8
|
||
if(codePoint<0x80){if((units-=1)<0)break;bytes.push(codePoint);}else if(codePoint<0x800){if((units-=2)<0)break;bytes.push(codePoint>>0x6|0xC0,codePoint&0x3F|0x80);}else if(codePoint<0x10000){if((units-=3)<0)break;bytes.push(codePoint>>0xC|0xE0,codePoint>>0x6&0x3F|0x80,codePoint&0x3F|0x80);}else if(codePoint<0x110000){if((units-=4)<0)break;bytes.push(codePoint>>0x12|0xF0,codePoint>>0xC&0x3F|0x80,codePoint>>0x6&0x3F|0x80,codePoint&0x3F|0x80);}else{throw new Error('Invalid code point');}}return bytes;}function asciiToBytes(str){const byteArray=[];for(let i=0;i<str.length;++i){// Node's code seems to be doing this and not & 0x7F..
|
||
byteArray.push(str.charCodeAt(i)&0xFF);}return byteArray;}function utf16leToBytes(str,units){let c,hi,lo;const byteArray=[];for(let i=0;i<str.length;++i){if((units-=2)<0)break;c=str.charCodeAt(i);hi=c>>8;lo=c%256;byteArray.push(lo);byteArray.push(hi);}return byteArray;}function base64ToBytes(str){return base64.toByteArray(base64clean(str));}function blitBuffer(src,dst,offset,length){let i;for(i=0;i<length;++i){if(i+offset>=dst.length||i>=src.length)break;dst[i+offset]=src[i];}return i;}// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass
|
||
// the `instanceof` check but they should be treated as of that type.
|
||
// See: https://github.com/feross/buffer/issues/166
|
||
function isInstance(obj,type){return obj instanceof type||obj!=null&&obj.constructor!=null&&obj.constructor.name!=null&&obj.constructor.name===type.name;}function numberIsNaN(obj){// For IE11 support
|
||
return obj!==obj;// eslint-disable-line no-self-compare
|
||
}// Create lookup table for `toString('hex')`
|
||
// See: https://github.com/feross/buffer/issues/219
|
||
const hexSliceLookupTable=function(){const alphabet='0123456789abcdef';const table=new Array(256);for(let i=0;i<16;++i){const i16=i*16;for(let j=0;j<16;++j){table[i16+j]=alphabet[i]+alphabet[j];}}return table;}();// Return not function with Error if BigInt not supported
|
||
function defineBigIntMethod(fn){return typeof BigInt==='undefined'?BufferBigIntNotDefined:fn;}function BufferBigIntNotDefined(){throw new Error('BigInt not supported');}
|
||
|
||
/***/ })
|
||
|
||
/******/ });
|
||
/************************************************************************/
|
||
/******/ // The module cache
|
||
/******/ var __webpack_module_cache__ = {};
|
||
/******/
|
||
/******/ // The require function
|
||
/******/ function __webpack_require__(moduleId) {
|
||
/******/ // Check if module is in cache
|
||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||
/******/ if (cachedModule !== undefined) {
|
||
/******/ return cachedModule.exports;
|
||
/******/ }
|
||
/******/ // Create a new module (and put it into the cache)
|
||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||
/******/ // no module.id needed
|
||
/******/ // no module.loaded needed
|
||
/******/ exports: {}
|
||
/******/ };
|
||
/******/
|
||
/******/ // Execute the module function
|
||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||
/******/
|
||
/******/ // Return the exports of the module
|
||
/******/ return module.exports;
|
||
/******/ }
|
||
/******/
|
||
/************************************************************************/
|
||
/******/ /* webpack/runtime/define property getters */
|
||
/******/ !function() {
|
||
/******/ // define getter functions for harmony exports
|
||
/******/ __webpack_require__.d = function(exports, definition) {
|
||
/******/ for(var key in definition) {
|
||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||
/******/ }
|
||
/******/ }
|
||
/******/ };
|
||
/******/ }();
|
||
/******/
|
||
/******/ /* webpack/runtime/global */
|
||
/******/ !function() {
|
||
/******/ __webpack_require__.g = (function() {
|
||
/******/ if (typeof globalThis === 'object') return globalThis;
|
||
/******/ try {
|
||
/******/ return this || new Function('return this')();
|
||
/******/ } catch (e) {
|
||
/******/ if (typeof window === 'object') return window;
|
||
/******/ }
|
||
/******/ })();
|
||
/******/ }();
|
||
/******/
|
||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||
/******/ !function() {
|
||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||
/******/ }();
|
||
/******/
|
||
/******/ /* webpack/runtime/make namespace object */
|
||
/******/ !function() {
|
||
/******/ // define __esModule on exports
|
||
/******/ __webpack_require__.r = function(exports) {
|
||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||
/******/ }
|
||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||
/******/ };
|
||
/******/ }();
|
||
/******/
|
||
/************************************************************************/
|
||
var __webpack_exports__ = {};
|
||
// This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
|
||
!function() {
|
||
"use strict";
|
||
|
||
;// ../../libs/common/src/autofill/constants/match-patterns.ts
|
||
const CardExpiryDateDelimiters = ["/", "-", ".", " "];
|
||
// `CardExpiryDateDelimiters` is not intended solely for regex consumption,
|
||
// so we need to format it here
|
||
const ExpiryDateDelimitersPattern = "\\" +
|
||
CardExpiryDateDelimiters.join("\\")
|
||
// replace space character with the regex whitespace character class
|
||
.replace(" ", "s");
|
||
const MonthPattern = "(([1]{1}[0-2]{1})|(0?[1-9]{1}))";
|
||
// Because we're dealing with expiry dates, we assume the year will be in current or next century (as of 2024)
|
||
const match_patterns_ExpiryFullYearPattern = "2[0-1]{1}\\d{2}";
|
||
const match_patterns_DelimiterPatternExpression = new RegExp(`[${ExpiryDateDelimitersPattern}]`, "g");
|
||
const match_patterns_IrrelevantExpiryCharactersPatternExpression = new RegExp(
|
||
// "nor digits" to ensure numbers are removed from guidance pattern, which aren't covered by ^\w
|
||
`[^\\d${ExpiryDateDelimitersPattern}]`, "g");
|
||
const match_patterns_MonthPatternExpression = new RegExp(`^${MonthPattern}$`);
|
||
const match_patterns_ExpiryFullYearPatternExpression = new RegExp(`^${match_patterns_ExpiryFullYearPattern}$`);
|
||
|
||
;// ../../libs/common/src/autofill/constants/index.ts
|
||
const TYPE_CHECK = {
|
||
FUNCTION: "function",
|
||
NUMBER: "number",
|
||
STRING: "string",
|
||
};
|
||
const EVENTS = {
|
||
CHANGE: "change",
|
||
INPUT: "input",
|
||
KEYDOWN: "keydown",
|
||
KEYPRESS: "keypress",
|
||
KEYUP: "keyup",
|
||
BLUR: "blur",
|
||
CLICK: "click",
|
||
FOCUS: "focus",
|
||
FOCUSIN: "focusin",
|
||
FOCUSOUT: "focusout",
|
||
SCROLL: "scroll",
|
||
RESIZE: "resize",
|
||
DOMCONTENTLOADED: "DOMContentLoaded",
|
||
LOAD: "load",
|
||
MESSAGE: "message",
|
||
VISIBILITYCHANGE: "visibilitychange",
|
||
MOUSEENTER: "mouseenter",
|
||
MOUSELEAVE: "mouseleave",
|
||
MOUSEUP: "mouseup",
|
||
MOUSEOUT: "mouseout",
|
||
SUBMIT: "submit",
|
||
};
|
||
const ClearClipboardDelay = {
|
||
Never: null,
|
||
TenSeconds: 10,
|
||
TwentySeconds: 20,
|
||
ThirtySeconds: 30,
|
||
OneMinute: 60,
|
||
TwoMinutes: 120,
|
||
FiveMinutes: 300,
|
||
};
|
||
/* Ids for context menu items and messaging events */
|
||
const AUTOFILL_CARD_ID = "autofill-card";
|
||
const AUTOFILL_ID = "autofill";
|
||
const SHOW_AUTOFILL_BUTTON = "show-autofill-button";
|
||
const AUTOFILL_IDENTITY_ID = "autofill-identity";
|
||
const COPY_IDENTIFIER_ID = "copy-identifier";
|
||
const COPY_PASSWORD_ID = "copy-password";
|
||
const COPY_USERNAME_ID = "copy-username";
|
||
const COPY_VERIFICATION_CODE_ID = "copy-totp";
|
||
const CREATE_CARD_ID = "create-card";
|
||
const CREATE_IDENTITY_ID = "create-identity";
|
||
const CREATE_LOGIN_ID = "create-login";
|
||
const GENERATE_PASSWORD_ID = "generate-password";
|
||
const NOOP_COMMAND_SUFFIX = "noop";
|
||
const ROOT_ID = "root";
|
||
const SEPARATOR_ID = "separator";
|
||
const UPDATE_PASSWORD = "update-password";
|
||
const NOTIFICATION_BAR_LIFESPAN_MS = 150000; // 150 seconds
|
||
const AUTOFILL_OVERLAY_HANDLE_REPOSITION = "autofill-overlay-handle-reposition-event";
|
||
const AUTOFILL_OVERLAY_HANDLE_SCROLL = "autofill-overlay-handle-scroll-event";
|
||
const UPDATE_PASSKEYS_HEADINGS_ON_SCROLL = "update-passkeys-headings-on-scroll";
|
||
const AUTOFILL_TRIGGER_FORM_FIELD_SUBMIT = "autofill-trigger-form-field-submit";
|
||
const AutofillOverlayVisibility = {
|
||
Off: 0,
|
||
OnButtonClick: 1,
|
||
OnFieldFocus: 2,
|
||
};
|
||
const BrowserClientVendors = {
|
||
Chrome: "Chrome",
|
||
Opera: "Opera",
|
||
Edge: "Edge",
|
||
Vivaldi: "Vivaldi",
|
||
Unknown: "Unknown",
|
||
};
|
||
const BrowserShortcutsUris = {
|
||
Chrome: "chrome://extensions/shortcuts",
|
||
Opera: "opera://extensions/shortcuts",
|
||
Edge: "edge://extensions/shortcuts",
|
||
Vivaldi: "vivaldi://extensions/shortcuts",
|
||
Unknown: "https://bitwarden.com/help/keyboard-shortcuts",
|
||
};
|
||
const DisablePasswordManagerUris = {
|
||
Chrome: "chrome://settings/autofill",
|
||
Opera: "opera://settings/autofill",
|
||
Edge: "edge://settings/passwords",
|
||
Vivaldi: "vivaldi://settings/autofill",
|
||
Unknown: "https://bitwarden.com/help/disable-browser-autofill/",
|
||
};
|
||
const ExtensionCommand = {
|
||
AutofillCommand: "autofill_cmd",
|
||
AutofillCard: "autofill_card",
|
||
AutofillIdentity: "autofill_identity",
|
||
AutofillLogin: "autofill_login",
|
||
OpenAutofillOverlay: "open_autofill_overlay",
|
||
GeneratePassword: "generate_password",
|
||
OpenPopup: "open_popup",
|
||
LockVault: "lock_vault",
|
||
NoopCommand: "noop",
|
||
};
|
||
const CLEAR_NOTIFICATION_LOGIN_DATA_DURATION = (/* unused pure expression or super */ null && (60 * 1000)); // 1 minute
|
||
const MAX_DEEP_QUERY_RECURSION_DEPTH = 4;
|
||
|
||
|
||
;// ../../node_modules/tslib/tslib.es6.mjs
|
||
/******************************************************************************
|
||
Copyright (c) Microsoft Corporation.
|
||
|
||
Permission to use, copy, modify, and/or distribute this software for any
|
||
purpose with or without fee is hereby granted.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||
PERFORMANCE OF THIS SOFTWARE.
|
||
***************************************************************************** *//* global Reflect, Promise, SuppressedError, Symbol, Iterator */var extendStatics=function(d,b){extendStatics=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(d,b){d.__proto__=b;}||function(d,b){for(var p in b)if(Object.prototype.hasOwnProperty.call(b,p))d[p]=b[p];};return extendStatics(d,b);};function __extends(d,b){if(typeof b!=="function"&&b!==null)throw new TypeError("Class extends value "+String(b)+" is not a constructor or null");extendStatics(d,b);function __(){this.constructor=d;}d.prototype=b===null?Object.create(b):(__.prototype=b.prototype,new __());}var __assign=function(){__assign=Object.assign||function __assign(t){for(var s,i=1,n=arguments.length;i<n;i++){s=arguments[i];for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p))t[p]=s[p];}return t;};return __assign.apply(this,arguments);};function __rest(s,e){var t={};for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p)&&e.indexOf(p)<0)t[p]=s[p];if(s!=null&&typeof Object.getOwnPropertySymbols==="function")for(var i=0,p=Object.getOwnPropertySymbols(s);i<p.length;i++){if(e.indexOf(p[i])<0&&Object.prototype.propertyIsEnumerable.call(s,p[i]))t[p[i]]=s[p[i]];}return t;}function __decorate(decorators,target,key,desc){var c=arguments.length,r=c<3?target:desc===null?desc=Object.getOwnPropertyDescriptor(target,key):desc,d;if(typeof Reflect==="object"&&typeof Reflect.decorate==="function")r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)if(d=decorators[i])r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r;return c>3&&r&&Object.defineProperty(target,key,r),r;}function __param(paramIndex,decorator){return function(target,key){decorator(target,key,paramIndex);};}function __esDecorate(ctor,descriptorIn,decorators,contextIn,initializers,extraInitializers){function accept(f){if(f!==void 0&&typeof f!=="function")throw new TypeError("Function expected");return f;}var kind=contextIn.kind,key=kind==="getter"?"get":kind==="setter"?"set":"value";var target=!descriptorIn&&ctor?contextIn["static"]?ctor:ctor.prototype:null;var descriptor=descriptorIn||(target?Object.getOwnPropertyDescriptor(target,contextIn.name):{});var _,done=false;for(var i=decorators.length-1;i>=0;i--){var context={};for(var p in contextIn)context[p]=p==="access"?{}:contextIn[p];for(var p in contextIn.access)context.access[p]=contextIn.access[p];context.addInitializer=function(f){if(done)throw new TypeError("Cannot add initializers after decoration has completed");extraInitializers.push(accept(f||null));};var result=(0,decorators[i])(kind==="accessor"?{get:descriptor.get,set:descriptor.set}:descriptor[key],context);if(kind==="accessor"){if(result===void 0)continue;if(result===null||typeof result!=="object")throw new TypeError("Object expected");if(_=accept(result.get))descriptor.get=_;if(_=accept(result.set))descriptor.set=_;if(_=accept(result.init))initializers.unshift(_);}else if(_=accept(result)){if(kind==="field")initializers.unshift(_);else descriptor[key]=_;}}if(target)Object.defineProperty(target,contextIn.name,descriptor);done=true;};function __runInitializers(thisArg,initializers,value){var useValue=arguments.length>2;for(var i=0;i<initializers.length;i++){value=useValue?initializers[i].call(thisArg,value):initializers[i].call(thisArg);}return useValue?value:void 0;};function __propKey(x){return typeof x==="symbol"?x:"".concat(x);};function __setFunctionName(f,name,prefix){if(typeof name==="symbol")name=name.description?"[".concat(name.description,"]"):"";return Object.defineProperty(f,"name",{configurable:true,value:prefix?"".concat(prefix," ",name):name});};function __metadata(metadataKey,metadataValue){if(typeof Reflect==="object"&&typeof Reflect.metadata==="function")return Reflect.metadata(metadataKey,metadataValue);}function __awaiter(thisArg,_arguments,P,generator){function adopt(value){return value instanceof P?value:new P(function(resolve){resolve(value);});}return new(P||(P=Promise))(function(resolve,reject){function fulfilled(value){try{step(generator.next(value));}catch(e){reject(e);}}function rejected(value){try{step(generator["throw"](value));}catch(e){reject(e);}}function step(result){result.done?resolve(result.value):adopt(result.value).then(fulfilled,rejected);}step((generator=generator.apply(thisArg,_arguments||[])).next());});}function __generator(thisArg,body){var _={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1];},trys:[],ops:[]},f,y,t,g=Object.create((typeof Iterator==="function"?Iterator:Object).prototype);return g.next=verb(0),g["throw"]=verb(1),g["return"]=verb(2),typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this;}),g;function verb(n){return function(v){return step([n,v]);};}function step(op){if(f)throw new TypeError("Generator is already executing.");while(g&&(g=0,op[0]&&(_=0)),_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue;}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break;}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break;}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break;}if(t[2])_.ops.pop();_.trys.pop();continue;}op=body.call(thisArg,_);}catch(e){op=[6,e];y=0;}finally{f=t=0;}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true};}}var __createBinding=Object.create?function(o,m,k,k2){if(k2===undefined)k2=k;var desc=Object.getOwnPropertyDescriptor(m,k);if(!desc||("get"in desc?!m.__esModule:desc.writable||desc.configurable)){desc={enumerable:true,get:function(){return m[k];}};}Object.defineProperty(o,k2,desc);}:function(o,m,k,k2){if(k2===undefined)k2=k;o[k2]=m[k];};function __exportStar(m,o){for(var p in m)if(p!=="default"&&!Object.prototype.hasOwnProperty.call(o,p))__createBinding(o,m,p);}function __values(o){var s=typeof Symbol==="function"&&Symbol.iterator,m=s&&o[s],i=0;if(m)return m.call(o);if(o&&typeof o.length==="number")return{next:function(){if(o&&i>=o.length)o=void 0;return{value:o&&o[i++],done:!o};}};throw new TypeError(s?"Object is not iterable.":"Symbol.iterator is not defined.");}function __read(o,n){var m=typeof Symbol==="function"&&o[Symbol.iterator];if(!m)return o;var i=m.call(o),r,ar=[],e;try{while((n===void 0||n-->0)&&!(r=i.next()).done)ar.push(r.value);}catch(error){e={error:error};}finally{try{if(r&&!r.done&&(m=i["return"]))m.call(i);}finally{if(e)throw e.error;}}return ar;}/** @deprecated */function __spread(){for(var ar=[],i=0;i<arguments.length;i++)ar=ar.concat(__read(arguments[i]));return ar;}/** @deprecated */function __spreadArrays(){for(var s=0,i=0,il=arguments.length;i<il;i++)s+=arguments[i].length;for(var r=Array(s),k=0,i=0;i<il;i++)for(var a=arguments[i],j=0,jl=a.length;j<jl;j++,k++)r[k]=a[j];return r;}function __spreadArray(to,from,pack){if(pack||arguments.length===2)for(var i=0,l=from.length,ar;i<l;i++){if(ar||!(i in from)){if(!ar)ar=Array.prototype.slice.call(from,0,i);ar[i]=from[i];}}return to.concat(ar||Array.prototype.slice.call(from));}function __await(v){return this instanceof __await?(this.v=v,this):new __await(v);}function __asyncGenerator(thisArg,_arguments,generator){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var g=generator.apply(thisArg,_arguments||[]),i,q=[];return i=Object.create((typeof AsyncIterator==="function"?AsyncIterator:Object).prototype),verb("next"),verb("throw"),verb("return",awaitReturn),i[Symbol.asyncIterator]=function(){return this;},i;function awaitReturn(f){return function(v){return Promise.resolve(v).then(f,reject);};}function verb(n,f){if(g[n]){i[n]=function(v){return new Promise(function(a,b){q.push([n,v,a,b])>1||resume(n,v);});};if(f)i[n]=f(i[n]);}}function resume(n,v){try{step(g[n](v));}catch(e){settle(q[0][3],e);}}function step(r){r.value instanceof __await?Promise.resolve(r.value.v).then(fulfill,reject):settle(q[0][2],r);}function fulfill(value){resume("next",value);}function reject(value){resume("throw",value);}function settle(f,v){if(f(v),q.shift(),q.length)resume(q[0][0],q[0][1]);}}function __asyncDelegator(o){var i,p;return i={},verb("next"),verb("throw",function(e){throw e;}),verb("return"),i[Symbol.iterator]=function(){return this;},i;function verb(n,f){i[n]=o[n]?function(v){return(p=!p)?{value:__await(o[n](v)),done:false}:f?f(v):v;}:f;}}function __asyncValues(o){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var m=o[Symbol.asyncIterator],i;return m?m.call(o):(o=typeof __values==="function"?__values(o):o[Symbol.iterator](),i={},verb("next"),verb("throw"),verb("return"),i[Symbol.asyncIterator]=function(){return this;},i);function verb(n){i[n]=o[n]&&function(v){return new Promise(function(resolve,reject){v=o[n](v),settle(resolve,reject,v.done,v.value);});};}function settle(resolve,reject,d,v){Promise.resolve(v).then(function(v){resolve({value:v,done:d});},reject);}}function __makeTemplateObject(cooked,raw){if(Object.defineProperty){Object.defineProperty(cooked,"raw",{value:raw});}else{cooked.raw=raw;}return cooked;};var __setModuleDefault=Object.create?function(o,v){Object.defineProperty(o,"default",{enumerable:true,value:v});}:function(o,v){o["default"]=v;};var ownKeys=function(o){ownKeys=Object.getOwnPropertyNames||function(o){var ar=[];for(var k in o)if(Object.prototype.hasOwnProperty.call(o,k))ar[ar.length]=k;return ar;};return ownKeys(o);};function __importStar(mod){if(mod&&mod.__esModule)return mod;var result={};if(mod!=null)for(var k=ownKeys(mod),i=0;i<k.length;i++)if(k[i]!=="default")__createBinding(result,mod,k[i]);__setModuleDefault(result,mod);return result;}function __importDefault(mod){return mod&&mod.__esModule?mod:{default:mod};}function __classPrivateFieldGet(receiver,state,kind,f){if(kind==="a"&&!f)throw new TypeError("Private accessor was defined without a getter");if(typeof state==="function"?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot read private member from an object whose class did not declare it");return kind==="m"?f:kind==="a"?f.call(receiver):f?f.value:state.get(receiver);}function __classPrivateFieldSet(receiver,state,value,kind,f){if(kind==="m")throw new TypeError("Private method is not writable");if(kind==="a"&&!f)throw new TypeError("Private accessor was defined without a setter");if(typeof state==="function"?receiver!==state||!f:!state.has(receiver))throw new TypeError("Cannot write private member to an object whose class did not declare it");return kind==="a"?f.call(receiver,value):f?f.value=value:state.set(receiver,value),value;}function __classPrivateFieldIn(state,receiver){if(receiver===null||typeof receiver!=="object"&&typeof receiver!=="function")throw new TypeError("Cannot use 'in' operator on non-object");return typeof state==="function"?receiver===state:state.has(receiver);}function __addDisposableResource(env,value,async){if(value!==null&&value!==void 0){if(typeof value!=="object"&&typeof value!=="function")throw new TypeError("Object expected.");var dispose,inner;if(async){if(!Symbol.asyncDispose)throw new TypeError("Symbol.asyncDispose is not defined.");dispose=value[Symbol.asyncDispose];}if(dispose===void 0){if(!Symbol.dispose)throw new TypeError("Symbol.dispose is not defined.");dispose=value[Symbol.dispose];if(async)inner=dispose;}if(typeof dispose!=="function")throw new TypeError("Object not disposable.");if(inner)dispose=function(){try{inner.call(this);}catch(e){return Promise.reject(e);}};env.stack.push({value:value,dispose:dispose,async:async});}else if(async){env.stack.push({async:true});}return value;}var _SuppressedError=typeof SuppressedError==="function"?SuppressedError:function(error,suppressed,message){var e=new Error(message);return e.name="SuppressedError",e.error=error,e.suppressed=suppressed,e;};function __disposeResources(env){function fail(e){env.error=env.hasError?new _SuppressedError(e,env.error,"An error was suppressed during disposal."):e;env.hasError=true;}var r,s=0;function next(){while(r=env.stack.pop()){try{if(!r.async&&s===1)return s=0,env.stack.push(r),Promise.resolve().then(next);if(r.dispose){var result=r.dispose.call(r.value);if(r.async)return s|=2,Promise.resolve(result).then(next,function(e){fail(e);return next();});}else s|=1;}catch(e){fail(e);}}if(s===1)return env.hasError?Promise.reject(env.error):Promise.resolve();if(env.hasError)throw env.error;}return next();}function __rewriteRelativeImportExtension(path,preserveJsx){if(typeof path==="string"&&/^\.\.?\//.test(path)){return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,function(m,tsx,d,ext,cm){return tsx?preserveJsx?".jsx":".js":d&&(!ext||!cm)?m:d+ext+"."+cm.toLowerCase()+"js";});}return path;}/* harmony default export */ var tslib_es6 = ({__extends,__assign,__rest,__decorate,__param,__esDecorate,__runInitializers,__propKey,__setFunctionName,__metadata,__awaiter,__generator,__createBinding,__exportStar,__values,__read,__spread,__spreadArrays,__spreadArray,__await,__asyncGenerator,__asyncDelegator,__asyncValues,__makeTemplateObject,__importStar,__importDefault,__classPrivateFieldGet,__classPrivateFieldSet,__classPrivateFieldIn,__addDisposableResource,__disposeResources,__rewriteRelativeImportExtension});
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isFunction.js
|
||
function isFunction(value){return typeof value==='function';}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js
|
||
function createErrorClass(createImpl){var _super=function(instance){Error.call(instance);instance.stack=new Error().stack;};var ctorFunc=createImpl(_super);ctorFunc.prototype=Object.create(Error.prototype);ctorFunc.prototype.constructor=ctorFunc;return ctorFunc;}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js
|
||
var UnsubscriptionError=createErrorClass(function(_super){return function UnsubscriptionErrorImpl(errors){_super(this);this.message=errors?errors.length+" errors occurred during unsubscription:\n"+errors.map(function(err,i){return i+1+") "+err.toString();}).join('\n '):'';this.name='UnsubscriptionError';this.errors=errors;};});
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/arrRemove.js
|
||
function arrRemove(arr,item){if(arr){var index=arr.indexOf(item);0<=index&&arr.splice(index,1);}}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/Subscription.js
|
||
var Subscription=function(){function Subscription(initialTeardown){this.initialTeardown=initialTeardown;this.closed=false;this._parentage=null;this._finalizers=null;}Subscription.prototype.unsubscribe=function(){var e_1,_a,e_2,_b;var errors;if(!this.closed){this.closed=true;var _parentage=this._parentage;if(_parentage){this._parentage=null;if(Array.isArray(_parentage)){try{for(var _parentage_1=__values(_parentage),_parentage_1_1=_parentage_1.next();!_parentage_1_1.done;_parentage_1_1=_parentage_1.next()){var parent_1=_parentage_1_1.value;parent_1.remove(this);}}catch(e_1_1){e_1={error:e_1_1};}finally{try{if(_parentage_1_1&&!_parentage_1_1.done&&(_a=_parentage_1.return))_a.call(_parentage_1);}finally{if(e_1)throw e_1.error;}}}else{_parentage.remove(this);}}var initialFinalizer=this.initialTeardown;if(isFunction(initialFinalizer)){try{initialFinalizer();}catch(e){errors=e instanceof UnsubscriptionError?e.errors:[e];}}var _finalizers=this._finalizers;if(_finalizers){this._finalizers=null;try{for(var _finalizers_1=__values(_finalizers),_finalizers_1_1=_finalizers_1.next();!_finalizers_1_1.done;_finalizers_1_1=_finalizers_1.next()){var finalizer=_finalizers_1_1.value;try{execFinalizer(finalizer);}catch(err){errors=errors!==null&&errors!==void 0?errors:[];if(err instanceof UnsubscriptionError){errors=__spreadArray(__spreadArray([],__read(errors)),__read(err.errors));}else{errors.push(err);}}}}catch(e_2_1){e_2={error:e_2_1};}finally{try{if(_finalizers_1_1&&!_finalizers_1_1.done&&(_b=_finalizers_1.return))_b.call(_finalizers_1);}finally{if(e_2)throw e_2.error;}}}if(errors){throw new UnsubscriptionError(errors);}}};Subscription.prototype.add=function(teardown){var _a;if(teardown&&teardown!==this){if(this.closed){execFinalizer(teardown);}else{if(teardown instanceof Subscription){if(teardown.closed||teardown._hasParent(this)){return;}teardown._addParent(this);}(this._finalizers=(_a=this._finalizers)!==null&&_a!==void 0?_a:[]).push(teardown);}}};Subscription.prototype._hasParent=function(parent){var _parentage=this._parentage;return _parentage===parent||Array.isArray(_parentage)&&_parentage.includes(parent);};Subscription.prototype._addParent=function(parent){var _parentage=this._parentage;this._parentage=Array.isArray(_parentage)?(_parentage.push(parent),_parentage):_parentage?[_parentage,parent]:parent;};Subscription.prototype._removeParent=function(parent){var _parentage=this._parentage;if(_parentage===parent){this._parentage=null;}else if(Array.isArray(_parentage)){arrRemove(_parentage,parent);}};Subscription.prototype.remove=function(teardown){var _finalizers=this._finalizers;_finalizers&&arrRemove(_finalizers,teardown);if(teardown instanceof Subscription){teardown._removeParent(this);}};Subscription.EMPTY=function(){var empty=new Subscription();empty.closed=true;return empty;}();return Subscription;}();var EMPTY_SUBSCRIPTION=Subscription.EMPTY;function isSubscription(value){return value instanceof Subscription||value&&'closed'in value&&isFunction(value.remove)&&isFunction(value.add)&&isFunction(value.unsubscribe);}function execFinalizer(finalizer){if(isFunction(finalizer)){finalizer();}else{finalizer.unsubscribe();}}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/config.js
|
||
var config={onUnhandledError:null,onStoppedNotification:null,Promise:undefined,useDeprecatedSynchronousErrorHandling:false,useDeprecatedNextContext:false};
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js
|
||
var timeoutProvider={setTimeout:function(handler,timeout){var args=[];for(var _i=2;_i<arguments.length;_i++){args[_i-2]=arguments[_i];}var delegate=timeoutProvider.delegate;if(delegate===null||delegate===void 0?void 0:delegate.setTimeout){return delegate.setTimeout.apply(delegate,__spreadArray([handler,timeout],__read(args)));}return setTimeout.apply(void 0,__spreadArray([handler,timeout],__read(args)));},clearTimeout:function(handle){var delegate=timeoutProvider.delegate;return((delegate===null||delegate===void 0?void 0:delegate.clearTimeout)||clearTimeout)(handle);},delegate:undefined};
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js
|
||
function reportUnhandledError(err){timeoutProvider.setTimeout(function(){var onUnhandledError=config.onUnhandledError;if(onUnhandledError){onUnhandledError(err);}else{throw err;}});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/noop.js
|
||
function noop(){}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/NotificationFactories.js
|
||
var COMPLETE_NOTIFICATION=function(){return createNotification('C',undefined,undefined);}();function errorNotification(error){return createNotification('E',undefined,error);}function nextNotification(value){return createNotification('N',value,undefined);}function createNotification(kind,value,error){return{kind:kind,value:value,error:error};}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/errorContext.js
|
||
var context=null;function errorContext(cb){if(config.useDeprecatedSynchronousErrorHandling){var isRoot=!context;if(isRoot){context={errorThrown:false,error:null};}cb();if(isRoot){var _a=context,errorThrown=_a.errorThrown,error=_a.error;context=null;if(errorThrown){throw error;}}}else{cb();}}function captureError(err){if(config.useDeprecatedSynchronousErrorHandling&&context){context.errorThrown=true;context.error=err;}}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/Subscriber.js
|
||
var Subscriber=function(_super){__extends(Subscriber,_super);function Subscriber(destination){var _this=_super.call(this)||this;_this.isStopped=false;if(destination){_this.destination=destination;if(isSubscription(destination)){destination.add(_this);}}else{_this.destination=EMPTY_OBSERVER;}return _this;}Subscriber.create=function(next,error,complete){return new SafeSubscriber(next,error,complete);};Subscriber.prototype.next=function(value){if(this.isStopped){handleStoppedNotification(nextNotification(value),this);}else{this._next(value);}};Subscriber.prototype.error=function(err){if(this.isStopped){handleStoppedNotification(errorNotification(err),this);}else{this.isStopped=true;this._error(err);}};Subscriber.prototype.complete=function(){if(this.isStopped){handleStoppedNotification(COMPLETE_NOTIFICATION,this);}else{this.isStopped=true;this._complete();}};Subscriber.prototype.unsubscribe=function(){if(!this.closed){this.isStopped=true;_super.prototype.unsubscribe.call(this);this.destination=null;}};Subscriber.prototype._next=function(value){this.destination.next(value);};Subscriber.prototype._error=function(err){try{this.destination.error(err);}finally{this.unsubscribe();}};Subscriber.prototype._complete=function(){try{this.destination.complete();}finally{this.unsubscribe();}};return Subscriber;}(Subscription);var _bind=Function.prototype.bind;function bind(fn,thisArg){return _bind.call(fn,thisArg);}var ConsumerObserver=function(){function ConsumerObserver(partialObserver){this.partialObserver=partialObserver;}ConsumerObserver.prototype.next=function(value){var partialObserver=this.partialObserver;if(partialObserver.next){try{partialObserver.next(value);}catch(error){handleUnhandledError(error);}}};ConsumerObserver.prototype.error=function(err){var partialObserver=this.partialObserver;if(partialObserver.error){try{partialObserver.error(err);}catch(error){handleUnhandledError(error);}}else{handleUnhandledError(err);}};ConsumerObserver.prototype.complete=function(){var partialObserver=this.partialObserver;if(partialObserver.complete){try{partialObserver.complete();}catch(error){handleUnhandledError(error);}}};return ConsumerObserver;}();var SafeSubscriber=function(_super){__extends(SafeSubscriber,_super);function SafeSubscriber(observerOrNext,error,complete){var _this=_super.call(this)||this;var partialObserver;if(isFunction(observerOrNext)||!observerOrNext){partialObserver={next:observerOrNext!==null&&observerOrNext!==void 0?observerOrNext:undefined,error:error!==null&&error!==void 0?error:undefined,complete:complete!==null&&complete!==void 0?complete:undefined};}else{var context_1;if(_this&&config.useDeprecatedNextContext){context_1=Object.create(observerOrNext);context_1.unsubscribe=function(){return _this.unsubscribe();};partialObserver={next:observerOrNext.next&&bind(observerOrNext.next,context_1),error:observerOrNext.error&&bind(observerOrNext.error,context_1),complete:observerOrNext.complete&&bind(observerOrNext.complete,context_1)};}else{partialObserver=observerOrNext;}}_this.destination=new ConsumerObserver(partialObserver);return _this;}return SafeSubscriber;}(Subscriber);function handleUnhandledError(error){if(config.useDeprecatedSynchronousErrorHandling){captureError(error);}else{reportUnhandledError(error);}}function defaultErrorHandler(err){throw err;}function handleStoppedNotification(notification,subscriber){var onStoppedNotification=config.onStoppedNotification;onStoppedNotification&&timeoutProvider.setTimeout(function(){return onStoppedNotification(notification,subscriber);});}var EMPTY_OBSERVER={closed:true,next:noop,error:defaultErrorHandler,complete:noop};
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/symbol/observable.js
|
||
var observable=function(){return typeof Symbol==='function'&&Symbol.observable||'@@observable';}();
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/identity.js
|
||
function identity(x){return x;}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/pipe.js
|
||
function pipe(){var fns=[];for(var _i=0;_i<arguments.length;_i++){fns[_i]=arguments[_i];}return pipeFromArray(fns);}function pipeFromArray(fns){if(fns.length===0){return identity;}if(fns.length===1){return fns[0];}return function piped(input){return fns.reduce(function(prev,fn){return fn(prev);},input);};}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/Observable.js
|
||
var Observable_Observable=function(){function Observable(subscribe){if(subscribe){this._subscribe=subscribe;}}Observable.prototype.lift=function(operator){var observable=new Observable();observable.source=this;observable.operator=operator;return observable;};Observable.prototype.subscribe=function(observerOrNext,error,complete){var _this=this;var subscriber=isSubscriber(observerOrNext)?observerOrNext:new SafeSubscriber(observerOrNext,error,complete);errorContext(function(){var _a=_this,operator=_a.operator,source=_a.source;subscriber.add(operator?operator.call(subscriber,source):source?_this._subscribe(subscriber):_this._trySubscribe(subscriber));});return subscriber;};Observable.prototype._trySubscribe=function(sink){try{return this._subscribe(sink);}catch(err){sink.error(err);}};Observable.prototype.forEach=function(next,promiseCtor){var _this=this;promiseCtor=getPromiseCtor(promiseCtor);return new promiseCtor(function(resolve,reject){var subscriber=new SafeSubscriber({next:function(value){try{next(value);}catch(err){reject(err);subscriber.unsubscribe();}},error:reject,complete:resolve});_this.subscribe(subscriber);});};Observable.prototype._subscribe=function(subscriber){var _a;return(_a=this.source)===null||_a===void 0?void 0:_a.subscribe(subscriber);};Observable.prototype[observable]=function(){return this;};Observable.prototype.pipe=function(){var operations=[];for(var _i=0;_i<arguments.length;_i++){operations[_i]=arguments[_i];}return pipeFromArray(operations)(this);};Observable.prototype.toPromise=function(promiseCtor){var _this=this;promiseCtor=getPromiseCtor(promiseCtor);return new promiseCtor(function(resolve,reject){var value;_this.subscribe(function(x){return value=x;},function(err){return reject(err);},function(){return resolve(value);});});};Observable.create=function(subscribe){return new Observable(subscribe);};return Observable;}();function getPromiseCtor(promiseCtor){var _a;return(_a=promiseCtor!==null&&promiseCtor!==void 0?promiseCtor:config.Promise)!==null&&_a!==void 0?_a:Promise;}function isObserver(value){return value&&isFunction(value.next)&&isFunction(value.error)&&isFunction(value.complete);}function isSubscriber(value){return value&&value instanceof Subscriber||isObserver(value)&&isSubscription(value);}
|
||
;// ../../libs/client-type/src/index.ts
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var ClientType;
|
||
(function (ClientType) {
|
||
ClientType["Web"] = "web";
|
||
ClientType["Browser"] = "browser";
|
||
ClientType["Desktop"] = "desktop";
|
||
// Mobile = "mobile",
|
||
ClientType["Cli"] = "cli";
|
||
// DirectoryConnector = "connector",
|
||
})(ClientType || (ClientType = {}));
|
||
|
||
;// ../../libs/common/src/enums/client-type.enum.ts
|
||
|
||
|
||
;// ../../libs/common/src/enums/device-type.enum.ts
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var DeviceType;
|
||
(function (DeviceType) {
|
||
DeviceType[DeviceType["Android"] = 0] = "Android";
|
||
DeviceType[DeviceType["iOS"] = 1] = "iOS";
|
||
DeviceType[DeviceType["ChromeExtension"] = 2] = "ChromeExtension";
|
||
DeviceType[DeviceType["FirefoxExtension"] = 3] = "FirefoxExtension";
|
||
DeviceType[DeviceType["OperaExtension"] = 4] = "OperaExtension";
|
||
DeviceType[DeviceType["EdgeExtension"] = 5] = "EdgeExtension";
|
||
DeviceType[DeviceType["WindowsDesktop"] = 6] = "WindowsDesktop";
|
||
DeviceType[DeviceType["MacOsDesktop"] = 7] = "MacOsDesktop";
|
||
DeviceType[DeviceType["LinuxDesktop"] = 8] = "LinuxDesktop";
|
||
DeviceType[DeviceType["ChromeBrowser"] = 9] = "ChromeBrowser";
|
||
DeviceType[DeviceType["FirefoxBrowser"] = 10] = "FirefoxBrowser";
|
||
DeviceType[DeviceType["OperaBrowser"] = 11] = "OperaBrowser";
|
||
DeviceType[DeviceType["EdgeBrowser"] = 12] = "EdgeBrowser";
|
||
DeviceType[DeviceType["IEBrowser"] = 13] = "IEBrowser";
|
||
DeviceType[DeviceType["UnknownBrowser"] = 14] = "UnknownBrowser";
|
||
DeviceType[DeviceType["AndroidAmazon"] = 15] = "AndroidAmazon";
|
||
DeviceType[DeviceType["UWP"] = 16] = "UWP";
|
||
DeviceType[DeviceType["SafariBrowser"] = 17] = "SafariBrowser";
|
||
DeviceType[DeviceType["VivaldiBrowser"] = 18] = "VivaldiBrowser";
|
||
DeviceType[DeviceType["VivaldiExtension"] = 19] = "VivaldiExtension";
|
||
DeviceType[DeviceType["SafariExtension"] = 20] = "SafariExtension";
|
||
DeviceType[DeviceType["SDK"] = 21] = "SDK";
|
||
DeviceType[DeviceType["Server"] = 22] = "Server";
|
||
DeviceType[DeviceType["WindowsCLI"] = 23] = "WindowsCLI";
|
||
DeviceType[DeviceType["MacOsCLI"] = 24] = "MacOsCLI";
|
||
DeviceType[DeviceType["LinuxCLI"] = 25] = "LinuxCLI";
|
||
DeviceType[DeviceType["DuckDuckGoBrowser"] = 26] = "DuckDuckGoBrowser";
|
||
})(DeviceType || (DeviceType = {}));
|
||
const DeviceTypeMetadata = {
|
||
[DeviceType.Android]: { category: "mobile", platform: "Android" },
|
||
[DeviceType.iOS]: { category: "mobile", platform: "iOS" },
|
||
[DeviceType.AndroidAmazon]: { category: "mobile", platform: "Amazon" },
|
||
[DeviceType.ChromeExtension]: { category: "extension", platform: "Chrome" },
|
||
[DeviceType.FirefoxExtension]: { category: "extension", platform: "Firefox" },
|
||
[DeviceType.OperaExtension]: { category: "extension", platform: "Opera" },
|
||
[DeviceType.EdgeExtension]: { category: "extension", platform: "Edge" },
|
||
[DeviceType.VivaldiExtension]: { category: "extension", platform: "Vivaldi" },
|
||
[DeviceType.SafariExtension]: { category: "extension", platform: "Safari" },
|
||
[DeviceType.ChromeBrowser]: { category: "webApp", platform: "Chrome" },
|
||
[DeviceType.FirefoxBrowser]: { category: "webApp", platform: "Firefox" },
|
||
[DeviceType.OperaBrowser]: { category: "webApp", platform: "Opera" },
|
||
[DeviceType.EdgeBrowser]: { category: "webApp", platform: "Edge" },
|
||
[DeviceType.IEBrowser]: { category: "webApp", platform: "IE" },
|
||
[DeviceType.SafariBrowser]: { category: "webApp", platform: "Safari" },
|
||
[DeviceType.VivaldiBrowser]: { category: "webApp", platform: "Vivaldi" },
|
||
[DeviceType.DuckDuckGoBrowser]: { category: "webApp", platform: "DuckDuckGo" },
|
||
[DeviceType.UnknownBrowser]: { category: "webApp", platform: "Unknown" },
|
||
[DeviceType.WindowsDesktop]: { category: "desktop", platform: "Windows" },
|
||
[DeviceType.MacOsDesktop]: { category: "desktop", platform: "macOS" },
|
||
[DeviceType.LinuxDesktop]: { category: "desktop", platform: "Linux" },
|
||
[DeviceType.UWP]: { category: "desktop", platform: "Windows UWP" },
|
||
[DeviceType.WindowsCLI]: { category: "cli", platform: "Windows" },
|
||
[DeviceType.MacOsCLI]: { category: "cli", platform: "macOS" },
|
||
[DeviceType.LinuxCLI]: { category: "cli", platform: "Linux" },
|
||
[DeviceType.SDK]: { category: "sdk", platform: "" },
|
||
[DeviceType.Server]: { category: "server", platform: "" },
|
||
};
|
||
|
||
;// ../../libs/common/src/enums/event-system-user.enum.ts
|
||
// Note: the enum key is used to describe the EventSystemUser in the UI. Be careful about changing it.
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var EventSystemUser;
|
||
(function (EventSystemUser) {
|
||
EventSystemUser[EventSystemUser["SCIM"] = 1] = "SCIM";
|
||
EventSystemUser[EventSystemUser["DomainVerification"] = 2] = "DomainVerification";
|
||
EventSystemUser[EventSystemUser["PublicApi"] = 3] = "PublicApi";
|
||
})(EventSystemUser || (EventSystemUser = {}));
|
||
|
||
;// ../../libs/common/src/enums/event-type.enum.ts
|
||
// Increment by 100 for each new set of events
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var EventType;
|
||
(function (EventType) {
|
||
EventType[EventType["User_LoggedIn"] = 1000] = "User_LoggedIn";
|
||
EventType[EventType["User_ChangedPassword"] = 1001] = "User_ChangedPassword";
|
||
EventType[EventType["User_Updated2fa"] = 1002] = "User_Updated2fa";
|
||
EventType[EventType["User_Disabled2fa"] = 1003] = "User_Disabled2fa";
|
||
EventType[EventType["User_Recovered2fa"] = 1004] = "User_Recovered2fa";
|
||
EventType[EventType["User_FailedLogIn"] = 1005] = "User_FailedLogIn";
|
||
EventType[EventType["User_FailedLogIn2fa"] = 1006] = "User_FailedLogIn2fa";
|
||
EventType[EventType["User_ClientExportedVault"] = 1007] = "User_ClientExportedVault";
|
||
EventType[EventType["User_UpdatedTempPassword"] = 1008] = "User_UpdatedTempPassword";
|
||
EventType[EventType["User_MigratedKeyToKeyConnector"] = 1009] = "User_MigratedKeyToKeyConnector";
|
||
EventType[EventType["User_RequestedDeviceApproval"] = 1010] = "User_RequestedDeviceApproval";
|
||
EventType[EventType["User_TdeOffboardingPasswordSet"] = 1011] = "User_TdeOffboardingPasswordSet";
|
||
EventType[EventType["Cipher_Created"] = 1100] = "Cipher_Created";
|
||
EventType[EventType["Cipher_Updated"] = 1101] = "Cipher_Updated";
|
||
EventType[EventType["Cipher_Deleted"] = 1102] = "Cipher_Deleted";
|
||
EventType[EventType["Cipher_AttachmentCreated"] = 1103] = "Cipher_AttachmentCreated";
|
||
EventType[EventType["Cipher_AttachmentDeleted"] = 1104] = "Cipher_AttachmentDeleted";
|
||
EventType[EventType["Cipher_Shared"] = 1105] = "Cipher_Shared";
|
||
EventType[EventType["Cipher_UpdatedCollections"] = 1106] = "Cipher_UpdatedCollections";
|
||
EventType[EventType["Cipher_ClientViewed"] = 1107] = "Cipher_ClientViewed";
|
||
EventType[EventType["Cipher_ClientToggledPasswordVisible"] = 1108] = "Cipher_ClientToggledPasswordVisible";
|
||
EventType[EventType["Cipher_ClientToggledHiddenFieldVisible"] = 1109] = "Cipher_ClientToggledHiddenFieldVisible";
|
||
EventType[EventType["Cipher_ClientToggledCardCodeVisible"] = 1110] = "Cipher_ClientToggledCardCodeVisible";
|
||
EventType[EventType["Cipher_ClientCopiedPassword"] = 1111] = "Cipher_ClientCopiedPassword";
|
||
EventType[EventType["Cipher_ClientCopiedHiddenField"] = 1112] = "Cipher_ClientCopiedHiddenField";
|
||
EventType[EventType["Cipher_ClientCopiedCardCode"] = 1113] = "Cipher_ClientCopiedCardCode";
|
||
EventType[EventType["Cipher_ClientAutofilled"] = 1114] = "Cipher_ClientAutofilled";
|
||
EventType[EventType["Cipher_SoftDeleted"] = 1115] = "Cipher_SoftDeleted";
|
||
EventType[EventType["Cipher_Restored"] = 1116] = "Cipher_Restored";
|
||
EventType[EventType["Cipher_ClientToggledCardNumberVisible"] = 1117] = "Cipher_ClientToggledCardNumberVisible";
|
||
EventType[EventType["Cipher_ClientToggledTOTPSeedVisible"] = 1118] = "Cipher_ClientToggledTOTPSeedVisible";
|
||
EventType[EventType["Collection_Created"] = 1300] = "Collection_Created";
|
||
EventType[EventType["Collection_Updated"] = 1301] = "Collection_Updated";
|
||
EventType[EventType["Collection_Deleted"] = 1302] = "Collection_Deleted";
|
||
EventType[EventType["Group_Created"] = 1400] = "Group_Created";
|
||
EventType[EventType["Group_Updated"] = 1401] = "Group_Updated";
|
||
EventType[EventType["Group_Deleted"] = 1402] = "Group_Deleted";
|
||
EventType[EventType["OrganizationUser_Invited"] = 1500] = "OrganizationUser_Invited";
|
||
EventType[EventType["OrganizationUser_Confirmed"] = 1501] = "OrganizationUser_Confirmed";
|
||
EventType[EventType["OrganizationUser_Updated"] = 1502] = "OrganizationUser_Updated";
|
||
EventType[EventType["OrganizationUser_Removed"] = 1503] = "OrganizationUser_Removed";
|
||
EventType[EventType["OrganizationUser_UpdatedGroups"] = 1504] = "OrganizationUser_UpdatedGroups";
|
||
EventType[EventType["OrganizationUser_UnlinkedSso"] = 1505] = "OrganizationUser_UnlinkedSso";
|
||
EventType[EventType["OrganizationUser_ResetPassword_Enroll"] = 1506] = "OrganizationUser_ResetPassword_Enroll";
|
||
EventType[EventType["OrganizationUser_ResetPassword_Withdraw"] = 1507] = "OrganizationUser_ResetPassword_Withdraw";
|
||
EventType[EventType["OrganizationUser_AdminResetPassword"] = 1508] = "OrganizationUser_AdminResetPassword";
|
||
EventType[EventType["OrganizationUser_ResetSsoLink"] = 1509] = "OrganizationUser_ResetSsoLink";
|
||
EventType[EventType["OrganizationUser_FirstSsoLogin"] = 1510] = "OrganizationUser_FirstSsoLogin";
|
||
EventType[EventType["OrganizationUser_Revoked"] = 1511] = "OrganizationUser_Revoked";
|
||
EventType[EventType["OrganizationUser_Restored"] = 1512] = "OrganizationUser_Restored";
|
||
EventType[EventType["OrganizationUser_ApprovedAuthRequest"] = 1513] = "OrganizationUser_ApprovedAuthRequest";
|
||
EventType[EventType["OrganizationUser_RejectedAuthRequest"] = 1514] = "OrganizationUser_RejectedAuthRequest";
|
||
EventType[EventType["OrganizationUser_Deleted"] = 1515] = "OrganizationUser_Deleted";
|
||
EventType[EventType["OrganizationUser_Left"] = 1516] = "OrganizationUser_Left";
|
||
EventType[EventType["Organization_Updated"] = 1600] = "Organization_Updated";
|
||
EventType[EventType["Organization_PurgedVault"] = 1601] = "Organization_PurgedVault";
|
||
EventType[EventType["Organization_ClientExportedVault"] = 1602] = "Organization_ClientExportedVault";
|
||
EventType[EventType["Organization_VaultAccessed"] = 1603] = "Organization_VaultAccessed";
|
||
EventType[EventType["Organization_EnabledSso"] = 1604] = "Organization_EnabledSso";
|
||
EventType[EventType["Organization_DisabledSso"] = 1605] = "Organization_DisabledSso";
|
||
EventType[EventType["Organization_EnabledKeyConnector"] = 1606] = "Organization_EnabledKeyConnector";
|
||
EventType[EventType["Organization_DisabledKeyConnector"] = 1607] = "Organization_DisabledKeyConnector";
|
||
EventType[EventType["Organization_SponsorshipsSynced"] = 1608] = "Organization_SponsorshipsSynced";
|
||
EventType[EventType["Organization_CollectionManagementUpdated"] = 1609] = "Organization_CollectionManagementUpdated";
|
||
EventType[EventType["Organization_CollectionManagement_LimitCollectionCreationEnabled"] = 1610] = "Organization_CollectionManagement_LimitCollectionCreationEnabled";
|
||
EventType[EventType["Organization_CollectionManagement_LimitCollectionCreationDisabled"] = 1611] = "Organization_CollectionManagement_LimitCollectionCreationDisabled";
|
||
EventType[EventType["Organization_CollectionManagement_LimitCollectionDeletionEnabled"] = 1612] = "Organization_CollectionManagement_LimitCollectionDeletionEnabled";
|
||
EventType[EventType["Organization_CollectionManagement_LimitCollectionDeletionDisabled"] = 1613] = "Organization_CollectionManagement_LimitCollectionDeletionDisabled";
|
||
EventType[EventType["Organization_CollectionManagement_LimitItemDeletionEnabled"] = 1614] = "Organization_CollectionManagement_LimitItemDeletionEnabled";
|
||
EventType[EventType["Organization_CollectionManagement_LimitItemDeletionDisabled"] = 1615] = "Organization_CollectionManagement_LimitItemDeletionDisabled";
|
||
EventType[EventType["Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsEnabled"] = 1616] = "Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsEnabled";
|
||
EventType[EventType["Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsDisabled"] = 1617] = "Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsDisabled";
|
||
EventType[EventType["Organization_ItemOrganization_Accepted"] = 1618] = "Organization_ItemOrganization_Accepted";
|
||
EventType[EventType["Organization_ItemOrganization_Declined"] = 1619] = "Organization_ItemOrganization_Declined";
|
||
EventType[EventType["Policy_Updated"] = 1700] = "Policy_Updated";
|
||
EventType[EventType["ProviderUser_Invited"] = 1800] = "ProviderUser_Invited";
|
||
EventType[EventType["ProviderUser_Confirmed"] = 1801] = "ProviderUser_Confirmed";
|
||
EventType[EventType["ProviderUser_Updated"] = 1802] = "ProviderUser_Updated";
|
||
EventType[EventType["ProviderUser_Removed"] = 1803] = "ProviderUser_Removed";
|
||
EventType[EventType["ProviderOrganization_Created"] = 1900] = "ProviderOrganization_Created";
|
||
EventType[EventType["ProviderOrganization_Added"] = 1901] = "ProviderOrganization_Added";
|
||
EventType[EventType["ProviderOrganization_Removed"] = 1902] = "ProviderOrganization_Removed";
|
||
EventType[EventType["ProviderOrganization_VaultAccessed"] = 1903] = "ProviderOrganization_VaultAccessed";
|
||
EventType[EventType["OrganizationDomain_Added"] = 2000] = "OrganizationDomain_Added";
|
||
EventType[EventType["OrganizationDomain_Removed"] = 2001] = "OrganizationDomain_Removed";
|
||
EventType[EventType["OrganizationDomain_Verified"] = 2002] = "OrganizationDomain_Verified";
|
||
EventType[EventType["OrganizationDomain_NotVerified"] = 2003] = "OrganizationDomain_NotVerified";
|
||
EventType[EventType["Secret_Retrieved"] = 2100] = "Secret_Retrieved";
|
||
EventType[EventType["Secret_Created"] = 2101] = "Secret_Created";
|
||
EventType[EventType["Secret_Edited"] = 2102] = "Secret_Edited";
|
||
EventType[EventType["Secret_Deleted"] = 2103] = "Secret_Deleted";
|
||
EventType[EventType["Secret_Permanently_Deleted"] = 2104] = "Secret_Permanently_Deleted";
|
||
EventType[EventType["Secret_Restored"] = 2105] = "Secret_Restored";
|
||
EventType[EventType["Project_Retrieved"] = 2200] = "Project_Retrieved";
|
||
EventType[EventType["Project_Created"] = 2201] = "Project_Created";
|
||
EventType[EventType["Project_Edited"] = 2202] = "Project_Edited";
|
||
EventType[EventType["Project_Deleted"] = 2203] = "Project_Deleted";
|
||
EventType[EventType["ServiceAccount_UserAdded"] = 2300] = "ServiceAccount_UserAdded";
|
||
EventType[EventType["ServiceAccount_UserRemoved"] = 2301] = "ServiceAccount_UserRemoved";
|
||
EventType[EventType["ServiceAccount_GroupAdded"] = 2302] = "ServiceAccount_GroupAdded";
|
||
EventType[EventType["ServiceAccount_GroupRemoved"] = 2303] = "ServiceAccount_GroupRemoved";
|
||
EventType[EventType["ServiceAccount_Created"] = 2304] = "ServiceAccount_Created";
|
||
EventType[EventType["ServiceAccount_Deleted"] = 2305] = "ServiceAccount_Deleted";
|
||
})(EventType || (EventType = {}));
|
||
|
||
;// ../../libs/common/src/enums/http-status-code.enum.ts
|
||
/**
|
||
* Hypertext Transfer Protocol (HTTP) response status codes.
|
||
*
|
||
* @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes}
|
||
* src: https://gist.github.com/RWOverdijk/6cef816cfdf5722228e01cc05fd4b094
|
||
*/
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var HttpStatusCode;
|
||
(function (HttpStatusCode) {
|
||
/**
|
||
* The server has received the request headers and the client should proceed to send the request body
|
||
* (in the case of a request for which a body needs to be sent; for example, a POST request).
|
||
* Sending a large request body to a server after a request has been rejected for inappropriate headers would be inefficient.
|
||
* To have a server check the request's headers, a client must send Expect: 100-continue as a header in its initial request
|
||
* and receive a 100 Continue status code in response before sending the body. The response 417 Expectation Failed indicates the request should not be continued.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Continue"] = 100] = "Continue";
|
||
/**
|
||
* The requester has asked the server to switch protocols and the server has agreed to do so.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["SwitchingProtocols"] = 101] = "SwitchingProtocols";
|
||
/**
|
||
* A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request.
|
||
* This code indicates that the server has received and is processing the request, but no response is available yet.
|
||
* This prevents the client from timing out and assuming the request was lost.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Processing"] = 102] = "Processing";
|
||
// **********************************************************************************************************
|
||
// 200s - SUCCESS
|
||
// **********************************************************************************************************
|
||
/**
|
||
* Standard response for successful HTTP requests.
|
||
* The actual response will depend on the request method used.
|
||
* In a GET request, the response will contain an entity corresponding to the requested resource.
|
||
* In a POST request, the response will contain an entity describing or containing the result of the action.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Ok"] = 200] = "Ok";
|
||
/**
|
||
* The request has been fulfilled, resulting in the creation of a new resource.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Created"] = 201] = "Created";
|
||
/**
|
||
* The request has been accepted for processing, but the processing has not been completed.
|
||
* The request might or might not be eventually acted upon, and may be disallowed when processing occurs.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Accepted"] = 202] = "Accepted";
|
||
/**
|
||
* SINCE HTTP/1.1
|
||
* The server is a transforming proxy that received a 200 OK from its origin,
|
||
* but is returning a modified version of the origin's response.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NonAuthoritativeInformation"] = 203] = "NonAuthoritativeInformation";
|
||
/**
|
||
* The server successfully processed the request and is not returning any content.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NoContent"] = 204] = "NoContent";
|
||
/**
|
||
* The server successfully processed the request, but is not returning any content.
|
||
* Unlike a 204 response, this response requires that the requester reset the document view.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["ResetContent"] = 205] = "ResetContent";
|
||
/**
|
||
* The server is delivering only part of the resource (byte serving) due to a range header sent by the client.
|
||
* The range header is used by HTTP clients to enable resuming of interrupted downloads,
|
||
* or split a download into multiple simultaneous streams.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["PartialContent"] = 206] = "PartialContent";
|
||
/**
|
||
* The message body that follows is an XML message and can contain a number of separate response codes,
|
||
* depending on how many sub-requests were made.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["MultiStatus"] = 207] = "MultiStatus";
|
||
/**
|
||
* The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response,
|
||
* and are not being included again.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["AlreadyReported"] = 208] = "AlreadyReported";
|
||
/**
|
||
* The server has fulfilled a request for the resource,
|
||
* and the response is a representation of the result of one or more instance-manipulations applied to the current instance.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["ImUsed"] = 226] = "ImUsed";
|
||
// **********************************************************************************************************
|
||
// 300s - Redirections
|
||
// **********************************************************************************************************
|
||
/**
|
||
* Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation).
|
||
* For example, this code could be used to present multiple video format options,
|
||
* to list files with different filename extensions, or to suggest word-sense disambiguation.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["MultipleChoices"] = 300] = "MultipleChoices";
|
||
/**
|
||
* This and all future requests should be directed to the given URI.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["MovedPermanently"] = 301] = "MovedPermanently";
|
||
/**
|
||
* This is an example of industry practice contradicting the standard.
|
||
* The HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect
|
||
* (the original describing phrase was "Moved Temporarily"), but popular browsers implemented 302
|
||
* with the functionality of a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307
|
||
* to distinguish between the two behaviours. However, some Web applications and frameworks
|
||
* use the 302 status code as if it were the 303.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Found"] = 302] = "Found";
|
||
/**
|
||
* SINCE HTTP/1.1
|
||
* The response to the request can be found under another URI using a GET method.
|
||
* When received in response to a POST (or PUT/DELETE), the client should presume that
|
||
* the server has received the data and should issue a redirect with a separate GET message.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["SeeOther"] = 303] = "SeeOther";
|
||
/**
|
||
* Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match.
|
||
* In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NotModified"] = 304] = "NotModified";
|
||
/**
|
||
* SINCE HTTP/1.1
|
||
* The requested resource is available only through a proxy, the address for which is provided in the response.
|
||
* Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status code, primarily for security reasons.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["UseProxy"] = 305] = "UseProxy";
|
||
/**
|
||
* No longer used. Originally meant "Subsequent requests should use the specified proxy."
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["SwitchProxy"] = 306] = "SwitchProxy";
|
||
/**
|
||
* SINCE HTTP/1.1
|
||
* In this case, the request should be repeated with another URI; however, future requests should still use the original URI.
|
||
* In contrast to how 302 was historically implemented, the request method is not allowed to be changed when reissuing the original request.
|
||
* For example, a POST request should be repeated using another POST request.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["TemporaryRedirect"] = 307] = "TemporaryRedirect";
|
||
/**
|
||
* The request and all future requests should be repeated using another URI.
|
||
* 307 and 308 parallel the behaviors of 302 and 301, but do not allow the HTTP method to change.
|
||
* So, for example, submitting a form to a permanently redirected resource may continue smoothly.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["PermanentRedirect"] = 308] = "PermanentRedirect";
|
||
// **********************************************************************************************************
|
||
// 400s - Client / User messed up
|
||
// **********************************************************************************************************
|
||
/**
|
||
* The server cannot or will not process the request due to an apparent client error
|
||
* (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing).
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["BadRequest"] = 400] = "BadRequest";
|
||
/**
|
||
* Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet
|
||
* been provided. The response must include a WWW-Authenticate header field containing a challenge applicable to the
|
||
* requested resource. See Basic access authentication and Digest access authentication. 401 semantically means
|
||
* "unauthenticated",i.e. the user does not have the necessary credentials.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Unauthorized"] = 401] = "Unauthorized";
|
||
/**
|
||
* Reserved for future use. The original intention was that this code might be used as part of some form of digital
|
||
* cash or micro payment scheme, but that has not happened, and this code is not usually used.
|
||
* Google Developers API uses this status if a particular developer has exceeded the daily limit on requests.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["PaymentRequired"] = 402] = "PaymentRequired";
|
||
/**
|
||
* The request was valid, but the server is refusing action.
|
||
* The user might not have the necessary permissions for a resource.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Forbidden"] = 403] = "Forbidden";
|
||
/**
|
||
* The requested resource could not be found but may be available in the future.
|
||
* Subsequent requests by the client are permissible.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NotFound"] = 404] = "NotFound";
|
||
/**
|
||
* A request method is not supported for the requested resource;
|
||
* for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["MethodNotAllowed"] = 405] = "MethodNotAllowed";
|
||
/**
|
||
* The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NotAcceptable"] = 406] = "NotAcceptable";
|
||
/**
|
||
* The client must first authenticate itself with the proxy.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired";
|
||
/**
|
||
* The server timed out waiting for the request.
|
||
* According to HTTP specifications:
|
||
* "The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time."
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["RequestTimeout"] = 408] = "RequestTimeout";
|
||
/**
|
||
* Indicates that the request could not be processed because of conflict in the request,
|
||
* such as an edit conflict between multiple simultaneous updates.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Conflict"] = 409] = "Conflict";
|
||
/**
|
||
* Indicates that the resource requested is no longer available and will not be available again.
|
||
* This should be used when a resource has been intentionally removed and the resource should be purged.
|
||
* Upon receiving a 410 status code, the client should not request the resource in the future.
|
||
* Clients such as search engines should remove the resource from their indices.
|
||
* Most use cases do not require clients and search engines to purge the resource, and a "404 Not Found" may be used instead.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Gone"] = 410] = "Gone";
|
||
/**
|
||
* The request did not specify the length of its content, which is required by the requested resource.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["LengthRequired"] = 411] = "LengthRequired";
|
||
/**
|
||
* The server does not meet one of the preconditions that the requester put on the request.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["PreconditionFailed"] = 412] = "PreconditionFailed";
|
||
/**
|
||
* The request is larger than the server is willing or able to process. Previously called "Request Entity Too Large".
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["PayloadTooLarge"] = 413] = "PayloadTooLarge";
|
||
/**
|
||
* The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request,
|
||
* in which case it should be converted to a POST request.
|
||
* Called "Request-URI Too Long" previously.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["UriTooLong"] = 414] = "UriTooLong";
|
||
/**
|
||
* The request entity has a media type which the server or resource does not support.
|
||
* For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
|
||
/**
|
||
* The client has asked for a portion of the file (byte serving), but the server cannot supply that portion.
|
||
* For example, if the client asked for a part of the file that lies beyond the end of the file.
|
||
* Called "Requested Range Not Satisfiable" previously.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["RangeNotSatisfiable"] = 416] = "RangeNotSatisfiable";
|
||
/**
|
||
* The server cannot meet the requirements of the Expect request-header field.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["ExpectationFailed"] = 417] = "ExpectationFailed";
|
||
/**
|
||
* This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol,
|
||
* and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by
|
||
* teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including Google.com.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["IAmATeapot"] = 418] = "IAmATeapot";
|
||
/**
|
||
* The request was directed at a server that is not able to produce a response (for example because a connection reuse).
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["MisdirectedRequest"] = 421] = "MisdirectedRequest";
|
||
/**
|
||
* The request was well-formed but was unable to be followed due to semantic errors.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["UnprocessableEntity"] = 422] = "UnprocessableEntity";
|
||
/**
|
||
* The resource that is being accessed is locked.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["Locked"] = 423] = "Locked";
|
||
/**
|
||
* The request failed due to failure of a previous request (e.g., a PROPPATCH).
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["FailedDependency"] = 424] = "FailedDependency";
|
||
/**
|
||
* The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["UpgradeRequired"] = 426] = "UpgradeRequired";
|
||
/**
|
||
* The origin server requires the request to be conditional.
|
||
* Intended to prevent "the 'lost update' problem, where a client
|
||
* GETs a resource's state, modifies it, and PUTs it back to the server,
|
||
* when meanwhile a third party has modified the state on the server, leading to a conflict."
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["PreconditionRequired"] = 428] = "PreconditionRequired";
|
||
/**
|
||
* The user has sent too many requests in a given amount of time. Intended for use with rate-limiting schemes.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["TooManyRequests"] = 429] = "TooManyRequests";
|
||
/**
|
||
* The server is unwilling to process the request because either an individual header field,
|
||
* or all the header fields collectively, are too large.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
|
||
/**
|
||
* A server operator has received a legal demand to deny access to a resource or to a set of resources
|
||
* that includes the requested resource. The code 451 was chosen as a reference to the novel Fahrenheit 451.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
|
||
// **********************************************************************************************************
|
||
// 500s - Server messed up
|
||
// **********************************************************************************************************
|
||
/**
|
||
* A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["InternalServerError"] = 500] = "InternalServerError";
|
||
/**
|
||
* The server either does not recognize the request method, or it lacks the ability to fulfill the request.
|
||
* Usually this implies future availability (e.g., a new feature of a web-service API).
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NotImplemented"] = 501] = "NotImplemented";
|
||
/**
|
||
* The server was acting as a gateway or proxy and received an invalid response from the upstream server.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["BadGateway"] = 502] = "BadGateway";
|
||
/**
|
||
* The server is currently unavailable (because it is overloaded or down for maintenance).
|
||
* Generally, this is a temporary state.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["ServiceUnavailable"] = 503] = "ServiceUnavailable";
|
||
/**
|
||
* The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["GatewayTimeout"] = 504] = "GatewayTimeout";
|
||
/**
|
||
* The server does not support the HTTP protocol version used in the request
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["HttpVersionNotSupported"] = 505] = "HttpVersionNotSupported";
|
||
/**
|
||
* Transparent content negotiation for the request results in a circular reference.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
|
||
/**
|
||
* The server is unable to store the representation needed to complete the request.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["InsufficientStorage"] = 507] = "InsufficientStorage";
|
||
/**
|
||
* The server detected an infinite loop while processing the request.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["LoopDetected"] = 508] = "LoopDetected";
|
||
/**
|
||
* Further extensions to the request are required for the server to fulfill it.
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NotExtended"] = 510] = "NotExtended";
|
||
/**
|
||
* The client needs to authenticate to gain network access.
|
||
* Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used
|
||
* to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).
|
||
*/
|
||
HttpStatusCode[HttpStatusCode["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
|
||
})(HttpStatusCode || (HttpStatusCode = {}));
|
||
|
||
;// ../../libs/common/src/enums/integration-type.enum.ts
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var IntegrationType;
|
||
(function (IntegrationType) {
|
||
IntegrationType["Integration"] = "integration";
|
||
IntegrationType["SDK"] = "sdk";
|
||
IntegrationType["SSO"] = "sso";
|
||
IntegrationType["SCIM"] = "scim";
|
||
IntegrationType["BWDC"] = "bwdc";
|
||
IntegrationType["EVENT"] = "event";
|
||
IntegrationType["DEVICE"] = "device";
|
||
})(IntegrationType || (IntegrationType = {}));
|
||
|
||
;// ../../libs/common/src/enums/native-messaging-version.enum.ts
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var NativeMessagingVersion;
|
||
(function (NativeMessagingVersion) {
|
||
NativeMessagingVersion[NativeMessagingVersion["One"] = 1] = "One";
|
||
NativeMessagingVersion[NativeMessagingVersion["Latest"] = 1] = "Latest";
|
||
})(NativeMessagingVersion || (NativeMessagingVersion = {}));
|
||
|
||
;// ../../libs/common/src/enums/notification-type.enum.ts
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var NotificationType;
|
||
(function (NotificationType) {
|
||
NotificationType[NotificationType["SyncCipherUpdate"] = 0] = "SyncCipherUpdate";
|
||
NotificationType[NotificationType["SyncCipherCreate"] = 1] = "SyncCipherCreate";
|
||
NotificationType[NotificationType["SyncLoginDelete"] = 2] = "SyncLoginDelete";
|
||
NotificationType[NotificationType["SyncFolderDelete"] = 3] = "SyncFolderDelete";
|
||
NotificationType[NotificationType["SyncCiphers"] = 4] = "SyncCiphers";
|
||
NotificationType[NotificationType["SyncVault"] = 5] = "SyncVault";
|
||
NotificationType[NotificationType["SyncOrgKeys"] = 6] = "SyncOrgKeys";
|
||
NotificationType[NotificationType["SyncFolderCreate"] = 7] = "SyncFolderCreate";
|
||
NotificationType[NotificationType["SyncFolderUpdate"] = 8] = "SyncFolderUpdate";
|
||
NotificationType[NotificationType["SyncCipherDelete"] = 9] = "SyncCipherDelete";
|
||
NotificationType[NotificationType["SyncSettings"] = 10] = "SyncSettings";
|
||
NotificationType[NotificationType["LogOut"] = 11] = "LogOut";
|
||
NotificationType[NotificationType["SyncSendCreate"] = 12] = "SyncSendCreate";
|
||
NotificationType[NotificationType["SyncSendUpdate"] = 13] = "SyncSendUpdate";
|
||
NotificationType[NotificationType["SyncSendDelete"] = 14] = "SyncSendDelete";
|
||
NotificationType[NotificationType["AuthRequest"] = 15] = "AuthRequest";
|
||
NotificationType[NotificationType["AuthRequestResponse"] = 16] = "AuthRequestResponse";
|
||
NotificationType[NotificationType["SyncOrganizations"] = 17] = "SyncOrganizations";
|
||
NotificationType[NotificationType["SyncOrganizationStatusChanged"] = 18] = "SyncOrganizationStatusChanged";
|
||
NotificationType[NotificationType["SyncOrganizationCollectionSettingChanged"] = 19] = "SyncOrganizationCollectionSettingChanged";
|
||
NotificationType[NotificationType["Notification"] = 20] = "Notification";
|
||
NotificationType[NotificationType["NotificationStatus"] = 21] = "NotificationStatus";
|
||
NotificationType[NotificationType["RefreshSecurityTasks"] = 22] = "RefreshSecurityTasks";
|
||
NotificationType[NotificationType["OrganizationBankAccountVerified"] = 23] = "OrganizationBankAccountVerified";
|
||
NotificationType[NotificationType["ProviderBankAccountVerified"] = 24] = "ProviderBankAccountVerified";
|
||
NotificationType[NotificationType["SyncPolicy"] = 25] = "SyncPolicy";
|
||
})(NotificationType || (NotificationType = {}));
|
||
|
||
;// ../../libs/common/src/enums/push-notification-logout-reason.enum.ts
|
||
const PushNotificationLogOutReasonType = Object.freeze({
|
||
KdfChange: 0,
|
||
});
|
||
|
||
;// ../../libs/common/src/enums/index.ts
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;// ../../libs/platform/src/services/browser-service.ts
|
||
function isBrowserSafariApi() {
|
||
return (navigator.userAgent.indexOf(" Safari/") !== -1 &&
|
||
navigator.userAgent.indexOf(" Chrome/") === -1 &&
|
||
navigator.userAgent.indexOf(" Chromium/") === -1);
|
||
}
|
||
|
||
;// ../../libs/common/src/platform/scheduling/task-scheduler.service.ts
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
/**
|
||
* Creates a RXJS scheduler based on a {@link TaskSchedulerService}.
|
||
*
|
||
* @description This API defers to `TaskSchedulerService` to schedule a task to be ran
|
||
* in the future but the task that is ran is NOT the remainder of your RXJS pipeline. The
|
||
* task you want ran must instead be registered in a location reachable on a service worker
|
||
* startup (on browser). An example of an acceptible location is the constructor of a service
|
||
* you know is created in `MainBackground`. Uses of this API in other clients _can_ have the
|
||
* `registerTaskHandler` call in more places, but in order to have it work across clients
|
||
* it is recommended to register it according to the rules of browser.
|
||
*
|
||
* @link https://rxjs.dev/guide/scheduler#using-schedulers
|
||
*
|
||
* @example
|
||
* ```ts
|
||
* class MyService {
|
||
* constructor(messageListener: MessageListener, taskScheduler: TaskSchedulerService) {
|
||
* // VERY IMPORTANT!
|
||
* this.taskSchedulerService.registerTaskHandler(SchedulerTaskNames.myTaskName, async () => {
|
||
* await this.runEvent();
|
||
* });
|
||
*
|
||
* messageListener.messages$(MY_MESSAGE).pipe(
|
||
* debounceTime(
|
||
* 10 * 1000,
|
||
* toScheduler(taskScheduler, ShedulerTaskNames.myTaskName),
|
||
* ),
|
||
* switchMap(() => this.runEvent()),
|
||
* )
|
||
* }
|
||
* }
|
||
* ```
|
||
*
|
||
* @param taskScheduler The task scheduler service to use to shedule RXJS work.
|
||
* @param taskName The name of the task that the handler should be registered and scheduled based on.
|
||
* @returns A SchedulerLike object that can be passed in to RXJS operators like `delay` and `timeout`.
|
||
*/
|
||
function toScheduler(taskScheduler, taskName) {
|
||
return new TaskSchedulerSheduler(taskScheduler, taskName);
|
||
}
|
||
class TaskSchedulerSheduler {
|
||
constructor(taskSchedulerService, taskName) {
|
||
this.taskSchedulerService = taskSchedulerService;
|
||
this.taskName = taskName;
|
||
}
|
||
schedule(work, delay, state) {
|
||
return this.taskSchedulerService.setTimeout(this.taskName, delay !== null && delay !== void 0 ? delay : 0);
|
||
}
|
||
now() {
|
||
return asyncScheduler.now();
|
||
}
|
||
}
|
||
class TaskSchedulerService {
|
||
}
|
||
|
||
;// ../../libs/common/src/platform/scheduling/default-task-scheduler.service.ts
|
||
var default_task_scheduler_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
class DefaultTaskSchedulerService extends TaskSchedulerService {
|
||
constructor(logService) {
|
||
super();
|
||
this.logService = logService;
|
||
this.taskHandlers = new Map();
|
||
}
|
||
/**
|
||
* Sets a timeout and returns the timeout id.
|
||
*
|
||
* @param taskName - The name of the task. Unused in the base implementation.
|
||
* @param delayInMs - The delay in milliseconds.
|
||
*/
|
||
setTimeout(taskName, delayInMs) {
|
||
this.validateRegisteredTask(taskName);
|
||
const timeoutHandle = globalThis.setTimeout(() => this.triggerTask(taskName), delayInMs);
|
||
return new Subscription(() => globalThis.clearTimeout(timeoutHandle));
|
||
}
|
||
/**
|
||
* Sets an interval and returns the interval id.
|
||
*
|
||
* @param taskName - The name of the task. Unused in the base implementation.
|
||
* @param intervalInMs - The interval in milliseconds.
|
||
* @param _initialDelayInMs - The initial delay in milliseconds. Unused in the base implementation.
|
||
*/
|
||
setInterval(taskName, intervalInMs, _initialDelayInMs) {
|
||
this.validateRegisteredTask(taskName);
|
||
const intervalHandle = globalThis.setInterval(() => this.triggerTask(taskName), intervalInMs);
|
||
return new Subscription(() => globalThis.clearInterval(intervalHandle));
|
||
}
|
||
/**
|
||
* Registers a task handler.
|
||
*
|
||
* @param taskName - The name of the task.
|
||
* @param handler - The task handler.
|
||
*/
|
||
registerTaskHandler(taskName, handler) {
|
||
const existingHandler = this.taskHandlers.get(taskName);
|
||
if (existingHandler) {
|
||
this.logService.warning(`Task handler for ${taskName} already exists. Overwriting.`);
|
||
this.unregisterTaskHandler(taskName);
|
||
}
|
||
this.taskHandlers.set(taskName, handler);
|
||
}
|
||
/**
|
||
* Unregisters a task handler.
|
||
*
|
||
* @param taskName - The name of the task.
|
||
*/
|
||
unregisterTaskHandler(taskName) {
|
||
this.taskHandlers.delete(taskName);
|
||
}
|
||
/**
|
||
* Triggers a task.
|
||
*
|
||
* @param taskName - The name of the task.
|
||
* @param _periodInMinutes - The period in minutes. Unused in the base implementation.
|
||
*/
|
||
triggerTask(taskName, _periodInMinutes) {
|
||
return default_task_scheduler_service_awaiter(this, void 0, void 0, function* () {
|
||
const handler = this.taskHandlers.get(taskName);
|
||
if (handler) {
|
||
handler();
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Validates that a task handler is registered.
|
||
*
|
||
* @param taskName - The name of the task.
|
||
*/
|
||
validateRegisteredTask(taskName) {
|
||
if (!this.taskHandlers.has(taskName)) {
|
||
throw new Error(`Task handler for ${taskName} not registered. Unable to schedule task.`);
|
||
}
|
||
}
|
||
}
|
||
|
||
;// ../../libs/common/src/platform/scheduling/scheduled-task-name.enum.ts
|
||
const scheduled_task_name_enum_ScheduledTaskNames = {
|
||
generatePasswordClearClipboardTimeout: "generatePasswordClearClipboardTimeout",
|
||
systemClearClipboardTimeout: "systemClearClipboardTimeout",
|
||
loginStrategySessionTimeout: "loginStrategySessionTimeout",
|
||
notificationsReconnectTimeout: "notificationsReconnectTimeout",
|
||
fido2ClientAbortTimeout: "fido2ClientAbortTimeout",
|
||
scheduleNextSyncInterval: "scheduleNextSyncInterval",
|
||
eventUploadsInterval: "eventUploadsInterval",
|
||
vaultTimeoutCheckInterval: "vaultTimeoutCheckInterval",
|
||
clearPopupViewCache: "clearPopupViewCache",
|
||
phishingDomainUpdate: "phishingDomainUpdate",
|
||
};
|
||
|
||
;// ../../libs/common/src/platform/scheduling/index.ts
|
||
|
||
|
||
|
||
|
||
;// ../../libs/platform/src/background-sync/background-sync.service.ts
|
||
|
||
/**
|
||
* The default interval between background syncs.
|
||
* 300,000ms = 5 minutes
|
||
*/
|
||
const DEFAULT_SYNC_INTERVAL_MS = 300000;
|
||
/**
|
||
* Service responsible for registering and managing background synchronization for the browser extension.
|
||
* Handles scheduling of periodic sync operations using the task scheduler infrastructure.
|
||
*/
|
||
class BackgroundSyncService {
|
||
/**
|
||
* Creates a new instance of BackgroundSyncService.
|
||
* @param taskSchedulerService - Service that handles scheduling and execution of periodic tasks
|
||
*/
|
||
constructor(taskSchedulerService) {
|
||
this.taskSchedulerService = taskSchedulerService;
|
||
}
|
||
/**
|
||
* Registers a callback function to be executed when the sync interval task is triggered.
|
||
* This associates the sync task name with the provided callback in the task scheduler.
|
||
*
|
||
* @param syncCallback - The function to execute when the sync task is triggered
|
||
*/
|
||
register(syncCallback) {
|
||
this.taskSchedulerService.registerTaskHandler(ScheduledTaskNames.scheduleNextSyncInterval, syncCallback);
|
||
}
|
||
/**
|
||
* Initializes the background sync service by scheduling the sync interval task.
|
||
* This sets up a recurring timer that triggers the registered sync callback at regular intervals.
|
||
*
|
||
* @param intervalMs - The interval in milliseconds between sync operations (defaults to 300000ms/5 minutes)
|
||
*/
|
||
init(intervalMs = DEFAULT_SYNC_INTERVAL_MS) {
|
||
intervalMs = intervalMs < 1 ? DEFAULT_SYNC_INTERVAL_MS : intervalMs;
|
||
this.taskSchedulerService.setInterval(ScheduledTaskNames.scheduleNextSyncInterval, intervalMs);
|
||
}
|
||
}
|
||
|
||
;// ../../libs/platform/src/background-sync/index.ts
|
||
|
||
|
||
;// ../../libs/platform/src/index.ts
|
||
|
||
|
||
|
||
;// ./src/browser/safariApp.ts
|
||
|
||
class SafariApp {
|
||
static sendMessageToApp(command, data = null, resolveNow = false) {
|
||
if (!browser_api_BrowserApi.isSafariApi) {
|
||
return Promise.resolve(null);
|
||
}
|
||
return new Promise((resolve) => {
|
||
const now = new Date();
|
||
const messageId = now.getTime().toString() + "_" + Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
|
||
browser.runtime.sendNativeMessage("com.bitwarden.desktop", {
|
||
id: messageId,
|
||
command: command,
|
||
data: data,
|
||
responseData: null,
|
||
}, (response) => {
|
||
resolve(response);
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/logging/src/log-level.ts
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var LogLevel;
|
||
(function (LogLevel) {
|
||
LogLevel[LogLevel["Debug"] = 0] = "Debug";
|
||
LogLevel[LogLevel["Info"] = 1] = "Info";
|
||
LogLevel[LogLevel["Warning"] = 2] = "Warning";
|
||
LogLevel[LogLevel["Error"] = 3] = "Error";
|
||
})(LogLevel || (LogLevel = {}));
|
||
|
||
;// ../../libs/logging/src/console-log.service.ts
|
||
|
||
class ConsoleLogService {
|
||
constructor(isDev, filter = null) {
|
||
this.isDev = isDev;
|
||
this.filter = filter;
|
||
this.timersMap = new Map();
|
||
}
|
||
debug(message, ...optionalParams) {
|
||
if (!this.isDev) {
|
||
return;
|
||
}
|
||
this.write(LogLevel.Debug, message, ...optionalParams);
|
||
}
|
||
info(message, ...optionalParams) {
|
||
this.write(LogLevel.Info, message, ...optionalParams);
|
||
}
|
||
warning(message, ...optionalParams) {
|
||
this.write(LogLevel.Warning, message, ...optionalParams);
|
||
}
|
||
error(message, ...optionalParams) {
|
||
this.write(LogLevel.Error, message, ...optionalParams);
|
||
}
|
||
write(level, message, ...optionalParams) {
|
||
if (this.filter != null && this.filter(level)) {
|
||
return;
|
||
}
|
||
switch (level) {
|
||
case LogLevel.Debug:
|
||
// eslint-disable-next-line
|
||
console.log(message, ...optionalParams);
|
||
break;
|
||
case LogLevel.Info:
|
||
// eslint-disable-next-line
|
||
console.log(message, ...optionalParams);
|
||
break;
|
||
case LogLevel.Warning:
|
||
// eslint-disable-next-line
|
||
console.warn(message, ...optionalParams);
|
||
break;
|
||
case LogLevel.Error:
|
||
// eslint-disable-next-line
|
||
console.error(message, ...optionalParams);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
measure(start, trackGroup, track, name, properties) {
|
||
const measureName = `[${track}]: ${name}`;
|
||
const measure = performance.measure(measureName, {
|
||
start: start,
|
||
detail: {
|
||
devtools: {
|
||
dataType: "track-entry",
|
||
track,
|
||
trackGroup,
|
||
properties,
|
||
},
|
||
},
|
||
});
|
||
this.info(`${measureName} took ${measure.duration}`, properties);
|
||
return measure;
|
||
}
|
||
mark(name) {
|
||
const mark = performance.mark(name, {
|
||
detail: {
|
||
devtools: {
|
||
dataType: "marker",
|
||
},
|
||
},
|
||
});
|
||
this.info(mark.name, new Date().toISOString());
|
||
return mark;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/logging/src/index.ts
|
||
|
||
|
||
|
||
|
||
;// ../../libs/common/src/platform/services/console-log.service.ts
|
||
|
||
|
||
;// ./src/platform/services/browser-clipboard.service.ts
|
||
var browser_clipboard_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class BrowserClipboardService {
|
||
/**
|
||
* Copies the given text to the user's clipboard.
|
||
*
|
||
* @param globalContext - The global window context.
|
||
* @param text - The text to copy.
|
||
*/
|
||
static copy(globalContext, text) {
|
||
return browser_clipboard_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!BrowserClipboardService.isClipboardApiSupported(globalContext, "writeText")) {
|
||
this.useLegacyCopyMethod(globalContext, text);
|
||
return;
|
||
}
|
||
try {
|
||
yield globalContext.navigator.clipboard.writeText(text);
|
||
}
|
||
catch (error) {
|
||
BrowserClipboardService.consoleLogService.debug(`Error copying to clipboard using the clipboard API, attempting legacy method: ${error}`);
|
||
this.useLegacyCopyMethod(globalContext, text);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Reads the user's clipboard and returns the text.
|
||
*
|
||
* @param globalContext - The global window context.
|
||
*/
|
||
static read(globalContext) {
|
||
return browser_clipboard_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!BrowserClipboardService.isClipboardApiSupported(globalContext, "readText")) {
|
||
return this.useLegacyReadMethod(globalContext);
|
||
}
|
||
try {
|
||
return yield globalContext.navigator.clipboard.readText();
|
||
}
|
||
catch (error) {
|
||
BrowserClipboardService.consoleLogService.debug(`Error reading from clipboard using the clipboard API, attempting legacy method: ${error}`);
|
||
return this.useLegacyReadMethod(globalContext);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Copies the given text to the user's clipboard using the legacy `execCommand` method. This
|
||
* method is used as a fallback when the clipboard API is not supported or fails.
|
||
*
|
||
* @param globalContext - The global window context.
|
||
* @param text - The text to copy.
|
||
*/
|
||
static useLegacyCopyMethod(globalContext, text) {
|
||
if (!BrowserClipboardService.isLegacyClipboardMethodSupported(globalContext, "copy")) {
|
||
BrowserClipboardService.consoleLogService.warning("Legacy copy method not supported");
|
||
return;
|
||
}
|
||
const textareaElement = globalContext.document.createElement("textarea");
|
||
textareaElement.textContent = !text ? " " : text;
|
||
textareaElement.style.position = "fixed";
|
||
globalContext.document.body.appendChild(textareaElement);
|
||
textareaElement.select();
|
||
try {
|
||
globalContext.document.execCommand("copy");
|
||
}
|
||
catch (error) {
|
||
BrowserClipboardService.consoleLogService.warning(`Error writing to clipboard: ${error}`);
|
||
}
|
||
finally {
|
||
globalContext.document.body.removeChild(textareaElement);
|
||
}
|
||
}
|
||
/**
|
||
* Reads the user's clipboard using the legacy `execCommand` method. This method is used as a
|
||
* fallback when the clipboard API is not supported or fails.
|
||
*
|
||
* @param globalContext - The global window context.
|
||
*/
|
||
static useLegacyReadMethod(globalContext) {
|
||
if (!BrowserClipboardService.isLegacyClipboardMethodSupported(globalContext, "paste")) {
|
||
BrowserClipboardService.consoleLogService.warning("Legacy paste method not supported");
|
||
return "";
|
||
}
|
||
const textareaElement = globalContext.document.createElement("textarea");
|
||
textareaElement.style.position = "fixed";
|
||
globalContext.document.body.appendChild(textareaElement);
|
||
textareaElement.focus();
|
||
try {
|
||
return globalContext.document.execCommand("paste") ? textareaElement.value : "";
|
||
}
|
||
catch (error) {
|
||
BrowserClipboardService.consoleLogService.warning(`Error reading from clipboard: ${error}`);
|
||
}
|
||
finally {
|
||
globalContext.document.body.removeChild(textareaElement);
|
||
}
|
||
return "";
|
||
}
|
||
/**
|
||
* Checks if the clipboard API is supported in the current environment.
|
||
*
|
||
* @param globalContext - The global window context.
|
||
* @param method - The clipboard API method to check for support.
|
||
*/
|
||
static isClipboardApiSupported(globalContext, method) {
|
||
return "clipboard" in globalContext.navigator && method in globalContext.navigator.clipboard;
|
||
}
|
||
/**
|
||
* Checks if the legacy clipboard method is supported in the current environment.
|
||
*
|
||
* @param globalContext - The global window context.
|
||
* @param method - The legacy clipboard method to check for support.
|
||
*/
|
||
static isLegacyClipboardMethodSupported(globalContext, method) {
|
||
return ("queryCommandSupported" in globalContext.document &&
|
||
globalContext.document.queryCommandSupported(method));
|
||
}
|
||
}
|
||
BrowserClipboardService.consoleLogService = new ConsoleLogService(false);
|
||
/* harmony default export */ var browser_clipboard_service = (BrowserClipboardService);
|
||
|
||
;// ./src/platform/services/platform-utils/browser-platform-utils.service.ts
|
||
var browser_platform_utils_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
|
||
|
||
|
||
class BrowserPlatformUtilsService {
|
||
constructor(clipboardWriteCallback, globalContext, offscreenDocumentService) {
|
||
this.clipboardWriteCallback = clipboardWriteCallback;
|
||
this.globalContext = globalContext;
|
||
this.offscreenDocumentService = offscreenDocumentService;
|
||
}
|
||
static getDevice(globalContext) {
|
||
if (this.deviceCache) {
|
||
return this.deviceCache;
|
||
}
|
||
// ORDERING MATTERS HERE
|
||
// Ordered from most specific to least specific. We try to discern the greatest detail
|
||
// for the type of extension the user is on by checking specific cases first and as we go down
|
||
// the list we hope to catch all by the most generic clients they could be on.
|
||
if (BrowserPlatformUtilsService.isFirefox()) {
|
||
this.deviceCache = DeviceType.FirefoxExtension;
|
||
}
|
||
else if (BrowserPlatformUtilsService.isOpera(globalContext)) {
|
||
this.deviceCache = DeviceType.OperaExtension;
|
||
}
|
||
else if (BrowserPlatformUtilsService.isEdge()) {
|
||
this.deviceCache = DeviceType.EdgeExtension;
|
||
}
|
||
else if (BrowserPlatformUtilsService.isVivaldi()) {
|
||
this.deviceCache = DeviceType.VivaldiExtension;
|
||
}
|
||
else if (BrowserPlatformUtilsService.isChrome(globalContext)) {
|
||
this.deviceCache = DeviceType.ChromeExtension;
|
||
}
|
||
else if (BrowserPlatformUtilsService.isSafari(globalContext)) {
|
||
this.deviceCache = DeviceType.SafariExtension;
|
||
}
|
||
return this.deviceCache;
|
||
}
|
||
getDevice() {
|
||
return BrowserPlatformUtilsService.getDevice(this.globalContext);
|
||
}
|
||
getDeviceString() {
|
||
const device = DeviceType[this.getDevice()].toLowerCase();
|
||
return device.replace("extension", "");
|
||
}
|
||
getClientType() {
|
||
return ClientType.Browser;
|
||
}
|
||
static isFirefox() {
|
||
return (navigator.userAgent.indexOf(" Firefox/") !== -1 ||
|
||
navigator.userAgent.indexOf(" Gecko/") !== -1);
|
||
}
|
||
isFirefox() {
|
||
return this.getDevice() === DeviceType.FirefoxExtension;
|
||
}
|
||
static isChrome(globalContext) {
|
||
return globalContext.chrome && navigator.userAgent.indexOf(" Chrome/") !== -1;
|
||
}
|
||
isChrome() {
|
||
return this.getDevice() === DeviceType.ChromeExtension;
|
||
}
|
||
static isEdge() {
|
||
return navigator.userAgent.indexOf(" Edg/") !== -1;
|
||
}
|
||
isEdge() {
|
||
return this.getDevice() === DeviceType.EdgeExtension;
|
||
}
|
||
static isOpera(globalContext) {
|
||
var _a;
|
||
return (!!((_a = globalContext.opr) === null || _a === void 0 ? void 0 : _a.addons) ||
|
||
!!globalContext.opera ||
|
||
navigator.userAgent.indexOf(" OPR/") >= 0);
|
||
}
|
||
isOpera() {
|
||
return this.getDevice() === DeviceType.OperaExtension;
|
||
}
|
||
static isVivaldi() {
|
||
return navigator.userAgent.indexOf(" Vivaldi/") !== -1;
|
||
}
|
||
isVivaldi() {
|
||
return this.getDevice() === DeviceType.VivaldiExtension;
|
||
}
|
||
static isSafari(globalContext) {
|
||
// Opera masquerades as Safari, so make sure we're not there first
|
||
return (!BrowserPlatformUtilsService.isOpera(globalContext) &&
|
||
navigator.userAgent.indexOf(" Safari/") !== -1);
|
||
}
|
||
static safariVersion() {
|
||
var _a;
|
||
return (_a = navigator.userAgent.match("Version/([0-9.]*)")) === null || _a === void 0 ? void 0 : _a[1];
|
||
}
|
||
isSafari() {
|
||
return this.getDevice() === DeviceType.SafariExtension;
|
||
}
|
||
isChromium() {
|
||
return this.isChrome() || this.isEdge() || this.isOpera() || this.isVivaldi();
|
||
}
|
||
/**
|
||
* Safari previous to version 16.1 had a bug which caused artifacts on hover in large extension popups.
|
||
* https://bugs.webkit.org/show_bug.cgi?id=218704
|
||
*/
|
||
static shouldApplySafariHeightFix(globalContext) {
|
||
var _a;
|
||
if (BrowserPlatformUtilsService.getDevice(globalContext) !== DeviceType.SafariExtension) {
|
||
return false;
|
||
}
|
||
const version = BrowserPlatformUtilsService.safariVersion();
|
||
const parts = (_a = version === null || version === void 0 ? void 0 : version.split(".")) === null || _a === void 0 ? void 0 : _a.map((v) => Number(v));
|
||
return (parts === null || parts === void 0 ? void 0 : parts[0]) < 16 || ((parts === null || parts === void 0 ? void 0 : parts[0]) === 16 && (parts === null || parts === void 0 ? void 0 : parts[1]) === 0);
|
||
}
|
||
isIE() {
|
||
return false;
|
||
}
|
||
isMacAppStore() {
|
||
return false;
|
||
}
|
||
/**
|
||
* Identifies if the vault popup is currently open. This is done by sending a
|
||
* message to the popup and waiting for a response. If a response is received,
|
||
* the view is open.
|
||
*/
|
||
isPopupOpen() {
|
||
return browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
if (this.isSafari()) {
|
||
// Query views on safari since chrome.runtime.sendMessage does not timeout and will hang.
|
||
return browser_api_BrowserApi.isPopupOpen();
|
||
}
|
||
return new Promise((resolve, reject) => {
|
||
chrome.runtime.sendMessage({ command: "checkVaultPopupHeartbeat" }, (response) => {
|
||
if (chrome.runtime.lastError != null) {
|
||
// This error means that nothing was there to listen to the message,
|
||
// meaning the view is not open.
|
||
if (chrome.runtime.lastError.message ===
|
||
"Could not establish connection. Receiving end does not exist.") {
|
||
resolve(false);
|
||
return;
|
||
}
|
||
// All unhandled errors still reject
|
||
reject(chrome.runtime.lastError);
|
||
return;
|
||
}
|
||
resolve(Boolean(response));
|
||
});
|
||
});
|
||
});
|
||
}
|
||
lockTimeout() {
|
||
return null;
|
||
}
|
||
launchUri(uri, options) {
|
||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||
browser_api_BrowserApi.createNewTab(uri, options && options.extensionPage === true);
|
||
}
|
||
getApplicationVersion() {
|
||
var _a;
|
||
const manifest = chrome.runtime.getManifest();
|
||
return Promise.resolve((_a = manifest.version_name) !== null && _a !== void 0 ? _a : manifest.version);
|
||
}
|
||
getApplicationVersionNumber() {
|
||
const manifest = chrome.runtime.getManifest();
|
||
return Promise.resolve(manifest.version.split(RegExp("[+|-]"))[0].trim());
|
||
}
|
||
supportsWebAuthn(win) {
|
||
return typeof PublicKeyCredential !== "undefined";
|
||
}
|
||
supportsDuo() {
|
||
return true;
|
||
}
|
||
supportsAutofill() {
|
||
return true;
|
||
}
|
||
supportsFileDownloads() {
|
||
return false;
|
||
}
|
||
isDev() {
|
||
return "production" === "development";
|
||
}
|
||
isSelfHost() {
|
||
return false;
|
||
}
|
||
/**
|
||
* Copies the passed text to the clipboard. For Safari, this will use
|
||
* the native messaging API to send the text to the Bitwarden app. If
|
||
* the extension is using manifest v3, the offscreen document API will
|
||
* be used to copy the text to the clipboard. Otherwise, the browser's
|
||
* clipboard API will be used.
|
||
*
|
||
* @param text - The text to copy to the clipboard.
|
||
* @param options - Options for the clipboard operation.
|
||
*/
|
||
copyToClipboard(text, options) {
|
||
const windowContext = (options === null || options === void 0 ? void 0 : options.window) || this.globalContext;
|
||
const clearing = Boolean(options === null || options === void 0 ? void 0 : options.clearing);
|
||
const clearMs = (options === null || options === void 0 ? void 0 : options.clearMs) || null;
|
||
const handleClipboardWriteCallback = () => {
|
||
if (!clearing && this.clipboardWriteCallback != null) {
|
||
this.clipboardWriteCallback(text, clearMs);
|
||
}
|
||
};
|
||
if (this.isSafari()) {
|
||
void SafariApp.sendMessageToApp("copyToClipboard", text).then(handleClipboardWriteCallback);
|
||
return;
|
||
}
|
||
if (this.isChrome() && text === "") {
|
||
text = "\u0000";
|
||
}
|
||
if (browser_api_BrowserApi.isManifestVersion(3) && this.offscreenDocumentService.offscreenApiSupported()) {
|
||
void this.triggerOffscreenCopyToClipboard(text).then(handleClipboardWriteCallback);
|
||
return;
|
||
}
|
||
void browser_clipboard_service.copy(windowContext, text).then(handleClipboardWriteCallback);
|
||
}
|
||
/**
|
||
* Reads the text from the clipboard. For Safari, this will use the
|
||
* native messaging API to request the text from the Bitwarden app. If
|
||
* the extension is using manifest v3, the offscreen document API will
|
||
* be used to read the text from the clipboard. Otherwise, the browser's
|
||
* clipboard API will be used.
|
||
*
|
||
* @param options - Options for the clipboard operation.
|
||
*/
|
||
readFromClipboard(options) {
|
||
return browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
const windowContext = (options === null || options === void 0 ? void 0 : options.window) || this.globalContext;
|
||
if (this.isSafari()) {
|
||
return yield SafariApp.sendMessageToApp("readFromClipboard");
|
||
}
|
||
if (browser_api_BrowserApi.isManifestVersion(3) && this.offscreenDocumentService.offscreenApiSupported()) {
|
||
return yield this.triggerOffscreenReadFromClipboard();
|
||
}
|
||
return yield browser_clipboard_service.read(windowContext);
|
||
});
|
||
}
|
||
supportsSecureStorage() {
|
||
return false;
|
||
}
|
||
getAutofillKeyboardShortcut() {
|
||
return browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
let autofillCommand;
|
||
// You can not change the command in Safari or obtain it programmatically
|
||
if (this.isSafari()) {
|
||
autofillCommand = "Cmd+Shift+L";
|
||
}
|
||
else if (this.isFirefox()) {
|
||
autofillCommand = (yield browser.commands.getAll()).find((c) => c.name === ExtensionCommand.AutofillLogin).shortcut;
|
||
// Firefox is returning Ctrl instead of Cmd for the modifier key on macOS if
|
||
// the command is the default one set on installation.
|
||
if ((yield browser.runtime.getPlatformInfo()).os === "mac" &&
|
||
autofillCommand === "Ctrl+Shift+L") {
|
||
autofillCommand = "Cmd+Shift+L";
|
||
}
|
||
}
|
||
else {
|
||
yield new Promise((resolve) => chrome.commands.getAll((c) => resolve((autofillCommand = c.find((c) => c.name === ExtensionCommand.AutofillLogin).shortcut))));
|
||
}
|
||
return autofillCommand;
|
||
});
|
||
}
|
||
packageType() {
|
||
return browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
switch (this.getDevice()) {
|
||
case DeviceType.ChromeExtension:
|
||
return "Chrome Extension";
|
||
case DeviceType.FirefoxExtension:
|
||
return "Firefox Extension";
|
||
case DeviceType.OperaExtension:
|
||
return "Opera Extension";
|
||
case DeviceType.EdgeExtension:
|
||
return "Edge Extension";
|
||
case DeviceType.VivaldiExtension:
|
||
return "Vivaldi Extension";
|
||
case DeviceType.SafariExtension:
|
||
return "Safari Extension";
|
||
default:
|
||
return "Unknown Browser Extension";
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Triggers the offscreen document API to copy the text to the clipboard.
|
||
*/
|
||
triggerOffscreenCopyToClipboard(text) {
|
||
return browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.offscreenDocumentService.withDocument([chrome.offscreen.Reason.CLIPBOARD], "Write text to the clipboard.", () => browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
yield browser_api_BrowserApi.sendMessageWithResponse("offscreenCopyToClipboard", { text });
|
||
}));
|
||
});
|
||
}
|
||
/**
|
||
* Triggers the offscreen document API to read the text from the clipboard.
|
||
*/
|
||
triggerOffscreenReadFromClipboard() {
|
||
return browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
const response = yield this.offscreenDocumentService.withDocument([chrome.offscreen.Reason.CLIPBOARD], "Read text from the clipboard.", () => browser_platform_utils_service_awaiter(this, void 0, void 0, function* () {
|
||
return yield browser_api_BrowserApi.sendMessageWithResponse("offscreenReadFromClipboard");
|
||
}));
|
||
if (typeof response === "string") {
|
||
return response;
|
||
}
|
||
return "";
|
||
});
|
||
}
|
||
}
|
||
BrowserPlatformUtilsService.deviceCache = null;
|
||
|
||
;// ./src/platform/browser/browser-api.register-content-scripts-polyfill.ts
|
||
var browser_api_register_content_scripts_polyfill_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
/**
|
||
* MIT License
|
||
*
|
||
* Copyright (c) Federico Brigante <me@fregante.com> (https://fregante.com)
|
||
*
|
||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||
*
|
||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||
*
|
||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
*
|
||
* @see https://github.com/fregante/content-scripts-register-polyfill
|
||
* @version 4.0.2
|
||
*/
|
||
|
||
|
||
let registerContentScripts;
|
||
function registerContentScriptsPolyfill(contentScriptOptions, callback) {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () {
|
||
if (!registerContentScripts) {
|
||
registerContentScripts = buildRegisterContentScriptsPolyfill();
|
||
}
|
||
return registerContentScripts(contentScriptOptions, callback);
|
||
});
|
||
}
|
||
function buildRegisterContentScriptsPolyfill() {
|
||
var _a, _b;
|
||
const logService = new ConsoleLogService(false);
|
||
const chromeProxy = globalThis.chrome && NestedProxy(globalThis.chrome);
|
||
const patternValidationRegex = /^(https?|wss?|file|ftp|\*):\/\/(\*|\*\.[^*/]+|[^*/]+)\/.*$|^file:\/\/\/.*$|^resource:\/\/(\*|\*\.[^*/]+|[^*/]+)\/.*$|^about:/;
|
||
const isFirefox = (_a = globalThis.navigator) === null || _a === void 0 ? void 0 : _a.userAgent.includes("Firefox/");
|
||
const gotScripting = Boolean((_b = globalThis.chrome) === null || _b === void 0 ? void 0 : _b.scripting);
|
||
const gotNavigation = typeof chrome === "object" && "webNavigation" in chrome;
|
||
function NestedProxy(target) {
|
||
return new Proxy(target, {
|
||
get(target, prop) {
|
||
if (!target[prop]) {
|
||
return;
|
||
}
|
||
if (typeof target[prop] !== "function") {
|
||
return NestedProxy(target[prop]);
|
||
}
|
||
return (...arguments_) => new Promise((resolve, reject) => {
|
||
target[prop](...arguments_, (result) => {
|
||
if (chrome.runtime.lastError) {
|
||
reject(new Error(chrome.runtime.lastError.message));
|
||
}
|
||
else {
|
||
resolve(result);
|
||
}
|
||
});
|
||
});
|
||
},
|
||
});
|
||
}
|
||
function assertValidPattern(matchPattern) {
|
||
if (!isValidPattern(matchPattern)) {
|
||
throw new Error(`${matchPattern} is an invalid pattern, it must match ${String(patternValidationRegex)}`);
|
||
}
|
||
}
|
||
function isValidPattern(matchPattern) {
|
||
return matchPattern === "<all_urls>" || patternValidationRegex.test(matchPattern);
|
||
}
|
||
function getRawPatternRegex(matchPattern) {
|
||
assertValidPattern(matchPattern);
|
||
let [, protocol, host = "", pathname] = matchPattern.split(/(^[^:]+:[/][/])([^/]+)?/);
|
||
protocol = protocol
|
||
.replace("*", isFirefox ? "(https?|wss?)" : "https?")
|
||
.replaceAll(/[/]/g, "[/]");
|
||
if (host === "*") {
|
||
host = "[^/]+";
|
||
}
|
||
else if (host) {
|
||
host = host
|
||
.replace(/^[*][.]/, "([^/]+.)*")
|
||
.replaceAll(/[.]/g, "[.]")
|
||
.replace(/[*]$/, "[^.]+");
|
||
}
|
||
pathname = pathname
|
||
.replaceAll(/[/]/g, "[/]")
|
||
.replaceAll(/[.]/g, "[.]")
|
||
.replaceAll(/[*]/g, ".*");
|
||
return "^" + protocol + host + "(" + pathname + ")?$";
|
||
}
|
||
function patternToRegex(...matchPatterns) {
|
||
if (matchPatterns.length === 0) {
|
||
return /$./;
|
||
}
|
||
if (matchPatterns.includes("<all_urls>")) {
|
||
// <all_urls> regex
|
||
return /^(https?|file|ftp):[/]+/;
|
||
}
|
||
if (matchPatterns.includes("*://*/*")) {
|
||
// all stars regex
|
||
return isFirefox ? /^(https?|wss?):[/][/][^/]+([/].*)?$/ : /^https?:[/][/][^/]+([/].*)?$/;
|
||
}
|
||
return new RegExp(matchPatterns.map((x) => getRawPatternRegex(x)).join("|"));
|
||
}
|
||
function castAllFramesTarget(target) {
|
||
if (typeof target === "object") {
|
||
return Object.assign(Object.assign({}, target), { allFrames: false });
|
||
}
|
||
return {
|
||
tabId: target,
|
||
frameId: undefined,
|
||
allFrames: true,
|
||
};
|
||
}
|
||
function castArray(possibleArray) {
|
||
if (Array.isArray(possibleArray)) {
|
||
return possibleArray;
|
||
}
|
||
return [possibleArray];
|
||
}
|
||
function createTarget(tabId, frameId, allFrames) {
|
||
if (frameId === undefined) {
|
||
return {
|
||
tabId,
|
||
frameIds: undefined,
|
||
allFrames: allFrames,
|
||
};
|
||
}
|
||
else {
|
||
return {
|
||
tabId,
|
||
frameIds: [frameId],
|
||
allFrames: undefined,
|
||
};
|
||
}
|
||
}
|
||
function insertCSS(_a) {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, arguments, void 0, function* ({ tabId, frameId, files, allFrames, matchAboutBlank, runAt, }, { ignoreTargetErrors } = {}) {
|
||
const everyInsertion = Promise.all(files.map((content) => browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () {
|
||
if (typeof content === "string") {
|
||
content = { file: content };
|
||
}
|
||
if (gotScripting) {
|
||
if ("file" in content) {
|
||
return chrome.scripting.insertCSS({
|
||
target: createTarget(tabId, frameId, allFrames),
|
||
files: [content.file],
|
||
});
|
||
}
|
||
else {
|
||
return chrome.scripting.insertCSS({
|
||
target: createTarget(tabId, frameId, allFrames),
|
||
css: content.code,
|
||
});
|
||
}
|
||
}
|
||
return chromeProxy.tabs.insertCSS(tabId, Object.assign(Object.assign({}, content), { matchAboutBlank,
|
||
allFrames,
|
||
frameId, runAt: runAt !== null && runAt !== void 0 ? runAt : "document_start" }));
|
||
})));
|
||
if (ignoreTargetErrors) {
|
||
yield catchTargetInjectionErrors(everyInsertion);
|
||
}
|
||
else {
|
||
yield everyInsertion;
|
||
}
|
||
});
|
||
}
|
||
function assertNoCode(files) {
|
||
if (files.some((content) => "code" in content)) {
|
||
throw new Error("chrome.scripting does not support injecting strings of `code`");
|
||
}
|
||
}
|
||
function executeScript(_a) {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, arguments, void 0, function* ({ tabId, frameId, files, allFrames, matchAboutBlank, runAt, }, { ignoreTargetErrors } = {}) {
|
||
const normalizedFiles = files.map((file) => (typeof file === "string" ? { file } : file));
|
||
if (gotScripting) {
|
||
assertNoCode(normalizedFiles);
|
||
const injection = chrome.scripting.executeScript({
|
||
target: createTarget(tabId, frameId, allFrames),
|
||
files: normalizedFiles.map(({ file }) => file),
|
||
});
|
||
if (ignoreTargetErrors) {
|
||
yield catchTargetInjectionErrors(injection);
|
||
}
|
||
else {
|
||
yield injection;
|
||
}
|
||
return;
|
||
}
|
||
const executions = [];
|
||
for (const content of normalizedFiles) {
|
||
if ("code" in content) {
|
||
yield executions.at(-1);
|
||
}
|
||
executions.push(chromeProxy.tabs.executeScript(tabId, Object.assign(Object.assign({}, content), { matchAboutBlank,
|
||
allFrames,
|
||
frameId,
|
||
runAt })));
|
||
}
|
||
if (ignoreTargetErrors) {
|
||
yield catchTargetInjectionErrors(Promise.all(executions));
|
||
}
|
||
else {
|
||
yield Promise.all(executions);
|
||
}
|
||
});
|
||
}
|
||
function injectContentScript(where_1, scripts_1) {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, arguments, void 0, function* (where, scripts, options = {}) {
|
||
const targets = castArray(where);
|
||
yield Promise.all(targets.map((target) => browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () { return injectContentScriptInSpecificTarget(castAllFramesTarget(target), scripts, options); })));
|
||
});
|
||
}
|
||
function injectContentScriptInSpecificTarget(_a, scripts_1) {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, arguments, void 0, function* ({ frameId, tabId, allFrames }, scripts, options = {}) {
|
||
const injections = castArray(scripts).flatMap((script) => {
|
||
var _a, _b, _c, _d, _e, _f;
|
||
return [
|
||
insertCSS({
|
||
tabId,
|
||
frameId,
|
||
allFrames,
|
||
files: (_a = script.css) !== null && _a !== void 0 ? _a : [],
|
||
matchAboutBlank: (_b = script.matchAboutBlank) !== null && _b !== void 0 ? _b : script.match_about_blank,
|
||
runAt: (_c = script.runAt) !== null && _c !== void 0 ? _c : script.run_at,
|
||
}, options),
|
||
executeScript({
|
||
tabId,
|
||
frameId,
|
||
allFrames,
|
||
files: (_d = script.js) !== null && _d !== void 0 ? _d : [],
|
||
matchAboutBlank: (_e = script.matchAboutBlank) !== null && _e !== void 0 ? _e : script.match_about_blank,
|
||
runAt: (_f = script.runAt) !== null && _f !== void 0 ? _f : script.run_at,
|
||
}, options),
|
||
];
|
||
});
|
||
yield Promise.all(injections);
|
||
});
|
||
}
|
||
function catchTargetInjectionErrors(promise) {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () {
|
||
try {
|
||
yield promise;
|
||
}
|
||
catch (error) {
|
||
const targetErrors = /^No frame with id \d+ in tab \d+.$|^No tab with id: \d+.$|^The tab was closed.$|^The frame was removed.$/;
|
||
if (!targetErrors.test(error === null || error === void 0 ? void 0 : error.message)) {
|
||
throw error;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
function isOriginPermitted(url) {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () {
|
||
return chromeProxy.permissions.contains({
|
||
origins: [new URL(url).origin + "/*"],
|
||
});
|
||
});
|
||
}
|
||
return (contentScriptOptions, callback) => browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () {
|
||
const { js = [], css = [], matchAboutBlank, matches = [], excludeMatches, runAt, } = contentScriptOptions;
|
||
let { allFrames } = contentScriptOptions;
|
||
if (gotNavigation) {
|
||
allFrames = false;
|
||
}
|
||
else if (allFrames) {
|
||
logService.warning("`allFrames: true` requires the `webNavigation` permission to work correctly: https://github.com/fregante/content-scripts-register-polyfill#permissions");
|
||
}
|
||
if (matches.length === 0) {
|
||
throw new Error("Type error for parameter contentScriptOptions (Error processing matches: Array requires at least 1 items; you have 0) for contentScripts.register.");
|
||
}
|
||
yield Promise.all(matches.map((pattern) => browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () {
|
||
if (!(yield chromeProxy.permissions.contains({ origins: [pattern] }))) {
|
||
throw new Error(`Permission denied to register a content script for ${pattern}`);
|
||
}
|
||
})));
|
||
const matchesRegex = patternToRegex(...matches);
|
||
const excludeMatchesRegex = patternToRegex(...(excludeMatches !== null && excludeMatches !== void 0 ? excludeMatches : []));
|
||
const inject = (url_1, tabId_1, ...args_1) => browser_api_register_content_scripts_polyfill_awaiter(this, [url_1, tabId_1, ...args_1], void 0, function* (url, tabId, frameId = 0) {
|
||
if (!matchesRegex.test(url) ||
|
||
excludeMatchesRegex.test(url) ||
|
||
!(yield isOriginPermitted(url))) {
|
||
return;
|
||
}
|
||
yield injectContentScript({ tabId, frameId }, { css, js, matchAboutBlank, runAt }, { ignoreTargetErrors: true });
|
||
});
|
||
const tabListener = (tabId_1, _a, _b) => browser_api_register_content_scripts_polyfill_awaiter(this, [tabId_1, _a, _b], void 0, function* (tabId, { status }, { url }) {
|
||
if (status === "loading" && url) {
|
||
void inject(url, tabId);
|
||
}
|
||
});
|
||
const navListener = (_a) => browser_api_register_content_scripts_polyfill_awaiter(this, [_a], void 0, function* ({ tabId, frameId, url, }) {
|
||
void inject(url, tabId, frameId);
|
||
});
|
||
if (gotNavigation) {
|
||
browser_api_BrowserApi.addListener(chrome.webNavigation.onCommitted, navListener);
|
||
}
|
||
else {
|
||
browser_api_BrowserApi.addListener(chrome.tabs.onUpdated, tabListener);
|
||
}
|
||
const registeredContentScript = {
|
||
unregister() {
|
||
return browser_api_register_content_scripts_polyfill_awaiter(this, void 0, void 0, function* () {
|
||
if (gotNavigation) {
|
||
chrome.webNavigation.onCommitted.removeListener(navListener);
|
||
}
|
||
else {
|
||
chrome.tabs.onUpdated.removeListener(tabListener);
|
||
}
|
||
});
|
||
},
|
||
};
|
||
if (typeof callback === "function") {
|
||
callback(registeredContentScript);
|
||
}
|
||
return registeredContentScript;
|
||
});
|
||
}
|
||
|
||
;// ./src/platform/browser/browser-api.ts
|
||
var browser_api_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
|
||
|
||
|
||
|
||
class browser_api_BrowserApi {
|
||
static get manifestVersion() {
|
||
return chrome.runtime.getManifest().manifest_version;
|
||
}
|
||
/**
|
||
* Determines if the extension manifest version is the given version.
|
||
*
|
||
* @param expectedVersion - The expected manifest version to check against.
|
||
*/
|
||
static isManifestVersion(expectedVersion) {
|
||
return browser_api_BrowserApi.manifestVersion === expectedVersion;
|
||
}
|
||
/**
|
||
* Helper method that attempts to distinguish whether a message sender is internal to the extension or not.
|
||
*
|
||
* Currently this is done through source origin matching, and frameId checking (only top-level frames are internal).
|
||
* @param sender a message sender
|
||
* @param logger an optional logger to log validation results
|
||
* @returns whether or not the sender appears to be internal to the extension
|
||
*/
|
||
static senderIsInternal(sender, logger) {
|
||
var _a, _b;
|
||
if (!(sender === null || sender === void 0 ? void 0 : sender.origin)) {
|
||
logger === null || logger === void 0 ? void 0 : logger.warning("[BrowserApi] Message sender has no origin");
|
||
return false;
|
||
}
|
||
const extensionUrl = (typeof chrome !== "undefined" && ((_a = chrome.runtime) === null || _a === void 0 ? void 0 : _a.getURL(""))) ||
|
||
(typeof browser !== "undefined" && ((_b = browser.runtime) === null || _b === void 0 ? void 0 : _b.getURL(""))) ||
|
||
"";
|
||
if (!extensionUrl) {
|
||
logger === null || logger === void 0 ? void 0 : logger.warning("[BrowserApi] Unable to determine extension URL");
|
||
return false;
|
||
}
|
||
// Normalize both URLs by removing trailing slashes
|
||
const normalizedOrigin = sender.origin.replace(/\/$/, "").toLowerCase();
|
||
const normalizedExtensionUrl = extensionUrl.replace(/\/$/, "").toLowerCase();
|
||
if (!normalizedOrigin.startsWith(normalizedExtensionUrl)) {
|
||
logger === null || logger === void 0 ? void 0 : logger.warning(`[BrowserApi] Message sender origin (${normalizedOrigin}) does not match extension URL (${normalizedExtensionUrl})`);
|
||
return false;
|
||
}
|
||
// We only send messages from the top-level frame, but frameId is only set if tab is set, which for popups it is not.
|
||
if ("frameId" in sender && sender.frameId !== 0) {
|
||
logger === null || logger === void 0 ? void 0 : logger.warning("[BrowserApi] Message sender is not from the top-level frame");
|
||
return false;
|
||
}
|
||
logger === null || logger === void 0 ? void 0 : logger.info("[BrowserApi] Message sender appears to be internal");
|
||
return true;
|
||
}
|
||
/**
|
||
* Gets all open browser windows, including their tabs.
|
||
*
|
||
* @returns A promise that resolves to an array of browser windows.
|
||
*/
|
||
static getWindows() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.windows.getAll({ populate: true }, resolve));
|
||
});
|
||
}
|
||
/**
|
||
* Gets the current window or the window with the given id.
|
||
*
|
||
* @param windowId - The id of the window to get. If not provided, the current window is returned.
|
||
*/
|
||
static getWindow(windowId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
if (!windowId) {
|
||
return browser_api_BrowserApi.getCurrentWindow();
|
||
}
|
||
return yield browser_api_BrowserApi.getWindowById(windowId);
|
||
});
|
||
}
|
||
/**
|
||
* Gets the currently active browser window.
|
||
*/
|
||
static getCurrentWindow() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.windows.getCurrent({ populate: true }, resolve));
|
||
});
|
||
}
|
||
/**
|
||
* Gets the window with the given id.
|
||
*
|
||
* @param windowId - The id of the window to get.
|
||
*/
|
||
static getWindowById(windowId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.windows.get(windowId, { populate: true }, resolve));
|
||
});
|
||
}
|
||
static createWindow(options) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => {
|
||
chrome.windows.create(options, (newWindow) => browser_api_awaiter(this, void 0, void 0, function* () {
|
||
if (!browser_api_BrowserApi.isSafariApi) {
|
||
return resolve(newWindow);
|
||
}
|
||
// Safari doesn't close the default extension popup when a new window is created so we need to
|
||
// manually trigger the close by focusing the main window after the new window is created
|
||
const allWindows = yield new Promise((resolve) => {
|
||
chrome.windows.getAll({ windowTypes: ["normal"] }, (windows) => resolve(windows));
|
||
});
|
||
const mainWindow = allWindows.find((window) => window.id !== newWindow.id);
|
||
// No main window found, resolve the new window
|
||
if (mainWindow == null || !mainWindow.id) {
|
||
return resolve(newWindow);
|
||
}
|
||
// Focus the main window to close the extension popup
|
||
chrome.windows.update(mainWindow.id, { focused: true }, () => {
|
||
// Refocus the newly created window
|
||
chrome.windows.update(newWindow.id, { focused: true }, () => {
|
||
resolve(newWindow);
|
||
});
|
||
});
|
||
}));
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Removes the window with the given id.
|
||
*
|
||
* @param windowId - The id of the window to remove.
|
||
*/
|
||
static removeWindow(windowId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.windows.remove(windowId, () => resolve()));
|
||
});
|
||
}
|
||
/**
|
||
* Updates the properties of the window with the given id.
|
||
*
|
||
* @param windowId - The id of the window to update.
|
||
* @param options - The window properties to update.
|
||
*/
|
||
static updateWindowProperties(windowId, options) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.windows.update(windowId, options, () => {
|
||
resolve();
|
||
}));
|
||
});
|
||
}
|
||
/**
|
||
* Focuses the window with the given id.
|
||
*
|
||
* @param windowId - The id of the window to focus.
|
||
*/
|
||
static focusWindow(windowId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
yield browser_api_BrowserApi.updateWindowProperties(windowId, { focused: true });
|
||
});
|
||
}
|
||
static getTabFromCurrentWindowId() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return yield browser_api_BrowserApi.tabsQueryFirstCurrentWindowForSafari({
|
||
active: true,
|
||
windowId: chrome.windows.WINDOW_ID_CURRENT,
|
||
});
|
||
});
|
||
}
|
||
static getBrowserClientVendor(clientWindow) {
|
||
const device = BrowserPlatformUtilsService.getDevice(clientWindow);
|
||
switch (device) {
|
||
case DeviceType.ChromeExtension:
|
||
case DeviceType.ChromeBrowser:
|
||
return BrowserClientVendors.Chrome;
|
||
case DeviceType.OperaExtension:
|
||
case DeviceType.OperaBrowser:
|
||
return BrowserClientVendors.Opera;
|
||
case DeviceType.EdgeExtension:
|
||
case DeviceType.EdgeBrowser:
|
||
return BrowserClientVendors.Edge;
|
||
case DeviceType.VivaldiExtension:
|
||
case DeviceType.VivaldiBrowser:
|
||
return BrowserClientVendors.Vivaldi;
|
||
default:
|
||
return BrowserClientVendors.Unknown;
|
||
}
|
||
}
|
||
/**
|
||
* Gets the tab with the given id.
|
||
*
|
||
* @param tabId - The id of the tab to get.
|
||
*/
|
||
static getTab(tabId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
if (!tabId) {
|
||
return null;
|
||
}
|
||
if (browser_api_BrowserApi.isManifestVersion(3)) {
|
||
return yield chrome.tabs.get(tabId);
|
||
}
|
||
return new Promise((resolve) => chrome.tabs.get(tabId, (tab) => {
|
||
resolve(tab);
|
||
}));
|
||
});
|
||
}
|
||
static getTabFromCurrentWindow() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return yield browser_api_BrowserApi.tabsQueryFirstCurrentWindowForSafari({
|
||
active: true,
|
||
currentWindow: true,
|
||
});
|
||
});
|
||
}
|
||
static getActiveTabs() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return yield browser_api_BrowserApi.tabsQuery({
|
||
active: true,
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Fetch the currently open browser tab
|
||
*/
|
||
static getCurrentTab() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
if (browser_api_BrowserApi.isManifestVersion(3)) {
|
||
return yield chrome.tabs.getCurrent();
|
||
}
|
||
return new Promise((resolve) => chrome.tabs.getCurrent((tab) => {
|
||
resolve(tab);
|
||
}));
|
||
});
|
||
}
|
||
/**
|
||
* Closes a browser tab with the given id
|
||
*
|
||
* @param tabId The id of the tab to close
|
||
*/
|
||
static closeTab(tabId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
if (tabId) {
|
||
if (browser_api_BrowserApi.isWebExtensionsApi) {
|
||
yield browser.tabs.remove(tabId).catch((error) => {
|
||
throw new Error("[BrowserApi] Failed to remove current tab: " + error.message);
|
||
});
|
||
}
|
||
else if (browser_api_BrowserApi.isChromeApi) {
|
||
yield chrome.tabs.remove(tabId).catch((error) => {
|
||
throw new Error("[BrowserApi] Failed to remove current tab: " + error.message);
|
||
});
|
||
}
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Navigates a browser tab to the given URL
|
||
*
|
||
* @param tabId The id of the tab to navigate
|
||
* @param url The URL to navigate to
|
||
*/
|
||
static navigateTabToUrl(tabId, url) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
if (tabId) {
|
||
if (browser_api_BrowserApi.isWebExtensionsApi) {
|
||
yield browser.tabs.update(tabId, { url: url.href }).catch((error) => {
|
||
throw new Error("Failed to navigate tab to URL: " + error.message);
|
||
});
|
||
}
|
||
else if (browser_api_BrowserApi.isChromeApi) {
|
||
chrome.tabs.update(tabId, { url: url.href }, () => {
|
||
if (chrome.runtime.lastError) {
|
||
throw new Error("Failed to navigate tab to URL: " + chrome.runtime.lastError.message);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
});
|
||
}
|
||
static tabsQuery(options) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => {
|
||
chrome.tabs.query(options, (tabs) => {
|
||
resolve(tabs);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
static tabsQueryFirst(options) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
const tabs = yield browser_api_BrowserApi.tabsQuery(options);
|
||
if (tabs.length > 0) {
|
||
return tabs[0];
|
||
}
|
||
return null;
|
||
});
|
||
}
|
||
/**
|
||
* Drop-in replacement for {@link BrowserApi.tabsQueryFirst}.
|
||
*
|
||
* Safari sometimes returns >1 tabs unexpectedly even when
|
||
* specifying a `windowId` or `currentWindow: true` query option.
|
||
*
|
||
* For all of these calls,
|
||
* ```
|
||
* await chrome.tabs.query({active: true, currentWindow: true})
|
||
* await chrome.tabs.query({active: true, windowId: chrome.windows.WINDOW_ID_CURRENT})
|
||
* await chrome.tabs.query({active: true, windowId: 10})
|
||
* ```
|
||
*
|
||
* Safari could return:
|
||
* ```
|
||
* [
|
||
* {windowId: 2, pinned: true, title: "Incorrect tab in another window", …},
|
||
* {windowId: 10, title: "Correct tab in foreground", …},
|
||
* ]
|
||
* ```
|
||
*
|
||
* This function captures the current window ID manually before running the query,
|
||
* then finds and returns the tab with the matching window ID.
|
||
*
|
||
* See the `SafariTabsQuery` tests in `browser-api.spec.ts`.
|
||
*
|
||
* This workaround can be removed when Safari fixes this bug.
|
||
*/
|
||
static tabsQueryFirstCurrentWindowForSafari(options) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if (!browser_api_BrowserApi.isSafariApi) {
|
||
return yield browser_api_BrowserApi.tabsQueryFirst(options);
|
||
}
|
||
const currentWindowId = (yield browser_api_BrowserApi.getCurrentWindow()).id;
|
||
const tabs = yield browser_api_BrowserApi.tabsQuery(options);
|
||
if (tabs.length <= 1 || currentWindowId == null) {
|
||
return tabs[0];
|
||
}
|
||
return (_a = tabs.find((t) => t.windowId === currentWindowId)) !== null && _a !== void 0 ? _a : tabs[0];
|
||
});
|
||
}
|
||
static tabSendMessageData(tab, command, data = null) {
|
||
const obj = {
|
||
command: command,
|
||
};
|
||
if (data != null) {
|
||
obj.data = data;
|
||
}
|
||
return browser_api_BrowserApi.tabSendMessage(tab, obj);
|
||
}
|
||
static tabSendMessage(tab_1, obj_1) {
|
||
return browser_api_awaiter(this, arguments, void 0, function* (tab, obj, options = null, rejectOnError = false) {
|
||
if (!tab || !tab.id) {
|
||
return;
|
||
}
|
||
return new Promise((resolve, reject) => {
|
||
chrome.tabs.sendMessage(tab.id, obj, options, (response) => {
|
||
if (chrome.runtime.lastError && rejectOnError) {
|
||
// Some error happened
|
||
reject();
|
||
}
|
||
resolve(response);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
static sendTabsMessage(tabId, message, options, responseCallback) {
|
||
chrome.tabs.sendMessage(tabId, message, options, responseCallback);
|
||
}
|
||
static getRuntimeURL(path) {
|
||
if (browser_api_BrowserApi.isWebExtensionsApi) {
|
||
return browser.runtime.getURL(path);
|
||
}
|
||
else if (browser_api_BrowserApi.isChromeApi) {
|
||
return chrome.runtime.getURL(path);
|
||
}
|
||
}
|
||
static onWindowCreated(callback) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
// FIXME: Make sure that is does not cause a memory leak in Safari or use BrowserApi.AddListener
|
||
// and test that it doesn't break.
|
||
// eslint-disable-next-line no-restricted-syntax
|
||
return chrome.windows.onCreated.addListener(callback);
|
||
});
|
||
}
|
||
/**
|
||
* Gets the background page for the extension. This method is
|
||
* not valid within manifest v3 background service workers. As
|
||
* a result, it will return null when called from that context.
|
||
*/
|
||
static getBackgroundPage() {
|
||
if (typeof chrome.extension.getBackgroundPage === "undefined") {
|
||
return null;
|
||
}
|
||
return chrome.extension.getBackgroundPage();
|
||
}
|
||
/**
|
||
* Accepts a window object and determines if it is
|
||
* associated with the background page of the extension.
|
||
*
|
||
* @param window - The window to check.
|
||
*/
|
||
static isBackgroundPage(window) {
|
||
return typeof window !== "undefined" && window === browser_api_BrowserApi.getBackgroundPage();
|
||
}
|
||
/**
|
||
* Gets the extension views that match the given properties. This method is not
|
||
* available within background service worker. As a result, it will return an
|
||
* empty array when called from that context.
|
||
*
|
||
* @param fetchProperties - The properties used to filter extension views.
|
||
*/
|
||
static getExtensionViews(fetchProperties) {
|
||
if (typeof chrome.extension.getViews === "undefined") {
|
||
return [];
|
||
}
|
||
return chrome.extension.getViews(fetchProperties);
|
||
}
|
||
/**
|
||
* Queries all extension views that are of type `popup`
|
||
* and returns whether any are currently open.
|
||
*/
|
||
static isPopupOpen() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return Promise.resolve(browser_api_BrowserApi.getExtensionViews({ type: "popup" }).length > 0);
|
||
});
|
||
}
|
||
static createNewTab(url, active = true) {
|
||
return new Promise((resolve) => chrome.tabs.create({ url: url, active: active }, (tab) => resolve(tab)));
|
||
}
|
||
/**
|
||
* Gathers the details for a specified sub-frame of a tab.
|
||
*
|
||
* @param details - The details of the frame to get.
|
||
*/
|
||
static getFrameDetails(details) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.webNavigation.getFrame(details, resolve));
|
||
});
|
||
}
|
||
/**
|
||
* Gets all frames associated with a tab.
|
||
*
|
||
* @param tabId - The id of the tab to get the frames for.
|
||
*/
|
||
static getAllFrameDetails(tabId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.webNavigation.getAllFrames({ tabId }, resolve));
|
||
});
|
||
}
|
||
static messageListener(name, callback) {
|
||
browser_api_BrowserApi.addListener(chrome.runtime.onMessage, callback);
|
||
}
|
||
static messageListener$() {
|
||
return new Observable_Observable((subscriber) => {
|
||
const handler = (message) => {
|
||
subscriber.next(message);
|
||
};
|
||
browser_api_BrowserApi.addListener(chrome.runtime.onMessage, handler);
|
||
return () => browser_api_BrowserApi.removeListener(chrome.runtime.onMessage, handler);
|
||
});
|
||
}
|
||
static storageChangeListener(callback) {
|
||
browser_api_BrowserApi.addListener(chrome.storage.onChanged, callback);
|
||
}
|
||
/**
|
||
* Adds a callback to the given chrome event in a cross-browser platform manner.
|
||
*
|
||
* **Important:** All event listeners in the browser extension popup context must
|
||
* use this instead of the native APIs to handle unsubscribing from Safari properly.
|
||
*
|
||
* @param event - The event in which to add the listener to.
|
||
* @param callback - The callback you want registered onto the event.
|
||
*/
|
||
static addListener(event, callback) {
|
||
event.addListener(callback);
|
||
if (browser_api_BrowserApi.isSafariApi && !browser_api_BrowserApi.isBackgroundPage(self)) {
|
||
browser_api_BrowserApi.trackedChromeEventListeners.push([event, callback]);
|
||
browser_api_BrowserApi.setupUnloadListeners();
|
||
}
|
||
}
|
||
/**
|
||
* Removes a callback from the given chrome event in a cross-browser platform manner.
|
||
* @param event - The event in which to remove the listener from.
|
||
* @param callback - The callback you want removed from the event.
|
||
*/
|
||
static removeListener(event, callback) {
|
||
event.removeListener(callback);
|
||
if (browser_api_BrowserApi.isSafariApi && !browser_api_BrowserApi.isBackgroundPage(self)) {
|
||
const index = browser_api_BrowserApi.trackedChromeEventListeners.findIndex(([_event, eventListener]) => {
|
||
return eventListener == callback;
|
||
});
|
||
if (index !== -1) {
|
||
browser_api_BrowserApi.trackedChromeEventListeners.splice(index, 1);
|
||
}
|
||
}
|
||
}
|
||
// Setup the event to destroy all the listeners when the popup gets unloaded in Safari, otherwise we get a memory leak
|
||
static setupUnloadListeners() {
|
||
// The MDN recommend using 'visibilitychange' but that event is fired any time the popup window is obscured as well
|
||
// 'pagehide' works just like 'unload' but is compatible with the back/forward cache, so we prefer using that one
|
||
self.addEventListener("pagehide", () => {
|
||
for (const [event, callback] of browser_api_BrowserApi.trackedChromeEventListeners) {
|
||
event.removeListener(callback);
|
||
}
|
||
});
|
||
}
|
||
static sendMessage(subscriber, arg = {}) {
|
||
const message = Object.assign({}, { command: subscriber }, arg);
|
||
return chrome.runtime.sendMessage(message);
|
||
}
|
||
static sendMessageWithResponse(subscriber, arg = {}) {
|
||
const message = Object.assign({}, { command: subscriber }, arg);
|
||
return new Promise((resolve) => chrome.runtime.sendMessage(message, resolve));
|
||
}
|
||
static focusTab(tabId) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||
chrome.tabs.update(tabId, { active: true, highlighted: true });
|
||
});
|
||
}
|
||
static closePopup(win) {
|
||
if (browser_api_BrowserApi.isWebExtensionsApi && browser_api_BrowserApi.isFirefoxOnAndroid) {
|
||
// Reactivating the active tab dismisses the popup tab. The promise final
|
||
// condition is only called if the popup wasn't already dismissed (future proofing).
|
||
// ref: https://bugzilla.mozilla.org/show_bug.cgi?id=1433604
|
||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||
browser.tabs.update({ active: true }).finally(win.close);
|
||
}
|
||
else {
|
||
win.close();
|
||
}
|
||
}
|
||
static gaFilter() {
|
||
return "production" !== "production";
|
||
}
|
||
static getUILanguage() {
|
||
return chrome.i18n.getUILanguage();
|
||
}
|
||
/**
|
||
* Handles reloading the extension using the underlying functionality exposed by the browser API.
|
||
*/
|
||
static reloadExtension() {
|
||
// If we do `chrome.runtime.reload` on safari they will send an onInstalled reason of install
|
||
// and that prompts us to show a new tab, this apparently doesn't happen on sideloaded
|
||
// extensions and only shows itself production scenarios. See: https://bitwarden.atlassian.net/browse/PM-12298
|
||
if (this.isSafariApi) {
|
||
return self.location.reload();
|
||
}
|
||
return chrome.runtime.reload();
|
||
}
|
||
/**
|
||
* Reloads all open extension views, except the background page. Will also
|
||
* skip reloading the current window location if exemptCurrentHref is true.
|
||
*
|
||
* @param exemptCurrentHref - Whether to exempt the current window location from the reload.
|
||
*/
|
||
static reloadOpenWindows(exemptCurrentHref = false) {
|
||
const views = browser_api_BrowserApi.getExtensionViews();
|
||
if (!views.length) {
|
||
return;
|
||
}
|
||
const currentHref = self.location.href;
|
||
views
|
||
.filter((w) => w.location.href != null && !w.location.href.includes("background.html"))
|
||
.filter((w) => !exemptCurrentHref || w.location.href !== currentHref)
|
||
.forEach((w) => w.location.reload());
|
||
}
|
||
static connectNative(application) {
|
||
if (browser_api_BrowserApi.isWebExtensionsApi) {
|
||
return browser.runtime.connectNative(application);
|
||
}
|
||
else if (browser_api_BrowserApi.isChromeApi) {
|
||
return chrome.runtime.connectNative(application);
|
||
}
|
||
}
|
||
static requestPermission(permission) {
|
||
if (browser_api_BrowserApi.isWebExtensionsApi) {
|
||
return browser.permissions.request(permission);
|
||
}
|
||
return new Promise((resolve) => {
|
||
chrome.permissions.request(permission, resolve);
|
||
});
|
||
}
|
||
/**
|
||
* Checks if the user has provided the given permissions to the extension.
|
||
*
|
||
* @param permissions - The permissions to check.
|
||
*/
|
||
static permissionsGranted(permissions) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
return new Promise((resolve) => chrome.permissions.contains({ permissions }, (result) => resolve(result)));
|
||
});
|
||
}
|
||
static getPlatformInfo() {
|
||
if (browser_api_BrowserApi.isWebExtensionsApi) {
|
||
return browser.runtime.getPlatformInfo();
|
||
}
|
||
return new Promise((resolve) => {
|
||
chrome.runtime.getPlatformInfo(resolve);
|
||
});
|
||
}
|
||
/**
|
||
* Returns the supported BrowserAction API based on the manifest version.
|
||
*/
|
||
static getBrowserAction() {
|
||
return browser_api_BrowserApi.isManifestVersion(3) ? chrome.action : chrome.browserAction;
|
||
}
|
||
static getSidebarAction(win) {
|
||
var _a;
|
||
const deviceType = BrowserPlatformUtilsService.getDevice(win);
|
||
if (deviceType === DeviceType.FirefoxExtension) {
|
||
return browser.sidebarAction;
|
||
}
|
||
if (deviceType === DeviceType.OperaExtension) {
|
||
return (_a = win.opr) === null || _a === void 0 ? void 0 : _a.sidebarAction;
|
||
}
|
||
return null;
|
||
}
|
||
static captureVisibleTab() {
|
||
return new Promise((resolve) => {
|
||
chrome.tabs.captureVisibleTab(null, { format: "png" }, resolve);
|
||
});
|
||
}
|
||
/**
|
||
* Extension API helper method used to execute a script in a tab.
|
||
*
|
||
* @see https://developer.chrome.com/docs/extensions/reference/tabs/#method-executeScript
|
||
* @param tabId - The id of the tab to execute the script in.
|
||
* @param details {@link "InjectDetails" https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/extensionTypes/InjectDetails}
|
||
* @param scriptingApiDetails {@link "ExecutionWorld" https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/ExecutionWorld}
|
||
*/
|
||
static executeScriptInTab(tabId, details, scriptingApiDetails) {
|
||
if (browser_api_BrowserApi.isManifestVersion(3)) {
|
||
let target;
|
||
if (typeof details.frameId === "number") {
|
||
target = { tabId, frameIds: [details.frameId] };
|
||
}
|
||
else if (details.allFrames) {
|
||
target = { tabId, allFrames: true };
|
||
}
|
||
else {
|
||
target = { tabId };
|
||
}
|
||
return chrome.scripting.executeScript({
|
||
target,
|
||
files: details.file ? [details.file] : null,
|
||
injectImmediately: details.runAt === "document_start",
|
||
world: (scriptingApiDetails === null || scriptingApiDetails === void 0 ? void 0 : scriptingApiDetails.world) || chrome.scripting.ExecutionWorld.ISOLATED,
|
||
});
|
||
}
|
||
return new Promise((resolve) => {
|
||
chrome.tabs.executeScript(tabId, details, (result) => {
|
||
resolve(result);
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Identifies if the browser autofill settings are overridden by the extension.
|
||
*/
|
||
static browserAutofillSettingsOverridden() {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
if (!(yield browser_api_BrowserApi.permissionsGranted(["privacy"]))) {
|
||
return false;
|
||
}
|
||
const checkOverrideStatus = (details) => details.levelOfControl === "controlled_by_this_extension" && !details.value;
|
||
const autofillAddressOverridden = yield new Promise((resolve) => chrome.privacy.services.autofillAddressEnabled.get({}, (details) => resolve(checkOverrideStatus(details))));
|
||
const autofillCreditCardOverridden = yield new Promise((resolve) => chrome.privacy.services.autofillCreditCardEnabled.get({}, (details) => resolve(checkOverrideStatus(details))));
|
||
const passwordSavingOverridden = yield new Promise((resolve) => chrome.privacy.services.passwordSavingEnabled.get({}, (details) => resolve(checkOverrideStatus(details))));
|
||
return autofillAddressOverridden && autofillCreditCardOverridden && passwordSavingOverridden;
|
||
});
|
||
}
|
||
/**
|
||
* Updates the browser autofill settings to the given value.
|
||
*
|
||
* @param value - Determines whether to enable or disable the autofill settings.
|
||
*/
|
||
static updateDefaultBrowserAutofillSettings(value) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
yield chrome.privacy.services.autofillAddressEnabled.set({ value });
|
||
yield chrome.privacy.services.autofillCreditCardEnabled.set({ value });
|
||
yield chrome.privacy.services.passwordSavingEnabled.set({ value });
|
||
});
|
||
}
|
||
/**
|
||
* Handles registration of static content scripts within manifest v2.
|
||
*
|
||
* @param contentScriptOptions - Details of the registered content scripts
|
||
*/
|
||
static registerContentScriptsMv2(contentScriptOptions) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if (typeof browser !== "undefined" && !!((_a = browser.contentScripts) === null || _a === void 0 ? void 0 : _a.register)) {
|
||
return yield browser.contentScripts.register(contentScriptOptions);
|
||
}
|
||
return yield registerContentScriptsPolyfill(contentScriptOptions);
|
||
});
|
||
}
|
||
/**
|
||
* Handles registration of static content scripts within manifest v3.
|
||
*
|
||
* @param scripts - Details of the registered content scripts
|
||
*/
|
||
static registerContentScriptsMv3(scripts) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
yield chrome.scripting.registerContentScripts(scripts);
|
||
});
|
||
}
|
||
/**
|
||
* Handles unregistering of static content scripts within manifest v3.
|
||
*
|
||
* @param filter - Optional filter to unregister content scripts. Passing an empty object will unregister all content scripts.
|
||
*/
|
||
static unregisterContentScriptsMv3(filter) {
|
||
return browser_api_awaiter(this, void 0, void 0, function* () {
|
||
yield chrome.scripting.unregisterContentScripts(filter);
|
||
});
|
||
}
|
||
}
|
||
browser_api_BrowserApi.isWebExtensionsApi = typeof browser !== "undefined";
|
||
browser_api_BrowserApi.isSafariApi = isBrowserSafariApi();
|
||
browser_api_BrowserApi.isChromeApi = !browser_api_BrowserApi.isSafariApi && typeof chrome !== "undefined";
|
||
browser_api_BrowserApi.isFirefoxOnAndroid = navigator.userAgent.indexOf("Firefox/") !== -1 && navigator.userAgent.indexOf("Android") !== -1;
|
||
// Keep track of all the events registered in a Safari popup so we can remove
|
||
// them when the popup gets unloaded, otherwise we cause a memory leak
|
||
browser_api_BrowserApi.trackedChromeEventListeners = [];
|
||
|
||
;// ./src/autofill/notification/abstractions/notification-bar.ts
|
||
const NotificationTypes = {
|
||
Add: "add",
|
||
Change: "change",
|
||
Unlock: "unlock",
|
||
AtRiskPassword: "at-risk-password",
|
||
};
|
||
|
||
|
||
;// ./src/autofill/enums/autofill-port.enum.ts
|
||
const AutofillPort = {
|
||
InjectedScript: "autofill-injected-script-port",
|
||
};
|
||
|
||
|
||
;// ./src/autofill/utils/index.ts
|
||
var utils_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Generates a random string of characters.
|
||
*
|
||
* @param length - The length of the random string to generate.
|
||
*/
|
||
function generateRandomChars(length) {
|
||
const chars = "abcdefghijklmnopqrstuvwxyz";
|
||
const randomChars = [];
|
||
const randomBytes = new Uint8Array(length);
|
||
globalThis.crypto.getRandomValues(randomBytes);
|
||
for (let byteIndex = 0; byteIndex < randomBytes.length; byteIndex++) {
|
||
const byte = randomBytes[byteIndex];
|
||
randomChars.push(chars[byte % chars.length]);
|
||
}
|
||
return randomChars.join("");
|
||
}
|
||
/**
|
||
* Polyfills the requestIdleCallback API with a setTimeout fallback.
|
||
*
|
||
* @param callback - The callback function to run when the browser is idle.
|
||
* @param options - The options to pass to the requestIdleCallback function.
|
||
*/
|
||
function requestIdleCallbackPolyfill(callback, options) {
|
||
if ("requestIdleCallback" in globalThis) {
|
||
return globalThis.requestIdleCallback(() => callback(), options);
|
||
}
|
||
return globalThis.setTimeout(() => callback(), 1);
|
||
}
|
||
/**
|
||
* Polyfills the cancelIdleCallback API with a clearTimeout fallback.
|
||
*
|
||
* @param id - The ID of the idle callback to cancel.
|
||
*/
|
||
function cancelIdleCallbackPolyfill(id) {
|
||
if ("cancelIdleCallback" in globalThis) {
|
||
return globalThis.cancelIdleCallback(id);
|
||
}
|
||
return globalThis.clearTimeout(id);
|
||
}
|
||
/**
|
||
* Generates a random string of characters that formatted as a custom element name.
|
||
*/
|
||
function generateRandomCustomElementName() {
|
||
const length = Math.floor(Math.random() * 5) + 8; // Between 8 and 12 characters
|
||
const numHyphens = Math.min(Math.max(Math.floor(Math.random() * 4), 1), length - 1); // At least 1, maximum of 3 hyphens
|
||
const hyphenIndices = [];
|
||
while (hyphenIndices.length < numHyphens) {
|
||
const index = Math.floor(Math.random() * (length - 1)) + 1;
|
||
if (!hyphenIndices.includes(index)) {
|
||
hyphenIndices.push(index);
|
||
}
|
||
}
|
||
hyphenIndices.sort((a, b) => a - b);
|
||
let randomString = "";
|
||
let prevIndex = 0;
|
||
for (let index = 0; index < hyphenIndices.length; index++) {
|
||
const hyphenIndex = hyphenIndices[index];
|
||
randomString = randomString + generateRandomChars(hyphenIndex - prevIndex) + "-";
|
||
prevIndex = hyphenIndex;
|
||
}
|
||
randomString += generateRandomChars(length - prevIndex);
|
||
return randomString;
|
||
}
|
||
/**
|
||
* Builds a DOM element from an SVG string.
|
||
*
|
||
* @param svgString - The SVG string to build the DOM element from.
|
||
* @param ariaHidden - Determines whether the SVG should be hidden from screen readers.
|
||
*/
|
||
function buildSvgDomElement(svgString, ariaHidden = true) {
|
||
const domParser = new DOMParser();
|
||
const svgDom = domParser.parseFromString(svgString, "image/svg+xml");
|
||
const domElement = svgDom.documentElement;
|
||
domElement.setAttribute("aria-hidden", `${ariaHidden}`);
|
||
return domElement;
|
||
}
|
||
/**
|
||
* Sends a message to the extension.
|
||
*
|
||
* @param command - The command to send.
|
||
* @param options - The options to send with the command.
|
||
*/
|
||
function sendExtensionMessage(command_1) {
|
||
return utils_awaiter(this, arguments, void 0, function* (command, options = {}) {
|
||
if (typeof browser !== "undefined" &&
|
||
typeof browser.runtime !== "undefined" &&
|
||
typeof browser.runtime.sendMessage !== "undefined") {
|
||
return browser.runtime.sendMessage(Object.assign({ command }, options));
|
||
}
|
||
return new Promise((resolve) => chrome.runtime.sendMessage(Object.assign({ command }, options), (response) => {
|
||
if (chrome.runtime.lastError) {
|
||
resolve(null);
|
||
}
|
||
resolve(response);
|
||
}));
|
||
});
|
||
}
|
||
/**
|
||
* Sets CSS styles on an element.
|
||
*
|
||
* @param element - The element to set the styles on.
|
||
* @param styles - The styles to set on the element.
|
||
* @param priority - Determines whether the styles should be set as important.
|
||
*/
|
||
function setElementStyles(element, styles, priority) {
|
||
if (!element || !styles || !Object.keys(styles).length) {
|
||
return;
|
||
}
|
||
for (const styleProperty in styles) {
|
||
element.style.setProperty(styleProperty.replace(/([a-z])([A-Z])/g, "$1-$2"), // Convert camelCase to kebab-case
|
||
styles[styleProperty], priority ? "important" : undefined);
|
||
}
|
||
}
|
||
/**
|
||
* Sets up a long-lived connection with the extension background
|
||
* and triggers an onDisconnect event if the extension context
|
||
* is invalidated.
|
||
*
|
||
* @param callback - Callback export function to run when the extension disconnects
|
||
*/
|
||
function setupExtensionDisconnectAction(callback) {
|
||
const port = chrome.runtime.connect({ name: AutofillPort.InjectedScript });
|
||
const onDisconnectCallback = (disconnectedPort) => {
|
||
callback(disconnectedPort);
|
||
port.onDisconnect.removeListener(onDisconnectCallback);
|
||
};
|
||
port.onDisconnect.addListener(onDisconnectCallback);
|
||
}
|
||
/**
|
||
* Handles setup of the extension disconnect action for the autofill init class
|
||
* in both instances where the overlay might or might not be initialized.
|
||
*
|
||
* @param windowContext - The global window context
|
||
*/
|
||
function setupAutofillInitDisconnectAction(windowContext) {
|
||
if (!windowContext.bitwardenAutofillInit) {
|
||
return;
|
||
}
|
||
const onDisconnectCallback = () => {
|
||
windowContext.bitwardenAutofillInit.destroy();
|
||
delete windowContext.bitwardenAutofillInit;
|
||
};
|
||
setupExtensionDisconnectAction(onDisconnectCallback);
|
||
}
|
||
/**
|
||
* Identifies whether an element is a fillable form field.
|
||
* This is determined by whether the element is a form field and not a span.
|
||
*
|
||
* @param formFieldElement - The form field element to check.
|
||
*/
|
||
function elementIsFillableFormField(formFieldElement) {
|
||
return !elementIsSpanElement(formFieldElement);
|
||
}
|
||
/**
|
||
* Identifies whether an element is an instance of a specific tag name.
|
||
*
|
||
* @param element - The element to check.
|
||
* @param tagName - The tag name to check against.
|
||
*/
|
||
function elementIsInstanceOf(element, tagName) {
|
||
return nodeIsElement(element) && element.tagName.toLowerCase() === tagName;
|
||
}
|
||
/**
|
||
* Identifies whether an element is a span element.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsSpanElement(element) {
|
||
return elementIsInstanceOf(element, "span");
|
||
}
|
||
/**
|
||
* Identifies whether an element is an input field.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsInputElement(element) {
|
||
return elementIsInstanceOf(element, "input");
|
||
}
|
||
/**
|
||
* Identifies whether an element is a select field.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsSelectElement(element) {
|
||
return elementIsInstanceOf(element, "select");
|
||
}
|
||
/**
|
||
* Identifies whether an element is a textarea field.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsTextAreaElement(element) {
|
||
return elementIsInstanceOf(element, "textarea");
|
||
}
|
||
/**
|
||
* Identifies whether an element is a form element.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsFormElement(element) {
|
||
return elementIsInstanceOf(element, "form");
|
||
}
|
||
/**
|
||
* Identifies whether an element is a label element.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsLabelElement(element) {
|
||
return elementIsInstanceOf(element, "label");
|
||
}
|
||
/**
|
||
* Identifies whether an element is a description details `dd` element.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsDescriptionDetailsElement(element) {
|
||
return elementIsInstanceOf(element, "dd");
|
||
}
|
||
/**
|
||
* Identifies whether an element is a description term `dt` element.
|
||
*
|
||
* @param element - The element to check.
|
||
*/
|
||
function elementIsDescriptionTermElement(element) {
|
||
return elementIsInstanceOf(element, "dt");
|
||
}
|
||
/**
|
||
* Identifies whether a node is an HTML element.
|
||
*
|
||
* @param node - The node to check.
|
||
*/
|
||
function nodeIsElement(node) {
|
||
if (!node) {
|
||
return false;
|
||
}
|
||
return (node === null || node === void 0 ? void 0 : node.nodeType) === Node.ELEMENT_NODE;
|
||
}
|
||
/**
|
||
* Identifies whether a node is an input element.
|
||
*
|
||
* @param node - The node to check.
|
||
*/
|
||
function nodeIsInputElement(node) {
|
||
return nodeIsElement(node) && elementIsInputElement(node);
|
||
}
|
||
/**
|
||
* Identifies whether a node is a form element.
|
||
*
|
||
* @param node - The node to check.
|
||
*/
|
||
function nodeIsFormElement(node) {
|
||
return nodeIsElement(node) && elementIsFormElement(node);
|
||
}
|
||
function nodeIsTypeSubmitElement(node) {
|
||
return nodeIsElement(node) && getPropertyOrAttribute(node, "type") === "submit";
|
||
}
|
||
function nodeIsButtonElement(node) {
|
||
return (nodeIsElement(node) &&
|
||
(elementIsInstanceOf(node, "button") ||
|
||
getPropertyOrAttribute(node, "type") === "button"));
|
||
}
|
||
function nodeIsAnchorElement(node) {
|
||
return nodeIsElement(node) && elementIsInstanceOf(node, "a");
|
||
}
|
||
/**
|
||
* Returns a boolean representing the attribute value of an element.
|
||
*
|
||
* @param element
|
||
* @param attributeName
|
||
* @param checkString
|
||
*/
|
||
function getAttributeBoolean(element, attributeName, checkString = false) {
|
||
if (checkString) {
|
||
return getPropertyOrAttribute(element, attributeName) === "true";
|
||
}
|
||
return Boolean(getPropertyOrAttribute(element, attributeName));
|
||
}
|
||
/**
|
||
* Get the value of a property or attribute from a FormFieldElement.
|
||
*
|
||
* @param element
|
||
* @param attributeName
|
||
*/
|
||
function getPropertyOrAttribute(element, attributeName) {
|
||
if (attributeName in element) {
|
||
return element[attributeName];
|
||
}
|
||
return element.getAttribute(attributeName);
|
||
}
|
||
/**
|
||
* Throttles a callback function to run at most once every `limit` milliseconds.
|
||
*
|
||
* @param callback - The callback function to throttle.
|
||
* @param limit - The time in milliseconds to throttle the callback.
|
||
*/
|
||
function throttle(callback, limit) {
|
||
let waitingDelay = false;
|
||
return function (...args) {
|
||
if (!waitingDelay) {
|
||
callback.apply(this, args);
|
||
waitingDelay = true;
|
||
globalThis.setTimeout(() => (waitingDelay = false), limit);
|
||
}
|
||
};
|
||
}
|
||
/**
|
||
* Debounces a callback function to run after a delay of `delay` milliseconds.
|
||
*
|
||
* @param callback - The callback function to debounce.
|
||
* @param delay - The time in milliseconds to debounce the callback.
|
||
* @param immediate - Determines whether the callback should run immediately.
|
||
*/
|
||
function debounce(callback, delay, immediate) {
|
||
let timeout;
|
||
return function (...args) {
|
||
const callImmediately = !!immediate && !timeout;
|
||
if (timeout) {
|
||
globalThis.clearTimeout(timeout);
|
||
}
|
||
timeout = globalThis.setTimeout(() => {
|
||
timeout = null;
|
||
if (!callImmediately) {
|
||
callback.apply(this, args);
|
||
}
|
||
}, delay);
|
||
if (callImmediately) {
|
||
callback.apply(this, args);
|
||
}
|
||
};
|
||
}
|
||
/**
|
||
* Gathers and normalizes keywords from a potential submit button element. Used
|
||
* to verify if the element submits a login or change password form.
|
||
*
|
||
* @param element - The element to gather keywords from.
|
||
*/
|
||
function getSubmitButtonKeywordsSet(element) {
|
||
const keywords = [
|
||
element.textContent,
|
||
element.getAttribute("type"),
|
||
element.getAttribute("value"),
|
||
element.getAttribute("aria-label"),
|
||
element.getAttribute("aria-labelledby"),
|
||
element.getAttribute("aria-describedby"),
|
||
element.getAttribute("title"),
|
||
element.getAttribute("id"),
|
||
element.getAttribute("name"),
|
||
element.getAttribute("class"),
|
||
];
|
||
const keywordsSet = new Set();
|
||
for (let i = 0; i < keywords.length; i++) {
|
||
if (typeof keywords[i] === "string") {
|
||
// Iterate over all keywords metadata and split them by non-letter characters.
|
||
// This ensures we check against individual words and not the entire string.
|
||
keywords[i]
|
||
.toLowerCase()
|
||
.replace(/[-\s]/g, "")
|
||
.split(/[^\p{L}]+/gu)
|
||
.forEach((keyword) => {
|
||
if (keyword) {
|
||
keywordsSet.add(keyword);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
return keywordsSet;
|
||
}
|
||
/**
|
||
* Generates the origin and subdomain match patterns for the URL.
|
||
*
|
||
* @param url - The URL of the tab
|
||
*/
|
||
function generateDomainMatchPatterns(url) {
|
||
try {
|
||
const extensionUrlPattern = /^(chrome|chrome-extension|moz-extension|safari-web-extension):\/\/\/?/;
|
||
if (extensionUrlPattern.test(url)) {
|
||
return [];
|
||
}
|
||
// Add protocol to URL if it is missing to allow for parsing the hostname correctly
|
||
const urlPattern = /^(https?|file):\/\/\/?/;
|
||
if (!urlPattern.test(url)) {
|
||
url = `https://${url}`;
|
||
}
|
||
let protocolGlob = "*://";
|
||
if (url.startsWith("file:///")) {
|
||
protocolGlob = "*:///"; // File URLs require three slashes to be a valid match pattern
|
||
}
|
||
const parsedUrl = new URL(url);
|
||
const originMatchPattern = `${protocolGlob}${parsedUrl.hostname}/*`;
|
||
const splitHost = parsedUrl.hostname.split(".");
|
||
const domain = splitHost.slice(-2).join(".");
|
||
const subDomainMatchPattern = `${protocolGlob}*.${domain}/*`;
|
||
return [originMatchPattern, subDomainMatchPattern];
|
||
}
|
||
catch (_a) {
|
||
return [];
|
||
}
|
||
}
|
||
/**
|
||
* Determines if the status code of the web response is invalid. An invalid status code is
|
||
* any status code that is not in the 200-299 range.
|
||
*
|
||
* @param statusCode - The status code of the web response
|
||
*/
|
||
function isInvalidResponseStatusCode(statusCode) {
|
||
return statusCode < 200 || statusCode >= 300;
|
||
}
|
||
/**
|
||
* Determines if the current context is within a sandboxed iframe.
|
||
*/
|
||
function currentlyInSandboxedIframe() {
|
||
var _a, _b;
|
||
if (String(self.origin).toLowerCase() === "null" || globalThis.location.hostname === "") {
|
||
return true;
|
||
}
|
||
const sandbox = (_b = (_a = globalThis.frameElement) === null || _a === void 0 ? void 0 : _a.getAttribute) === null || _b === void 0 ? void 0 : _b.call(_a, "sandbox");
|
||
// No frameElement or sandbox attribute means not sandboxed
|
||
if (sandbox === null || sandbox === undefined) {
|
||
return false;
|
||
}
|
||
// An empty string means fully sandboxed
|
||
if (sandbox === "") {
|
||
return true;
|
||
}
|
||
const tokens = new Set(sandbox.toLowerCase().split(" "));
|
||
return !["allow-scripts", "allow-same-origin"].every((token) => tokens.has(token));
|
||
}
|
||
/**
|
||
* This object allows us to map a special character to a key name. The key name is used
|
||
* in gathering the i18n translation of the written version of the special character.
|
||
*/
|
||
const specialCharacterToKeyMap = {
|
||
" ": "spaceCharacterDescriptor",
|
||
"~": "tildeCharacterDescriptor",
|
||
"`": "backtickCharacterDescriptor",
|
||
"!": "exclamationCharacterDescriptor",
|
||
"@": "atSignCharacterDescriptor",
|
||
"#": "hashSignCharacterDescriptor",
|
||
$: "dollarSignCharacterDescriptor",
|
||
"%": "percentSignCharacterDescriptor",
|
||
"^": "caretCharacterDescriptor",
|
||
"&": "ampersandCharacterDescriptor",
|
||
"*": "asteriskCharacterDescriptor",
|
||
"(": "parenLeftCharacterDescriptor",
|
||
")": "parenRightCharacterDescriptor",
|
||
"-": "hyphenCharacterDescriptor",
|
||
_: "underscoreCharacterDescriptor",
|
||
"+": "plusCharacterDescriptor",
|
||
"=": "equalsCharacterDescriptor",
|
||
"{": "braceLeftCharacterDescriptor",
|
||
"}": "braceRightCharacterDescriptor",
|
||
"[": "bracketLeftCharacterDescriptor",
|
||
"]": "bracketRightCharacterDescriptor",
|
||
"|": "pipeCharacterDescriptor",
|
||
"\\": "backSlashCharacterDescriptor",
|
||
":": "colonCharacterDescriptor",
|
||
";": "semicolonCharacterDescriptor",
|
||
'"': "doubleQuoteCharacterDescriptor",
|
||
"'": "singleQuoteCharacterDescriptor",
|
||
"<": "lessThanCharacterDescriptor",
|
||
">": "greaterThanCharacterDescriptor",
|
||
",": "commaCharacterDescriptor",
|
||
".": "periodCharacterDescriptor",
|
||
"?": "questionCharacterDescriptor",
|
||
"/": "forwardSlashCharacterDescriptor",
|
||
};
|
||
/**
|
||
* Determines if the current rect values are not all 0.
|
||
*/
|
||
function rectHasSize(rect) {
|
||
if (rect.right > 0 && rect.left > 0 && rect.top > 0 && rect.bottom > 0) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Checks if all the values corresponding to the specified keys in an object are null.
|
||
* If no keys are specified, checks all keys in the object.
|
||
*
|
||
* @param obj - The object to check.
|
||
* @param keys - An optional array of keys to check in the object. Defaults to all keys.
|
||
* @returns Returns true if all values for the specified keys (or all keys if none are provided) are null; otherwise, false.
|
||
*/
|
||
function areKeyValuesNull(obj, keys) {
|
||
const keysToCheck = keys && keys.length > 0 ? keys : Object.keys(obj);
|
||
return keysToCheck.every((key) => obj[key] == null);
|
||
}
|
||
|
||
;// ./src/autofill/overlay/notifications/content/overlay-notifications-content.service.ts
|
||
var overlay_notifications_content_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
var overlay_notifications_content_service_rest = (undefined && undefined.__rest) || function (s, e) {
|
||
var t = {};
|
||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||
t[p] = s[p];
|
||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||
t[p[i]] = s[p[i]];
|
||
}
|
||
return t;
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
|
||
|
||
class OverlayNotificationsContentService {
|
||
constructor() {
|
||
var _a;
|
||
this.notificationBarRootElement = null;
|
||
this.notificationBarElement = null;
|
||
this.notificationBarIframeElement = null;
|
||
this.notificationBarShadowRoot = null;
|
||
this.currentNotificationBarType = null;
|
||
this.notificationBarContainerStyles = {
|
||
height: "400px",
|
||
width: "430px",
|
||
maxWidth: "calc(100% - 20px)",
|
||
minHeight: "initial",
|
||
top: "10px",
|
||
right: "0px",
|
||
padding: "0",
|
||
position: "fixed",
|
||
zIndex: "2147483647",
|
||
visibility: "visible",
|
||
borderRadius: "4px",
|
||
border: "none",
|
||
backgroundColor: "transparent",
|
||
overflow: "hidden",
|
||
transition: "box-shadow 0.15s ease",
|
||
transitionDelay: "0.15s",
|
||
};
|
||
this.notificationBarIframeElementStyles = {
|
||
width: "100%",
|
||
height: "100%",
|
||
border: "0",
|
||
display: "block",
|
||
position: "relative",
|
||
transition: "transform 0.15s ease-out, opacity 0.15s ease",
|
||
borderRadius: "4px",
|
||
colorScheme: "auto",
|
||
};
|
||
this.extensionMessageHandlers = {
|
||
openNotificationBar: ({ message }) => this.handleOpenNotificationBarMessage(message),
|
||
closeNotificationBar: ({ message }) => this.handleCloseNotificationBarMessage(message),
|
||
adjustNotificationBar: ({ message }) => this.handleAdjustNotificationBarHeightMessage(message),
|
||
saveCipherAttemptCompleted: ({ message }) => this.handleSaveCipherAttemptCompletedMessage(message),
|
||
};
|
||
/**
|
||
* Handles the load event for the notification bar iframe.
|
||
* This will animate the notification bar into view.
|
||
*/
|
||
this.handleNotificationBarIframeOnLoad = () => {
|
||
var _a;
|
||
setElementStyles(this.notificationBarIframeElement, { transform: "translateX(0)", opacity: "1" }, true);
|
||
(_a = this.notificationBarIframeElement) === null || _a === void 0 ? void 0 : _a.removeEventListener(EVENTS.LOAD, this.handleNotificationBarIframeOnLoad);
|
||
};
|
||
this.extensionOrigin = (_a = browser_api_BrowserApi.getRuntimeURL("")) === null || _a === void 0 ? void 0 : _a.slice(0, -1);
|
||
void sendExtensionMessage("checkNotificationQueue");
|
||
}
|
||
/**
|
||
* Returns the message handlers for the content script.
|
||
*/
|
||
get messageHandlers() {
|
||
return this.extensionMessageHandlers;
|
||
}
|
||
/**
|
||
* Opens the notification bar with the provided init data. Will trigger a closure
|
||
* of the notification bar if the type of the notification bar changes.
|
||
*
|
||
* @param message - The message containing the initialization data for the notification bar.
|
||
*/
|
||
handleOpenNotificationBarMessage(message) {
|
||
return overlay_notifications_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!message.data) {
|
||
return;
|
||
}
|
||
const { type, typeData, params } = message.data;
|
||
if (this.currentNotificationBarType && type !== this.currentNotificationBarType) {
|
||
this.closeNotificationBar();
|
||
}
|
||
const initData = {
|
||
type: type,
|
||
isVaultLocked: typeData.isVaultLocked,
|
||
theme: typeData.theme,
|
||
removeIndividualVault: typeData.removeIndividualVault,
|
||
importType: typeData.importType,
|
||
launchTimestamp: typeData.launchTimestamp,
|
||
params,
|
||
};
|
||
if (globalThis.document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", () => this.openNotificationBar(initData));
|
||
return;
|
||
}
|
||
this.openNotificationBar(initData);
|
||
});
|
||
}
|
||
/**
|
||
* Closes the notification bar. If the message contains a flag to fade out the notification,
|
||
* the notification bar will fade out before being removed from the DOM.
|
||
*
|
||
* @param message - The message containing the data for closing the notification bar.
|
||
*/
|
||
handleCloseNotificationBarMessage(message) {
|
||
var _a, _b;
|
||
const closedByUser = typeof ((_a = message.data) === null || _a === void 0 ? void 0 : _a.closedByUser) === "boolean" ? message.data.closedByUser : true;
|
||
if ((_b = message.data) === null || _b === void 0 ? void 0 : _b.fadeOutNotification) {
|
||
setElementStyles(this.notificationBarIframeElement, { opacity: "0" }, true);
|
||
globalThis.setTimeout(() => this.closeNotificationBar(closedByUser), 150);
|
||
return;
|
||
}
|
||
this.closeNotificationBar(closedByUser);
|
||
}
|
||
/**
|
||
* Adjusts the height of the notification bar.
|
||
*
|
||
* @param message - The message containing the height of the notification bar.
|
||
*/
|
||
handleAdjustNotificationBarHeightMessage(message) {
|
||
var _a;
|
||
if (this.notificationBarElement && ((_a = message.data) === null || _a === void 0 ? void 0 : _a.height)) {
|
||
this.notificationBarElement.style.height = `${message.data.height}px`;
|
||
}
|
||
}
|
||
/**
|
||
* Handles the message for when a save cipher attempt has completed. This triggers an update
|
||
* to the presentation of the notification bar, facilitating a visual indication of the save
|
||
* attempt's success or failure.
|
||
*
|
||
* @param message
|
||
* @private
|
||
*/
|
||
handleSaveCipherAttemptCompletedMessage(message) {
|
||
// destructure error out of data
|
||
const _a = (message === null || message === void 0 ? void 0 : message.data) || {}, { error } = _a, otherData = overlay_notifications_content_service_rest(_a, ["error"]);
|
||
this.sendMessageToNotificationBarIframe({
|
||
command: "saveCipherAttemptCompleted",
|
||
data: Object.keys(otherData).length ? otherData : undefined,
|
||
error,
|
||
});
|
||
}
|
||
/**
|
||
* Opens the notification bar with the given initialization data.
|
||
*
|
||
* @param initData
|
||
* @private
|
||
*/
|
||
openNotificationBar(initData) {
|
||
if (!this.notificationBarRootElement && !this.notificationBarIframeElement) {
|
||
this.createNotificationBarIframeElement(initData);
|
||
this.createNotificationBarElement();
|
||
this.setupInitNotificationBarMessageListener(initData);
|
||
globalThis.document.body.appendChild(this.notificationBarRootElement);
|
||
}
|
||
}
|
||
/**
|
||
* Creates the iframe element for the notification bar.
|
||
*
|
||
* @param initData - The initialization data for the notification bar.
|
||
*/
|
||
createNotificationBarIframeElement(initData) {
|
||
const isNotificationFresh = initData.launchTimestamp && Date.now() - initData.launchTimestamp < 250;
|
||
this.currentNotificationBarType = initData.type;
|
||
this.notificationBarIframeElement = globalThis.document.createElement("iframe");
|
||
this.notificationBarIframeElement.id = "bit-notification-bar-iframe";
|
||
const parentOrigin = globalThis.location.origin;
|
||
const iframeUrl = new URL(browser_api_BrowserApi.getRuntimeURL("notification/bar.html"));
|
||
iframeUrl.searchParams.set("parentOrigin", parentOrigin);
|
||
this.notificationBarIframeElement.src = iframeUrl.toString();
|
||
setElementStyles(this.notificationBarIframeElement, Object.assign(Object.assign({}, this.notificationBarIframeElementStyles), { transform: isNotificationFresh ? "translateX(100%)" : "translateX(0)", opacity: isNotificationFresh ? "1" : "0" }), true);
|
||
this.notificationBarIframeElement.addEventListener(EVENTS.LOAD, this.handleNotificationBarIframeOnLoad);
|
||
}
|
||
/**
|
||
* Creates the container for the notification bar iframe with shadow DOM.
|
||
*/
|
||
createNotificationBarElement() {
|
||
if (this.notificationBarIframeElement) {
|
||
this.notificationBarRootElement = globalThis.document.createElement("bit-notification-bar-root");
|
||
this.notificationBarShadowRoot = this.notificationBarRootElement.attachShadow({
|
||
mode: "closed",
|
||
delegatesFocus: true,
|
||
});
|
||
this.notificationBarElement = globalThis.document.createElement("div");
|
||
this.notificationBarElement.id = "bit-notification-bar";
|
||
setElementStyles(this.notificationBarElement, this.notificationBarContainerStyles, true);
|
||
this.notificationBarShadowRoot.appendChild(this.notificationBarElement);
|
||
this.notificationBarElement.appendChild(this.notificationBarIframeElement);
|
||
}
|
||
}
|
||
/**
|
||
* Sets up the message listener for the initialization of the notification bar.
|
||
* This will send the initialization data to the notification bar iframe.
|
||
*
|
||
* @param initData - The initialization data for the notification bar.
|
||
*/
|
||
setupInitNotificationBarMessageListener(initData) {
|
||
const handleInitNotificationBarMessage = (event) => {
|
||
const { source, data } = event;
|
||
if (source !== this.notificationBarIframeElement.contentWindow ||
|
||
(data === null || data === void 0 ? void 0 : data.command) !== "initNotificationBar") {
|
||
return;
|
||
}
|
||
this.sendMessageToNotificationBarIframe({
|
||
command: "initNotificationBar",
|
||
initData,
|
||
parentOrigin: globalThis.location.origin,
|
||
});
|
||
globalThis.removeEventListener("message", handleInitNotificationBarMessage);
|
||
};
|
||
if (this.notificationBarIframeElement) {
|
||
globalThis.addEventListener("message", handleInitNotificationBarMessage);
|
||
}
|
||
}
|
||
/**
|
||
* Closes the notification bar. Will trigger a removal of the notification bar
|
||
* from the background queue if the notification bar was closed by the user.
|
||
*
|
||
* @param closedByUserAction - Whether the notification bar was closed by the user.
|
||
*/
|
||
closeNotificationBar(closedByUserAction = false) {
|
||
if (!this.notificationBarRootElement && !this.notificationBarIframeElement) {
|
||
return;
|
||
}
|
||
this.notificationBarIframeElement.remove();
|
||
this.notificationBarIframeElement = null;
|
||
this.notificationBarElement.remove();
|
||
this.notificationBarElement = null;
|
||
this.notificationBarShadowRoot = null;
|
||
this.notificationBarRootElement.remove();
|
||
this.notificationBarRootElement = null;
|
||
const removableNotificationTypes = new Set([
|
||
NotificationTypes.Add,
|
||
NotificationTypes.Change,
|
||
NotificationTypes.AtRiskPassword,
|
||
]);
|
||
if (closedByUserAction && removableNotificationTypes.has(this.currentNotificationBarType)) {
|
||
void sendExtensionMessage("bgRemoveTabFromNotificationQueue");
|
||
}
|
||
this.currentNotificationBarType = null;
|
||
}
|
||
/**
|
||
* Sends a message to the notification bar iframe.
|
||
*
|
||
* @param message - The message to send to the notification bar iframe.
|
||
*/
|
||
sendMessageToNotificationBarIframe(message) {
|
||
if (this.notificationBarIframeElement) {
|
||
this.notificationBarIframeElement.contentWindow.postMessage(message, this.extensionOrigin);
|
||
}
|
||
}
|
||
/**
|
||
* Destroys the notification bar.
|
||
*/
|
||
destroy() {
|
||
this.closeNotificationBar(true);
|
||
}
|
||
}
|
||
|
||
// EXTERNAL MODULE: ../../node_modules/@webcomponents/custom-elements/custom-elements.min.js
|
||
var custom_elements_min = __webpack_require__(70526);
|
||
;// ../../node_modules/lit/polyfill-support.js
|
||
!function(i){"function"==typeof define&&define.amd?define(i):i();}(function(){"use strict";/**
|
||
* @license
|
||
* Copyright 2017 Google LLC
|
||
* SPDX-License-Identifier: BSD-3-Clause
|
||
*/var i,n,o="__scoped";null!==(i=globalThis.reactiveElementPolyfillSupport)&&void 0!==i||(globalThis.reactiveElementPolyfillSupport=function(i){var n=i.ReactiveElement;if(void 0!==window.ShadyCSS&&(!window.ShadyCSS.nativeShadow||window.ShadyCSS.ApplyShim)){var t=n.prototype;window.ShadyDOM&&window.ShadyDOM.inUse&&!0===window.ShadyDOM.noPatch&&window.ShadyDOM.patchElementProto(t);var d=t.createRenderRoot;t.createRenderRoot=function(){var i,n,t,w=this.localName;if(window.ShadyCSS.nativeShadow)return d.call(this);if(!this.constructor.hasOwnProperty(o)){this.constructor[o]=!0;var v=this.constructor.elementStyles.map(function(i){return i instanceof CSSStyleSheet?Array.from(i.cssRules).reduce(function(i,n){return i+n.cssText;},""):i.cssText;});null===(n=null===(i=window.ShadyCSS)||void 0===i?void 0:i.ScopingShim)||void 0===n||n.prepareAdoptedCssText(v,w),void 0===this.constructor._$AJ&&window.ShadyCSS.prepareTemplateStyles(document.createElement("template"),w);}return null!==(t=this.shadowRoot)&&void 0!==t?t:this.attachShadow(this.constructor.shadowRootOptions);};var w=t.connectedCallback;t.connectedCallback=function(){w.call(this),this.hasUpdated&&window.ShadyCSS.styleElement(this);};var v=t._$AE;t._$AE=function(i){this.hasUpdated||window.ShadyCSS.styleElement(this),v.call(this,i);};}});var t,d=new Set(),w=new Map();null!==(n=globalThis.litHtmlPolyfillSupport)&&void 0!==n||(globalThis.litHtmlPolyfillSupport=function(i,n){if(void 0!==window.ShadyCSS&&(!window.ShadyCSS.nativeShadow||window.ShadyCSS.ApplyShim)){var o=function(i){return void 0!==i&&!d.has(i);},t=function(i){var n=w.get(i);return void 0===n&&w.set(i,n=[]),n;},v=new Map(),l=i.createElement;i.createElement=function(n,d){var w=l.call(i,n,d),v=null==d?void 0:d.scope;if(void 0!==v&&(window.ShadyCSS.nativeShadow||window.ShadyCSS.prepareTemplateDom(w,v),o(v))){var r=t(v),u=w.content.querySelectorAll("style");r.push.apply(r,Array.from(u).map(function(i){var n;return null===(n=i.parentNode)||void 0===n||n.removeChild(i),i.textContent;}));}return w;};var r=document.createDocumentFragment(),u=document.createComment(""),s=n.prototype,e=s._$AI;s._$AI=function(i,n){var v,l;void 0===n&&(n=this);var s=this._$AA.parentNode,a=null===(v=this.options)||void 0===v?void 0:v.scope;if(s instanceof ShadowRoot&&o(a)){var h=this._$AA,f=this._$AB;r.appendChild(u),this._$AA=u,this._$AB=null,e.call(this,i,n);var c=(null==i?void 0:i._$litType$)?this._$AH._$AD.el:document.createElement("template");if(function(i,n){var o,v=t(i),l=0!==v.length;l&&((o=document.createElement("style")).textContent=v.join("\n"),n.content.appendChild(o)),d.add(i),w.delete(i),window.ShadyCSS.prepareTemplateStyles(n,i),l&&window.ShadyCSS.nativeShadow&&null!==(o=n.content.querySelector("style"))&&n.content.appendChild(o);}(a,c),r.removeChild(u),null===(l=window.ShadyCSS)||void 0===l?void 0:l.nativeShadow){var y=c.content.querySelector("style");null!==y&&r.appendChild(y.cloneNode(!0));}s.insertBefore(r,f),this._$AA=h,this._$AB=f;}else e.call(this,i,n);},s._$AC=function(n){var o,t=null===(o=this.options)||void 0===o?void 0:o.scope,d=v.get(t);void 0===d&&v.set(t,d=new Map());var w=d.get(n.strings);return void 0===w&&d.set(n.strings,w=new i(n,this.options)),w;};}}),null!==(t=globalThis.litElementPolyfillSupport)&&void 0!==t||(globalThis.litElementPolyfillSupport=function(i){var n=i.LitElement;if(void 0!==window.ShadyCSS&&(!window.ShadyCSS.nativeShadow||window.ShadyCSS.ApplyShim)){n._$AJ=!0;var o=n.prototype,t=o.createRenderRoot;o.createRenderRoot=function(){return this.renderOptions.scope=this.localName,t.call(this);};}});});
|
||
;// ../../node_modules/tabbable/dist/index.esm.js
|
||
/*!
|
||
* tabbable 6.3.0
|
||
* @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
|
||
*/// NOTE: separate `:not()` selectors has broader browser support than the newer
|
||
// `:not([inert], [inert] *)` (Feb 2023)
|
||
// CAREFUL: JSDom does not support `:not([inert] *)` as a selector; using it causes
|
||
// the entire query to fail, resulting in no nodes found, which will break a lot
|
||
// of things... so we have to rely on JS to identify nodes inside an inert container
|
||
var candidateSelectors=['input:not([inert])','select:not([inert])','textarea:not([inert])','a[href]:not([inert])','button:not([inert])','[tabindex]:not(slot):not([inert])','audio[controls]:not([inert])','video[controls]:not([inert])','[contenteditable]:not([contenteditable="false"]):not([inert])','details>summary:first-of-type:not([inert])','details:not([inert])'];var candidateSelector=/* #__PURE__ */candidateSelectors.join(',');var NoElement=typeof Element==='undefined';var matches=NoElement?function(){}:Element.prototype.matches||Element.prototype.msMatchesSelector||Element.prototype.webkitMatchesSelector;var getRootNode=!NoElement&&Element.prototype.getRootNode?function(element){var _element$getRootNode;return element===null||element===void 0?void 0:(_element$getRootNode=element.getRootNode)===null||_element$getRootNode===void 0?void 0:_element$getRootNode.call(element);}:function(element){return element===null||element===void 0?void 0:element.ownerDocument;};/**
|
||
* Determines if a node is inert or in an inert ancestor.
|
||
* @param {Element} [node]
|
||
* @param {boolean} [lookUp] If true and `node` is not inert, looks up at ancestors to
|
||
* see if any of them are inert. If false, only `node` itself is considered.
|
||
* @returns {boolean} True if inert itself or by way of being in an inert ancestor.
|
||
* False if `node` is falsy.
|
||
*/var _isInert=function isInert(node,lookUp){var _node$getAttribute;if(lookUp===void 0){lookUp=true;}// CAREFUL: JSDom does not support inert at all, so we can't use the `HTMLElement.inert`
|
||
// JS API property; we have to check the attribute, which can either be empty or 'true';
|
||
// if it's `null` (not specified) or 'false', it's an active element
|
||
var inertAtt=node===null||node===void 0?void 0:(_node$getAttribute=node.getAttribute)===null||_node$getAttribute===void 0?void 0:_node$getAttribute.call(node,'inert');var inert=inertAtt===''||inertAtt==='true';// NOTE: this could also be handled with `node.matches('[inert], :is([inert] *)')`
|
||
// if it weren't for `matches()` not being a function on shadow roots; the following
|
||
// code works for any kind of node
|
||
// CAREFUL: JSDom does not appear to support certain selectors like `:not([inert] *)`
|
||
// so it likely would not support `:is([inert] *)` either...
|
||
var result=inert||lookUp&&node&&_isInert(node.parentNode);// recursive
|
||
return result;};/**
|
||
* Determines if a node's content is editable.
|
||
* @param {Element} [node]
|
||
* @returns True if it's content-editable; false if it's not or `node` is falsy.
|
||
*/var isContentEditable=function isContentEditable(node){var _node$getAttribute2;// CAREFUL: JSDom does not support the `HTMLElement.isContentEditable` API so we have
|
||
// to use the attribute directly to check for this, which can either be empty or 'true';
|
||
// if it's `null` (not specified) or 'false', it's a non-editable element
|
||
var attValue=node===null||node===void 0?void 0:(_node$getAttribute2=node.getAttribute)===null||_node$getAttribute2===void 0?void 0:_node$getAttribute2.call(node,'contenteditable');return attValue===''||attValue==='true';};/**
|
||
* @param {Element} el container to check in
|
||
* @param {boolean} includeContainer add container to check
|
||
* @param {(node: Element) => boolean} filter filter candidates
|
||
* @returns {Element[]}
|
||
*/var getCandidates=function getCandidates(el,includeContainer,filter){// even if `includeContainer=false`, we still have to check it for inertness because
|
||
// if it's inert, all its children are inert
|
||
if(_isInert(el)){return[];}var candidates=Array.prototype.slice.apply(el.querySelectorAll(candidateSelector));if(includeContainer&&matches.call(el,candidateSelector)){candidates.unshift(el);}candidates=candidates.filter(filter);return candidates;};/**
|
||
* @callback GetShadowRoot
|
||
* @param {Element} element to check for shadow root
|
||
* @returns {ShadowRoot|boolean} ShadowRoot if available or boolean indicating if a shadowRoot is attached but not available.
|
||
*//**
|
||
* @callback ShadowRootFilter
|
||
* @param {Element} shadowHostNode the element which contains shadow content
|
||
* @returns {boolean} true if a shadow root could potentially contain valid candidates.
|
||
*//**
|
||
* @typedef {Object} CandidateScope
|
||
* @property {Element} scopeParent contains inner candidates
|
||
* @property {Element[]} candidates list of candidates found in the scope parent
|
||
*//**
|
||
* @typedef {Object} IterativeOptions
|
||
* @property {GetShadowRoot|boolean} getShadowRoot true if shadow support is enabled; falsy if not;
|
||
* if a function, implies shadow support is enabled and either returns the shadow root of an element
|
||
* or a boolean stating if it has an undisclosed shadow root
|
||
* @property {(node: Element) => boolean} filter filter candidates
|
||
* @property {boolean} flatten if true then result will flatten any CandidateScope into the returned list
|
||
* @property {ShadowRootFilter} shadowRootFilter filter shadow roots;
|
||
*//**
|
||
* @param {Element[]} elements list of element containers to match candidates from
|
||
* @param {boolean} includeContainer add container list to check
|
||
* @param {IterativeOptions} options
|
||
* @returns {Array.<Element|CandidateScope>}
|
||
*/var _getCandidatesIteratively=function getCandidatesIteratively(elements,includeContainer,options){var candidates=[];var elementsToCheck=Array.from(elements);while(elementsToCheck.length){var element=elementsToCheck.shift();if(_isInert(element,false)){// no need to look up since we're drilling down
|
||
// anything inside this container will also be inert
|
||
continue;}if(element.tagName==='SLOT'){// add shadow dom slot scope (slot itself cannot be focusable)
|
||
var assigned=element.assignedElements();var content=assigned.length?assigned:element.children;var nestedCandidates=_getCandidatesIteratively(content,true,options);if(options.flatten){candidates.push.apply(candidates,nestedCandidates);}else{candidates.push({scopeParent:element,candidates:nestedCandidates});}}else{// check candidate element
|
||
var validCandidate=matches.call(element,candidateSelector);if(validCandidate&&options.filter(element)&&(includeContainer||!elements.includes(element))){candidates.push(element);}// iterate over shadow content if possible
|
||
var shadowRoot=element.shadowRoot||// check for an undisclosed shadow
|
||
typeof options.getShadowRoot==='function'&&options.getShadowRoot(element);// no inert look up because we're already drilling down and checking for inertness
|
||
// on the way down, so all containers to this root node should have already been
|
||
// vetted as non-inert
|
||
var validShadowRoot=!_isInert(shadowRoot,false)&&(!options.shadowRootFilter||options.shadowRootFilter(element));if(shadowRoot&&validShadowRoot){// add shadow dom scope IIF a shadow root node was given; otherwise, an undisclosed
|
||
// shadow exists, so look at light dom children as fallback BUT create a scope for any
|
||
// child candidates found because they're likely slotted elements (elements that are
|
||
// children of the web component element (which has the shadow), in the light dom, but
|
||
// slotted somewhere _inside_ the undisclosed shadow) -- the scope is created below,
|
||
// _after_ we return from this recursive call
|
||
var _nestedCandidates=_getCandidatesIteratively(shadowRoot===true?element.children:shadowRoot.children,true,options);if(options.flatten){candidates.push.apply(candidates,_nestedCandidates);}else{candidates.push({scopeParent:element,candidates:_nestedCandidates});}}else{// there's not shadow so just dig into the element's (light dom) children
|
||
// __without__ giving the element special scope treatment
|
||
elementsToCheck.unshift.apply(elementsToCheck,element.children);}}}return candidates;};/**
|
||
* @private
|
||
* Determines if the node has an explicitly specified `tabindex` attribute.
|
||
* @param {HTMLElement} node
|
||
* @returns {boolean} True if so; false if not.
|
||
*/var hasTabIndex=function hasTabIndex(node){return!isNaN(parseInt(node.getAttribute('tabindex'),10));};/**
|
||
* Determine the tab index of a given node.
|
||
* @param {HTMLElement} node
|
||
* @returns {number} Tab order (negative, 0, or positive number).
|
||
* @throws {Error} If `node` is falsy.
|
||
*/var getTabIndex=function getTabIndex(node){if(!node){throw new Error('No node provided');}if(node.tabIndex<0){// in Chrome, <details/>, <audio controls/> and <video controls/> elements get a default
|
||
// `tabIndex` of -1 when the 'tabindex' attribute isn't specified in the DOM,
|
||
// yet they are still part of the regular tab order; in FF, they get a default
|
||
// `tabIndex` of 0; since Chrome still puts those elements in the regular tab
|
||
// order, consider their tab index to be 0.
|
||
// Also browsers do not return `tabIndex` correctly for contentEditable nodes;
|
||
// so if they don't have a tabindex attribute specifically set, assume it's 0.
|
||
if((/^(AUDIO|VIDEO|DETAILS)$/.test(node.tagName)||isContentEditable(node))&&!hasTabIndex(node)){return 0;}}return node.tabIndex;};/**
|
||
* Determine the tab index of a given node __for sort order purposes__.
|
||
* @param {HTMLElement} node
|
||
* @param {boolean} [isScope] True for a custom element with shadow root or slot that, by default,
|
||
* has tabIndex -1, but needs to be sorted by document order in order for its content to be
|
||
* inserted into the correct sort position.
|
||
* @returns {number} Tab order (negative, 0, or positive number).
|
||
*/var getSortOrderTabIndex=function getSortOrderTabIndex(node,isScope){var tabIndex=getTabIndex(node);if(tabIndex<0&&isScope&&!hasTabIndex(node)){return 0;}return tabIndex;};var sortOrderedTabbables=function sortOrderedTabbables(a,b){return a.tabIndex===b.tabIndex?a.documentOrder-b.documentOrder:a.tabIndex-b.tabIndex;};var isInput=function isInput(node){return node.tagName==='INPUT';};var isHiddenInput=function isHiddenInput(node){return isInput(node)&&node.type==='hidden';};var isDetailsWithSummary=function isDetailsWithSummary(node){var r=node.tagName==='DETAILS'&&Array.prototype.slice.apply(node.children).some(function(child){return child.tagName==='SUMMARY';});return r;};var getCheckedRadio=function getCheckedRadio(nodes,form){for(var i=0;i<nodes.length;i++){if(nodes[i].checked&&nodes[i].form===form){return nodes[i];}}};var isTabbableRadio=function isTabbableRadio(node){if(!node.name){return true;}var radioScope=node.form||getRootNode(node);var queryRadios=function queryRadios(name){return radioScope.querySelectorAll('input[type="radio"][name="'+name+'"]');};var radioSet;if(typeof window!=='undefined'&&typeof window.CSS!=='undefined'&&typeof window.CSS.escape==='function'){radioSet=queryRadios(window.CSS.escape(node.name));}else{try{radioSet=queryRadios(node.name);}catch(err){// eslint-disable-next-line no-console
|
||
console.error('Looks like you have a radio button with a name attribute containing invalid CSS selector characters and need the CSS.escape polyfill: %s',err.message);return false;}}var checked=getCheckedRadio(radioSet,node.form);return!checked||checked===node;};var isRadio=function isRadio(node){return isInput(node)&&node.type==='radio';};var isNonTabbableRadio=function isNonTabbableRadio(node){return isRadio(node)&&!isTabbableRadio(node);};// determines if a node is ultimately attached to the window's document
|
||
var isNodeAttached=function isNodeAttached(node){var _nodeRoot;// The root node is the shadow root if the node is in a shadow DOM; some document otherwise
|
||
// (but NOT _the_ document; see second 'If' comment below for more).
|
||
// If rootNode is shadow root, it'll have a host, which is the element to which the shadow
|
||
// is attached, and the one we need to check if it's in the document or not (because the
|
||
// shadow, and all nodes it contains, is never considered in the document since shadows
|
||
// behave like self-contained DOMs; but if the shadow's HOST, which is part of the document,
|
||
// is hidden, or is not in the document itself but is detached, it will affect the shadow's
|
||
// visibility, including all the nodes it contains). The host could be any normal node,
|
||
// or a custom element (i.e. web component). Either way, that's the one that is considered
|
||
// part of the document, not the shadow root, nor any of its children (i.e. the node being
|
||
// tested).
|
||
// To further complicate things, we have to look all the way up until we find a shadow HOST
|
||
// that is attached (or find none) because the node might be in nested shadows...
|
||
// If rootNode is not a shadow root, it won't have a host, and so rootNode should be the
|
||
// document (per the docs) and while it's a Document-type object, that document does not
|
||
// appear to be the same as the node's `ownerDocument` for some reason, so it's safer
|
||
// to ignore the rootNode at this point, and use `node.ownerDocument`. Otherwise,
|
||
// using `rootNode.contains(node)` will _always_ be true we'll get false-positives when
|
||
// node is actually detached.
|
||
// NOTE: If `nodeRootHost` or `node` happens to be the `document` itself (which is possible
|
||
// if a tabbable/focusable node was quickly added to the DOM, focused, and then removed
|
||
// from the DOM as in https://github.com/focus-trap/focus-trap-react/issues/905), then
|
||
// `ownerDocument` will be `null`, hence the optional chaining on it.
|
||
var nodeRoot=node&&getRootNode(node);var nodeRootHost=(_nodeRoot=nodeRoot)===null||_nodeRoot===void 0?void 0:_nodeRoot.host;// in some cases, a detached node will return itself as the root instead of a document or
|
||
// shadow root object, in which case, we shouldn't try to look further up the host chain
|
||
var attached=false;if(nodeRoot&&nodeRoot!==node){var _nodeRootHost,_nodeRootHost$ownerDo,_node$ownerDocument;attached=!!((_nodeRootHost=nodeRootHost)!==null&&_nodeRootHost!==void 0&&(_nodeRootHost$ownerDo=_nodeRootHost.ownerDocument)!==null&&_nodeRootHost$ownerDo!==void 0&&_nodeRootHost$ownerDo.contains(nodeRootHost)||node!==null&&node!==void 0&&(_node$ownerDocument=node.ownerDocument)!==null&&_node$ownerDocument!==void 0&&_node$ownerDocument.contains(node));while(!attached&&nodeRootHost){var _nodeRoot2,_nodeRootHost2,_nodeRootHost2$ownerD;// since it's not attached and we have a root host, the node MUST be in a nested shadow DOM,
|
||
// which means we need to get the host's host and check if that parent host is contained
|
||
// in (i.e. attached to) the document
|
||
nodeRoot=getRootNode(nodeRootHost);nodeRootHost=(_nodeRoot2=nodeRoot)===null||_nodeRoot2===void 0?void 0:_nodeRoot2.host;attached=!!((_nodeRootHost2=nodeRootHost)!==null&&_nodeRootHost2!==void 0&&(_nodeRootHost2$ownerD=_nodeRootHost2.ownerDocument)!==null&&_nodeRootHost2$ownerD!==void 0&&_nodeRootHost2$ownerD.contains(nodeRootHost));}}return attached;};var isZeroArea=function isZeroArea(node){var _node$getBoundingClie=node.getBoundingClientRect(),width=_node$getBoundingClie.width,height=_node$getBoundingClie.height;return width===0&&height===0;};var isHidden=function isHidden(node,_ref){var displayCheck=_ref.displayCheck,getShadowRoot=_ref.getShadowRoot;if(displayCheck==='full-native'){if('checkVisibility'in node){// Chrome >= 105, Edge >= 105, Firefox >= 106, Safari >= 17.4
|
||
// @see https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility#browser_compatibility
|
||
var visible=node.checkVisibility({// Checking opacity might be desirable for some use cases, but natively,
|
||
// opacity zero elements _are_ focusable and tabbable.
|
||
checkOpacity:false,opacityProperty:false,contentVisibilityAuto:true,visibilityProperty:true,// This is an alias for `visibilityProperty`. Contemporary browsers
|
||
// support both. However, this alias has wider browser support (Chrome
|
||
// >= 105 and Firefox >= 106, vs. Chrome >= 121 and Firefox >= 122), so
|
||
// we include it anyway.
|
||
checkVisibilityCSS:true});return!visible;}// Fall through to manual visibility checks
|
||
}// NOTE: visibility will be `undefined` if node is detached from the document
|
||
// (see notes about this further down), which means we will consider it visible
|
||
// (this is legacy behavior from a very long way back)
|
||
// NOTE: we check this regardless of `displayCheck="none"` because this is a
|
||
// _visibility_ check, not a _display_ check
|
||
if(getComputedStyle(node).visibility==='hidden'){return true;}var isDirectSummary=matches.call(node,'details>summary:first-of-type');var nodeUnderDetails=isDirectSummary?node.parentElement:node;if(matches.call(nodeUnderDetails,'details:not([open]) *')){return true;}if(!displayCheck||displayCheck==='full'||// full-native can run this branch when it falls through in case
|
||
// Element#checkVisibility is unsupported
|
||
displayCheck==='full-native'||displayCheck==='legacy-full'){if(typeof getShadowRoot==='function'){// figure out if we should consider the node to be in an undisclosed shadow and use the
|
||
// 'non-zero-area' fallback
|
||
var originalNode=node;while(node){var parentElement=node.parentElement;var rootNode=getRootNode(node);if(parentElement&&!parentElement.shadowRoot&&getShadowRoot(parentElement)===true// check if there's an undisclosed shadow
|
||
){// node has an undisclosed shadow which means we can only treat it as a black box, so we
|
||
// fall back to a non-zero-area test
|
||
return isZeroArea(node);}else if(node.assignedSlot){// iterate up slot
|
||
node=node.assignedSlot;}else if(!parentElement&&rootNode!==node.ownerDocument){// cross shadow boundary
|
||
node=rootNode.host;}else{// iterate up normal dom
|
||
node=parentElement;}}node=originalNode;}// else, `getShadowRoot` might be true, but all that does is enable shadow DOM support
|
||
// (i.e. it does not also presume that all nodes might have undisclosed shadows); or
|
||
// it might be a falsy value, which means shadow DOM support is disabled
|
||
// Since we didn't find it sitting in an undisclosed shadow (or shadows are disabled)
|
||
// now we can just test to see if it would normally be visible or not, provided it's
|
||
// attached to the main document.
|
||
// NOTE: We must consider case where node is inside a shadow DOM and given directly to
|
||
// `isTabbable()` or `isFocusable()` -- regardless of `getShadowRoot` option setting.
|
||
if(isNodeAttached(node)){// this works wherever the node is: if there's at least one client rect, it's
|
||
// somehow displayed; it also covers the CSS 'display: contents' case where the
|
||
// node itself is hidden in place of its contents; and there's no need to search
|
||
// up the hierarchy either
|
||
return!node.getClientRects().length;}// Else, the node isn't attached to the document, which means the `getClientRects()`
|
||
// API will __always__ return zero rects (this can happen, for example, if React
|
||
// is used to render nodes onto a detached tree, as confirmed in this thread:
|
||
// https://github.com/facebook/react/issues/9117#issuecomment-284228870)
|
||
//
|
||
// It also means that even window.getComputedStyle(node).display will return `undefined`
|
||
// because styles are only computed for nodes that are in the document.
|
||
//
|
||
// NOTE: THIS HAS BEEN THE CASE FOR YEARS. It is not new, nor is it caused by tabbable
|
||
// somehow. Though it was never stated officially, anyone who has ever used tabbable
|
||
// APIs on nodes in detached containers has actually implicitly used tabbable in what
|
||
// was later (as of v5.2.0 on Apr 9, 2021) called `displayCheck="none"` mode -- essentially
|
||
// considering __everything__ to be visible because of the innability to determine styles.
|
||
//
|
||
// v6.0.0: As of this major release, the default 'full' option __no longer treats detached
|
||
// nodes as visible with the 'none' fallback.__
|
||
if(displayCheck!=='legacy-full'){return true;// hidden
|
||
}// else, fallback to 'none' mode and consider the node visible
|
||
}else if(displayCheck==='non-zero-area'){// NOTE: Even though this tests that the node's client rect is non-zero to determine
|
||
// whether it's displayed, and that a detached node will __always__ have a zero-area
|
||
// client rect, we don't special-case for whether the node is attached or not. In
|
||
// this mode, we do want to consider nodes that have a zero area to be hidden at all
|
||
// times, and that includes attached or not.
|
||
return isZeroArea(node);}// visible, as far as we can tell, or per current `displayCheck=none` mode, we assume
|
||
// it's visible
|
||
return false;};// form fields (nested) inside a disabled fieldset are not focusable/tabbable
|
||
// unless they are in the _first_ <legend> element of the top-most disabled
|
||
// fieldset
|
||
var isDisabledFromFieldset=function isDisabledFromFieldset(node){if(/^(INPUT|BUTTON|SELECT|TEXTAREA)$/.test(node.tagName)){var parentNode=node.parentElement;// check if `node` is contained in a disabled <fieldset>
|
||
while(parentNode){if(parentNode.tagName==='FIELDSET'&&parentNode.disabled){// look for the first <legend> among the children of the disabled <fieldset>
|
||
for(var i=0;i<parentNode.children.length;i++){var child=parentNode.children.item(i);// when the first <legend> (in document order) is found
|
||
if(child.tagName==='LEGEND'){// if its parent <fieldset> is not nested in another disabled <fieldset>,
|
||
// return whether `node` is a descendant of its first <legend>
|
||
return matches.call(parentNode,'fieldset[disabled] *')?true:!child.contains(node);}}// the disabled <fieldset> containing `node` has no <legend>
|
||
return true;}parentNode=parentNode.parentElement;}}// else, node's tabbable/focusable state should not be affected by a fieldset's
|
||
// enabled/disabled state
|
||
return false;};var isNodeMatchingSelectorFocusable=function isNodeMatchingSelectorFocusable(options,node){if(node.disabled||// we must do an inert look up to filter out any elements inside an inert ancestor
|
||
// because we're limited in the type of selectors we can use in JSDom (see related
|
||
// note related to `candidateSelectors`)
|
||
_isInert(node)||isHiddenInput(node)||isHidden(node,options)||// For a details element with a summary, the summary element gets the focus
|
||
isDetailsWithSummary(node)||isDisabledFromFieldset(node)){return false;}return true;};var isNodeMatchingSelectorTabbable=function isNodeMatchingSelectorTabbable(options,node){if(isNonTabbableRadio(node)||getTabIndex(node)<0||!isNodeMatchingSelectorFocusable(options,node)){return false;}return true;};var isShadowRootTabbable=function isShadowRootTabbable(shadowHostNode){var tabIndex=parseInt(shadowHostNode.getAttribute('tabindex'),10);if(isNaN(tabIndex)||tabIndex>=0){return true;}// If a custom element has an explicit negative tabindex,
|
||
// browsers will not allow tab targeting said element's children.
|
||
return false;};/**
|
||
* @param {Array.<Element|CandidateScope>} candidates
|
||
* @returns Element[]
|
||
*/var _sortByOrder=function sortByOrder(candidates){var regularTabbables=[];var orderedTabbables=[];candidates.forEach(function(item,i){var isScope=!!item.scopeParent;var element=isScope?item.scopeParent:item;var candidateTabindex=getSortOrderTabIndex(element,isScope);var elements=isScope?_sortByOrder(item.candidates):element;if(candidateTabindex===0){isScope?regularTabbables.push.apply(regularTabbables,elements):regularTabbables.push(element);}else{orderedTabbables.push({documentOrder:i,tabIndex:candidateTabindex,item:item,isScope:isScope,content:elements});}});return orderedTabbables.sort(sortOrderedTabbables).reduce(function(acc,sortable){sortable.isScope?acc.push.apply(acc,sortable.content):acc.push(sortable.content);return acc;},[]).concat(regularTabbables);};var tabbable=function tabbable(container,options){options=options||{};var candidates;if(options.getShadowRoot){candidates=_getCandidatesIteratively([container],options.includeContainer,{filter:isNodeMatchingSelectorTabbable.bind(null,options),flatten:false,getShadowRoot:options.getShadowRoot,shadowRootFilter:isShadowRootTabbable});}else{candidates=getCandidates(container,options.includeContainer,isNodeMatchingSelectorTabbable.bind(null,options));}return _sortByOrder(candidates);};var focusable=function focusable(container,options){options=options||{};var candidates;if(options.getShadowRoot){candidates=_getCandidatesIteratively([container],options.includeContainer,{filter:isNodeMatchingSelectorFocusable.bind(null,options),flatten:true,getShadowRoot:options.getShadowRoot});}else{candidates=getCandidates(container,options.includeContainer,isNodeMatchingSelectorFocusable.bind(null,options));}return candidates;};var isTabbable=function isTabbable(node,options){options=options||{};if(!node){throw new Error('No node provided');}if(matches.call(node,candidateSelector)===false){return false;}return isNodeMatchingSelectorTabbable(options,node);};var focusableCandidateSelector=/* #__PURE__ */(/* unused pure expression or super */ null && (candidateSelectors.concat('iframe').join(',')));var isFocusable=function isFocusable(node,options){options=options||{};if(!node){throw new Error('No node provided');}if(matches.call(node,focusableCandidateSelector)===false){return false;}return isNodeMatchingSelectorFocusable(options,node);};
|
||
;// ../../libs/common/src/vault/enums/cipher-reprompt-type.ts
|
||
const CipherRepromptType = {
|
||
None: 0,
|
||
Password: 1,
|
||
};
|
||
/**
|
||
* Normalizes a CipherRepromptType value to ensure compatibility with the SDK.
|
||
* @param value - The cipher reprompt type from user data
|
||
* @returns Valid CipherRepromptType, defaults to CipherRepromptType.None if unrecognized
|
||
*/
|
||
function normalizeCipherRepromptTypeForSdk(value) {
|
||
switch (value) {
|
||
case CipherRepromptType.None:
|
||
case CipherRepromptType.Password:
|
||
return value;
|
||
default:
|
||
return CipherRepromptType.None;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/common/src/vault/enums/cipher-type.ts
|
||
const _CipherType = Object.freeze({
|
||
Login: 1,
|
||
SecureNote: 2,
|
||
Card: 3,
|
||
Identity: 4,
|
||
SshKey: 5,
|
||
});
|
||
// FIXME: Update typing of `CipherType` to be `Record<keyof _CipherType, CipherType>` which is ADR-0025 compliant when the TypeScript version is at least 5.8.
|
||
const CipherType = _CipherType;
|
||
/**
|
||
* Reverse mapping of Cipher Types to their associated names.
|
||
* Prefer using {@link toCipherTypeName} rather than accessing this object directly.
|
||
*
|
||
* When represented as an enum in TypeScript, this mapping was provided
|
||
* by default. Now using a constant object it needs to be defined manually.
|
||
*/
|
||
const cipherTypeNames = Object.freeze(Object.fromEntries(Object.entries(CipherType).map(([key, value]) => [value, key])));
|
||
/**
|
||
* Returns the associated name for the cipher type, will throw when the name is not found.
|
||
*/
|
||
function toCipherTypeName(type) {
|
||
const name = cipherTypeNames[type];
|
||
return name;
|
||
}
|
||
/**
|
||
* @returns `true` if the value is a valid `CipherType`, `false` otherwise.
|
||
*/
|
||
const isCipherType = (value) => {
|
||
return Object.values(CipherType).includes(value);
|
||
};
|
||
/**
|
||
* Converts a value to a `CipherType` if it is valid, otherwise returns `null`.
|
||
*/
|
||
const toCipherType = (value) => {
|
||
if (isCipherType(value)) {
|
||
return value;
|
||
}
|
||
if (typeof value === "string") {
|
||
const valueAsInt = parseInt(value, 10);
|
||
if (isCipherType(valueAsInt)) {
|
||
return valueAsInt;
|
||
}
|
||
}
|
||
return undefined;
|
||
};
|
||
|
||
;// ../../libs/common/src/vault/enums/field-type.enum.ts
|
||
const _FieldType = Object.freeze({
|
||
Text: 0,
|
||
Hidden: 1,
|
||
Boolean: 2,
|
||
Linked: 3,
|
||
});
|
||
const FieldType = _FieldType;
|
||
/**
|
||
* Normalizes a FieldType value to ensure compatibility with the SDK.
|
||
* @param value - The field type from user data
|
||
* @returns Valid FieldType, defaults to FieldType.Text if unrecognized
|
||
*/
|
||
function normalizeFieldTypeForSdk(value) {
|
||
switch (value) {
|
||
case FieldType.Text:
|
||
case FieldType.Hidden:
|
||
case FieldType.Boolean:
|
||
case FieldType.Linked:
|
||
return value;
|
||
default:
|
||
return FieldType.Text;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/common/src/vault/enums/linked-id-type.enum.ts
|
||
// LoginView
|
||
const LoginLinkedId = {
|
||
Username: 100,
|
||
Password: 101,
|
||
};
|
||
// CardView
|
||
const CardLinkedId = {
|
||
CardholderName: 300,
|
||
ExpMonth: 301,
|
||
ExpYear: 302,
|
||
Code: 303,
|
||
Brand: 304,
|
||
Number: 305,
|
||
};
|
||
// IdentityView
|
||
const IdentityLinkedId = {
|
||
Title: 400,
|
||
MiddleName: 401,
|
||
Address1: 402,
|
||
Address2: 403,
|
||
Address3: 404,
|
||
City: 405,
|
||
State: 406,
|
||
PostalCode: 407,
|
||
Country: 408,
|
||
Company: 409,
|
||
Email: 410,
|
||
Phone: 411,
|
||
Ssn: 412,
|
||
Username: 413,
|
||
PassportNumber: 414,
|
||
LicenseNumber: 415,
|
||
FirstName: 416,
|
||
LastName: 417,
|
||
FullName: 418,
|
||
};
|
||
/**
|
||
* Normalizes a LinkedIdType value to ensure compatibility with the SDK.
|
||
* @param value - The linked ID type from user data
|
||
* @returns Valid LinkedIdType or undefined if unrecognized
|
||
*/
|
||
function normalizeLinkedIdTypeForSdk(value) {
|
||
if (value == null) {
|
||
return undefined;
|
||
}
|
||
// Check all valid LinkedId numeric values (100-418)
|
||
const allValidValues = [
|
||
...Object.values(LoginLinkedId),
|
||
...Object.values(CardLinkedId),
|
||
...Object.values(IdentityLinkedId),
|
||
];
|
||
return allValidValues.includes(value) ? value : undefined;
|
||
}
|
||
|
||
;// ../../libs/common/src/vault/enums/secure-note-type.enum.ts
|
||
const SecureNoteType = {
|
||
Generic: 0,
|
||
};
|
||
/**
|
||
* Normalizes a SecureNoteType value to ensure compatibility with the SDK.
|
||
* @param value - The secure note type from user data
|
||
* @returns Valid SecureNoteType, defaults to SecureNoteType.Generic if unrecognized
|
||
*/
|
||
function normalizeSecureNoteTypeForSdk(value) {
|
||
return SecureNoteType.Generic;
|
||
}
|
||
|
||
;// ../../libs/common/src/vault/enums/extension-page-urls.enum.ts
|
||
/**
|
||
* Available pages within the extension by their URL.
|
||
* Useful when opening a specific page within the popup.
|
||
*/
|
||
const ExtensionPageUrls = {
|
||
Index: "popup/index.html#/",
|
||
AtRiskPasswords: "popup/index.html#/at-risk-passwords",
|
||
};
|
||
|
||
;// ../../libs/common/src/vault/enums/index.ts
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;// ./src/autofill/enums/autofill-field.enums.ts
|
||
const AutofillFieldQualifier = {
|
||
password: "password",
|
||
newPassword: "newPassword",
|
||
username: "username",
|
||
cardholderName: "cardholderName",
|
||
cardNumber: "cardNumber",
|
||
cardExpirationMonth: "cardExpirationMonth",
|
||
cardExpirationYear: "cardExpirationYear",
|
||
cardExpirationDate: "cardExpirationDate",
|
||
cardCvv: "cardCvv",
|
||
identityTitle: "identityTitle",
|
||
identityFirstName: "identityFirstName",
|
||
identityMiddleName: "identityMiddleName",
|
||
identityLastName: "identityLastName",
|
||
identityFullName: "identityFullName",
|
||
identityAddress1: "identityAddress1",
|
||
identityAddress2: "identityAddress2",
|
||
identityAddress3: "identityAddress3",
|
||
identityCity: "identityCity",
|
||
identityState: "identityState",
|
||
identityPostalCode: "identityPostalCode",
|
||
identityCountry: "identityCountry",
|
||
identityCompany: "identityCompany",
|
||
identityPhone: "identityPhone",
|
||
identityEmail: "identityEmail",
|
||
identityUsername: "identityUsername",
|
||
};
|
||
|
||
;// ./src/autofill/enums/autofill-overlay.enum.ts
|
||
const AutofillOverlayElement = {
|
||
Button: "autofill-inline-menu-button",
|
||
List: "autofill-inline-menu-list",
|
||
};
|
||
const AutofillOverlayPort = {
|
||
Button: "autofill-inline-menu-button-port",
|
||
ButtonMessageConnector: "autofill-inline-menu-button-message-connector",
|
||
List: "autofill-inline-menu-list-port",
|
||
ListMessageConnector: "autofill-inline-menu-list-message-connector",
|
||
};
|
||
const RedirectFocusDirection = {
|
||
Current: "current",
|
||
Previous: "previous",
|
||
Next: "next",
|
||
};
|
||
const InlineMenuFillTypes = {
|
||
AccountCreationUsername: 5,
|
||
PasswordGeneration: 6,
|
||
CurrentPasswordUpdate: 7,
|
||
};
|
||
const InlineMenuAccountCreationFieldType = {
|
||
Text: "text",
|
||
Email: "email",
|
||
Password: "password",
|
||
Totp: "totp",
|
||
};
|
||
const MAX_SUB_FRAME_DEPTH = 8;
|
||
|
||
;// ./src/autofill/services/autofill-constants.ts
|
||
class AutoFillConstants {
|
||
}
|
||
AutoFillConstants.EmailFieldNames = [
|
||
// English
|
||
"email",
|
||
"email address",
|
||
"e-mail",
|
||
"e-mail address",
|
||
// German
|
||
"email adresse",
|
||
"e-mail adresse",
|
||
];
|
||
AutoFillConstants.UsernameFieldNames = [
|
||
// English
|
||
"username",
|
||
"user name",
|
||
"userid",
|
||
"user id",
|
||
"customer id",
|
||
"login id",
|
||
"login",
|
||
// German
|
||
"benutzername",
|
||
"benutzer name",
|
||
"benutzerid",
|
||
"benutzer id",
|
||
...AutoFillConstants.EmailFieldNames,
|
||
];
|
||
AutoFillConstants.TotpFieldNames = [
|
||
"totp",
|
||
"totpcode",
|
||
"2facode",
|
||
"approvals_code",
|
||
"mfacode",
|
||
"otc-code",
|
||
"onetimecode",
|
||
"otp-code",
|
||
"otpcode",
|
||
"onetimepassword",
|
||
"security_code",
|
||
"second-factor",
|
||
"twofactor",
|
||
"twofa",
|
||
"twofactorcode",
|
||
"verificationcode",
|
||
"verification code",
|
||
];
|
||
AutoFillConstants.RecoveryCodeFieldNames = ["backup", "recovery"];
|
||
AutoFillConstants.AmbiguousTotpFieldNames = ["code", "pin", "otc", "otp", "2fa", "mfa"];
|
||
AutoFillConstants.SearchFieldNames = ["search", "query", "find", "go"];
|
||
AutoFillConstants.NewEmailFieldKeywords = [
|
||
"new-email",
|
||
"newemail",
|
||
"new email",
|
||
"neue e-mail",
|
||
];
|
||
AutoFillConstants.RegistrationKeywords = [
|
||
"register",
|
||
"signup",
|
||
"sign-up",
|
||
"join",
|
||
"create",
|
||
];
|
||
AutoFillConstants.NewsletterFormNames = ["newsletter"];
|
||
AutoFillConstants.FieldIgnoreList = ["captcha", "findanything", "forgot"];
|
||
AutoFillConstants.PasswordFieldExcludeList = [
|
||
"hint",
|
||
...AutoFillConstants.FieldIgnoreList,
|
||
...AutoFillConstants.TotpFieldNames,
|
||
];
|
||
AutoFillConstants.ExcludedAutofillLoginTypes = [
|
||
"hidden",
|
||
"file",
|
||
"button",
|
||
"image",
|
||
"reset",
|
||
"search",
|
||
];
|
||
AutoFillConstants.ExcludedAutofillTypes = [
|
||
"radio",
|
||
"checkbox",
|
||
...AutoFillConstants.ExcludedAutofillLoginTypes,
|
||
];
|
||
AutoFillConstants.ExcludedInlineMenuTypes = [
|
||
"textarea",
|
||
...AutoFillConstants.ExcludedAutofillTypes,
|
||
];
|
||
AutoFillConstants.ExcludedIdentityAutocompleteTypes = new Set([
|
||
"current-password",
|
||
"new-password",
|
||
]);
|
||
class CreditCardAutoFillConstants {
|
||
}
|
||
CreditCardAutoFillConstants.CardAttributes = [
|
||
"autoCompleteType",
|
||
"data-stripe",
|
||
"htmlName",
|
||
"htmlID",
|
||
"title",
|
||
"label-tag",
|
||
"placeholder",
|
||
"label-left",
|
||
"label-top",
|
||
"data-recurly",
|
||
];
|
||
CreditCardAutoFillConstants.CardAttributesExtended = [
|
||
...CreditCardAutoFillConstants.CardAttributes,
|
||
"label-right",
|
||
];
|
||
CreditCardAutoFillConstants.CardHolderFieldNames = [
|
||
"accountholdername",
|
||
"cc-name",
|
||
"card-name",
|
||
"cardholder-name",
|
||
"cardholder",
|
||
"name",
|
||
"nom",
|
||
];
|
||
CreditCardAutoFillConstants.CardHolderFieldNameValues = [
|
||
"accountholdername",
|
||
"cc-name",
|
||
"card-name",
|
||
"cardholder-name",
|
||
"cardholder",
|
||
"tbName",
|
||
];
|
||
CreditCardAutoFillConstants.CardNumberFieldNames = [
|
||
"cc-number",
|
||
"cc-num",
|
||
"card-number",
|
||
"card-num",
|
||
"number",
|
||
"cc",
|
||
"cc-no",
|
||
"card-no",
|
||
"credit-card",
|
||
"numero-carte",
|
||
"carte",
|
||
"carte-credit",
|
||
"num-carte",
|
||
"cb-num",
|
||
"card-pan",
|
||
];
|
||
CreditCardAutoFillConstants.CardNumberFieldNameValues = [
|
||
"cc-number",
|
||
"cc-num",
|
||
"card-number",
|
||
"card-num",
|
||
"cc-no",
|
||
"card-no",
|
||
"numero-carte",
|
||
"num-carte",
|
||
"cb-num",
|
||
];
|
||
CreditCardAutoFillConstants.CardExpiryFieldNames = [
|
||
"cc-exp",
|
||
"card-exp",
|
||
"cc-expiration",
|
||
"card-expiration",
|
||
"cc-ex",
|
||
"card-ex",
|
||
"card-expire",
|
||
"card-expiry",
|
||
"validite",
|
||
"expiration",
|
||
"expiry",
|
||
"mm-yy",
|
||
"mm-yyyy",
|
||
"yy-mm",
|
||
"yyyy-mm",
|
||
"expiration-date",
|
||
"payment-card-expiration",
|
||
"payment-cc-date",
|
||
];
|
||
CreditCardAutoFillConstants.CardExpiryFieldNameValues = [
|
||
"mm-yy",
|
||
"mm-yyyy",
|
||
"yy-mm",
|
||
"yyyy-mm",
|
||
"expiration-date",
|
||
"payment-card-expiration",
|
||
];
|
||
CreditCardAutoFillConstants.ExpiryMonthFieldNames = [
|
||
"exp-month",
|
||
"cc-exp-month",
|
||
"cc-month",
|
||
"card-month",
|
||
"cc-mo",
|
||
"card-mo",
|
||
"exp-mo",
|
||
"card-exp-mo",
|
||
"cc-exp-mo",
|
||
"card-expiration-month",
|
||
"expiration-month",
|
||
"cc-mm",
|
||
"cc-m",
|
||
"card-mm",
|
||
"card-m",
|
||
"card-exp-mm",
|
||
"cc-exp-mm",
|
||
"exp-mm",
|
||
"exp-m",
|
||
"expire-month",
|
||
"expire-mo",
|
||
"expiry-month",
|
||
"expiry-mo",
|
||
"card-expire-month",
|
||
"card-expire-mo",
|
||
"card-expiry-month",
|
||
"card-expiry-mo",
|
||
"mois-validite",
|
||
"mois-expiration",
|
||
"m-validite",
|
||
"m-expiration",
|
||
"expiry-date-field-month",
|
||
"expiration-date-month",
|
||
"expiration-date-mm",
|
||
"exp-mon",
|
||
"validity-mo",
|
||
"exp-date-mo",
|
||
"cb-date-mois",
|
||
"date-m",
|
||
];
|
||
CreditCardAutoFillConstants.ExpiryYearFieldNames = [
|
||
"exp-year",
|
||
"cc-exp-year",
|
||
"cc-year",
|
||
"card-year",
|
||
"cc-yr",
|
||
"card-yr",
|
||
"exp-yr",
|
||
"card-exp-yr",
|
||
"cc-exp-yr",
|
||
"card-expiration-year",
|
||
"expiration-year",
|
||
"cc-yy",
|
||
"cc-y",
|
||
"card-yy",
|
||
"card-y",
|
||
"card-exp-yy",
|
||
"cc-exp-yy",
|
||
"exp-yy",
|
||
"exp-y",
|
||
"cc-yyyy",
|
||
"card-yyyy",
|
||
"card-exp-yyyy",
|
||
"cc-exp-yyyy",
|
||
"expire-year",
|
||
"expire-yr",
|
||
"expiry-year",
|
||
"expiry-yr",
|
||
"card-expire-year",
|
||
"card-expire-yr",
|
||
"card-expiry-year",
|
||
"card-expiry-yr",
|
||
"an-validite",
|
||
"an-expiration",
|
||
"annee-validite",
|
||
"annee-expiration",
|
||
"expiry-date-field-year",
|
||
"expiration-date-year",
|
||
"cb-date-ann",
|
||
"expiration-date-yy",
|
||
"expiration-date-yyyy",
|
||
"validity-year",
|
||
"exp-date-year",
|
||
"date-y",
|
||
];
|
||
CreditCardAutoFillConstants.CVVFieldNames = [
|
||
"cvv",
|
||
"cvc",
|
||
"cvv2",
|
||
"cc-csc",
|
||
"cc-cvv",
|
||
"card-csc",
|
||
"card-cvv",
|
||
"cvd",
|
||
"cid",
|
||
"cvc2",
|
||
"cnv",
|
||
"cvn2",
|
||
"cc-code",
|
||
"card-code",
|
||
"code-securite",
|
||
"security-code",
|
||
"crypto",
|
||
"card-verif",
|
||
"verification-code",
|
||
"csc",
|
||
"ccv",
|
||
];
|
||
CreditCardAutoFillConstants.CardBrandFieldNames = [
|
||
"cc-type",
|
||
"card-type",
|
||
"card-brand",
|
||
"cc-brand",
|
||
"cb-type",
|
||
];
|
||
// Note, these are expressions of user-guidance for the expected expiry date format to be used
|
||
CreditCardAutoFillConstants.CardExpiryDateFormats = [
|
||
// English
|
||
{
|
||
Month: "mm",
|
||
MonthShort: "m",
|
||
Year: "yyyy",
|
||
YearShort: "yy",
|
||
},
|
||
// Danish
|
||
{
|
||
Month: "mm",
|
||
MonthShort: "m",
|
||
Year: "åååå",
|
||
YearShort: "åå",
|
||
},
|
||
// German/Dutch
|
||
{
|
||
Month: "mm",
|
||
MonthShort: "m",
|
||
Year: "jjjj",
|
||
YearShort: "jj",
|
||
},
|
||
// French/Spanish/Italian
|
||
{
|
||
Month: "mm",
|
||
MonthShort: "m",
|
||
Year: "aa",
|
||
YearShort: "aa",
|
||
},
|
||
// Russian
|
||
{
|
||
Month: "мм",
|
||
MonthShort: "м",
|
||
Year: "гггг",
|
||
YearShort: "гг",
|
||
},
|
||
// Portuguese
|
||
{
|
||
Month: "mm",
|
||
MonthShort: "m",
|
||
Year: "rrrr",
|
||
YearShort: "rr",
|
||
},
|
||
];
|
||
// Each index represents a language. These three arrays should all be the same length.
|
||
// 0: English, 1: Danish, 2: German/Dutch, 3: French/Spanish/Italian, 4: Russian, 5: Portuguese
|
||
CreditCardAutoFillConstants.MonthAbbr = ["mm", "mm", "mm", "mm", "мм", "mm"];
|
||
CreditCardAutoFillConstants.YearAbbrShort = ["yy", "åå", "jj", "aa", "гг", "rr"];
|
||
CreditCardAutoFillConstants.YearAbbrLong = ["yyyy", "åååå", "jjjj", "aa", "гггг", "rrrr"];
|
||
class IdentityAutoFillConstants {
|
||
}
|
||
IdentityAutoFillConstants.IdentityAttributes = [
|
||
"autoCompleteType",
|
||
"data-stripe",
|
||
"htmlName",
|
||
"htmlID",
|
||
"label-tag",
|
||
"placeholder",
|
||
"label-left",
|
||
"label-top",
|
||
"data-recurly",
|
||
"accountCreationFieldType",
|
||
];
|
||
IdentityAutoFillConstants.FullNameFieldNames = ["name", "full-name", "your-name"];
|
||
IdentityAutoFillConstants.FullNameFieldNameValues = ["full-name", "your-name"];
|
||
IdentityAutoFillConstants.TitleFieldNames = [
|
||
"honorific-prefix",
|
||
"prefix",
|
||
"title",
|
||
// German
|
||
"anrede",
|
||
];
|
||
IdentityAutoFillConstants.FirstnameFieldNames = [
|
||
// English
|
||
"f-name",
|
||
"first-name",
|
||
"given-name",
|
||
"first-n",
|
||
// German
|
||
"vorname",
|
||
];
|
||
IdentityAutoFillConstants.MiddlenameFieldNames = [
|
||
"m-name",
|
||
"middle-name",
|
||
"additional-name",
|
||
"middle-initial",
|
||
"middle-n",
|
||
"middle-i",
|
||
];
|
||
IdentityAutoFillConstants.LastnameFieldNames = [
|
||
// English
|
||
"l-name",
|
||
"last-name",
|
||
"s-name",
|
||
"surname",
|
||
"family-name",
|
||
"family-n",
|
||
"last-n",
|
||
// German
|
||
"nachname",
|
||
"familienname",
|
||
];
|
||
IdentityAutoFillConstants.EmailFieldNames = ["e-mail", "email-address"];
|
||
IdentityAutoFillConstants.AddressFieldNames = [
|
||
"address",
|
||
"street-address",
|
||
"addr",
|
||
"street",
|
||
"mailing-addr",
|
||
"billing-addr",
|
||
"mail-addr",
|
||
"bill-addr",
|
||
// German
|
||
"strasse",
|
||
"adresse",
|
||
];
|
||
IdentityAutoFillConstants.AddressFieldNameValues = [
|
||
"mailing-addr",
|
||
"billing-addr",
|
||
"mail-addr",
|
||
"bill-addr",
|
||
];
|
||
IdentityAutoFillConstants.Address1FieldNames = [
|
||
"address-1",
|
||
"address-line-1",
|
||
"addr-1",
|
||
"street-1",
|
||
];
|
||
IdentityAutoFillConstants.Address2FieldNames = [
|
||
"address-2",
|
||
"address-line-2",
|
||
"addr-2",
|
||
"street-2",
|
||
"address-ext",
|
||
];
|
||
IdentityAutoFillConstants.Address3FieldNames = [
|
||
"address-3",
|
||
"address-line-3",
|
||
"addr-3",
|
||
"street-3",
|
||
];
|
||
IdentityAutoFillConstants.PostalCodeFieldNames = [
|
||
"postal",
|
||
"zip",
|
||
"zip2",
|
||
"zip-code",
|
||
"postal-code",
|
||
"post-code",
|
||
"postcode",
|
||
"address-zip",
|
||
"address-postal",
|
||
"address-code",
|
||
"address-postal-code",
|
||
"address-zip-code",
|
||
// German
|
||
"plz",
|
||
"postleitzahl",
|
||
];
|
||
IdentityAutoFillConstants.CityFieldNames = [
|
||
"city",
|
||
"town",
|
||
"address-level-2",
|
||
"address-city",
|
||
"address-town",
|
||
// German
|
||
"ort",
|
||
"stadt",
|
||
"wohnort",
|
||
];
|
||
IdentityAutoFillConstants.StateFieldNames = [
|
||
"state",
|
||
"province",
|
||
"provence",
|
||
"address-level-1",
|
||
"address-state",
|
||
"address-province",
|
||
// German
|
||
"bundesland",
|
||
];
|
||
IdentityAutoFillConstants.CountryFieldNames = [
|
||
"country",
|
||
"country-code",
|
||
"country-name",
|
||
"address-country",
|
||
"address-country-name",
|
||
"address-country-code",
|
||
// German
|
||
"land",
|
||
];
|
||
IdentityAutoFillConstants.PhoneFieldNames = [
|
||
"phone",
|
||
"mobile",
|
||
"mobile-phone",
|
||
"tel",
|
||
"telephone",
|
||
"phone-number",
|
||
// German
|
||
"telefon",
|
||
"telefonnummer",
|
||
"mobil",
|
||
"handy",
|
||
];
|
||
IdentityAutoFillConstants.UserNameFieldNames = ["user-name", "user-id", "screen-name"];
|
||
IdentityAutoFillConstants.CompanyFieldNames = [
|
||
"company",
|
||
"company-name",
|
||
"organization",
|
||
"organization-name",
|
||
// German
|
||
"firma",
|
||
];
|
||
IdentityAutoFillConstants.IsoCountries = {
|
||
afghanistan: "AF",
|
||
"aland islands": "AX",
|
||
albania: "AL",
|
||
algeria: "DZ",
|
||
"american samoa": "AS",
|
||
andorra: "AD",
|
||
angola: "AO",
|
||
anguilla: "AI",
|
||
antarctica: "AQ",
|
||
"antigua and barbuda": "AG",
|
||
argentina: "AR",
|
||
armenia: "AM",
|
||
aruba: "AW",
|
||
australia: "AU",
|
||
austria: "AT",
|
||
azerbaijan: "AZ",
|
||
bahamas: "BS",
|
||
bahrain: "BH",
|
||
bangladesh: "BD",
|
||
barbados: "BB",
|
||
belarus: "BY",
|
||
belgium: "BE",
|
||
belize: "BZ",
|
||
benin: "BJ",
|
||
bermuda: "BM",
|
||
bhutan: "BT",
|
||
bolivia: "BO",
|
||
"bosnia and herzegovina": "BA",
|
||
botswana: "BW",
|
||
"bouvet island": "BV",
|
||
brazil: "BR",
|
||
"british indian ocean territory": "IO",
|
||
"brunei darussalam": "BN",
|
||
bulgaria: "BG",
|
||
"burkina faso": "BF",
|
||
burundi: "BI",
|
||
cambodia: "KH",
|
||
cameroon: "CM",
|
||
canada: "CA",
|
||
"cape verde": "CV",
|
||
"cayman islands": "KY",
|
||
"central african republic": "CF",
|
||
chad: "TD",
|
||
chile: "CL",
|
||
china: "CN",
|
||
"christmas island": "CX",
|
||
"cocos (keeling) islands": "CC",
|
||
colombia: "CO",
|
||
comoros: "KM",
|
||
congo: "CG",
|
||
"congo, democratic republic": "CD",
|
||
"cook islands": "CK",
|
||
"costa rica": "CR",
|
||
"cote d'ivoire": "CI",
|
||
croatia: "HR",
|
||
cuba: "CU",
|
||
cyprus: "CY",
|
||
"czech republic": "CZ",
|
||
denmark: "DK",
|
||
djibouti: "DJ",
|
||
dominica: "DM",
|
||
"dominican republic": "DO",
|
||
ecuador: "EC",
|
||
egypt: "EG",
|
||
"el salvador": "SV",
|
||
"equatorial guinea": "GQ",
|
||
eritrea: "ER",
|
||
estonia: "EE",
|
||
ethiopia: "ET",
|
||
"falkland islands": "FK",
|
||
"faroe islands": "FO",
|
||
fiji: "FJ",
|
||
finland: "FI",
|
||
france: "FR",
|
||
"french guiana": "GF",
|
||
"french polynesia": "PF",
|
||
"french southern territories": "TF",
|
||
gabon: "GA",
|
||
gambia: "GM",
|
||
georgia: "GE",
|
||
germany: "DE",
|
||
ghana: "GH",
|
||
gibraltar: "GI",
|
||
greece: "GR",
|
||
greenland: "GL",
|
||
grenada: "GD",
|
||
guadeloupe: "GP",
|
||
guam: "GU",
|
||
guatemala: "GT",
|
||
guernsey: "GG",
|
||
guinea: "GN",
|
||
"guinea-bissau": "GW",
|
||
guyana: "GY",
|
||
haiti: "HT",
|
||
"heard island & mcdonald islands": "HM",
|
||
"holy see (vatican city state)": "VA",
|
||
honduras: "HN",
|
||
"hong kong": "HK",
|
||
hungary: "HU",
|
||
iceland: "IS",
|
||
india: "IN",
|
||
indonesia: "ID",
|
||
"iran, islamic republic of": "IR",
|
||
iraq: "IQ",
|
||
ireland: "IE",
|
||
"isle of man": "IM",
|
||
israel: "IL",
|
||
italy: "IT",
|
||
jamaica: "JM",
|
||
japan: "JP",
|
||
jersey: "JE",
|
||
jordan: "JO",
|
||
kazakhstan: "KZ",
|
||
kenya: "KE",
|
||
kiribati: "KI",
|
||
"republic of korea": "KR",
|
||
"south korea": "KR",
|
||
"democratic people's republic of korea": "KP",
|
||
"north korea": "KP",
|
||
kuwait: "KW",
|
||
kyrgyzstan: "KG",
|
||
"lao people's democratic republic": "LA",
|
||
latvia: "LV",
|
||
lebanon: "LB",
|
||
lesotho: "LS",
|
||
liberia: "LR",
|
||
"libyan arab jamahiriya": "LY",
|
||
liechtenstein: "LI",
|
||
lithuania: "LT",
|
||
luxembourg: "LU",
|
||
macao: "MO",
|
||
macedonia: "MK",
|
||
madagascar: "MG",
|
||
malawi: "MW",
|
||
malaysia: "MY",
|
||
maldives: "MV",
|
||
mali: "ML",
|
||
malta: "MT",
|
||
"marshall islands": "MH",
|
||
martinique: "MQ",
|
||
mauritania: "MR",
|
||
mauritius: "MU",
|
||
mayotte: "YT",
|
||
mexico: "MX",
|
||
"micronesia, federated states of": "FM",
|
||
moldova: "MD",
|
||
monaco: "MC",
|
||
mongolia: "MN",
|
||
montenegro: "ME",
|
||
montserrat: "MS",
|
||
morocco: "MA",
|
||
mozambique: "MZ",
|
||
myanmar: "MM",
|
||
namibia: "NA",
|
||
nauru: "NR",
|
||
nepal: "NP",
|
||
netherlands: "NL",
|
||
"netherlands antilles": "AN",
|
||
"new caledonia": "NC",
|
||
"new zealand": "NZ",
|
||
nicaragua: "NI",
|
||
niger: "NE",
|
||
nigeria: "NG",
|
||
niue: "NU",
|
||
"norfolk island": "NF",
|
||
"northern mariana islands": "MP",
|
||
norway: "NO",
|
||
oman: "OM",
|
||
pakistan: "PK",
|
||
palau: "PW",
|
||
"palestinian territory, occupied": "PS",
|
||
panama: "PA",
|
||
"papua new guinea": "PG",
|
||
paraguay: "PY",
|
||
peru: "PE",
|
||
philippines: "PH",
|
||
pitcairn: "PN",
|
||
poland: "PL",
|
||
portugal: "PT",
|
||
"puerto rico": "PR",
|
||
qatar: "QA",
|
||
reunion: "RE",
|
||
romania: "RO",
|
||
"russian federation": "RU",
|
||
rwanda: "RW",
|
||
"saint barthelemy": "BL",
|
||
"saint helena": "SH",
|
||
"saint kitts and nevis": "KN",
|
||
"saint lucia": "LC",
|
||
"saint martin": "MF",
|
||
"saint pierre and miquelon": "PM",
|
||
"saint vincent and grenadines": "VC",
|
||
samoa: "WS",
|
||
"san marino": "SM",
|
||
"sao tome and principe": "ST",
|
||
"saudi arabia": "SA",
|
||
senegal: "SN",
|
||
serbia: "RS",
|
||
seychelles: "SC",
|
||
"sierra leone": "SL",
|
||
singapore: "SG",
|
||
slovakia: "SK",
|
||
slovenia: "SI",
|
||
"solomon islands": "SB",
|
||
somalia: "SO",
|
||
"south africa": "ZA",
|
||
"south georgia and sandwich isl.": "GS",
|
||
spain: "ES",
|
||
"sri lanka": "LK",
|
||
sudan: "SD",
|
||
suriname: "SR",
|
||
"svalbard and jan mayen": "SJ",
|
||
swaziland: "SZ",
|
||
sweden: "SE",
|
||
switzerland: "CH",
|
||
"syrian arab republic": "SY",
|
||
taiwan: "TW",
|
||
tajikistan: "TJ",
|
||
tanzania: "TZ",
|
||
thailand: "TH",
|
||
"timor-leste": "TL",
|
||
togo: "TG",
|
||
tokelau: "TK",
|
||
tonga: "TO",
|
||
"trinidad and tobago": "TT",
|
||
tunisia: "TN",
|
||
turkey: "TR",
|
||
turkmenistan: "TM",
|
||
"turks and caicos islands": "TC",
|
||
tuvalu: "TV",
|
||
uganda: "UG",
|
||
ukraine: "UA",
|
||
"united arab emirates": "AE",
|
||
"united kingdom": "GB",
|
||
"united states": "US",
|
||
"united states outlying islands": "UM",
|
||
uruguay: "UY",
|
||
uzbekistan: "UZ",
|
||
vanuatu: "VU",
|
||
venezuela: "VE",
|
||
vietnam: "VN",
|
||
"virgin islands, british": "VG",
|
||
"virgin islands, u.s.": "VI",
|
||
"wallis and futuna": "WF",
|
||
"western sahara": "EH",
|
||
yemen: "YE",
|
||
zambia: "ZM",
|
||
zimbabwe: "ZW",
|
||
};
|
||
IdentityAutoFillConstants.IsoStates = {
|
||
alabama: "AL",
|
||
alaska: "AK",
|
||
"american samoa": "AS",
|
||
arizona: "AZ",
|
||
arkansas: "AR",
|
||
california: "CA",
|
||
colorado: "CO",
|
||
connecticut: "CT",
|
||
delaware: "DE",
|
||
"district of columbia": "DC",
|
||
"federated states of micronesia": "FM",
|
||
florida: "FL",
|
||
georgia: "GA",
|
||
guam: "GU",
|
||
hawaii: "HI",
|
||
idaho: "ID",
|
||
illinois: "IL",
|
||
indiana: "IN",
|
||
iowa: "IA",
|
||
kansas: "KS",
|
||
kentucky: "KY",
|
||
louisiana: "LA",
|
||
maine: "ME",
|
||
"marshall islands": "MH",
|
||
maryland: "MD",
|
||
massachusetts: "MA",
|
||
michigan: "MI",
|
||
minnesota: "MN",
|
||
mississippi: "MS",
|
||
missouri: "MO",
|
||
montana: "MT",
|
||
nebraska: "NE",
|
||
nevada: "NV",
|
||
"new hampshire": "NH",
|
||
"new jersey": "NJ",
|
||
"new mexico": "NM",
|
||
"new york": "NY",
|
||
"north carolina": "NC",
|
||
"north dakota": "ND",
|
||
"northern mariana islands": "MP",
|
||
ohio: "OH",
|
||
oklahoma: "OK",
|
||
oregon: "OR",
|
||
palau: "PW",
|
||
pennsylvania: "PA",
|
||
"puerto rico": "PR",
|
||
"rhode island": "RI",
|
||
"south carolina": "SC",
|
||
"south dakota": "SD",
|
||
tennessee: "TN",
|
||
texas: "TX",
|
||
utah: "UT",
|
||
vermont: "VT",
|
||
"virgin islands": "VI",
|
||
virginia: "VA",
|
||
washington: "WA",
|
||
"west virginia": "WV",
|
||
wisconsin: "WI",
|
||
wyoming: "WY",
|
||
};
|
||
IdentityAutoFillConstants.IsoProvinces = {
|
||
alberta: "AB",
|
||
"british columbia": "BC",
|
||
manitoba: "MB",
|
||
"new brunswick": "NB",
|
||
"newfoundland and labrador": "NL",
|
||
"nova scotia": "NS",
|
||
ontario: "ON",
|
||
"prince edward island": "PE",
|
||
quebec: "QC",
|
||
saskatchewan: "SK",
|
||
};
|
||
const SubmitLoginButtonNames = [
|
||
"login",
|
||
"signin",
|
||
"submit",
|
||
"continue",
|
||
"next",
|
||
"verify",
|
||
];
|
||
const SubmitChangePasswordButtonNames = [
|
||
"change",
|
||
"save",
|
||
"savepassword",
|
||
"updatepassword",
|
||
"changepassword",
|
||
"resetpassword",
|
||
];
|
||
|
||
;// ./src/autofill/services/autofill-overlay-content.service.ts
|
||
var autofill_overlay_content_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
class AutofillOverlayContentService {
|
||
constructor(domQueryService, domElementVisibilityService, inlineMenuFieldQualificationService, inlineMenuContentService) {
|
||
this.domQueryService = domQueryService;
|
||
this.domElementVisibilityService = domElementVisibilityService;
|
||
this.inlineMenuFieldQualificationService = inlineMenuFieldQualificationService;
|
||
this.inlineMenuContentService = inlineMenuContentService;
|
||
this.pageDetailsUpdateRequired = false;
|
||
this.findTabs = tabbable;
|
||
this.sendExtensionMessage = sendExtensionMessage;
|
||
this.formFieldElements = new Map();
|
||
this.hiddenFormFieldElements = new WeakMap();
|
||
this.formElements = new Set();
|
||
this.submitElements = new Set();
|
||
this.fieldsWithSubmitElements = new WeakMap();
|
||
this.ignoredFieldTypes = new Set(AutoFillConstants.ExcludedInlineMenuTypes);
|
||
this.userFilledFields = {};
|
||
this.focusableElements = [];
|
||
this.eventHandlersMemo = {};
|
||
this.extensionMessageHandlers = {
|
||
addNewVaultItemFromOverlay: ({ message }) => this.addNewVaultItem(message),
|
||
focusMostRecentlyFocusedField: () => this.focusMostRecentlyFocusedField(),
|
||
blurMostRecentlyFocusedField: () => this.blurMostRecentlyFocusedField(),
|
||
unsetMostRecentlyFocusedField: () => this.unsetMostRecentlyFocusedField(),
|
||
checkIsMostRecentlyFocusedFieldWithinViewport: () => this.checkIsMostRecentlyFocusedFieldWithinViewport(),
|
||
bgVaultItemRepromptPopoutOpened: () => this.blurMostRecentlyFocusedField(true),
|
||
bgUnlockPopoutOpened: () => this.blurMostRecentlyFocusedField(true),
|
||
redirectAutofillInlineMenuFocusOut: ({ message }) => { var _a; return this.redirectInlineMenuFocusOut((_a = message === null || message === void 0 ? void 0 : message.data) === null || _a === void 0 ? void 0 : _a.direction); },
|
||
getSubFrameOffsets: ({ message }) => this.getSubFrameOffsets(message),
|
||
getSubFrameOffsetsFromWindowMessage: ({ message }) => this.getSubFrameOffsetsFromWindowMessage(message),
|
||
checkMostRecentlyFocusedFieldHasValue: () => this.mostRecentlyFocusedFieldHasValue(),
|
||
setupRebuildSubFrameOffsetsListeners: () => this.setupRebuildSubFrameOffsetsListeners(),
|
||
destroyAutofillInlineMenuListeners: () => this.destroy(),
|
||
getInlineMenuFormFieldData: ({ message }) => this.handleGetInlineMenuFormFieldDataMessage(message),
|
||
generatedPasswordModifyLogin: () => this.sendGeneratedPasswordModifyLogin(),
|
||
};
|
||
this.loginFieldQualifiers = {
|
||
[AutofillFieldQualifier.username]: this.inlineMenuFieldQualificationService.isUsernameField,
|
||
[AutofillFieldQualifier.password]: this.inlineMenuFieldQualificationService.isCurrentPasswordField,
|
||
};
|
||
this.accountCreationFieldQualifiers = {
|
||
[AutofillFieldQualifier.username]: this.inlineMenuFieldQualificationService.isUsernameField,
|
||
[AutofillFieldQualifier.newPassword]: this.inlineMenuFieldQualificationService.isNewPasswordField,
|
||
};
|
||
this.cardFieldQualifiers = {
|
||
[AutofillFieldQualifier.cardholderName]: this.inlineMenuFieldQualificationService.isFieldForCardholderName,
|
||
[AutofillFieldQualifier.cardNumber]: this.inlineMenuFieldQualificationService.isFieldForCardNumber,
|
||
[AutofillFieldQualifier.cardExpirationMonth]: this.inlineMenuFieldQualificationService.isFieldForCardExpirationMonth,
|
||
[AutofillFieldQualifier.cardExpirationYear]: this.inlineMenuFieldQualificationService.isFieldForCardExpirationYear,
|
||
[AutofillFieldQualifier.cardExpirationDate]: this.inlineMenuFieldQualificationService.isFieldForCardExpirationDate,
|
||
[AutofillFieldQualifier.cardCvv]: this.inlineMenuFieldQualificationService.isFieldForCardCvv,
|
||
};
|
||
this.identityFieldQualifiers = {
|
||
[AutofillFieldQualifier.identityTitle]: this.inlineMenuFieldQualificationService.isFieldForIdentityTitle,
|
||
[AutofillFieldQualifier.identityFirstName]: this.inlineMenuFieldQualificationService.isFieldForIdentityFirstName,
|
||
[AutofillFieldQualifier.identityMiddleName]: this.inlineMenuFieldQualificationService.isFieldForIdentityMiddleName,
|
||
[AutofillFieldQualifier.identityLastName]: this.inlineMenuFieldQualificationService.isFieldForIdentityLastName,
|
||
[AutofillFieldQualifier.identityFullName]: this.inlineMenuFieldQualificationService.isFieldForIdentityFullName,
|
||
[AutofillFieldQualifier.identityAddress1]: this.inlineMenuFieldQualificationService.isFieldForIdentityAddress1,
|
||
[AutofillFieldQualifier.identityAddress2]: this.inlineMenuFieldQualificationService.isFieldForIdentityAddress2,
|
||
[AutofillFieldQualifier.identityAddress3]: this.inlineMenuFieldQualificationService.isFieldForIdentityAddress3,
|
||
[AutofillFieldQualifier.identityCity]: this.inlineMenuFieldQualificationService.isFieldForIdentityCity,
|
||
[AutofillFieldQualifier.identityState]: this.inlineMenuFieldQualificationService.isFieldForIdentityState,
|
||
[AutofillFieldQualifier.identityPostalCode]: this.inlineMenuFieldQualificationService.isFieldForIdentityPostalCode,
|
||
[AutofillFieldQualifier.identityCountry]: this.inlineMenuFieldQualificationService.isFieldForIdentityCountry,
|
||
[AutofillFieldQualifier.identityCompany]: this.inlineMenuFieldQualificationService.isFieldForIdentityCompany,
|
||
[AutofillFieldQualifier.identityPhone]: this.inlineMenuFieldQualificationService.isFieldForIdentityPhone,
|
||
[AutofillFieldQualifier.identityEmail]: this.inlineMenuFieldQualificationService.isFieldForIdentityEmail,
|
||
[AutofillFieldQualifier.identityUsername]: this.inlineMenuFieldQualificationService.isFieldForIdentityUsername,
|
||
};
|
||
this.refreshMenuLayerPosition = () => { var _a; return (_a = this.inlineMenuContentService) === null || _a === void 0 ? void 0 : _a.refreshTopLayerPosition(); };
|
||
this.getOwnedInlineMenuTagNames = () => { var _a; return ((_a = this.inlineMenuContentService) === null || _a === void 0 ? void 0 : _a.getOwnedTagNames()) || []; };
|
||
this.getUnownedTopLayerItems = (includeCandidates) => { var _a; return (_a = this.inlineMenuContentService) === null || _a === void 0 ? void 0 : _a.getUnownedTopLayerItems(includeCandidates); };
|
||
/**
|
||
* On password generation, send form field data i.e. modified login data
|
||
*/
|
||
this.sendGeneratedPasswordModifyLogin = () => autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.sendExtensionMessage("generatedPasswordFilled", this.getFormFieldData());
|
||
});
|
||
/**
|
||
* Sets up the event listeners that trigger an indication that a form has been submitted.
|
||
*
|
||
* @param submitButton - The submit button element to set up the event listeners for.
|
||
*/
|
||
this.setupSubmitButtonEventListeners = (submitButton) => {
|
||
if (!submitButton || this.submitElements.has(submitButton)) {
|
||
return;
|
||
}
|
||
this.submitElements.add(submitButton);
|
||
const handler = this.useEventHandlersMemo(throttle(this.handleSubmitButtonInteraction, 150), AUTOFILL_TRIGGER_FORM_FIELD_SUBMIT);
|
||
submitButton.addEventListener(EVENTS.KEYUP, handler);
|
||
globalThis.document.addEventListener(EVENTS.CLICK, handler);
|
||
globalThis.document.addEventListener(EVENTS.MOUSEUP, handler);
|
||
};
|
||
/**
|
||
* Handles click and keyup events that trigger behavior for a submit button element.
|
||
*
|
||
* @param event - The event that triggered the submit button interaction.
|
||
*/
|
||
this.handleSubmitButtonInteraction = (event) => {
|
||
if (!this.submitElements.has(event.target) ||
|
||
(event.type === "keyup" &&
|
||
!["Enter", "Space"].includes(event.code))) {
|
||
return;
|
||
}
|
||
this.handleFormFieldSubmitEvent();
|
||
};
|
||
/**
|
||
* Handles the repositioning of the autofill overlay when the form is submitted.
|
||
*/
|
||
this.handleFormFieldSubmitEvent = () => {
|
||
void this.sendExtensionMessage("formFieldSubmitted", this.getFormFieldData());
|
||
};
|
||
/**
|
||
* Handles capturing the form field data for a notification message. Will not trigger this behavior
|
||
* in the case where the user is still typing in the field unless the focus is ignored.
|
||
*/
|
||
this.handleGetInlineMenuFormFieldDataMessage = (_a) => autofill_overlay_content_service_awaiter(this, [_a], void 0, function* ({ ignoreFieldFocus, }) {
|
||
if (!ignoreFieldFocus && (yield this.isFieldCurrentlyFocused())) {
|
||
return;
|
||
}
|
||
return this.getFormFieldData();
|
||
});
|
||
/**
|
||
* Returns the form field data used for add login and change password notifications.
|
||
*/
|
||
this.getFormFieldData = () => {
|
||
var _a, _b, _c;
|
||
return {
|
||
uri: globalThis.document.URL,
|
||
username: ((_a = this.userFilledFields["username"]) === null || _a === void 0 ? void 0 : _a.value) || "",
|
||
password: ((_b = this.userFilledFields["password"]) === null || _b === void 0 ? void 0 : _b.value) || "",
|
||
newPassword: ((_c = this.userFilledFields["newPassword"]) === null || _c === void 0 ? void 0 : _c.value) || "",
|
||
};
|
||
};
|
||
/**
|
||
* Helper method that facilitates registration of an event handler to a form field element.
|
||
*
|
||
* @param eventHandler - The event handler to memoize.
|
||
* @param memoIndex - The memo index to use for the event handler.
|
||
*/
|
||
this.useEventHandlersMemo = (eventHandler, memoIndex) => {
|
||
return this.eventHandlersMemo[memoIndex] || (this.eventHandlersMemo[memoIndex] = eventHandler);
|
||
};
|
||
/**
|
||
* Form Field blur event handler. Updates the value identifying whether
|
||
* the field is focused and sends a message to check if the inline menu itself
|
||
* is currently focused.
|
||
*/
|
||
this.handleFormFieldBlurEvent = () => {
|
||
void this.updateIsFieldCurrentlyFocused(false);
|
||
void this.sendExtensionMessage("checkAutofillInlineMenuFocused");
|
||
};
|
||
/**
|
||
* Form field keyup event handler. Facilitates the ability to remove the
|
||
* autofill inline menu using the escape key, focusing the inline menu list using
|
||
* the ArrowDown key, and ensuring that the inline menu is repositioned when
|
||
* the form is submitted using the Enter key.
|
||
*
|
||
* @param event - The keyup event.
|
||
*/
|
||
this.handleFormFieldKeyupEvent = (event) => autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const eventCode = event.code;
|
||
if (eventCode === "Escape") {
|
||
void this.sendExtensionMessage("closeAutofillInlineMenu", {
|
||
forceCloseInlineMenu: true,
|
||
});
|
||
return;
|
||
}
|
||
if (eventCode === "Enter" && !(yield this.isFieldCurrentlyFilling())) {
|
||
void this.handleOverlayRepositionEvent();
|
||
return;
|
||
}
|
||
if (eventCode === "ArrowDown") {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
void this.focusInlineMenuList();
|
||
}
|
||
});
|
||
/**
|
||
* Sets up and memoizes the form field input event handler.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the input event.
|
||
*/
|
||
this.handleFormFieldInputEvent = (formFieldElement) => {
|
||
return this.useEventHandlersMemo(debounce(() => this.triggerFormFieldInput(formFieldElement), 100, true), this.getFormFieldHandlerMemoIndex(formFieldElement, EVENTS.INPUT));
|
||
};
|
||
/**
|
||
* Handles qualification of the user filled field based on the field qualifiers provided.
|
||
*
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
* @param qualifiers - The field qualifiers to use when qualifying the user filled field.
|
||
*/
|
||
this.qualifyUserFilledField = (autofillFieldData, qualifiers) => {
|
||
for (const [fieldQualifier, fieldQualifierFunction] of Object.entries(qualifiers)) {
|
||
if (fieldQualifierFunction(autofillFieldData)) {
|
||
autofillFieldData.fieldQualifier = fieldQualifier;
|
||
return;
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* Sets up and memoizes the form field click event handler.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the click event.
|
||
*/
|
||
this.handleFormFieldClickEvent = (formFieldElement) => {
|
||
return this.useEventHandlersMemo(() => this.triggerFormFieldClickedAction(formFieldElement), this.getFormFieldHandlerMemoIndex(formFieldElement, EVENTS.CLICK));
|
||
};
|
||
/**
|
||
* Sets up and memoizes the form field focus event handler.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
*/
|
||
this.handleFormFieldFocusEvent = (formFieldElement) => {
|
||
return this.useEventHandlersMemo(() => this.triggerFormFieldFocusedAction(formFieldElement), this.getFormFieldHandlerMemoIndex(formFieldElement, EVENTS.FOCUS));
|
||
};
|
||
/**
|
||
* Triggers an update in the background script focused status of the form field element.
|
||
*
|
||
* @param isFieldCurrentlyFocused - The focused status of the form field element.
|
||
*/
|
||
this.updateIsFieldCurrentlyFocused = (isFieldCurrentlyFocused) => autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.sendExtensionMessage("updateIsFieldCurrentlyFocused", { isFieldCurrentlyFocused });
|
||
});
|
||
/**
|
||
* Handles the focus event on a hidden field. When
|
||
* triggered, the inline menu is set up on the field.
|
||
*
|
||
* @param event - The focus event.
|
||
*/
|
||
this.handleHiddenFieldFocusEvent = (event) => {
|
||
const formFieldElement = event.target;
|
||
this.handleHiddenElementFallbackEvent(formFieldElement);
|
||
};
|
||
/**
|
||
* Handles an input event on a hidden field. When triggered, the inline menu is set up on the
|
||
* field. We also capture the input value for the field to facilitate presentation of the value
|
||
* for the field in the notification bar.
|
||
*
|
||
* @param event - The input event.
|
||
*/
|
||
this.handleHiddenFieldInputEvent = (event) => autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const formFieldElement = event.target;
|
||
this.handleHiddenElementFallbackEvent(formFieldElement);
|
||
yield this.triggerFormFieldInput(formFieldElement);
|
||
});
|
||
/**
|
||
* Handles updating the hidden element when a fallback event is triggered.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
*/
|
||
this.handleHiddenElementFallbackEvent = (formFieldElement) => {
|
||
const autofillFieldData = this.hiddenFormFieldElements.get(formFieldElement);
|
||
if (autofillFieldData) {
|
||
autofillFieldData.readonly = getAttributeBoolean(formFieldElement, "disabled");
|
||
autofillFieldData.disabled = getAttributeBoolean(formFieldElement, "disabled");
|
||
autofillFieldData.viewable = true;
|
||
void this.setupOverlayListenersOnQualifiedField(formFieldElement, autofillFieldData);
|
||
}
|
||
this.removeHiddenFieldFallbackListener(formFieldElement);
|
||
};
|
||
/**
|
||
* Calculates the sub frame positioning for the current frame
|
||
* through all parent frames until the top frame is reached.
|
||
*
|
||
* @param event - The message event.
|
||
*/
|
||
this.calculateSubFramePositioning = (event) => autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const subFrameData = event.data.subFrameData;
|
||
subFrameData.subFrameDepth++;
|
||
if (subFrameData.subFrameDepth >= MAX_SUB_FRAME_DEPTH) {
|
||
void this.sendExtensionMessage("destroyAutofillInlineMenuListeners", { subFrameData });
|
||
return;
|
||
}
|
||
let subFrameOffsets;
|
||
const iframes = globalThis.document.querySelectorAll("iframe");
|
||
for (let i = 0; i < iframes.length; i++) {
|
||
if (iframes[i].contentWindow === event.source) {
|
||
const iframeElement = iframes[i];
|
||
subFrameOffsets = this.calculateSubFrameOffsets(iframeElement, subFrameData.url, subFrameData.frameId);
|
||
if (!subFrameOffsets) {
|
||
return;
|
||
}
|
||
subFrameData.top += subFrameOffsets.top;
|
||
subFrameData.left += subFrameOffsets.left;
|
||
const parentFrameId = yield this.sendExtensionMessage("getCurrentTabFrameId");
|
||
if (typeof parentFrameId !== "undefined") {
|
||
subFrameData.parentFrameIds.push(parentFrameId);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (globalThis.window.self !== globalThis.window.top) {
|
||
globalThis.parent.postMessage({ command: "calculateSubFramePositioning", subFrameData }, "*");
|
||
return;
|
||
}
|
||
void this.sendExtensionMessage("updateSubFrameData", { subFrameData });
|
||
});
|
||
/**
|
||
* Sets up global event listeners and the mutation
|
||
* observer to facilitate required changes to the
|
||
* overlay elements.
|
||
*/
|
||
this.setupGlobalEventListeners = () => {
|
||
globalThis.addEventListener(EVENTS.MESSAGE, this.handleWindowMessageEvent);
|
||
globalThis.document.addEventListener(EVENTS.VISIBILITYCHANGE, this.handleVisibilityChangeEvent);
|
||
globalThis.addEventListener(EVENTS.FOCUSOUT, this.handleWindowFocusOutEvent);
|
||
this.setOverlayRepositionEventListeners();
|
||
};
|
||
/**
|
||
* Handles window messages that are sent to the current frame. Will trigger a
|
||
* calculation of the sub frame offsets through the parent frame.
|
||
*
|
||
* @param event - The message event.
|
||
*/
|
||
this.handleWindowMessageEvent = (event) => {
|
||
var _a;
|
||
if (((_a = event.data) === null || _a === void 0 ? void 0 : _a.command) === "calculateSubFramePositioning") {
|
||
void this.calculateSubFramePositioning(event);
|
||
}
|
||
};
|
||
/**
|
||
* Handles the window focus out event, triggering a focus check on the
|
||
* inline menu if the document has focus and a closure of the inline
|
||
* menu if it does not have focus.
|
||
*/
|
||
this.handleWindowFocusOutEvent = () => {
|
||
if (document.hasFocus()) {
|
||
this.handleFormFieldBlurEvent();
|
||
return;
|
||
}
|
||
void this.sendExtensionMessage("closeAutofillInlineMenu", {
|
||
forceCloseInlineMenu: true,
|
||
});
|
||
};
|
||
/**
|
||
* Handles the visibility change event. This method will remove the
|
||
* autofill overlay if the document is not visible.
|
||
*/
|
||
this.handleVisibilityChangeEvent = () => {
|
||
if (globalThis.document.visibilityState === "hidden") {
|
||
void this.sendExtensionMessage("closeAutofillInlineMenu", {
|
||
forceCloseInlineMenu: true,
|
||
});
|
||
}
|
||
if (this.mostRecentlyFocusedField) {
|
||
this.unsetMostRecentlyFocusedField();
|
||
}
|
||
};
|
||
/**
|
||
* Handles the resize or scroll events that enact
|
||
* repositioning of existing overlay elements.
|
||
*/
|
||
this.handleOverlayRepositionEvent = () => autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.sendExtensionMessage("triggerAutofillOverlayReposition");
|
||
});
|
||
/**
|
||
* Sets up listeners that facilitate a rebuild of the sub frame offsets
|
||
* when a user interacts or focuses an element within the frame.
|
||
*/
|
||
this.setupRebuildSubFrameOffsetsListeners = () => {
|
||
if (globalThis.window.top === globalThis.window || this.formFieldElements.size < 1) {
|
||
return;
|
||
}
|
||
this.removeSubFrameFocusOutListeners();
|
||
globalThis.addEventListener(EVENTS.FOCUS, this.handleSubFrameFocusInEvent);
|
||
globalThis.document.body.addEventListener(EVENTS.MOUSEENTER, this.handleSubFrameFocusInEvent);
|
||
};
|
||
/**
|
||
* Removes the listeners that facilitate a rebuild of the sub frame offsets.
|
||
*/
|
||
this.removeRebuildSubFrameOffsetsListeners = () => {
|
||
globalThis.removeEventListener(EVENTS.FOCUS, this.handleSubFrameFocusInEvent);
|
||
globalThis.document.body.removeEventListener(EVENTS.MOUSEENTER, this.handleSubFrameFocusInEvent);
|
||
};
|
||
/**
|
||
* Re-establishes listeners that handle the sub frame offsets rebuild of the frame
|
||
* based on user interaction with the sub frame.
|
||
*/
|
||
this.setupSubFrameFocusOutListeners = () => {
|
||
globalThis.addEventListener(EVENTS.BLUR, this.setupRebuildSubFrameOffsetsListeners);
|
||
globalThis.document.body.addEventListener(EVENTS.MOUSELEAVE, this.setupRebuildSubFrameOffsetsListeners);
|
||
};
|
||
/**
|
||
* Removes the listeners that trigger when a user focuses away from the sub frame.
|
||
*/
|
||
this.removeSubFrameFocusOutListeners = () => {
|
||
globalThis.removeEventListener(EVENTS.BLUR, this.setupRebuildSubFrameOffsetsListeners);
|
||
globalThis.document.body.removeEventListener(EVENTS.MOUSELEAVE, this.setupRebuildSubFrameOffsetsListeners);
|
||
};
|
||
/**
|
||
* Sends a message to the background script to trigger a rebuild of the sub frame
|
||
* offsets. Will deregister the listeners to ensure that other focus and mouse
|
||
* events do not unnecessarily re-trigger a sub frame rebuild.
|
||
*/
|
||
this.handleSubFrameFocusInEvent = () => {
|
||
void this.sendExtensionMessage("triggerSubFrameFocusInRebuild");
|
||
this.removeRebuildSubFrameOffsetsListeners();
|
||
this.setupSubFrameFocusOutListeners();
|
||
};
|
||
}
|
||
/**
|
||
* Initializes the autofill overlay content service by setting up the mutation observers.
|
||
* The observers will be instantiated on DOMContentLoaded if the page is current loading.
|
||
*/
|
||
init() {
|
||
void this.getInlineMenuCardsVisibility();
|
||
void this.getInlineMenuIdentitiesVisibility();
|
||
if (globalThis.document.readyState === "loading") {
|
||
globalThis.document.addEventListener(EVENTS.DOMCONTENTLOADED, this.setupGlobalEventListeners);
|
||
return;
|
||
}
|
||
this.setupGlobalEventListeners();
|
||
}
|
||
/**
|
||
* Getter used to access the extension message handlers associated
|
||
* with the autofill overlay content service.
|
||
*/
|
||
get messageHandlers() {
|
||
return this.extensionMessageHandlers;
|
||
}
|
||
/**
|
||
* Sets up the autofill inline menu listener on the form field element. This method is called
|
||
* during the page details collection process.
|
||
*
|
||
* @param formFieldElement - Form field elements identified during the page details collection process.
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
* @param pageDetails - The collected page details from the tab.
|
||
*/
|
||
setupOverlayListeners(formFieldElement, autofillFieldData, pageDetails) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (currentlyInSandboxedIframe() ||
|
||
this.formFieldElements.has(formFieldElement) ||
|
||
this.isIgnoredField(autofillFieldData, pageDetails)) {
|
||
return;
|
||
}
|
||
if (this.isHiddenField(formFieldElement, autofillFieldData)) {
|
||
return;
|
||
}
|
||
yield this.setupOverlayListenersOnQualifiedField(formFieldElement, autofillFieldData);
|
||
});
|
||
}
|
||
/**
|
||
* Removes focus from the most recently focused field element.
|
||
*/
|
||
blurMostRecentlyFocusedField() {
|
||
return autofill_overlay_content_service_awaiter(this, arguments, void 0, function* (isClosingInlineMenu = false) {
|
||
var _a;
|
||
(_a = this.mostRecentlyFocusedField) === null || _a === void 0 ? void 0 : _a.blur();
|
||
if (isClosingInlineMenu) {
|
||
yield this.sendExtensionMessage("closeAutofillInlineMenu", { forceCloseInlineMenu: true });
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Clears all cached user filled fields.
|
||
*/
|
||
clearUserFilledFields() {
|
||
Object.keys(this.userFilledFields).forEach((key) => {
|
||
if (this.userFilledFields[key]) {
|
||
delete this.userFilledFields[key];
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Formats any found user filled fields for a login cipher and sends a message
|
||
* to the background script to add a new cipher.
|
||
*/
|
||
addNewVaultItem(_a) {
|
||
return autofill_overlay_content_service_awaiter(this, arguments, void 0, function* ({ addNewCipherType }) {
|
||
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
|
||
const command = "autofillOverlayAddNewVaultItem";
|
||
const password = ((_b = this.userFilledFields["newPassword"]) === null || _b === void 0 ? void 0 : _b.value) || ((_c = this.userFilledFields["password"]) === null || _c === void 0 ? void 0 : _c.value);
|
||
if (addNewCipherType === CipherType.Login) {
|
||
const login = {
|
||
username: ((_d = this.userFilledFields["username"]) === null || _d === void 0 ? void 0 : _d.value) || "",
|
||
password: password || "",
|
||
uri: globalThis.document.URL,
|
||
hostname: globalThis.document.location.hostname,
|
||
};
|
||
yield this.sendExtensionMessage(command, { addNewCipherType, login });
|
||
return;
|
||
}
|
||
if (addNewCipherType === CipherType.Card) {
|
||
const card = {
|
||
cardholderName: ((_e = this.userFilledFields["cardholderName"]) === null || _e === void 0 ? void 0 : _e.value) || "",
|
||
number: ((_f = this.userFilledFields["cardNumber"]) === null || _f === void 0 ? void 0 : _f.value) || "",
|
||
expirationMonth: ((_g = this.userFilledFields["cardExpirationMonth"]) === null || _g === void 0 ? void 0 : _g.value) || "",
|
||
expirationYear: ((_h = this.userFilledFields["cardExpirationYear"]) === null || _h === void 0 ? void 0 : _h.value) || "",
|
||
expirationDate: ((_j = this.userFilledFields["cardExpirationDate"]) === null || _j === void 0 ? void 0 : _j.value) || "",
|
||
cvv: ((_k = this.userFilledFields["cardCvv"]) === null || _k === void 0 ? void 0 : _k.value) || "",
|
||
};
|
||
yield this.sendExtensionMessage(command, { addNewCipherType, card });
|
||
return;
|
||
}
|
||
if (addNewCipherType === CipherType.Identity) {
|
||
const identity = {
|
||
title: ((_l = this.userFilledFields["identityTitle"]) === null || _l === void 0 ? void 0 : _l.value) || "",
|
||
firstName: ((_m = this.userFilledFields["identityFirstName"]) === null || _m === void 0 ? void 0 : _m.value) || "",
|
||
middleName: ((_o = this.userFilledFields["identityMiddleName"]) === null || _o === void 0 ? void 0 : _o.value) || "",
|
||
lastName: ((_p = this.userFilledFields["identityLastName"]) === null || _p === void 0 ? void 0 : _p.value) || "",
|
||
fullName: ((_q = this.userFilledFields["identityFullName"]) === null || _q === void 0 ? void 0 : _q.value) || "",
|
||
address1: ((_r = this.userFilledFields["identityAddress1"]) === null || _r === void 0 ? void 0 : _r.value) || "",
|
||
address2: ((_s = this.userFilledFields["identityAddress2"]) === null || _s === void 0 ? void 0 : _s.value) || "",
|
||
address3: ((_t = this.userFilledFields["identityAddress3"]) === null || _t === void 0 ? void 0 : _t.value) || "",
|
||
city: ((_u = this.userFilledFields["identityCity"]) === null || _u === void 0 ? void 0 : _u.value) || "",
|
||
state: ((_v = this.userFilledFields["identityState"]) === null || _v === void 0 ? void 0 : _v.value) || "",
|
||
postalCode: ((_w = this.userFilledFields["identityPostalCode"]) === null || _w === void 0 ? void 0 : _w.value) || "",
|
||
country: ((_x = this.userFilledFields["identityCountry"]) === null || _x === void 0 ? void 0 : _x.value) || "",
|
||
company: ((_y = this.userFilledFields["identityCompany"]) === null || _y === void 0 ? void 0 : _y.value) || "",
|
||
phone: ((_z = this.userFilledFields["identityPhone"]) === null || _z === void 0 ? void 0 : _z.value) || "",
|
||
email: ((_0 = this.userFilledFields["identityEmail"]) === null || _0 === void 0 ? void 0 : _0.value) || "",
|
||
username: ((_1 = this.userFilledFields["identityUsername"]) === null || _1 === void 0 ? void 0 : _1.value) || "",
|
||
};
|
||
yield this.sendExtensionMessage(command, { addNewCipherType, identity });
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Focuses the most recently focused field element.
|
||
*/
|
||
focusMostRecentlyFocusedField() {
|
||
var _a;
|
||
(_a = this.mostRecentlyFocusedField) === null || _a === void 0 ? void 0 : _a.focus();
|
||
}
|
||
/**
|
||
* Sets the most recently focused field within the current frame to a `null` value.
|
||
*/
|
||
unsetMostRecentlyFocusedField() {
|
||
this.mostRecentlyFocusedField = null;
|
||
}
|
||
/**
|
||
* Redirects the keyboard focus out of the inline menu, selecting the element that is
|
||
* either previous or next in the tab order. If the direction is current, the most
|
||
* recently focused field will be focused.
|
||
*
|
||
* @param direction - The direction to redirect the focus out.
|
||
*/
|
||
redirectInlineMenuFocusOut(direction) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!direction || !this.mostRecentlyFocusedField || !(yield this.isInlineMenuListVisible())) {
|
||
return;
|
||
}
|
||
if (direction === RedirectFocusDirection.Current) {
|
||
this.focusMostRecentlyFocusedField();
|
||
this.closeInlineMenuOnRedirectTimeout = globalThis.setTimeout(() => void this.sendExtensionMessage("closeAutofillInlineMenu"), 100);
|
||
return;
|
||
}
|
||
if (!this.focusableElements.length) {
|
||
this.focusableElements = this.findTabs(globalThis.document.body, { getShadowRoot: true });
|
||
}
|
||
const focusedElementIndex = this.focusableElements.findIndex((element) => element === this.mostRecentlyFocusedField);
|
||
const indexOffset = direction === RedirectFocusDirection.Previous ? -1 : 1;
|
||
const redirectFocusElement = this.focusableElements[focusedElementIndex + indexOffset];
|
||
if (redirectFocusElement) {
|
||
redirectFocusElement.focus();
|
||
return;
|
||
}
|
||
this.focusMostRecentlyFocusedField();
|
||
});
|
||
}
|
||
/**
|
||
* Sets up the event listeners that facilitate interaction with the form field elements.
|
||
* Will clear any cached form field element handlers that are encountered when setting
|
||
* up a form field element.
|
||
*
|
||
* @param formFieldElement - The form field element to set up the event listeners for.
|
||
*/
|
||
setupFormFieldElementEventListeners(formFieldElement) {
|
||
this.removeCachedFormFieldEventListeners(formFieldElement);
|
||
formFieldElement.addEventListener(EVENTS.INPUT, this.handleFormFieldInputEvent(formFieldElement));
|
||
formFieldElement.addEventListener(EVENTS.FOCUS, this.handleFormFieldFocusEvent(formFieldElement));
|
||
if (elementIsSelectElement(formFieldElement)) {
|
||
return;
|
||
}
|
||
formFieldElement.addEventListener(EVENTS.BLUR, this.handleFormFieldBlurEvent);
|
||
formFieldElement.addEventListener(EVENTS.KEYUP, this.handleFormFieldKeyupEvent);
|
||
formFieldElement.addEventListener(EVENTS.CLICK, this.handleFormFieldClickEvent(formFieldElement));
|
||
}
|
||
/**
|
||
* Removes any cached form field element handlers that are encountered
|
||
* when setting up a form field element to present the inline menu.
|
||
*
|
||
* @param formFieldElement - The form field element to remove the cached handlers for.
|
||
*/
|
||
removeCachedFormFieldEventListeners(formFieldElement) {
|
||
const handlers = [EVENTS.INPUT, EVENTS.CLICK, EVENTS.FOCUS];
|
||
for (let index = 0; index < handlers.length; index++) {
|
||
const event = handlers[index];
|
||
const memoIndex = this.getFormFieldHandlerMemoIndex(formFieldElement, event);
|
||
const existingHandler = this.eventHandlersMemo[memoIndex];
|
||
if (!existingHandler) {
|
||
return;
|
||
}
|
||
formFieldElement.removeEventListener(event, existingHandler);
|
||
delete this.eventHandlersMemo[memoIndex];
|
||
}
|
||
}
|
||
/**
|
||
* Sets up listeners on the submit button that triggers a submission of the field's form.
|
||
*
|
||
* @param formFieldElement - The form field element to set up the submit button listeners for.
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
setupFormSubmissionEventListeners(formFieldElement, autofillFieldData) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!elementIsFillableFormField(formFieldElement) ||
|
||
autofillFieldData.inlineMenuFillType === CipherType.Card) {
|
||
return;
|
||
}
|
||
if (autofillFieldData.form) {
|
||
yield this.setupSubmitListenerOnFieldWithForms(formFieldElement);
|
||
return;
|
||
}
|
||
yield this.setupSubmitListenerOnFormlessField(formFieldElement);
|
||
return;
|
||
});
|
||
}
|
||
/**
|
||
* Sets up the submit listener on the form field element that contains a form element.
|
||
* Will establish on submit event listeners on the form element and click listeners on
|
||
* the submit button element that triggers the submission of the form.
|
||
*
|
||
* @param formFieldElement - The form field element to set up the submit listener for.
|
||
*/
|
||
setupSubmitListenerOnFieldWithForms(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const formElement = formFieldElement.form;
|
||
if (formElement && !this.formElements.has(formElement)) {
|
||
this.formElements.add(formElement);
|
||
formElement.addEventListener(EVENTS.SUBMIT, this.handleFormFieldSubmitEvent);
|
||
const closestSubmitButton = yield this.findSubmitButton(formElement);
|
||
// If we cannot find a submit button within the form, check for a submit button outside the form.
|
||
if (!closestSubmitButton) {
|
||
yield this.setupSubmitListenerOnFormlessField(formFieldElement);
|
||
return;
|
||
}
|
||
this.setupSubmitButtonEventListeners(closestSubmitButton);
|
||
return;
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Sets up the submit listener on the form field element that does not contain a form element.
|
||
* Will establish a submit button event listener on the closest formless submit button element.
|
||
*
|
||
* @param formFieldElement - The form field element to set up the submit listener for.
|
||
*/
|
||
setupSubmitListenerOnFormlessField(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (formFieldElement && !this.fieldsWithSubmitElements.has(formFieldElement)) {
|
||
const closestSubmitButton = yield this.findClosestFormlessSubmitButton(formFieldElement);
|
||
this.setupSubmitButtonEventListeners(closestSubmitButton);
|
||
}
|
||
return;
|
||
});
|
||
}
|
||
/**
|
||
* Finds the closest formless submit button element to the form field element.
|
||
*
|
||
* @param formFieldElement - The form field element to find the closest formless submit button for.
|
||
*/
|
||
findClosestFormlessSubmitButton(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
let currentElement = formFieldElement;
|
||
while (currentElement && currentElement.tagName !== "HTML") {
|
||
const submitButton = yield this.findSubmitButton(currentElement);
|
||
if (submitButton) {
|
||
this.formFieldElements.forEach((_, element) => {
|
||
if (currentElement.contains(element)) {
|
||
this.fieldsWithSubmitElements.set(element, submitButton);
|
||
}
|
||
});
|
||
return submitButton;
|
||
}
|
||
if (!currentElement.parentElement && currentElement.getRootNode() instanceof ShadowRoot) {
|
||
currentElement = currentElement.getRootNode().host;
|
||
continue;
|
||
}
|
||
currentElement = currentElement.parentElement;
|
||
}
|
||
return null;
|
||
});
|
||
}
|
||
/**
|
||
* Finds the submit button element within the provided element. Will attempt to find a generic
|
||
* submit element before attempting to find a button or button-like element.
|
||
*
|
||
* @param element - The element to find the submit button within.
|
||
*/
|
||
findSubmitButton(element) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const genericSubmitElement = yield this.querySubmitButtonElement(element, "[type='submit']", (node) => nodeIsTypeSubmitElement(node));
|
||
if (genericSubmitElement) {
|
||
return genericSubmitElement;
|
||
}
|
||
const submitButtonElement = yield this.querySubmitButtonElement(element, "button, [type='button']", (node) => nodeIsButtonElement(node));
|
||
if (submitButtonElement) {
|
||
return submitButtonElement;
|
||
}
|
||
// If the submit button is not a traditional button element, check for an anchor element that contains submission keywords.
|
||
const submitAnchorElement = yield this.querySubmitButtonElement(element, "a", (node) => nodeIsAnchorElement(node));
|
||
if (submitAnchorElement) {
|
||
return submitAnchorElement;
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Queries the provided element for a submit button element using the provided selector.
|
||
*
|
||
* @param element - The element to query for a submit button.
|
||
* @param selector - The selector to use to query the element for a submit button.
|
||
* @param treeWalkerFilter - The tree walker filter to use when querying the element.
|
||
*/
|
||
querySubmitButtonElement(element, selector, treeWalkerFilter) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const submitButtonElements = this.domQueryService.query(element, selector, treeWalkerFilter);
|
||
for (let index = 0; index < submitButtonElements.length; index++) {
|
||
const submitElement = submitButtonElements[index];
|
||
if (this.isElementSubmitButton(submitElement) &&
|
||
(yield this.domElementVisibilityService.isElementViewable(submitElement))) {
|
||
return submitElement;
|
||
}
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Determines if the provided element is a submit button element.
|
||
*
|
||
* @param element - The element to determine if it is a submit button.
|
||
*/
|
||
isElementSubmitButton(element) {
|
||
return (this.inlineMenuFieldQualificationService.isElementLoginSubmitButton(element) ||
|
||
this.inlineMenuFieldQualificationService.isElementChangePasswordSubmitButton(element));
|
||
}
|
||
/**
|
||
* Formats the memoIndex for the form field event handler.
|
||
*
|
||
* @param formFieldElement - The form field element to format the memo index for.
|
||
* @param event - The event to format the memo index for.
|
||
*/
|
||
getFormFieldHandlerMemoIndex(formFieldElement, event) {
|
||
return `${formFieldElement.opid}-${formFieldElement.id}-${event}-handler`;
|
||
}
|
||
/**
|
||
* Triggers a focus of the inline menu list, if it is visible. If the list is not visible,
|
||
* the inline menu will be opened and the list will be focused after a short delay. Ensures
|
||
* that the inline menu list is focused when the user presses the down arrow key.
|
||
*/
|
||
focusInlineMenuList() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (this.mostRecentlyFocusedField && !(yield this.isInlineMenuListVisible())) {
|
||
this.clearFocusInlineMenuListTimeout();
|
||
yield this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField);
|
||
yield this.sendExtensionMessage("openAutofillInlineMenu", { isOpeningFullInlineMenu: true });
|
||
this.focusInlineMenuListTimeout = globalThis.setTimeout(() => this.sendExtensionMessage("focusAutofillInlineMenuList"), 125);
|
||
return;
|
||
}
|
||
void this.sendExtensionMessage("focusAutofillInlineMenuList");
|
||
});
|
||
}
|
||
/**
|
||
* Triggers when the form field element receives an input event. This method will
|
||
* store the modified form element data for use when the user attempts to add a new
|
||
* vault item. It also acts to remove the inline menu list while the user is typing.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the input event.
|
||
*/
|
||
triggerFormFieldInput(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!elementIsFillableFormField(formFieldElement)) {
|
||
return;
|
||
}
|
||
this.storeModifiedFormElement(formFieldElement);
|
||
if (elementIsSelectElement(formFieldElement)) {
|
||
return;
|
||
}
|
||
yield this.sendExtensionMessage("closeAutofillInlineMenu", {
|
||
overlayElement: AutofillOverlayElement.List,
|
||
forceCloseInlineMenu: true,
|
||
});
|
||
if (!(formFieldElement === null || formFieldElement === void 0 ? void 0 : formFieldElement.value)) {
|
||
yield this.sendExtensionMessage("openAutofillInlineMenu");
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Stores the modified form element data for use when the user attempts to add a new
|
||
* vault item. This method will also store the most recently focused field, if it is
|
||
* not already stored.
|
||
*
|
||
* @param formFieldElement
|
||
* @private
|
||
*/
|
||
storeModifiedFormElement(formFieldElement) {
|
||
if (formFieldElement !== this.mostRecentlyFocusedField) {
|
||
void this.updateMostRecentlyFocusedField(formFieldElement);
|
||
}
|
||
const autofillFieldData = this.formFieldElements.get(formFieldElement);
|
||
if (!autofillFieldData) {
|
||
return;
|
||
}
|
||
if (!autofillFieldData.fieldQualifier) {
|
||
switch (autofillFieldData.inlineMenuFillType) {
|
||
case CipherType.Login:
|
||
case InlineMenuFillTypes.CurrentPasswordUpdate:
|
||
this.qualifyUserFilledField(autofillFieldData, this.loginFieldQualifiers);
|
||
break;
|
||
case InlineMenuFillTypes.AccountCreationUsername:
|
||
case InlineMenuFillTypes.PasswordGeneration:
|
||
this.qualifyUserFilledField(autofillFieldData, this.accountCreationFieldQualifiers);
|
||
break;
|
||
case CipherType.Card:
|
||
this.qualifyUserFilledField(autofillFieldData, this.cardFieldQualifiers);
|
||
break;
|
||
case CipherType.Identity:
|
||
this.qualifyUserFilledField(autofillFieldData, this.identityFieldQualifiers);
|
||
break;
|
||
}
|
||
}
|
||
this.storeQualifiedUserFilledField(formFieldElement, autofillFieldData);
|
||
}
|
||
/**
|
||
* Stores the qualified user filled filed to allow for referencing its value when adding a new vault item.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the input event.
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
storeQualifiedUserFilledField(formFieldElement, autofillFieldData) {
|
||
if (!autofillFieldData.fieldQualifier) {
|
||
return;
|
||
}
|
||
const clonedNode = formFieldElement.cloneNode(true);
|
||
const identityLoginFields = [
|
||
AutofillFieldQualifier.identityUsername,
|
||
AutofillFieldQualifier.identityEmail,
|
||
];
|
||
if (identityLoginFields.includes(autofillFieldData.fieldQualifier)) {
|
||
this.userFilledFields[AutofillFieldQualifier.username] = clonedNode;
|
||
}
|
||
this.userFilledFields[autofillFieldData.fieldQualifier] = clonedNode;
|
||
}
|
||
/**
|
||
* Triggers when the form field element receives a click event. This method will
|
||
* trigger the focused action for the form field element if the inline menu is not visible.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the click event.
|
||
*/
|
||
triggerFormFieldClickedAction(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if ((yield this.isInlineMenuButtonVisible()) || (yield this.isInlineMenuListVisible())) {
|
||
return;
|
||
}
|
||
yield this.triggerFormFieldFocusedAction(formFieldElement);
|
||
});
|
||
}
|
||
/**
|
||
* Triggers when the form field element receives a focus event. This method will
|
||
* update the most recently focused field and open the autofill inline menu if the
|
||
* autofill process is not currently active.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
*/
|
||
triggerFormFieldFocusedAction(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (yield this.isFieldCurrentlyFilling()) {
|
||
return;
|
||
}
|
||
if (this.pageDetailsUpdateRequired) {
|
||
yield this.sendExtensionMessage("bgCollectPageDetails", {
|
||
sender: "autofillOverlayContentService",
|
||
});
|
||
this.pageDetailsUpdateRequired = false;
|
||
}
|
||
if (elementIsSelectElement(formFieldElement)) {
|
||
yield this.sendExtensionMessage("closeAutofillInlineMenu", {
|
||
forceCloseInlineMenu: true,
|
||
});
|
||
return;
|
||
}
|
||
yield this.updateIsFieldCurrentlyFocused(true);
|
||
yield this.updateMostRecentlyFocusedField(formFieldElement);
|
||
yield this.sendExtensionMessage("openAutofillInlineMenu");
|
||
});
|
||
}
|
||
/**
|
||
* Updates the data used to position the inline menu elements in relation
|
||
* to the most recently focused form field.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
*/
|
||
updateMostRecentlyFocusedField(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!formFieldElement ||
|
||
!elementIsFillableFormField(formFieldElement) ||
|
||
elementIsSelectElement(formFieldElement)) {
|
||
return;
|
||
}
|
||
this.mostRecentlyFocusedField = formFieldElement;
|
||
const { paddingRight, paddingLeft } = globalThis.getComputedStyle(formFieldElement);
|
||
const { width, height, top, left } = yield this.getMostRecentlyFocusedFieldRects(formFieldElement);
|
||
const autofillFieldData = this.formFieldElements.get(formFieldElement);
|
||
this.focusedFieldData = {
|
||
focusedFieldStyles: { paddingRight, paddingLeft },
|
||
focusedFieldRects: { width, height, top, left },
|
||
inlineMenuFillType: autofillFieldData === null || autofillFieldData === void 0 ? void 0 : autofillFieldData.inlineMenuFillType,
|
||
showPasskeys: !!(autofillFieldData === null || autofillFieldData === void 0 ? void 0 : autofillFieldData.showPasskeys),
|
||
accountCreationFieldType: autofillFieldData === null || autofillFieldData === void 0 ? void 0 : autofillFieldData.accountCreationFieldType,
|
||
focusedFieldForm: autofillFieldData === null || autofillFieldData === void 0 ? void 0 : autofillFieldData.form,
|
||
focusedFieldOpid: autofillFieldData === null || autofillFieldData === void 0 ? void 0 : autofillFieldData.opid,
|
||
};
|
||
const allFields = this.formFieldElements;
|
||
const allFieldsRect = [];
|
||
for (const key of allFields.keys()) {
|
||
const rect = yield this.getMostRecentlyFocusedFieldRects(key);
|
||
allFieldsRect.push(Object.assign(Object.assign({}, allFields.get(key)), { rect })); // Add the combined result to the array
|
||
}
|
||
yield this.sendExtensionMessage("updateFocusedFieldData", {
|
||
focusedFieldData: this.focusedFieldData,
|
||
allFieldsRect,
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Gets the bounding client rects for the most recently focused field. This method will
|
||
* attempt to use an intersection observer to get the most recently focused field's
|
||
* bounding client rects. If the intersection observer is not supported, or the
|
||
* intersection observer does not return a valid bounding client rect, the form
|
||
* field element's bounding client rect will be used.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
*/
|
||
getMostRecentlyFocusedFieldRects(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const focusedFieldRects = yield this.getBoundingClientRectFromIntersectionObserver(formFieldElement);
|
||
if (focusedFieldRects) {
|
||
return focusedFieldRects;
|
||
}
|
||
return formFieldElement.getBoundingClientRect();
|
||
});
|
||
}
|
||
/**
|
||
* Gets the bounds of the form field element from the IntersectionObserver API.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
*/
|
||
getBoundingClientRectFromIntersectionObserver(formFieldElement) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!("IntersectionObserver" in globalThis) && !("IntersectionObserverEntry" in globalThis)) {
|
||
return null;
|
||
}
|
||
return new Promise((resolve) => {
|
||
const intersectionObserver = new IntersectionObserver((entries) => {
|
||
var _a;
|
||
let fieldBoundingClientRects = (_a = entries[0]) === null || _a === void 0 ? void 0 : _a.boundingClientRect;
|
||
if (!(fieldBoundingClientRects === null || fieldBoundingClientRects === void 0 ? void 0 : fieldBoundingClientRects.width) || !fieldBoundingClientRects.height) {
|
||
fieldBoundingClientRects = null;
|
||
}
|
||
intersectionObserver.disconnect();
|
||
resolve(fieldBoundingClientRects);
|
||
}, {
|
||
root: globalThis.document.body,
|
||
rootMargin: "0px",
|
||
threshold: 0.9999, // Safari doesn't seem to function properly with a threshold of 1
|
||
});
|
||
intersectionObserver.observe(formFieldElement);
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Identifies if the field should have the autofill inline menu setup on it. Currently, this is mainly
|
||
* determined by whether the field correlates with a login cipher. This method will need to be
|
||
* updated in the future to support other types of forms.
|
||
*
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
* @param pageDetails - The collected page details from the tab.
|
||
*/
|
||
isIgnoredField(autofillFieldData, pageDetails) {
|
||
if (this.ignoredFieldTypes.has(autofillFieldData.type)) {
|
||
return true;
|
||
}
|
||
if (this.inlineMenuFieldQualificationService.isFieldForLoginForm(autofillFieldData, pageDetails)) {
|
||
void this.setQualifiedLoginFillType(autofillFieldData);
|
||
return false;
|
||
}
|
||
if (this.showInlineMenuCards &&
|
||
this.inlineMenuFieldQualificationService.isFieldForCreditCardForm(autofillFieldData, pageDetails)) {
|
||
autofillFieldData.inlineMenuFillType = CipherType.Card;
|
||
return false;
|
||
}
|
||
if (this.inlineMenuFieldQualificationService.isFieldForAccountCreationForm(autofillFieldData, pageDetails)) {
|
||
const hasUsernameField = [...this.formFieldElements.values()].some((field) => this.inlineMenuFieldQualificationService.isUsernameField(field));
|
||
if (hasUsernameField) {
|
||
void this.setQualifiedLoginFillType(autofillFieldData);
|
||
}
|
||
else {
|
||
this.setQualifiedAccountCreationFillType(autofillFieldData);
|
||
}
|
||
return false;
|
||
}
|
||
if (this.showInlineMenuIdentities &&
|
||
this.inlineMenuFieldQualificationService.isFieldForIdentityForm(autofillFieldData, pageDetails)) {
|
||
autofillFieldData.inlineMenuFillType = CipherType.Identity;
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
/**
|
||
* Sets the autofill field data that indicates this field is part of a login form
|
||
*
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
setQualifiedLoginFillType(autofillFieldData) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
// Check if this is a current password field in a password change form
|
||
if (this.inlineMenuFieldQualificationService.isUpdateCurrentPasswordField(autofillFieldData)) {
|
||
autofillFieldData.inlineMenuFillType = InlineMenuFillTypes.CurrentPasswordUpdate;
|
||
return;
|
||
}
|
||
autofillFieldData.inlineMenuFillType = CipherType.Login;
|
||
autofillFieldData.showPasskeys = autofillFieldData.autoCompleteType.includes("webauthn");
|
||
this.qualifyAccountCreationFieldType(autofillFieldData);
|
||
});
|
||
}
|
||
/**
|
||
* Sets the autofill field data that indicates this field is part of an account creation or update form.
|
||
*
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
setQualifiedAccountCreationFillType(autofillFieldData) {
|
||
if (this.inlineMenuFieldQualificationService.isNewPasswordField(autofillFieldData)) {
|
||
autofillFieldData.inlineMenuFillType = InlineMenuFillTypes.PasswordGeneration;
|
||
this.qualifyAccountCreationFieldType(autofillFieldData);
|
||
return;
|
||
}
|
||
if (this.inlineMenuFieldQualificationService.isUpdateCurrentPasswordField(autofillFieldData)) {
|
||
autofillFieldData.inlineMenuFillType = InlineMenuFillTypes.CurrentPasswordUpdate;
|
||
return;
|
||
}
|
||
if (this.inlineMenuFieldQualificationService.isUsernameField(autofillFieldData)) {
|
||
autofillFieldData.inlineMenuFillType = InlineMenuFillTypes.AccountCreationUsername;
|
||
this.qualifyAccountCreationFieldType(autofillFieldData);
|
||
}
|
||
}
|
||
/**
|
||
* Sets the account creation field type for the autofill field data based on the field's attributes.
|
||
*
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
qualifyAccountCreationFieldType(autofillFieldData) {
|
||
if (this.inlineMenuFieldQualificationService.isTotpField(autofillFieldData)) {
|
||
autofillFieldData.accountCreationFieldType = InlineMenuAccountCreationFieldType.Totp;
|
||
return;
|
||
}
|
||
if (!this.inlineMenuFieldQualificationService.isUsernameField(autofillFieldData)) {
|
||
autofillFieldData.accountCreationFieldType = InlineMenuAccountCreationFieldType.Password;
|
||
return;
|
||
}
|
||
if (!this.showInlineMenuIdentities) {
|
||
return;
|
||
}
|
||
if (this.inlineMenuFieldQualificationService.isEmailField(autofillFieldData)) {
|
||
autofillFieldData.accountCreationFieldType = InlineMenuAccountCreationFieldType.Email;
|
||
return;
|
||
}
|
||
autofillFieldData.accountCreationFieldType = InlineMenuAccountCreationFieldType.Text;
|
||
}
|
||
/**
|
||
* Validates whether a field is considered to be "hidden" based on the field's attributes.
|
||
* If the field is hidden, a fallback listener will be set up to ensure that the
|
||
* field will have the inline menu set up on it when it becomes visible.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
isHiddenField(formFieldElement, autofillFieldData) {
|
||
if (!autofillFieldData.readonly && !autofillFieldData.disabled && autofillFieldData.viewable) {
|
||
this.removeHiddenFieldFallbackListener(formFieldElement);
|
||
return false;
|
||
}
|
||
this.setupHiddenFieldFallbackListener(formFieldElement, autofillFieldData);
|
||
return true;
|
||
}
|
||
/**
|
||
* Sets up a fallback listener that will facilitate setting up the
|
||
* inline menu on the field when it becomes visible and focused.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
setupHiddenFieldFallbackListener(formFieldElement, autofillFieldData) {
|
||
this.hiddenFormFieldElements.set(formFieldElement, autofillFieldData);
|
||
formFieldElement.addEventListener(EVENTS.FOCUS, this.handleHiddenFieldFocusEvent);
|
||
formFieldElement.addEventListener(EVENTS.INPUT, this.handleHiddenFieldInputEvent);
|
||
}
|
||
/**
|
||
* Removes the fallback listener that facilitates setting up the inline
|
||
* menu on the field when it becomes visible and focused.
|
||
*
|
||
* @param formFieldElement - The form field element that triggered the focus event.
|
||
*/
|
||
removeHiddenFieldFallbackListener(formFieldElement) {
|
||
formFieldElement.removeEventListener(EVENTS.FOCUS, this.handleHiddenFieldFocusEvent);
|
||
formFieldElement.removeEventListener(EVENTS.INPUT, this.handleHiddenFieldInputEvent);
|
||
this.hiddenFormFieldElements.delete(formFieldElement);
|
||
}
|
||
/**
|
||
* Sets up the inline menu on a qualified form field element.
|
||
*
|
||
* @param formFieldElement - The form field element to set up the inline menu on.
|
||
* @param autofillFieldData - Autofill field data captured from the form field element.
|
||
*/
|
||
setupOverlayListenersOnQualifiedField(formFieldElement, autofillFieldData) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
this.formFieldElements.set(formFieldElement, autofillFieldData);
|
||
if (elementIsFillableFormField(formFieldElement) && !!formFieldElement.value) {
|
||
this.storeModifiedFormElement(formFieldElement);
|
||
}
|
||
this.setupFormFieldElementEventListeners(formFieldElement);
|
||
yield this.setupFormSubmissionEventListeners(formFieldElement, autofillFieldData);
|
||
if (globalThis.document.hasFocus() &&
|
||
this.getRootNodeActiveElement(formFieldElement) === formFieldElement) {
|
||
yield this.triggerFormFieldFocusedAction(formFieldElement);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Queries the background script for the autofill inline menu's Cards visibility setting.
|
||
* If the setting is not found, a default value of true will be used
|
||
* @private
|
||
*/
|
||
getInlineMenuCardsVisibility() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const inlineMenuCardsVisibility = yield this.sendExtensionMessage("getInlineMenuCardsVisibility");
|
||
this.showInlineMenuCards = inlineMenuCardsVisibility !== null && inlineMenuCardsVisibility !== void 0 ? inlineMenuCardsVisibility : true;
|
||
});
|
||
}
|
||
/**
|
||
* Queries the background script for the autofill inline menu's Identities visibility setting.
|
||
* If the setting is not found, a default value of true will be used
|
||
* @private
|
||
*/
|
||
getInlineMenuIdentitiesVisibility() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const inlineMenuIdentitiesVisibility = yield this.sendExtensionMessage("getInlineMenuIdentitiesVisibility");
|
||
this.showInlineMenuIdentities = inlineMenuIdentitiesVisibility !== null && inlineMenuIdentitiesVisibility !== void 0 ? inlineMenuIdentitiesVisibility : true;
|
||
});
|
||
}
|
||
/**
|
||
* Indicates whether the most recently focused field has a value.
|
||
*/
|
||
mostRecentlyFocusedFieldHasValue() {
|
||
var _a;
|
||
return Boolean((_a = this.mostRecentlyFocusedField) === null || _a === void 0 ? void 0 : _a.value);
|
||
}
|
||
/**
|
||
* Checks if a field is currently filling within an frame in the tab.
|
||
*/
|
||
isFieldCurrentlyFilling() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
return (yield this.sendExtensionMessage("checkIsFieldCurrentlyFilling")) === true;
|
||
});
|
||
}
|
||
/**
|
||
* Checks if the inline menu button is visible at the top frame.
|
||
*/
|
||
isInlineMenuButtonVisible() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
return (yield this.sendExtensionMessage("checkIsAutofillInlineMenuButtonVisible")) === true;
|
||
});
|
||
}
|
||
/**
|
||
* Checks if the inline menu list if visible at the top frame.
|
||
*/
|
||
isInlineMenuListVisible() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
return (yield this.sendExtensionMessage("checkIsAutofillInlineMenuListVisible")) === true;
|
||
});
|
||
}
|
||
/**
|
||
* Checks if the field is currently focused within the top frame.
|
||
*/
|
||
isFieldCurrentlyFocused() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
return (yield this.sendExtensionMessage("checkIsFieldCurrentlyFocused")) === true;
|
||
});
|
||
}
|
||
/**
|
||
* Gets the root node of the passed element and returns the active element within that root node.
|
||
*
|
||
* @param element - The element to get the root node active element for.
|
||
*/
|
||
getRootNodeActiveElement(element) {
|
||
if (!element) {
|
||
return null;
|
||
}
|
||
const documentRoot = element.getRootNode();
|
||
return documentRoot === null || documentRoot === void 0 ? void 0 : documentRoot.activeElement;
|
||
}
|
||
/**
|
||
* Queries all iframe elements within the document and returns the
|
||
* sub frame offsets for each iframe element.
|
||
*
|
||
* @param message - The message object from the extension.
|
||
*/
|
||
getSubFrameOffsets(message) {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const { subFrameUrl } = message;
|
||
const subFrameUrlVariations = this.getSubFrameUrlVariations(subFrameUrl);
|
||
if (!subFrameUrlVariations) {
|
||
return null;
|
||
}
|
||
let iframeElement = null;
|
||
const iframeElements = globalThis.document.getElementsByTagName("iframe");
|
||
for (let iframeIndex = 0; iframeIndex < iframeElements.length; iframeIndex++) {
|
||
const iframe = iframeElements[iframeIndex];
|
||
if (!subFrameUrlVariations.has(iframe.src)) {
|
||
continue;
|
||
}
|
||
if (iframeElement) {
|
||
return null;
|
||
}
|
||
iframeElement = iframe;
|
||
}
|
||
if (!iframeElement) {
|
||
return null;
|
||
}
|
||
return this.calculateSubFrameOffsets(iframeElement, subFrameUrl);
|
||
});
|
||
}
|
||
/**
|
||
* Returns a set of all possible URL variations for the sub frame URL.
|
||
*
|
||
* @param subFrameUrl - The URL of the sub frame.
|
||
*/
|
||
getSubFrameUrlVariations(subFrameUrl) {
|
||
try {
|
||
const url = new URL(subFrameUrl, globalThis.location.href);
|
||
const pathAndHash = url.pathname + url.hash;
|
||
const pathAndSearch = url.pathname + url.search;
|
||
const pathSearchAndHash = pathAndSearch + url.hash;
|
||
const pathNameWithoutTrailingSlash = url.pathname.replace(/\/$/, "");
|
||
const pathWithoutTrailingSlashAndHash = pathNameWithoutTrailingSlash + url.hash;
|
||
const pathWithoutTrailingSlashAndSearch = pathNameWithoutTrailingSlash + url.search;
|
||
const pathWithoutTrailingSlashSearchAndHash = pathWithoutTrailingSlashAndSearch + url.hash;
|
||
return new Set([
|
||
url.href,
|
||
url.href.replace(/\/$/, ""),
|
||
url.pathname,
|
||
pathAndHash,
|
||
pathAndSearch,
|
||
pathSearchAndHash,
|
||
pathNameWithoutTrailingSlash,
|
||
pathWithoutTrailingSlashAndHash,
|
||
pathWithoutTrailingSlashAndSearch,
|
||
pathWithoutTrailingSlashSearchAndHash,
|
||
url.hostname + url.pathname,
|
||
url.hostname + pathAndHash,
|
||
url.hostname + pathAndSearch,
|
||
url.hostname + pathSearchAndHash,
|
||
url.hostname + pathNameWithoutTrailingSlash,
|
||
url.hostname + pathWithoutTrailingSlashAndHash,
|
||
url.hostname + pathWithoutTrailingSlashAndSearch,
|
||
url.hostname + pathWithoutTrailingSlashSearchAndHash,
|
||
url.origin + url.pathname,
|
||
url.origin + pathAndHash,
|
||
url.origin + pathAndSearch,
|
||
url.origin + pathSearchAndHash,
|
||
url.origin + pathNameWithoutTrailingSlash,
|
||
url.origin + pathWithoutTrailingSlashAndHash,
|
||
url.origin + pathWithoutTrailingSlashAndSearch,
|
||
url.origin + pathWithoutTrailingSlashSearchAndHash,
|
||
]);
|
||
// FIXME: Remove when updating file. Eslint update
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
}
|
||
catch (_error) {
|
||
return null;
|
||
}
|
||
}
|
||
/**
|
||
* Posts a message to the parent frame to calculate the sub frame offset of the current frame.
|
||
*
|
||
* @param message - The message object from the extension.
|
||
*/
|
||
getSubFrameOffsetsFromWindowMessage(message) {
|
||
globalThis.parent.postMessage({
|
||
command: "calculateSubFramePositioning",
|
||
subFrameData: {
|
||
url: window.location.href,
|
||
frameId: message.subFrameId,
|
||
left: 0,
|
||
top: 0,
|
||
parentFrameIds: [0],
|
||
subFrameDepth: 0,
|
||
},
|
||
}, "*");
|
||
}
|
||
/**
|
||
* Calculates the bounding rect for the queried frame and returns the
|
||
* offset data for the sub frame.
|
||
*
|
||
* @param iframeElement - The iframe element to calculate the sub frame offsets for.
|
||
* @param subFrameUrl - The URL of the sub frame.
|
||
* @param frameId - The frame ID of the sub frame.
|
||
*/
|
||
calculateSubFrameOffsets(iframeElement, subFrameUrl, frameId) {
|
||
const iframeRect = iframeElement.getBoundingClientRect();
|
||
const iframeRectHasSize = iframeRect.width > 0 && iframeRect.height > 0;
|
||
const iframeStyles = globalThis.getComputedStyle(iframeElement);
|
||
const paddingLeft = parseInt(iframeStyles.getPropertyValue("padding-left")) || 0;
|
||
const paddingTop = parseInt(iframeStyles.getPropertyValue("padding-top")) || 0;
|
||
const borderWidthLeft = parseInt(iframeStyles.getPropertyValue("border-left-width")) || 0;
|
||
const borderWidthTop = parseInt(iframeStyles.getPropertyValue("border-top-width")) || 0;
|
||
if (!iframeRect || !iframeRectHasSize || !iframeElement.isConnected) {
|
||
return null;
|
||
}
|
||
return {
|
||
url: subFrameUrl,
|
||
frameId,
|
||
top: iframeRect.top + paddingTop + borderWidthTop,
|
||
left: iframeRect.left + paddingLeft + borderWidthLeft,
|
||
};
|
||
}
|
||
/**
|
||
* Sets up event listeners that facilitate repositioning
|
||
* the overlay elements on scroll or resize.
|
||
*/
|
||
setOverlayRepositionEventListeners() {
|
||
let currentScrollY = globalThis.scrollY;
|
||
let currentScrollX = globalThis.scrollX;
|
||
let mostRecentTargetScrollY = 0;
|
||
const repositionHandler = this.useEventHandlersMemo(throttle(this.handleOverlayRepositionEvent, 250), AUTOFILL_OVERLAY_HANDLE_REPOSITION);
|
||
const eventTargetContainsFocusedField = (eventTarget) => {
|
||
if (typeof eventTarget.contains !== "function") {
|
||
return false;
|
||
}
|
||
const targetScrollY = eventTarget.scrollTop;
|
||
if (targetScrollY === mostRecentTargetScrollY) {
|
||
return false;
|
||
}
|
||
if (eventTarget === this.mostRecentlyFocusedField ||
|
||
eventTarget.contains(this.mostRecentlyFocusedField)) {
|
||
mostRecentTargetScrollY = targetScrollY;
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
const scrollHandler = this.useEventHandlersMemo(throttle((event) => autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (currentScrollY !== globalThis.scrollY ||
|
||
currentScrollX !== globalThis.scrollX ||
|
||
eventTargetContainsFocusedField(event.target)) {
|
||
repositionHandler(event);
|
||
}
|
||
currentScrollY = globalThis.scrollY;
|
||
currentScrollX = globalThis.scrollX;
|
||
}), 50), AUTOFILL_OVERLAY_HANDLE_SCROLL);
|
||
globalThis.addEventListener(EVENTS.SCROLL, scrollHandler, {
|
||
capture: true,
|
||
passive: true,
|
||
});
|
||
globalThis.addEventListener(EVENTS.RESIZE, repositionHandler);
|
||
}
|
||
/**
|
||
* Removes the listeners that facilitate repositioning
|
||
* the overlay elements on scroll or resize.
|
||
*/
|
||
removeOverlayRepositionEventListeners() {
|
||
globalThis.removeEventListener(EVENTS.SCROLL, this.eventHandlersMemo[AUTOFILL_OVERLAY_HANDLE_SCROLL], {
|
||
capture: true,
|
||
});
|
||
globalThis.removeEventListener(EVENTS.RESIZE, this.eventHandlersMemo[AUTOFILL_OVERLAY_HANDLE_REPOSITION]);
|
||
delete this.eventHandlersMemo[AUTOFILL_OVERLAY_HANDLE_SCROLL];
|
||
delete this.eventHandlersMemo[AUTOFILL_OVERLAY_HANDLE_REPOSITION];
|
||
}
|
||
/**
|
||
* Triggers an update in the most recently focused field's data and returns
|
||
* whether the field is within the viewport bounds. If not within the bounds
|
||
* of the viewport, the inline menu will be closed.
|
||
*/
|
||
checkIsMostRecentlyFocusedFieldWithinViewport() {
|
||
return autofill_overlay_content_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c, _d;
|
||
yield this.updateMostRecentlyFocusedField(this.mostRecentlyFocusedField);
|
||
const focusedFieldRectsTop = (_b = (_a = this.focusedFieldData) === null || _a === void 0 ? void 0 : _a.focusedFieldRects) === null || _b === void 0 ? void 0 : _b.top;
|
||
const focusedFieldRectsBottom = focusedFieldRectsTop + ((_d = (_c = this.focusedFieldData) === null || _c === void 0 ? void 0 : _c.focusedFieldRects) === null || _d === void 0 ? void 0 : _d.height);
|
||
const viewportHeight = globalThis.innerHeight + globalThis.scrollY;
|
||
return (!globalThis.isNaN(focusedFieldRectsTop) &&
|
||
focusedFieldRectsTop >= 0 &&
|
||
focusedFieldRectsTop < viewportHeight &&
|
||
focusedFieldRectsBottom <= viewportHeight);
|
||
});
|
||
}
|
||
/**
|
||
* Clears the timeout that triggers a debounced focus of the inline menu list.
|
||
*/
|
||
clearFocusInlineMenuListTimeout() {
|
||
if (this.focusInlineMenuListTimeout) {
|
||
globalThis.clearTimeout(this.focusInlineMenuListTimeout);
|
||
}
|
||
}
|
||
/**
|
||
* Clears the timeout that triggers the closing of the inline menu on a focus redirection.
|
||
*/
|
||
clearCloseInlineMenuOnRedirectTimeout() {
|
||
if (this.closeInlineMenuOnRedirectTimeout) {
|
||
globalThis.clearTimeout(this.closeInlineMenuOnRedirectTimeout);
|
||
}
|
||
}
|
||
/**
|
||
* Destroys the autofill overlay content service. This method will
|
||
* disconnect the mutation observers and remove all event listeners.
|
||
*/
|
||
destroy() {
|
||
this.clearFocusInlineMenuListTimeout();
|
||
this.clearCloseInlineMenuOnRedirectTimeout();
|
||
this.formFieldElements.forEach((_autofillField, formFieldElement) => {
|
||
this.removeCachedFormFieldEventListeners(formFieldElement);
|
||
formFieldElement.removeEventListener(EVENTS.BLUR, this.handleFormFieldBlurEvent);
|
||
formFieldElement.removeEventListener(EVENTS.KEYUP, this.handleFormFieldKeyupEvent);
|
||
this.formFieldElements.delete(formFieldElement);
|
||
});
|
||
this.clearUserFilledFields();
|
||
this.userFilledFields = null;
|
||
globalThis.removeEventListener(EVENTS.MESSAGE, this.handleWindowMessageEvent);
|
||
globalThis.document.removeEventListener(EVENTS.VISIBILITYCHANGE, this.handleVisibilityChangeEvent);
|
||
globalThis.removeEventListener(EVENTS.FOCUSOUT, this.handleFormFieldBlurEvent);
|
||
this.removeOverlayRepositionEventListeners();
|
||
this.removeRebuildSubFrameOffsetsListeners();
|
||
this.removeSubFrameFocusOutListeners();
|
||
}
|
||
}
|
||
|
||
;// ./src/autofill/services/dom-element-visibility.service.ts
|
||
var dom_element_visibility_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
class DomElementVisibilityService {
|
||
constructor(inlineMenuContentService) {
|
||
this.inlineMenuContentService = inlineMenuContentService;
|
||
this.cachedComputedStyle = null;
|
||
}
|
||
/**
|
||
* Checks if an element is viewable. This is done by checking if the element is within the
|
||
* viewport bounds, not hidden by CSS, and not hidden behind another element.
|
||
* @param element
|
||
*/
|
||
isElementViewable(element) {
|
||
return dom_element_visibility_service_awaiter(this, void 0, void 0, function* () {
|
||
const elementBoundingClientRect = element.getBoundingClientRect();
|
||
if (this.isElementOutsideViewportBounds(element, elementBoundingClientRect) ||
|
||
this.isElementHiddenByCss(element)) {
|
||
return false;
|
||
}
|
||
return this.formFieldIsNotHiddenBehindAnotherElement(element, elementBoundingClientRect);
|
||
});
|
||
}
|
||
/**
|
||
* Check if the target element is hidden using CSS. This is done by checking the opacity, display,
|
||
* visibility, and clip-path CSS properties of the element. We also check the opacity of all
|
||
* parent elements to ensure that the target element is not hidden by a parent element.
|
||
* @param {HTMLElement} element
|
||
* @returns {boolean}
|
||
* @public
|
||
*/
|
||
isElementHiddenByCss(element) {
|
||
this.cachedComputedStyle = null;
|
||
if (this.isElementInvisible(element) ||
|
||
this.isElementNotDisplayed(element) ||
|
||
this.isElementNotVisible(element) ||
|
||
this.isElementClipped(element)) {
|
||
return true;
|
||
}
|
||
let parentElement = element.parentElement;
|
||
while (parentElement && parentElement !== element.ownerDocument.documentElement) {
|
||
this.cachedComputedStyle = null;
|
||
if (this.isElementInvisible(parentElement)) {
|
||
return true;
|
||
}
|
||
parentElement = parentElement.parentElement;
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Gets the computed style of a given element, will only calculate the computed
|
||
* style if the element's style has not been previously cached.
|
||
* @param {HTMLElement} element
|
||
* @param {string} styleProperty
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
getElementStyle(element, styleProperty) {
|
||
if (!this.cachedComputedStyle) {
|
||
this.cachedComputedStyle = (element.ownerDocument.defaultView || globalThis).getComputedStyle(element);
|
||
}
|
||
return this.cachedComputedStyle.getPropertyValue(styleProperty);
|
||
}
|
||
/**
|
||
* Checks if the opacity of the target element is less than 0.1.
|
||
* @param {HTMLElement} element
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isElementInvisible(element) {
|
||
return parseFloat(this.getElementStyle(element, "opacity")) < 0.1;
|
||
}
|
||
/**
|
||
* Checks if the target element has a display property of none.
|
||
* @param {HTMLElement} element
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isElementNotDisplayed(element) {
|
||
return this.getElementStyle(element, "display") === "none";
|
||
}
|
||
/**
|
||
* Checks if the target element has a visibility property of hidden or collapse.
|
||
* @param {HTMLElement} element
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isElementNotVisible(element) {
|
||
return new Set(["hidden", "collapse"]).has(this.getElementStyle(element, "visibility"));
|
||
}
|
||
/**
|
||
* Checks if the target element has a clip-path property that hides the element.
|
||
* @param {HTMLElement} element
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isElementClipped(element) {
|
||
return new Set([
|
||
"inset(50%)",
|
||
"inset(100%)",
|
||
"circle(0)",
|
||
"circle(0px)",
|
||
"circle(0px at 50% 50%)",
|
||
"polygon(0 0, 0 0, 0 0, 0 0)",
|
||
"polygon(0px 0px, 0px 0px, 0px 0px, 0px 0px)",
|
||
]).has(this.getElementStyle(element, "clipPath"));
|
||
}
|
||
/**
|
||
* Checks if the target element is outside the viewport bounds. This is done by checking if the
|
||
* element is too small or is overflowing the viewport bounds.
|
||
* @param {HTMLElement} targetElement
|
||
* @param {DOMRectReadOnly | null} targetElementBoundingClientRect
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isElementOutsideViewportBounds(targetElement, targetElementBoundingClientRect = null) {
|
||
const documentElement = targetElement.ownerDocument.documentElement;
|
||
const documentElementWidth = documentElement.scrollWidth;
|
||
const documentElementHeight = documentElement.scrollHeight;
|
||
const elementBoundingClientRect = targetElementBoundingClientRect || targetElement.getBoundingClientRect();
|
||
const elementTopOffset = elementBoundingClientRect.top - documentElement.clientTop;
|
||
const elementLeftOffset = elementBoundingClientRect.left - documentElement.clientLeft;
|
||
const isElementSizeInsufficient = elementBoundingClientRect.width < 10 || elementBoundingClientRect.height < 10;
|
||
const isElementOverflowingLeftViewport = elementLeftOffset < 0;
|
||
const isElementOverflowingRightViewport = elementLeftOffset + elementBoundingClientRect.width > documentElementWidth;
|
||
const isElementOverflowingTopViewport = elementTopOffset < 0;
|
||
const isElementOverflowingBottomViewport = elementTopOffset + elementBoundingClientRect.height > documentElementHeight;
|
||
return (isElementSizeInsufficient ||
|
||
isElementOverflowingLeftViewport ||
|
||
isElementOverflowingRightViewport ||
|
||
isElementOverflowingTopViewport ||
|
||
isElementOverflowingBottomViewport);
|
||
}
|
||
/**
|
||
* Checks if a passed FormField is not hidden behind another element. This is done by
|
||
* checking if the element at the center point of the FormField is the FormField itself
|
||
* or one of its labels.
|
||
* @param {FormFieldElement} targetElement
|
||
* @param {DOMRectReadOnly | null} targetElementBoundingClientRect
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
formFieldIsNotHiddenBehindAnotherElement(targetElement, targetElementBoundingClientRect = null) {
|
||
var _a, _b;
|
||
const elementBoundingClientRect = targetElementBoundingClientRect || targetElement.getBoundingClientRect();
|
||
const elementRootNode = targetElement.getRootNode();
|
||
const rootElement = elementRootNode instanceof ShadowRoot ? elementRootNode : targetElement.ownerDocument;
|
||
const elementAtCenterPoint = rootElement.elementFromPoint(elementBoundingClientRect.left + elementBoundingClientRect.width / 2, elementBoundingClientRect.top + elementBoundingClientRect.height / 2);
|
||
if (elementAtCenterPoint === targetElement) {
|
||
return true;
|
||
}
|
||
if ((_a = this.inlineMenuContentService) === null || _a === void 0 ? void 0 : _a.isElementInlineMenu(elementAtCenterPoint)) {
|
||
return true;
|
||
}
|
||
const targetElementLabelsSet = new Set(targetElement.labels);
|
||
if (targetElementLabelsSet.has(elementAtCenterPoint)) {
|
||
return true;
|
||
}
|
||
const closestParentLabel = (_b = elementAtCenterPoint === null || elementAtCenterPoint === void 0 ? void 0 : elementAtCenterPoint.parentElement) === null || _b === void 0 ? void 0 : _b.closest("label");
|
||
return closestParentLabel ? targetElementLabelsSet.has(closestParentLabel) : false;
|
||
}
|
||
}
|
||
/* harmony default export */ var dom_element_visibility_service = (DomElementVisibilityService);
|
||
|
||
;// ./src/autofill/services/dom-query.service.ts
|
||
var dom_query_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
class DomQueryService {
|
||
constructor() {
|
||
this.ignoredTreeWalkerNodes = new Set([
|
||
"svg",
|
||
"script",
|
||
"noscript",
|
||
"head",
|
||
"style",
|
||
"link",
|
||
"meta",
|
||
"title",
|
||
"base",
|
||
"img",
|
||
"picture",
|
||
"video",
|
||
"audio",
|
||
"object",
|
||
"source",
|
||
"track",
|
||
"param",
|
||
"map",
|
||
"area",
|
||
]);
|
||
/**
|
||
* Checks if the page contains any shadow DOM elements.
|
||
*/
|
||
this.checkPageContainsShadowDom = () => {
|
||
this.pageContainsShadowDom = this.queryShadowRoots(globalThis.document.body, true).length > 0;
|
||
};
|
||
void this.init();
|
||
}
|
||
/**
|
||
* Sets up a query that will trigger a deepQuery of the DOM, querying all elements that match the given query string.
|
||
* If the deepQuery fails or reaches a max recursion depth, it will fall back to a treeWalker query.
|
||
*
|
||
* @param root - The root element to start the query from
|
||
* @param queryString - The query string to match elements against
|
||
* @param treeWalkerFilter - The filter callback to use for the treeWalker query
|
||
* @param mutationObserver - The MutationObserver to use for observing shadow roots
|
||
* @param forceDeepQueryAttempt - Whether to force a deep query attempt
|
||
* @param ignoredTreeWalkerNodesOverride - An optional set of node names to ignore when using the treeWalker strategy
|
||
*/
|
||
query(root, queryString, treeWalkerFilter, mutationObserver, forceDeepQueryAttempt, ignoredTreeWalkerNodesOverride) {
|
||
const ignoredTreeWalkerNodes = ignoredTreeWalkerNodesOverride || this.ignoredTreeWalkerNodes;
|
||
if (!forceDeepQueryAttempt) {
|
||
return this.queryAllTreeWalkerNodes(root, treeWalkerFilter, ignoredTreeWalkerNodes, mutationObserver);
|
||
}
|
||
try {
|
||
return this.deepQueryElements(root, queryString, mutationObserver);
|
||
}
|
||
catch (_a) {
|
||
return this.queryAllTreeWalkerNodes(root, treeWalkerFilter, ignoredTreeWalkerNodes, mutationObserver);
|
||
}
|
||
}
|
||
/**
|
||
* Initializes the DomQueryService, checking for the presence of shadow DOM elements on the page.
|
||
*/
|
||
init() {
|
||
return dom_query_service_awaiter(this, void 0, void 0, function* () {
|
||
if (globalThis.document.readyState === "complete") {
|
||
this.checkPageContainsShadowDom();
|
||
return;
|
||
}
|
||
globalThis.addEventListener(EVENTS.LOAD, this.checkPageContainsShadowDom);
|
||
});
|
||
}
|
||
/**
|
||
* Queries all elements in the DOM that match the given query string.
|
||
* Also, recursively queries all shadow roots for the element.
|
||
*
|
||
* @param root - The root element to start the query from
|
||
* @param queryString - The query string to match elements against
|
||
* @param mutationObserver - The MutationObserver to use for observing shadow roots
|
||
*/
|
||
deepQueryElements(root, queryString, mutationObserver) {
|
||
let elements = this.queryElements(root, queryString);
|
||
const shadowRoots = this.recursivelyQueryShadowRoots(root);
|
||
for (let index = 0; index < shadowRoots.length; index++) {
|
||
const shadowRoot = shadowRoots[index];
|
||
elements = elements.concat(this.queryElements(shadowRoot, queryString));
|
||
if (mutationObserver) {
|
||
mutationObserver.observe(shadowRoot, {
|
||
attributes: true,
|
||
childList: true,
|
||
subtree: true,
|
||
});
|
||
}
|
||
}
|
||
return elements;
|
||
}
|
||
/**
|
||
* Queries the DOM for elements based on the given query string.
|
||
*
|
||
* @param root - The root element to start the query from
|
||
* @param queryString - The query string to match elements against
|
||
*/
|
||
queryElements(root, queryString) {
|
||
if (!root.querySelector(queryString)) {
|
||
return [];
|
||
}
|
||
return Array.from(root.querySelectorAll(queryString));
|
||
}
|
||
/**
|
||
* Recursively queries all shadow roots found within the given root element.
|
||
* Will also set up a mutation observer on the shadow root if the
|
||
* `isObservingShadowRoot` parameter is set to true.
|
||
*
|
||
* @param root - The root element to start the query from
|
||
* @param depth - The depth of the recursion
|
||
*/
|
||
recursivelyQueryShadowRoots(root, depth = 0) {
|
||
if (!this.pageContainsShadowDom) {
|
||
return [];
|
||
}
|
||
if (depth >= MAX_DEEP_QUERY_RECURSION_DEPTH) {
|
||
throw new Error("Max recursion depth reached");
|
||
}
|
||
let shadowRoots = this.queryShadowRoots(root);
|
||
for (let index = 0; index < shadowRoots.length; index++) {
|
||
const shadowRoot = shadowRoots[index];
|
||
shadowRoots = shadowRoots.concat(this.recursivelyQueryShadowRoots(shadowRoot, depth + 1));
|
||
}
|
||
return shadowRoots;
|
||
}
|
||
/**
|
||
* Queries any immediate shadow roots found within the given root element.
|
||
*
|
||
* @param root - The root element to start the query from
|
||
* @param returnSingleShadowRoot - Whether to return a single shadow root or an array of shadow roots
|
||
*/
|
||
queryShadowRoots(root, returnSingleShadowRoot = false) {
|
||
if (!root) {
|
||
return [];
|
||
}
|
||
const shadowRoots = [];
|
||
const potentialShadowRoots = root.querySelectorAll(":defined");
|
||
for (let index = 0; index < potentialShadowRoots.length; index++) {
|
||
const shadowRoot = this.getShadowRoot(potentialShadowRoots[index]);
|
||
if (!shadowRoot) {
|
||
continue;
|
||
}
|
||
shadowRoots.push(shadowRoot);
|
||
if (returnSingleShadowRoot) {
|
||
break;
|
||
}
|
||
}
|
||
return shadowRoots;
|
||
}
|
||
/**
|
||
* Attempts to get the ShadowRoot of the passed node. If support for the
|
||
* extension based openOrClosedShadowRoot API is available, it will be used.
|
||
* Will return null if the node is not an HTMLElement or if the node has
|
||
* child nodes.
|
||
*
|
||
* @param {Node} node
|
||
*/
|
||
getShadowRoot(node) {
|
||
var _a;
|
||
if (!nodeIsElement(node)) {
|
||
return null;
|
||
}
|
||
if (node.shadowRoot) {
|
||
return node.shadowRoot;
|
||
}
|
||
if ((_a = chrome.dom) === null || _a === void 0 ? void 0 : _a.openOrClosedShadowRoot) {
|
||
try {
|
||
return chrome.dom.openOrClosedShadowRoot(node);
|
||
}
|
||
catch (_b) {
|
||
return null;
|
||
}
|
||
}
|
||
// Firefox-specific equivalent of `openOrClosedShadowRoot`
|
||
return node.openOrClosedShadowRoot;
|
||
}
|
||
/**
|
||
* Queries the DOM for all the nodes that match the given filter callback
|
||
* and returns a collection of nodes.
|
||
* @param rootNode
|
||
* @param filterCallback
|
||
* @param ignoredTreeWalkerNodes
|
||
* @param mutationObserver
|
||
*/
|
||
queryAllTreeWalkerNodes(rootNode, filterCallback, ignoredTreeWalkerNodes, mutationObserver) {
|
||
const treeWalkerQueryResults = [];
|
||
this.buildTreeWalkerNodesQueryResults(rootNode, treeWalkerQueryResults, filterCallback, ignoredTreeWalkerNodes, mutationObserver);
|
||
return treeWalkerQueryResults;
|
||
}
|
||
/**
|
||
* Recursively builds a collection of nodes that match the given filter callback.
|
||
* If a node has a ShadowRoot, it will be observed for mutations.
|
||
*
|
||
* @param rootNode
|
||
* @param treeWalkerQueryResults
|
||
* @param filterCallback
|
||
* @param ignoredTreeWalkerNodes
|
||
* @param mutationObserver
|
||
*/
|
||
buildTreeWalkerNodesQueryResults(rootNode, treeWalkerQueryResults, filterCallback, ignoredTreeWalkerNodes, mutationObserver) {
|
||
const treeWalker = document === null || document === void 0 ? void 0 : document.createTreeWalker(rootNode, NodeFilter.SHOW_ELEMENT, (node) => {
|
||
var _a;
|
||
return ignoredTreeWalkerNodes.has((_a = node.nodeName) === null || _a === void 0 ? void 0 : _a.toLowerCase())
|
||
? NodeFilter.FILTER_REJECT
|
||
: NodeFilter.FILTER_ACCEPT;
|
||
});
|
||
let currentNode = treeWalker === null || treeWalker === void 0 ? void 0 : treeWalker.currentNode;
|
||
while (currentNode) {
|
||
if (filterCallback(currentNode)) {
|
||
treeWalkerQueryResults.push(currentNode);
|
||
}
|
||
const nodeShadowRoot = this.getShadowRoot(currentNode);
|
||
if (nodeShadowRoot) {
|
||
if (mutationObserver) {
|
||
mutationObserver.observe(nodeShadowRoot, {
|
||
attributes: true,
|
||
childList: true,
|
||
subtree: true,
|
||
});
|
||
}
|
||
this.buildTreeWalkerNodesQueryResults(nodeShadowRoot, treeWalkerQueryResults, filterCallback, ignoredTreeWalkerNodes, mutationObserver);
|
||
}
|
||
currentNode = treeWalker === null || treeWalker === void 0 ? void 0 : treeWalker.nextNode();
|
||
}
|
||
}
|
||
}
|
||
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/ObjectUnsubscribedError.js
|
||
var ObjectUnsubscribedError=createErrorClass(function(_super){return function ObjectUnsubscribedErrorImpl(){_super(this);this.name='ObjectUnsubscribedError';this.message='object unsubscribed';};});
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/Subject.js
|
||
var Subject_Subject=function(_super){__extends(Subject,_super);function Subject(){var _this=_super.call(this)||this;_this.closed=false;_this.currentObservers=null;_this.observers=[];_this.isStopped=false;_this.hasError=false;_this.thrownError=null;return _this;}Subject.prototype.lift=function(operator){var subject=new AnonymousSubject(this,this);subject.operator=operator;return subject;};Subject.prototype._throwIfClosed=function(){if(this.closed){throw new ObjectUnsubscribedError();}};Subject.prototype.next=function(value){var _this=this;errorContext(function(){var e_1,_a;_this._throwIfClosed();if(!_this.isStopped){if(!_this.currentObservers){_this.currentObservers=Array.from(_this.observers);}try{for(var _b=__values(_this.currentObservers),_c=_b.next();!_c.done;_c=_b.next()){var observer=_c.value;observer.next(value);}}catch(e_1_1){e_1={error:e_1_1};}finally{try{if(_c&&!_c.done&&(_a=_b.return))_a.call(_b);}finally{if(e_1)throw e_1.error;}}}});};Subject.prototype.error=function(err){var _this=this;errorContext(function(){_this._throwIfClosed();if(!_this.isStopped){_this.hasError=_this.isStopped=true;_this.thrownError=err;var observers=_this.observers;while(observers.length){observers.shift().error(err);}}});};Subject.prototype.complete=function(){var _this=this;errorContext(function(){_this._throwIfClosed();if(!_this.isStopped){_this.isStopped=true;var observers=_this.observers;while(observers.length){observers.shift().complete();}}});};Subject.prototype.unsubscribe=function(){this.isStopped=this.closed=true;this.observers=this.currentObservers=null;};Object.defineProperty(Subject.prototype,"observed",{get:function(){var _a;return((_a=this.observers)===null||_a===void 0?void 0:_a.length)>0;},enumerable:false,configurable:true});Subject.prototype._trySubscribe=function(subscriber){this._throwIfClosed();return _super.prototype._trySubscribe.call(this,subscriber);};Subject.prototype._subscribe=function(subscriber){this._throwIfClosed();this._checkFinalizedStatuses(subscriber);return this._innerSubscribe(subscriber);};Subject.prototype._innerSubscribe=function(subscriber){var _this=this;var _a=this,hasError=_a.hasError,isStopped=_a.isStopped,observers=_a.observers;if(hasError||isStopped){return EMPTY_SUBSCRIPTION;}this.currentObservers=null;observers.push(subscriber);return new Subscription(function(){_this.currentObservers=null;arrRemove(observers,subscriber);});};Subject.prototype._checkFinalizedStatuses=function(subscriber){var _a=this,hasError=_a.hasError,thrownError=_a.thrownError,isStopped=_a.isStopped;if(hasError){subscriber.error(thrownError);}else if(isStopped){subscriber.complete();}};Subject.prototype.asObservable=function(){var observable=new Observable_Observable();observable.source=this;return observable;};Subject.create=function(destination,source){return new AnonymousSubject(destination,source);};return Subject;}(Observable_Observable);var AnonymousSubject=function(_super){__extends(AnonymousSubject,_super);function AnonymousSubject(destination,source){var _this=_super.call(this)||this;_this.destination=destination;_this.source=source;return _this;}AnonymousSubject.prototype.next=function(value){var _a,_b;(_b=(_a=this.destination)===null||_a===void 0?void 0:_a.next)===null||_b===void 0?void 0:_b.call(_a,value);};AnonymousSubject.prototype.error=function(err){var _a,_b;(_b=(_a=this.destination)===null||_a===void 0?void 0:_a.error)===null||_b===void 0?void 0:_b.call(_a,err);};AnonymousSubject.prototype.complete=function(){var _a,_b;(_b=(_a=this.destination)===null||_a===void 0?void 0:_a.complete)===null||_b===void 0?void 0:_b.call(_a);};AnonymousSubject.prototype._subscribe=function(subscriber){var _a,_b;return(_b=(_a=this.source)===null||_a===void 0?void 0:_a.subscribe(subscriber))!==null&&_b!==void 0?_b:EMPTY_SUBSCRIPTION;};return AnonymousSubject;}(Subject_Subject);
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduler/dateTimestampProvider.js
|
||
var dateTimestampProvider={now:function(){return(dateTimestampProvider.delegate||Date).now();},delegate:undefined};
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/ReplaySubject.js
|
||
var ReplaySubject_ReplaySubject=function(_super){__extends(ReplaySubject,_super);function ReplaySubject(_bufferSize,_windowTime,_timestampProvider){if(_bufferSize===void 0){_bufferSize=Infinity;}if(_windowTime===void 0){_windowTime=Infinity;}if(_timestampProvider===void 0){_timestampProvider=dateTimestampProvider;}var _this=_super.call(this)||this;_this._bufferSize=_bufferSize;_this._windowTime=_windowTime;_this._timestampProvider=_timestampProvider;_this._buffer=[];_this._infiniteTimeWindow=true;_this._infiniteTimeWindow=_windowTime===Infinity;_this._bufferSize=Math.max(1,_bufferSize);_this._windowTime=Math.max(1,_windowTime);return _this;}ReplaySubject.prototype.next=function(value){var _a=this,isStopped=_a.isStopped,_buffer=_a._buffer,_infiniteTimeWindow=_a._infiniteTimeWindow,_timestampProvider=_a._timestampProvider,_windowTime=_a._windowTime;if(!isStopped){_buffer.push(value);!_infiniteTimeWindow&&_buffer.push(_timestampProvider.now()+_windowTime);}this._trimBuffer();_super.prototype.next.call(this,value);};ReplaySubject.prototype._subscribe=function(subscriber){this._throwIfClosed();this._trimBuffer();var subscription=this._innerSubscribe(subscriber);var _a=this,_infiniteTimeWindow=_a._infiniteTimeWindow,_buffer=_a._buffer;var copy=_buffer.slice();for(var i=0;i<copy.length&&!subscriber.closed;i+=_infiniteTimeWindow?1:2){subscriber.next(copy[i]);}this._checkFinalizedStatuses(subscriber);return subscription;};ReplaySubject.prototype._trimBuffer=function(){var _a=this,_bufferSize=_a._bufferSize,_timestampProvider=_a._timestampProvider,_buffer=_a._buffer,_infiniteTimeWindow=_a._infiniteTimeWindow;var adjustedBufferSize=(_infiniteTimeWindow?1:2)*_bufferSize;_bufferSize<Infinity&&adjustedBufferSize<_buffer.length&&_buffer.splice(0,_buffer.length-adjustedBufferSize);if(!_infiniteTimeWindow){var now=_timestampProvider.now();var last=0;for(var i=1;i<_buffer.length&&_buffer[i]<=now;i+=2){last=i;}last&&_buffer.splice(0,last+1);}};return ReplaySubject;}(Subject_Subject);
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/lift.js
|
||
function hasLift(source){return isFunction(source===null||source===void 0?void 0:source.lift);}function operate(init){return function(source){if(hasLift(source)){return source.lift(function(liftedSource){try{return init(liftedSource,this);}catch(err){this.error(err);}});}throw new TypeError('Unable to lift unknown Observable type');};}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/OperatorSubscriber.js
|
||
function createOperatorSubscriber(destination,onNext,onComplete,onError,onFinalize){return new OperatorSubscriber(destination,onNext,onComplete,onError,onFinalize);}var OperatorSubscriber=function(_super){__extends(OperatorSubscriber,_super);function OperatorSubscriber(destination,onNext,onComplete,onError,onFinalize,shouldUnsubscribe){var _this=_super.call(this,destination)||this;_this.onFinalize=onFinalize;_this.shouldUnsubscribe=shouldUnsubscribe;_this._next=onNext?function(value){try{onNext(value);}catch(err){destination.error(err);}}:_super.prototype._next;_this._error=onError?function(err){try{onError(err);}catch(err){destination.error(err);}finally{this.unsubscribe();}}:_super.prototype._error;_this._complete=onComplete?function(){try{onComplete();}catch(err){destination.error(err);}finally{this.unsubscribe();}}:_super.prototype._complete;return _this;}OperatorSubscriber.prototype.unsubscribe=function(){var _a;if(!this.shouldUnsubscribe||this.shouldUnsubscribe()){var closed_1=this.closed;_super.prototype.unsubscribe.call(this);!closed_1&&((_a=this.onFinalize)===null||_a===void 0?void 0:_a.call(this));}};return OperatorSubscriber;}(Subscriber);
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/filter.js
|
||
function filter_filter(predicate,thisArg){return operate(function(source,subscriber){var index=0;source.subscribe(createOperatorSubscriber(subscriber,function(value){return predicate.call(thisArg,value,index++)&&subscriber.next(value);}));});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/scanInternals.js
|
||
function scanInternals(accumulator,seed,hasSeed,emitOnNext,emitBeforeComplete){return function(source,subscriber){var hasState=hasSeed;var state=seed;var index=0;source.subscribe(createOperatorSubscriber(subscriber,function(value){var i=index++;state=hasState?accumulator(state,value,i):(hasState=true,value);emitOnNext&&subscriber.next(state);},emitBeforeComplete&&function(){hasState&&subscriber.next(state);subscriber.complete();}));};}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/scan.js
|
||
function scan(accumulator,seed){return operate(scanInternals(accumulator,seed,arguments.length>=2,true));}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduler/Action.js
|
||
var Action=function(_super){__extends(Action,_super);function Action(scheduler,work){return _super.call(this)||this;}Action.prototype.schedule=function(state,delay){if(delay===void 0){delay=0;}return this;};return Action;}(Subscription);
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduler/intervalProvider.js
|
||
var intervalProvider={setInterval:function(handler,timeout){var args=[];for(var _i=2;_i<arguments.length;_i++){args[_i-2]=arguments[_i];}var delegate=intervalProvider.delegate;if(delegate===null||delegate===void 0?void 0:delegate.setInterval){return delegate.setInterval.apply(delegate,__spreadArray([handler,timeout],__read(args)));}return setInterval.apply(void 0,__spreadArray([handler,timeout],__read(args)));},clearInterval:function(handle){var delegate=intervalProvider.delegate;return((delegate===null||delegate===void 0?void 0:delegate.clearInterval)||clearInterval)(handle);},delegate:undefined};
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncAction.js
|
||
var AsyncAction=function(_super){__extends(AsyncAction,_super);function AsyncAction(scheduler,work){var _this=_super.call(this,scheduler,work)||this;_this.scheduler=scheduler;_this.work=work;_this.pending=false;return _this;}AsyncAction.prototype.schedule=function(state,delay){var _a;if(delay===void 0){delay=0;}if(this.closed){return this;}this.state=state;var id=this.id;var scheduler=this.scheduler;if(id!=null){this.id=this.recycleAsyncId(scheduler,id,delay);}this.pending=true;this.delay=delay;this.id=(_a=this.id)!==null&&_a!==void 0?_a:this.requestAsyncId(scheduler,this.id,delay);return this;};AsyncAction.prototype.requestAsyncId=function(scheduler,_id,delay){if(delay===void 0){delay=0;}return intervalProvider.setInterval(scheduler.flush.bind(scheduler,this),delay);};AsyncAction.prototype.recycleAsyncId=function(_scheduler,id,delay){if(delay===void 0){delay=0;}if(delay!=null&&this.delay===delay&&this.pending===false){return id;}if(id!=null){intervalProvider.clearInterval(id);}return undefined;};AsyncAction.prototype.execute=function(state,delay){if(this.closed){return new Error('executing a cancelled action');}this.pending=false;var error=this._execute(state,delay);if(error){return error;}else if(this.pending===false&&this.id!=null){this.id=this.recycleAsyncId(this.scheduler,this.id,null);}};AsyncAction.prototype._execute=function(state,_delay){var errored=false;var errorValue;try{this.work(state);}catch(e){errored=true;errorValue=e?e:new Error('Scheduled action threw falsy error');}if(errored){this.unsubscribe();return errorValue;}};AsyncAction.prototype.unsubscribe=function(){if(!this.closed){var _a=this,id=_a.id,scheduler=_a.scheduler;var actions=scheduler.actions;this.work=this.state=this.scheduler=null;this.pending=false;arrRemove(actions,this);if(id!=null){this.id=this.recycleAsyncId(scheduler,id,null);}this.delay=null;_super.prototype.unsubscribe.call(this);}};return AsyncAction;}(Action);
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/Scheduler.js
|
||
var Scheduler=function(){function Scheduler(schedulerActionCtor,now){if(now===void 0){now=Scheduler.now;}this.schedulerActionCtor=schedulerActionCtor;this.now=now;}Scheduler.prototype.schedule=function(work,delay,state){if(delay===void 0){delay=0;}return new this.schedulerActionCtor(this,work).schedule(state,delay);};Scheduler.now=dateTimestampProvider.now;return Scheduler;}();
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncScheduler.js
|
||
var AsyncScheduler=function(_super){__extends(AsyncScheduler,_super);function AsyncScheduler(SchedulerAction,now){if(now===void 0){now=Scheduler.now;}var _this=_super.call(this,SchedulerAction,now)||this;_this.actions=[];_this._active=false;return _this;}AsyncScheduler.prototype.flush=function(action){var actions=this.actions;if(this._active){actions.push(action);return;}var error;this._active=true;do{if(error=action.execute(action.state,action.delay)){break;}}while(action=actions.shift());this._active=false;if(error){while(action=actions.shift()){action.unsubscribe();}throw error;}};return AsyncScheduler;}(Scheduler);
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduler/async.js
|
||
var async_asyncScheduler=new AsyncScheduler(AsyncAction);var async_async=async_asyncScheduler;
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isScheduler.js
|
||
function isScheduler(value){return value&&isFunction(value.schedule);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isDate.js
|
||
function isValidDate(value){return value instanceof Date&&!isNaN(value);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/timer.js
|
||
function timer_timer(dueTime,intervalOrScheduler,scheduler){if(dueTime===void 0){dueTime=0;}if(scheduler===void 0){scheduler=async_async;}var intervalDuration=-1;if(intervalOrScheduler!=null){if(isScheduler(intervalOrScheduler)){scheduler=intervalOrScheduler;}else{intervalDuration=intervalOrScheduler;}}return new Observable_Observable(function(subscriber){var due=isValidDate(dueTime)?+dueTime-scheduler.now():dueTime;if(due<0){due=0;}var n=0;return scheduler.schedule(function(){if(!subscriber.closed){subscriber.next(n++);if(0<=intervalDuration){this.schedule(undefined,intervalDuration);}else{subscriber.complete();}}},due);});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/map.js
|
||
function map_map(project,thisArg){return operate(function(source,subscriber){var index=0;source.subscribe(createOperatorSubscriber(subscriber,function(value){subscriber.next(project.call(thisArg,value,index++));}));});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isArrayLike.js
|
||
var isArrayLike=function(x){return x&&typeof x.length==='number'&&typeof x!=='function';};
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isPromise.js
|
||
function isPromise(value){return isFunction(value===null||value===void 0?void 0:value.then);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isInteropObservable.js
|
||
function isInteropObservable(input){return isFunction(input[observable]);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isAsyncIterable.js
|
||
function isAsyncIterable(obj){return Symbol.asyncIterator&&isFunction(obj===null||obj===void 0?void 0:obj[Symbol.asyncIterator]);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/throwUnobservableError.js
|
||
function createInvalidObservableTypeError(input){return new TypeError("You provided "+(input!==null&&typeof input==='object'?'an invalid object':"'"+input+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.");}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/symbol/iterator.js
|
||
function getSymbolIterator(){if(typeof Symbol!=='function'||!Symbol.iterator){return'@@iterator';}return Symbol.iterator;}var iterator_iterator=getSymbolIterator();
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isIterable.js
|
||
function isIterable(input){return isFunction(input===null||input===void 0?void 0:input[iterator_iterator]);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/isReadableStreamLike.js
|
||
function readableStreamLikeToAsyncGenerator(readableStream){return __asyncGenerator(this,arguments,function readableStreamLikeToAsyncGenerator_1(){var reader,_a,value,done;return __generator(this,function(_b){switch(_b.label){case 0:reader=readableStream.getReader();_b.label=1;case 1:_b.trys.push([1,,9,10]);_b.label=2;case 2:if(false)// removed by dead control flow
|
||
{}return[4,__await(reader.read())];case 3:_a=_b.sent(),value=_a.value,done=_a.done;if(!done)return[3,5];return[4,__await(void 0)];case 4:return[2,_b.sent()];case 5:return[4,__await(value)];case 6:return[4,_b.sent()];case 7:_b.sent();return[3,2];case 8:return[3,10];case 9:reader.releaseLock();return[7];case 10:return[2];}});});}function isReadableStreamLike(obj){return isFunction(obj===null||obj===void 0?void 0:obj.getReader);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/innerFrom.js
|
||
function innerFrom(input){if(input instanceof Observable_Observable){return input;}if(input!=null){if(isInteropObservable(input)){return fromInteropObservable(input);}if(isArrayLike(input)){return fromArrayLike(input);}if(isPromise(input)){return fromPromise(input);}if(isAsyncIterable(input)){return fromAsyncIterable(input);}if(isIterable(input)){return fromIterable(input);}if(isReadableStreamLike(input)){return fromReadableStreamLike(input);}}throw createInvalidObservableTypeError(input);}function fromInteropObservable(obj){return new Observable_Observable(function(subscriber){var obs=obj[observable]();if(isFunction(obs.subscribe)){return obs.subscribe(subscriber);}throw new TypeError('Provided object does not correctly implement Symbol.observable');});}function fromArrayLike(array){return new Observable_Observable(function(subscriber){for(var i=0;i<array.length&&!subscriber.closed;i++){subscriber.next(array[i]);}subscriber.complete();});}function fromPromise(promise){return new Observable_Observable(function(subscriber){promise.then(function(value){if(!subscriber.closed){subscriber.next(value);subscriber.complete();}},function(err){return subscriber.error(err);}).then(null,reportUnhandledError);});}function fromIterable(iterable){return new Observable_Observable(function(subscriber){var e_1,_a;try{for(var iterable_1=__values(iterable),iterable_1_1=iterable_1.next();!iterable_1_1.done;iterable_1_1=iterable_1.next()){var value=iterable_1_1.value;subscriber.next(value);if(subscriber.closed){return;}}}catch(e_1_1){e_1={error:e_1_1};}finally{try{if(iterable_1_1&&!iterable_1_1.done&&(_a=iterable_1.return))_a.call(iterable_1);}finally{if(e_1)throw e_1.error;}}subscriber.complete();});}function fromAsyncIterable(asyncIterable){return new Observable_Observable(function(subscriber){process(asyncIterable,subscriber).catch(function(err){return subscriber.error(err);});});}function fromReadableStreamLike(readableStream){return fromAsyncIterable(readableStreamLikeToAsyncGenerator(readableStream));}function process(asyncIterable,subscriber){var asyncIterable_1,asyncIterable_1_1;var e_2,_a;return __awaiter(this,void 0,void 0,function(){var value,e_2_1;return __generator(this,function(_b){switch(_b.label){case 0:_b.trys.push([0,5,6,11]);asyncIterable_1=__asyncValues(asyncIterable);_b.label=1;case 1:return[4,asyncIterable_1.next()];case 2:if(!(asyncIterable_1_1=_b.sent(),!asyncIterable_1_1.done))return[3,4];value=asyncIterable_1_1.value;subscriber.next(value);if(subscriber.closed){return[2];}_b.label=3;case 3:return[3,1];case 4:return[3,11];case 5:e_2_1=_b.sent();e_2={error:e_2_1};return[3,11];case 6:_b.trys.push([6,,9,10]);if(!(asyncIterable_1_1&&!asyncIterable_1_1.done&&(_a=asyncIterable_1.return)))return[3,8];return[4,_a.call(asyncIterable_1)];case 7:_b.sent();_b.label=8;case 8:return[3,10];case 9:if(e_2)throw e_2.error;return[7];case 10:return[7];case 11:subscriber.complete();return[2];}});});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/executeSchedule.js
|
||
function executeSchedule(parentSubscription,scheduler,work,delay,repeat){if(delay===void 0){delay=0;}if(repeat===void 0){repeat=false;}var scheduleSubscription=scheduler.schedule(function(){work();if(repeat){parentSubscription.add(this.schedule(null,delay));}else{this.unsubscribe();}},delay);parentSubscription.add(scheduleSubscription);if(!repeat){return scheduleSubscription;}}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/mergeInternals.js
|
||
function mergeInternals(source,subscriber,project,concurrent,onBeforeNext,expand,innerSubScheduler,additionalFinalizer){var buffer=[];var active=0;var index=0;var isComplete=false;var checkComplete=function(){if(isComplete&&!buffer.length&&!active){subscriber.complete();}};var outerNext=function(value){return active<concurrent?doInnerSub(value):buffer.push(value);};var doInnerSub=function(value){expand&&subscriber.next(value);active++;var innerComplete=false;innerFrom(project(value,index++)).subscribe(createOperatorSubscriber(subscriber,function(innerValue){onBeforeNext===null||onBeforeNext===void 0?void 0:onBeforeNext(innerValue);if(expand){outerNext(innerValue);}else{subscriber.next(innerValue);}},function(){innerComplete=true;},undefined,function(){if(innerComplete){try{active--;var _loop_1=function(){var bufferedValue=buffer.shift();if(innerSubScheduler){executeSchedule(subscriber,innerSubScheduler,function(){return doInnerSub(bufferedValue);});}else{doInnerSub(bufferedValue);}};while(buffer.length&&active<concurrent){_loop_1();}checkComplete();}catch(err){subscriber.error(err);}}}));};source.subscribe(createOperatorSubscriber(subscriber,outerNext,function(){isComplete=true;checkComplete();}));return function(){additionalFinalizer===null||additionalFinalizer===void 0?void 0:additionalFinalizer();};}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/mergeMap.js
|
||
function mergeMap(project,resultSelector,concurrent){if(concurrent===void 0){concurrent=Infinity;}if(isFunction(resultSelector)){return mergeMap(function(a,i){return map_map(function(b,ii){return resultSelector(a,b,i,ii);})(innerFrom(project(a,i)));},concurrent);}else if(typeof resultSelector==='number'){concurrent=resultSelector;}return operate(function(source,subscriber){return mergeInternals(source,subscriber,project,concurrent);});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/mergeAll.js
|
||
function mergeAll(concurrent){if(concurrent===void 0){concurrent=Infinity;}return mergeMap(identity,concurrent);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/empty.js
|
||
var EMPTY=new Observable_Observable(function(subscriber){return subscriber.complete();});function empty(scheduler){return scheduler?emptyScheduled(scheduler):EMPTY;}function emptyScheduled(scheduler){return new Observable(function(subscriber){return scheduler.schedule(function(){return subscriber.complete();});});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/args.js
|
||
function last(arr){return arr[arr.length-1];}function popResultSelector(args){return isFunction(last(args))?args.pop():undefined;}function popScheduler(args){return isScheduler(last(args))?args.pop():undefined;}function popNumber(args,defaultValue){return typeof last(args)==='number'?args.pop():defaultValue;}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/observeOn.js
|
||
function observeOn(scheduler,delay){if(delay===void 0){delay=0;}return operate(function(source,subscriber){source.subscribe(createOperatorSubscriber(subscriber,function(value){return executeSchedule(subscriber,scheduler,function(){return subscriber.next(value);},delay);},function(){return executeSchedule(subscriber,scheduler,function(){return subscriber.complete();},delay);},function(err){return executeSchedule(subscriber,scheduler,function(){return subscriber.error(err);},delay);}));});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/subscribeOn.js
|
||
function subscribeOn(scheduler,delay){if(delay===void 0){delay=0;}return operate(function(source,subscriber){subscriber.add(scheduler.schedule(function(){return source.subscribe(subscriber);},delay));});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleObservable.js
|
||
function scheduleObservable(input,scheduler){return innerFrom(input).pipe(subscribeOn(scheduler),observeOn(scheduler));}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduled/schedulePromise.js
|
||
function schedulePromise(input,scheduler){return innerFrom(input).pipe(subscribeOn(scheduler),observeOn(scheduler));}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleArray.js
|
||
function scheduleArray(input,scheduler){return new Observable_Observable(function(subscriber){var i=0;return scheduler.schedule(function(){if(i===input.length){subscriber.complete();}else{subscriber.next(input[i++]);if(!subscriber.closed){this.schedule();}}});});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleIterable.js
|
||
function scheduleIterable(input,scheduler){return new Observable_Observable(function(subscriber){var iterator;executeSchedule(subscriber,scheduler,function(){iterator=input[iterator_iterator]();executeSchedule(subscriber,scheduler,function(){var _a;var value;var done;try{_a=iterator.next(),value=_a.value,done=_a.done;}catch(err){subscriber.error(err);return;}if(done){subscriber.complete();}else{subscriber.next(value);}},0,true);});return function(){return isFunction(iterator===null||iterator===void 0?void 0:iterator.return)&&iterator.return();};});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleAsyncIterable.js
|
||
function scheduleAsyncIterable(input,scheduler){if(!input){throw new Error('Iterable cannot be null');}return new Observable_Observable(function(subscriber){executeSchedule(subscriber,scheduler,function(){var iterator=input[Symbol.asyncIterator]();executeSchedule(subscriber,scheduler,function(){iterator.next().then(function(result){if(result.done){subscriber.complete();}else{subscriber.next(result.value);}});},0,true);});});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleReadableStreamLike.js
|
||
function scheduleReadableStreamLike(input,scheduler){return scheduleAsyncIterable(readableStreamLikeToAsyncGenerator(input),scheduler);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/scheduled/scheduled.js
|
||
function scheduled(input,scheduler){if(input!=null){if(isInteropObservable(input)){return scheduleObservable(input,scheduler);}if(isArrayLike(input)){return scheduleArray(input,scheduler);}if(isPromise(input)){return schedulePromise(input,scheduler);}if(isAsyncIterable(input)){return scheduleAsyncIterable(input,scheduler);}if(isIterable(input)){return scheduleIterable(input,scheduler);}if(isReadableStreamLike(input)){return scheduleReadableStreamLike(input,scheduler);}}throw createInvalidObservableTypeError(input);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/from.js
|
||
function from(input,scheduler){return scheduler?scheduled(input,scheduler):innerFrom(input);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/merge.js
|
||
function merge_merge(){var args=[];for(var _i=0;_i<arguments.length;_i++){args[_i]=arguments[_i];}var scheduler=popScheduler(args);var concurrent=popNumber(args,Infinity);var sources=args;return!sources.length?EMPTY:sources.length===1?innerFrom(sources[0]):mergeAll(concurrent)(from(sources,scheduler));}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/concatAll.js
|
||
function concatAll(){return mergeAll(1);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/concat.js
|
||
function concat(){var args=[];for(var _i=0;_i<arguments.length;_i++){args[_i]=arguments[_i];}return concatAll()(from(args,popScheduler(args)));}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/startWith.js
|
||
function startWith(){var values=[];for(var _i=0;_i<arguments.length;_i++){values[_i]=arguments[_i];}var scheduler=popScheduler(values);return operate(function(source,subscriber){(scheduler?concat(values,source,scheduler):concat(values,source)).subscribe(subscriber);});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/EmptyError.js
|
||
var EmptyError=createErrorClass(function(_super){return function EmptyErrorImpl(){_super(this);this.name='EmptyError';this.message='no elements in sequence';};});
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/firstValueFrom.js
|
||
function firstValueFrom_firstValueFrom(source,config){var hasConfig=typeof config==='object';return new Promise(function(resolve,reject){var subscriber=new SafeSubscriber({next:function(value){resolve(value);subscriber.unsubscribe();},error:reject,complete:function(){if(hasConfig){resolve(config.defaultValue);}else{reject(new EmptyError());}}});source.subscribe(subscriber);});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/share.js
|
||
function share_share(options){if(options===void 0){options={};}var _a=options.connector,connector=_a===void 0?function(){return new Subject_Subject();}:_a,_b=options.resetOnError,resetOnError=_b===void 0?true:_b,_c=options.resetOnComplete,resetOnComplete=_c===void 0?true:_c,_d=options.resetOnRefCountZero,resetOnRefCountZero=_d===void 0?true:_d;return function(wrapperSource){var connection;var resetConnection;var subject;var refCount=0;var hasCompleted=false;var hasErrored=false;var cancelReset=function(){resetConnection===null||resetConnection===void 0?void 0:resetConnection.unsubscribe();resetConnection=undefined;};var reset=function(){cancelReset();connection=subject=undefined;hasCompleted=hasErrored=false;};var resetAndUnsubscribe=function(){var conn=connection;reset();conn===null||conn===void 0?void 0:conn.unsubscribe();};return operate(function(source,subscriber){refCount++;if(!hasErrored&&!hasCompleted){cancelReset();}var dest=subject=subject!==null&&subject!==void 0?subject:connector();subscriber.add(function(){refCount--;if(refCount===0&&!hasErrored&&!hasCompleted){resetConnection=handleReset(resetAndUnsubscribe,resetOnRefCountZero);}});dest.subscribe(subscriber);if(!connection&&refCount>0){connection=new SafeSubscriber({next:function(value){return dest.next(value);},error:function(err){hasErrored=true;cancelReset();resetConnection=handleReset(reset,resetOnError,err);dest.error(err);},complete:function(){hasCompleted=true;cancelReset();resetConnection=handleReset(reset,resetOnComplete);dest.complete();}});innerFrom(source).subscribe(connection);}})(wrapperSource);};}function handleReset(reset,on){var args=[];for(var _i=2;_i<arguments.length;_i++){args[_i-2]=arguments[_i];}if(on===true){reset();return;}if(on===false){return;}var onSubscriber=new SafeSubscriber({next:function(){onSubscriber.unsubscribe();reset();}});return innerFrom(on.apply(void 0,__spreadArray([],__read(args)))).subscribe(onSubscriber);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/takeUntil.js
|
||
function takeUntil(notifier){return operate(function(source,subscriber){innerFrom(notifier).subscribe(createOperatorSubscriber(subscriber,function(){return subscriber.complete();},noop));!subscriber.closed&&source.subscribe(subscriber);});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/pairwise.js
|
||
function pairwise(){return operate(function(source,subscriber){var prev;var hasPrev=false;source.subscribe(createOperatorSubscriber(subscriber,function(value){var p=prev;prev=value;hasPrev&&subscriber.next([p,value]);hasPrev=true;}));});}
|
||
;// ../../libs/common/src/auth/enums/authentication-status.ts
|
||
/**
|
||
* The authentication status of the user
|
||
*
|
||
* See `AuthService.authStatusFor$` for details on how we determine the user's `AuthenticationStatus`
|
||
*/
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var AuthenticationStatus;
|
||
(function (AuthenticationStatus) {
|
||
/**
|
||
* User is not authenticated
|
||
* - The user does not have an active account userId and/or an access token in state
|
||
*/
|
||
AuthenticationStatus[AuthenticationStatus["LoggedOut"] = 0] = "LoggedOut";
|
||
/**
|
||
* User is authenticated but not decrypted
|
||
* - The user has an access token, but no user key in state
|
||
* - Vault data cannot be decrypted (because there is no user key)
|
||
*/
|
||
AuthenticationStatus[AuthenticationStatus["Locked"] = 1] = "Locked";
|
||
/**
|
||
* User is authenticated and decrypted
|
||
* - The user has an access token and a user key in state
|
||
* - Vault data can be decrypted (via user key)
|
||
*/
|
||
AuthenticationStatus[AuthenticationStatus["Unlocked"] = 2] = "Unlocked";
|
||
})(AuthenticationStatus || (AuthenticationStatus = {}));
|
||
|
||
// EXTERNAL MODULE: ../../node_modules/path-browserify/index.js
|
||
var path_browserify = __webpack_require__(58803);
|
||
// EXTERNAL MODULE: ../../node_modules/buffer/index.js
|
||
var node_modules_buffer = __webpack_require__(97763);
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/of.js
|
||
function of_of(){var args=[];for(var _i=0;_i<arguments.length;_i++){args[_i]=arguments[_i];}var scheduler=popScheduler(args);return from(args,scheduler);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/switchMap.js
|
||
function switchMap_switchMap(project,resultSelector){return operate(function(source,subscriber){var innerSubscriber=null;var index=0;var isComplete=false;var checkComplete=function(){return isComplete&&!innerSubscriber&&subscriber.complete();};source.subscribe(createOperatorSubscriber(subscriber,function(value){innerSubscriber===null||innerSubscriber===void 0?void 0:innerSubscriber.unsubscribe();var innerIndex=0;var outerIndex=index++;innerFrom(project(value,outerIndex)).subscribe(innerSubscriber=createOperatorSubscriber(subscriber,function(innerValue){return subscriber.next(resultSelector?resultSelector(value,innerValue,outerIndex,innerIndex++):innerValue);},function(){innerSubscriber=null;checkComplete();}));},function(){isComplete=true;checkComplete();}));});}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/domain.js
|
||
/**
|
||
* Check if `vhost` is a valid suffix of `hostname` (top-domain)
|
||
*
|
||
* It means that `vhost` needs to be a suffix of `hostname` and we then need to
|
||
* make sure that: either they are equal, or the character preceding `vhost` in
|
||
* `hostname` is a '.' (it should not be a partial label).
|
||
*
|
||
* * hostname = 'not.evil.com' and vhost = 'vil.com' => not ok
|
||
* * hostname = 'not.evil.com' and vhost = 'evil.com' => ok
|
||
* * hostname = 'not.evil.com' and vhost = 'not.evil.com' => ok
|
||
*/function shareSameDomainSuffix(hostname,vhost){if(hostname.endsWith(vhost)){return hostname.length===vhost.length||hostname[hostname.length-vhost.length-1]==='.';}return false;}/**
|
||
* Given a hostname and its public suffix, extract the general domain.
|
||
*/function extractDomainWithSuffix(hostname,publicSuffix){// Locate the index of the last '.' in the part of the `hostname` preceding
|
||
// the public suffix.
|
||
//
|
||
// examples:
|
||
// 1. not.evil.co.uk => evil.co.uk
|
||
// ^ ^
|
||
// | | start of public suffix
|
||
// | index of the last dot
|
||
//
|
||
// 2. example.co.uk => example.co.uk
|
||
// ^ ^
|
||
// | | start of public suffix
|
||
// |
|
||
// | (-1) no dot found before the public suffix
|
||
const publicSuffixIndex=hostname.length-publicSuffix.length-2;const lastDotBeforeSuffixIndex=hostname.lastIndexOf('.',publicSuffixIndex);// No '.' found, then `hostname` is the general domain (no sub-domain)
|
||
if(lastDotBeforeSuffixIndex===-1){return hostname;}// Extract the part between the last '.'
|
||
return hostname.slice(lastDotBeforeSuffixIndex+1);}/**
|
||
* Detects the domain based on rules and upon and a host string
|
||
*/function getDomain(suffix,hostname,options){// Check if `hostname` ends with a member of `validHosts`.
|
||
if(options.validHosts!==null){const validHosts=options.validHosts;for(const vhost of validHosts){if(/*@__INLINE__*/shareSameDomainSuffix(hostname,vhost)){return vhost;}}}let numberOfLeadingDots=0;if(hostname.startsWith('.')){while(numberOfLeadingDots<hostname.length&&hostname[numberOfLeadingDots]==='.'){numberOfLeadingDots+=1;}}// If `hostname` is a valid public suffix, then there is no domain to return.
|
||
// Since we already know that `getPublicSuffix` returns a suffix of `hostname`
|
||
// there is no need to perform a string comparison and we only compare the
|
||
// size.
|
||
if(suffix.length===hostname.length-numberOfLeadingDots){return null;}// To extract the general domain, we start by identifying the public suffix
|
||
// (if any), then consider the domain to be the public suffix with one added
|
||
// level of depth. (e.g.: if hostname is `not.evil.co.uk` and public suffix:
|
||
// `co.uk`, then we take one more level: `evil`, giving the final result:
|
||
// `evil.co.uk`).
|
||
return/*@__INLINE__*/extractDomainWithSuffix(hostname,suffix);}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/domain-without-suffix.js
|
||
/**
|
||
* Return the part of domain without suffix.
|
||
*
|
||
* Example: for domain 'foo.com', the result would be 'foo'.
|
||
*/function getDomainWithoutSuffix(domain,suffix){// Note: here `domain` and `suffix` cannot have the same length because in
|
||
// this case we set `domain` to `null` instead. It is thus safe to assume
|
||
// that `suffix` is shorter than `domain`.
|
||
return domain.slice(0,-suffix.length-1);}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/extract-hostname.js
|
||
/**
|
||
* @param url - URL we want to extract a hostname from.
|
||
* @param urlIsValidHostname - hint from caller; true if `url` is already a valid hostname.
|
||
*/function extractHostname(url,urlIsValidHostname){let start=0;let end=url.length;let hasUpper=false;// If url is not already a valid hostname, then try to extract hostname.
|
||
if(!urlIsValidHostname){// Special handling of data URLs
|
||
if(url.startsWith('data:')){return null;}// Trim leading spaces
|
||
while(start<url.length&&url.charCodeAt(start)<=32){start+=1;}// Trim trailing spaces
|
||
while(end>start+1&&url.charCodeAt(end-1)<=32){end-=1;}// Skip scheme.
|
||
if(url.charCodeAt(start)===47/* '/' */&&url.charCodeAt(start+1)===47/* '/' */){start+=2;}else{const indexOfProtocol=url.indexOf(':/',start);if(indexOfProtocol!==-1){// Implement fast-path for common protocols. We expect most protocols
|
||
// should be one of these 4 and thus we will not need to perform the
|
||
// more expansive validity check most of the time.
|
||
const protocolSize=indexOfProtocol-start;const c0=url.charCodeAt(start);const c1=url.charCodeAt(start+1);const c2=url.charCodeAt(start+2);const c3=url.charCodeAt(start+3);const c4=url.charCodeAt(start+4);if(protocolSize===5&&c0===104/* 'h' */&&c1===116/* 't' */&&c2===116/* 't' */&&c3===112/* 'p' */&&c4===115/* 's' */){// https
|
||
}else if(protocolSize===4&&c0===104/* 'h' */&&c1===116/* 't' */&&c2===116/* 't' */&&c3===112/* 'p' */){// http
|
||
}else if(protocolSize===3&&c0===119/* 'w' */&&c1===115/* 's' */&&c2===115/* 's' */){// wss
|
||
}else if(protocolSize===2&&c0===119/* 'w' */&&c1===115/* 's' */){// ws
|
||
}else{// Check that scheme is valid
|
||
for(let i=start;i<indexOfProtocol;i+=1){const lowerCaseCode=url.charCodeAt(i)|32;if(!(lowerCaseCode>=97&&lowerCaseCode<=122||// [a, z]
|
||
lowerCaseCode>=48&&lowerCaseCode<=57||// [0, 9]
|
||
lowerCaseCode===46||// '.'
|
||
lowerCaseCode===45||// '-'
|
||
lowerCaseCode===43// '+'
|
||
)){return null;}}}// Skip 0, 1 or more '/' after ':/'
|
||
start=indexOfProtocol+2;while(url.charCodeAt(start)===47/* '/' */){start+=1;}}}// Detect first occurrence of '/', '?' or '#'. We also keep track of the
|
||
// last occurrence of '@', ']' or ':' to speed-up subsequent parsing of
|
||
// (respectively), identifier, ipv6 or port.
|
||
let indexOfIdentifier=-1;let indexOfClosingBracket=-1;let indexOfPort=-1;for(let i=start;i<end;i+=1){const code=url.charCodeAt(i);if(code===35||// '#'
|
||
code===47||// '/'
|
||
code===63// '?'
|
||
){end=i;break;}else if(code===64){// '@'
|
||
indexOfIdentifier=i;}else if(code===93){// ']'
|
||
indexOfClosingBracket=i;}else if(code===58){// ':'
|
||
indexOfPort=i;}else if(code>=65&&code<=90){hasUpper=true;}}// Detect identifier: '@'
|
||
if(indexOfIdentifier!==-1&&indexOfIdentifier>start&&indexOfIdentifier<end){start=indexOfIdentifier+1;}// Handle ipv6 addresses
|
||
if(url.charCodeAt(start)===91/* '[' */){if(indexOfClosingBracket!==-1){return url.slice(start+1,indexOfClosingBracket).toLowerCase();}return null;}else if(indexOfPort!==-1&&indexOfPort>start&&indexOfPort<end){// Detect port: ':'
|
||
end=indexOfPort;}}// Trim trailing dots
|
||
while(end>start+1&&url.charCodeAt(end-1)===46/* '.' */){end-=1;}const hostname=start!==0||end!==url.length?url.slice(start,end):url;if(hasUpper){return hostname.toLowerCase();}return hostname;}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/is-ip.js
|
||
/**
|
||
* Check if a hostname is an IP. You should be aware that this only works
|
||
* because `hostname` is already garanteed to be a valid hostname!
|
||
*/function isProbablyIpv4(hostname){// Cannot be shorted than 1.1.1.1
|
||
if(hostname.length<7){return false;}// Cannot be longer than: 255.255.255.255
|
||
if(hostname.length>15){return false;}let numberOfDots=0;for(let i=0;i<hostname.length;i+=1){const code=hostname.charCodeAt(i);if(code===46/* '.' */){numberOfDots+=1;}else if(code<48/* '0' */||code>57/* '9' */){return false;}}return numberOfDots===3&&hostname.charCodeAt(0)!==46/* '.' */&&hostname.charCodeAt(hostname.length-1)!==46/* '.' */;}/**
|
||
* Similar to isProbablyIpv4.
|
||
*/function isProbablyIpv6(hostname){if(hostname.length<3){return false;}let start=hostname.startsWith('[')?1:0;let end=hostname.length;if(hostname[end-1]===']'){end-=1;}// We only consider the maximum size of a normal IPV6. Note that this will
|
||
// fail on so-called "IPv4 mapped IPv6 addresses" but this is a corner-case
|
||
// and a proper validation library should be used for these.
|
||
if(end-start>39){return false;}let hasColon=false;for(;start<end;start+=1){const code=hostname.charCodeAt(start);if(code===58/* ':' */){hasColon=true;}else if(!(code>=48&&code<=57||// 0-9
|
||
code>=97&&code<=102||// a-f
|
||
code>=65&&code<=90// A-F
|
||
)){return false;}}return hasColon;}/**
|
||
* Check if `hostname` is *probably* a valid ip addr (either ipv6 or ipv4).
|
||
* This *will not* work on any string. We need `hostname` to be a valid
|
||
* hostname.
|
||
*/function isIp(hostname){return isProbablyIpv6(hostname)||isProbablyIpv4(hostname);}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/is-valid.js
|
||
/**
|
||
* Implements fast shallow verification of hostnames. This does not perform a
|
||
* struct check on the content of labels (classes of Unicode characters, etc.)
|
||
* but instead check that the structure is valid (number of labels, length of
|
||
* labels, etc.).
|
||
*
|
||
* If you need stricter validation, consider using an external library.
|
||
*/function isValidAscii(code){return code>=97&&code<=122||code>=48&&code<=57||code>127;}/**
|
||
* Check if a hostname string is valid. It's usually a preliminary check before
|
||
* trying to use getDomain or anything else.
|
||
*
|
||
* Beware: it does not check if the TLD exists.
|
||
*//* harmony default export */ function is_valid(hostname){if(hostname.length>255){return false;}if(hostname.length===0){return false;}if(/*@__INLINE__*/!isValidAscii(hostname.charCodeAt(0))&&hostname.charCodeAt(0)!==46&&// '.' (dot)
|
||
hostname.charCodeAt(0)!==95// '_' (underscore)
|
||
){return false;}// Validate hostname according to RFC
|
||
let lastDotIndex=-1;let lastCharCode=-1;const len=hostname.length;for(let i=0;i<len;i+=1){const code=hostname.charCodeAt(i);if(code===46/* '.' */){if(// Check that previous label is < 63 bytes long (64 = 63 + '.')
|
||
i-lastDotIndex>64||// Check that previous character was not already a '.'
|
||
lastCharCode===46||// Check that the previous label does not end with a '-' (dash)
|
||
lastCharCode===45||// Check that the previous label does not end with a '_' (underscore)
|
||
lastCharCode===95){return false;}lastDotIndex=i;}else if(!(/*@__INLINE__*/isValidAscii(code)||code===45||code===95)){// Check if there is a forbidden character in the label
|
||
return false;}lastCharCode=code;}return(// Check that last label is shorter than 63 chars
|
||
len-lastDotIndex-1<=63&&// Check that the last character is an allowed trailing label character.
|
||
// Since we already checked that the char is a valid hostname character,
|
||
// we only need to check that it's different from '-'.
|
||
lastCharCode!==45);}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/options.js
|
||
function setDefaultsImpl({allowIcannDomains=true,allowPrivateDomains=false,detectIp=true,extractHostname=true,mixedInputs=true,validHosts=null,validateHostname=true}){return{allowIcannDomains,allowPrivateDomains,detectIp,extractHostname,mixedInputs,validHosts,validateHostname};}const DEFAULT_OPTIONS=/*@__INLINE__*/setDefaultsImpl({});function setDefaults(options){if(options===undefined){return DEFAULT_OPTIONS;}return/*@__INLINE__*/setDefaultsImpl(options);}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/subdomain.js
|
||
/**
|
||
* Returns the subdomain of a hostname string
|
||
*/function getSubdomain(hostname,domain){// If `hostname` and `domain` are the same, then there is no sub-domain
|
||
if(domain.length===hostname.length){return'';}return hostname.slice(0,-domain.length-1);}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/factory.js
|
||
/**
|
||
* Implement a factory allowing to plug different implementations of suffix
|
||
* lookup (e.g.: using a trie or the packed hashes datastructures). This is used
|
||
* and exposed in `tldts.ts` and `tldts-experimental.ts` bundle entrypoints.
|
||
*/function getEmptyResult(){return{domain:null,domainWithoutSuffix:null,hostname:null,isIcann:null,isIp:null,isPrivate:null,publicSuffix:null,subdomain:null};}function factory_resetResult(result){result.domain=null;result.domainWithoutSuffix=null;result.hostname=null;result.isIcann=null;result.isIp=null;result.isPrivate=null;result.publicSuffix=null;result.subdomain=null;}function factory_parseImpl(url,step,suffixLookup,partialOptions,result){const options=/*@__INLINE__*/setDefaults(partialOptions);// Very fast approximate check to make sure `url` is a string. This is needed
|
||
// because the library will not necessarily be used in a typed setup and
|
||
// values of arbitrary types might be given as argument.
|
||
if(typeof url!=='string'){return result;}// Extract hostname from `url` only if needed. This can be made optional
|
||
// using `options.extractHostname`. This option will typically be used
|
||
// whenever we are sure the inputs to `parse` are already hostnames and not
|
||
// arbitrary URLs.
|
||
//
|
||
// `mixedInput` allows to specify if we expect a mix of URLs and hostnames
|
||
// as input. If only hostnames are expected then `extractHostname` can be
|
||
// set to `false` to speed-up parsing. If only URLs are expected then
|
||
// `mixedInputs` can be set to `false`. The `mixedInputs` is only a hint
|
||
// and will not change the behavior of the library.
|
||
if(!options.extractHostname){result.hostname=url;}else if(options.mixedInputs){result.hostname=extractHostname(url,is_valid(url));}else{result.hostname=extractHostname(url,false);}// Check if `hostname` is a valid ip address
|
||
if(options.detectIp&&result.hostname!==null){result.isIp=isIp(result.hostname);if(result.isIp){return result;}}// Perform hostname validation if enabled. If hostname is not valid, no need to
|
||
// go further as there will be no valid domain or sub-domain. This validation
|
||
// is applied before any early returns to ensure consistent behavior across
|
||
// all API methods including getHostname().
|
||
if(options.validateHostname&&options.extractHostname&&result.hostname!==null&&!is_valid(result.hostname)){result.hostname=null;return result;}if(step===0/* FLAG.HOSTNAME */||result.hostname===null){return result;}// Extract public suffix
|
||
suffixLookup(result.hostname,options,result);if(step===2/* FLAG.PUBLIC_SUFFIX */||result.publicSuffix===null){return result;}// Extract domain
|
||
result.domain=getDomain(result.publicSuffix,result.hostname,options);if(step===3/* FLAG.DOMAIN */||result.domain===null){return result;}// Extract subdomain
|
||
result.subdomain=getSubdomain(result.hostname,result.domain);if(step===4/* FLAG.SUB_DOMAIN */){return result;}// Extract domain without suffix
|
||
result.domainWithoutSuffix=getDomainWithoutSuffix(result.domain,result.publicSuffix);return result;}
|
||
;// ../../node_modules/tldts-core/dist/es6/src/lookup/fast-path.js
|
||
/* harmony default export */ function fast_path(hostname,options,out){// Fast path for very popular suffixes; this allows to by-pass lookup
|
||
// completely as well as any extra allocation or string manipulation.
|
||
if(!options.allowPrivateDomains&&hostname.length>3){const last=hostname.length-1;const c3=hostname.charCodeAt(last);const c2=hostname.charCodeAt(last-1);const c1=hostname.charCodeAt(last-2);const c0=hostname.charCodeAt(last-3);if(c3===109/* 'm' */&&c2===111/* 'o' */&&c1===99/* 'c' */&&c0===46/* '.' */){out.isIcann=true;out.isPrivate=false;out.publicSuffix='com';return true;}else if(c3===103/* 'g' */&&c2===114/* 'r' */&&c1===111/* 'o' */&&c0===46/* '.' */){out.isIcann=true;out.isPrivate=false;out.publicSuffix='org';return true;}else if(c3===117/* 'u' */&&c2===100/* 'd' */&&c1===101/* 'e' */&&c0===46/* '.' */){out.isIcann=true;out.isPrivate=false;out.publicSuffix='edu';return true;}else if(c3===118/* 'v' */&&c2===111/* 'o' */&&c1===103/* 'g' */&&c0===46/* '.' */){out.isIcann=true;out.isPrivate=false;out.publicSuffix='gov';return true;}else if(c3===116/* 't' */&&c2===101/* 'e' */&&c1===110/* 'n' */&&c0===46/* '.' */){out.isIcann=true;out.isPrivate=false;out.publicSuffix='net';return true;}else if(c3===101/* 'e' */&&c2===100/* 'd' */&&c1===46/* '.' */){out.isIcann=true;out.isPrivate=false;out.publicSuffix='de';return true;}}return false;}
|
||
;// ../../node_modules/tldts-core/dist/es6/index.js
|
||
|
||
;// ../../node_modules/tldts/dist/es6/src/data/trie.js
|
||
const exceptions=function(){const _0=[1,{}],_1=[0,{"city":_0}];const exceptions=[0,{"ck":[0,{"www":_0}],"jp":[0,{"kawasaki":_1,"kitakyushu":_1,"kobe":_1,"nagoya":_1,"sapporo":_1,"sendai":_1,"yokohama":_1}]}];return exceptions;}();const rules=function(){const _2=[1,{}],_3=[2,{}],_4=[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2}],_5=[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2}],_6=[0,{"*":_3}],_7=[2,{"s":_6}],_8=[0,{"relay":_3}],_9=[2,{"id":_3}],_10=[1,{"gov":_2}],_11=[0,{"airflow":_6,"lambda-url":_3,"transfer-webapp":_3}],_12=[0,{"airflow":_6,"transfer-webapp":_3}],_13=[0,{"transfer-webapp":_3,"transfer-webapp-fips":_3}],_14=[0,{"notebook":_3,"studio":_3}],_15=[0,{"labeling":_3,"notebook":_3,"studio":_3}],_16=[0,{"notebook":_3}],_17=[0,{"labeling":_3,"notebook":_3,"notebook-fips":_3,"studio":_3}],_18=[0,{"notebook":_3,"notebook-fips":_3,"studio":_3,"studio-fips":_3}],_19=[0,{"shop":_3}],_20=[0,{"*":_2}],_21=[1,{"co":_3}],_22=[0,{"objects":_3}],_23=[2,{"nodes":_3}],_24=[0,{"my":_3}],_25=[0,{"s3":_3,"s3-accesspoint":_3,"s3-website":_3}],_26=[0,{"s3":_3,"s3-accesspoint":_3}],_27=[0,{"direct":_3}],_28=[0,{"webview-assets":_3}],_29=[0,{"vfs":_3,"webview-assets":_3}],_30=[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_25,"s3":_3,"s3-accesspoint":_3,"s3-object-lambda":_3,"s3-website":_3,"aws-cloud9":_28,"cloud9":_29}],_31=[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_26,"s3":_3,"s3-accesspoint":_3,"s3-object-lambda":_3,"s3-website":_3,"aws-cloud9":_28,"cloud9":_29}],_32=[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_25,"s3":_3,"s3-accesspoint":_3,"s3-object-lambda":_3,"s3-website":_3,"analytics-gateway":_3,"aws-cloud9":_28,"cloud9":_29}],_33=[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_25,"s3":_3,"s3-accesspoint":_3,"s3-object-lambda":_3,"s3-website":_3}],_34=[0,{"s3":_3,"s3-accesspoint":_3,"s3-accesspoint-fips":_3,"s3-fips":_3,"s3-website":_3}],_35=[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_34,"s3":_3,"s3-accesspoint":_3,"s3-accesspoint-fips":_3,"s3-fips":_3,"s3-object-lambda":_3,"s3-website":_3,"aws-cloud9":_28,"cloud9":_29}],_36=[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_34,"s3":_3,"s3-accesspoint":_3,"s3-accesspoint-fips":_3,"s3-deprecated":_3,"s3-fips":_3,"s3-object-lambda":_3,"s3-website":_3,"analytics-gateway":_3,"aws-cloud9":_28,"cloud9":_29}],_37=[0,{"s3":_3,"s3-accesspoint":_3,"s3-accesspoint-fips":_3,"s3-fips":_3}],_38=[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_37,"s3":_3,"s3-accesspoint":_3,"s3-accesspoint-fips":_3,"s3-fips":_3,"s3-object-lambda":_3,"s3-website":_3}],_39=[0,{"auth":_3}],_40=[0,{"auth":_3,"auth-fips":_3}],_41=[0,{"auth-fips":_3}],_42=[0,{"apps":_3}],_43=[0,{"paas":_3}],_44=[2,{"eu":_3}],_45=[0,{"app":_3}],_46=[0,{"site":_3}],_47=[1,{"com":_2,"edu":_2,"net":_2,"org":_2}],_48=[0,{"j":_3}],_49=[0,{"dyn":_3}],_50=[2,{"web":_3}],_51=[1,{"co":_2,"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2}],_52=[0,{"p":_3}],_53=[0,{"user":_3}],_54=[0,{"cdn":_3}],_55=[2,{"raw":_6}],_56=[0,{"cust":_3,"reservd":_3}],_57=[0,{"cust":_3}],_58=[0,{"s3":_3}],_59=[1,{"biz":_2,"com":_2,"edu":_2,"gov":_2,"info":_2,"net":_2,"org":_2}],_60=[0,{"ipfs":_3}],_61=[1,{"framer":_3}],_62=[0,{"forgot":_3}],_63=[1,{"gs":_2}],_64=[0,{"nes":_2}],_65=[1,{"k12":_2,"cc":_2,"lib":_2}],_66=[1,{"cc":_2}],_67=[1,{"cc":_2,"lib":_2}];const rules=[0,{"ac":[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"drr":_3,"feedback":_3,"forms":_3}],"ad":_2,"ae":[1,{"ac":_2,"co":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"sch":_2}],"aero":[1,{"airline":_2,"airport":_2,"accident-investigation":_2,"accident-prevention":_2,"aerobatic":_2,"aeroclub":_2,"aerodrome":_2,"agents":_2,"air-surveillance":_2,"air-traffic-control":_2,"aircraft":_2,"airtraffic":_2,"ambulance":_2,"association":_2,"author":_2,"ballooning":_2,"broker":_2,"caa":_2,"cargo":_2,"catering":_2,"certification":_2,"championship":_2,"charter":_2,"civilaviation":_2,"club":_2,"conference":_2,"consultant":_2,"consulting":_2,"control":_2,"council":_2,"crew":_2,"design":_2,"dgca":_2,"educator":_2,"emergency":_2,"engine":_2,"engineer":_2,"entertainment":_2,"equipment":_2,"exchange":_2,"express":_2,"federation":_2,"flight":_2,"freight":_2,"fuel":_2,"gliding":_2,"government":_2,"groundhandling":_2,"group":_2,"hanggliding":_2,"homebuilt":_2,"insurance":_2,"journal":_2,"journalist":_2,"leasing":_2,"logistics":_2,"magazine":_2,"maintenance":_2,"marketplace":_2,"media":_2,"microlight":_2,"modelling":_2,"navigation":_2,"parachuting":_2,"paragliding":_2,"passenger-association":_2,"pilot":_2,"press":_2,"production":_2,"recreation":_2,"repbody":_2,"res":_2,"research":_2,"rotorcraft":_2,"safety":_2,"scientist":_2,"services":_2,"show":_2,"skydiving":_2,"software":_2,"student":_2,"taxi":_2,"trader":_2,"trading":_2,"trainer":_2,"union":_2,"workinggroup":_2,"works":_2}],"af":_4,"ag":[1,{"co":_2,"com":_2,"net":_2,"nom":_2,"org":_2,"obj":_3}],"ai":[1,{"com":_2,"net":_2,"off":_2,"org":_2,"uwu":_3,"framer":_3}],"al":_5,"am":[1,{"co":_2,"com":_2,"commune":_2,"net":_2,"org":_2,"radio":_3}],"ao":[1,{"co":_2,"ed":_2,"edu":_2,"gov":_2,"gv":_2,"it":_2,"og":_2,"org":_2,"pb":_2}],"aq":_2,"ar":[1,{"bet":_2,"com":_2,"coop":_2,"edu":_2,"gob":_2,"gov":_2,"int":_2,"mil":_2,"musica":_2,"mutual":_2,"net":_2,"org":_2,"seg":_2,"senasa":_2,"tur":_2}],"arpa":[1,{"e164":_2,"home":_2,"in-addr":_2,"ip6":_2,"iris":_2,"uri":_2,"urn":_2}],"as":_10,"asia":[1,{"cloudns":_3,"daemon":_3,"dix":_3}],"at":[1,{"4":_3,"ac":[1,{"sth":_2}],"co":_2,"gv":_2,"or":_2,"funkfeuer":[0,{"wien":_3}],"futurecms":[0,{"*":_3,"ex":_6,"in":_6}],"futurehosting":_3,"futuremailing":_3,"ortsinfo":[0,{"ex":_6,"kunden":_6}],"biz":_3,"info":_3,"123webseite":_3,"priv":_3,"my":_3,"myspreadshop":_3,"12hp":_3,"2ix":_3,"4lima":_3,"lima-city":_3}],"au":[1,{"asn":_2,"com":[1,{"cloudlets":[0,{"mel":_3}],"myspreadshop":_3}],"edu":[1,{"act":_2,"catholic":_2,"nsw":_2,"nt":_2,"qld":_2,"sa":_2,"tas":_2,"vic":_2,"wa":_2}],"gov":[1,{"qld":_2,"sa":_2,"tas":_2,"vic":_2,"wa":_2}],"id":_2,"net":_2,"org":_2,"conf":_2,"oz":_2,"act":_2,"nsw":_2,"nt":_2,"qld":_2,"sa":_2,"tas":_2,"vic":_2,"wa":_2,"hrsn":[0,{"vps":_3}]}],"aw":[1,{"com":_2}],"ax":_2,"az":[1,{"biz":_2,"co":_2,"com":_2,"edu":_2,"gov":_2,"info":_2,"int":_2,"mil":_2,"name":_2,"net":_2,"org":_2,"pp":_2,"pro":_2}],"ba":[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"brendly":_19,"rs":_3}],"bb":[1,{"biz":_2,"co":_2,"com":_2,"edu":_2,"gov":_2,"info":_2,"net":_2,"org":_2,"store":_2,"tv":_2}],"bd":[1,{"ac":_2,"ai":_2,"co":_2,"com":_2,"edu":_2,"gov":_2,"id":_2,"info":_2,"it":_2,"mil":_2,"net":_2,"org":_2,"sch":_2,"tv":_2}],"be":[1,{"ac":_2,"cloudns":_3,"webhosting":_3,"interhostsolutions":[0,{"cloud":_3}],"kuleuven":[0,{"ezproxy":_3}],"123website":_3,"myspreadshop":_3,"transurl":_6}],"bf":_10,"bg":[1,{"0":_2,"1":_2,"2":_2,"3":_2,"4":_2,"5":_2,"6":_2,"7":_2,"8":_2,"9":_2,"a":_2,"b":_2,"c":_2,"d":_2,"e":_2,"f":_2,"g":_2,"h":_2,"i":_2,"j":_2,"k":_2,"l":_2,"m":_2,"n":_2,"o":_2,"p":_2,"q":_2,"r":_2,"s":_2,"t":_2,"u":_2,"v":_2,"w":_2,"x":_2,"y":_2,"z":_2,"barsy":_3}],"bh":_4,"bi":[1,{"co":_2,"com":_2,"edu":_2,"or":_2,"org":_2}],"biz":[1,{"activetrail":_3,"cloud-ip":_3,"cloudns":_3,"jozi":_3,"dyndns":_3,"for-better":_3,"for-more":_3,"for-some":_3,"for-the":_3,"selfip":_3,"webhop":_3,"orx":_3,"mmafan":_3,"myftp":_3,"no-ip":_3,"dscloud":_3}],"bj":[1,{"africa":_2,"agro":_2,"architectes":_2,"assur":_2,"avocats":_2,"co":_2,"com":_2,"eco":_2,"econo":_2,"edu":_2,"info":_2,"loisirs":_2,"money":_2,"net":_2,"org":_2,"ote":_2,"restaurant":_2,"resto":_2,"tourism":_2,"univ":_2}],"bm":_4,"bn":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"co":_3}],"bo":[1,{"com":_2,"edu":_2,"gob":_2,"int":_2,"mil":_2,"net":_2,"org":_2,"tv":_2,"web":_2,"academia":_2,"agro":_2,"arte":_2,"blog":_2,"bolivia":_2,"ciencia":_2,"cooperativa":_2,"democracia":_2,"deporte":_2,"ecologia":_2,"economia":_2,"empresa":_2,"indigena":_2,"industria":_2,"info":_2,"medicina":_2,"movimiento":_2,"musica":_2,"natural":_2,"nombre":_2,"noticias":_2,"patria":_2,"plurinacional":_2,"politica":_2,"profesional":_2,"pueblo":_2,"revista":_2,"salud":_2,"tecnologia":_2,"tksat":_2,"transporte":_2,"wiki":_2}],"br":[1,{"9guacu":_2,"abc":_2,"adm":_2,"adv":_2,"agr":_2,"aju":_2,"am":_2,"anani":_2,"aparecida":_2,"api":_2,"app":_2,"arq":_2,"art":_2,"ato":_2,"b":_2,"barueri":_2,"belem":_2,"bet":_2,"bhz":_2,"bib":_2,"bio":_2,"blog":_2,"bmd":_2,"boavista":_2,"bsb":_2,"campinagrande":_2,"campinas":_2,"caxias":_2,"cim":_2,"cng":_2,"cnt":_2,"com":[1,{"simplesite":_3}],"contagem":_2,"coop":_2,"coz":_2,"cri":_2,"cuiaba":_2,"curitiba":_2,"def":_2,"des":_2,"det":_2,"dev":_2,"ecn":_2,"eco":_2,"edu":_2,"emp":_2,"enf":_2,"eng":_2,"esp":_2,"etc":_2,"eti":_2,"far":_2,"feira":_2,"flog":_2,"floripa":_2,"fm":_2,"fnd":_2,"fortal":_2,"fot":_2,"foz":_2,"fst":_2,"g12":_2,"geo":_2,"ggf":_2,"goiania":_2,"gov":[1,{"ac":_2,"al":_2,"am":_2,"ap":_2,"ba":_2,"ce":_2,"df":_2,"es":_2,"go":_2,"ma":_2,"mg":_2,"ms":_2,"mt":_2,"pa":_2,"pb":_2,"pe":_2,"pi":_2,"pr":_2,"rj":_2,"rn":_2,"ro":_2,"rr":_2,"rs":_2,"sc":_2,"se":_2,"sp":_2,"to":_2}],"gru":_2,"ia":_2,"imb":_2,"ind":_2,"inf":_2,"jab":_2,"jampa":_2,"jdf":_2,"joinville":_2,"jor":_2,"jus":_2,"leg":[1,{"ac":_3,"al":_3,"am":_3,"ap":_3,"ba":_3,"ce":_3,"df":_3,"es":_3,"go":_3,"ma":_3,"mg":_3,"ms":_3,"mt":_3,"pa":_3,"pb":_3,"pe":_3,"pi":_3,"pr":_3,"rj":_3,"rn":_3,"ro":_3,"rr":_3,"rs":_3,"sc":_3,"se":_3,"sp":_3,"to":_3}],"leilao":_2,"lel":_2,"log":_2,"londrina":_2,"macapa":_2,"maceio":_2,"manaus":_2,"maringa":_2,"mat":_2,"med":_2,"mil":_2,"morena":_2,"mp":_2,"mus":_2,"natal":_2,"net":_2,"niteroi":_2,"nom":_20,"not":_2,"ntr":_2,"odo":_2,"ong":_2,"org":_2,"osasco":_2,"palmas":_2,"poa":_2,"ppg":_2,"pro":_2,"psc":_2,"psi":_2,"pvh":_2,"qsl":_2,"radio":_2,"rec":_2,"recife":_2,"rep":_2,"ribeirao":_2,"rio":_2,"riobranco":_2,"riopreto":_2,"salvador":_2,"sampa":_2,"santamaria":_2,"santoandre":_2,"saobernardo":_2,"saogonca":_2,"seg":_2,"sjc":_2,"slg":_2,"slz":_2,"social":_2,"sorocaba":_2,"srv":_2,"taxi":_2,"tc":_2,"tec":_2,"teo":_2,"the":_2,"tmp":_2,"trd":_2,"tur":_2,"tv":_2,"udi":_2,"vet":_2,"vix":_2,"vlog":_2,"wiki":_2,"xyz":_2,"zlg":_2,"tche":_3}],"bs":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"we":_3}],"bt":_4,"bv":_2,"bw":[1,{"ac":_2,"co":_2,"gov":_2,"net":_2,"org":_2}],"by":[1,{"gov":_2,"mil":_2,"com":_2,"of":_2,"mediatech":_3}],"bz":[1,{"co":_2,"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"za":_3,"mydns":_3,"gsj":_3}],"ca":[1,{"ab":_2,"bc":_2,"mb":_2,"nb":_2,"nf":_2,"nl":_2,"ns":_2,"nt":_2,"nu":_2,"on":_2,"pe":_2,"qc":_2,"sk":_2,"yk":_2,"gc":_2,"barsy":_3,"awdev":_6,"co":_3,"no-ip":_3,"onid":_3,"myspreadshop":_3,"box":_3}],"cat":_2,"cc":[1,{"cleverapps":_3,"cloud-ip":_3,"cloudns":_3,"ftpaccess":_3,"game-server":_3,"myphotos":_3,"scrapping":_3,"twmail":_3,"csx":_3,"fantasyleague":_3,"spawn":[0,{"instances":_3}]}],"cd":_10,"cf":_2,"cg":_2,"ch":[1,{"square7":_3,"cloudns":_3,"cloudscale":[0,{"cust":_3,"lpg":_22,"rma":_22}],"objectstorage":[0,{"lpg":_3,"rma":_3}],"flow":[0,{"ae":[0,{"alp1":_3}],"appengine":_3}],"linkyard-cloud":_3,"gotdns":_3,"dnsking":_3,"123website":_3,"myspreadshop":_3,"firenet":[0,{"*":_3,"svc":_6}],"12hp":_3,"2ix":_3,"4lima":_3,"lima-city":_3}],"ci":[1,{"ac":_2,"xn--aroport-bya":_2,"aéroport":_2,"asso":_2,"co":_2,"com":_2,"ed":_2,"edu":_2,"go":_2,"gouv":_2,"int":_2,"net":_2,"or":_2,"org":_2}],"ck":_20,"cl":[1,{"co":_2,"gob":_2,"gov":_2,"mil":_2,"cloudns":_3}],"cm":[1,{"co":_2,"com":_2,"gov":_2,"net":_2}],"cn":[1,{"ac":_2,"com":[1,{"amazonaws":[0,{"cn-north-1":[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"rds":_6,"dualstack":_25,"s3":_3,"s3-accesspoint":_3,"s3-deprecated":_3,"s3-object-lambda":_3,"s3-website":_3}],"cn-northwest-1":[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"rds":_6,"dualstack":_26,"s3":_3,"s3-accesspoint":_3,"s3-object-lambda":_3,"s3-website":_3}],"compute":_6,"airflow":[0,{"cn-north-1":_6,"cn-northwest-1":_6}],"eb":[0,{"cn-north-1":_3,"cn-northwest-1":_3}],"elb":_6}],"amazonwebservices":[0,{"on":[0,{"cn-north-1":_12,"cn-northwest-1":_12}]}],"sagemaker":[0,{"cn-north-1":_14,"cn-northwest-1":_14}]}],"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"xn--55qx5d":_2,"公司":_2,"xn--od0alg":_2,"網絡":_2,"xn--io0a7i":_2,"网络":_2,"ah":_2,"bj":_2,"cq":_2,"fj":_2,"gd":_2,"gs":_2,"gx":_2,"gz":_2,"ha":_2,"hb":_2,"he":_2,"hi":_2,"hk":_2,"hl":_2,"hn":_2,"jl":_2,"js":_2,"jx":_2,"ln":_2,"mo":_2,"nm":_2,"nx":_2,"qh":_2,"sc":_2,"sd":_2,"sh":[1,{"as":_3}],"sn":_2,"sx":_2,"tj":_2,"tw":_2,"xj":_2,"xz":_2,"yn":_2,"zj":_2,"canva-apps":_3,"canvasite":_24,"myqnapcloud":_3,"quickconnect":_27}],"co":[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"nom":_2,"org":_2,"carrd":_3,"crd":_3,"otap":_6,"hidns":_3,"leadpages":_3,"lpages":_3,"mypi":_3,"xmit":_6,"firewalledreplit":_9,"repl":_9,"supabase":[2,{"realtime":_3,"storage":_3}],"umso":_3}],"com":[1,{"a2hosted":_3,"cpserver":_3,"adobeaemcloud":[2,{"dev":_6}],"africa":_3,"aivencloud":_3,"alibabacloudcs":_3,"kasserver":_3,"amazonaws":[0,{"af-south-1":_30,"ap-east-1":_31,"ap-northeast-1":_32,"ap-northeast-2":_32,"ap-northeast-3":_30,"ap-south-1":_32,"ap-south-2":_33,"ap-southeast-1":_32,"ap-southeast-2":_32,"ap-southeast-3":_33,"ap-southeast-4":_33,"ap-southeast-5":[0,{"execute-api":_3,"dualstack":_25,"s3":_3,"s3-accesspoint":_3,"s3-deprecated":_3,"s3-object-lambda":_3,"s3-website":_3}],"ca-central-1":_35,"ca-west-1":[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_34,"s3":_3,"s3-accesspoint":_3,"s3-accesspoint-fips":_3,"s3-fips":_3,"s3-object-lambda":_3,"s3-website":_3}],"eu-central-1":_32,"eu-central-2":_33,"eu-north-1":_31,"eu-south-1":_30,"eu-south-2":_33,"eu-west-1":[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_25,"s3":_3,"s3-accesspoint":_3,"s3-deprecated":_3,"s3-object-lambda":_3,"s3-website":_3,"analytics-gateway":_3,"aws-cloud9":_28,"cloud9":_29}],"eu-west-2":_31,"eu-west-3":_30,"il-central-1":[0,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_25,"s3":_3,"s3-accesspoint":_3,"s3-object-lambda":_3,"s3-website":_3,"aws-cloud9":_28,"cloud9":[0,{"vfs":_3}]}],"me-central-1":_33,"me-south-1":_31,"sa-east-1":_30,"us-east-1":[2,{"execute-api":_3,"emrappui-prod":_3,"emrnotebooks-prod":_3,"emrstudio-prod":_3,"dualstack":_34,"s3":_3,"s3-accesspoint":_3,"s3-accesspoint-fips":_3,"s3-deprecated":_3,"s3-fips":_3,"s3-object-lambda":_3,"s3-website":_3,"analytics-gateway":_3,"aws-cloud9":_28,"cloud9":_29}],"us-east-2":_36,"us-gov-east-1":_38,"us-gov-west-1":_38,"us-west-1":_35,"us-west-2":_36,"compute":_6,"compute-1":_6,"airflow":[0,{"af-south-1":_6,"ap-east-1":_6,"ap-northeast-1":_6,"ap-northeast-2":_6,"ap-northeast-3":_6,"ap-south-1":_6,"ap-south-2":_6,"ap-southeast-1":_6,"ap-southeast-2":_6,"ap-southeast-3":_6,"ap-southeast-4":_6,"ap-southeast-5":_6,"ap-southeast-7":_6,"ca-central-1":_6,"ca-west-1":_6,"eu-central-1":_6,"eu-central-2":_6,"eu-north-1":_6,"eu-south-1":_6,"eu-south-2":_6,"eu-west-1":_6,"eu-west-2":_6,"eu-west-3":_6,"il-central-1":_6,"me-central-1":_6,"me-south-1":_6,"sa-east-1":_6,"us-east-1":_6,"us-east-2":_6,"us-west-1":_6,"us-west-2":_6}],"rds":[0,{"af-south-1":_6,"ap-east-1":_6,"ap-east-2":_6,"ap-northeast-1":_6,"ap-northeast-2":_6,"ap-northeast-3":_6,"ap-south-1":_6,"ap-south-2":_6,"ap-southeast-1":_6,"ap-southeast-2":_6,"ap-southeast-3":_6,"ap-southeast-4":_6,"ap-southeast-5":_6,"ap-southeast-6":_6,"ap-southeast-7":_6,"ca-central-1":_6,"ca-west-1":_6,"eu-central-1":_6,"eu-central-2":_6,"eu-west-1":_6,"eu-west-2":_6,"eu-west-3":_6,"il-central-1":_6,"me-central-1":_6,"me-south-1":_6,"mx-central-1":_6,"sa-east-1":_6,"us-east-1":_6,"us-east-2":_6,"us-gov-east-1":_6,"us-gov-west-1":_6,"us-northeast-1":_6,"us-west-1":_6,"us-west-2":_6}],"s3":_3,"s3-1":_3,"s3-ap-east-1":_3,"s3-ap-northeast-1":_3,"s3-ap-northeast-2":_3,"s3-ap-northeast-3":_3,"s3-ap-south-1":_3,"s3-ap-southeast-1":_3,"s3-ap-southeast-2":_3,"s3-ca-central-1":_3,"s3-eu-central-1":_3,"s3-eu-north-1":_3,"s3-eu-west-1":_3,"s3-eu-west-2":_3,"s3-eu-west-3":_3,"s3-external-1":_3,"s3-fips-us-gov-east-1":_3,"s3-fips-us-gov-west-1":_3,"s3-global":[0,{"accesspoint":[0,{"mrap":_3}]}],"s3-me-south-1":_3,"s3-sa-east-1":_3,"s3-us-east-2":_3,"s3-us-gov-east-1":_3,"s3-us-gov-west-1":_3,"s3-us-west-1":_3,"s3-us-west-2":_3,"s3-website-ap-northeast-1":_3,"s3-website-ap-southeast-1":_3,"s3-website-ap-southeast-2":_3,"s3-website-eu-west-1":_3,"s3-website-sa-east-1":_3,"s3-website-us-east-1":_3,"s3-website-us-gov-west-1":_3,"s3-website-us-west-1":_3,"s3-website-us-west-2":_3,"elb":_6}],"amazoncognito":[0,{"af-south-1":_39,"ap-east-1":_39,"ap-northeast-1":_39,"ap-northeast-2":_39,"ap-northeast-3":_39,"ap-south-1":_39,"ap-south-2":_39,"ap-southeast-1":_39,"ap-southeast-2":_39,"ap-southeast-3":_39,"ap-southeast-4":_39,"ap-southeast-5":_39,"ap-southeast-7":_39,"ca-central-1":_39,"ca-west-1":_39,"eu-central-1":_39,"eu-central-2":_39,"eu-north-1":_39,"eu-south-1":_39,"eu-south-2":_39,"eu-west-1":_39,"eu-west-2":_39,"eu-west-3":_39,"il-central-1":_39,"me-central-1":_39,"me-south-1":_39,"mx-central-1":_39,"sa-east-1":_39,"us-east-1":_40,"us-east-2":_40,"us-gov-east-1":_41,"us-gov-west-1":_41,"us-west-1":_40,"us-west-2":_40}],"amplifyapp":_3,"awsapprunner":_6,"awsapps":_3,"elasticbeanstalk":[2,{"af-south-1":_3,"ap-east-1":_3,"ap-northeast-1":_3,"ap-northeast-2":_3,"ap-northeast-3":_3,"ap-south-1":_3,"ap-southeast-1":_3,"ap-southeast-2":_3,"ap-southeast-3":_3,"ap-southeast-5":_3,"ap-southeast-7":_3,"ca-central-1":_3,"eu-central-1":_3,"eu-north-1":_3,"eu-south-1":_3,"eu-south-2":_3,"eu-west-1":_3,"eu-west-2":_3,"eu-west-3":_3,"il-central-1":_3,"me-central-1":_3,"me-south-1":_3,"sa-east-1":_3,"us-east-1":_3,"us-east-2":_3,"us-gov-east-1":_3,"us-gov-west-1":_3,"us-west-1":_3,"us-west-2":_3}],"awsglobalaccelerator":_3,"siiites":_3,"appspacehosted":_3,"appspaceusercontent":_3,"on-aptible":_3,"myasustor":_3,"balena-devices":_3,"boutir":_3,"bplaced":_3,"cafjs":_3,"canva-apps":_3,"canva-hosted-embed":_3,"canvacode":_3,"rice-labs":_3,"cdn77-storage":_3,"br":_3,"cn":_3,"de":_3,"eu":_3,"jpn":_3,"mex":_3,"ru":_3,"sa":_3,"uk":_3,"us":_3,"za":_3,"clever-cloud":[0,{"services":_6}],"abrdns":_3,"dnsabr":_3,"ip-ddns":_3,"jdevcloud":_3,"wpdevcloud":_3,"cf-ipfs":_3,"cloudflare-ipfs":_3,"trycloudflare":_3,"co":_3,"devinapps":_6,"builtwithdark":_3,"datadetect":[0,{"demo":_3,"instance":_3}],"dattolocal":_3,"dattorelay":_3,"dattoweb":_3,"mydatto":_3,"digitaloceanspaces":_6,"discordsays":_3,"discordsez":_3,"drayddns":_3,"dreamhosters":_3,"durumis":_3,"blogdns":_3,"cechire":_3,"dnsalias":_3,"dnsdojo":_3,"doesntexist":_3,"dontexist":_3,"doomdns":_3,"dyn-o-saur":_3,"dynalias":_3,"dyndns-at-home":_3,"dyndns-at-work":_3,"dyndns-blog":_3,"dyndns-free":_3,"dyndns-home":_3,"dyndns-ip":_3,"dyndns-mail":_3,"dyndns-office":_3,"dyndns-pics":_3,"dyndns-remote":_3,"dyndns-server":_3,"dyndns-web":_3,"dyndns-wiki":_3,"dyndns-work":_3,"est-a-la-maison":_3,"est-a-la-masion":_3,"est-le-patron":_3,"est-mon-blogueur":_3,"from-ak":_3,"from-al":_3,"from-ar":_3,"from-ca":_3,"from-ct":_3,"from-dc":_3,"from-de":_3,"from-fl":_3,"from-ga":_3,"from-hi":_3,"from-ia":_3,"from-id":_3,"from-il":_3,"from-in":_3,"from-ks":_3,"from-ky":_3,"from-ma":_3,"from-md":_3,"from-mi":_3,"from-mn":_3,"from-mo":_3,"from-ms":_3,"from-mt":_3,"from-nc":_3,"from-nd":_3,"from-ne":_3,"from-nh":_3,"from-nj":_3,"from-nm":_3,"from-nv":_3,"from-oh":_3,"from-ok":_3,"from-or":_3,"from-pa":_3,"from-pr":_3,"from-ri":_3,"from-sc":_3,"from-sd":_3,"from-tn":_3,"from-tx":_3,"from-ut":_3,"from-va":_3,"from-vt":_3,"from-wa":_3,"from-wi":_3,"from-wv":_3,"from-wy":_3,"getmyip":_3,"gotdns":_3,"hobby-site":_3,"homelinux":_3,"homeunix":_3,"iamallama":_3,"is-a-anarchist":_3,"is-a-blogger":_3,"is-a-bookkeeper":_3,"is-a-bulls-fan":_3,"is-a-caterer":_3,"is-a-chef":_3,"is-a-conservative":_3,"is-a-cpa":_3,"is-a-cubicle-slave":_3,"is-a-democrat":_3,"is-a-designer":_3,"is-a-doctor":_3,"is-a-financialadvisor":_3,"is-a-geek":_3,"is-a-green":_3,"is-a-guru":_3,"is-a-hard-worker":_3,"is-a-hunter":_3,"is-a-landscaper":_3,"is-a-lawyer":_3,"is-a-liberal":_3,"is-a-libertarian":_3,"is-a-llama":_3,"is-a-musician":_3,"is-a-nascarfan":_3,"is-a-nurse":_3,"is-a-painter":_3,"is-a-personaltrainer":_3,"is-a-photographer":_3,"is-a-player":_3,"is-a-republican":_3,"is-a-rockstar":_3,"is-a-socialist":_3,"is-a-student":_3,"is-a-teacher":_3,"is-a-techie":_3,"is-a-therapist":_3,"is-an-accountant":_3,"is-an-actor":_3,"is-an-actress":_3,"is-an-anarchist":_3,"is-an-artist":_3,"is-an-engineer":_3,"is-an-entertainer":_3,"is-certified":_3,"is-gone":_3,"is-into-anime":_3,"is-into-cars":_3,"is-into-cartoons":_3,"is-into-games":_3,"is-leet":_3,"is-not-certified":_3,"is-slick":_3,"is-uberleet":_3,"is-with-theband":_3,"isa-geek":_3,"isa-hockeynut":_3,"issmarterthanyou":_3,"likes-pie":_3,"likescandy":_3,"neat-url":_3,"saves-the-whales":_3,"selfip":_3,"sells-for-less":_3,"sells-for-u":_3,"servebbs":_3,"simple-url":_3,"space-to-rent":_3,"teaches-yoga":_3,"writesthisblog":_3,"ddnsfree":_3,"ddnsgeek":_3,"giize":_3,"gleeze":_3,"kozow":_3,"loseyourip":_3,"ooguy":_3,"theworkpc":_3,"mytuleap":_3,"tuleap-partners":_3,"encoreapi":_3,"evennode":[0,{"eu-1":_3,"eu-2":_3,"eu-3":_3,"eu-4":_3,"us-1":_3,"us-2":_3,"us-3":_3,"us-4":_3}],"onfabrica":_3,"fastly-edge":_3,"fastly-terrarium":_3,"fastvps-server":_3,"mydobiss":_3,"firebaseapp":_3,"fldrv":_3,"forgeblocks":_3,"framercanvas":_3,"freebox-os":_3,"freeboxos":_3,"freemyip":_3,"aliases121":_3,"gentapps":_3,"gentlentapis":_3,"githubusercontent":_3,"0emm":_6,"appspot":[2,{"r":_6}],"blogspot":_3,"codespot":_3,"googleapis":_3,"googlecode":_3,"pagespeedmobilizer":_3,"withgoogle":_3,"withyoutube":_3,"grayjayleagues":_3,"hatenablog":_3,"hatenadiary":_3,"herokuapp":_3,"gr":_3,"smushcdn":_3,"wphostedmail":_3,"wpmucdn":_3,"pixolino":_3,"apps-1and1":_3,"live-website":_3,"webspace-host":_3,"dopaas":_3,"hosted-by-previder":_43,"hosteur":[0,{"rag-cloud":_3,"rag-cloud-ch":_3}],"ik-server":[0,{"jcloud":_3,"jcloud-ver-jpc":_3}],"jelastic":[0,{"demo":_3}],"massivegrid":_43,"wafaicloud":[0,{"jed":_3,"ryd":_3}],"eu1-plenit":_3,"la1-plenit":_3,"us1-plenit":_3,"webadorsite":_3,"joyent":[0,{"cns":_6}],"on-forge":_3,"on-vapor":_3,"lpusercontent":_3,"linode":[0,{"members":_3,"nodebalancer":_6}],"linodeobjects":_6,"linodeusercontent":[0,{"ip":_3}],"localtonet":_3,"lovableproject":_3,"barsycenter":_3,"barsyonline":_3,"lutrausercontent":_6,"modelscape":_3,"mwcloudnonprod":_3,"polyspace":_3,"mazeplay":_3,"miniserver":_3,"atmeta":_3,"fbsbx":_42,"meteorapp":_44,"routingthecloud":_3,"same-app":_3,"same-preview":_3,"mydbserver":_3,"mochausercontent":_3,"hostedpi":_3,"mythic-beasts":[0,{"caracal":_3,"customer":_3,"fentiger":_3,"lynx":_3,"ocelot":_3,"oncilla":_3,"onza":_3,"sphinx":_3,"vs":_3,"x":_3,"yali":_3}],"nospamproxy":[0,{"cloud":[2,{"o365":_3}]}],"4u":_3,"nfshost":_3,"3utilities":_3,"blogsyte":_3,"ciscofreak":_3,"damnserver":_3,"ddnsking":_3,"ditchyourip":_3,"dnsiskinky":_3,"dynns":_3,"geekgalaxy":_3,"health-carereform":_3,"homesecuritymac":_3,"homesecuritypc":_3,"myactivedirectory":_3,"mysecuritycamera":_3,"myvnc":_3,"net-freaks":_3,"onthewifi":_3,"point2this":_3,"quicksytes":_3,"securitytactics":_3,"servebeer":_3,"servecounterstrike":_3,"serveexchange":_3,"serveftp":_3,"servegame":_3,"servehalflife":_3,"servehttp":_3,"servehumour":_3,"serveirc":_3,"servemp3":_3,"servep2p":_3,"servepics":_3,"servequake":_3,"servesarcasm":_3,"stufftoread":_3,"unusualperson":_3,"workisboring":_3,"myiphost":_3,"observableusercontent":[0,{"static":_3}],"simplesite":_3,"oaiusercontent":_6,"orsites":_3,"operaunite":_3,"customer-oci":[0,{"*":_3,"oci":_6,"ocp":_6,"ocs":_6}],"oraclecloudapps":_6,"oraclegovcloudapps":_6,"authgear-staging":_3,"authgearapps":_3,"skygearapp":_3,"outsystemscloud":_3,"ownprovider":_3,"pgfog":_3,"pagexl":_3,"gotpantheon":_3,"paywhirl":_6,"upsunapp":_3,"postman-echo":_3,"prgmr":[0,{"xen":_3}],"project-study":[0,{"dev":_3}],"pythonanywhere":_44,"qa2":_3,"alpha-myqnapcloud":_3,"dev-myqnapcloud":_3,"mycloudnas":_3,"mynascloud":_3,"myqnapcloud":_3,"qualifioapp":_3,"ladesk":_3,"qualyhqpartner":_6,"qualyhqportal":_6,"qbuser":_3,"quipelements":_6,"rackmaze":_3,"readthedocs-hosted":_3,"rhcloud":_3,"onrender":_3,"render":_45,"subsc-pay":_3,"180r":_3,"dojin":_3,"sakuratan":_3,"sakuraweb":_3,"x0":_3,"code":[0,{"builder":_6,"dev-builder":_6,"stg-builder":_6}],"salesforce":[0,{"platform":[0,{"code-builder-stg":[0,{"test":[0,{"001":_6}]}]}]}],"logoip":_3,"scrysec":_3,"firewall-gateway":_3,"myshopblocks":_3,"myshopify":_3,"shopitsite":_3,"1kapp":_3,"appchizi":_3,"applinzi":_3,"sinaapp":_3,"vipsinaapp":_3,"streamlitapp":_3,"try-snowplow":_3,"playstation-cloud":_3,"myspreadshop":_3,"w-corp-staticblitz":_3,"w-credentialless-staticblitz":_3,"w-staticblitz":_3,"stackhero-network":_3,"stdlib":[0,{"api":_3}],"strapiapp":[2,{"media":_3}],"streak-link":_3,"streaklinks":_3,"streakusercontent":_3,"temp-dns":_3,"dsmynas":_3,"familyds":_3,"mytabit":_3,"taveusercontent":_3,"tb-hosting":_46,"reservd":_3,"thingdustdata":_3,"townnews-staging":_3,"typeform":[0,{"pro":_3}],"hk":_3,"it":_3,"deus-canvas":_3,"vultrobjects":_6,"wafflecell":_3,"hotelwithflight":_3,"reserve-online":_3,"cprapid":_3,"pleskns":_3,"remotewd":_3,"wiardweb":[0,{"pages":_3}],"wixsite":_3,"wixstudio":_3,"messwithdns":_3,"woltlab-demo":_3,"wpenginepowered":[2,{"js":_3}],"xnbay":[2,{"u2":_3,"u2-local":_3}],"yolasite":_3}],"coop":_2,"cr":[1,{"ac":_2,"co":_2,"ed":_2,"fi":_2,"go":_2,"or":_2,"sa":_2}],"cu":[1,{"com":_2,"edu":_2,"gob":_2,"inf":_2,"nat":_2,"net":_2,"org":_2}],"cv":[1,{"com":_2,"edu":_2,"id":_2,"int":_2,"net":_2,"nome":_2,"org":_2,"publ":_2}],"cw":_47,"cx":[1,{"gov":_2,"cloudns":_3,"ath":_3,"info":_3,"assessments":_3,"calculators":_3,"funnels":_3,"paynow":_3,"quizzes":_3,"researched":_3,"tests":_3}],"cy":[1,{"ac":_2,"biz":_2,"com":[1,{"scaleforce":_48}],"ekloges":_2,"gov":_2,"ltd":_2,"mil":_2,"net":_2,"org":_2,"press":_2,"pro":_2,"tm":_2}],"cz":[1,{"gov":_2,"contentproxy9":[0,{"rsc":_3}],"realm":_3,"e4":_3,"co":_3,"metacentrum":[0,{"cloud":_6,"custom":_3}],"muni":[0,{"cloud":[0,{"flt":_3,"usr":_3}]}]}],"de":[1,{"bplaced":_3,"square7":_3,"com":_3,"cosidns":_49,"dnsupdater":_3,"dynamisches-dns":_3,"internet-dns":_3,"l-o-g-i-n":_3,"ddnss":[2,{"dyn":_3,"dyndns":_3}],"dyn-ip24":_3,"dyndns1":_3,"home-webserver":[2,{"dyn":_3}],"myhome-server":_3,"dnshome":_3,"fuettertdasnetz":_3,"isteingeek":_3,"istmein":_3,"lebtimnetz":_3,"leitungsen":_3,"traeumtgerade":_3,"frusky":_6,"goip":_3,"xn--gnstigbestellen-zvb":_3,"günstigbestellen":_3,"xn--gnstigliefern-wob":_3,"günstigliefern":_3,"hs-heilbronn":[0,{"it":[0,{"pages":_3,"pages-research":_3}]}],"dyn-berlin":_3,"in-berlin":_3,"in-brb":_3,"in-butter":_3,"in-dsl":_3,"in-vpn":_3,"iservschule":_3,"mein-iserv":_3,"schuldock":_3,"schulplattform":_3,"schulserver":_3,"test-iserv":_3,"keymachine":_3,"co":_3,"git-repos":_3,"lcube-server":_3,"svn-repos":_3,"barsy":_3,"webspaceconfig":_3,"123webseite":_3,"rub":_3,"ruhr-uni-bochum":[2,{"noc":[0,{"io":_3}]}],"logoip":_3,"firewall-gateway":_3,"my-gateway":_3,"my-router":_3,"spdns":_3,"my":_3,"speedpartner":[0,{"customer":_3}],"myspreadshop":_3,"taifun-dns":_3,"12hp":_3,"2ix":_3,"4lima":_3,"lima-city":_3,"dd-dns":_3,"dray-dns":_3,"draydns":_3,"dyn-vpn":_3,"dynvpn":_3,"mein-vigor":_3,"my-vigor":_3,"my-wan":_3,"syno-ds":_3,"synology-diskstation":_3,"synology-ds":_3,"virtual-user":_3,"virtualuser":_3,"community-pro":_3,"diskussionsbereich":_3,"xenonconnect":_6}],"dj":_2,"dk":[1,{"biz":_3,"co":_3,"firm":_3,"reg":_3,"store":_3,"123hjemmeside":_3,"myspreadshop":_3}],"dm":_51,"do":[1,{"art":_2,"com":_2,"edu":_2,"gob":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"sld":_2,"web":_2}],"dz":[1,{"art":_2,"asso":_2,"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"pol":_2,"soc":_2,"tm":_2}],"ec":[1,{"abg":_2,"adm":_2,"agron":_2,"arqt":_2,"art":_2,"bar":_2,"chef":_2,"com":_2,"cont":_2,"cpa":_2,"cue":_2,"dent":_2,"dgn":_2,"disco":_2,"doc":_2,"edu":_2,"eng":_2,"esm":_2,"fin":_2,"fot":_2,"gal":_2,"gob":_2,"gov":_2,"gye":_2,"ibr":_2,"info":_2,"k12":_2,"lat":_2,"loj":_2,"med":_2,"mil":_2,"mktg":_2,"mon":_2,"net":_2,"ntr":_2,"odont":_2,"org":_2,"pro":_2,"prof":_2,"psic":_2,"psiq":_2,"pub":_2,"rio":_2,"rrpp":_2,"sal":_2,"tech":_2,"tul":_2,"tur":_2,"uio":_2,"vet":_2,"xxx":_2,"base":_3,"official":_3}],"edu":[1,{"rit":[0,{"git-pages":_3}]}],"ee":[1,{"aip":_2,"com":_2,"edu":_2,"fie":_2,"gov":_2,"lib":_2,"med":_2,"org":_2,"pri":_2,"riik":_2}],"eg":[1,{"ac":_2,"com":_2,"edu":_2,"eun":_2,"gov":_2,"info":_2,"me":_2,"mil":_2,"name":_2,"net":_2,"org":_2,"sci":_2,"sport":_2,"tv":_2}],"er":_20,"es":[1,{"com":_2,"edu":_2,"gob":_2,"nom":_2,"org":_2,"123miweb":_3,"myspreadshop":_3}],"et":[1,{"biz":_2,"com":_2,"edu":_2,"gov":_2,"info":_2,"name":_2,"net":_2,"org":_2}],"eu":[1,{"cloudns":_3,"prvw":_3,"dogado":[0,{"jelastic":_3}],"barsy":_3,"spdns":_3,"nxa":_6,"directwp":_3,"transurl":_6,"diskstation":_3}],"fi":[1,{"aland":_2,"dy":_3,"xn--hkkinen-5wa":_3,"häkkinen":_3,"iki":_3,"cloudplatform":[0,{"fi":_3}],"datacenter":[0,{"demo":_3,"paas":_3}],"kapsi":_3,"123kotisivu":_3,"myspreadshop":_3}],"fj":[1,{"ac":_2,"biz":_2,"com":_2,"edu":_2,"gov":_2,"id":_2,"info":_2,"mil":_2,"name":_2,"net":_2,"org":_2,"pro":_2}],"fk":_20,"fm":[1,{"com":_2,"edu":_2,"net":_2,"org":_2,"radio":_3,"user":_6}],"fo":_2,"fr":[1,{"asso":_2,"com":_2,"gouv":_2,"nom":_2,"prd":_2,"tm":_2,"avoues":_2,"cci":_2,"greta":_2,"huissier-justice":_2,"en-root":_3,"fbx-os":_3,"fbxos":_3,"freebox-os":_3,"freeboxos":_3,"goupile":_3,"123siteweb":_3,"on-web":_3,"chirurgiens-dentistes-en-france":_3,"dedibox":_3,"aeroport":_3,"avocat":_3,"chambagri":_3,"chirurgiens-dentistes":_3,"experts-comptables":_3,"medecin":_3,"notaires":_3,"pharmacien":_3,"port":_3,"veterinaire":_3,"myspreadshop":_3,"ynh":_3}],"ga":_2,"gb":_2,"gd":[1,{"edu":_2,"gov":_2}],"ge":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"pvt":_2,"school":_2}],"gf":_2,"gg":[1,{"co":_2,"net":_2,"org":_2,"ply":[0,{"at":_6,"d6":_3}],"botdash":_3,"kaas":_3,"stackit":_3,"panel":[2,{"daemon":_3}]}],"gh":[1,{"biz":_2,"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2}],"gi":[1,{"com":_2,"edu":_2,"gov":_2,"ltd":_2,"mod":_2,"org":_2}],"gl":[1,{"co":_2,"com":_2,"edu":_2,"net":_2,"org":_2}],"gm":_2,"gn":[1,{"ac":_2,"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2}],"gov":_2,"gp":[1,{"asso":_2,"com":_2,"edu":_2,"mobi":_2,"net":_2,"org":_2}],"gq":_2,"gr":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"barsy":_3,"simplesite":_3}],"gs":_2,"gt":[1,{"com":_2,"edu":_2,"gob":_2,"ind":_2,"mil":_2,"net":_2,"org":_2}],"gu":[1,{"com":_2,"edu":_2,"gov":_2,"guam":_2,"info":_2,"net":_2,"org":_2,"web":_2}],"gw":[1,{"nx":_3}],"gy":_51,"hk":[1,{"com":_2,"edu":_2,"gov":_2,"idv":_2,"net":_2,"org":_2,"xn--ciqpn":_2,"个人":_2,"xn--gmqw5a":_2,"個人":_2,"xn--55qx5d":_2,"公司":_2,"xn--mxtq1m":_2,"政府":_2,"xn--lcvr32d":_2,"敎育":_2,"xn--wcvs22d":_2,"教育":_2,"xn--gmq050i":_2,"箇人":_2,"xn--uc0atv":_2,"組織":_2,"xn--uc0ay4a":_2,"組织":_2,"xn--od0alg":_2,"網絡":_2,"xn--zf0avx":_2,"網络":_2,"xn--mk0axi":_2,"组織":_2,"xn--tn0ag":_2,"组织":_2,"xn--od0aq3b":_2,"网絡":_2,"xn--io0a7i":_2,"网络":_2,"inc":_3,"ltd":_3}],"hm":_2,"hn":[1,{"com":_2,"edu":_2,"gob":_2,"mil":_2,"net":_2,"org":_2}],"hr":[1,{"com":_2,"from":_2,"iz":_2,"name":_2,"brendly":_19}],"ht":[1,{"adult":_2,"art":_2,"asso":_2,"com":_2,"coop":_2,"edu":_2,"firm":_2,"gouv":_2,"info":_2,"med":_2,"net":_2,"org":_2,"perso":_2,"pol":_2,"pro":_2,"rel":_2,"shop":_2,"rt":_3}],"hu":[1,{"2000":_2,"agrar":_2,"bolt":_2,"casino":_2,"city":_2,"co":_2,"erotica":_2,"erotika":_2,"film":_2,"forum":_2,"games":_2,"hotel":_2,"info":_2,"ingatlan":_2,"jogasz":_2,"konyvelo":_2,"lakas":_2,"media":_2,"news":_2,"org":_2,"priv":_2,"reklam":_2,"sex":_2,"shop":_2,"sport":_2,"suli":_2,"szex":_2,"tm":_2,"tozsde":_2,"utazas":_2,"video":_2}],"id":[1,{"ac":_2,"biz":_2,"co":_2,"desa":_2,"go":_2,"kop":_2,"mil":_2,"my":_2,"net":_2,"or":_2,"ponpes":_2,"sch":_2,"web":_2,"e":_3,"zone":_3}],"ie":[1,{"gov":_2,"myspreadshop":_3}],"il":[1,{"ac":_2,"co":[1,{"ravpage":_3,"mytabit":_3,"tabitorder":_3}],"gov":_2,"idf":_2,"k12":_2,"muni":_2,"net":_2,"org":_2}],"xn--4dbrk0ce":[1,{"xn--4dbgdty6c":_2,"xn--5dbhl8d":_2,"xn--8dbq2a":_2,"xn--hebda8b":_2}],"ישראל":[1,{"אקדמיה":_2,"ישוב":_2,"צהל":_2,"ממשל":_2}],"im":[1,{"ac":_2,"co":[1,{"ltd":_2,"plc":_2}],"com":_2,"net":_2,"org":_2,"tt":_2,"tv":_2}],"in":[1,{"5g":_2,"6g":_2,"ac":_2,"ai":_2,"am":_2,"bank":_2,"bihar":_2,"biz":_2,"business":_2,"ca":_2,"cn":_2,"co":_2,"com":_2,"coop":_2,"cs":_2,"delhi":_2,"dr":_2,"edu":_2,"er":_2,"fin":_2,"firm":_2,"gen":_2,"gov":_2,"gujarat":_2,"ind":_2,"info":_2,"int":_2,"internet":_2,"io":_2,"me":_2,"mil":_2,"net":_2,"nic":_2,"org":_2,"pg":_2,"post":_2,"pro":_2,"res":_2,"travel":_2,"tv":_2,"uk":_2,"up":_2,"us":_2,"cloudns":_3,"barsy":_3,"web":_3,"supabase":_3}],"info":[1,{"cloudns":_3,"dynamic-dns":_3,"barrel-of-knowledge":_3,"barrell-of-knowledge":_3,"dyndns":_3,"for-our":_3,"groks-the":_3,"groks-this":_3,"here-for-more":_3,"knowsitall":_3,"selfip":_3,"webhop":_3,"barsy":_3,"mayfirst":_3,"mittwald":_3,"mittwaldserver":_3,"typo3server":_3,"dvrcam":_3,"ilovecollege":_3,"no-ip":_3,"forumz":_3,"nsupdate":_3,"dnsupdate":_3,"v-info":_3}],"int":[1,{"eu":_2}],"io":[1,{"2038":_3,"co":_2,"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"nom":_2,"org":_2,"on-acorn":_6,"myaddr":_3,"apigee":_3,"b-data":_3,"beagleboard":_3,"bitbucket":_3,"bluebite":_3,"boxfuse":_3,"brave":_7,"browsersafetymark":_3,"bubble":_54,"bubbleapps":_3,"bigv":[0,{"uk0":_3}],"cleverapps":_3,"cloudbeesusercontent":_3,"dappnode":[0,{"dyndns":_3}],"darklang":_3,"definima":_3,"dedyn":_3,"icp0":_55,"icp1":_55,"qzz":_3,"fh-muenster":_3,"shw":_3,"forgerock":[0,{"id":_3}],"gitbook":_3,"github":_3,"gitlab":_3,"lolipop":_3,"hasura-app":_3,"hostyhosting":_3,"hypernode":_3,"moonscale":_6,"beebyte":_43,"beebyteapp":[0,{"sekd1":_3}],"jele":_3,"webthings":_3,"loginline":_3,"barsy":_3,"azurecontainer":_6,"ngrok":[2,{"ap":_3,"au":_3,"eu":_3,"in":_3,"jp":_3,"sa":_3,"us":_3}],"nodeart":[0,{"stage":_3}],"pantheonsite":_3,"pstmn":[2,{"mock":_3}],"protonet":_3,"qcx":[2,{"sys":_6}],"qoto":_3,"vaporcloud":_3,"myrdbx":_3,"rb-hosting":_46,"on-k3s":_6,"on-rio":_6,"readthedocs":_3,"resindevice":_3,"resinstaging":[0,{"devices":_3}],"hzc":_3,"sandcats":_3,"scrypted":[0,{"client":_3}],"mo-siemens":_3,"lair":_42,"stolos":_6,"musician":_3,"utwente":_3,"edugit":_3,"telebit":_3,"thingdust":[0,{"dev":_56,"disrec":_56,"prod":_57,"testing":_56}],"tickets":_3,"webflow":_3,"webflowtest":_3,"editorx":_3,"wixstudio":_3,"basicserver":_3,"virtualserver":_3}],"iq":_5,"ir":[1,{"ac":_2,"co":_2,"gov":_2,"id":_2,"net":_2,"org":_2,"sch":_2,"xn--mgba3a4f16a":_2,"ایران":_2,"xn--mgba3a4fra":_2,"ايران":_2,"arvanedge":_3,"vistablog":_3}],"is":_2,"it":[1,{"edu":_2,"gov":_2,"abr":_2,"abruzzo":_2,"aosta-valley":_2,"aostavalley":_2,"bas":_2,"basilicata":_2,"cal":_2,"calabria":_2,"cam":_2,"campania":_2,"emilia-romagna":_2,"emiliaromagna":_2,"emr":_2,"friuli-v-giulia":_2,"friuli-ve-giulia":_2,"friuli-vegiulia":_2,"friuli-venezia-giulia":_2,"friuli-veneziagiulia":_2,"friuli-vgiulia":_2,"friuliv-giulia":_2,"friulive-giulia":_2,"friulivegiulia":_2,"friulivenezia-giulia":_2,"friuliveneziagiulia":_2,"friulivgiulia":_2,"fvg":_2,"laz":_2,"lazio":_2,"lig":_2,"liguria":_2,"lom":_2,"lombardia":_2,"lombardy":_2,"lucania":_2,"mar":_2,"marche":_2,"mol":_2,"molise":_2,"piedmont":_2,"piemonte":_2,"pmn":_2,"pug":_2,"puglia":_2,"sar":_2,"sardegna":_2,"sardinia":_2,"sic":_2,"sicilia":_2,"sicily":_2,"taa":_2,"tos":_2,"toscana":_2,"trentin-sud-tirol":_2,"xn--trentin-sd-tirol-rzb":_2,"trentin-süd-tirol":_2,"trentin-sudtirol":_2,"xn--trentin-sdtirol-7vb":_2,"trentin-südtirol":_2,"trentin-sued-tirol":_2,"trentin-suedtirol":_2,"trentino":_2,"trentino-a-adige":_2,"trentino-aadige":_2,"trentino-alto-adige":_2,"trentino-altoadige":_2,"trentino-s-tirol":_2,"trentino-stirol":_2,"trentino-sud-tirol":_2,"xn--trentino-sd-tirol-c3b":_2,"trentino-süd-tirol":_2,"trentino-sudtirol":_2,"xn--trentino-sdtirol-szb":_2,"trentino-südtirol":_2,"trentino-sued-tirol":_2,"trentino-suedtirol":_2,"trentinoa-adige":_2,"trentinoaadige":_2,"trentinoalto-adige":_2,"trentinoaltoadige":_2,"trentinos-tirol":_2,"trentinostirol":_2,"trentinosud-tirol":_2,"xn--trentinosd-tirol-rzb":_2,"trentinosüd-tirol":_2,"trentinosudtirol":_2,"xn--trentinosdtirol-7vb":_2,"trentinosüdtirol":_2,"trentinosued-tirol":_2,"trentinosuedtirol":_2,"trentinsud-tirol":_2,"xn--trentinsd-tirol-6vb":_2,"trentinsüd-tirol":_2,"trentinsudtirol":_2,"xn--trentinsdtirol-nsb":_2,"trentinsüdtirol":_2,"trentinsued-tirol":_2,"trentinsuedtirol":_2,"tuscany":_2,"umb":_2,"umbria":_2,"val-d-aosta":_2,"val-daosta":_2,"vald-aosta":_2,"valdaosta":_2,"valle-aosta":_2,"valle-d-aosta":_2,"valle-daosta":_2,"valleaosta":_2,"valled-aosta":_2,"valledaosta":_2,"vallee-aoste":_2,"xn--valle-aoste-ebb":_2,"vallée-aoste":_2,"vallee-d-aoste":_2,"xn--valle-d-aoste-ehb":_2,"vallée-d-aoste":_2,"valleeaoste":_2,"xn--valleaoste-e7a":_2,"valléeaoste":_2,"valleedaoste":_2,"xn--valledaoste-ebb":_2,"valléedaoste":_2,"vao":_2,"vda":_2,"ven":_2,"veneto":_2,"ag":_2,"agrigento":_2,"al":_2,"alessandria":_2,"alto-adige":_2,"altoadige":_2,"an":_2,"ancona":_2,"andria-barletta-trani":_2,"andria-trani-barletta":_2,"andriabarlettatrani":_2,"andriatranibarletta":_2,"ao":_2,"aosta":_2,"aoste":_2,"ap":_2,"aq":_2,"aquila":_2,"ar":_2,"arezzo":_2,"ascoli-piceno":_2,"ascolipiceno":_2,"asti":_2,"at":_2,"av":_2,"avellino":_2,"ba":_2,"balsan":_2,"balsan-sudtirol":_2,"xn--balsan-sdtirol-nsb":_2,"balsan-südtirol":_2,"balsan-suedtirol":_2,"bari":_2,"barletta-trani-andria":_2,"barlettatraniandria":_2,"belluno":_2,"benevento":_2,"bergamo":_2,"bg":_2,"bi":_2,"biella":_2,"bl":_2,"bn":_2,"bo":_2,"bologna":_2,"bolzano":_2,"bolzano-altoadige":_2,"bozen":_2,"bozen-sudtirol":_2,"xn--bozen-sdtirol-2ob":_2,"bozen-südtirol":_2,"bozen-suedtirol":_2,"br":_2,"brescia":_2,"brindisi":_2,"bs":_2,"bt":_2,"bulsan":_2,"bulsan-sudtirol":_2,"xn--bulsan-sdtirol-nsb":_2,"bulsan-südtirol":_2,"bulsan-suedtirol":_2,"bz":_2,"ca":_2,"cagliari":_2,"caltanissetta":_2,"campidano-medio":_2,"campidanomedio":_2,"campobasso":_2,"carbonia-iglesias":_2,"carboniaiglesias":_2,"carrara-massa":_2,"carraramassa":_2,"caserta":_2,"catania":_2,"catanzaro":_2,"cb":_2,"ce":_2,"cesena-forli":_2,"xn--cesena-forl-mcb":_2,"cesena-forlì":_2,"cesenaforli":_2,"xn--cesenaforl-i8a":_2,"cesenaforlì":_2,"ch":_2,"chieti":_2,"ci":_2,"cl":_2,"cn":_2,"co":_2,"como":_2,"cosenza":_2,"cr":_2,"cremona":_2,"crotone":_2,"cs":_2,"ct":_2,"cuneo":_2,"cz":_2,"dell-ogliastra":_2,"dellogliastra":_2,"en":_2,"enna":_2,"fc":_2,"fe":_2,"fermo":_2,"ferrara":_2,"fg":_2,"fi":_2,"firenze":_2,"florence":_2,"fm":_2,"foggia":_2,"forli-cesena":_2,"xn--forl-cesena-fcb":_2,"forlì-cesena":_2,"forlicesena":_2,"xn--forlcesena-c8a":_2,"forlìcesena":_2,"fr":_2,"frosinone":_2,"ge":_2,"genoa":_2,"genova":_2,"go":_2,"gorizia":_2,"gr":_2,"grosseto":_2,"iglesias-carbonia":_2,"iglesiascarbonia":_2,"im":_2,"imperia":_2,"is":_2,"isernia":_2,"kr":_2,"la-spezia":_2,"laquila":_2,"laspezia":_2,"latina":_2,"lc":_2,"le":_2,"lecce":_2,"lecco":_2,"li":_2,"livorno":_2,"lo":_2,"lodi":_2,"lt":_2,"lu":_2,"lucca":_2,"macerata":_2,"mantova":_2,"massa-carrara":_2,"massacarrara":_2,"matera":_2,"mb":_2,"mc":_2,"me":_2,"medio-campidano":_2,"mediocampidano":_2,"messina":_2,"mi":_2,"milan":_2,"milano":_2,"mn":_2,"mo":_2,"modena":_2,"monza":_2,"monza-brianza":_2,"monza-e-della-brianza":_2,"monzabrianza":_2,"monzaebrianza":_2,"monzaedellabrianza":_2,"ms":_2,"mt":_2,"na":_2,"naples":_2,"napoli":_2,"no":_2,"novara":_2,"nu":_2,"nuoro":_2,"og":_2,"ogliastra":_2,"olbia-tempio":_2,"olbiatempio":_2,"or":_2,"oristano":_2,"ot":_2,"pa":_2,"padova":_2,"padua":_2,"palermo":_2,"parma":_2,"pavia":_2,"pc":_2,"pd":_2,"pe":_2,"perugia":_2,"pesaro-urbino":_2,"pesarourbino":_2,"pescara":_2,"pg":_2,"pi":_2,"piacenza":_2,"pisa":_2,"pistoia":_2,"pn":_2,"po":_2,"pordenone":_2,"potenza":_2,"pr":_2,"prato":_2,"pt":_2,"pu":_2,"pv":_2,"pz":_2,"ra":_2,"ragusa":_2,"ravenna":_2,"rc":_2,"re":_2,"reggio-calabria":_2,"reggio-emilia":_2,"reggiocalabria":_2,"reggioemilia":_2,"rg":_2,"ri":_2,"rieti":_2,"rimini":_2,"rm":_2,"rn":_2,"ro":_2,"roma":_2,"rome":_2,"rovigo":_2,"sa":_2,"salerno":_2,"sassari":_2,"savona":_2,"si":_2,"siena":_2,"siracusa":_2,"so":_2,"sondrio":_2,"sp":_2,"sr":_2,"ss":_2,"xn--sdtirol-n2a":_2,"südtirol":_2,"suedtirol":_2,"sv":_2,"ta":_2,"taranto":_2,"te":_2,"tempio-olbia":_2,"tempioolbia":_2,"teramo":_2,"terni":_2,"tn":_2,"to":_2,"torino":_2,"tp":_2,"tr":_2,"trani-andria-barletta":_2,"trani-barletta-andria":_2,"traniandriabarletta":_2,"tranibarlettaandria":_2,"trapani":_2,"trento":_2,"treviso":_2,"trieste":_2,"ts":_2,"turin":_2,"tv":_2,"ud":_2,"udine":_2,"urbino-pesaro":_2,"urbinopesaro":_2,"va":_2,"varese":_2,"vb":_2,"vc":_2,"ve":_2,"venezia":_2,"venice":_2,"verbania":_2,"vercelli":_2,"verona":_2,"vi":_2,"vibo-valentia":_2,"vibovalentia":_2,"vicenza":_2,"viterbo":_2,"vr":_2,"vs":_2,"vt":_2,"vv":_2,"12chars":_3,"ibxos":_3,"iliadboxos":_3,"neen":[0,{"jc":_3}],"123homepage":_3,"16-b":_3,"32-b":_3,"64-b":_3,"myspreadshop":_3,"syncloud":_3}],"je":[1,{"co":_2,"net":_2,"org":_2,"of":_3}],"jm":_20,"jo":[1,{"agri":_2,"ai":_2,"com":_2,"edu":_2,"eng":_2,"fm":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"per":_2,"phd":_2,"sch":_2,"tv":_2}],"jobs":_2,"jp":[1,{"ac":_2,"ad":_2,"co":_2,"ed":_2,"go":_2,"gr":_2,"lg":_2,"ne":[1,{"aseinet":_53,"gehirn":_3,"ivory":_3,"mail-box":_3,"mints":_3,"mokuren":_3,"opal":_3,"sakura":_3,"sumomo":_3,"topaz":_3}],"or":_2,"aichi":[1,{"aisai":_2,"ama":_2,"anjo":_2,"asuke":_2,"chiryu":_2,"chita":_2,"fuso":_2,"gamagori":_2,"handa":_2,"hazu":_2,"hekinan":_2,"higashiura":_2,"ichinomiya":_2,"inazawa":_2,"inuyama":_2,"isshiki":_2,"iwakura":_2,"kanie":_2,"kariya":_2,"kasugai":_2,"kira":_2,"kiyosu":_2,"komaki":_2,"konan":_2,"kota":_2,"mihama":_2,"miyoshi":_2,"nishio":_2,"nisshin":_2,"obu":_2,"oguchi":_2,"oharu":_2,"okazaki":_2,"owariasahi":_2,"seto":_2,"shikatsu":_2,"shinshiro":_2,"shitara":_2,"tahara":_2,"takahama":_2,"tobishima":_2,"toei":_2,"togo":_2,"tokai":_2,"tokoname":_2,"toyoake":_2,"toyohashi":_2,"toyokawa":_2,"toyone":_2,"toyota":_2,"tsushima":_2,"yatomi":_2}],"akita":[1,{"akita":_2,"daisen":_2,"fujisato":_2,"gojome":_2,"hachirogata":_2,"happou":_2,"higashinaruse":_2,"honjo":_2,"honjyo":_2,"ikawa":_2,"kamikoani":_2,"kamioka":_2,"katagami":_2,"kazuno":_2,"kitaakita":_2,"kosaka":_2,"kyowa":_2,"misato":_2,"mitane":_2,"moriyoshi":_2,"nikaho":_2,"noshiro":_2,"odate":_2,"oga":_2,"ogata":_2,"semboku":_2,"yokote":_2,"yurihonjo":_2}],"aomori":[1,{"aomori":_2,"gonohe":_2,"hachinohe":_2,"hashikami":_2,"hiranai":_2,"hirosaki":_2,"itayanagi":_2,"kuroishi":_2,"misawa":_2,"mutsu":_2,"nakadomari":_2,"noheji":_2,"oirase":_2,"owani":_2,"rokunohe":_2,"sannohe":_2,"shichinohe":_2,"shingo":_2,"takko":_2,"towada":_2,"tsugaru":_2,"tsuruta":_2}],"chiba":[1,{"abiko":_2,"asahi":_2,"chonan":_2,"chosei":_2,"choshi":_2,"chuo":_2,"funabashi":_2,"futtsu":_2,"hanamigawa":_2,"ichihara":_2,"ichikawa":_2,"ichinomiya":_2,"inzai":_2,"isumi":_2,"kamagaya":_2,"kamogawa":_2,"kashiwa":_2,"katori":_2,"katsuura":_2,"kimitsu":_2,"kisarazu":_2,"kozaki":_2,"kujukuri":_2,"kyonan":_2,"matsudo":_2,"midori":_2,"mihama":_2,"minamiboso":_2,"mobara":_2,"mutsuzawa":_2,"nagara":_2,"nagareyama":_2,"narashino":_2,"narita":_2,"noda":_2,"oamishirasato":_2,"omigawa":_2,"onjuku":_2,"otaki":_2,"sakae":_2,"sakura":_2,"shimofusa":_2,"shirako":_2,"shiroi":_2,"shisui":_2,"sodegaura":_2,"sosa":_2,"tako":_2,"tateyama":_2,"togane":_2,"tohnosho":_2,"tomisato":_2,"urayasu":_2,"yachimata":_2,"yachiyo":_2,"yokaichiba":_2,"yokoshibahikari":_2,"yotsukaido":_2}],"ehime":[1,{"ainan":_2,"honai":_2,"ikata":_2,"imabari":_2,"iyo":_2,"kamijima":_2,"kihoku":_2,"kumakogen":_2,"masaki":_2,"matsuno":_2,"matsuyama":_2,"namikata":_2,"niihama":_2,"ozu":_2,"saijo":_2,"seiyo":_2,"shikokuchuo":_2,"tobe":_2,"toon":_2,"uchiko":_2,"uwajima":_2,"yawatahama":_2}],"fukui":[1,{"echizen":_2,"eiheiji":_2,"fukui":_2,"ikeda":_2,"katsuyama":_2,"mihama":_2,"minamiechizen":_2,"obama":_2,"ohi":_2,"ono":_2,"sabae":_2,"sakai":_2,"takahama":_2,"tsuruga":_2,"wakasa":_2}],"fukuoka":[1,{"ashiya":_2,"buzen":_2,"chikugo":_2,"chikuho":_2,"chikujo":_2,"chikushino":_2,"chikuzen":_2,"chuo":_2,"dazaifu":_2,"fukuchi":_2,"hakata":_2,"higashi":_2,"hirokawa":_2,"hisayama":_2,"iizuka":_2,"inatsuki":_2,"kaho":_2,"kasuga":_2,"kasuya":_2,"kawara":_2,"keisen":_2,"koga":_2,"kurate":_2,"kurogi":_2,"kurume":_2,"minami":_2,"miyako":_2,"miyama":_2,"miyawaka":_2,"mizumaki":_2,"munakata":_2,"nakagawa":_2,"nakama":_2,"nishi":_2,"nogata":_2,"ogori":_2,"okagaki":_2,"okawa":_2,"oki":_2,"omuta":_2,"onga":_2,"onojo":_2,"oto":_2,"saigawa":_2,"sasaguri":_2,"shingu":_2,"shinyoshitomi":_2,"shonai":_2,"soeda":_2,"sue":_2,"tachiarai":_2,"tagawa":_2,"takata":_2,"toho":_2,"toyotsu":_2,"tsuiki":_2,"ukiha":_2,"umi":_2,"usui":_2,"yamada":_2,"yame":_2,"yanagawa":_2,"yukuhashi":_2}],"fukushima":[1,{"aizubange":_2,"aizumisato":_2,"aizuwakamatsu":_2,"asakawa":_2,"bandai":_2,"date":_2,"fukushima":_2,"furudono":_2,"futaba":_2,"hanawa":_2,"higashi":_2,"hirata":_2,"hirono":_2,"iitate":_2,"inawashiro":_2,"ishikawa":_2,"iwaki":_2,"izumizaki":_2,"kagamiishi":_2,"kaneyama":_2,"kawamata":_2,"kitakata":_2,"kitashiobara":_2,"koori":_2,"koriyama":_2,"kunimi":_2,"miharu":_2,"mishima":_2,"namie":_2,"nango":_2,"nishiaizu":_2,"nishigo":_2,"okuma":_2,"omotego":_2,"ono":_2,"otama":_2,"samegawa":_2,"shimogo":_2,"shirakawa":_2,"showa":_2,"soma":_2,"sukagawa":_2,"taishin":_2,"tamakawa":_2,"tanagura":_2,"tenei":_2,"yabuki":_2,"yamato":_2,"yamatsuri":_2,"yanaizu":_2,"yugawa":_2}],"gifu":[1,{"anpachi":_2,"ena":_2,"gifu":_2,"ginan":_2,"godo":_2,"gujo":_2,"hashima":_2,"hichiso":_2,"hida":_2,"higashishirakawa":_2,"ibigawa":_2,"ikeda":_2,"kakamigahara":_2,"kani":_2,"kasahara":_2,"kasamatsu":_2,"kawaue":_2,"kitagata":_2,"mino":_2,"minokamo":_2,"mitake":_2,"mizunami":_2,"motosu":_2,"nakatsugawa":_2,"ogaki":_2,"sakahogi":_2,"seki":_2,"sekigahara":_2,"shirakawa":_2,"tajimi":_2,"takayama":_2,"tarui":_2,"toki":_2,"tomika":_2,"wanouchi":_2,"yamagata":_2,"yaotsu":_2,"yoro":_2}],"gunma":[1,{"annaka":_2,"chiyoda":_2,"fujioka":_2,"higashiagatsuma":_2,"isesaki":_2,"itakura":_2,"kanna":_2,"kanra":_2,"katashina":_2,"kawaba":_2,"kiryu":_2,"kusatsu":_2,"maebashi":_2,"meiwa":_2,"midori":_2,"minakami":_2,"naganohara":_2,"nakanojo":_2,"nanmoku":_2,"numata":_2,"oizumi":_2,"ora":_2,"ota":_2,"shibukawa":_2,"shimonita":_2,"shinto":_2,"showa":_2,"takasaki":_2,"takayama":_2,"tamamura":_2,"tatebayashi":_2,"tomioka":_2,"tsukiyono":_2,"tsumagoi":_2,"ueno":_2,"yoshioka":_2}],"hiroshima":[1,{"asaminami":_2,"daiwa":_2,"etajima":_2,"fuchu":_2,"fukuyama":_2,"hatsukaichi":_2,"higashihiroshima":_2,"hongo":_2,"jinsekikogen":_2,"kaita":_2,"kui":_2,"kumano":_2,"kure":_2,"mihara":_2,"miyoshi":_2,"naka":_2,"onomichi":_2,"osakikamijima":_2,"otake":_2,"saka":_2,"sera":_2,"seranishi":_2,"shinichi":_2,"shobara":_2,"takehara":_2}],"hokkaido":[1,{"abashiri":_2,"abira":_2,"aibetsu":_2,"akabira":_2,"akkeshi":_2,"asahikawa":_2,"ashibetsu":_2,"ashoro":_2,"assabu":_2,"atsuma":_2,"bibai":_2,"biei":_2,"bifuka":_2,"bihoro":_2,"biratori":_2,"chippubetsu":_2,"chitose":_2,"date":_2,"ebetsu":_2,"embetsu":_2,"eniwa":_2,"erimo":_2,"esan":_2,"esashi":_2,"fukagawa":_2,"fukushima":_2,"furano":_2,"furubira":_2,"haboro":_2,"hakodate":_2,"hamatonbetsu":_2,"hidaka":_2,"higashikagura":_2,"higashikawa":_2,"hiroo":_2,"hokuryu":_2,"hokuto":_2,"honbetsu":_2,"horokanai":_2,"horonobe":_2,"ikeda":_2,"imakane":_2,"ishikari":_2,"iwamizawa":_2,"iwanai":_2,"kamifurano":_2,"kamikawa":_2,"kamishihoro":_2,"kamisunagawa":_2,"kamoenai":_2,"kayabe":_2,"kembuchi":_2,"kikonai":_2,"kimobetsu":_2,"kitahiroshima":_2,"kitami":_2,"kiyosato":_2,"koshimizu":_2,"kunneppu":_2,"kuriyama":_2,"kuromatsunai":_2,"kushiro":_2,"kutchan":_2,"kyowa":_2,"mashike":_2,"matsumae":_2,"mikasa":_2,"minamifurano":_2,"mombetsu":_2,"moseushi":_2,"mukawa":_2,"muroran":_2,"naie":_2,"nakagawa":_2,"nakasatsunai":_2,"nakatombetsu":_2,"nanae":_2,"nanporo":_2,"nayoro":_2,"nemuro":_2,"niikappu":_2,"niki":_2,"nishiokoppe":_2,"noboribetsu":_2,"numata":_2,"obihiro":_2,"obira":_2,"oketo":_2,"okoppe":_2,"otaru":_2,"otobe":_2,"otofuke":_2,"otoineppu":_2,"oumu":_2,"ozora":_2,"pippu":_2,"rankoshi":_2,"rebun":_2,"rikubetsu":_2,"rishiri":_2,"rishirifuji":_2,"saroma":_2,"sarufutsu":_2,"shakotan":_2,"shari":_2,"shibecha":_2,"shibetsu":_2,"shikabe":_2,"shikaoi":_2,"shimamaki":_2,"shimizu":_2,"shimokawa":_2,"shinshinotsu":_2,"shintoku":_2,"shiranuka":_2,"shiraoi":_2,"shiriuchi":_2,"sobetsu":_2,"sunagawa":_2,"taiki":_2,"takasu":_2,"takikawa":_2,"takinoue":_2,"teshikaga":_2,"tobetsu":_2,"tohma":_2,"tomakomai":_2,"tomari":_2,"toya":_2,"toyako":_2,"toyotomi":_2,"toyoura":_2,"tsubetsu":_2,"tsukigata":_2,"urakawa":_2,"urausu":_2,"uryu":_2,"utashinai":_2,"wakkanai":_2,"wassamu":_2,"yakumo":_2,"yoichi":_2}],"hyogo":[1,{"aioi":_2,"akashi":_2,"ako":_2,"amagasaki":_2,"aogaki":_2,"asago":_2,"ashiya":_2,"awaji":_2,"fukusaki":_2,"goshiki":_2,"harima":_2,"himeji":_2,"ichikawa":_2,"inagawa":_2,"itami":_2,"kakogawa":_2,"kamigori":_2,"kamikawa":_2,"kasai":_2,"kasuga":_2,"kawanishi":_2,"miki":_2,"minamiawaji":_2,"nishinomiya":_2,"nishiwaki":_2,"ono":_2,"sanda":_2,"sannan":_2,"sasayama":_2,"sayo":_2,"shingu":_2,"shinonsen":_2,"shiso":_2,"sumoto":_2,"taishi":_2,"taka":_2,"takarazuka":_2,"takasago":_2,"takino":_2,"tamba":_2,"tatsuno":_2,"toyooka":_2,"yabu":_2,"yashiro":_2,"yoka":_2,"yokawa":_2}],"ibaraki":[1,{"ami":_2,"asahi":_2,"bando":_2,"chikusei":_2,"daigo":_2,"fujishiro":_2,"hitachi":_2,"hitachinaka":_2,"hitachiomiya":_2,"hitachiota":_2,"ibaraki":_2,"ina":_2,"inashiki":_2,"itako":_2,"iwama":_2,"joso":_2,"kamisu":_2,"kasama":_2,"kashima":_2,"kasumigaura":_2,"koga":_2,"miho":_2,"mito":_2,"moriya":_2,"naka":_2,"namegata":_2,"oarai":_2,"ogawa":_2,"omitama":_2,"ryugasaki":_2,"sakai":_2,"sakuragawa":_2,"shimodate":_2,"shimotsuma":_2,"shirosato":_2,"sowa":_2,"suifu":_2,"takahagi":_2,"tamatsukuri":_2,"tokai":_2,"tomobe":_2,"tone":_2,"toride":_2,"tsuchiura":_2,"tsukuba":_2,"uchihara":_2,"ushiku":_2,"yachiyo":_2,"yamagata":_2,"yawara":_2,"yuki":_2}],"ishikawa":[1,{"anamizu":_2,"hakui":_2,"hakusan":_2,"kaga":_2,"kahoku":_2,"kanazawa":_2,"kawakita":_2,"komatsu":_2,"nakanoto":_2,"nanao":_2,"nomi":_2,"nonoichi":_2,"noto":_2,"shika":_2,"suzu":_2,"tsubata":_2,"tsurugi":_2,"uchinada":_2,"wajima":_2}],"iwate":[1,{"fudai":_2,"fujisawa":_2,"hanamaki":_2,"hiraizumi":_2,"hirono":_2,"ichinohe":_2,"ichinoseki":_2,"iwaizumi":_2,"iwate":_2,"joboji":_2,"kamaishi":_2,"kanegasaki":_2,"karumai":_2,"kawai":_2,"kitakami":_2,"kuji":_2,"kunohe":_2,"kuzumaki":_2,"miyako":_2,"mizusawa":_2,"morioka":_2,"ninohe":_2,"noda":_2,"ofunato":_2,"oshu":_2,"otsuchi":_2,"rikuzentakata":_2,"shiwa":_2,"shizukuishi":_2,"sumita":_2,"tanohata":_2,"tono":_2,"yahaba":_2,"yamada":_2}],"kagawa":[1,{"ayagawa":_2,"higashikagawa":_2,"kanonji":_2,"kotohira":_2,"manno":_2,"marugame":_2,"mitoyo":_2,"naoshima":_2,"sanuki":_2,"tadotsu":_2,"takamatsu":_2,"tonosho":_2,"uchinomi":_2,"utazu":_2,"zentsuji":_2}],"kagoshima":[1,{"akune":_2,"amami":_2,"hioki":_2,"isa":_2,"isen":_2,"izumi":_2,"kagoshima":_2,"kanoya":_2,"kawanabe":_2,"kinko":_2,"kouyama":_2,"makurazaki":_2,"matsumoto":_2,"minamitane":_2,"nakatane":_2,"nishinoomote":_2,"satsumasendai":_2,"soo":_2,"tarumizu":_2,"yusui":_2}],"kanagawa":[1,{"aikawa":_2,"atsugi":_2,"ayase":_2,"chigasaki":_2,"ebina":_2,"fujisawa":_2,"hadano":_2,"hakone":_2,"hiratsuka":_2,"isehara":_2,"kaisei":_2,"kamakura":_2,"kiyokawa":_2,"matsuda":_2,"minamiashigara":_2,"miura":_2,"nakai":_2,"ninomiya":_2,"odawara":_2,"oi":_2,"oiso":_2,"sagamihara":_2,"samukawa":_2,"tsukui":_2,"yamakita":_2,"yamato":_2,"yokosuka":_2,"yugawara":_2,"zama":_2,"zushi":_2}],"kochi":[1,{"aki":_2,"geisei":_2,"hidaka":_2,"higashitsuno":_2,"ino":_2,"kagami":_2,"kami":_2,"kitagawa":_2,"kochi":_2,"mihara":_2,"motoyama":_2,"muroto":_2,"nahari":_2,"nakamura":_2,"nankoku":_2,"nishitosa":_2,"niyodogawa":_2,"ochi":_2,"okawa":_2,"otoyo":_2,"otsuki":_2,"sakawa":_2,"sukumo":_2,"susaki":_2,"tosa":_2,"tosashimizu":_2,"toyo":_2,"tsuno":_2,"umaji":_2,"yasuda":_2,"yusuhara":_2}],"kumamoto":[1,{"amakusa":_2,"arao":_2,"aso":_2,"choyo":_2,"gyokuto":_2,"kamiamakusa":_2,"kikuchi":_2,"kumamoto":_2,"mashiki":_2,"mifune":_2,"minamata":_2,"minamioguni":_2,"nagasu":_2,"nishihara":_2,"oguni":_2,"ozu":_2,"sumoto":_2,"takamori":_2,"uki":_2,"uto":_2,"yamaga":_2,"yamato":_2,"yatsushiro":_2}],"kyoto":[1,{"ayabe":_2,"fukuchiyama":_2,"higashiyama":_2,"ide":_2,"ine":_2,"joyo":_2,"kameoka":_2,"kamo":_2,"kita":_2,"kizu":_2,"kumiyama":_2,"kyotamba":_2,"kyotanabe":_2,"kyotango":_2,"maizuru":_2,"minami":_2,"minamiyamashiro":_2,"miyazu":_2,"muko":_2,"nagaokakyo":_2,"nakagyo":_2,"nantan":_2,"oyamazaki":_2,"sakyo":_2,"seika":_2,"tanabe":_2,"uji":_2,"ujitawara":_2,"wazuka":_2,"yamashina":_2,"yawata":_2}],"mie":[1,{"asahi":_2,"inabe":_2,"ise":_2,"kameyama":_2,"kawagoe":_2,"kiho":_2,"kisosaki":_2,"kiwa":_2,"komono":_2,"kumano":_2,"kuwana":_2,"matsusaka":_2,"meiwa":_2,"mihama":_2,"minamiise":_2,"misugi":_2,"miyama":_2,"nabari":_2,"shima":_2,"suzuka":_2,"tado":_2,"taiki":_2,"taki":_2,"tamaki":_2,"toba":_2,"tsu":_2,"udono":_2,"ureshino":_2,"watarai":_2,"yokkaichi":_2}],"miyagi":[1,{"furukawa":_2,"higashimatsushima":_2,"ishinomaki":_2,"iwanuma":_2,"kakuda":_2,"kami":_2,"kawasaki":_2,"marumori":_2,"matsushima":_2,"minamisanriku":_2,"misato":_2,"murata":_2,"natori":_2,"ogawara":_2,"ohira":_2,"onagawa":_2,"osaki":_2,"rifu":_2,"semine":_2,"shibata":_2,"shichikashuku":_2,"shikama":_2,"shiogama":_2,"shiroishi":_2,"tagajo":_2,"taiwa":_2,"tome":_2,"tomiya":_2,"wakuya":_2,"watari":_2,"yamamoto":_2,"zao":_2}],"miyazaki":[1,{"aya":_2,"ebino":_2,"gokase":_2,"hyuga":_2,"kadogawa":_2,"kawaminami":_2,"kijo":_2,"kitagawa":_2,"kitakata":_2,"kitaura":_2,"kobayashi":_2,"kunitomi":_2,"kushima":_2,"mimata":_2,"miyakonojo":_2,"miyazaki":_2,"morotsuka":_2,"nichinan":_2,"nishimera":_2,"nobeoka":_2,"saito":_2,"shiiba":_2,"shintomi":_2,"takaharu":_2,"takanabe":_2,"takazaki":_2,"tsuno":_2}],"nagano":[1,{"achi":_2,"agematsu":_2,"anan":_2,"aoki":_2,"asahi":_2,"azumino":_2,"chikuhoku":_2,"chikuma":_2,"chino":_2,"fujimi":_2,"hakuba":_2,"hara":_2,"hiraya":_2,"iida":_2,"iijima":_2,"iiyama":_2,"iizuna":_2,"ikeda":_2,"ikusaka":_2,"ina":_2,"karuizawa":_2,"kawakami":_2,"kiso":_2,"kisofukushima":_2,"kitaaiki":_2,"komagane":_2,"komoro":_2,"matsukawa":_2,"matsumoto":_2,"miasa":_2,"minamiaiki":_2,"minamimaki":_2,"minamiminowa":_2,"minowa":_2,"miyada":_2,"miyota":_2,"mochizuki":_2,"nagano":_2,"nagawa":_2,"nagiso":_2,"nakagawa":_2,"nakano":_2,"nozawaonsen":_2,"obuse":_2,"ogawa":_2,"okaya":_2,"omachi":_2,"omi":_2,"ookuwa":_2,"ooshika":_2,"otaki":_2,"otari":_2,"sakae":_2,"sakaki":_2,"saku":_2,"sakuho":_2,"shimosuwa":_2,"shinanomachi":_2,"shiojiri":_2,"suwa":_2,"suzaka":_2,"takagi":_2,"takamori":_2,"takayama":_2,"tateshina":_2,"tatsuno":_2,"togakushi":_2,"togura":_2,"tomi":_2,"ueda":_2,"wada":_2,"yamagata":_2,"yamanouchi":_2,"yasaka":_2,"yasuoka":_2}],"nagasaki":[1,{"chijiwa":_2,"futsu":_2,"goto":_2,"hasami":_2,"hirado":_2,"iki":_2,"isahaya":_2,"kawatana":_2,"kuchinotsu":_2,"matsuura":_2,"nagasaki":_2,"obama":_2,"omura":_2,"oseto":_2,"saikai":_2,"sasebo":_2,"seihi":_2,"shimabara":_2,"shinkamigoto":_2,"togitsu":_2,"tsushima":_2,"unzen":_2}],"nara":[1,{"ando":_2,"gose":_2,"heguri":_2,"higashiyoshino":_2,"ikaruga":_2,"ikoma":_2,"kamikitayama":_2,"kanmaki":_2,"kashiba":_2,"kashihara":_2,"katsuragi":_2,"kawai":_2,"kawakami":_2,"kawanishi":_2,"koryo":_2,"kurotaki":_2,"mitsue":_2,"miyake":_2,"nara":_2,"nosegawa":_2,"oji":_2,"ouda":_2,"oyodo":_2,"sakurai":_2,"sango":_2,"shimoichi":_2,"shimokitayama":_2,"shinjo":_2,"soni":_2,"takatori":_2,"tawaramoto":_2,"tenkawa":_2,"tenri":_2,"uda":_2,"yamatokoriyama":_2,"yamatotakada":_2,"yamazoe":_2,"yoshino":_2}],"niigata":[1,{"aga":_2,"agano":_2,"gosen":_2,"itoigawa":_2,"izumozaki":_2,"joetsu":_2,"kamo":_2,"kariwa":_2,"kashiwazaki":_2,"minamiuonuma":_2,"mitsuke":_2,"muika":_2,"murakami":_2,"myoko":_2,"nagaoka":_2,"niigata":_2,"ojiya":_2,"omi":_2,"sado":_2,"sanjo":_2,"seiro":_2,"seirou":_2,"sekikawa":_2,"shibata":_2,"tagami":_2,"tainai":_2,"tochio":_2,"tokamachi":_2,"tsubame":_2,"tsunan":_2,"uonuma":_2,"yahiko":_2,"yoita":_2,"yuzawa":_2}],"oita":[1,{"beppu":_2,"bungoono":_2,"bungotakada":_2,"hasama":_2,"hiji":_2,"himeshima":_2,"hita":_2,"kamitsue":_2,"kokonoe":_2,"kuju":_2,"kunisaki":_2,"kusu":_2,"oita":_2,"saiki":_2,"taketa":_2,"tsukumi":_2,"usa":_2,"usuki":_2,"yufu":_2}],"okayama":[1,{"akaiwa":_2,"asakuchi":_2,"bizen":_2,"hayashima":_2,"ibara":_2,"kagamino":_2,"kasaoka":_2,"kibichuo":_2,"kumenan":_2,"kurashiki":_2,"maniwa":_2,"misaki":_2,"nagi":_2,"niimi":_2,"nishiawakura":_2,"okayama":_2,"satosho":_2,"setouchi":_2,"shinjo":_2,"shoo":_2,"soja":_2,"takahashi":_2,"tamano":_2,"tsuyama":_2,"wake":_2,"yakage":_2}],"okinawa":[1,{"aguni":_2,"ginowan":_2,"ginoza":_2,"gushikami":_2,"haebaru":_2,"higashi":_2,"hirara":_2,"iheya":_2,"ishigaki":_2,"ishikawa":_2,"itoman":_2,"izena":_2,"kadena":_2,"kin":_2,"kitadaito":_2,"kitanakagusuku":_2,"kumejima":_2,"kunigami":_2,"minamidaito":_2,"motobu":_2,"nago":_2,"naha":_2,"nakagusuku":_2,"nakijin":_2,"nanjo":_2,"nishihara":_2,"ogimi":_2,"okinawa":_2,"onna":_2,"shimoji":_2,"taketomi":_2,"tarama":_2,"tokashiki":_2,"tomigusuku":_2,"tonaki":_2,"urasoe":_2,"uruma":_2,"yaese":_2,"yomitan":_2,"yonabaru":_2,"yonaguni":_2,"zamami":_2}],"osaka":[1,{"abeno":_2,"chihayaakasaka":_2,"chuo":_2,"daito":_2,"fujiidera":_2,"habikino":_2,"hannan":_2,"higashiosaka":_2,"higashisumiyoshi":_2,"higashiyodogawa":_2,"hirakata":_2,"ibaraki":_2,"ikeda":_2,"izumi":_2,"izumiotsu":_2,"izumisano":_2,"kadoma":_2,"kaizuka":_2,"kanan":_2,"kashiwara":_2,"katano":_2,"kawachinagano":_2,"kishiwada":_2,"kita":_2,"kumatori":_2,"matsubara":_2,"minato":_2,"minoh":_2,"misaki":_2,"moriguchi":_2,"neyagawa":_2,"nishi":_2,"nose":_2,"osakasayama":_2,"sakai":_2,"sayama":_2,"sennan":_2,"settsu":_2,"shijonawate":_2,"shimamoto":_2,"suita":_2,"tadaoka":_2,"taishi":_2,"tajiri":_2,"takaishi":_2,"takatsuki":_2,"tondabayashi":_2,"toyonaka":_2,"toyono":_2,"yao":_2}],"saga":[1,{"ariake":_2,"arita":_2,"fukudomi":_2,"genkai":_2,"hamatama":_2,"hizen":_2,"imari":_2,"kamimine":_2,"kanzaki":_2,"karatsu":_2,"kashima":_2,"kitagata":_2,"kitahata":_2,"kiyama":_2,"kouhoku":_2,"kyuragi":_2,"nishiarita":_2,"ogi":_2,"omachi":_2,"ouchi":_2,"saga":_2,"shiroishi":_2,"taku":_2,"tara":_2,"tosu":_2,"yoshinogari":_2}],"saitama":[1,{"arakawa":_2,"asaka":_2,"chichibu":_2,"fujimi":_2,"fujimino":_2,"fukaya":_2,"hanno":_2,"hanyu":_2,"hasuda":_2,"hatogaya":_2,"hatoyama":_2,"hidaka":_2,"higashichichibu":_2,"higashimatsuyama":_2,"honjo":_2,"ina":_2,"iruma":_2,"iwatsuki":_2,"kamiizumi":_2,"kamikawa":_2,"kamisato":_2,"kasukabe":_2,"kawagoe":_2,"kawaguchi":_2,"kawajima":_2,"kazo":_2,"kitamoto":_2,"koshigaya":_2,"kounosu":_2,"kuki":_2,"kumagaya":_2,"matsubushi":_2,"minano":_2,"misato":_2,"miyashiro":_2,"miyoshi":_2,"moroyama":_2,"nagatoro":_2,"namegawa":_2,"niiza":_2,"ogano":_2,"ogawa":_2,"ogose":_2,"okegawa":_2,"omiya":_2,"otaki":_2,"ranzan":_2,"ryokami":_2,"saitama":_2,"sakado":_2,"satte":_2,"sayama":_2,"shiki":_2,"shiraoka":_2,"soka":_2,"sugito":_2,"toda":_2,"tokigawa":_2,"tokorozawa":_2,"tsurugashima":_2,"urawa":_2,"warabi":_2,"yashio":_2,"yokoze":_2,"yono":_2,"yorii":_2,"yoshida":_2,"yoshikawa":_2,"yoshimi":_2}],"shiga":[1,{"aisho":_2,"gamo":_2,"higashiomi":_2,"hikone":_2,"koka":_2,"konan":_2,"kosei":_2,"koto":_2,"kusatsu":_2,"maibara":_2,"moriyama":_2,"nagahama":_2,"nishiazai":_2,"notogawa":_2,"omihachiman":_2,"otsu":_2,"ritto":_2,"ryuoh":_2,"takashima":_2,"takatsuki":_2,"torahime":_2,"toyosato":_2,"yasu":_2}],"shimane":[1,{"akagi":_2,"ama":_2,"gotsu":_2,"hamada":_2,"higashiizumo":_2,"hikawa":_2,"hikimi":_2,"izumo":_2,"kakinoki":_2,"masuda":_2,"matsue":_2,"misato":_2,"nishinoshima":_2,"ohda":_2,"okinoshima":_2,"okuizumo":_2,"shimane":_2,"tamayu":_2,"tsuwano":_2,"unnan":_2,"yakumo":_2,"yasugi":_2,"yatsuka":_2}],"shizuoka":[1,{"arai":_2,"atami":_2,"fuji":_2,"fujieda":_2,"fujikawa":_2,"fujinomiya":_2,"fukuroi":_2,"gotemba":_2,"haibara":_2,"hamamatsu":_2,"higashiizu":_2,"ito":_2,"iwata":_2,"izu":_2,"izunokuni":_2,"kakegawa":_2,"kannami":_2,"kawanehon":_2,"kawazu":_2,"kikugawa":_2,"kosai":_2,"makinohara":_2,"matsuzaki":_2,"minamiizu":_2,"mishima":_2,"morimachi":_2,"nishiizu":_2,"numazu":_2,"omaezaki":_2,"shimada":_2,"shimizu":_2,"shimoda":_2,"shizuoka":_2,"susono":_2,"yaizu":_2,"yoshida":_2}],"tochigi":[1,{"ashikaga":_2,"bato":_2,"haga":_2,"ichikai":_2,"iwafune":_2,"kaminokawa":_2,"kanuma":_2,"karasuyama":_2,"kuroiso":_2,"mashiko":_2,"mibu":_2,"moka":_2,"motegi":_2,"nasu":_2,"nasushiobara":_2,"nikko":_2,"nishikata":_2,"nogi":_2,"ohira":_2,"ohtawara":_2,"oyama":_2,"sakura":_2,"sano":_2,"shimotsuke":_2,"shioya":_2,"takanezawa":_2,"tochigi":_2,"tsuga":_2,"ujiie":_2,"utsunomiya":_2,"yaita":_2}],"tokushima":[1,{"aizumi":_2,"anan":_2,"ichiba":_2,"itano":_2,"kainan":_2,"komatsushima":_2,"matsushige":_2,"mima":_2,"minami":_2,"miyoshi":_2,"mugi":_2,"nakagawa":_2,"naruto":_2,"sanagochi":_2,"shishikui":_2,"tokushima":_2,"wajiki":_2}],"tokyo":[1,{"adachi":_2,"akiruno":_2,"akishima":_2,"aogashima":_2,"arakawa":_2,"bunkyo":_2,"chiyoda":_2,"chofu":_2,"chuo":_2,"edogawa":_2,"fuchu":_2,"fussa":_2,"hachijo":_2,"hachioji":_2,"hamura":_2,"higashikurume":_2,"higashimurayama":_2,"higashiyamato":_2,"hino":_2,"hinode":_2,"hinohara":_2,"inagi":_2,"itabashi":_2,"katsushika":_2,"kita":_2,"kiyose":_2,"kodaira":_2,"koganei":_2,"kokubunji":_2,"komae":_2,"koto":_2,"kouzushima":_2,"kunitachi":_2,"machida":_2,"meguro":_2,"minato":_2,"mitaka":_2,"mizuho":_2,"musashimurayama":_2,"musashino":_2,"nakano":_2,"nerima":_2,"ogasawara":_2,"okutama":_2,"ome":_2,"oshima":_2,"ota":_2,"setagaya":_2,"shibuya":_2,"shinagawa":_2,"shinjuku":_2,"suginami":_2,"sumida":_2,"tachikawa":_2,"taito":_2,"tama":_2,"toshima":_2}],"tottori":[1,{"chizu":_2,"hino":_2,"kawahara":_2,"koge":_2,"kotoura":_2,"misasa":_2,"nanbu":_2,"nichinan":_2,"sakaiminato":_2,"tottori":_2,"wakasa":_2,"yazu":_2,"yonago":_2}],"toyama":[1,{"asahi":_2,"fuchu":_2,"fukumitsu":_2,"funahashi":_2,"himi":_2,"imizu":_2,"inami":_2,"johana":_2,"kamiichi":_2,"kurobe":_2,"nakaniikawa":_2,"namerikawa":_2,"nanto":_2,"nyuzen":_2,"oyabe":_2,"taira":_2,"takaoka":_2,"tateyama":_2,"toga":_2,"tonami":_2,"toyama":_2,"unazuki":_2,"uozu":_2,"yamada":_2}],"wakayama":[1,{"arida":_2,"aridagawa":_2,"gobo":_2,"hashimoto":_2,"hidaka":_2,"hirogawa":_2,"inami":_2,"iwade":_2,"kainan":_2,"kamitonda":_2,"katsuragi":_2,"kimino":_2,"kinokawa":_2,"kitayama":_2,"koya":_2,"koza":_2,"kozagawa":_2,"kudoyama":_2,"kushimoto":_2,"mihama":_2,"misato":_2,"nachikatsuura":_2,"shingu":_2,"shirahama":_2,"taiji":_2,"tanabe":_2,"wakayama":_2,"yuasa":_2,"yura":_2}],"yamagata":[1,{"asahi":_2,"funagata":_2,"higashine":_2,"iide":_2,"kahoku":_2,"kaminoyama":_2,"kaneyama":_2,"kawanishi":_2,"mamurogawa":_2,"mikawa":_2,"murayama":_2,"nagai":_2,"nakayama":_2,"nanyo":_2,"nishikawa":_2,"obanazawa":_2,"oe":_2,"oguni":_2,"ohkura":_2,"oishida":_2,"sagae":_2,"sakata":_2,"sakegawa":_2,"shinjo":_2,"shirataka":_2,"shonai":_2,"takahata":_2,"tendo":_2,"tozawa":_2,"tsuruoka":_2,"yamagata":_2,"yamanobe":_2,"yonezawa":_2,"yuza":_2}],"yamaguchi":[1,{"abu":_2,"hagi":_2,"hikari":_2,"hofu":_2,"iwakuni":_2,"kudamatsu":_2,"mitou":_2,"nagato":_2,"oshima":_2,"shimonoseki":_2,"shunan":_2,"tabuse":_2,"tokuyama":_2,"toyota":_2,"ube":_2,"yuu":_2}],"yamanashi":[1,{"chuo":_2,"doshi":_2,"fuefuki":_2,"fujikawa":_2,"fujikawaguchiko":_2,"fujiyoshida":_2,"hayakawa":_2,"hokuto":_2,"ichikawamisato":_2,"kai":_2,"kofu":_2,"koshu":_2,"kosuge":_2,"minami-alps":_2,"minobu":_2,"nakamichi":_2,"nanbu":_2,"narusawa":_2,"nirasaki":_2,"nishikatsura":_2,"oshino":_2,"otsuki":_2,"showa":_2,"tabayama":_2,"tsuru":_2,"uenohara":_2,"yamanakako":_2,"yamanashi":_2}],"xn--ehqz56n":_2,"三重":_2,"xn--1lqs03n":_2,"京都":_2,"xn--qqqt11m":_2,"佐賀":_2,"xn--f6qx53a":_2,"兵庫":_2,"xn--djrs72d6uy":_2,"北海道":_2,"xn--mkru45i":_2,"千葉":_2,"xn--0trq7p7nn":_2,"和歌山":_2,"xn--5js045d":_2,"埼玉":_2,"xn--kbrq7o":_2,"大分":_2,"xn--pssu33l":_2,"大阪":_2,"xn--ntsq17g":_2,"奈良":_2,"xn--uisz3g":_2,"宮城":_2,"xn--6btw5a":_2,"宮崎":_2,"xn--1ctwo":_2,"富山":_2,"xn--6orx2r":_2,"山口":_2,"xn--rht61e":_2,"山形":_2,"xn--rht27z":_2,"山梨":_2,"xn--nit225k":_2,"岐阜":_2,"xn--rht3d":_2,"岡山":_2,"xn--djty4k":_2,"岩手":_2,"xn--klty5x":_2,"島根":_2,"xn--kltx9a":_2,"広島":_2,"xn--kltp7d":_2,"徳島":_2,"xn--c3s14m":_2,"愛媛":_2,"xn--vgu402c":_2,"愛知":_2,"xn--efvn9s":_2,"新潟":_2,"xn--1lqs71d":_2,"東京":_2,"xn--4pvxs":_2,"栃木":_2,"xn--uuwu58a":_2,"沖縄":_2,"xn--zbx025d":_2,"滋賀":_2,"xn--8pvr4u":_2,"熊本":_2,"xn--5rtp49c":_2,"石川":_2,"xn--ntso0iqx3a":_2,"神奈川":_2,"xn--elqq16h":_2,"福井":_2,"xn--4it168d":_2,"福岡":_2,"xn--klt787d":_2,"福島":_2,"xn--rny31h":_2,"秋田":_2,"xn--7t0a264c":_2,"群馬":_2,"xn--uist22h":_2,"茨城":_2,"xn--8ltr62k":_2,"長崎":_2,"xn--2m4a15e":_2,"長野":_2,"xn--32vp30h":_2,"青森":_2,"xn--4it797k":_2,"静岡":_2,"xn--5rtq34k":_2,"香川":_2,"xn--k7yn95e":_2,"高知":_2,"xn--tor131o":_2,"鳥取":_2,"xn--d5qv7z876c":_2,"鹿児島":_2,"kawasaki":_20,"kitakyushu":_20,"kobe":_20,"nagoya":_20,"sapporo":_20,"sendai":_20,"yokohama":_20,"buyshop":_3,"fashionstore":_3,"handcrafted":_3,"kawaiishop":_3,"supersale":_3,"theshop":_3,"0am":_3,"0g0":_3,"0j0":_3,"0t0":_3,"mydns":_3,"pgw":_3,"wjg":_3,"usercontent":_3,"angry":_3,"babyblue":_3,"babymilk":_3,"backdrop":_3,"bambina":_3,"bitter":_3,"blush":_3,"boo":_3,"boy":_3,"boyfriend":_3,"but":_3,"candypop":_3,"capoo":_3,"catfood":_3,"cheap":_3,"chicappa":_3,"chillout":_3,"chips":_3,"chowder":_3,"chu":_3,"ciao":_3,"cocotte":_3,"coolblog":_3,"cranky":_3,"cutegirl":_3,"daa":_3,"deca":_3,"deci":_3,"digick":_3,"egoism":_3,"fakefur":_3,"fem":_3,"flier":_3,"floppy":_3,"fool":_3,"frenchkiss":_3,"girlfriend":_3,"girly":_3,"gloomy":_3,"gonna":_3,"greater":_3,"hacca":_3,"heavy":_3,"her":_3,"hiho":_3,"hippy":_3,"holy":_3,"hungry":_3,"icurus":_3,"itigo":_3,"jellybean":_3,"kikirara":_3,"kill":_3,"kilo":_3,"kuron":_3,"littlestar":_3,"lolipopmc":_3,"lolitapunk":_3,"lomo":_3,"lovepop":_3,"lovesick":_3,"main":_3,"mods":_3,"mond":_3,"mongolian":_3,"moo":_3,"namaste":_3,"nikita":_3,"nobushi":_3,"noor":_3,"oops":_3,"parallel":_3,"parasite":_3,"pecori":_3,"peewee":_3,"penne":_3,"pepper":_3,"perma":_3,"pigboat":_3,"pinoko":_3,"punyu":_3,"pupu":_3,"pussycat":_3,"pya":_3,"raindrop":_3,"readymade":_3,"sadist":_3,"schoolbus":_3,"secret":_3,"staba":_3,"stripper":_3,"sub":_3,"sunnyday":_3,"thick":_3,"tonkotsu":_3,"under":_3,"upper":_3,"velvet":_3,"verse":_3,"versus":_3,"vivian":_3,"watson":_3,"weblike":_3,"whitesnow":_3,"zombie":_3,"hateblo":_3,"hatenablog":_3,"hatenadiary":_3,"2-d":_3,"bona":_3,"crap":_3,"daynight":_3,"eek":_3,"flop":_3,"halfmoon":_3,"jeez":_3,"matrix":_3,"mimoza":_3,"netgamers":_3,"nyanta":_3,"o0o0":_3,"rdy":_3,"rgr":_3,"rulez":_3,"sakurastorage":[0,{"isk01":_58,"isk02":_58}],"saloon":_3,"sblo":_3,"skr":_3,"tank":_3,"uh-oh":_3,"undo":_3,"webaccel":[0,{"rs":_3,"user":_3}],"websozai":_3,"xii":_3}],"ke":[1,{"ac":_2,"co":_2,"go":_2,"info":_2,"me":_2,"mobi":_2,"ne":_2,"or":_2,"sc":_2}],"kg":[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"us":_3,"xx":_3}],"kh":_20,"ki":_59,"km":[1,{"ass":_2,"com":_2,"edu":_2,"gov":_2,"mil":_2,"nom":_2,"org":_2,"prd":_2,"tm":_2,"asso":_2,"coop":_2,"gouv":_2,"medecin":_2,"notaires":_2,"pharmaciens":_2,"presse":_2,"veterinaire":_2}],"kn":[1,{"edu":_2,"gov":_2,"net":_2,"org":_2}],"kp":[1,{"com":_2,"edu":_2,"gov":_2,"org":_2,"rep":_2,"tra":_2}],"kr":[1,{"ac":_2,"ai":_2,"co":_2,"es":_2,"go":_2,"hs":_2,"io":_2,"it":_2,"kg":_2,"me":_2,"mil":_2,"ms":_2,"ne":_2,"or":_2,"pe":_2,"re":_2,"sc":_2,"busan":_2,"chungbuk":_2,"chungnam":_2,"daegu":_2,"daejeon":_2,"gangwon":_2,"gwangju":_2,"gyeongbuk":_2,"gyeonggi":_2,"gyeongnam":_2,"incheon":_2,"jeju":_2,"jeonbuk":_2,"jeonnam":_2,"seoul":_2,"ulsan":_2,"c01":_3,"eliv-cdn":_3,"eliv-dns":_3,"mmv":_3,"vki":_3}],"kw":[1,{"com":_2,"edu":_2,"emb":_2,"gov":_2,"ind":_2,"net":_2,"org":_2}],"ky":_47,"kz":[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"jcloud":_3}],"la":[1,{"com":_2,"edu":_2,"gov":_2,"info":_2,"int":_2,"net":_2,"org":_2,"per":_2,"bnr":_3}],"lb":_4,"lc":[1,{"co":_2,"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"oy":_3}],"li":_2,"lk":[1,{"ac":_2,"assn":_2,"com":_2,"edu":_2,"gov":_2,"grp":_2,"hotel":_2,"int":_2,"ltd":_2,"net":_2,"ngo":_2,"org":_2,"sch":_2,"soc":_2,"web":_2}],"lr":_4,"ls":[1,{"ac":_2,"biz":_2,"co":_2,"edu":_2,"gov":_2,"info":_2,"net":_2,"org":_2,"sc":_2}],"lt":_10,"lu":[1,{"123website":_3}],"lv":[1,{"asn":_2,"com":_2,"conf":_2,"edu":_2,"gov":_2,"id":_2,"mil":_2,"net":_2,"org":_2}],"ly":[1,{"com":_2,"edu":_2,"gov":_2,"id":_2,"med":_2,"net":_2,"org":_2,"plc":_2,"sch":_2}],"ma":[1,{"ac":_2,"co":_2,"gov":_2,"net":_2,"org":_2,"press":_2}],"mc":[1,{"asso":_2,"tm":_2}],"md":[1,{"ir":_3}],"me":[1,{"ac":_2,"co":_2,"edu":_2,"gov":_2,"its":_2,"net":_2,"org":_2,"priv":_2,"c66":_3,"craft":_3,"edgestack":_3,"filegear":_3,"filegear-sg":_3,"lohmus":_3,"barsy":_3,"mcdir":_3,"brasilia":_3,"ddns":_3,"dnsfor":_3,"hopto":_3,"loginto":_3,"noip":_3,"webhop":_3,"soundcast":_3,"tcp4":_3,"vp4":_3,"diskstation":_3,"dscloud":_3,"i234":_3,"myds":_3,"synology":_3,"transip":_46,"nohost":_3}],"mg":[1,{"co":_2,"com":_2,"edu":_2,"gov":_2,"mil":_2,"nom":_2,"org":_2,"prd":_2}],"mh":_2,"mil":_2,"mk":[1,{"com":_2,"edu":_2,"gov":_2,"inf":_2,"name":_2,"net":_2,"org":_2}],"ml":[1,{"ac":_2,"art":_2,"asso":_2,"com":_2,"edu":_2,"gouv":_2,"gov":_2,"info":_2,"inst":_2,"net":_2,"org":_2,"pr":_2,"presse":_2}],"mm":_20,"mn":[1,{"edu":_2,"gov":_2,"org":_2,"nyc":_3}],"mo":_4,"mobi":[1,{"barsy":_3,"dscloud":_3}],"mp":[1,{"ju":_3}],"mq":_2,"mr":_10,"ms":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"minisite":_3}],"mt":_47,"mu":[1,{"ac":_2,"co":_2,"com":_2,"gov":_2,"net":_2,"or":_2,"org":_2}],"museum":_2,"mv":[1,{"aero":_2,"biz":_2,"com":_2,"coop":_2,"edu":_2,"gov":_2,"info":_2,"int":_2,"mil":_2,"museum":_2,"name":_2,"net":_2,"org":_2,"pro":_2}],"mw":[1,{"ac":_2,"biz":_2,"co":_2,"com":_2,"coop":_2,"edu":_2,"gov":_2,"int":_2,"net":_2,"org":_2}],"mx":[1,{"com":_2,"edu":_2,"gob":_2,"net":_2,"org":_2}],"my":[1,{"biz":_2,"com":_2,"edu":_2,"gov":_2,"mil":_2,"name":_2,"net":_2,"org":_2}],"mz":[1,{"ac":_2,"adv":_2,"co":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2}],"na":[1,{"alt":_2,"co":_2,"com":_2,"gov":_2,"net":_2,"org":_2}],"name":[1,{"her":_62,"his":_62,"ispmanager":_3}],"nc":[1,{"asso":_2,"nom":_2}],"ne":_2,"net":[1,{"adobeaemcloud":_3,"adobeio-static":_3,"adobeioruntime":_3,"akadns":_3,"akamai":_3,"akamai-staging":_3,"akamaiedge":_3,"akamaiedge-staging":_3,"akamaihd":_3,"akamaihd-staging":_3,"akamaiorigin":_3,"akamaiorigin-staging":_3,"akamaized":_3,"akamaized-staging":_3,"edgekey":_3,"edgekey-staging":_3,"edgesuite":_3,"edgesuite-staging":_3,"alwaysdata":_3,"myamaze":_3,"cloudfront":_3,"appudo":_3,"atlassian-dev":[0,{"prod":_54}],"myfritz":_3,"onavstack":_3,"shopselect":_3,"blackbaudcdn":_3,"boomla":_3,"bplaced":_3,"square7":_3,"cdn77":[0,{"r":_3}],"cdn77-ssl":_3,"gb":_3,"hu":_3,"jp":_3,"se":_3,"uk":_3,"clickrising":_3,"ddns-ip":_3,"dns-cloud":_3,"dns-dynamic":_3,"cloudaccess":_3,"cloudflare":[2,{"cdn":_3}],"cloudflareanycast":_54,"cloudflarecn":_54,"cloudflareglobal":_54,"ctfcloud":_3,"feste-ip":_3,"knx-server":_3,"static-access":_3,"cryptonomic":_6,"dattolocal":_3,"mydatto":_3,"debian":_3,"definima":_3,"deno":_3,"icp":_6,"de5":_3,"at-band-camp":_3,"blogdns":_3,"broke-it":_3,"buyshouses":_3,"dnsalias":_3,"dnsdojo":_3,"does-it":_3,"dontexist":_3,"dynalias":_3,"dynathome":_3,"endofinternet":_3,"from-az":_3,"from-co":_3,"from-la":_3,"from-ny":_3,"gets-it":_3,"ham-radio-op":_3,"homeftp":_3,"homeip":_3,"homelinux":_3,"homeunix":_3,"in-the-band":_3,"is-a-chef":_3,"is-a-geek":_3,"isa-geek":_3,"kicks-ass":_3,"office-on-the":_3,"podzone":_3,"scrapper-site":_3,"selfip":_3,"sells-it":_3,"servebbs":_3,"serveftp":_3,"thruhere":_3,"webhop":_3,"casacam":_3,"dynu":_3,"dynv6":_3,"twmail":_3,"ru":_3,"channelsdvr":[2,{"u":_3}],"fastly":[0,{"freetls":_3,"map":_3,"prod":[0,{"a":_3,"global":_3}],"ssl":[0,{"a":_3,"b":_3,"global":_3}]}],"fastlylb":[2,{"map":_3}],"edgeapp":_3,"keyword-on":_3,"live-on":_3,"server-on":_3,"cdn-edges":_3,"heteml":_3,"cloudfunctions":_3,"grafana-dev":_3,"iobb":_3,"moonscale":_3,"in-dsl":_3,"in-vpn":_3,"oninferno":_3,"botdash":_3,"apps-1and1":_3,"ipifony":_3,"cloudjiffy":[2,{"fra1-de":_3,"west1-us":_3}],"elastx":[0,{"jls-sto1":_3,"jls-sto2":_3,"jls-sto3":_3}],"massivegrid":[0,{"paas":[0,{"fr-1":_3,"lon-1":_3,"lon-2":_3,"ny-1":_3,"ny-2":_3,"sg-1":_3}]}],"saveincloud":[0,{"jelastic":_3,"nordeste-idc":_3}],"scaleforce":_48,"kinghost":_3,"uni5":_3,"krellian":_3,"ggff":_3,"localto":_6,"barsy":_3,"luyani":_3,"memset":_3,"azure-api":_3,"azure-mobile":_3,"azureedge":_3,"azurefd":_3,"azurestaticapps":[2,{"1":_3,"2":_3,"3":_3,"4":_3,"5":_3,"6":_3,"7":_3,"centralus":_3,"eastasia":_3,"eastus2":_3,"westeurope":_3,"westus2":_3}],"azurewebsites":_3,"cloudapp":_3,"trafficmanager":_3,"windows":[0,{"core":[0,{"blob":_3}],"servicebus":_3}],"mynetname":[0,{"sn":_3}],"routingthecloud":_3,"bounceme":_3,"ddns":_3,"eating-organic":_3,"mydissent":_3,"myeffect":_3,"mymediapc":_3,"mypsx":_3,"mysecuritycamera":_3,"nhlfan":_3,"no-ip":_3,"pgafan":_3,"privatizehealthinsurance":_3,"redirectme":_3,"serveblog":_3,"serveminecraft":_3,"sytes":_3,"dnsup":_3,"hicam":_3,"now-dns":_3,"ownip":_3,"vpndns":_3,"cloudycluster":_3,"ovh":[0,{"hosting":_6,"webpaas":_6}],"rackmaze":_3,"myradweb":_3,"in":_3,"subsc-pay":_3,"squares":_3,"schokokeks":_3,"firewall-gateway":_3,"seidat":_3,"senseering":_3,"siteleaf":_3,"mafelo":_3,"myspreadshop":_3,"vps-host":[2,{"jelastic":[0,{"atl":_3,"njs":_3,"ric":_3}]}],"srcf":[0,{"soc":_3,"user":_3}],"supabase":_3,"dsmynas":_3,"familyds":_3,"ts":[2,{"c":_6}],"torproject":[2,{"pages":_3}],"tunnelmole":_3,"vusercontent":_3,"reserve-online":_3,"localcert":_3,"community-pro":_3,"meinforum":_3,"yandexcloud":[2,{"storage":_3,"website":_3}],"za":_3,"zabc":_3}],"nf":[1,{"arts":_2,"com":_2,"firm":_2,"info":_2,"net":_2,"other":_2,"per":_2,"rec":_2,"store":_2,"web":_2}],"ng":[1,{"com":_2,"edu":_2,"gov":_2,"i":_2,"mil":_2,"mobi":_2,"name":_2,"net":_2,"org":_2,"sch":_2,"biz":[2,{"co":_3,"dl":_3,"go":_3,"lg":_3,"on":_3}],"col":_3,"firm":_3,"gen":_3,"ltd":_3,"ngo":_3,"plc":_3}],"ni":[1,{"ac":_2,"biz":_2,"co":_2,"com":_2,"edu":_2,"gob":_2,"in":_2,"info":_2,"int":_2,"mil":_2,"net":_2,"nom":_2,"org":_2,"web":_2}],"nl":[1,{"co":_3,"hosting-cluster":_3,"gov":_3,"khplay":_3,"123website":_3,"myspreadshop":_3,"transurl":_6,"cistron":_3,"demon":_3}],"no":[1,{"fhs":_2,"folkebibl":_2,"fylkesbibl":_2,"idrett":_2,"museum":_2,"priv":_2,"vgs":_2,"dep":_2,"herad":_2,"kommune":_2,"mil":_2,"stat":_2,"aa":_63,"ah":_63,"bu":_63,"fm":_63,"hl":_63,"hm":_63,"jan-mayen":_63,"mr":_63,"nl":_63,"nt":_63,"of":_63,"ol":_63,"oslo":_63,"rl":_63,"sf":_63,"st":_63,"svalbard":_63,"tm":_63,"tr":_63,"va":_63,"vf":_63,"akrehamn":_2,"xn--krehamn-dxa":_2,"åkrehamn":_2,"algard":_2,"xn--lgrd-poac":_2,"ålgård":_2,"arna":_2,"bronnoysund":_2,"xn--brnnysund-m8ac":_2,"brønnøysund":_2,"brumunddal":_2,"bryne":_2,"drobak":_2,"xn--drbak-wua":_2,"drøbak":_2,"egersund":_2,"fetsund":_2,"floro":_2,"xn--flor-jra":_2,"florø":_2,"fredrikstad":_2,"hokksund":_2,"honefoss":_2,"xn--hnefoss-q1a":_2,"hønefoss":_2,"jessheim":_2,"jorpeland":_2,"xn--jrpeland-54a":_2,"jørpeland":_2,"kirkenes":_2,"kopervik":_2,"krokstadelva":_2,"langevag":_2,"xn--langevg-jxa":_2,"langevåg":_2,"leirvik":_2,"mjondalen":_2,"xn--mjndalen-64a":_2,"mjøndalen":_2,"mo-i-rana":_2,"mosjoen":_2,"xn--mosjen-eya":_2,"mosjøen":_2,"nesoddtangen":_2,"orkanger":_2,"osoyro":_2,"xn--osyro-wua":_2,"osøyro":_2,"raholt":_2,"xn--rholt-mra":_2,"råholt":_2,"sandnessjoen":_2,"xn--sandnessjen-ogb":_2,"sandnessjøen":_2,"skedsmokorset":_2,"slattum":_2,"spjelkavik":_2,"stathelle":_2,"stavern":_2,"stjordalshalsen":_2,"xn--stjrdalshalsen-sqb":_2,"stjørdalshalsen":_2,"tananger":_2,"tranby":_2,"vossevangen":_2,"aarborte":_2,"aejrie":_2,"afjord":_2,"xn--fjord-lra":_2,"åfjord":_2,"agdenes":_2,"akershus":_64,"aknoluokta":_2,"xn--koluokta-7ya57h":_2,"ákŋoluokta":_2,"al":_2,"xn--l-1fa":_2,"ål":_2,"alaheadju":_2,"xn--laheadju-7ya":_2,"álaheadju":_2,"alesund":_2,"xn--lesund-hua":_2,"ålesund":_2,"alstahaug":_2,"alta":_2,"xn--lt-liac":_2,"áltá":_2,"alvdal":_2,"amli":_2,"xn--mli-tla":_2,"åmli":_2,"amot":_2,"xn--mot-tla":_2,"åmot":_2,"andasuolo":_2,"andebu":_2,"andoy":_2,"xn--andy-ira":_2,"andøy":_2,"ardal":_2,"xn--rdal-poa":_2,"årdal":_2,"aremark":_2,"arendal":_2,"xn--s-1fa":_2,"ås":_2,"aseral":_2,"xn--seral-lra":_2,"åseral":_2,"asker":_2,"askim":_2,"askoy":_2,"xn--asky-ira":_2,"askøy":_2,"askvoll":_2,"asnes":_2,"xn--snes-poa":_2,"åsnes":_2,"audnedaln":_2,"aukra":_2,"aure":_2,"aurland":_2,"aurskog-holand":_2,"xn--aurskog-hland-jnb":_2,"aurskog-høland":_2,"austevoll":_2,"austrheim":_2,"averoy":_2,"xn--avery-yua":_2,"averøy":_2,"badaddja":_2,"xn--bdddj-mrabd":_2,"bådåddjå":_2,"xn--brum-voa":_2,"bærum":_2,"bahcavuotna":_2,"xn--bhcavuotna-s4a":_2,"báhcavuotna":_2,"bahccavuotna":_2,"xn--bhccavuotna-k7a":_2,"báhccavuotna":_2,"baidar":_2,"xn--bidr-5nac":_2,"báidár":_2,"bajddar":_2,"xn--bjddar-pta":_2,"bájddar":_2,"balat":_2,"xn--blt-elab":_2,"bálát":_2,"balestrand":_2,"ballangen":_2,"balsfjord":_2,"bamble":_2,"bardu":_2,"barum":_2,"batsfjord":_2,"xn--btsfjord-9za":_2,"båtsfjord":_2,"bearalvahki":_2,"xn--bearalvhki-y4a":_2,"bearalváhki":_2,"beardu":_2,"beiarn":_2,"berg":_2,"bergen":_2,"berlevag":_2,"xn--berlevg-jxa":_2,"berlevåg":_2,"bievat":_2,"xn--bievt-0qa":_2,"bievát":_2,"bindal":_2,"birkenes":_2,"bjerkreim":_2,"bjugn":_2,"bodo":_2,"xn--bod-2na":_2,"bodø":_2,"bokn":_2,"bomlo":_2,"xn--bmlo-gra":_2,"bømlo":_2,"bremanger":_2,"bronnoy":_2,"xn--brnny-wuac":_2,"brønnøy":_2,"budejju":_2,"buskerud":_64,"bygland":_2,"bykle":_2,"cahcesuolo":_2,"xn--hcesuolo-7ya35b":_2,"čáhcesuolo":_2,"davvenjarga":_2,"xn--davvenjrga-y4a":_2,"davvenjárga":_2,"davvesiida":_2,"deatnu":_2,"dielddanuorri":_2,"divtasvuodna":_2,"divttasvuotna":_2,"donna":_2,"xn--dnna-gra":_2,"dønna":_2,"dovre":_2,"drammen":_2,"drangedal":_2,"dyroy":_2,"xn--dyry-ira":_2,"dyrøy":_2,"eid":_2,"eidfjord":_2,"eidsberg":_2,"eidskog":_2,"eidsvoll":_2,"eigersund":_2,"elverum":_2,"enebakk":_2,"engerdal":_2,"etne":_2,"etnedal":_2,"evenassi":_2,"xn--eveni-0qa01ga":_2,"evenášši":_2,"evenes":_2,"evje-og-hornnes":_2,"farsund":_2,"fauske":_2,"fedje":_2,"fet":_2,"finnoy":_2,"xn--finny-yua":_2,"finnøy":_2,"fitjar":_2,"fjaler":_2,"fjell":_2,"fla":_2,"xn--fl-zia":_2,"flå":_2,"flakstad":_2,"flatanger":_2,"flekkefjord":_2,"flesberg":_2,"flora":_2,"folldal":_2,"forde":_2,"xn--frde-gra":_2,"førde":_2,"forsand":_2,"fosnes":_2,"xn--frna-woa":_2,"fræna":_2,"frana":_2,"frei":_2,"frogn":_2,"froland":_2,"frosta":_2,"froya":_2,"xn--frya-hra":_2,"frøya":_2,"fuoisku":_2,"fuossko":_2,"fusa":_2,"fyresdal":_2,"gaivuotna":_2,"xn--givuotna-8ya":_2,"gáivuotna":_2,"galsa":_2,"xn--gls-elac":_2,"gálsá":_2,"gamvik":_2,"gangaviika":_2,"xn--ggaviika-8ya47h":_2,"gáŋgaviika":_2,"gaular":_2,"gausdal":_2,"giehtavuoatna":_2,"gildeskal":_2,"xn--gildeskl-g0a":_2,"gildeskål":_2,"giske":_2,"gjemnes":_2,"gjerdrum":_2,"gjerstad":_2,"gjesdal":_2,"gjovik":_2,"xn--gjvik-wua":_2,"gjøvik":_2,"gloppen":_2,"gol":_2,"gran":_2,"grane":_2,"granvin":_2,"gratangen":_2,"grimstad":_2,"grong":_2,"grue":_2,"gulen":_2,"guovdageaidnu":_2,"ha":_2,"xn--h-2fa":_2,"hå":_2,"habmer":_2,"xn--hbmer-xqa":_2,"hábmer":_2,"hadsel":_2,"xn--hgebostad-g3a":_2,"hægebostad":_2,"hagebostad":_2,"halden":_2,"halsa":_2,"hamar":_2,"hamaroy":_2,"hammarfeasta":_2,"xn--hmmrfeasta-s4ac":_2,"hámmárfeasta":_2,"hammerfest":_2,"hapmir":_2,"xn--hpmir-xqa":_2,"hápmir":_2,"haram":_2,"hareid":_2,"harstad":_2,"hasvik":_2,"hattfjelldal":_2,"haugesund":_2,"hedmark":[0,{"os":_2,"valer":_2,"xn--vler-qoa":_2,"våler":_2}],"hemne":_2,"hemnes":_2,"hemsedal":_2,"hitra":_2,"hjartdal":_2,"hjelmeland":_2,"hobol":_2,"xn--hobl-ira":_2,"hobøl":_2,"hof":_2,"hol":_2,"hole":_2,"holmestrand":_2,"holtalen":_2,"xn--holtlen-hxa":_2,"holtålen":_2,"hordaland":[0,{"os":_2}],"hornindal":_2,"horten":_2,"hoyanger":_2,"xn--hyanger-q1a":_2,"høyanger":_2,"hoylandet":_2,"xn--hylandet-54a":_2,"høylandet":_2,"hurdal":_2,"hurum":_2,"hvaler":_2,"hyllestad":_2,"ibestad":_2,"inderoy":_2,"xn--indery-fya":_2,"inderøy":_2,"iveland":_2,"ivgu":_2,"jevnaker":_2,"jolster":_2,"xn--jlster-bya":_2,"jølster":_2,"jondal":_2,"kafjord":_2,"xn--kfjord-iua":_2,"kåfjord":_2,"karasjohka":_2,"xn--krjohka-hwab49j":_2,"kárášjohka":_2,"karasjok":_2,"karlsoy":_2,"karmoy":_2,"xn--karmy-yua":_2,"karmøy":_2,"kautokeino":_2,"klabu":_2,"xn--klbu-woa":_2,"klæbu":_2,"klepp":_2,"kongsberg":_2,"kongsvinger":_2,"kraanghke":_2,"xn--kranghke-b0a":_2,"kråanghke":_2,"kragero":_2,"xn--krager-gya":_2,"kragerø":_2,"kristiansand":_2,"kristiansund":_2,"krodsherad":_2,"xn--krdsherad-m8a":_2,"krødsherad":_2,"xn--kvfjord-nxa":_2,"kvæfjord":_2,"xn--kvnangen-k0a":_2,"kvænangen":_2,"kvafjord":_2,"kvalsund":_2,"kvam":_2,"kvanangen":_2,"kvinesdal":_2,"kvinnherad":_2,"kviteseid":_2,"kvitsoy":_2,"xn--kvitsy-fya":_2,"kvitsøy":_2,"laakesvuemie":_2,"xn--lrdal-sra":_2,"lærdal":_2,"lahppi":_2,"xn--lhppi-xqa":_2,"láhppi":_2,"lardal":_2,"larvik":_2,"lavagis":_2,"lavangen":_2,"leangaviika":_2,"xn--leagaviika-52b":_2,"leaŋgaviika":_2,"lebesby":_2,"leikanger":_2,"leirfjord":_2,"leka":_2,"leksvik":_2,"lenvik":_2,"lerdal":_2,"lesja":_2,"levanger":_2,"lier":_2,"lierne":_2,"lillehammer":_2,"lillesand":_2,"lindas":_2,"xn--linds-pra":_2,"lindås":_2,"lindesnes":_2,"loabat":_2,"xn--loabt-0qa":_2,"loabát":_2,"lodingen":_2,"xn--ldingen-q1a":_2,"lødingen":_2,"lom":_2,"loppa":_2,"lorenskog":_2,"xn--lrenskog-54a":_2,"lørenskog":_2,"loten":_2,"xn--lten-gra":_2,"løten":_2,"lund":_2,"lunner":_2,"luroy":_2,"xn--lury-ira":_2,"lurøy":_2,"luster":_2,"lyngdal":_2,"lyngen":_2,"malatvuopmi":_2,"xn--mlatvuopmi-s4a":_2,"málatvuopmi":_2,"malselv":_2,"xn--mlselv-iua":_2,"målselv":_2,"malvik":_2,"mandal":_2,"marker":_2,"marnardal":_2,"masfjorden":_2,"masoy":_2,"xn--msy-ula0h":_2,"måsøy":_2,"matta-varjjat":_2,"xn--mtta-vrjjat-k7af":_2,"mátta-várjjat":_2,"meland":_2,"meldal":_2,"melhus":_2,"meloy":_2,"xn--mely-ira":_2,"meløy":_2,"meraker":_2,"xn--merker-kua":_2,"meråker":_2,"midsund":_2,"midtre-gauldal":_2,"moareke":_2,"xn--moreke-jua":_2,"moåreke":_2,"modalen":_2,"modum":_2,"molde":_2,"more-og-romsdal":[0,{"heroy":_2,"sande":_2}],"xn--mre-og-romsdal-qqb":[0,{"xn--hery-ira":_2,"sande":_2}],"møre-og-romsdal":[0,{"herøy":_2,"sande":_2}],"moskenes":_2,"moss":_2,"muosat":_2,"xn--muost-0qa":_2,"muosát":_2,"naamesjevuemie":_2,"xn--nmesjevuemie-tcba":_2,"nååmesjevuemie":_2,"xn--nry-yla5g":_2,"nærøy":_2,"namdalseid":_2,"namsos":_2,"namsskogan":_2,"nannestad":_2,"naroy":_2,"narviika":_2,"narvik":_2,"naustdal":_2,"navuotna":_2,"xn--nvuotna-hwa":_2,"návuotna":_2,"nedre-eiker":_2,"nesna":_2,"nesodden":_2,"nesseby":_2,"nesset":_2,"nissedal":_2,"nittedal":_2,"nord-aurdal":_2,"nord-fron":_2,"nord-odal":_2,"norddal":_2,"nordkapp":_2,"nordland":[0,{"bo":_2,"xn--b-5ga":_2,"bø":_2,"heroy":_2,"xn--hery-ira":_2,"herøy":_2}],"nordre-land":_2,"nordreisa":_2,"nore-og-uvdal":_2,"notodden":_2,"notteroy":_2,"xn--nttery-byae":_2,"nøtterøy":_2,"odda":_2,"oksnes":_2,"xn--ksnes-uua":_2,"øksnes":_2,"omasvuotna":_2,"oppdal":_2,"oppegard":_2,"xn--oppegrd-ixa":_2,"oppegård":_2,"orkdal":_2,"orland":_2,"xn--rland-uua":_2,"ørland":_2,"orskog":_2,"xn--rskog-uua":_2,"ørskog":_2,"orsta":_2,"xn--rsta-fra":_2,"ørsta":_2,"osen":_2,"osteroy":_2,"xn--ostery-fya":_2,"osterøy":_2,"ostfold":[0,{"valer":_2}],"xn--stfold-9xa":[0,{"xn--vler-qoa":_2}],"østfold":[0,{"våler":_2}],"ostre-toten":_2,"xn--stre-toten-zcb":_2,"østre-toten":_2,"overhalla":_2,"ovre-eiker":_2,"xn--vre-eiker-k8a":_2,"øvre-eiker":_2,"oyer":_2,"xn--yer-zna":_2,"øyer":_2,"oygarden":_2,"xn--ygarden-p1a":_2,"øygarden":_2,"oystre-slidre":_2,"xn--ystre-slidre-ujb":_2,"øystre-slidre":_2,"porsanger":_2,"porsangu":_2,"xn--porsgu-sta26f":_2,"porsáŋgu":_2,"porsgrunn":_2,"rade":_2,"xn--rde-ula":_2,"råde":_2,"radoy":_2,"xn--rady-ira":_2,"radøy":_2,"xn--rlingen-mxa":_2,"rælingen":_2,"rahkkeravju":_2,"xn--rhkkervju-01af":_2,"ráhkkerávju":_2,"raisa":_2,"xn--risa-5na":_2,"ráisa":_2,"rakkestad":_2,"ralingen":_2,"rana":_2,"randaberg":_2,"rauma":_2,"rendalen":_2,"rennebu":_2,"rennesoy":_2,"xn--rennesy-v1a":_2,"rennesøy":_2,"rindal":_2,"ringebu":_2,"ringerike":_2,"ringsaker":_2,"risor":_2,"xn--risr-ira":_2,"risør":_2,"rissa":_2,"roan":_2,"rodoy":_2,"xn--rdy-0nab":_2,"rødøy":_2,"rollag":_2,"romsa":_2,"romskog":_2,"xn--rmskog-bya":_2,"rømskog":_2,"roros":_2,"xn--rros-gra":_2,"røros":_2,"rost":_2,"xn--rst-0na":_2,"røst":_2,"royken":_2,"xn--ryken-vua":_2,"røyken":_2,"royrvik":_2,"xn--ryrvik-bya":_2,"røyrvik":_2,"ruovat":_2,"rygge":_2,"salangen":_2,"salat":_2,"xn--slat-5na":_2,"sálat":_2,"xn--slt-elab":_2,"sálát":_2,"saltdal":_2,"samnanger":_2,"sandefjord":_2,"sandnes":_2,"sandoy":_2,"xn--sandy-yua":_2,"sandøy":_2,"sarpsborg":_2,"sauda":_2,"sauherad":_2,"sel":_2,"selbu":_2,"selje":_2,"seljord":_2,"siellak":_2,"sigdal":_2,"siljan":_2,"sirdal":_2,"skanit":_2,"xn--sknit-yqa":_2,"skánit":_2,"skanland":_2,"xn--sknland-fxa":_2,"skånland":_2,"skaun":_2,"skedsmo":_2,"ski":_2,"skien":_2,"skierva":_2,"xn--skierv-uta":_2,"skiervá":_2,"skiptvet":_2,"skjak":_2,"xn--skjk-soa":_2,"skjåk":_2,"skjervoy":_2,"xn--skjervy-v1a":_2,"skjervøy":_2,"skodje":_2,"smola":_2,"xn--smla-hra":_2,"smøla":_2,"snaase":_2,"xn--snase-nra":_2,"snåase":_2,"snasa":_2,"xn--snsa-roa":_2,"snåsa":_2,"snillfjord":_2,"snoasa":_2,"sogndal":_2,"sogne":_2,"xn--sgne-gra":_2,"søgne":_2,"sokndal":_2,"sola":_2,"solund":_2,"somna":_2,"xn--smna-gra":_2,"sømna":_2,"sondre-land":_2,"xn--sndre-land-0cb":_2,"søndre-land":_2,"songdalen":_2,"sor-aurdal":_2,"xn--sr-aurdal-l8a":_2,"sør-aurdal":_2,"sor-fron":_2,"xn--sr-fron-q1a":_2,"sør-fron":_2,"sor-odal":_2,"xn--sr-odal-q1a":_2,"sør-odal":_2,"sor-varanger":_2,"xn--sr-varanger-ggb":_2,"sør-varanger":_2,"sorfold":_2,"xn--srfold-bya":_2,"sørfold":_2,"sorreisa":_2,"xn--srreisa-q1a":_2,"sørreisa":_2,"sortland":_2,"sorum":_2,"xn--srum-gra":_2,"sørum":_2,"spydeberg":_2,"stange":_2,"stavanger":_2,"steigen":_2,"steinkjer":_2,"stjordal":_2,"xn--stjrdal-s1a":_2,"stjørdal":_2,"stokke":_2,"stor-elvdal":_2,"stord":_2,"stordal":_2,"storfjord":_2,"strand":_2,"stranda":_2,"stryn":_2,"sula":_2,"suldal":_2,"sund":_2,"sunndal":_2,"surnadal":_2,"sveio":_2,"svelvik":_2,"sykkylven":_2,"tana":_2,"telemark":[0,{"bo":_2,"xn--b-5ga":_2,"bø":_2}],"time":_2,"tingvoll":_2,"tinn":_2,"tjeldsund":_2,"tjome":_2,"xn--tjme-hra":_2,"tjøme":_2,"tokke":_2,"tolga":_2,"tonsberg":_2,"xn--tnsberg-q1a":_2,"tønsberg":_2,"torsken":_2,"xn--trna-woa":_2,"træna":_2,"trana":_2,"tranoy":_2,"xn--trany-yua":_2,"tranøy":_2,"troandin":_2,"trogstad":_2,"xn--trgstad-r1a":_2,"trøgstad":_2,"tromsa":_2,"tromso":_2,"xn--troms-zua":_2,"tromsø":_2,"trondheim":_2,"trysil":_2,"tvedestrand":_2,"tydal":_2,"tynset":_2,"tysfjord":_2,"tysnes":_2,"xn--tysvr-vra":_2,"tysvær":_2,"tysvar":_2,"ullensaker":_2,"ullensvang":_2,"ulvik":_2,"unjarga":_2,"xn--unjrga-rta":_2,"unjárga":_2,"utsira":_2,"vaapste":_2,"vadso":_2,"xn--vads-jra":_2,"vadsø":_2,"xn--vry-yla5g":_2,"værøy":_2,"vaga":_2,"xn--vg-yiab":_2,"vågå":_2,"vagan":_2,"xn--vgan-qoa":_2,"vågan":_2,"vagsoy":_2,"xn--vgsy-qoa0j":_2,"vågsøy":_2,"vaksdal":_2,"valle":_2,"vang":_2,"vanylven":_2,"vardo":_2,"xn--vard-jra":_2,"vardø":_2,"varggat":_2,"xn--vrggt-xqad":_2,"várggát":_2,"varoy":_2,"vefsn":_2,"vega":_2,"vegarshei":_2,"xn--vegrshei-c0a":_2,"vegårshei":_2,"vennesla":_2,"verdal":_2,"verran":_2,"vestby":_2,"vestfold":[0,{"sande":_2}],"vestnes":_2,"vestre-slidre":_2,"vestre-toten":_2,"vestvagoy":_2,"xn--vestvgy-ixa6o":_2,"vestvågøy":_2,"vevelstad":_2,"vik":_2,"vikna":_2,"vindafjord":_2,"voagat":_2,"volda":_2,"voss":_2,"co":_3,"123hjemmeside":_3,"myspreadshop":_3}],"np":_20,"nr":_59,"nu":[1,{"merseine":_3,"mine":_3,"shacknet":_3,"enterprisecloud":_3}],"nz":[1,{"ac":_2,"co":_2,"cri":_2,"geek":_2,"gen":_2,"govt":_2,"health":_2,"iwi":_2,"kiwi":_2,"maori":_2,"xn--mori-qsa":_2,"māori":_2,"mil":_2,"net":_2,"org":_2,"parliament":_2,"school":_2,"cloudns":_3}],"om":[1,{"co":_2,"com":_2,"edu":_2,"gov":_2,"med":_2,"museum":_2,"net":_2,"org":_2,"pro":_2}],"onion":_2,"org":[1,{"altervista":_3,"pimienta":_3,"poivron":_3,"potager":_3,"sweetpepper":_3,"cdn77":[0,{"c":_3,"rsc":_3}],"cdn77-secure":[0,{"origin":[0,{"ssl":_3}]}],"ae":_3,"cloudns":_3,"ip-dynamic":_3,"ddnss":_3,"dpdns":_3,"duckdns":_3,"tunk":_3,"blogdns":_3,"blogsite":_3,"boldlygoingnowhere":_3,"dnsalias":_3,"dnsdojo":_3,"doesntexist":_3,"dontexist":_3,"doomdns":_3,"dvrdns":_3,"dynalias":_3,"dyndns":[2,{"go":_3,"home":_3}],"endofinternet":_3,"endoftheinternet":_3,"from-me":_3,"game-host":_3,"gotdns":_3,"hobby-site":_3,"homedns":_3,"homeftp":_3,"homelinux":_3,"homeunix":_3,"is-a-bruinsfan":_3,"is-a-candidate":_3,"is-a-celticsfan":_3,"is-a-chef":_3,"is-a-geek":_3,"is-a-knight":_3,"is-a-linux-user":_3,"is-a-patsfan":_3,"is-a-soxfan":_3,"is-found":_3,"is-lost":_3,"is-saved":_3,"is-very-bad":_3,"is-very-evil":_3,"is-very-good":_3,"is-very-nice":_3,"is-very-sweet":_3,"isa-geek":_3,"kicks-ass":_3,"misconfused":_3,"podzone":_3,"readmyblog":_3,"selfip":_3,"sellsyourhome":_3,"servebbs":_3,"serveftp":_3,"servegame":_3,"stuff-4-sale":_3,"webhop":_3,"accesscam":_3,"camdvr":_3,"freeddns":_3,"mywire":_3,"webredirect":_3,"twmail":_3,"eu":[2,{"al":_3,"asso":_3,"at":_3,"au":_3,"be":_3,"bg":_3,"ca":_3,"cd":_3,"ch":_3,"cn":_3,"cy":_3,"cz":_3,"de":_3,"dk":_3,"edu":_3,"ee":_3,"es":_3,"fi":_3,"fr":_3,"gr":_3,"hr":_3,"hu":_3,"ie":_3,"il":_3,"in":_3,"int":_3,"is":_3,"it":_3,"jp":_3,"kr":_3,"lt":_3,"lu":_3,"lv":_3,"me":_3,"mk":_3,"mt":_3,"my":_3,"net":_3,"ng":_3,"nl":_3,"no":_3,"nz":_3,"pl":_3,"pt":_3,"ro":_3,"ru":_3,"se":_3,"si":_3,"sk":_3,"tr":_3,"uk":_3,"us":_3}],"fedorainfracloud":_3,"fedorapeople":_3,"fedoraproject":[0,{"cloud":_3,"os":_45,"stg":[0,{"os":_45}]}],"freedesktop":_3,"hatenadiary":_3,"hepforge":_3,"in-dsl":_3,"in-vpn":_3,"js":_3,"barsy":_3,"mayfirst":_3,"routingthecloud":_3,"bmoattachments":_3,"cable-modem":_3,"collegefan":_3,"couchpotatofries":_3,"hopto":_3,"mlbfan":_3,"myftp":_3,"mysecuritycamera":_3,"nflfan":_3,"no-ip":_3,"read-books":_3,"ufcfan":_3,"zapto":_3,"dynserv":_3,"now-dns":_3,"is-local":_3,"httpbin":_3,"pubtls":_3,"jpn":_3,"my-firewall":_3,"myfirewall":_3,"spdns":_3,"small-web":_3,"dsmynas":_3,"familyds":_3,"teckids":_58,"tuxfamily":_3,"diskstation":_3,"hk":_3,"us":_3,"toolforge":_3,"wmcloud":[2,{"beta":_3}],"wmflabs":_3,"za":_3}],"pa":[1,{"abo":_2,"ac":_2,"com":_2,"edu":_2,"gob":_2,"ing":_2,"med":_2,"net":_2,"nom":_2,"org":_2,"sld":_2}],"pe":[1,{"com":_2,"edu":_2,"gob":_2,"mil":_2,"net":_2,"nom":_2,"org":_2}],"pf":[1,{"com":_2,"edu":_2,"org":_2}],"pg":_20,"ph":[1,{"com":_2,"edu":_2,"gov":_2,"i":_2,"mil":_2,"net":_2,"ngo":_2,"org":_2,"cloudns":_3}],"pk":[1,{"ac":_2,"biz":_2,"com":_2,"edu":_2,"fam":_2,"gkp":_2,"gob":_2,"gog":_2,"gok":_2,"gop":_2,"gos":_2,"gov":_2,"net":_2,"org":_2,"web":_2}],"pl":[1,{"com":_2,"net":_2,"org":_2,"agro":_2,"aid":_2,"atm":_2,"auto":_2,"biz":_2,"edu":_2,"gmina":_2,"gsm":_2,"info":_2,"mail":_2,"media":_2,"miasta":_2,"mil":_2,"nieruchomosci":_2,"nom":_2,"pc":_2,"powiat":_2,"priv":_2,"realestate":_2,"rel":_2,"sex":_2,"shop":_2,"sklep":_2,"sos":_2,"szkola":_2,"targi":_2,"tm":_2,"tourism":_2,"travel":_2,"turystyka":_2,"gov":[1,{"ap":_2,"griw":_2,"ic":_2,"is":_2,"kmpsp":_2,"konsulat":_2,"kppsp":_2,"kwp":_2,"kwpsp":_2,"mup":_2,"mw":_2,"oia":_2,"oirm":_2,"oke":_2,"oow":_2,"oschr":_2,"oum":_2,"pa":_2,"pinb":_2,"piw":_2,"po":_2,"pr":_2,"psp":_2,"psse":_2,"pup":_2,"rzgw":_2,"sa":_2,"sdn":_2,"sko":_2,"so":_2,"sr":_2,"starostwo":_2,"ug":_2,"ugim":_2,"um":_2,"umig":_2,"upow":_2,"uppo":_2,"us":_2,"uw":_2,"uzs":_2,"wif":_2,"wiih":_2,"winb":_2,"wios":_2,"witd":_2,"wiw":_2,"wkz":_2,"wsa":_2,"wskr":_2,"wsse":_2,"wuoz":_2,"wzmiuw":_2,"zp":_2,"zpisdn":_2}],"augustow":_2,"babia-gora":_2,"bedzin":_2,"beskidy":_2,"bialowieza":_2,"bialystok":_2,"bielawa":_2,"bieszczady":_2,"boleslawiec":_2,"bydgoszcz":_2,"bytom":_2,"cieszyn":_2,"czeladz":_2,"czest":_2,"dlugoleka":_2,"elblag":_2,"elk":_2,"glogow":_2,"gniezno":_2,"gorlice":_2,"grajewo":_2,"ilawa":_2,"jaworzno":_2,"jelenia-gora":_2,"jgora":_2,"kalisz":_2,"karpacz":_2,"kartuzy":_2,"kaszuby":_2,"katowice":_2,"kazimierz-dolny":_2,"kepno":_2,"ketrzyn":_2,"klodzko":_2,"kobierzyce":_2,"kolobrzeg":_2,"konin":_2,"konskowola":_2,"kutno":_2,"lapy":_2,"lebork":_2,"legnica":_2,"lezajsk":_2,"limanowa":_2,"lomza":_2,"lowicz":_2,"lubin":_2,"lukow":_2,"malbork":_2,"malopolska":_2,"mazowsze":_2,"mazury":_2,"mielec":_2,"mielno":_2,"mragowo":_2,"naklo":_2,"nowaruda":_2,"nysa":_2,"olawa":_2,"olecko":_2,"olkusz":_2,"olsztyn":_2,"opoczno":_2,"opole":_2,"ostroda":_2,"ostroleka":_2,"ostrowiec":_2,"ostrowwlkp":_2,"pila":_2,"pisz":_2,"podhale":_2,"podlasie":_2,"polkowice":_2,"pomorskie":_2,"pomorze":_2,"prochowice":_2,"pruszkow":_2,"przeworsk":_2,"pulawy":_2,"radom":_2,"rawa-maz":_2,"rybnik":_2,"rzeszow":_2,"sanok":_2,"sejny":_2,"skoczow":_2,"slask":_2,"slupsk":_2,"sosnowiec":_2,"stalowa-wola":_2,"starachowice":_2,"stargard":_2,"suwalki":_2,"swidnica":_2,"swiebodzin":_2,"swinoujscie":_2,"szczecin":_2,"szczytno":_2,"tarnobrzeg":_2,"tgory":_2,"turek":_2,"tychy":_2,"ustka":_2,"walbrzych":_2,"warmia":_2,"warszawa":_2,"waw":_2,"wegrow":_2,"wielun":_2,"wlocl":_2,"wloclawek":_2,"wodzislaw":_2,"wolomin":_2,"wroclaw":_2,"zachpomor":_2,"zagan":_2,"zarow":_2,"zgora":_2,"zgorzelec":_2,"art":_3,"gliwice":_3,"krakow":_3,"poznan":_3,"wroc":_3,"zakopane":_3,"beep":_3,"ecommerce-shop":_3,"cfolks":_3,"dfirma":_3,"dkonto":_3,"you2":_3,"shoparena":_3,"homesklep":_3,"sdscloud":_3,"unicloud":_3,"lodz":_3,"pabianice":_3,"plock":_3,"sieradz":_3,"skierniewice":_3,"zgierz":_3,"krasnik":_3,"leczna":_3,"lubartow":_3,"lublin":_3,"poniatowa":_3,"swidnik":_3,"co":_3,"torun":_3,"simplesite":_3,"myspreadshop":_3,"gda":_3,"gdansk":_3,"gdynia":_3,"med":_3,"sopot":_3,"bielsko":_3}],"pm":[1,{"own":_3,"name":_3}],"pn":[1,{"co":_2,"edu":_2,"gov":_2,"net":_2,"org":_2}],"post":_2,"pr":[1,{"biz":_2,"com":_2,"edu":_2,"gov":_2,"info":_2,"isla":_2,"name":_2,"net":_2,"org":_2,"pro":_2,"ac":_2,"est":_2,"prof":_2}],"pro":[1,{"aaa":_2,"aca":_2,"acct":_2,"avocat":_2,"bar":_2,"cpa":_2,"eng":_2,"jur":_2,"law":_2,"med":_2,"recht":_2,"12chars":_3,"cloudns":_3,"barsy":_3,"ngrok":_3}],"ps":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"plo":_2,"sec":_2}],"pt":[1,{"com":_2,"edu":_2,"gov":_2,"int":_2,"net":_2,"nome":_2,"org":_2,"publ":_2,"123paginaweb":_3}],"pw":[1,{"gov":_2,"cloudns":_3,"x443":_3}],"py":[1,{"com":_2,"coop":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2}],"qa":[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"name":_2,"net":_2,"org":_2,"sch":_2}],"re":[1,{"asso":_2,"com":_2,"netlib":_3,"can":_3}],"ro":[1,{"arts":_2,"com":_2,"firm":_2,"info":_2,"nom":_2,"nt":_2,"org":_2,"rec":_2,"store":_2,"tm":_2,"www":_2,"co":_3,"shop":_3,"barsy":_3}],"rs":[1,{"ac":_2,"co":_2,"edu":_2,"gov":_2,"in":_2,"org":_2,"brendly":_19,"barsy":_3,"ox":_3}],"ru":[1,{"ac":_3,"edu":_3,"gov":_3,"int":_3,"mil":_3,"eurodir":_3,"adygeya":_3,"bashkiria":_3,"bir":_3,"cbg":_3,"com":_3,"dagestan":_3,"grozny":_3,"kalmykia":_3,"kustanai":_3,"marine":_3,"mordovia":_3,"msk":_3,"mytis":_3,"nalchik":_3,"nov":_3,"pyatigorsk":_3,"spb":_3,"vladikavkaz":_3,"vladimir":_3,"na4u":_3,"mircloud":_3,"myjino":[2,{"hosting":_6,"landing":_6,"spectrum":_6,"vps":_6}],"cldmail":[0,{"hb":_3}],"mcdir":[2,{"vps":_3}],"mcpre":_3,"net":_3,"org":_3,"pp":_3,"lk3":_3,"ras":_3}],"rw":[1,{"ac":_2,"co":_2,"coop":_2,"gov":_2,"mil":_2,"net":_2,"org":_2}],"sa":[1,{"com":_2,"edu":_2,"gov":_2,"med":_2,"net":_2,"org":_2,"pub":_2,"sch":_2}],"sb":_4,"sc":_4,"sd":[1,{"com":_2,"edu":_2,"gov":_2,"info":_2,"med":_2,"net":_2,"org":_2,"tv":_2}],"se":[1,{"a":_2,"ac":_2,"b":_2,"bd":_2,"brand":_2,"c":_2,"d":_2,"e":_2,"f":_2,"fh":_2,"fhsk":_2,"fhv":_2,"g":_2,"h":_2,"i":_2,"k":_2,"komforb":_2,"kommunalforbund":_2,"komvux":_2,"l":_2,"lanbib":_2,"m":_2,"n":_2,"naturbruksgymn":_2,"o":_2,"org":_2,"p":_2,"parti":_2,"pp":_2,"press":_2,"r":_2,"s":_2,"t":_2,"tm":_2,"u":_2,"w":_2,"x":_2,"y":_2,"z":_2,"com":_3,"iopsys":_3,"123minsida":_3,"itcouldbewor":_3,"myspreadshop":_3}],"sg":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"enscaled":_3}],"sh":[1,{"com":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"hashbang":_3,"botda":_3,"lovable":_3,"platform":[0,{"ent":_3,"eu":_3,"us":_3}],"teleport":_3,"now":_3}],"si":[1,{"f5":_3,"gitapp":_3,"gitpage":_3}],"sj":_2,"sk":_2,"sl":_4,"sm":_2,"sn":[1,{"art":_2,"com":_2,"edu":_2,"gouv":_2,"org":_2,"perso":_2,"univ":_2}],"so":[1,{"com":_2,"edu":_2,"gov":_2,"me":_2,"net":_2,"org":_2,"surveys":_3}],"sr":_2,"ss":[1,{"biz":_2,"co":_2,"com":_2,"edu":_2,"gov":_2,"me":_2,"net":_2,"org":_2,"sch":_2}],"st":[1,{"co":_2,"com":_2,"consulado":_2,"edu":_2,"embaixada":_2,"mil":_2,"net":_2,"org":_2,"principe":_2,"saotome":_2,"store":_2,"helioho":_3,"kirara":_3,"noho":_3}],"su":[1,{"abkhazia":_3,"adygeya":_3,"aktyubinsk":_3,"arkhangelsk":_3,"armenia":_3,"ashgabad":_3,"azerbaijan":_3,"balashov":_3,"bashkiria":_3,"bryansk":_3,"bukhara":_3,"chimkent":_3,"dagestan":_3,"east-kazakhstan":_3,"exnet":_3,"georgia":_3,"grozny":_3,"ivanovo":_3,"jambyl":_3,"kalmykia":_3,"kaluga":_3,"karacol":_3,"karaganda":_3,"karelia":_3,"khakassia":_3,"krasnodar":_3,"kurgan":_3,"kustanai":_3,"lenug":_3,"mangyshlak":_3,"mordovia":_3,"msk":_3,"murmansk":_3,"nalchik":_3,"navoi":_3,"north-kazakhstan":_3,"nov":_3,"obninsk":_3,"penza":_3,"pokrovsk":_3,"sochi":_3,"spb":_3,"tashkent":_3,"termez":_3,"togliatti":_3,"troitsk":_3,"tselinograd":_3,"tula":_3,"tuva":_3,"vladikavkaz":_3,"vladimir":_3,"vologda":_3}],"sv":[1,{"com":_2,"edu":_2,"gob":_2,"org":_2,"red":_2}],"sx":_10,"sy":_5,"sz":[1,{"ac":_2,"co":_2,"org":_2}],"tc":_2,"td":_2,"tel":_2,"tf":[1,{"sch":_3}],"tg":_2,"th":[1,{"ac":_2,"co":_2,"go":_2,"in":_2,"mi":_2,"net":_2,"or":_2,"online":_3,"shop":_3}],"tj":[1,{"ac":_2,"biz":_2,"co":_2,"com":_2,"edu":_2,"go":_2,"gov":_2,"int":_2,"mil":_2,"name":_2,"net":_2,"nic":_2,"org":_2,"test":_2,"web":_2}],"tk":_2,"tl":_10,"tm":[1,{"co":_2,"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"nom":_2,"org":_2}],"tn":[1,{"com":_2,"ens":_2,"fin":_2,"gov":_2,"ind":_2,"info":_2,"intl":_2,"mincom":_2,"nat":_2,"net":_2,"org":_2,"perso":_2,"tourism":_2,"orangecloud":_3}],"to":[1,{"611":_3,"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"oya":_3,"x0":_3,"quickconnect":_27,"vpnplus":_3}],"tr":[1,{"av":_2,"bbs":_2,"bel":_2,"biz":_2,"com":_2,"dr":_2,"edu":_2,"gen":_2,"gov":_2,"info":_2,"k12":_2,"kep":_2,"mil":_2,"name":_2,"net":_2,"org":_2,"pol":_2,"tel":_2,"tsk":_2,"tv":_2,"web":_2,"nc":_10}],"tt":[1,{"biz":_2,"co":_2,"com":_2,"edu":_2,"gov":_2,"info":_2,"mil":_2,"name":_2,"net":_2,"org":_2,"pro":_2}],"tv":[1,{"better-than":_3,"dyndns":_3,"on-the-web":_3,"worse-than":_3,"from":_3,"sakura":_3}],"tw":[1,{"club":_2,"com":[1,{"mymailer":_3}],"ebiz":_2,"edu":_2,"game":_2,"gov":_2,"idv":_2,"mil":_2,"net":_2,"org":_2,"url":_3,"mydns":_3}],"tz":[1,{"ac":_2,"co":_2,"go":_2,"hotel":_2,"info":_2,"me":_2,"mil":_2,"mobi":_2,"ne":_2,"or":_2,"sc":_2,"tv":_2}],"ua":[1,{"com":_2,"edu":_2,"gov":_2,"in":_2,"net":_2,"org":_2,"cherkassy":_2,"cherkasy":_2,"chernigov":_2,"chernihiv":_2,"chernivtsi":_2,"chernovtsy":_2,"ck":_2,"cn":_2,"cr":_2,"crimea":_2,"cv":_2,"dn":_2,"dnepropetrovsk":_2,"dnipropetrovsk":_2,"donetsk":_2,"dp":_2,"if":_2,"ivano-frankivsk":_2,"kh":_2,"kharkiv":_2,"kharkov":_2,"kherson":_2,"khmelnitskiy":_2,"khmelnytskyi":_2,"kiev":_2,"kirovograd":_2,"km":_2,"kr":_2,"kropyvnytskyi":_2,"krym":_2,"ks":_2,"kv":_2,"kyiv":_2,"lg":_2,"lt":_2,"lugansk":_2,"luhansk":_2,"lutsk":_2,"lv":_2,"lviv":_2,"mk":_2,"mykolaiv":_2,"nikolaev":_2,"od":_2,"odesa":_2,"odessa":_2,"pl":_2,"poltava":_2,"rivne":_2,"rovno":_2,"rv":_2,"sb":_2,"sebastopol":_2,"sevastopol":_2,"sm":_2,"sumy":_2,"te":_2,"ternopil":_2,"uz":_2,"uzhgorod":_2,"uzhhorod":_2,"vinnica":_2,"vinnytsia":_2,"vn":_2,"volyn":_2,"yalta":_2,"zakarpattia":_2,"zaporizhzhe":_2,"zaporizhzhia":_2,"zhitomir":_2,"zhytomyr":_2,"zp":_2,"zt":_2,"cc":_3,"inf":_3,"ltd":_3,"cx":_3,"biz":_3,"co":_3,"pp":_3,"v":_3}],"ug":[1,{"ac":_2,"co":_2,"com":_2,"edu":_2,"go":_2,"gov":_2,"mil":_2,"ne":_2,"or":_2,"org":_2,"sc":_2,"us":_2}],"uk":[1,{"ac":_2,"co":[1,{"bytemark":[0,{"dh":_3,"vm":_3}],"layershift":_48,"barsy":_3,"barsyonline":_3,"retrosnub":_57,"nh-serv":_3,"no-ip":_3,"adimo":_3,"myspreadshop":_3}],"gov":[1,{"api":_3,"campaign":_3,"service":_3}],"ltd":_2,"me":_2,"net":_2,"nhs":_2,"org":[1,{"glug":_3,"lug":_3,"lugs":_3,"affinitylottery":_3,"raffleentry":_3,"weeklylottery":_3}],"plc":_2,"police":_2,"sch":_20,"conn":_3,"copro":_3,"hosp":_3,"independent-commission":_3,"independent-inquest":_3,"independent-inquiry":_3,"independent-panel":_3,"independent-review":_3,"public-inquiry":_3,"royal-commission":_3,"pymnt":_3,"barsy":_3,"nimsite":_3,"oraclegovcloudapps":_6}],"us":[1,{"dni":_2,"isa":_2,"nsn":_2,"ak":_65,"al":_65,"ar":_65,"as":_65,"az":_65,"ca":_65,"co":_65,"ct":_65,"dc":_65,"de":_66,"fl":_65,"ga":_65,"gu":_65,"hi":_67,"ia":_65,"id":_65,"il":_65,"in":_65,"ks":_65,"ky":_65,"la":_65,"ma":[1,{"k12":[1,{"chtr":_2,"paroch":_2,"pvt":_2}],"cc":_2,"lib":_2}],"md":_65,"me":_65,"mi":[1,{"k12":_2,"cc":_2,"lib":_2,"ann-arbor":_2,"cog":_2,"dst":_2,"eaton":_2,"gen":_2,"mus":_2,"tec":_2,"washtenaw":_2}],"mn":_65,"mo":_65,"ms":[1,{"k12":_2,"cc":_2}],"mt":_65,"nc":_65,"nd":_67,"ne":_65,"nh":_65,"nj":_65,"nm":_65,"nv":_65,"ny":_65,"oh":_65,"ok":_65,"or":_65,"pa":_65,"pr":_65,"ri":_67,"sc":_65,"sd":_67,"tn":_65,"tx":_65,"ut":_65,"va":_65,"vi":_65,"vt":_65,"wa":_65,"wi":_65,"wv":_66,"wy":_65,"cloudns":_3,"is-by":_3,"land-4-sale":_3,"stuff-4-sale":_3,"heliohost":_3,"enscaled":[0,{"phx":_3}],"mircloud":_3,"ngo":_3,"golffan":_3,"noip":_3,"pointto":_3,"freeddns":_3,"srv":[2,{"gh":_3,"gl":_3}],"platterp":_3,"servername":_3}],"uy":[1,{"com":_2,"edu":_2,"gub":_2,"mil":_2,"net":_2,"org":_2}],"uz":[1,{"co":_2,"com":_2,"net":_2,"org":_2}],"va":_2,"vc":[1,{"com":_2,"edu":_2,"gov":_2,"mil":_2,"net":_2,"org":_2,"gv":[2,{"d":_3}],"0e":_6,"mydns":_3}],"ve":[1,{"arts":_2,"bib":_2,"co":_2,"com":_2,"e12":_2,"edu":_2,"emprende":_2,"firm":_2,"gob":_2,"gov":_2,"ia":_2,"info":_2,"int":_2,"mil":_2,"net":_2,"nom":_2,"org":_2,"rar":_2,"rec":_2,"store":_2,"tec":_2,"web":_2}],"vg":[1,{"edu":_2}],"vi":[1,{"co":_2,"com":_2,"k12":_2,"net":_2,"org":_2}],"vn":[1,{"ac":_2,"ai":_2,"biz":_2,"com":_2,"edu":_2,"gov":_2,"health":_2,"id":_2,"info":_2,"int":_2,"io":_2,"name":_2,"net":_2,"org":_2,"pro":_2,"angiang":_2,"bacgiang":_2,"backan":_2,"baclieu":_2,"bacninh":_2,"baria-vungtau":_2,"bentre":_2,"binhdinh":_2,"binhduong":_2,"binhphuoc":_2,"binhthuan":_2,"camau":_2,"cantho":_2,"caobang":_2,"daklak":_2,"daknong":_2,"danang":_2,"dienbien":_2,"dongnai":_2,"dongthap":_2,"gialai":_2,"hagiang":_2,"haiduong":_2,"haiphong":_2,"hanam":_2,"hanoi":_2,"hatinh":_2,"haugiang":_2,"hoabinh":_2,"hungyen":_2,"khanhhoa":_2,"kiengiang":_2,"kontum":_2,"laichau":_2,"lamdong":_2,"langson":_2,"laocai":_2,"longan":_2,"namdinh":_2,"nghean":_2,"ninhbinh":_2,"ninhthuan":_2,"phutho":_2,"phuyen":_2,"quangbinh":_2,"quangnam":_2,"quangngai":_2,"quangninh":_2,"quangtri":_2,"soctrang":_2,"sonla":_2,"tayninh":_2,"thaibinh":_2,"thainguyen":_2,"thanhhoa":_2,"thanhphohochiminh":_2,"thuathienhue":_2,"tiengiang":_2,"travinh":_2,"tuyenquang":_2,"vinhlong":_2,"vinhphuc":_2,"yenbai":_2}],"vu":_47,"wf":[1,{"biz":_3,"sch":_3}],"ws":[1,{"com":_2,"edu":_2,"gov":_2,"net":_2,"org":_2,"advisor":_6,"cloud66":_3,"dyndns":_3,"mypets":_3}],"yt":[1,{"org":_3}],"xn--mgbaam7a8h":_2,"امارات":_2,"xn--y9a3aq":_2,"հայ":_2,"xn--54b7fta0cc":_2,"বাংলা":_2,"xn--90ae":_2,"бг":_2,"xn--mgbcpq6gpa1a":_2,"البحرين":_2,"xn--90ais":_2,"бел":_2,"xn--fiqs8s":_2,"中国":_2,"xn--fiqz9s":_2,"中國":_2,"xn--lgbbat1ad8j":_2,"الجزائر":_2,"xn--wgbh1c":_2,"مصر":_2,"xn--e1a4c":_2,"ею":_2,"xn--qxa6a":_2,"ευ":_2,"xn--mgbah1a3hjkrd":_2,"موريتانيا":_2,"xn--node":_2,"გე":_2,"xn--qxam":_2,"ελ":_2,"xn--j6w193g":[1,{"xn--gmqw5a":_2,"xn--55qx5d":_2,"xn--mxtq1m":_2,"xn--wcvs22d":_2,"xn--uc0atv":_2,"xn--od0alg":_2}],"香港":[1,{"個人":_2,"公司":_2,"政府":_2,"教育":_2,"組織":_2,"網絡":_2}],"xn--2scrj9c":_2,"ಭಾರತ":_2,"xn--3hcrj9c":_2,"ଭାରତ":_2,"xn--45br5cyl":_2,"ভাৰত":_2,"xn--h2breg3eve":_2,"भारतम्":_2,"xn--h2brj9c8c":_2,"भारोत":_2,"xn--mgbgu82a":_2,"ڀارت":_2,"xn--rvc1e0am3e":_2,"ഭാരതം":_2,"xn--h2brj9c":_2,"भारत":_2,"xn--mgbbh1a":_2,"بارت":_2,"xn--mgbbh1a71e":_2,"بھارت":_2,"xn--fpcrj9c3d":_2,"భారత్":_2,"xn--gecrj9c":_2,"ભારત":_2,"xn--s9brj9c":_2,"ਭਾਰਤ":_2,"xn--45brj9c":_2,"ভারত":_2,"xn--xkc2dl3a5ee0h":_2,"இந்தியா":_2,"xn--mgba3a4f16a":_2,"ایران":_2,"xn--mgba3a4fra":_2,"ايران":_2,"xn--mgbtx2b":_2,"عراق":_2,"xn--mgbayh7gpa":_2,"الاردن":_2,"xn--3e0b707e":_2,"한국":_2,"xn--80ao21a":_2,"қаз":_2,"xn--q7ce6a":_2,"ລາວ":_2,"xn--fzc2c9e2c":_2,"ලංකා":_2,"xn--xkc2al3hye2a":_2,"இலங்கை":_2,"xn--mgbc0a9azcg":_2,"المغرب":_2,"xn--d1alf":_2,"мкд":_2,"xn--l1acc":_2,"мон":_2,"xn--mix891f":_2,"澳門":_2,"xn--mix082f":_2,"澳门":_2,"xn--mgbx4cd0ab":_2,"مليسيا":_2,"xn--mgb9awbf":_2,"عمان":_2,"xn--mgbai9azgqp6j":_2,"پاکستان":_2,"xn--mgbai9a5eva00b":_2,"پاكستان":_2,"xn--ygbi2ammx":_2,"فلسطين":_2,"xn--90a3ac":[1,{"xn--80au":_2,"xn--90azh":_2,"xn--d1at":_2,"xn--c1avg":_2,"xn--o1ac":_2,"xn--o1ach":_2}],"срб":[1,{"ак":_2,"обр":_2,"од":_2,"орг":_2,"пр":_2,"упр":_2}],"xn--p1ai":_2,"рф":_2,"xn--wgbl6a":_2,"قطر":_2,"xn--mgberp4a5d4ar":_2,"السعودية":_2,"xn--mgberp4a5d4a87g":_2,"السعودیة":_2,"xn--mgbqly7c0a67fbc":_2,"السعودیۃ":_2,"xn--mgbqly7cvafr":_2,"السعوديه":_2,"xn--mgbpl2fh":_2,"سودان":_2,"xn--yfro4i67o":_2,"新加坡":_2,"xn--clchc0ea0b2g2a9gcd":_2,"சிங்கப்பூர்":_2,"xn--ogbpf8fl":_2,"سورية":_2,"xn--mgbtf8fl":_2,"سوريا":_2,"xn--o3cw4h":[1,{"xn--o3cyx2a":_2,"xn--12co0c3b4eva":_2,"xn--m3ch0j3a":_2,"xn--h3cuzk1di":_2,"xn--12c1fe0br":_2,"xn--12cfi8ixb8l":_2}],"ไทย":[1,{"ทหาร":_2,"ธุรกิจ":_2,"เน็ต":_2,"รัฐบาล":_2,"ศึกษา":_2,"องค์กร":_2}],"xn--pgbs0dh":_2,"تونس":_2,"xn--kpry57d":_2,"台灣":_2,"xn--kprw13d":_2,"台湾":_2,"xn--nnx388a":_2,"臺灣":_2,"xn--j1amh":_2,"укр":_2,"xn--mgb2ddes":_2,"اليمن":_2,"xxx":_2,"ye":_5,"za":[0,{"ac":_2,"agric":_2,"alt":_2,"co":_2,"edu":_2,"gov":_2,"grondar":_2,"law":_2,"mil":_2,"net":_2,"ngo":_2,"nic":_2,"nis":_2,"nom":_2,"org":_2,"school":_2,"tm":_2,"web":_2}],"zm":[1,{"ac":_2,"biz":_2,"co":_2,"com":_2,"edu":_2,"gov":_2,"info":_2,"mil":_2,"net":_2,"org":_2,"sch":_2}],"zw":[1,{"ac":_2,"co":_2,"gov":_2,"mil":_2,"org":_2}],"aaa":_2,"aarp":_2,"abb":_2,"abbott":_2,"abbvie":_2,"abc":_2,"able":_2,"abogado":_2,"abudhabi":_2,"academy":[1,{"official":_3}],"accenture":_2,"accountant":_2,"accountants":_2,"aco":_2,"actor":_2,"ads":_2,"adult":_2,"aeg":_2,"aetna":_2,"afl":_2,"africa":_2,"agakhan":_2,"agency":_2,"aig":_2,"airbus":_2,"airforce":_2,"airtel":_2,"akdn":_2,"alibaba":_2,"alipay":_2,"allfinanz":_2,"allstate":_2,"ally":_2,"alsace":_2,"alstom":_2,"amazon":_2,"americanexpress":_2,"americanfamily":_2,"amex":_2,"amfam":_2,"amica":_2,"amsterdam":_2,"analytics":_2,"android":_2,"anquan":_2,"anz":_2,"aol":_2,"apartments":_2,"app":[1,{"adaptable":_3,"aiven":_3,"beget":_6,"brave":_7,"clerk":_3,"clerkstage":_3,"cloudflare":_3,"wnext":_3,"csb":[2,{"preview":_3}],"convex":_3,"deta":_3,"ondigitalocean":_3,"easypanel":_3,"encr":[2,{"frontend":_3}],"evervault":_8,"expo":[2,{"staging":_3}],"edgecompute":_3,"on-fleek":_3,"flutterflow":_3,"e2b":_3,"framer":_3,"github":_3,"hosted":_6,"run":[0,{"*":_3,"mtls":_6}],"web":_3,"hackclub":_3,"hasura":_3,"botdash":_3,"leapcell":_3,"loginline":_3,"lovable":_3,"luyani":_3,"medusajs":_3,"messerli":_3,"mocha":_3,"netlify":_3,"ngrok":_3,"ngrok-free":_3,"developer":_6,"noop":_3,"northflank":_6,"upsun":_6,"railway":[0,{"up":_3}],"replit":_9,"nyat":_3,"snowflake":[0,{"*":_3,"privatelink":_6}],"streamlit":_3,"storipress":_3,"telebit":_3,"typedream":_3,"vercel":_3,"wal":_3,"wasmer":_3,"bookonline":_3,"windsurf":_3,"zeabur":_3,"zerops":_6}],"apple":_2,"aquarelle":_2,"arab":_2,"aramco":_2,"archi":_2,"army":_2,"art":_2,"arte":_2,"asda":_2,"associates":_2,"athleta":_2,"attorney":_2,"auction":_2,"audi":_2,"audible":_2,"audio":_2,"auspost":_2,"author":_2,"auto":_2,"autos":_2,"aws":[1,{"on":[0,{"af-south-1":_11,"ap-east-1":_11,"ap-northeast-1":_11,"ap-northeast-2":_11,"ap-northeast-3":_11,"ap-south-1":_11,"ap-south-2":_12,"ap-southeast-1":_11,"ap-southeast-2":_11,"ap-southeast-3":_11,"ap-southeast-4":_12,"ap-southeast-5":_12,"ca-central-1":_11,"ca-west-1":_12,"eu-central-1":_11,"eu-central-2":_12,"eu-north-1":_11,"eu-south-1":_11,"eu-south-2":_12,"eu-west-1":_11,"eu-west-2":_11,"eu-west-3":_11,"il-central-1":_12,"me-central-1":_12,"me-south-1":_11,"sa-east-1":_11,"us-east-1":_11,"us-east-2":_11,"us-west-1":_11,"us-west-2":_11,"us-gov-east-1":_13,"us-gov-west-1":_13}],"sagemaker":[0,{"ap-northeast-1":_15,"ap-northeast-2":_15,"ap-south-1":_15,"ap-southeast-1":_15,"ap-southeast-2":_15,"ca-central-1":_17,"eu-central-1":_15,"eu-west-1":_15,"eu-west-2":_15,"us-east-1":_17,"us-east-2":_17,"us-west-2":_17,"af-south-1":_14,"ap-east-1":_14,"ap-northeast-3":_14,"ap-south-2":_16,"ap-southeast-3":_14,"ap-southeast-4":_16,"ca-west-1":[0,{"notebook":_3,"notebook-fips":_3}],"eu-central-2":_14,"eu-north-1":_14,"eu-south-1":_14,"eu-south-2":_14,"eu-west-3":_14,"il-central-1":_14,"me-central-1":_14,"me-south-1":_14,"sa-east-1":_14,"us-gov-east-1":_18,"us-gov-west-1":_18,"us-west-1":[0,{"notebook":_3,"notebook-fips":_3,"studio":_3}],"experiments":_6}],"repost":[0,{"private":_6}]}],"axa":_2,"azure":_2,"baby":_2,"baidu":_2,"banamex":_2,"band":_2,"bank":_2,"bar":_2,"barcelona":_2,"barclaycard":_2,"barclays":_2,"barefoot":_2,"bargains":_2,"baseball":_2,"basketball":[1,{"aus":_3,"nz":_3}],"bauhaus":_2,"bayern":_2,"bbc":_2,"bbt":_2,"bbva":_2,"bcg":_2,"bcn":_2,"beats":_2,"beauty":_2,"beer":_2,"berlin":_2,"best":_2,"bestbuy":_2,"bet":_2,"bharti":_2,"bible":_2,"bid":_2,"bike":_2,"bing":_2,"bingo":_2,"bio":_2,"black":_2,"blackfriday":_2,"blockbuster":_2,"blog":_2,"bloomberg":_2,"blue":_2,"bms":_2,"bmw":_2,"bnpparibas":_2,"boats":_2,"boehringer":_2,"bofa":_2,"bom":_2,"bond":_2,"boo":_2,"book":_2,"booking":_2,"bosch":_2,"bostik":_2,"boston":_2,"bot":_2,"boutique":_2,"box":_2,"bradesco":_2,"bridgestone":_2,"broadway":_2,"broker":_2,"brother":_2,"brussels":_2,"build":[1,{"v0":_3,"windsurf":_3}],"builders":[1,{"cloudsite":_3}],"business":_21,"buy":_2,"buzz":_2,"bzh":_2,"cab":_2,"cafe":_2,"cal":_2,"call":_2,"calvinklein":_2,"cam":_2,"camera":_2,"camp":[1,{"emf":[0,{"at":_3}]}],"canon":_2,"capetown":_2,"capital":_2,"capitalone":_2,"car":_2,"caravan":_2,"cards":_2,"care":_2,"career":_2,"careers":_2,"cars":_2,"casa":[1,{"nabu":[0,{"ui":_3}]}],"case":_2,"cash":_2,"casino":_2,"catering":_2,"catholic":_2,"cba":_2,"cbn":_2,"cbre":_2,"center":_2,"ceo":_2,"cern":_2,"cfa":_2,"cfd":_2,"chanel":_2,"channel":_2,"charity":_2,"chase":_2,"chat":_2,"cheap":_2,"chintai":_2,"christmas":_2,"chrome":_2,"church":_2,"cipriani":_2,"circle":_2,"cisco":_2,"citadel":_2,"citi":_2,"citic":_2,"city":_2,"claims":_2,"cleaning":_2,"click":_2,"clinic":_2,"clinique":_2,"clothing":_2,"cloud":[1,{"convex":_3,"elementor":_3,"emergent":_3,"encoway":[0,{"eu":_3}],"statics":_6,"ravendb":_3,"axarnet":[0,{"es-1":_3}],"diadem":_3,"jelastic":[0,{"vip":_3}],"jele":_3,"jenv-aruba":[0,{"aruba":[0,{"eur":[0,{"it1":_3}]}],"it1":_3}],"keliweb":[2,{"cs":_3}],"oxa":[2,{"tn":_3,"uk":_3}],"primetel":[2,{"uk":_3}],"reclaim":[0,{"ca":_3,"uk":_3,"us":_3}],"trendhosting":[0,{"ch":_3,"de":_3}],"jote":_3,"jotelulu":_3,"kuleuven":_3,"laravel":_3,"linkyard":_3,"magentosite":_6,"matlab":_3,"observablehq":_3,"perspecta":_3,"vapor":_3,"on-rancher":_6,"scw":[0,{"baremetal":[0,{"fr-par-1":_3,"fr-par-2":_3,"nl-ams-1":_3}],"fr-par":[0,{"cockpit":_3,"ddl":_3,"dtwh":_3,"fnc":[2,{"functions":_3}],"ifr":_3,"k8s":_23,"kafk":_3,"mgdb":_3,"rdb":_3,"s3":_3,"s3-website":_3,"scbl":_3,"whm":_3}],"instances":[0,{"priv":_3,"pub":_3}],"k8s":_3,"nl-ams":[0,{"cockpit":_3,"ddl":_3,"dtwh":_3,"ifr":_3,"k8s":_23,"kafk":_3,"mgdb":_3,"rdb":_3,"s3":_3,"s3-website":_3,"scbl":_3,"whm":_3}],"pl-waw":[0,{"cockpit":_3,"ddl":_3,"dtwh":_3,"ifr":_3,"k8s":_23,"kafk":_3,"mgdb":_3,"rdb":_3,"s3":_3,"s3-website":_3,"scbl":_3}],"scalebook":_3,"smartlabeling":_3}],"servebolt":_3,"onstackit":[0,{"runs":_3}],"trafficplex":_3,"unison-services":_3,"urown":_3,"voorloper":_3,"zap":_3}],"club":[1,{"cloudns":_3,"jele":_3,"barsy":_3}],"clubmed":_2,"coach":_2,"codes":[1,{"owo":_6}],"coffee":_2,"college":_2,"cologne":_2,"commbank":_2,"community":[1,{"nog":_3,"ravendb":_3,"myforum":_3}],"company":_2,"compare":_2,"computer":_2,"comsec":_2,"condos":_2,"construction":_2,"consulting":_2,"contact":_2,"contractors":_2,"cooking":_2,"cool":[1,{"elementor":_3,"de":_3}],"corsica":_2,"country":_2,"coupon":_2,"coupons":_2,"courses":_2,"cpa":_2,"credit":_2,"creditcard":_2,"creditunion":_2,"cricket":_2,"crown":_2,"crs":_2,"cruise":_2,"cruises":_2,"cuisinella":_2,"cymru":_2,"cyou":_2,"dad":_2,"dance":_2,"data":_2,"date":_2,"dating":_2,"datsun":_2,"day":_2,"dclk":_2,"dds":_2,"deal":_2,"dealer":_2,"deals":_2,"degree":_2,"delivery":_2,"dell":_2,"deloitte":_2,"delta":_2,"democrat":_2,"dental":_2,"dentist":_2,"desi":_2,"design":[1,{"graphic":_3,"bss":_3}],"dev":[1,{"12chars":_3,"myaddr":_3,"panel":_3,"bearblog":_3,"lcl":_6,"lclstage":_6,"stg":_6,"stgstage":_6,"pages":_3,"r2":_3,"workers":_3,"deno":_3,"deno-staging":_3,"deta":_3,"lp":[2,{"api":_3,"objects":_3}],"evervault":_8,"fly":_3,"githubpreview":_3,"gateway":_6,"botdash":_3,"inbrowser":_6,"is-a-good":_3,"iserv":_3,"leapcell":_3,"runcontainers":_3,"localcert":[0,{"user":_6}],"loginline":_3,"barsy":_3,"mediatech":_3,"mocha-sandbox":_3,"modx":_3,"ngrok":_3,"ngrok-free":_3,"is-a-fullstack":_3,"is-cool":_3,"is-not-a":_3,"localplayer":_3,"xmit":_3,"platter-app":_3,"replit":[2,{"archer":_3,"bones":_3,"canary":_3,"global":_3,"hacker":_3,"id":_3,"janeway":_3,"kim":_3,"kira":_3,"kirk":_3,"odo":_3,"paris":_3,"picard":_3,"pike":_3,"prerelease":_3,"reed":_3,"riker":_3,"sisko":_3,"spock":_3,"staging":_3,"sulu":_3,"tarpit":_3,"teams":_3,"tucker":_3,"wesley":_3,"worf":_3}],"crm":[0,{"d":_6,"w":_6,"wa":_6,"wb":_6,"wc":_6,"wd":_6,"we":_6,"wf":_6}],"erp":_50,"vercel":_3,"webhare":_6,"hrsn":_3,"is-a":_3}],"dhl":_2,"diamonds":_2,"diet":_2,"digital":[1,{"cloudapps":[2,{"london":_3}]}],"direct":[1,{"libp2p":_3}],"directory":_2,"discount":_2,"discover":_2,"dish":_2,"diy":_2,"dnp":_2,"docs":_2,"doctor":_2,"dog":_2,"domains":_2,"dot":_2,"download":_2,"drive":_2,"dtv":_2,"dubai":_2,"dupont":_2,"durban":_2,"dvag":_2,"dvr":_2,"earth":_2,"eat":_2,"eco":_2,"edeka":_2,"education":_21,"email":[1,{"crisp":[0,{"on":_3}],"tawk":_52,"tawkto":_52}],"emerck":_2,"energy":_2,"engineer":_2,"engineering":_2,"enterprises":_2,"epson":_2,"equipment":_2,"ericsson":_2,"erni":_2,"esq":_2,"estate":[1,{"compute":_6}],"eurovision":_2,"eus":[1,{"party":_53}],"events":[1,{"koobin":_3,"co":_3}],"exchange":_2,"expert":_2,"exposed":_2,"express":_2,"extraspace":_2,"fage":_2,"fail":_2,"fairwinds":_2,"faith":_2,"family":_2,"fan":_2,"fans":_2,"farm":[1,{"storj":_3}],"farmers":_2,"fashion":_2,"fast":_2,"fedex":_2,"feedback":_2,"ferrari":_2,"ferrero":_2,"fidelity":_2,"fido":_2,"film":_2,"final":_2,"finance":_2,"financial":_21,"fire":_2,"firestone":_2,"firmdale":_2,"fish":_2,"fishing":_2,"fit":_2,"fitness":_2,"flickr":_2,"flights":_2,"flir":_2,"florist":_2,"flowers":_2,"fly":_2,"foo":_2,"food":_2,"football":_2,"ford":_2,"forex":_2,"forsale":_2,"forum":_2,"foundation":_2,"fox":_2,"free":_2,"fresenius":_2,"frl":_2,"frogans":_2,"frontier":_2,"ftr":_2,"fujitsu":_2,"fun":_2,"fund":_2,"furniture":_2,"futbol":_2,"fyi":_2,"gal":_2,"gallery":_2,"gallo":_2,"gallup":_2,"game":_2,"games":[1,{"pley":_3,"sheezy":_3}],"gap":_2,"garden":_2,"gay":[1,{"pages":_3}],"gbiz":_2,"gdn":[1,{"cnpy":_3}],"gea":_2,"gent":_2,"genting":_2,"george":_2,"ggee":_2,"gift":_2,"gifts":_2,"gives":_2,"giving":_2,"glass":_2,"gle":_2,"global":[1,{"appwrite":_3}],"globo":_2,"gmail":_2,"gmbh":_2,"gmo":_2,"gmx":_2,"godaddy":_2,"gold":_2,"goldpoint":_2,"golf":_2,"goo":_2,"goodyear":_2,"goog":[1,{"cloud":_3,"translate":_3,"usercontent":_6}],"google":_2,"gop":_2,"got":_2,"grainger":_2,"graphics":_2,"gratis":_2,"green":_2,"gripe":_2,"grocery":_2,"group":[1,{"discourse":_3}],"gucci":_2,"guge":_2,"guide":_2,"guitars":_2,"guru":_2,"hair":_2,"hamburg":_2,"hangout":_2,"haus":_2,"hbo":_2,"hdfc":_2,"hdfcbank":_2,"health":[1,{"hra":_3}],"healthcare":_2,"help":_2,"helsinki":_2,"here":_2,"hermes":_2,"hiphop":_2,"hisamitsu":_2,"hitachi":_2,"hiv":_2,"hkt":_2,"hockey":_2,"holdings":_2,"holiday":_2,"homedepot":_2,"homegoods":_2,"homes":_2,"homesense":_2,"honda":_2,"horse":_2,"hospital":_2,"host":[1,{"cloudaccess":_3,"freesite":_3,"easypanel":_3,"emergent":_3,"fastvps":_3,"myfast":_3,"tempurl":_3,"wpmudev":_3,"iserv":_3,"jele":_3,"mircloud":_3,"bolt":_3,"wp2":_3,"half":_3}],"hosting":[1,{"opencraft":_3}],"hot":_2,"hotel":_2,"hotels":_2,"hotmail":_2,"house":_2,"how":_2,"hsbc":_2,"hughes":_2,"hyatt":_2,"hyundai":_2,"ibm":_2,"icbc":_2,"ice":_2,"icu":_2,"ieee":_2,"ifm":_2,"ikano":_2,"imamat":_2,"imdb":_2,"immo":_2,"immobilien":_2,"inc":_2,"industries":_2,"infiniti":_2,"ing":_2,"ink":_2,"institute":_2,"insurance":_2,"insure":_2,"international":_2,"intuit":_2,"investments":_2,"ipiranga":_2,"irish":_2,"ismaili":_2,"ist":_2,"istanbul":_2,"itau":_2,"itv":_2,"jaguar":_2,"java":_2,"jcb":_2,"jeep":_2,"jetzt":_2,"jewelry":_2,"jio":_2,"jll":_2,"jmp":_2,"jnj":_2,"joburg":_2,"jot":_2,"joy":_2,"jpmorgan":_2,"jprs":_2,"juegos":_2,"juniper":_2,"kaufen":_2,"kddi":_2,"kerryhotels":_2,"kerryproperties":_2,"kfh":_2,"kia":_2,"kids":_2,"kim":_2,"kindle":_2,"kitchen":_2,"kiwi":_2,"koeln":_2,"komatsu":_2,"kosher":_2,"kpmg":_2,"kpn":_2,"krd":[1,{"co":_3,"edu":_3}],"kred":_2,"kuokgroup":_2,"kyoto":_2,"lacaixa":_2,"lamborghini":_2,"lamer":_2,"land":_2,"landrover":_2,"lanxess":_2,"lasalle":_2,"lat":_2,"latino":_2,"latrobe":_2,"law":_2,"lawyer":_2,"lds":_2,"lease":_2,"leclerc":_2,"lefrak":_2,"legal":_2,"lego":_2,"lexus":_2,"lgbt":_2,"lidl":_2,"life":_2,"lifeinsurance":_2,"lifestyle":_2,"lighting":_2,"like":_2,"lilly":_2,"limited":_2,"limo":_2,"lincoln":_2,"link":[1,{"myfritz":_3,"cyon":_3,"joinmc":_3,"dweb":_6,"inbrowser":_6,"nftstorage":_60,"mypep":_3,"storacha":_60,"w3s":_60}],"live":[1,{"aem":_3,"hlx":_3,"ewp":_6}],"living":_2,"llc":_2,"llp":_2,"loan":_2,"loans":_2,"locker":_2,"locus":_2,"lol":[1,{"omg":_3}],"london":_2,"lotte":_2,"lotto":_2,"love":_2,"lpl":_2,"lplfinancial":_2,"ltd":_2,"ltda":_2,"lundbeck":_2,"luxe":_2,"luxury":_2,"madrid":_2,"maif":_2,"maison":_2,"makeup":_2,"man":_2,"management":_2,"mango":_2,"map":_2,"market":_2,"marketing":_2,"markets":_2,"marriott":_2,"marshalls":_2,"mattel":_2,"mba":_2,"mckinsey":_2,"med":_2,"media":_61,"meet":_2,"melbourne":_2,"meme":_2,"memorial":_2,"men":_2,"menu":[1,{"barsy":_3,"barsyonline":_3}],"merck":_2,"merckmsd":_2,"miami":_2,"microsoft":_2,"mini":_2,"mint":_2,"mit":_2,"mitsubishi":_2,"mlb":_2,"mls":_2,"mma":_2,"mobile":_2,"moda":_2,"moe":_2,"moi":_2,"mom":_2,"monash":_2,"money":_2,"monster":_2,"mormon":_2,"mortgage":_2,"moscow":_2,"moto":_2,"motorcycles":_2,"mov":_2,"movie":_2,"msd":_2,"mtn":_2,"mtr":_2,"music":_2,"nab":_2,"nagoya":_2,"navy":_2,"nba":_2,"nec":_2,"netbank":_2,"netflix":_2,"network":[1,{"aem":_3,"alces":_6,"co":_3,"arvo":_3,"azimuth":_3,"tlon":_3}],"neustar":_2,"new":_2,"news":[1,{"noticeable":_3}],"next":_2,"nextdirect":_2,"nexus":_2,"nfl":_2,"ngo":_2,"nhk":_2,"nico":_2,"nike":_2,"nikon":_2,"ninja":_2,"nissan":_2,"nissay":_2,"nokia":_2,"norton":_2,"now":_2,"nowruz":_2,"nowtv":_2,"nra":_2,"nrw":_2,"ntt":_2,"nyc":_2,"obi":_2,"observer":_2,"office":_2,"okinawa":_2,"olayan":_2,"olayangroup":_2,"ollo":_2,"omega":_2,"one":[1,{"kin":_6,"service":_3,"website":_3}],"ong":[1,{"obl":_3}],"onl":_2,"online":[1,{"eero":_3,"eero-stage":_3,"websitebuilder":_3,"leapcell":_3,"barsy":_3}],"ooo":_2,"open":_2,"oracle":_2,"orange":[1,{"tech":_3}],"organic":_2,"origins":_2,"osaka":_2,"otsuka":_2,"ott":_2,"ovh":[1,{"nerdpol":_3}],"page":[1,{"aem":_3,"hlx":_3,"translated":_3,"codeberg":_3,"heyflow":_3,"prvcy":_3,"rocky":_3,"statichost":_3,"pdns":_3,"plesk":_3}],"panasonic":_2,"paris":_2,"pars":_2,"partners":_2,"parts":_2,"party":_2,"pay":_2,"pccw":_2,"pet":_2,"pfizer":_2,"pharmacy":_2,"phd":_2,"philips":_2,"phone":_2,"photo":_2,"photography":_2,"photos":_61,"physio":_2,"pics":_2,"pictet":_2,"pictures":[1,{"1337":_3}],"pid":_2,"pin":_2,"ping":_2,"pink":_2,"pioneer":_2,"pizza":[1,{"ngrok":_3}],"place":_21,"play":_2,"playstation":_2,"plumbing":_2,"plus":[1,{"playit":[2,{"at":_6,"with":_3}]}],"pnc":_2,"pohl":_2,"poker":_2,"politie":_2,"porn":_2,"praxi":_2,"press":_2,"prime":_2,"prod":_2,"productions":_2,"prof":_2,"progressive":_2,"promo":_2,"properties":_2,"property":_2,"protection":_2,"pru":_2,"prudential":_2,"pub":[1,{"id":_6,"kin":_6,"barsy":_3}],"pwc":_2,"qpon":_2,"quebec":_2,"quest":_2,"racing":_2,"radio":_2,"read":_2,"realestate":_2,"realtor":_2,"realty":_2,"recipes":_2,"red":_2,"redumbrella":_2,"rehab":_2,"reise":_2,"reisen":_2,"reit":_2,"reliance":_2,"ren":_2,"rent":_2,"rentals":_2,"repair":_2,"report":_2,"republican":_2,"rest":_2,"restaurant":_2,"review":_2,"reviews":[1,{"aem":_3}],"rexroth":_2,"rich":_2,"richardli":_2,"ricoh":_2,"ril":_2,"rio":_2,"rip":[1,{"clan":_3}],"rocks":[1,{"myddns":_3,"stackit":_3,"lima-city":_3,"webspace":_3}],"rodeo":_2,"rogers":_2,"room":_2,"rsvp":_2,"rugby":_2,"ruhr":_2,"run":[1,{"appwrite":_6,"canva":_3,"development":_3,"ravendb":_3,"liara":[2,{"iran":_3}],"lovable":_3,"needle":_3,"build":_6,"code":_6,"database":_6,"migration":_6,"onporter":_3,"repl":_3,"stackit":_3,"val":_50,"vercel":_3,"wix":_3}],"rwe":_2,"ryukyu":_2,"saarland":_2,"safe":_2,"safety":_2,"sakura":_2,"sale":_2,"salon":_2,"samsclub":_2,"samsung":_2,"sandvik":_2,"sandvikcoromant":_2,"sanofi":_2,"sap":_2,"sarl":_2,"sas":_2,"save":_2,"saxo":_2,"sbi":_2,"sbs":_2,"scb":_2,"schaeffler":_2,"schmidt":_2,"scholarships":_2,"school":_2,"schule":_2,"schwarz":_2,"science":_2,"scot":[1,{"gov":[2,{"service":_3}]}],"search":_2,"seat":_2,"secure":_2,"security":_2,"seek":_2,"select":_2,"sener":_2,"services":[1,{"loginline":_3}],"seven":_2,"sew":_2,"sex":_2,"sexy":_2,"sfr":_2,"shangrila":_2,"sharp":_2,"shell":_2,"shia":_2,"shiksha":_2,"shoes":_2,"shop":[1,{"base":_3,"hoplix":_3,"barsy":_3,"barsyonline":_3,"shopware":_3}],"shopping":_2,"shouji":_2,"show":_2,"silk":_2,"sina":_2,"singles":_2,"site":[1,{"square":_3,"canva":_24,"cloudera":_6,"convex":_3,"cyon":_3,"caffeine":_3,"fastvps":_3,"figma":_3,"figma-gov":_3,"preview":_3,"heyflow":_3,"jele":_3,"jouwweb":_3,"loginline":_3,"barsy":_3,"co":_3,"notion":_3,"omniwe":_3,"opensocial":_3,"madethis":_3,"support":_3,"platformsh":_6,"tst":_6,"byen":_3,"srht":_3,"novecore":_3,"cpanel":_3,"wpsquared":_3,"sourcecraft":_3}],"ski":_2,"skin":_2,"sky":_2,"skype":_2,"sling":_2,"smart":_2,"smile":_2,"sncf":_2,"soccer":_2,"social":_2,"softbank":_2,"software":_2,"sohu":_2,"solar":_2,"solutions":_2,"song":_2,"sony":_2,"soy":_2,"spa":_2,"space":[1,{"myfast":_3,"heiyu":_3,"hf":[2,{"static":_3}],"app-ionos":_3,"project":_3,"uber":_3,"xs4all":_3}],"sport":_2,"spot":_2,"srl":_2,"stada":_2,"staples":_2,"star":_2,"statebank":_2,"statefarm":_2,"stc":_2,"stcgroup":_2,"stockholm":_2,"storage":_2,"store":[1,{"barsy":_3,"sellfy":_3,"shopware":_3,"storebase":_3}],"stream":_2,"studio":_2,"study":_2,"style":_2,"sucks":_2,"supplies":_2,"supply":_2,"support":[1,{"barsy":_3}],"surf":_2,"surgery":_2,"suzuki":_2,"swatch":_2,"swiss":_2,"sydney":_2,"systems":[1,{"knightpoint":_3}],"tab":_2,"taipei":_2,"talk":_2,"taobao":_2,"target":_2,"tatamotors":_2,"tatar":_2,"tattoo":_2,"tax":_2,"taxi":_2,"tci":_2,"tdk":_2,"team":[1,{"discourse":_3,"jelastic":_3}],"tech":[1,{"cleverapps":_3}],"technology":_21,"temasek":_2,"tennis":_2,"teva":_2,"thd":_2,"theater":_2,"theatre":_2,"tiaa":_2,"tickets":_2,"tienda":_2,"tips":_2,"tires":_2,"tirol":_2,"tjmaxx":_2,"tjx":_2,"tkmaxx":_2,"tmall":_2,"today":[1,{"prequalifyme":_3}],"tokyo":_2,"tools":[1,{"addr":_49,"myaddr":_3}],"top":[1,{"ntdll":_3,"wadl":_6}],"toray":_2,"toshiba":_2,"total":_2,"tours":_2,"town":_2,"toyota":_2,"toys":_2,"trade":_2,"trading":_2,"training":_2,"travel":_2,"travelers":_2,"travelersinsurance":_2,"trust":_2,"trv":_2,"tube":_2,"tui":_2,"tunes":_2,"tushu":_2,"tvs":_2,"ubank":_2,"ubs":_2,"unicom":_2,"university":_2,"uno":_2,"uol":_2,"ups":_2,"vacations":_2,"vana":_2,"vanguard":_2,"vegas":_2,"ventures":_2,"verisign":_2,"versicherung":_2,"vet":_2,"viajes":_2,"video":_2,"vig":_2,"viking":_2,"villas":_2,"vin":_2,"vip":[1,{"hidns":_3}],"virgin":_2,"visa":_2,"vision":_2,"viva":_2,"vivo":_2,"vlaanderen":_2,"vodka":_2,"volvo":_2,"vote":_2,"voting":_2,"voto":_2,"voyage":_2,"wales":_2,"walmart":_2,"walter":_2,"wang":_2,"wanggou":_2,"watch":_2,"watches":_2,"weather":_2,"weatherchannel":_2,"webcam":_2,"weber":_2,"website":_61,"wed":_2,"wedding":_2,"weibo":_2,"weir":_2,"whoswho":_2,"wien":_2,"wiki":_61,"williamhill":_2,"win":_2,"windows":_2,"wine":_2,"winners":_2,"wme":_2,"wolterskluwer":_2,"woodside":_2,"work":_2,"works":_2,"world":_2,"wow":_2,"wtc":_2,"wtf":_2,"xbox":_2,"xerox":_2,"xihuan":_2,"xin":_2,"xn--11b4c3d":_2,"कॉम":_2,"xn--1ck2e1b":_2,"セール":_2,"xn--1qqw23a":_2,"佛山":_2,"xn--30rr7y":_2,"慈善":_2,"xn--3bst00m":_2,"集团":_2,"xn--3ds443g":_2,"在线":_2,"xn--3pxu8k":_2,"点看":_2,"xn--42c2d9a":_2,"คอม":_2,"xn--45q11c":_2,"八卦":_2,"xn--4gbrim":_2,"موقع":_2,"xn--55qw42g":_2,"公益":_2,"xn--55qx5d":_2,"公司":_2,"xn--5su34j936bgsg":_2,"香格里拉":_2,"xn--5tzm5g":_2,"网站":_2,"xn--6frz82g":_2,"移动":_2,"xn--6qq986b3xl":_2,"我爱你":_2,"xn--80adxhks":_2,"москва":_2,"xn--80aqecdr1a":_2,"католик":_2,"xn--80asehdb":_2,"онлайн":_2,"xn--80aswg":_2,"сайт":_2,"xn--8y0a063a":_2,"联通":_2,"xn--9dbq2a":_2,"קום":_2,"xn--9et52u":_2,"时尚":_2,"xn--9krt00a":_2,"微博":_2,"xn--b4w605ferd":_2,"淡马锡":_2,"xn--bck1b9a5dre4c":_2,"ファッション":_2,"xn--c1avg":_2,"орг":_2,"xn--c2br7g":_2,"नेट":_2,"xn--cck2b3b":_2,"ストア":_2,"xn--cckwcxetd":_2,"アマゾン":_2,"xn--cg4bki":_2,"삼성":_2,"xn--czr694b":_2,"商标":_2,"xn--czrs0t":_2,"商店":_2,"xn--czru2d":_2,"商城":_2,"xn--d1acj3b":_2,"дети":_2,"xn--eckvdtc9d":_2,"ポイント":_2,"xn--efvy88h":_2,"新闻":_2,"xn--fct429k":_2,"家電":_2,"xn--fhbei":_2,"كوم":_2,"xn--fiq228c5hs":_2,"中文网":_2,"xn--fiq64b":_2,"中信":_2,"xn--fjq720a":_2,"娱乐":_2,"xn--flw351e":_2,"谷歌":_2,"xn--fzys8d69uvgm":_2,"電訊盈科":_2,"xn--g2xx48c":_2,"购物":_2,"xn--gckr3f0f":_2,"クラウド":_2,"xn--gk3at1e":_2,"通販":_2,"xn--hxt814e":_2,"网店":_2,"xn--i1b6b1a6a2e":_2,"संगठन":_2,"xn--imr513n":_2,"餐厅":_2,"xn--io0a7i":_2,"网络":_2,"xn--j1aef":_2,"ком":_2,"xn--jlq480n2rg":_2,"亚马逊":_2,"xn--jvr189m":_2,"食品":_2,"xn--kcrx77d1x4a":_2,"飞利浦":_2,"xn--kput3i":_2,"手机":_2,"xn--mgba3a3ejt":_2,"ارامكو":_2,"xn--mgba7c0bbn0a":_2,"العليان":_2,"xn--mgbab2bd":_2,"بازار":_2,"xn--mgbca7dzdo":_2,"ابوظبي":_2,"xn--mgbi4ecexp":_2,"كاثوليك":_2,"xn--mgbt3dhd":_2,"همراه":_2,"xn--mk1bu44c":_2,"닷컴":_2,"xn--mxtq1m":_2,"政府":_2,"xn--ngbc5azd":_2,"شبكة":_2,"xn--ngbe9e0a":_2,"بيتك":_2,"xn--ngbrx":_2,"عرب":_2,"xn--nqv7f":_2,"机构":_2,"xn--nqv7fs00ema":_2,"组织机构":_2,"xn--nyqy26a":_2,"健康":_2,"xn--otu796d":_2,"招聘":_2,"xn--p1acf":[1,{"xn--90amc":_3,"xn--j1aef":_3,"xn--j1ael8b":_3,"xn--h1ahn":_3,"xn--j1adp":_3,"xn--c1avg":_3,"xn--80aaa0cvac":_3,"xn--h1aliz":_3,"xn--90a1af":_3,"xn--41a":_3}],"рус":[1,{"биз":_3,"ком":_3,"крым":_3,"мир":_3,"мск":_3,"орг":_3,"самара":_3,"сочи":_3,"спб":_3,"я":_3}],"xn--pssy2u":_2,"大拿":_2,"xn--q9jyb4c":_2,"みんな":_2,"xn--qcka1pmc":_2,"グーグル":_2,"xn--rhqv96g":_2,"世界":_2,"xn--rovu88b":_2,"書籍":_2,"xn--ses554g":_2,"网址":_2,"xn--t60b56a":_2,"닷넷":_2,"xn--tckwe":_2,"コム":_2,"xn--tiq49xqyj":_2,"天主教":_2,"xn--unup4y":_2,"游戏":_2,"xn--vermgensberater-ctb":_2,"vermögensberater":_2,"xn--vermgensberatung-pwb":_2,"vermögensberatung":_2,"xn--vhquv":_2,"企业":_2,"xn--vuq861b":_2,"信息":_2,"xn--w4r85el8fhu5dnra":_2,"嘉里大酒店":_2,"xn--w4rs40l":_2,"嘉里":_2,"xn--xhq521b":_2,"广东":_2,"xn--zfr164b":_2,"政务":_2,"xyz":[1,{"caffeine":_3,"botdash":_3,"telebit":_6}],"yachts":_2,"yahoo":_2,"yamaxun":_2,"yandex":_2,"yodobashi":_2,"yoga":_2,"yokohama":_2,"you":_2,"youtube":_2,"yun":_2,"zappos":_2,"zara":_2,"zero":_2,"zip":_2,"zone":[1,{"triton":_6,"stackit":_3,"lima":_3}],"zuerich":_2}];return rules;}();
|
||
;// ../../node_modules/tldts/dist/es6/src/suffix-trie.js
|
||
/**
|
||
* Lookup parts of domain in Trie
|
||
*/function lookupInTrie(parts,trie,index,allowedMask){let result=null;let node=trie;while(node!==undefined){// We have a match!
|
||
if((node[0]&allowedMask)!==0){result={index:index+1,isIcann:node[0]===1/* RULE_TYPE.ICANN */,isPrivate:node[0]===2/* RULE_TYPE.PRIVATE */};}// No more `parts` to look for
|
||
if(index===-1){break;}const succ=node[1];node=Object.prototype.hasOwnProperty.call(succ,parts[index])?succ[parts[index]]:succ['*'];index-=1;}return result;}/**
|
||
* Check if `hostname` has a valid public suffix in `trie`.
|
||
*/function suffix_trie_suffixLookup(hostname,options,out){var _a;if(fast_path(hostname,options,out)){return;}const hostnameParts=hostname.split('.');const allowedMask=(options.allowPrivateDomains?2/* RULE_TYPE.PRIVATE */:0)|(options.allowIcannDomains?1/* RULE_TYPE.ICANN */:0);// Look for exceptions
|
||
const exceptionMatch=lookupInTrie(hostnameParts,exceptions,hostnameParts.length-1,allowedMask);if(exceptionMatch!==null){out.isIcann=exceptionMatch.isIcann;out.isPrivate=exceptionMatch.isPrivate;out.publicSuffix=hostnameParts.slice(exceptionMatch.index+1).join('.');return;}// Look for a match in rules
|
||
const rulesMatch=lookupInTrie(hostnameParts,rules,hostnameParts.length-1,allowedMask);if(rulesMatch!==null){out.isIcann=rulesMatch.isIcann;out.isPrivate=rulesMatch.isPrivate;out.publicSuffix=hostnameParts.slice(rulesMatch.index).join('.');return;}// No match found...
|
||
// Prevailing rule is '*' so we consider the top-level domain to be the
|
||
// public suffix of `hostname` (e.g.: 'example.org' => 'org').
|
||
out.isIcann=false;out.isPrivate=false;out.publicSuffix=(_a=hostnameParts[hostnameParts.length-1])!==null&&_a!==void 0?_a:null;}
|
||
;// ../../node_modules/tldts/dist/es6/index.js
|
||
// For all methods but 'parse', it does not make sense to allocate an object
|
||
// every single time to only return the value of a specific attribute. To avoid
|
||
// this un-necessary allocation, we use a global object which is re-used.
|
||
const RESULT=getEmptyResult();function parse(url,options={}){return factory_parseImpl(url,5/* FLAG.ALL */,suffix_trie_suffixLookup,options,getEmptyResult());}function getHostname(url,options={}){/*@__INLINE__*/factory_resetResult(RESULT);return factory_parseImpl(url,0/* FLAG.HOSTNAME */,suffix_trie_suffixLookup,options,RESULT).hostname;}function getPublicSuffix(url,options={}){/*@__INLINE__*/resetResult(RESULT);return parseImpl(url,2/* FLAG.PUBLIC_SUFFIX */,suffixLookup,options,RESULT).publicSuffix;}function es6_getDomain(url,options={}){/*@__INLINE__*/resetResult(RESULT);return parseImpl(url,3/* FLAG.DOMAIN */,suffixLookup,options,RESULT).domain;}function es6_getSubdomain(url,options={}){/*@__INLINE__*/resetResult(RESULT);return parseImpl(url,4/* FLAG.SUB_DOMAIN */,suffixLookup,options,RESULT).subdomain;}function es6_getDomainWithoutSuffix(url,options={}){/*@__INLINE__*/resetResult(RESULT);return parseImpl(url,5/* FLAG.ALL */,suffixLookup,options,RESULT).domainWithoutSuffix;}
|
||
;// ../../libs/common/src/platform/misc/utils.ts
|
||
/* provided dependency */ var utils_process = __webpack_require__(45202);
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
/* eslint-disable no-useless-escape */
|
||
|
||
|
||
|
||
|
||
// FIXME: Remove when updating file. Eslint update
|
||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||
const nodeURL = typeof self === "undefined" ? __webpack_require__(10967) : null;
|
||
class utils_Utils {
|
||
static init() {
|
||
if (utils_Utils.inited) {
|
||
return;
|
||
}
|
||
utils_Utils.inited = true;
|
||
utils_Utils.isNode =
|
||
typeof utils_process !== "undefined" &&
|
||
utils_process.release != null &&
|
||
utils_process.release.name === "node";
|
||
utils_Utils.isBrowser = typeof window !== "undefined";
|
||
utils_Utils.isMobileBrowser = utils_Utils.isBrowser && this.isMobile(window);
|
||
utils_Utils.isAppleMobileBrowser = utils_Utils.isBrowser && this.isAppleMobile(window);
|
||
if (utils_Utils.isNode) {
|
||
utils_Utils.global = __webpack_require__.g;
|
||
}
|
||
else if (utils_Utils.isBrowser) {
|
||
utils_Utils.global = window;
|
||
}
|
||
else {
|
||
// If it's not browser or node then it must be a service worker
|
||
utils_Utils.global = self;
|
||
}
|
||
}
|
||
static fromB64ToArray(str) {
|
||
if (str == null) {
|
||
return null;
|
||
}
|
||
if (utils_Utils.isNode) {
|
||
return new Uint8Array(Buffer.from(str, "base64"));
|
||
}
|
||
else {
|
||
const binaryString = utils_Utils.global.atob(str);
|
||
const bytes = new Uint8Array(binaryString.length);
|
||
for (let i = 0; i < binaryString.length; i++) {
|
||
bytes[i] = binaryString.charCodeAt(i);
|
||
}
|
||
return bytes;
|
||
}
|
||
}
|
||
static fromUrlB64ToArray(str) {
|
||
return utils_Utils.fromB64ToArray(utils_Utils.fromUrlB64ToB64(str));
|
||
}
|
||
static fromHexToArray(str) {
|
||
if (utils_Utils.isNode) {
|
||
return new Uint8Array(Buffer.from(str, "hex"));
|
||
}
|
||
else {
|
||
const bytes = new Uint8Array(str.length / 2);
|
||
for (let i = 0; i < str.length; i += 2) {
|
||
bytes[i / 2] = parseInt(str.substr(i, 2), 16);
|
||
}
|
||
return bytes;
|
||
}
|
||
}
|
||
static fromUtf8ToArray(str) {
|
||
if (utils_Utils.isNode) {
|
||
return new Uint8Array(Buffer.from(str, "utf8"));
|
||
}
|
||
else {
|
||
const strUtf8 = unescape(encodeURIComponent(str));
|
||
const arr = new Uint8Array(strUtf8.length);
|
||
for (let i = 0; i < strUtf8.length; i++) {
|
||
arr[i] = strUtf8.charCodeAt(i);
|
||
}
|
||
return arr;
|
||
}
|
||
}
|
||
static fromByteStringToArray(str) {
|
||
if (str == null) {
|
||
return null;
|
||
}
|
||
const arr = new Uint8Array(str.length);
|
||
for (let i = 0; i < str.length; i++) {
|
||
arr[i] = str.charCodeAt(i);
|
||
}
|
||
return arr;
|
||
}
|
||
static fromBufferToB64(buffer) {
|
||
// Handle null / undefined input
|
||
if (buffer == null) {
|
||
return null;
|
||
}
|
||
const bytes = utils_Utils.normalizeToUint8Array(buffer);
|
||
// Handle empty input
|
||
if (bytes.length === 0) {
|
||
return "";
|
||
}
|
||
if (utils_Utils.isNode) {
|
||
return Buffer.from(bytes).toString("base64");
|
||
}
|
||
else {
|
||
let binary = "";
|
||
for (let i = 0; i < bytes.byteLength; i++) {
|
||
binary += String.fromCharCode(bytes[i]);
|
||
}
|
||
return utils_Utils.global.btoa(binary);
|
||
}
|
||
}
|
||
/**
|
||
* Normalizes input into a Uint8Array so we always have a uniform,
|
||
* byte-level view of the data. This avoids dealing with differences
|
||
* between ArrayBuffer (raw memory with no indexing) and other typed
|
||
* views (which may have element sizes, offsets, and lengths).
|
||
* @param buffer ArrayBuffer or ArrayBufferView (e.g. Uint8Array, DataView, etc.)
|
||
*/
|
||
static normalizeToUint8Array(buffer) {
|
||
/**
|
||
* 1) Uint8Array: already bytes → use directly.
|
||
* 2) ArrayBuffer: wrap whole buffer.
|
||
* 3) Other ArrayBufferView (e.g., DataView, Int32Array):
|
||
* wrap the view’s window (byteOffset..byteOffset+byteLength).
|
||
*/
|
||
if (buffer instanceof Uint8Array) {
|
||
return buffer;
|
||
}
|
||
else if (buffer instanceof ArrayBuffer) {
|
||
return new Uint8Array(buffer);
|
||
}
|
||
else {
|
||
const view = buffer;
|
||
return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
||
}
|
||
}
|
||
static fromBufferToUrlB64(buffer) {
|
||
return utils_Utils.fromB64toUrlB64(utils_Utils.fromBufferToB64(buffer));
|
||
}
|
||
static fromB64toUrlB64(b64Str) {
|
||
return b64Str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
||
}
|
||
static fromBufferToUtf8(buffer) {
|
||
return node_modules_buffer/* Buffer */.hp.from(buffer).toString("utf8");
|
||
}
|
||
static fromBufferToByteString(buffer) {
|
||
return String.fromCharCode.apply(null, new Uint8Array(buffer));
|
||
}
|
||
// ref: https://stackoverflow.com/a/40031979/1090359
|
||
static fromBufferToHex(buffer) {
|
||
if (utils_Utils.isNode) {
|
||
return Buffer.from(buffer).toString("hex");
|
||
}
|
||
else {
|
||
const bytes = new Uint8Array(buffer);
|
||
return Array.prototype.map
|
||
.call(bytes, (x) => ("00" + x.toString(16)).slice(-2))
|
||
.join("");
|
||
}
|
||
}
|
||
/**
|
||
* Converts a hex string to an ArrayBuffer.
|
||
* Note: this doesn't need any Node specific code as parseInt() / ArrayBuffer / Uint8Array
|
||
* work the same in Node and the browser.
|
||
* @param {string} hexString - A string of hexadecimal characters.
|
||
* @returns {ArrayBuffer} The ArrayBuffer representation of the hex string.
|
||
*/
|
||
static hexStringToArrayBuffer(hexString) {
|
||
// Check if the hexString has an even length, as each hex digit represents half a byte (4 bits),
|
||
// and it takes two hex digits to represent a full byte (8 bits).
|
||
if (hexString.length % 2 !== 0) {
|
||
throw "HexString has to be an even length";
|
||
}
|
||
// Create an ArrayBuffer with a length that is half the length of the hex string,
|
||
// because each pair of hex digits will become a single byte.
|
||
const arrayBuffer = new ArrayBuffer(hexString.length / 2);
|
||
// Create a Uint8Array view on top of the ArrayBuffer (each position represents a byte)
|
||
// as ArrayBuffers cannot be edited directly.
|
||
const uint8Array = new Uint8Array(arrayBuffer);
|
||
// Loop through the bytes
|
||
for (let i = 0; i < uint8Array.length; i++) {
|
||
// Extract two hex characters (1 byte)
|
||
const hexByte = hexString.substr(i * 2, 2);
|
||
// Convert hexByte into a decimal value from base 16. (ex: ff --> 255)
|
||
const byteValue = parseInt(hexByte, 16);
|
||
// Place the byte value into the uint8Array
|
||
uint8Array[i] = byteValue;
|
||
}
|
||
return arrayBuffer;
|
||
}
|
||
static fromUrlB64ToB64(urlB64Str) {
|
||
let output = urlB64Str.replace(/-/g, "+").replace(/_/g, "/");
|
||
switch (output.length % 4) {
|
||
case 0:
|
||
break;
|
||
case 2:
|
||
output += "==";
|
||
break;
|
||
case 3:
|
||
output += "=";
|
||
break;
|
||
default:
|
||
throw new Error("Illegal base64url string!");
|
||
}
|
||
return output;
|
||
}
|
||
static fromUrlB64ToUtf8(urlB64Str) {
|
||
return utils_Utils.fromB64ToUtf8(utils_Utils.fromUrlB64ToB64(urlB64Str));
|
||
}
|
||
static fromUtf8ToB64(utfStr) {
|
||
if (utils_Utils.isNode) {
|
||
return Buffer.from(utfStr, "utf8").toString("base64");
|
||
}
|
||
else {
|
||
return node_modules_buffer/* Buffer */.hp.from(utfStr, "utf8").toString("base64");
|
||
}
|
||
}
|
||
static fromUtf8ToUrlB64(utfStr) {
|
||
return utils_Utils.fromBufferToUrlB64(utils_Utils.fromUtf8ToArray(utfStr));
|
||
}
|
||
static fromB64ToUtf8(b64Str) {
|
||
if (utils_Utils.isNode) {
|
||
return Buffer.from(b64Str, "base64").toString("utf8");
|
||
}
|
||
else {
|
||
return node_modules_buffer/* Buffer */.hp.from(b64Str, "base64").toString("utf8");
|
||
}
|
||
}
|
||
// ref: http://stackoverflow.com/a/2117523/1090359
|
||
/** @deprecated Use newGuid from @bitwarden/guid instead */
|
||
static newGuid() {
|
||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||
const r = (Math.random() * 16) | 0;
|
||
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
||
return v.toString(16);
|
||
});
|
||
}
|
||
/** @deprecated Use isGuid from @bitwarden/guid instead */
|
||
static isGuid(id) {
|
||
return RegExp(utils_Utils.guidRegex, "i").test(id);
|
||
}
|
||
static getHostname(uriString) {
|
||
if (utils_Utils.isNullOrWhitespace(uriString)) {
|
||
return null;
|
||
}
|
||
uriString = uriString.trim();
|
||
if (uriString.startsWith("data:")) {
|
||
return null;
|
||
}
|
||
if (uriString.startsWith("about:")) {
|
||
return null;
|
||
}
|
||
if (uriString.startsWith("file:")) {
|
||
return null;
|
||
}
|
||
// Does uriString contain invalid characters
|
||
// TODO Needs to possibly be extended, although '!' is a reserved character
|
||
if (uriString.indexOf("!") > 0) {
|
||
return null;
|
||
}
|
||
try {
|
||
const hostname = getHostname(uriString, { validHosts: this.validHosts });
|
||
if (hostname != null) {
|
||
return hostname;
|
||
}
|
||
}
|
||
catch (_a) {
|
||
return null;
|
||
}
|
||
return null;
|
||
}
|
||
static getHost(uriString) {
|
||
const url = utils_Utils.getUrl(uriString);
|
||
try {
|
||
return url != null && url.host !== "" ? url.host : null;
|
||
}
|
||
catch (_a) {
|
||
return null;
|
||
}
|
||
}
|
||
static getDomain(uriString) {
|
||
if (utils_Utils.isNullOrWhitespace(uriString)) {
|
||
return null;
|
||
}
|
||
uriString = uriString.trim();
|
||
if (uriString.startsWith("data:")) {
|
||
return null;
|
||
}
|
||
if (uriString.startsWith("about:")) {
|
||
return null;
|
||
}
|
||
try {
|
||
const parseResult = parse(uriString, {
|
||
validHosts: this.validHosts,
|
||
allowPrivateDomains: true,
|
||
});
|
||
if (parseResult != null && parseResult.hostname != null) {
|
||
if (parseResult.hostname === "localhost" || parseResult.isIp) {
|
||
return parseResult.hostname;
|
||
}
|
||
if (parseResult.domain != null) {
|
||
return parseResult.domain;
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
catch (_a) {
|
||
return null;
|
||
}
|
||
return null;
|
||
}
|
||
static getQueryParams(uriString) {
|
||
const url = utils_Utils.getUrl(uriString);
|
||
if (url == null || url.search == null || url.search === "") {
|
||
return null;
|
||
}
|
||
const map = new Map();
|
||
const pairs = (url.search[0] === "?" ? url.search.substr(1) : url.search).split("&");
|
||
pairs.forEach((pair) => {
|
||
const parts = pair.split("=");
|
||
if (parts.length < 1) {
|
||
return;
|
||
}
|
||
map.set(decodeURIComponent(parts[0]).toLowerCase(), parts[1] == null ? "" : decodeURIComponent(parts[1]));
|
||
});
|
||
return map;
|
||
}
|
||
static getSortFunction(i18nService, prop) {
|
||
return (a, b) => {
|
||
if (a[prop] == null && b[prop] != null) {
|
||
return -1;
|
||
}
|
||
if (a[prop] != null && b[prop] == null) {
|
||
return 1;
|
||
}
|
||
if (a[prop] == null && b[prop] == null) {
|
||
return 0;
|
||
}
|
||
// The `as unknown as string` here is unfortunate because typescript doesn't property understand that the return of T[prop] will be a string
|
||
return i18nService.collator
|
||
? i18nService.collator.compare(a[prop], b[prop])
|
||
: a[prop].localeCompare(b[prop]);
|
||
};
|
||
}
|
||
static isNullOrWhitespace(str) {
|
||
return str == null || typeof str !== "string" || str.trim() === "";
|
||
}
|
||
static isNullOrEmpty(str) {
|
||
return str == null || typeof str !== "string" || str == "";
|
||
}
|
||
static isPromise(obj) {
|
||
return (obj != undefined && typeof obj["then"] === "function" && typeof obj["catch"] === "function");
|
||
}
|
||
static nameOf(name) {
|
||
return name;
|
||
}
|
||
static assign(target, source) {
|
||
return Object.assign(target, source);
|
||
}
|
||
static iterateEnum(obj) {
|
||
return Object.keys(obj).filter((k) => Number.isNaN(+k)).map((k) => obj[k]);
|
||
}
|
||
static getUrl(uriString) {
|
||
if (this.isNullOrWhitespace(uriString)) {
|
||
return null;
|
||
}
|
||
uriString = uriString.trim();
|
||
return utils_Utils.getUrlObject(uriString);
|
||
}
|
||
static camelToPascalCase(s) {
|
||
return s.charAt(0).toUpperCase() + s.slice(1);
|
||
}
|
||
/**
|
||
* There are a few ways to calculate text color for contrast, this one seems to fit accessibility guidelines best.
|
||
* https://stackoverflow.com/a/3943023/6869691
|
||
*
|
||
* @param {string} bgColor
|
||
* @param {number} [threshold] see stackoverflow link above
|
||
* @param {boolean} [svgTextFill]
|
||
* Indicates if this method is performed on an SVG <text> 'fill' attribute (e.g. <text fill="black"></text>).
|
||
* This check is necessary because the '!important' tag cannot be used in a 'fill' attribute.
|
||
*/
|
||
static pickTextColorBasedOnBgColor(bgColor, threshold = 186, svgTextFill = false) {
|
||
const bgColorHexNums = bgColor.charAt(0) === "#" ? bgColor.substring(1, 7) : bgColor;
|
||
const r = parseInt(bgColorHexNums.substring(0, 2), 16); // hexToR
|
||
const g = parseInt(bgColorHexNums.substring(2, 4), 16); // hexToG
|
||
const b = parseInt(bgColorHexNums.substring(4, 6), 16); // hexToB
|
||
const blackColor = svgTextFill ? "black" : "black !important";
|
||
const whiteColor = svgTextFill ? "white" : "white !important";
|
||
return r * 0.299 + g * 0.587 + b * 0.114 > threshold ? blackColor : whiteColor;
|
||
}
|
||
static stringToColor(str) {
|
||
let hash = 0;
|
||
for (let i = 0; i < str.length; i++) {
|
||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||
}
|
||
let color = "#";
|
||
for (let i = 0; i < 3; i++) {
|
||
const value = (hash >> (i * 8)) & 0xff;
|
||
color += ("00" + value.toString(16)).substr(-2);
|
||
}
|
||
return color;
|
||
}
|
||
/**
|
||
* @throws Will throw an error if the ContainerService has not been attached to the window object
|
||
*/
|
||
static getContainerService() {
|
||
if (this.global.bitwardenContainerService == null) {
|
||
throw new Error("global bitwardenContainerService not initialized.");
|
||
}
|
||
return this.global.bitwardenContainerService;
|
||
}
|
||
static validateHexColor(color) {
|
||
return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
|
||
}
|
||
/**
|
||
* Converts map to a Record<string, V> with the same data. Inverse of recordToMap
|
||
* Useful in toJSON methods, since Maps are not serializable
|
||
* @param map
|
||
* @returns
|
||
*/
|
||
static mapToRecord(map) {
|
||
if (map == null) {
|
||
return null;
|
||
}
|
||
if (!(map instanceof Map)) {
|
||
return map;
|
||
}
|
||
return Object.fromEntries(map);
|
||
}
|
||
/**
|
||
* Converts record to a Map<string, V> with the same data. Inverse of mapToRecord
|
||
* Useful in fromJSON methods, since Maps are not serializable
|
||
*
|
||
* Warning: If the record has string keys that are numbers, they will be converted to numbers in the map
|
||
* @param record
|
||
* @returns
|
||
*/
|
||
static recordToMap(record) {
|
||
if (record == null) {
|
||
return null;
|
||
}
|
||
else if (record instanceof Map) {
|
||
return record;
|
||
}
|
||
const entries = Object.entries(record);
|
||
if (entries.length === 0) {
|
||
return new Map();
|
||
}
|
||
if (isNaN(Number(entries[0][0]))) {
|
||
return new Map(entries);
|
||
}
|
||
else {
|
||
return new Map(entries.map((e) => [Number(e[0]), e[1]]));
|
||
}
|
||
}
|
||
/** Applies Object.assign, but converts the type nicely using Type-Fest Merge<Destination, Source> */
|
||
static merge(destination, source) {
|
||
return Object.assign(destination, source);
|
||
}
|
||
/**
|
||
* encodeURIComponent escapes all characters except the following:
|
||
* alphabetic, decimal digits, - _ . ! ~ * ' ( )
|
||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#encoding_for_rfc3986
|
||
*/
|
||
static encodeRFC3986URIComponent(str) {
|
||
return encodeURIComponent(str).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
||
}
|
||
/**
|
||
* Normalizes a path for defense against attacks like traversals
|
||
* @param denormalizedPath
|
||
* @returns
|
||
*/
|
||
static normalizePath(denormalizedPath) {
|
||
return path_browserify.normalize(decodeURIComponent(denormalizedPath)).replace(/^(\.\.(\/|\\|$))+/, "");
|
||
}
|
||
/**
|
||
* Validates an url checking against invalid patterns
|
||
* @param url
|
||
* @returns true if invalid patterns found, false if safe
|
||
*/
|
||
static invalidUrlPatterns(url) {
|
||
const invalidUrlPatterns = ["..", "%2e", "\\", "%5c"];
|
||
const decodedUrl = decodeURIComponent(url.toLocaleLowerCase());
|
||
// Check URL for invalidUrl patterns across entire URL
|
||
if (invalidUrlPatterns.some((p) => decodedUrl.includes(p))) {
|
||
return true;
|
||
}
|
||
// Check for additional invalid patterns inside URL params
|
||
if (decodedUrl.includes("?")) {
|
||
const hasInvalidParams = this.validateQueryParameters(decodedUrl);
|
||
if (hasInvalidParams) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Validates query parameters for additional invalid patterns
|
||
* @param url - The URL containing query parameters
|
||
* @returns true if invalid patterns found, false if safe
|
||
*/
|
||
static validateQueryParameters(url) {
|
||
try {
|
||
let queryString;
|
||
if (url.includes("?")) {
|
||
queryString = url.split("?")[1];
|
||
}
|
||
else {
|
||
return false;
|
||
}
|
||
const paramInvalidPatterns = ["/", "%2f", "#", "%23"];
|
||
return paramInvalidPatterns.some((p) => queryString.includes(p));
|
||
}
|
||
catch (error) {
|
||
throw new Error(`Error validating query parameters: ${error}`);
|
||
}
|
||
}
|
||
static isMobile(win) {
|
||
let mobile = false;
|
||
((a) => {
|
||
if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) ||
|
||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) {
|
||
mobile = true;
|
||
}
|
||
})(win.navigator.userAgent || win.navigator.vendor || win.opera);
|
||
return mobile || win.navigator.userAgent.match(/iPad/i) != null;
|
||
}
|
||
static delay(ms) {
|
||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||
}
|
||
/**
|
||
* Generate an observable from a function that returns a promise.
|
||
* Similar to the rxjs function {@link from} with one big exception:
|
||
* {@link from} will not re-execute the function when observers resubscribe.
|
||
* {@link Util.asyncToObservable} will execute `generator` for every
|
||
* subscribe, making it ideal if the value ever needs to be refreshed.
|
||
* */
|
||
static asyncToObservable(generator) {
|
||
return of_of(undefined).pipe(switchMap_switchMap(() => generator()));
|
||
}
|
||
/**
|
||
* Return the number of days remaining before a target date arrives.
|
||
* Returns 0 if the day has already passed.
|
||
*/
|
||
static daysRemaining(targetDate) {
|
||
const diffTime = targetDate.getTime() - Date.now();
|
||
const msPerDay = 86400000;
|
||
return Math.max(0, Math.floor(diffTime / msPerDay));
|
||
}
|
||
static isAppleMobile(win) {
|
||
return (win.navigator.userAgent.match(/iPhone/i) != null ||
|
||
win.navigator.userAgent.match(/iPad/i) != null);
|
||
}
|
||
static getUrlObject(uriString) {
|
||
// All the methods below require a protocol to properly parse a URL string
|
||
// Assume http if no other protocol is present
|
||
const hasProtocol = uriString.indexOf("://") > -1;
|
||
if (!hasProtocol && uriString.indexOf(".") > -1) {
|
||
uriString = "http://" + uriString;
|
||
}
|
||
else if (!hasProtocol) {
|
||
return null;
|
||
}
|
||
try {
|
||
if (nodeURL != null) {
|
||
return new nodeURL.URL(uriString);
|
||
}
|
||
return new URL(uriString);
|
||
// FIXME: Remove when updating file. Eslint update
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
}
|
||
catch (e) {
|
||
// Ignore error
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
utils_Utils.inited = false;
|
||
utils_Utils.isNode = false;
|
||
utils_Utils.isBrowser = true;
|
||
utils_Utils.isMobileBrowser = false;
|
||
utils_Utils.isAppleMobileBrowser = false;
|
||
utils_Utils.global = null;
|
||
// Transpiled version of /\p{Emoji_Presentation}/gu using https://mothereff.in/regexpu. Used for compatability in older browsers.
|
||
utils_Utils.regexpEmojiPresentation = /(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])/g;
|
||
utils_Utils.validHosts = ["localhost"];
|
||
utils_Utils.originalMinimumPasswordLength = 8;
|
||
utils_Utils.minimumPasswordLength = 12;
|
||
utils_Utils.DomainMatchBlacklist = new Map([
|
||
["google.com", new Set(["script.google.com"])],
|
||
]);
|
||
/** @deprecated Use guidRegex from @bitwarden/guid instead */
|
||
utils_Utils.guidRegex = /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/;
|
||
utils_Utils.init();
|
||
|
||
;// ../../libs/serialization/src/deserialization-helpers.ts
|
||
/**
|
||
*
|
||
* @param elementDeserializer
|
||
* @returns
|
||
*/
|
||
function array(elementDeserializer) {
|
||
return (array) => {
|
||
if (array == null) {
|
||
return null;
|
||
}
|
||
return array.map((element) => elementDeserializer(element));
|
||
};
|
||
}
|
||
/**
|
||
*
|
||
* @param valueDeserializer
|
||
*/
|
||
function record(valueDeserializer) {
|
||
return (jsonValue) => {
|
||
if (jsonValue == null) {
|
||
return null;
|
||
}
|
||
const output = {};
|
||
Object.entries(jsonValue).forEach(([key, value]) => {
|
||
output[key] = valueDeserializer(value);
|
||
});
|
||
return output;
|
||
};
|
||
}
|
||
|
||
;// ../../libs/state/src/core/key-definition.ts
|
||
|
||
/**
|
||
* KeyDefinitions describe the precise location to store data for a given piece of state.
|
||
* The StateDefinition is used to describe the domain of the state, and the KeyDefinition
|
||
* sub-divides that domain into specific keys.
|
||
*/
|
||
class KeyDefinition {
|
||
/**
|
||
* Creates a new instance of a KeyDefinition
|
||
* @param stateDefinition The state definition for which this key belongs to.
|
||
* @param key The name of the key, this should be unique per domain.
|
||
* @param options A set of options to customize the behavior of {@link KeyDefinition}. All options are required.
|
||
* @param options.deserializer A function to use to safely convert your type from json to your expected type.
|
||
* Your data may be serialized/deserialized at any time and this needs callback needs to be able to faithfully re-initialize
|
||
* from the JSON object representation of your type.
|
||
*/
|
||
constructor(stateDefinition, key, options) {
|
||
var _a;
|
||
this.stateDefinition = stateDefinition;
|
||
this.key = key;
|
||
this.options = options;
|
||
if (options.deserializer == null) {
|
||
throw new Error(`'deserializer' is a required property on key ${this.errorKeyName}`);
|
||
}
|
||
if (options.cleanupDelayMs < 0) {
|
||
throw new Error(`'cleanupDelayMs' must be greater than or equal to 0. Value of ${options.cleanupDelayMs} passed to key ${this.errorKeyName} `);
|
||
}
|
||
// Normalize optional debug options
|
||
const { enableUpdateLogging = false, enableRetrievalLogging = false } = (_a = options.debug) !== null && _a !== void 0 ? _a : {};
|
||
this.debug = {
|
||
enableUpdateLogging,
|
||
enableRetrievalLogging,
|
||
};
|
||
}
|
||
/**
|
||
* Gets the deserializer configured for this {@link KeyDefinition}
|
||
*/
|
||
get deserializer() {
|
||
return this.options.deserializer;
|
||
}
|
||
/**
|
||
* Gets the number of milliseconds to wait before cleaning up the state after the last subscriber has unsubscribed.
|
||
*/
|
||
get cleanupDelayMs() {
|
||
var _a;
|
||
return this.options.cleanupDelayMs < 0 ? 0 : ((_a = this.options.cleanupDelayMs) !== null && _a !== void 0 ? _a : 1000);
|
||
}
|
||
/**
|
||
* Creates a {@link KeyDefinition} for state that is an array.
|
||
* @param stateDefinition The state definition to be added to the KeyDefinition
|
||
* @param key The key to be added to the KeyDefinition
|
||
* @param options The options to customize the final {@link KeyDefinition}.
|
||
* @returns A {@link KeyDefinition} initialized for arrays, the options run
|
||
* the deserializer on the provided options for each element of an array.
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const MY_KEY = KeyDefinition.array<MyArrayElement>(MY_STATE, "key", {
|
||
* deserializer: (myJsonElement) => convertToElement(myJsonElement),
|
||
* });
|
||
* ```
|
||
*/
|
||
static array(stateDefinition, key,
|
||
// We have them provide options for the element of the array, depending on future options we add, this could get a little weird.
|
||
options) {
|
||
return new KeyDefinition(stateDefinition, key, Object.assign(Object.assign({}, options), { deserializer: array((e) => options.deserializer(e)) }));
|
||
}
|
||
/**
|
||
* Creates a {@link KeyDefinition} for state that is a record.
|
||
* @param stateDefinition The state definition to be added to the KeyDefinition
|
||
* @param key The key to be added to the KeyDefinition
|
||
* @param options The options to customize the final {@link KeyDefinition}.
|
||
* @returns A {@link KeyDefinition} that contains a serializer that will run the provided deserializer for each
|
||
* value in a record and returns every key as a string.
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const MY_KEY = KeyDefinition.record<MyRecordValue>(MY_STATE, "key", {
|
||
* deserializer: (myJsonValue) => convertToValue(myJsonValue),
|
||
* });
|
||
* ```
|
||
*/
|
||
static record(stateDefinition, key,
|
||
// We have them provide options for the value of the record, depending on future options we add, this could get a little weird.
|
||
options) {
|
||
return new KeyDefinition(stateDefinition, key, Object.assign(Object.assign({}, options), { deserializer: record((v) => options.deserializer(v)) }));
|
||
}
|
||
get fullName() {
|
||
return `${this.stateDefinition.name}_${this.key}`;
|
||
}
|
||
get errorKeyName() {
|
||
return `${this.stateDefinition.name} > ${this.key}`;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/guid/src/index.ts
|
||
const guidRegex = /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
|
||
function newGuid() {
|
||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||
const r = (Math.random() * 16) | 0;
|
||
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
||
return v.toString(16);
|
||
});
|
||
}
|
||
function isGuid(id) {
|
||
return guidRegex.test(id);
|
||
}
|
||
|
||
;// ../../libs/state/src/core/user-key-definition.ts
|
||
var _a;
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
const USER_KEY_DEFINITION_MARKER = Symbol("UserKeyDefinition");
|
||
class user_key_definition_UserKeyDefinition {
|
||
constructor(stateDefinition, key, options) {
|
||
var _b;
|
||
this.stateDefinition = stateDefinition;
|
||
this.key = key;
|
||
this.options = options;
|
||
this[_a] = true;
|
||
if (options.deserializer == null) {
|
||
throw new Error(`'deserializer' is a required property on key ${this.errorKeyName}`);
|
||
}
|
||
if (options.cleanupDelayMs < 0) {
|
||
throw new Error(`'cleanupDelayMs' must be greater than or equal to 0. Value of ${options.cleanupDelayMs} passed to key ${this.errorKeyName} `);
|
||
}
|
||
// Filter out repeat values
|
||
this.clearOn = Array.from(new Set(options.clearOn));
|
||
// Normalize optional debug options
|
||
const { enableUpdateLogging = false, enableRetrievalLogging = false } = (_b = options.debug) !== null && _b !== void 0 ? _b : {};
|
||
this.debug = {
|
||
enableUpdateLogging,
|
||
enableRetrievalLogging,
|
||
};
|
||
}
|
||
/**
|
||
* Gets the deserializer configured for this {@link KeyDefinition}
|
||
*/
|
||
get deserializer() {
|
||
return this.options.deserializer;
|
||
}
|
||
/**
|
||
* Gets the number of milliseconds to wait before cleaning up the state after the last subscriber has unsubscribed.
|
||
*/
|
||
get cleanupDelayMs() {
|
||
var _b;
|
||
return this.options.cleanupDelayMs < 0 ? 0 : ((_b = this.options.cleanupDelayMs) !== null && _b !== void 0 ? _b : 1000);
|
||
}
|
||
/**
|
||
* Creates a {@link UserKeyDefinition} for state that is an array.
|
||
* @param stateDefinition The state definition to be added to the UserKeyDefinition
|
||
* @param key The key to be added to the KeyDefinition
|
||
* @param options The options to customize the final {@link UserKeyDefinition}.
|
||
* @returns A {@link UserKeyDefinition} initialized for arrays, the options run
|
||
* the deserializer on the provided options for each element of an array
|
||
* **unless that array is null, in which case it will return an empty list.**
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const MY_KEY = UserKeyDefinition.array<MyArrayElement>(MY_STATE, "key", {
|
||
* deserializer: (myJsonElement) => convertToElement(myJsonElement),
|
||
* });
|
||
* ```
|
||
*/
|
||
static array(stateDefinition, key,
|
||
// We have them provide options for the element of the array, depending on future options we add, this could get a little weird.
|
||
options) {
|
||
return new user_key_definition_UserKeyDefinition(stateDefinition, key, Object.assign(Object.assign({}, options), { deserializer: array((e) => options.deserializer(e)) }));
|
||
}
|
||
/**
|
||
* Creates a {@link UserKeyDefinition} for state that is a record.
|
||
* @param stateDefinition The state definition to be added to the UserKeyDefinition
|
||
* @param key The key to be added to the KeyDefinition
|
||
* @param options The options to customize the final {@link UserKeyDefinition}.
|
||
* @returns A {@link UserKeyDefinition} that contains a serializer that will run the provided deserializer for each
|
||
* value in a record and returns every key as a string **unless that record is null, in which case it will return an record.**
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const MY_KEY = UserKeyDefinition.record<MyRecordValue>(MY_STATE, "key", {
|
||
* deserializer: (myJsonValue) => convertToValue(myJsonValue),
|
||
* });
|
||
* ```
|
||
*/
|
||
static record(stateDefinition, key,
|
||
// We have them provide options for the value of the record, depending on future options we add, this could get a little weird.
|
||
options) {
|
||
return new user_key_definition_UserKeyDefinition(stateDefinition, key, Object.assign(Object.assign({}, options), { deserializer: record((v) => options.deserializer(v)) }));
|
||
}
|
||
get fullName() {
|
||
return `${this.stateDefinition.name}_${this.key}`;
|
||
}
|
||
buildKey(userId) {
|
||
if (!isGuid(userId)) {
|
||
throw new Error(`You cannot build a user key without a valid UserId, building for key ${this.fullName}`);
|
||
}
|
||
return `user_${userId}_${this.stateDefinition.name}_${this.key}`;
|
||
}
|
||
get errorKeyName() {
|
||
return `${this.stateDefinition.name} > ${this.key}`;
|
||
}
|
||
}
|
||
_a = USER_KEY_DEFINITION_MARKER;
|
||
|
||
;// ../../libs/state/src/core/user-state.ts
|
||
const activeMarker = Symbol("active");
|
||
|
||
;// ../../libs/state/src/core/state-definition.ts
|
||
/**
|
||
* Defines the base location and instruction of where this state is expected to be located.
|
||
*/
|
||
class state_definition_StateDefinition {
|
||
/**
|
||
* Creates a new instance of {@link StateDefinition}, the creation of which is owned by the platform team.
|
||
* @param name The name of the state, this needs to be unique from all other {@link StateDefinition}'s.
|
||
* @param defaultStorageLocation The location of where this state should be stored.
|
||
*/
|
||
constructor(name, defaultStorageLocation, storageLocationOverrides) {
|
||
this.name = name;
|
||
this.defaultStorageLocation = defaultStorageLocation;
|
||
this.storageLocationOverrides = storageLocationOverrides !== null && storageLocationOverrides !== void 0 ? storageLocationOverrides : {};
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/core/state-definitions.ts
|
||
|
||
/**
|
||
* `StateDefinition`s comes with some rules, to facilitate a quick review from
|
||
* platform of this file, ensure you follow these rules, the ones marked with (tested)
|
||
* have unit tests that you can run locally.
|
||
*
|
||
* 1. (tested) Names should not be null or undefined
|
||
* 2. (tested) Name and storage location should be unique
|
||
* 3. (tested) Name and storage location can't differ from another export by only casing
|
||
* 4. (tested) Name should be longer than 3 characters. It should be descriptive, but brief.
|
||
* 5. (tested) Name should not contain spaces or underscores
|
||
* 6. Name should be human readable
|
||
* 7. Name should be in camelCase format (unit tests ensure the first character is lowercase)
|
||
* 8. Teams should only use state definitions they have created
|
||
* 9. StateDefinitions should only be used for keys relating to the state name they chose
|
||
*
|
||
*/
|
||
// Admin Console
|
||
const ORGANIZATIONS_DISK = new state_definition_StateDefinition("organizations", "disk");
|
||
const POLICIES_DISK = new state_definition_StateDefinition("policies", "disk");
|
||
const PROVIDERS_DISK = new state_definition_StateDefinition("providers", "disk");
|
||
const ORGANIZATION_MANAGEMENT_PREFERENCES_DISK = new state_definition_StateDefinition("organizationManagementPreferences", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const DELETE_MANAGED_USER_WARNING = new state_definition_StateDefinition("showDeleteManagedUserWarning", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const AUTO_CONFIRM = new state_definition_StateDefinition("autoConfirm", "disk", { web: "disk-local" });
|
||
// Billing
|
||
const BILLING_DISK = new state_definition_StateDefinition("billing", "disk");
|
||
const BILLING_MEMORY = new state_definition_StateDefinition("billing", "memory");
|
||
// Auth
|
||
const ACCOUNT_DISK = new state_definition_StateDefinition("account", "disk");
|
||
const ACCOUNT_MEMORY = new state_definition_StateDefinition("account", "memory");
|
||
const AUTH_REQUEST_DISK_LOCAL = new state_definition_StateDefinition("authRequestLocal", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const AVATAR_DISK = new state_definition_StateDefinition("avatar", "disk", { web: "disk-local" });
|
||
const DEVICE_TRUST_DISK_LOCAL = new state_definition_StateDefinition("deviceTrust", "disk", {
|
||
web: "disk-local",
|
||
browser: "disk-backup-local-storage",
|
||
});
|
||
const LOGIN_EMAIL_DISK = new state_definition_StateDefinition("loginEmail", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const LOGIN_EMAIL_MEMORY = new state_definition_StateDefinition("loginEmail", "memory");
|
||
const LOGIN_STRATEGY_MEMORY = new state_definition_StateDefinition("loginStrategy", "memory");
|
||
const MASTER_PASSWORD_DISK = new state_definition_StateDefinition("masterPassword", "disk");
|
||
const MASTER_PASSWORD_MEMORY = new state_definition_StateDefinition("masterPassword", "memory");
|
||
const MASTER_PASSWORD_UNLOCK_DISK = new state_definition_StateDefinition("masterPasswordUnlock", "disk");
|
||
const ROUTER_DISK = new state_definition_StateDefinition("router", "disk");
|
||
const SSO_DISK = new state_definition_StateDefinition("ssoLogin", "disk");
|
||
const SSO_DISK_LOCAL = new state_definition_StateDefinition("ssoLoginLocal", "disk", { web: "disk-local" });
|
||
const TOKEN_DISK = new state_definition_StateDefinition("token", "disk");
|
||
const TOKEN_DISK_LOCAL = new state_definition_StateDefinition("tokenDiskLocal", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const TOKEN_MEMORY = new state_definition_StateDefinition("token", "memory");
|
||
const SEND_ACCESS_DISK = new state_definition_StateDefinition("sendAccess", "disk");
|
||
const TWO_FACTOR_MEMORY = new state_definition_StateDefinition("twoFactor", "memory");
|
||
const USER_DECRYPTION_OPTIONS_DISK = new state_definition_StateDefinition("userDecryptionOptions", "disk");
|
||
const ORGANIZATION_INVITE_DISK = new state_definition_StateDefinition("organizationInvite", "disk");
|
||
const VAULT_TIMEOUT_SETTINGS_DISK_LOCAL = new state_definition_StateDefinition("vaultTimeoutSettings", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
// Autofill
|
||
const BADGE_SETTINGS_DISK = new state_definition_StateDefinition("badgeSettings", "disk");
|
||
const USER_NOTIFICATION_SETTINGS_DISK = new state_definition_StateDefinition("userNotificationSettings", "disk");
|
||
const DOMAIN_SETTINGS_DISK = new state_definition_StateDefinition("domainSettings", "disk");
|
||
const AUTOFILL_SETTINGS_DISK = new state_definition_StateDefinition("autofillSettings", "disk");
|
||
const AUTOFILL_SETTINGS_DISK_LOCAL = new state_definition_StateDefinition("autofillSettingsLocal", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const AUTOTYPE_SETTINGS_DISK = new state_definition_StateDefinition("autotypeSettings", "disk");
|
||
// Components
|
||
const NEW_WEB_LAYOUT_BANNER_DISK = new state_definition_StateDefinition("newWebLayoutBanner", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
// DIRT
|
||
const PHISHING_DETECTION_DISK = new state_definition_StateDefinition("phishingDetection", "disk");
|
||
// Platform
|
||
const APPLICATION_ID_DISK = new state_definition_StateDefinition("applicationId", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const CLEAR_EVENT_DISK = new state_definition_StateDefinition("clearEvent", "disk");
|
||
const CONFIG_DISK = new state_definition_StateDefinition("config", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const DESKTOP_SETTINGS_DISK = new state_definition_StateDefinition("desktopSettings", "disk");
|
||
const ENVIRONMENT_DISK = new state_definition_StateDefinition("environment", "disk");
|
||
const ENVIRONMENT_MEMORY = new state_definition_StateDefinition("environment", "memory");
|
||
const IPC_MEMORY = new state_definition_StateDefinition("interProcessCommunication", "memory");
|
||
const POPUP_VIEW_MEMORY = new state_definition_StateDefinition("popupView", "memory", {
|
||
browser: "memory-large-object",
|
||
});
|
||
const SYNC_DISK = new state_definition_StateDefinition("sync", "disk", { web: "memory" });
|
||
const THEMING_DISK = new state_definition_StateDefinition("theming", "disk", { web: "disk-local" });
|
||
const TRANSLATION_DISK = new state_definition_StateDefinition("translation", "disk", { web: "disk-local" });
|
||
const ANIMATION_DISK = new state_definition_StateDefinition("animation", "disk");
|
||
const TASK_SCHEDULER_DISK = new state_definition_StateDefinition("taskScheduler", "disk");
|
||
const EXTENSION_INITIAL_INSTALL_DISK = new state_definition_StateDefinition("extensionInitialInstall", "disk");
|
||
const WEB_PUSH_SUBSCRIPTION = new state_definition_StateDefinition("webPushSubscription", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
// Design System
|
||
const POPUP_STYLE_DISK = new state_definition_StateDefinition("popupStyle", "disk");
|
||
// Secrets Manager
|
||
const SM_ONBOARDING_DISK = new state_definition_StateDefinition("smOnboarding", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
// Tools
|
||
const EXTENSION_DISK = new state_definition_StateDefinition("extension", "disk");
|
||
const GENERATOR_DISK = new state_definition_StateDefinition("generator", "disk");
|
||
const GENERATOR_MEMORY = new state_definition_StateDefinition("generator", "memory");
|
||
const BROWSER_SEND_MEMORY = new state_definition_StateDefinition("sendBrowser", "memory");
|
||
const EVENT_COLLECTION_DISK = new state_definition_StateDefinition("eventCollection", "disk");
|
||
const SEND_DISK = new state_definition_StateDefinition("encryptedSend", "disk", {
|
||
web: "memory",
|
||
});
|
||
const SEND_MEMORY = new state_definition_StateDefinition("decryptedSend", "memory", {
|
||
browser: "memory-large-object",
|
||
});
|
||
const SEND_ACCESS_AUTH_MEMORY = new state_definition_StateDefinition("sendAccessAuth", "memory");
|
||
// Vault
|
||
const COLLECTION_DISK = new state_definition_StateDefinition("collection", "disk", {
|
||
web: "memory",
|
||
});
|
||
const COLLECTION_MEMORY = new state_definition_StateDefinition("decryptedCollections", "memory", {
|
||
browser: "memory-large-object",
|
||
});
|
||
const FOLDER_DISK = new state_definition_StateDefinition("folder", "disk", { web: "memory" });
|
||
const FOLDER_MEMORY = new state_definition_StateDefinition("decryptedFolders", "memory", {
|
||
browser: "memory-large-object",
|
||
});
|
||
const VAULT_FILTER_DISK = new state_definition_StateDefinition("vaultFilter", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const VAULT_ONBOARDING = new state_definition_StateDefinition("vaultOnboarding", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const VAULT_SETTINGS_DISK = new state_definition_StateDefinition("vaultSettings", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const VAULT_BROWSER_MEMORY = new state_definition_StateDefinition("vaultBrowser", "memory", {
|
||
browser: "memory-large-object",
|
||
});
|
||
const VAULT_SEARCH_MEMORY = new state_definition_StateDefinition("vaultSearch", "memory", {
|
||
browser: "memory-large-object",
|
||
});
|
||
const CIPHERS_DISK = new state_definition_StateDefinition("ciphers", "disk", { web: "memory" });
|
||
const CIPHERS_DISK_LOCAL = new state_definition_StateDefinition("ciphersLocal", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const CIPHERS_MEMORY = new state_definition_StateDefinition("ciphersMemory", "memory", {
|
||
browser: "memory-large-object",
|
||
});
|
||
const PREMIUM_BANNER_DISK_LOCAL = new state_definition_StateDefinition("premiumBannerReprompt", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const BANNERS_DISMISSED_DISK = new state_definition_StateDefinition("bannersDismissed", "disk");
|
||
const VAULT_APPEARANCE = new state_definition_StateDefinition("vaultAppearance", "disk");
|
||
const SECURITY_TASKS_DISK = new state_definition_StateDefinition("securityTasks", "disk");
|
||
const AT_RISK_PASSWORDS_PAGE_DISK = new state_definition_StateDefinition("atRiskPasswordsPage", "disk");
|
||
const NOTIFICATION_DISK = new state_definition_StateDefinition("notifications", "disk");
|
||
const NUDGES_DISK = new state_definition_StateDefinition("nudges", "disk", { web: "disk-local" });
|
||
const SETUP_EXTENSION_DISMISSED_DISK = new state_definition_StateDefinition("setupExtensionDismissed", "disk", {
|
||
web: "disk-local",
|
||
});
|
||
const VAULT_BROWSER_INTRO_CAROUSEL = new state_definition_StateDefinition("vaultBrowserIntroCarousel", "disk");
|
||
const VAULT_AT_RISK_PASSWORDS_MEMORY = new state_definition_StateDefinition("vaultAtRiskPasswords", "memory");
|
||
// KM
|
||
const BIOMETRIC_SETTINGS_DISK = new state_definition_StateDefinition("biometricSettings", "disk");
|
||
const ENCRYPTED_MIGRATION_DISK = new state_definition_StateDefinition("encryptedMigration", "disk");
|
||
const PIN_DISK = new state_definition_StateDefinition("pinUnlock", "disk");
|
||
const PIN_MEMORY = new state_definition_StateDefinition("pinUnlock", "memory");
|
||
const CRYPTO_DISK = new state_definition_StateDefinition("crypto", "disk");
|
||
const CRYPTO_MEMORY = new state_definition_StateDefinition("crypto", "memory");
|
||
const KDF_CONFIG_DISK = new state_definition_StateDefinition("kdfConfig", "disk");
|
||
const KEY_CONNECTOR_DISK = new state_definition_StateDefinition("keyConnector", "disk");
|
||
|
||
;// ../../libs/state/src/core/index.ts
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;// ../../libs/state/src/state-migrations/migration-builder.ts
|
||
var migration_builder_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
class migration_builder_MigrationBuilder {
|
||
/** Create a new MigrationBuilder with an empty buffer of migrations to perform.
|
||
*
|
||
* Add migrations to the buffer with {@link with} and {@link rollback}.
|
||
* @returns A new MigrationBuilder.
|
||
*/
|
||
static create() {
|
||
return new migration_builder_MigrationBuilder([]);
|
||
}
|
||
constructor(migrations) {
|
||
this.migrations = migrations;
|
||
}
|
||
/** Add a migrator to the MigrationBuilder. Types are updated such that the chained MigrationBuilder must currently be
|
||
* at state version equal to the from version of the migrator. Return as MigrationBuilder<TTo> where TTo is the to
|
||
* version of the migrator, so that the next migrator can be chained.
|
||
*
|
||
* @param migrate A migrator class or a tuple of a migrator class, the from version, and the to version. A tuple is
|
||
* required to instantiate version numbers unless a default constructor is defined.
|
||
* @returns A new MigrationBuilder with the to version of the migrator as the current version.
|
||
*/
|
||
with(...migrate) {
|
||
return this.addMigrator(migrate, "up");
|
||
}
|
||
/** Add a migrator to rollback on the MigrationBuilder's list of migrations. As with {@link with}, types of
|
||
* MigrationBuilder and Migrator must align. However, this time the migration is reversed so TCurrent of the
|
||
* MigrationBuilder must be equal to the to version of the migrator. Return as MigrationBuilder<TFrom> where TFrom
|
||
* is the from version of the migrator, so that the next migrator can be chained.
|
||
*
|
||
* @param migrate A migrator class or a tuple of a migrator class, the from version, and the to version. A tuple is
|
||
* required to instantiate version numbers unless a default constructor is defined.
|
||
* @returns A new MigrationBuilder with the from version of the migrator as the current version.
|
||
*/
|
||
rollback(...migrate) {
|
||
if (migrate.length === 3) {
|
||
migrate = [migrate[0], migrate[2], migrate[1]];
|
||
}
|
||
return this.addMigrator(migrate, "down");
|
||
}
|
||
/** Execute the migrations as defined in the MigrationBuilder's migrator buffer */
|
||
migrate(helper) {
|
||
return this.migrations.reduce((promise, migrator) => promise.then(() => migration_builder_awaiter(this, void 0, void 0, function* () {
|
||
yield this.runMigrator(migrator.migrator, helper, migrator.direction);
|
||
})), Promise.resolve());
|
||
}
|
||
addMigrator(migrate, direction = "up") {
|
||
const newMigration = migrate.length === 1
|
||
? { migrator: new migrate[0](), direction }
|
||
: { migrator: new migrate[0](migrate[1], migrate[2]), direction };
|
||
return new migration_builder_MigrationBuilder([...this.migrations, newMigration]);
|
||
}
|
||
runMigrator(migrator, helper, direction) {
|
||
return migration_builder_awaiter(this, void 0, void 0, function* () {
|
||
const shouldMigrate = yield migrator.shouldMigrate(helper, direction);
|
||
helper.info(`Migrator ${migrator.constructor.name} (to version ${migrator.toVersion}) should migrate: ${shouldMigrate} - ${direction}`);
|
||
if (shouldMigrate) {
|
||
const method = direction === "up" ? migrator.migrate : migrator.rollback;
|
||
yield method.bind(migrator)(helper);
|
||
helper.info(`Migrator ${migrator.constructor.name} (to version ${migrator.toVersion}) migrated - ${direction}`);
|
||
yield migrator.updateVersion(helper, direction);
|
||
helper.info(`Migrator ${migrator.constructor.name} (to version ${migrator.toVersion}) updated version - ${direction}`);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrator.ts
|
||
var migrator_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
const migrator_IRREVERSIBLE = new Error("Irreversible migration");
|
||
class migrator_Migrator {
|
||
constructor(fromVersion, toVersion) {
|
||
this.fromVersion = fromVersion;
|
||
this.toVersion = toVersion;
|
||
if (fromVersion == null || toVersion == null) {
|
||
throw new Error("Invalid migration");
|
||
}
|
||
if (fromVersion > toVersion) {
|
||
throw new Error("Invalid migration");
|
||
}
|
||
}
|
||
shouldMigrate(helper, direction) {
|
||
const startVersion = direction === "up" ? this.fromVersion : this.toVersion;
|
||
return Promise.resolve(helper.currentVersion === startVersion);
|
||
}
|
||
updateVersion(helper, direction) {
|
||
return migrator_awaiter(this, void 0, void 0, function* () {
|
||
const endVersion = direction === "up" ? this.toVersion : this.fromVersion;
|
||
helper.currentVersion = endVersion;
|
||
yield helper.set("stateVersion", endVersion);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/10-move-ever-had-user-key-to-state-providers.ts
|
||
var _10_move_ever_had_user_key_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_EVER_HAD_USER_KEY = {
|
||
key: "everHadUserKey",
|
||
stateDefinition: {
|
||
name: "crypto",
|
||
},
|
||
};
|
||
class _10_move_ever_had_user_key_to_state_providers_EverHadUserKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _10_move_ever_had_user_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _10_move_ever_had_user_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.everHadUserKey;
|
||
yield helper.setToUser(userId, USER_EVER_HAD_USER_KEY, value !== null && value !== void 0 ? value : false);
|
||
if (value != null) {
|
||
delete account.profile.everHadUserKey;
|
||
}
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _10_move_ever_had_user_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _10_move_ever_had_user_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, USER_EVER_HAD_USER_KEY);
|
||
if (account) {
|
||
account.profile = Object.assign((_a = account.profile) !== null && _a !== void 0 ? _a : {}, {
|
||
everHadUserKey: value,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_EVER_HAD_USER_KEY, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/11-move-org-keys-to-state-providers.ts
|
||
var _11_move_org_keys_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_ENCRYPTED_ORGANIZATION_KEYS = {
|
||
key: "organizationKeys",
|
||
stateDefinition: {
|
||
name: "crypto",
|
||
},
|
||
};
|
||
class _11_move_org_keys_to_state_providers_OrganizationKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _11_move_org_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _11_move_org_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const value = (_b = (_a = account === null || account === void 0 ? void 0 : account.keys) === null || _a === void 0 ? void 0 : _a.organizationKeys) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_ORGANIZATION_KEYS, value);
|
||
delete account.keys.organizationKeys;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _11_move_org_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _11_move_org_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, USER_ENCRYPTED_ORGANIZATION_KEYS);
|
||
if (account && value) {
|
||
account.keys = Object.assign((_a = account.keys) !== null && _a !== void 0 ? _a : {}, {
|
||
organizationKeys: {
|
||
encrypted: value,
|
||
},
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_ORGANIZATION_KEYS, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/12-move-environment-state-to-providers.ts
|
||
var _12_move_environment_state_to_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const ENVIRONMENT_STATE = { name: "environment" };
|
||
const REGION_KEY = { key: "region", stateDefinition: ENVIRONMENT_STATE };
|
||
const URLS_KEY = { key: "urls", stateDefinition: ENVIRONMENT_STATE };
|
||
class _12_move_environment_state_to_providers_MoveEnvironmentStateToProviders extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _12_move_environment_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyGlobal = yield helper.get("global");
|
||
// Move global data
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.region) != null) {
|
||
yield helper.setToGlobal(REGION_KEY, legacyGlobal.region);
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.environmentUrls) != null) {
|
||
yield helper.setToGlobal(URLS_KEY, legacyGlobal.environmentUrls);
|
||
}
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _12_move_environment_state_to_providers_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b, _c, _d, _e;
|
||
// Move account data
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.region) != null) {
|
||
yield helper.setToUser(userId, REGION_KEY, account.settings.region);
|
||
}
|
||
if (((_c = account === null || account === void 0 ? void 0 : account.settings) === null || _c === void 0 ? void 0 : _c.environmentUrls) != null) {
|
||
yield helper.setToUser(userId, URLS_KEY, account.settings.environmentUrls);
|
||
}
|
||
// Delete old account data
|
||
(_d = account === null || account === void 0 ? void 0 : account.settings) === null || _d === void 0 ? true : delete _d.region;
|
||
(_e = account === null || account === void 0 ? void 0 : account.settings) === null || _e === void 0 ? true : delete _e.environmentUrls;
|
||
yield helper.set(userId, account);
|
||
})));
|
||
// Delete legacy global data
|
||
legacyGlobal === null || legacyGlobal === void 0 ? true : delete legacyGlobal.region;
|
||
legacyGlobal === null || legacyGlobal === void 0 ? true : delete legacyGlobal.environmentUrls;
|
||
yield helper.set("global", legacyGlobal);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _12_move_environment_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
let legacyGlobal = yield helper.get("global");
|
||
let updatedLegacyGlobal = false;
|
||
const globalRegion = yield helper.getFromGlobal(REGION_KEY);
|
||
if (globalRegion) {
|
||
if (!legacyGlobal) {
|
||
legacyGlobal = {};
|
||
}
|
||
updatedLegacyGlobal = true;
|
||
legacyGlobal.region = globalRegion;
|
||
yield helper.setToGlobal(REGION_KEY, null);
|
||
}
|
||
const globalUrls = yield helper.getFromGlobal(URLS_KEY);
|
||
if (globalUrls) {
|
||
if (!legacyGlobal) {
|
||
legacyGlobal = {};
|
||
}
|
||
updatedLegacyGlobal = true;
|
||
legacyGlobal.environmentUrls = globalUrls;
|
||
yield helper.setToGlobal(URLS_KEY, null);
|
||
}
|
||
if (updatedLegacyGlobal) {
|
||
yield helper.set("global", legacyGlobal);
|
||
}
|
||
function rollbackUser(userId, account) {
|
||
return _12_move_environment_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
let updatedAccount = false;
|
||
const userRegion = yield helper.getFromUser(userId, REGION_KEY);
|
||
if (userRegion) {
|
||
if (!account) {
|
||
account = {};
|
||
}
|
||
if (!account.settings) {
|
||
account.settings = {};
|
||
}
|
||
updatedAccount = true;
|
||
account.settings.region = userRegion;
|
||
yield helper.setToUser(userId, REGION_KEY, null);
|
||
}
|
||
const userUrls = yield helper.getFromUser(userId, URLS_KEY);
|
||
if (userUrls) {
|
||
if (!account) {
|
||
account = {};
|
||
}
|
||
if (!account.settings) {
|
||
account.settings = {};
|
||
}
|
||
updatedAccount = true;
|
||
account.settings.environmentUrls = userUrls;
|
||
yield helper.setToUser(userId, URLS_KEY, null);
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/13-move-provider-keys-to-state-providers.ts
|
||
var _13_move_provider_keys_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_ENCRYPTED_PROVIDER_KEYS = {
|
||
key: "providerKeys",
|
||
stateDefinition: {
|
||
name: "crypto",
|
||
},
|
||
};
|
||
class _13_move_provider_keys_to_state_providers_ProviderKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _13_move_provider_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _13_move_provider_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const value = (_b = (_a = account === null || account === void 0 ? void 0 : account.keys) === null || _a === void 0 ? void 0 : _a.providerKeys) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_PROVIDER_KEYS, value);
|
||
delete account.keys.providerKeys;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _13_move_provider_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _13_move_provider_keys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, USER_ENCRYPTED_PROVIDER_KEYS);
|
||
if (account && value) {
|
||
account.keys = Object.assign((_a = account.keys) !== null && _a !== void 0 ? _a : {}, {
|
||
providerKeys: {
|
||
encrypted: value,
|
||
},
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_PROVIDER_KEYS, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/14-move-biometric-client-key-half-state-to-providers.ts
|
||
var _14_move_biometric_client_key_half_state_to_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// Biometric text, no auto prompt text, fingerprint validated, and prompt cancelled are refreshed on every app start, so we don't need to migrate them
|
||
const CLIENT_KEY_HALF = {
|
||
key: "clientKeyHalf",
|
||
stateDefinition: { name: "biometricSettings" },
|
||
};
|
||
class _14_move_biometric_client_key_half_state_to_providers_MoveBiometricClientKeyHalfToStateProviders extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _14_move_biometric_client_key_half_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _14_move_biometric_client_key_half_state_to_providers_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b, _c;
|
||
// Move account data
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.keys) === null || _b === void 0 ? void 0 : _b.biometricEncryptionClientKeyHalf) != null) {
|
||
yield helper.setToUser(userId, CLIENT_KEY_HALF, account.keys.biometricEncryptionClientKeyHalf);
|
||
// Delete old account data
|
||
(_c = account === null || account === void 0 ? void 0 : account.keys) === null || _c === void 0 ? true : delete _c.biometricEncryptionClientKeyHalf;
|
||
yield helper.set(userId, account);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _14_move_biometric_client_key_half_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId, account) {
|
||
return _14_move_biometric_client_key_half_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
let updatedAccount = false;
|
||
const userKeyHalf = yield helper.getFromUser(userId, CLIENT_KEY_HALF);
|
||
if (userKeyHalf) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_a = account.keys) !== null && _a !== void 0 ? _a : (account.keys = {});
|
||
updatedAccount = true;
|
||
account.keys.biometricEncryptionClientKeyHalf = userKeyHalf;
|
||
yield helper.setToUser(userId, CLIENT_KEY_HALF, null);
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/15-move-folder-state-to-state-provider.ts
|
||
var _15_move_folder_state_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_ENCRYPTED_FOLDERS = {
|
||
key: "folders",
|
||
stateDefinition: {
|
||
name: "folder",
|
||
},
|
||
};
|
||
class _15_move_folder_state_to_state_provider_FolderMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _15_move_folder_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _15_move_folder_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const value = (_b = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.folders) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_FOLDERS, value);
|
||
delete account.data.folders;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _15_move_folder_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _15_move_folder_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, USER_ENCRYPTED_FOLDERS);
|
||
if (account) {
|
||
account.data = Object.assign((_a = account.data) !== null && _a !== void 0 ? _a : {}, {
|
||
folders: {
|
||
encrypted: value,
|
||
},
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_FOLDERS, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/16-move-last-sync-to-state-provider.ts
|
||
var _16_move_last_sync_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const LAST_SYNC_KEY = {
|
||
key: "lastSync",
|
||
stateDefinition: {
|
||
name: "sync",
|
||
},
|
||
};
|
||
class _16_move_last_sync_to_state_provider_LastSyncMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _16_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _16_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.lastSync;
|
||
yield helper.setToUser(userId, LAST_SYNC_KEY, value !== null && value !== void 0 ? value : null);
|
||
if (value != null) {
|
||
delete account.profile.lastSync;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _16_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _16_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, LAST_SYNC_KEY);
|
||
if (account) {
|
||
account.profile = Object.assign((_a = account.profile) !== null && _a !== void 0 ? _a : {}, {
|
||
lastSync: value,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, LAST_SYNC_KEY, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/17-move-enable-passkeys-to-state-providers.ts
|
||
var _17_move_enable_passkeys_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_ENABLE_PASSKEYS = {
|
||
key: "enablePasskeys",
|
||
stateDefinition: {
|
||
name: "vaultSettings",
|
||
},
|
||
};
|
||
class _17_move_enable_passkeys_to_state_providers_EnablePasskeysMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _17_move_enable_passkeys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const global = yield helper.get("global");
|
||
if ((global === null || global === void 0 ? void 0 : global.enablePasskeys) != null) {
|
||
yield helper.setToGlobal(USER_ENABLE_PASSKEYS, global.enablePasskeys);
|
||
global === null || global === void 0 ? true : delete global.enablePasskeys;
|
||
yield helper.set("global", global);
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _17_move_enable_passkeys_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let global = yield helper.get("global");
|
||
const globalEnablePasskeys = yield helper.getFromGlobal(USER_ENABLE_PASSKEYS);
|
||
if (globalEnablePasskeys != null) {
|
||
global = Object.assign(global !== null && global !== void 0 ? global : {}, { enablePasskeys: globalEnablePasskeys });
|
||
yield helper.set("global", global);
|
||
yield helper.setToGlobal(USER_ENABLE_PASSKEYS, undefined);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/18-move-autofill-settings-to-state-providers.ts
|
||
var _18_move_autofill_settings_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// FIXME: Remove when updating file. Eslint update
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
const _18_move_autofill_settings_to_state_providers_AutofillOverlayVisibility = {
|
||
Off: 0,
|
||
OnButtonClick: 1,
|
||
OnFieldFocus: 2,
|
||
};
|
||
const autofillSettingsStateDefinition = {
|
||
stateDefinition: {
|
||
name: "autofillSettings",
|
||
},
|
||
};
|
||
class _18_move_autofill_settings_to_state_providers_AutofillSettingsKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _18_move_autofill_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
// global state (e.g. "autoFillOverlayVisibility -> inlineMenuVisibility")
|
||
const globalState = yield helper.get("global");
|
||
if ((globalState === null || globalState === void 0 ? void 0 : globalState.autoFillOverlayVisibility) != null) {
|
||
yield helper.setToGlobal({
|
||
stateDefinition: {
|
||
name: "autofillSettingsLocal",
|
||
},
|
||
key: "inlineMenuVisibility",
|
||
}, globalState.autoFillOverlayVisibility);
|
||
// delete `autoFillOverlayVisibility` from state global
|
||
delete globalState.autoFillOverlayVisibility;
|
||
yield helper.set("global", globalState);
|
||
}
|
||
// account state (e.g. account settings -> state provider framework keys)
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
// migrate account state
|
||
function migrateAccount(userId, account) {
|
||
return _18_move_autofill_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let updateAccount = false;
|
||
const accountSettings = account === null || account === void 0 ? void 0 : account.settings;
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.autoFillOnPageLoadDefault) != null) {
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoadDefault" }), accountSettings.autoFillOnPageLoadDefault);
|
||
delete account.settings.autoFillOnPageLoadDefault;
|
||
updateAccount = true;
|
||
}
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.enableAutoFillOnPageLoad) != null) {
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoad" }), accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.enableAutoFillOnPageLoad);
|
||
delete account.settings.enableAutoFillOnPageLoad;
|
||
updateAccount = true;
|
||
}
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.dismissedAutoFillOnPageLoadCallout) != null) {
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoadCalloutIsDismissed" }), accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.dismissedAutoFillOnPageLoadCallout);
|
||
delete account.settings.dismissedAutoFillOnPageLoadCallout;
|
||
updateAccount = true;
|
||
}
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.disableAutoTotpCopy) != null) {
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autoCopyTotp" }),
|
||
// invert the value to match the new naming convention
|
||
!(accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.disableAutoTotpCopy));
|
||
delete account.settings.disableAutoTotpCopy;
|
||
updateAccount = true;
|
||
}
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.activateAutoFillOnPageLoadFromPolicy) != null) {
|
||
yield helper.setToUser(userId, {
|
||
stateDefinition: {
|
||
name: "autofillSettingsLocal",
|
||
},
|
||
key: "activateAutofillOnPageLoadFromPolicy",
|
||
}, accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.activateAutoFillOnPageLoadFromPolicy);
|
||
delete account.settings.activateAutoFillOnPageLoadFromPolicy;
|
||
updateAccount = true;
|
||
}
|
||
if (updateAccount) {
|
||
// update the state account settings with the migrated values deleted
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _18_move_autofill_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
// global state (e.g. "inlineMenuVisibility -> autoFillOverlayVisibility")
|
||
const globalState = (yield helper.get("global")) || {};
|
||
const inlineMenuVisibility = yield helper.getFromGlobal({
|
||
stateDefinition: {
|
||
name: "autofillSettingsLocal",
|
||
},
|
||
key: "inlineMenuVisibility",
|
||
});
|
||
if (inlineMenuVisibility) {
|
||
yield helper.set("global", Object.assign(Object.assign({}, globalState), { autoFillOverlayVisibility: inlineMenuVisibility }));
|
||
// remove the global state provider framework key for `inlineMenuVisibility`
|
||
yield helper.setToGlobal({
|
||
stateDefinition: {
|
||
name: "autofillSettingsLocal",
|
||
},
|
||
key: "inlineMenuVisibility",
|
||
}, null);
|
||
}
|
||
// account state (e.g. state provider framework keys -> account settings)
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
// rollback account state
|
||
function rollbackAccount(userId, account) {
|
||
return _18_move_autofill_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let updateAccount = false;
|
||
let settings = (account === null || account === void 0 ? void 0 : account.settings) || {};
|
||
const autoFillOnPageLoadDefault = yield helper.getFromUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoadDefault" }));
|
||
const enableAutoFillOnPageLoad = yield helper.getFromUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoad" }));
|
||
const dismissedAutoFillOnPageLoadCallout = yield helper.getFromUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoadCalloutIsDismissed" }));
|
||
const autoCopyTotp = yield helper.getFromUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autoCopyTotp" }));
|
||
const activateAutoFillOnPageLoadFromPolicy = yield helper.getFromUser(userId, {
|
||
stateDefinition: {
|
||
name: "autofillSettingsLocal",
|
||
},
|
||
key: "activateAutofillOnPageLoadFromPolicy",
|
||
});
|
||
// update new settings and remove the account state provider framework keys for the rolled back values
|
||
if (autoFillOnPageLoadDefault != null) {
|
||
settings = Object.assign(Object.assign({}, settings), { autoFillOnPageLoadDefault });
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoadDefault" }), null);
|
||
updateAccount = true;
|
||
}
|
||
if (enableAutoFillOnPageLoad != null) {
|
||
settings = Object.assign(Object.assign({}, settings), { enableAutoFillOnPageLoad });
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoad" }), null);
|
||
updateAccount = true;
|
||
}
|
||
if (dismissedAutoFillOnPageLoadCallout != null) {
|
||
settings = Object.assign(Object.assign({}, settings), { dismissedAutoFillOnPageLoadCallout });
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autofillOnPageLoadCalloutIsDismissed" }), null);
|
||
updateAccount = true;
|
||
}
|
||
if (autoCopyTotp != null) {
|
||
// invert the value to match the new naming convention
|
||
settings = Object.assign(Object.assign({}, settings), { disableAutoTotpCopy: !autoCopyTotp });
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsStateDefinition), { key: "autoCopyTotp" }), null);
|
||
updateAccount = true;
|
||
}
|
||
if (activateAutoFillOnPageLoadFromPolicy != null) {
|
||
settings = Object.assign(Object.assign({}, settings), { activateAutoFillOnPageLoadFromPolicy });
|
||
yield helper.setToUser(userId, {
|
||
stateDefinition: {
|
||
name: "autofillSettingsLocal",
|
||
},
|
||
key: "activateAutofillOnPageLoadFromPolicy",
|
||
}, null);
|
||
updateAccount = true;
|
||
}
|
||
if (updateAccount) {
|
||
// commit updated settings to state
|
||
yield helper.set(userId, Object.assign(Object.assign({}, account), { settings }));
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/19-migrate-require-password-on-start.ts
|
||
var _19_migrate_require_password_on_start_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// Biometric text, no auto prompt text, fingerprint validated, and prompt cancelled are refreshed on every app start, so we don't need to migrate them
|
||
const REQUIRE_PASSWORD_ON_START = {
|
||
key: "requirePasswordOnStart",
|
||
stateDefinition: { name: "biometricSettings" },
|
||
};
|
||
class _19_migrate_require_password_on_start_RequirePasswordOnStartMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _19_migrate_require_password_on_start_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _19_migrate_require_password_on_start_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b;
|
||
// Move account data
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.requirePasswordOnStart) != null) {
|
||
yield helper.setToUser(userId, REQUIRE_PASSWORD_ON_START, account.settings.requirePasswordOnStart);
|
||
// Delete old account data
|
||
delete account.settings.requirePasswordOnStart;
|
||
yield helper.set(userId, account);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _19_migrate_require_password_on_start_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId, account) {
|
||
return _19_migrate_require_password_on_start_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const requirePassword = yield helper.getFromUser(userId, REQUIRE_PASSWORD_ON_START);
|
||
if (requirePassword) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_a = account.settings) !== null && _a !== void 0 ? _a : (account.settings = {});
|
||
account.settings.requirePasswordOnStart = requirePassword;
|
||
yield helper.setToUser(userId, REQUIRE_PASSWORD_ON_START, null);
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/20-move-private-key-to-state-providers.ts
|
||
var _20_move_private_key_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_ENCRYPTED_PRIVATE_KEY = {
|
||
key: "privateKey",
|
||
stateDefinition: {
|
||
name: "crypto",
|
||
},
|
||
};
|
||
class _20_move_private_key_to_state_providers_PrivateKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _20_move_private_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _20_move_private_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const value = (_b = (_a = account === null || account === void 0 ? void 0 : account.keys) === null || _a === void 0 ? void 0 : _a.privateKey) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_PRIVATE_KEY, value);
|
||
delete account.keys.privateKey;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _20_move_private_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _20_move_private_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, USER_ENCRYPTED_PRIVATE_KEY);
|
||
if (account && value) {
|
||
account.keys = Object.assign((_a = account.keys) !== null && _a !== void 0 ? _a : {}, {
|
||
privateKey: {
|
||
encrypted: value,
|
||
},
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_PRIVATE_KEY, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/21-move-collections-state-to-state-provider.ts
|
||
var _21_move_collections_state_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_ENCRYPTED_COLLECTIONS = {
|
||
key: "collections",
|
||
stateDefinition: {
|
||
name: "collection",
|
||
},
|
||
};
|
||
class _21_move_collections_state_to_state_provider_CollectionMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _21_move_collections_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _21_move_collections_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const value = (_b = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.collections) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_COLLECTIONS, value);
|
||
delete account.data.collections;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _21_move_collections_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _21_move_collections_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, USER_ENCRYPTED_COLLECTIONS);
|
||
if (account) {
|
||
account.data = Object.assign((_a = account.data) !== null && _a !== void 0 ? _a : {}, {
|
||
collections: {
|
||
encrypted: value,
|
||
},
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_ENCRYPTED_COLLECTIONS, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/22-move-collapsed-groupings-to-state-provider.ts
|
||
var _22_move_collapsed_groupings_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const COLLAPSED_GROUPINGS = {
|
||
key: "collapsedGroupings",
|
||
stateDefinition: {
|
||
name: "vaultFilter",
|
||
},
|
||
};
|
||
class _22_move_collapsed_groupings_to_state_provider_CollapsedGroupingsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _22_move_collapsed_groupings_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _22_move_collapsed_groupings_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = (_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.collapsedGroupings;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, COLLAPSED_GROUPINGS, value);
|
||
delete account.settings.collapsedGroupings;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _22_move_collapsed_groupings_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _22_move_collapsed_groupings_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, COLLAPSED_GROUPINGS);
|
||
if (account) {
|
||
account.settings = Object.assign((_a = account.settings) !== null && _a !== void 0 ? _a : {}, {
|
||
collapsedGroupings: value,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, COLLAPSED_GROUPINGS, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/23-move-biometric-prompts-to-state-providers.ts
|
||
var _23_move_biometric_prompts_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// prompt cancelled is refreshed on every app start/quit/unlock, so we don't need to migrate it
|
||
const DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT = {
|
||
key: "dismissedBiometricRequirePasswordOnStartCallout",
|
||
stateDefinition: { name: "biometricSettings" },
|
||
};
|
||
const PROMPT_AUTOMATICALLY = {
|
||
key: "promptAutomatically",
|
||
stateDefinition: { name: "biometricSettings" },
|
||
};
|
||
class _23_move_biometric_prompts_to_state_providers_MoveBiometricPromptsToStateProviders extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _23_move_biometric_prompts_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _23_move_biometric_prompts_to_state_providers_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b, _c, _d, _e;
|
||
if (account == null) {
|
||
return;
|
||
}
|
||
// Move account data
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.dismissedBiometricRequirePasswordOnStartCallout) != null) {
|
||
yield helper.setToUser(userId, DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT, account.settings.dismissedBiometricRequirePasswordOnStartCallout);
|
||
}
|
||
if (((_c = account === null || account === void 0 ? void 0 : account.settings) === null || _c === void 0 ? void 0 : _c.disableAutoBiometricsPrompt) != null) {
|
||
yield helper.setToUser(userId, PROMPT_AUTOMATICALLY, !account.settings.disableAutoBiometricsPrompt);
|
||
}
|
||
// Delete old account data
|
||
(_d = account === null || account === void 0 ? void 0 : account.settings) === null || _d === void 0 ? true : delete _d.dismissedBiometricRequirePasswordOnStartCallout;
|
||
(_e = account === null || account === void 0 ? void 0 : account.settings) === null || _e === void 0 ? true : delete _e.disableAutoBiometricsPrompt;
|
||
yield helper.set(userId, account);
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _23_move_biometric_prompts_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId, account) {
|
||
return _23_move_biometric_prompts_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
let updatedAccount = false;
|
||
const userDismissed = yield helper.getFromUser(userId, DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT);
|
||
if (userDismissed) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_a = account.settings) !== null && _a !== void 0 ? _a : (account.settings = {});
|
||
updatedAccount = true;
|
||
account.settings.dismissedBiometricRequirePasswordOnStartCallout = userDismissed;
|
||
yield helper.setToUser(userId, DISMISSED_BIOMETRIC_REQUIRE_PASSWORD_ON_START_CALLOUT, null);
|
||
}
|
||
const userPromptAutomatically = yield helper.getFromUser(userId, PROMPT_AUTOMATICALLY);
|
||
if (userPromptAutomatically != null) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_b = account.settings) !== null && _b !== void 0 ? _b : (account.settings = {});
|
||
updatedAccount = true;
|
||
account.settings.disableAutoBiometricsPrompt = !userPromptAutomatically;
|
||
yield helper.setToUser(userId, PROMPT_AUTOMATICALLY, null);
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/24-move-sm-onboarding-key-to-state-providers.ts
|
||
var _24_move_sm_onboarding_key_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const SM_ONBOARDING_TASKS = {
|
||
key: "tasks",
|
||
stateDefinition: { name: "smOnboarding" },
|
||
};
|
||
class _24_move_sm_onboarding_key_to_state_providers_SmOnboardingTasksMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _24_move_sm_onboarding_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _24_move_sm_onboarding_key_to_state_providers_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b;
|
||
// Move account data
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.smOnboardingTasks) != null) {
|
||
yield helper.setToUser(userId, SM_ONBOARDING_TASKS, account.settings.smOnboardingTasks);
|
||
// Delete old account data
|
||
delete account.settings.smOnboardingTasks;
|
||
yield helper.set(userId, account);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _24_move_sm_onboarding_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId, account) {
|
||
return _24_move_sm_onboarding_key_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const smOnboardingTasks = yield helper.getFromUser(userId, SM_ONBOARDING_TASKS);
|
||
if (smOnboardingTasks) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_a = account.settings) !== null && _a !== void 0 ? _a : (account.settings = {});
|
||
account.settings.smOnboardingTasks = smOnboardingTasks;
|
||
yield helper.setToUser(userId, SM_ONBOARDING_TASKS, null);
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/25-move-clear-clipboard-to-autofill-settings-state-provider.ts
|
||
var _25_move_clear_clipboard_to_autofill_settings_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// FIXME: Remove when updating file. Eslint update
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
const _25_move_clear_clipboard_to_autofill_settings_state_provider_ClearClipboardDelay = {
|
||
Never: null,
|
||
TenSeconds: 10,
|
||
TwentySeconds: 20,
|
||
ThirtySeconds: 30,
|
||
OneMinute: 60,
|
||
TwoMinutes: 120,
|
||
FiveMinutes: 300,
|
||
};
|
||
const autofillSettingsLocalStateDefinition = {
|
||
stateDefinition: {
|
||
name: "autofillSettingsLocal",
|
||
},
|
||
};
|
||
class _25_move_clear_clipboard_to_autofill_settings_state_provider_ClearClipboardDelayMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _25_move_clear_clipboard_to_autofill_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
// account state (e.g. account settings -> state provider framework keys)
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
// migrate account state
|
||
function migrateAccount(userId, account) {
|
||
return _25_move_clear_clipboard_to_autofill_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accountSettings = account === null || account === void 0 ? void 0 : account.settings;
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.clearClipboard) !== undefined) {
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsLocalStateDefinition), { key: "clearClipboardDelay" }), accountSettings.clearClipboard);
|
||
delete account.settings.clearClipboard;
|
||
// update the state account settings with the migrated values deleted
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _25_move_clear_clipboard_to_autofill_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
// account state (e.g. state provider framework keys -> account settings)
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
// rollback account state
|
||
function rollbackAccount(userId, account) {
|
||
return _25_move_clear_clipboard_to_autofill_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
let settings = (account === null || account === void 0 ? void 0 : account.settings) || {};
|
||
const clearClipboardDelay = yield helper.getFromUser(userId, Object.assign(Object.assign({}, autofillSettingsLocalStateDefinition), { key: "clearClipboardDelay" }));
|
||
// update new settings and remove the account state provider framework keys for the rolled back values
|
||
if (clearClipboardDelay !== undefined) {
|
||
settings = Object.assign(Object.assign({}, settings), { clearClipboard: clearClipboardDelay });
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, autofillSettingsLocalStateDefinition), { key: "clearClipboardDelay" }), null);
|
||
// commit updated settings to state
|
||
yield helper.set(userId, Object.assign(Object.assign({}, account), { settings }));
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/26-revert-move-last-sync-to-state-provider.ts
|
||
var _26_revert_move_last_sync_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _26_revert_move_last_sync_to_state_provider_LAST_SYNC_KEY = {
|
||
key: "lastSync",
|
||
stateDefinition: {
|
||
name: "sync",
|
||
},
|
||
};
|
||
class _26_revert_move_last_sync_to_state_provider_RevertLastSyncMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
rollback(helper) {
|
||
return _26_revert_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _26_revert_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.lastSync;
|
||
yield helper.setToUser(userId, _26_revert_move_last_sync_to_state_provider_LAST_SYNC_KEY, value !== null && value !== void 0 ? value : null);
|
||
if (value != null) {
|
||
delete account.profile.lastSync;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
migrate(helper) {
|
||
return _26_revert_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _26_revert_move_last_sync_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, _26_revert_move_last_sync_to_state_provider_LAST_SYNC_KEY);
|
||
if (account) {
|
||
account.profile = Object.assign((_a = account.profile) !== null && _a !== void 0 ? _a : {}, {
|
||
lastSync: value,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, _26_revert_move_last_sync_to_state_provider_LAST_SYNC_KEY, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/27-move-badge-settings-to-state-providers.ts
|
||
var _27_move_badge_settings_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const enableBadgeCounterKeyDefinition = {
|
||
stateDefinition: {
|
||
name: "badgeSettings",
|
||
},
|
||
key: "enableBadgeCounter",
|
||
};
|
||
class _27_move_badge_settings_to_state_providers_BadgeSettingsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _27_move_badge_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
// account state (e.g. account settings -> state provider framework keys)
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
// migrate account state
|
||
function migrateAccount(userId, account) {
|
||
return _27_move_badge_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accountSettings = account === null || account === void 0 ? void 0 : account.settings;
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.disableBadgeCounter) != undefined) {
|
||
yield helper.setToUser(userId, enableBadgeCounterKeyDefinition, !accountSettings.disableBadgeCounter);
|
||
delete account.settings.disableBadgeCounter;
|
||
// update the state account settings with the migrated values deleted
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _27_move_badge_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
// account state (e.g. state provider framework keys -> account settings)
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
// rollback account state
|
||
function rollbackAccount(userId, account) {
|
||
return _27_move_badge_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let settings = (account === null || account === void 0 ? void 0 : account.settings) || {};
|
||
const enableBadgeCounter = yield helper.getFromUser(userId, enableBadgeCounterKeyDefinition);
|
||
// update new settings and remove the account state provider framework keys for the rolled back values
|
||
if (enableBadgeCounter != undefined) {
|
||
settings = Object.assign(Object.assign({}, settings), { disableBadgeCounter: !enableBadgeCounter });
|
||
yield helper.setToUser(userId, enableBadgeCounterKeyDefinition, null);
|
||
// commit updated settings to state
|
||
yield helper.set(userId, Object.assign(Object.assign({}, account), { settings }));
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/28-move-biometric-unlock-to-state-providers.ts
|
||
var _28_move_biometric_unlock_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const BIOMETRIC_UNLOCK_ENABLED = {
|
||
key: "biometricUnlockEnabled",
|
||
stateDefinition: { name: "biometricSettings" },
|
||
};
|
||
class _28_move_biometric_unlock_to_state_providers_MoveBiometricUnlockToStateProviders extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _28_move_biometric_unlock_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _28_move_biometric_unlock_to_state_providers_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b, _c;
|
||
if (account == null) {
|
||
return;
|
||
}
|
||
// Move account data
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.biometricUnlock) != null) {
|
||
yield helper.setToUser(userId, BIOMETRIC_UNLOCK_ENABLED, account.settings.biometricUnlock);
|
||
}
|
||
// Delete old account data
|
||
(_c = account === null || account === void 0 ? void 0 : account.settings) === null || _c === void 0 ? true : delete _c.biometricUnlock;
|
||
yield helper.set(userId, account);
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _28_move_biometric_unlock_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId, account) {
|
||
return _28_move_biometric_unlock_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const biometricUnlock = yield helper.getFromUser(userId, BIOMETRIC_UNLOCK_ENABLED);
|
||
if (biometricUnlock != null) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_a = account.settings) !== null && _a !== void 0 ? _a : (account.settings = {});
|
||
account.settings.biometricUnlock = biometricUnlock;
|
||
yield helper.setToUser(userId, BIOMETRIC_UNLOCK_ENABLED, null);
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/29-move-user-notification-settings-to-state-provider.ts
|
||
var _29_move_user_notification_settings_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _29_move_user_notification_settings_to_state_provider_UserNotificationSettingsKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _29_move_user_notification_settings_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const globalState = yield helper.get("global");
|
||
// disableAddLoginNotification -> enableAddedLoginPrompt
|
||
if ((globalState === null || globalState === void 0 ? void 0 : globalState.disableAddLoginNotification) != null) {
|
||
yield helper.setToGlobal({
|
||
stateDefinition: {
|
||
name: "userNotificationSettings",
|
||
},
|
||
key: "enableAddedLoginPrompt",
|
||
}, !globalState.disableAddLoginNotification);
|
||
// delete `disableAddLoginNotification` from state global
|
||
delete globalState.disableAddLoginNotification;
|
||
yield helper.set("global", globalState);
|
||
}
|
||
// disableChangedPasswordNotification -> enableChangedPasswordPrompt
|
||
if ((globalState === null || globalState === void 0 ? void 0 : globalState.disableChangedPasswordNotification) != null) {
|
||
yield helper.setToGlobal({
|
||
stateDefinition: {
|
||
name: "userNotificationSettings",
|
||
},
|
||
key: "enableChangedPasswordPrompt",
|
||
}, !globalState.disableChangedPasswordNotification);
|
||
// delete `disableChangedPasswordNotification` from state global
|
||
delete globalState.disableChangedPasswordNotification;
|
||
yield helper.set("global", globalState);
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _29_move_user_notification_settings_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const globalState = (yield helper.get("global")) || {};
|
||
const enableAddedLoginPrompt = yield helper.getFromGlobal({
|
||
stateDefinition: {
|
||
name: "userNotificationSettings",
|
||
},
|
||
key: "enableAddedLoginPrompt",
|
||
});
|
||
const enableChangedPasswordPrompt = yield helper.getFromGlobal({
|
||
stateDefinition: {
|
||
name: "userNotificationSettings",
|
||
},
|
||
key: "enableChangedPasswordPrompt",
|
||
});
|
||
// enableAddedLoginPrompt -> disableAddLoginNotification
|
||
if (enableAddedLoginPrompt) {
|
||
yield helper.set("global", Object.assign(Object.assign({}, globalState), { disableAddLoginNotification: !enableAddedLoginPrompt }));
|
||
// remove the global state provider framework key for `enableAddedLoginPrompt`
|
||
yield helper.setToGlobal({
|
||
stateDefinition: {
|
||
name: "userNotificationSettings",
|
||
},
|
||
key: "enableAddedLoginPrompt",
|
||
}, null);
|
||
}
|
||
// enableChangedPasswordPrompt -> disableChangedPasswordNotification
|
||
if (enableChangedPasswordPrompt) {
|
||
yield helper.set("global", Object.assign(Object.assign({}, globalState), { disableChangedPasswordNotification: !enableChangedPasswordPrompt }));
|
||
// remove the global state provider framework key for `enableChangedPasswordPrompt`
|
||
yield helper.setToGlobal({
|
||
stateDefinition: {
|
||
name: "userNotificationSettings",
|
||
},
|
||
key: "enableChangedPasswordPrompt",
|
||
}, null);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/30-move-policy-state-to-state-provider.ts
|
||
var _30_move_policy_state_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var PolicyType;
|
||
(function (PolicyType) {
|
||
PolicyType[PolicyType["TwoFactorAuthentication"] = 0] = "TwoFactorAuthentication";
|
||
PolicyType[PolicyType["MasterPassword"] = 1] = "MasterPassword";
|
||
PolicyType[PolicyType["PasswordGenerator"] = 2] = "PasswordGenerator";
|
||
PolicyType[PolicyType["SingleOrg"] = 3] = "SingleOrg";
|
||
PolicyType[PolicyType["RequireSso"] = 4] = "RequireSso";
|
||
PolicyType[PolicyType["PersonalOwnership"] = 5] = "PersonalOwnership";
|
||
PolicyType[PolicyType["DisableSend"] = 6] = "DisableSend";
|
||
PolicyType[PolicyType["SendOptions"] = 7] = "SendOptions";
|
||
PolicyType[PolicyType["ResetPassword"] = 8] = "ResetPassword";
|
||
PolicyType[PolicyType["MaximumVaultTimeout"] = 9] = "MaximumVaultTimeout";
|
||
PolicyType[PolicyType["DisablePersonalVaultExport"] = 10] = "DisablePersonalVaultExport";
|
||
PolicyType[PolicyType["ActivateAutofill"] = 11] = "ActivateAutofill";
|
||
})(PolicyType || (PolicyType = {}));
|
||
const POLICIES_KEY = {
|
||
key: "policies",
|
||
stateDefinition: {
|
||
name: "policies",
|
||
},
|
||
};
|
||
class _30_move_policy_state_to_state_provider_PolicyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _30_move_policy_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _30_move_policy_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const value = (_b = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.policies) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, POLICIES_KEY, value);
|
||
delete account.data.policies;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all(accounts.map(({ userId, account }) => migrateAccount(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _30_move_policy_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _30_move_policy_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, POLICIES_KEY);
|
||
if (account) {
|
||
account.data = Object.assign((_a = account.data) !== null && _a !== void 0 ? _a : {}, {
|
||
policies: {
|
||
encrypted: value,
|
||
},
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, POLICIES_KEY, null);
|
||
});
|
||
}
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackAccount(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/31-move-enable-context-menu-to-autofill-settings-state-provider.ts
|
||
var _31_move_enable_context_menu_to_autofill_settings_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const enableContextMenuKeyDefinition = {
|
||
stateDefinition: {
|
||
name: "autofillSettings",
|
||
},
|
||
key: "enableContextMenu",
|
||
};
|
||
class _31_move_enable_context_menu_to_autofill_settings_state_provider_EnableContextMenuMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _31_move_enable_context_menu_to_autofill_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const globalState = yield helper.get("global");
|
||
// disableContextMenuItem -> enableContextMenu
|
||
if ((globalState === null || globalState === void 0 ? void 0 : globalState.disableContextMenuItem) != null) {
|
||
yield helper.setToGlobal(enableContextMenuKeyDefinition, !globalState.disableContextMenuItem);
|
||
// delete `disableContextMenuItem` from state global
|
||
delete globalState.disableContextMenuItem;
|
||
yield helper.set("global", globalState);
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _31_move_enable_context_menu_to_autofill_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const globalState = (yield helper.get("global")) || {};
|
||
const enableContextMenu = yield helper.getFromGlobal(enableContextMenuKeyDefinition);
|
||
// enableContextMenu -> disableContextMenuItem
|
||
if (enableContextMenu != null) {
|
||
yield helper.set("global", Object.assign(Object.assign({}, globalState), { disableContextMenuItem: !enableContextMenu }));
|
||
// remove the global state provider framework key for `enableContextMenu`
|
||
yield helper.setToGlobal(enableContextMenuKeyDefinition, null);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/32-move-preferred-language.ts
|
||
var _32_move_preferred_language_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const LOCALE_KEY = {
|
||
key: "locale",
|
||
stateDefinition: {
|
||
name: "translation",
|
||
},
|
||
};
|
||
class _32_move_preferred_language_PreferredLanguageMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _32_move_preferred_language_awaiter(this, void 0, void 0, function* () {
|
||
// global state
|
||
const global = yield helper.get("global");
|
||
if (!(global === null || global === void 0 ? void 0 : global.locale)) {
|
||
return;
|
||
}
|
||
yield helper.setToGlobal(LOCALE_KEY, global.locale);
|
||
delete global.locale;
|
||
yield helper.set("global", global);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _32_move_preferred_language_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const locale = yield helper.getFromGlobal(LOCALE_KEY);
|
||
if (!locale) {
|
||
return;
|
||
}
|
||
const global = (_a = (yield helper.get("global"))) !== null && _a !== void 0 ? _a : {};
|
||
global.locale = locale;
|
||
yield helper.set("global", global);
|
||
yield helper.setToGlobal(LOCALE_KEY, null);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/33-move-app-id-to-state-providers.ts
|
||
var _33_move_app_id_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const APP_ID_STORAGE_KEY = "appId";
|
||
const ANONYMOUS_APP_ID_STORAGE_KEY = "anonymousAppId";
|
||
const APP_ID_KEY = {
|
||
key: APP_ID_STORAGE_KEY,
|
||
stateDefinition: { name: "applicationId" },
|
||
};
|
||
const ANONYMOUS_APP_ID_KEY = {
|
||
key: ANONYMOUS_APP_ID_STORAGE_KEY,
|
||
stateDefinition: { name: "applicationId" },
|
||
};
|
||
class _33_move_app_id_to_state_providers_AppIdMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _33_move_app_id_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const appId = yield helper.get(APP_ID_STORAGE_KEY);
|
||
const anonymousAppId = yield helper.get(ANONYMOUS_APP_ID_STORAGE_KEY);
|
||
if (appId != null) {
|
||
yield helper.setToGlobal(APP_ID_KEY, appId);
|
||
yield helper.set(APP_ID_STORAGE_KEY, null);
|
||
}
|
||
if (anonymousAppId != null) {
|
||
yield helper.setToGlobal(ANONYMOUS_APP_ID_KEY, anonymousAppId);
|
||
yield helper.set(ANONYMOUS_APP_ID_STORAGE_KEY, null);
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _33_move_app_id_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const appId = yield helper.getFromGlobal(APP_ID_KEY);
|
||
const anonymousAppId = yield helper.getFromGlobal(ANONYMOUS_APP_ID_KEY);
|
||
if (appId != null) {
|
||
yield helper.set(APP_ID_STORAGE_KEY, appId);
|
||
yield helper.setToGlobal(APP_ID_KEY, null);
|
||
}
|
||
if (anonymousAppId != null) {
|
||
yield helper.set(ANONYMOUS_APP_ID_STORAGE_KEY, anonymousAppId);
|
||
yield helper.setToGlobal(ANONYMOUS_APP_ID_KEY, null);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/34-move-domain-settings-to-state-providers.ts
|
||
var _34_move_domain_settings_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// FIXME: Remove when updating file. Eslint update
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||
const UriMatchStrategy = {
|
||
Domain: 0,
|
||
Host: 1,
|
||
StartsWith: 2,
|
||
Exact: 3,
|
||
RegularExpression: 4,
|
||
Never: 5,
|
||
};
|
||
const defaultUriMatchStrategyDefinition = {
|
||
stateDefinition: {
|
||
name: "domainSettings",
|
||
},
|
||
key: "defaultUriMatchStrategy",
|
||
};
|
||
const equivalentDomainsDefinition = {
|
||
stateDefinition: {
|
||
name: "domainSettings",
|
||
},
|
||
key: "equivalentDomains",
|
||
};
|
||
const neverDomainsDefinition = {
|
||
stateDefinition: {
|
||
name: "domainSettings",
|
||
},
|
||
key: "neverDomains",
|
||
};
|
||
class _34_move_domain_settings_to_state_providers_DomainSettingsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _34_move_domain_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let updateAccount = false;
|
||
// global state ("neverDomains")
|
||
const globalState = yield helper.get("global");
|
||
if ((globalState === null || globalState === void 0 ? void 0 : globalState.neverDomains) != null) {
|
||
yield helper.setToGlobal(neverDomainsDefinition, globalState.neverDomains);
|
||
// delete `neverDomains` from state global
|
||
delete globalState.neverDomains;
|
||
yield helper.set("global", globalState);
|
||
}
|
||
// account state ("defaultUriMatch" and "settings.equivalentDomains")
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
// migrate account state
|
||
function migrateAccount(userId, account) {
|
||
return _34_move_domain_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const accountSettings = account === null || account === void 0 ? void 0 : account.settings;
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.defaultUriMatch) != undefined) {
|
||
yield helper.setToUser(userId, defaultUriMatchStrategyDefinition, accountSettings.defaultUriMatch);
|
||
delete account.settings.defaultUriMatch;
|
||
updateAccount = true;
|
||
}
|
||
if (((_a = accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.settings) === null || _a === void 0 ? void 0 : _a.equivalentDomains) != undefined) {
|
||
yield helper.setToUser(userId, equivalentDomainsDefinition, accountSettings.settings.equivalentDomains);
|
||
delete account.settings.settings.equivalentDomains;
|
||
delete account.settings.settings;
|
||
updateAccount = true;
|
||
}
|
||
if (updateAccount) {
|
||
// update the state account settings with the migrated values deleted
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _34_move_domain_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let updateAccount = false;
|
||
// global state ("neverDomains")
|
||
const globalState = (yield helper.get("global")) || {};
|
||
const neverDomains = yield helper.getFromGlobal(neverDomainsDefinition);
|
||
if (neverDomains != null) {
|
||
yield helper.set("global", Object.assign(Object.assign({}, globalState), { neverDomains: neverDomains }));
|
||
// remove the global state provider framework key for `neverDomains`
|
||
yield helper.setToGlobal(neverDomainsDefinition, null);
|
||
}
|
||
// account state ("defaultUriMatchStrategy" and "equivalentDomains")
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
// rollback account state
|
||
function rollbackAccount(userId, account) {
|
||
return _34_move_domain_settings_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let settings = (account === null || account === void 0 ? void 0 : account.settings) || {};
|
||
const defaultUriMatchStrategy = yield helper.getFromUser(userId, defaultUriMatchStrategyDefinition);
|
||
const equivalentDomains = yield helper.getFromUser(userId, equivalentDomainsDefinition);
|
||
// update new settings and remove the account state provider framework keys for the rolled back values
|
||
if (defaultUriMatchStrategy != null) {
|
||
settings = Object.assign(Object.assign({}, settings), { defaultUriMatch: defaultUriMatchStrategy });
|
||
yield helper.setToUser(userId, defaultUriMatchStrategyDefinition, null);
|
||
updateAccount = true;
|
||
}
|
||
if (equivalentDomains != null) {
|
||
settings = Object.assign(Object.assign({}, settings), { settings: { equivalentDomains } });
|
||
yield helper.setToUser(userId, equivalentDomainsDefinition, null);
|
||
updateAccount = true;
|
||
}
|
||
// commit updated settings to state
|
||
if (updateAccount) {
|
||
yield helper.set(userId, Object.assign(Object.assign({}, account), { settings }));
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/35-move-theme-to-state-providers.ts
|
||
var _35_move_theme_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const THEME_SELECTION = {
|
||
key: "selection",
|
||
stateDefinition: { name: "theming" },
|
||
};
|
||
class _35_move_theme_to_state_providers_MoveThemeToStateProviderMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _35_move_theme_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyGlobalState = yield helper.get("global");
|
||
const theme = legacyGlobalState === null || legacyGlobalState === void 0 ? void 0 : legacyGlobalState.theme;
|
||
if (theme != null) {
|
||
yield helper.setToGlobal(THEME_SELECTION, theme);
|
||
delete legacyGlobalState.theme;
|
||
yield helper.set("global", legacyGlobalState);
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _35_move_theme_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const theme = yield helper.getFromGlobal(THEME_SELECTION);
|
||
if (theme != null) {
|
||
const legacyGlobal = (_a = (yield helper.get("global"))) !== null && _a !== void 0 ? _a : {};
|
||
legacyGlobal.theme = theme;
|
||
yield helper.set("global", legacyGlobal);
|
||
yield helper.removeFromGlobal(THEME_SELECTION);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/36-move-show-card-and-identity-to-state-provider.ts
|
||
var _36_move_show_card_and_identity_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const vaultSettingsStateDefinition = {
|
||
stateDefinition: {
|
||
name: "vaultSettings",
|
||
},
|
||
};
|
||
class _36_move_show_card_and_identity_to_state_provider_VaultSettingsKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _36_move_show_card_and_identity_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
function migrateAccount(userId, account) {
|
||
return _36_move_show_card_and_identity_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
let updateAccount = false;
|
||
const accountSettings = account === null || account === void 0 ? void 0 : account.settings;
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.dontShowCardsCurrentTab) != null) {
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, vaultSettingsStateDefinition), { key: "showCardsCurrentTab" }), !accountSettings.dontShowCardsCurrentTab);
|
||
delete account.settings.dontShowCardsCurrentTab;
|
||
updateAccount = true;
|
||
}
|
||
if ((accountSettings === null || accountSettings === void 0 ? void 0 : accountSettings.dontShowIdentitiesCurrentTab) != null) {
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, vaultSettingsStateDefinition), { key: "showIdentitiesCurrentTab" }), !accountSettings.dontShowIdentitiesCurrentTab);
|
||
delete account.settings.dontShowIdentitiesCurrentTab;
|
||
updateAccount = true;
|
||
}
|
||
if (updateAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _36_move_show_card_and_identity_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
function rollbackAccount(userId, account) {
|
||
return _36_move_show_card_and_identity_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
let updateAccount = false;
|
||
let settings = (_a = account === null || account === void 0 ? void 0 : account.settings) !== null && _a !== void 0 ? _a : {};
|
||
const showCardsCurrentTab = yield helper.getFromUser(userId, Object.assign(Object.assign({}, vaultSettingsStateDefinition), { key: "showCardsCurrentTab" }));
|
||
const showIdentitiesCurrentTab = yield helper.getFromUser(userId, Object.assign(Object.assign({}, vaultSettingsStateDefinition), { key: "showIdentitiesCurrentTab" }));
|
||
if (showCardsCurrentTab != null) {
|
||
// invert the value to match the new naming convention
|
||
settings = Object.assign(Object.assign({}, settings), { dontShowCardsCurrentTab: !showCardsCurrentTab });
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, vaultSettingsStateDefinition), { key: "showCardsCurrentTab" }), null);
|
||
updateAccount = true;
|
||
}
|
||
if (showIdentitiesCurrentTab != null) {
|
||
// invert the value to match the new naming convention
|
||
settings = Object.assign(Object.assign({}, settings), { dontShowIdentitiesCurrentTab: !showIdentitiesCurrentTab });
|
||
yield helper.setToUser(userId, Object.assign(Object.assign({}, vaultSettingsStateDefinition), { key: "showIdentitiesCurrentTab" }), null);
|
||
updateAccount = true;
|
||
}
|
||
if (updateAccount) {
|
||
yield helper.set(userId, Object.assign(Object.assign({}, account), { settings }));
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/37-move-avatar-color-to-state-providers.ts
|
||
var _37_move_avatar_color_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const AVATAR_COLOR_STATE = { name: "avatar" };
|
||
const AVATAR_COLOR_KEY = {
|
||
key: "avatarColor",
|
||
stateDefinition: AVATAR_COLOR_STATE,
|
||
};
|
||
class _37_move_avatar_color_to_state_providers_AvatarColorMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _37_move_avatar_color_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _37_move_avatar_color_to_state_providers_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b, _c;
|
||
// Move account avatarColor
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.avatarColor) != null) {
|
||
yield helper.setToUser(userId, AVATAR_COLOR_KEY, account.settings.avatarColor);
|
||
// Delete old account avatarColor property
|
||
(_c = account === null || account === void 0 ? void 0 : account.settings) === null || _c === void 0 ? true : delete _c.avatarColor;
|
||
yield helper.set(userId, account);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _37_move_avatar_color_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId, account) {
|
||
return _37_move_avatar_color_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let updatedAccount = false;
|
||
const userAvatarColor = yield helper.getFromUser(userId, AVATAR_COLOR_KEY);
|
||
if (userAvatarColor) {
|
||
if (!account) {
|
||
account = {};
|
||
}
|
||
updatedAccount = true;
|
||
account.settings.avatarColor = userAvatarColor;
|
||
yield helper.setToUser(userId, AVATAR_COLOR_KEY, null);
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/38-migrate-token-svc-to-state-provider.ts
|
||
var _38_migrate_token_svc_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const EMAIL_TWO_FACTOR_TOKEN_RECORD_DISK_LOCAL = {
|
||
key: "emailTwoFactorTokenRecord",
|
||
stateDefinition: {
|
||
name: "tokenDiskLocal",
|
||
},
|
||
};
|
||
const TOKEN_STATE_DEF_LIKE = {
|
||
name: "token",
|
||
};
|
||
const ACCESS_TOKEN_DISK = {
|
||
key: "accessToken", // matches KeyDefinition.key
|
||
stateDefinition: TOKEN_STATE_DEF_LIKE,
|
||
};
|
||
const REFRESH_TOKEN_DISK = {
|
||
key: "refreshToken",
|
||
stateDefinition: TOKEN_STATE_DEF_LIKE,
|
||
};
|
||
const API_KEY_CLIENT_ID_DISK = {
|
||
key: "apiKeyClientId",
|
||
stateDefinition: TOKEN_STATE_DEF_LIKE,
|
||
};
|
||
const API_KEY_CLIENT_SECRET_DISK = {
|
||
key: "apiKeyClientSecret",
|
||
stateDefinition: TOKEN_STATE_DEF_LIKE,
|
||
};
|
||
class _38_migrate_token_svc_to_state_provider_TokenServiceStateProviderMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _38_migrate_token_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
// Move global data
|
||
const globalData = yield helper.get("global");
|
||
// Create new global record for 2FA token that we can accumulate data in
|
||
const emailTwoFactorTokenRecord = {};
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account, globalTwoFactorToken, emailTwoFactorTokenRecord) {
|
||
return _38_migrate_token_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c, _d, _e;
|
||
let updatedAccount = false;
|
||
// migrate 2FA token from global to user state
|
||
// Due to the existing implmentation, n users on the same device share the same global state value for 2FA token.
|
||
// So, we will just migrate it to all users to keep it valid for whichever was the user that set it previously.
|
||
// Note: don't bother migrating 2FA Token if user account or email is undefined
|
||
const email = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.email;
|
||
if (globalTwoFactorToken != undefined && account != undefined && email != undefined) {
|
||
emailTwoFactorTokenRecord[email] = globalTwoFactorToken;
|
||
// Note: don't set updatedAccount to true here as we aren't updating
|
||
// the legacy user state, just migrating a global state to a new user state
|
||
}
|
||
// Migrate access token
|
||
const existingAccessToken = (_b = account === null || account === void 0 ? void 0 : account.tokens) === null || _b === void 0 ? void 0 : _b.accessToken;
|
||
if (existingAccessToken != null) {
|
||
// Only migrate data that exists
|
||
if (helper.type !== "web-disk-local") {
|
||
// only migrate access token to session storage - never local.
|
||
yield helper.setToUser(userId, ACCESS_TOKEN_DISK, existingAccessToken);
|
||
}
|
||
delete account.tokens.accessToken;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate refresh token
|
||
const existingRefreshToken = (_c = account === null || account === void 0 ? void 0 : account.tokens) === null || _c === void 0 ? void 0 : _c.refreshToken;
|
||
if (existingRefreshToken != null) {
|
||
if (helper.type !== "web-disk-local") {
|
||
// only migrate refresh token to session storage - never local.
|
||
yield helper.setToUser(userId, REFRESH_TOKEN_DISK, existingRefreshToken);
|
||
}
|
||
delete account.tokens.refreshToken;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate API key client id
|
||
const existingApiKeyClientId = (_d = account === null || account === void 0 ? void 0 : account.profile) === null || _d === void 0 ? void 0 : _d.apiKeyClientId;
|
||
if (existingApiKeyClientId != null) {
|
||
if (helper.type !== "web-disk-local") {
|
||
// only migrate client id to session storage - never local.
|
||
yield helper.setToUser(userId, API_KEY_CLIENT_ID_DISK, existingApiKeyClientId);
|
||
}
|
||
delete account.profile.apiKeyClientId;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate API key client secret
|
||
const existingApiKeyClientSecret = (_e = account === null || account === void 0 ? void 0 : account.keys) === null || _e === void 0 ? void 0 : _e.apiKeyClientSecret;
|
||
if (existingApiKeyClientSecret != null) {
|
||
if (helper.type !== "web-disk-local") {
|
||
// only migrate client secret to session storage - never local.
|
||
yield helper.setToUser(userId, API_KEY_CLIENT_SECRET_DISK, existingApiKeyClientSecret);
|
||
}
|
||
delete account.keys.apiKeyClientSecret;
|
||
updatedAccount = true;
|
||
}
|
||
if (updatedAccount) {
|
||
// Save the migrated account only if it was updated
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([
|
||
...accounts.map(({ userId, account }) => migrateAccount(userId, account, globalData === null || globalData === void 0 ? void 0 : globalData.twoFactorToken, emailTwoFactorTokenRecord)),
|
||
]);
|
||
// Save the global 2FA token record
|
||
yield helper.setToGlobal(EMAIL_TWO_FACTOR_TOKEN_RECORD_DISK_LOCAL, emailTwoFactorTokenRecord);
|
||
// Delete global data
|
||
globalData === null || globalData === void 0 ? true : delete globalData.twoFactorToken;
|
||
yield helper.set("global", globalData);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _38_migrate_token_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const accounts = yield helper.getAccounts();
|
||
// Since we migrated the global 2FA token to all users, we need to rollback the 2FA token for all users
|
||
// but we only need to set it to the global state once
|
||
// Go through accounts and find the first user that has a non-null email and 2FA token
|
||
let migratedTwoFactorToken = null;
|
||
for (const { account } of accounts) {
|
||
const email = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.email;
|
||
if (email == null) {
|
||
continue;
|
||
}
|
||
const emailTwoFactorTokenRecord = yield helper.getFromGlobal(EMAIL_TWO_FACTOR_TOKEN_RECORD_DISK_LOCAL);
|
||
migratedTwoFactorToken = emailTwoFactorTokenRecord[email];
|
||
if (migratedTwoFactorToken != null) {
|
||
break;
|
||
}
|
||
}
|
||
if (migratedTwoFactorToken != null) {
|
||
let legacyGlobal = yield helper.get("global");
|
||
if (!legacyGlobal) {
|
||
legacyGlobal = {};
|
||
}
|
||
legacyGlobal.twoFactorToken = migratedTwoFactorToken;
|
||
yield helper.set("global", legacyGlobal);
|
||
}
|
||
// delete global 2FA token record
|
||
yield helper.setToGlobal(EMAIL_TWO_FACTOR_TOKEN_RECORD_DISK_LOCAL, null);
|
||
function rollbackAccount(userId, account) {
|
||
return _38_migrate_token_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
let updatedLegacyAccount = false;
|
||
// Rollback access token
|
||
const migratedAccessToken = yield helper.getFromUser(userId, ACCESS_TOKEN_DISK);
|
||
if ((account === null || account === void 0 ? void 0 : account.tokens) && migratedAccessToken != null) {
|
||
account.tokens.accessToken = migratedAccessToken;
|
||
updatedLegacyAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, ACCESS_TOKEN_DISK, null);
|
||
// Rollback refresh token
|
||
const migratedRefreshToken = yield helper.getFromUser(userId, REFRESH_TOKEN_DISK);
|
||
if ((account === null || account === void 0 ? void 0 : account.tokens) && migratedRefreshToken != null) {
|
||
account.tokens.refreshToken = migratedRefreshToken;
|
||
updatedLegacyAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, REFRESH_TOKEN_DISK, null);
|
||
// Rollback API key client id
|
||
const migratedApiKeyClientId = yield helper.getFromUser(userId, API_KEY_CLIENT_ID_DISK);
|
||
if ((account === null || account === void 0 ? void 0 : account.profile) && migratedApiKeyClientId != null) {
|
||
account.profile.apiKeyClientId = migratedApiKeyClientId;
|
||
updatedLegacyAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, API_KEY_CLIENT_ID_DISK, null);
|
||
// Rollback API key client secret
|
||
const migratedApiKeyClientSecret = yield helper.getFromUser(userId, API_KEY_CLIENT_SECRET_DISK);
|
||
if ((account === null || account === void 0 ? void 0 : account.keys) && migratedApiKeyClientSecret != null) {
|
||
account.keys.apiKeyClientSecret = migratedApiKeyClientSecret;
|
||
updatedLegacyAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, API_KEY_CLIENT_SECRET_DISK, null);
|
||
if (updatedLegacyAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/39-move-billing-account-profile-to-state-providers.ts
|
||
var _39_move_billing_account_profile_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const BILLING_ACCOUNT_PROFILE_KEY_DEFINITION = {
|
||
key: "accountProfile",
|
||
stateDefinition: {
|
||
name: "billing",
|
||
},
|
||
};
|
||
class _39_move_billing_account_profile_to_state_providers_MoveBillingAccountProfileMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _39_move_billing_account_profile_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
const migrateAccount = (userId, account) => _39_move_billing_account_profile_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c, _d;
|
||
const hasPremiumPersonally = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.hasPremiumPersonally;
|
||
const hasPremiumFromOrganization = (_b = account === null || account === void 0 ? void 0 : account.profile) === null || _b === void 0 ? void 0 : _b.hasPremiumFromOrganization;
|
||
if (hasPremiumPersonally != null || hasPremiumFromOrganization != null) {
|
||
yield helper.setToUser(userId, BILLING_ACCOUNT_PROFILE_KEY_DEFINITION, {
|
||
hasPremiumPersonally: hasPremiumPersonally,
|
||
hasPremiumFromOrganization: hasPremiumFromOrganization,
|
||
});
|
||
(_c = account === null || account === void 0 ? void 0 : account.profile) === null || _c === void 0 ? true : delete _c.hasPremiumPersonally;
|
||
(_d = account === null || account === void 0 ? void 0 : account.profile) === null || _d === void 0 ? true : delete _d.hasPremiumFromOrganization;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _39_move_billing_account_profile_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
const rollbackAccount = (userId, account) => _39_move_billing_account_profile_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, BILLING_ACCOUNT_PROFILE_KEY_DEFINITION);
|
||
if (account && value) {
|
||
account.profile = Object.assign((_a = account.profile) !== null && _a !== void 0 ? _a : {}, {
|
||
hasPremiumPersonally: value === null || value === void 0 ? void 0 : value.hasPremiumPersonally,
|
||
hasPremiumFromOrganization: value === null || value === void 0 ? void 0 : value.hasPremiumFromOrganization,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, BILLING_ACCOUNT_PROFILE_KEY_DEFINITION, null);
|
||
});
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/4-remove-ever-been-unlocked.ts
|
||
var _4_remove_ever_been_unlocked_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _4_remove_ever_been_unlocked_RemoveEverBeenUnlockedMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _4_remove_ever_been_unlocked_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function removeEverBeenUnlocked(userId, account) {
|
||
return _4_remove_ever_been_unlocked_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if (((_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.everBeenUnlocked) != null) {
|
||
delete account.profile.everBeenUnlocked;
|
||
return helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||
Promise.all(accounts.map(({ userId, account }) => removeEverBeenUnlocked(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
throw IRREVERSIBLE;
|
||
}
|
||
// Override is necessary because default implementation assumes `stateVersion` at the root, but for this version
|
||
// it is nested inside a global object.
|
||
updateVersion(helper, direction) {
|
||
return _4_remove_ever_been_unlocked_awaiter(this, void 0, void 0, function* () {
|
||
const endVersion = direction === "up" ? this.toVersion : this.fromVersion;
|
||
helper.currentVersion = endVersion;
|
||
const global = (yield helper.get("global")) || {};
|
||
yield helper.set("global", Object.assign(Object.assign({}, global), { stateVersion: endVersion }));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/40-move-organization-state-to-state-provider.ts
|
||
var _40_move_organization_state_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// Local declarations of `OrganizationData` and the types of it's properties.
|
||
// Duplicated to remain frozen in time when migration occurs.
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var OrganizationUserStatusType;
|
||
(function (OrganizationUserStatusType) {
|
||
OrganizationUserStatusType[OrganizationUserStatusType["Invited"] = 0] = "Invited";
|
||
OrganizationUserStatusType[OrganizationUserStatusType["Accepted"] = 1] = "Accepted";
|
||
OrganizationUserStatusType[OrganizationUserStatusType["Confirmed"] = 2] = "Confirmed";
|
||
OrganizationUserStatusType[OrganizationUserStatusType["Revoked"] = -1] = "Revoked";
|
||
})(OrganizationUserStatusType || (OrganizationUserStatusType = {}));
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var OrganizationUserType;
|
||
(function (OrganizationUserType) {
|
||
OrganizationUserType[OrganizationUserType["Owner"] = 0] = "Owner";
|
||
OrganizationUserType[OrganizationUserType["Admin"] = 1] = "Admin";
|
||
OrganizationUserType[OrganizationUserType["User"] = 2] = "User";
|
||
OrganizationUserType[OrganizationUserType["Manager"] = 3] = "Manager";
|
||
OrganizationUserType[OrganizationUserType["Custom"] = 4] = "Custom";
|
||
})(OrganizationUserType || (OrganizationUserType = {}));
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var ProviderType;
|
||
(function (ProviderType) {
|
||
ProviderType[ProviderType["Msp"] = 0] = "Msp";
|
||
ProviderType[ProviderType["Reseller"] = 1] = "Reseller";
|
||
})(ProviderType || (ProviderType = {}));
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var ProductType;
|
||
(function (ProductType) {
|
||
ProductType[ProductType["Free"] = 0] = "Free";
|
||
ProductType[ProductType["Families"] = 1] = "Families";
|
||
ProductType[ProductType["Teams"] = 2] = "Teams";
|
||
ProductType[ProductType["Enterprise"] = 3] = "Enterprise";
|
||
ProductType[ProductType["TeamsStarter"] = 4] = "TeamsStarter";
|
||
})(ProductType || (ProductType = {}));
|
||
const USER_ORGANIZATIONS = {
|
||
key: "organizations",
|
||
stateDefinition: {
|
||
name: "organizations",
|
||
},
|
||
};
|
||
class _40_move_organization_state_to_state_provider_OrganizationMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _40_move_organization_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _40_move_organization_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.organizations;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, USER_ORGANIZATIONS, value);
|
||
delete account.data.organizations;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all(accounts.map(({ userId, account }) => migrateAccount(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _40_move_organization_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _40_move_organization_state_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, USER_ORGANIZATIONS);
|
||
if (account) {
|
||
account.data = Object.assign((_a = account.data) !== null && _a !== void 0 ? _a : {}, {
|
||
organizations: value,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_ORGANIZATIONS, null);
|
||
});
|
||
}
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackAccount(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/41-move-event-collection-to-state-provider.ts
|
||
var _41_move_event_collection_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const EVENT_COLLECTION = {
|
||
stateDefinition: {
|
||
name: "eventCollection",
|
||
},
|
||
key: "eventCollection",
|
||
};
|
||
class _41_move_event_collection_to_state_provider_EventCollectionMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _41_move_event_collection_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _41_move_event_collection_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.eventCollection;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, EVENT_COLLECTION, value);
|
||
delete account.data.eventCollection;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _41_move_event_collection_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _41_move_event_collection_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, EVENT_COLLECTION);
|
||
if (account) {
|
||
account.data = Object.assign((_a = account.data) !== null && _a !== void 0 ? _a : {}, {
|
||
eventCollection: value,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, EVENT_COLLECTION, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/42-move-enable-favicon-to-domain-settings-state-provider.ts
|
||
var _42_move_enable_favicon_to_domain_settings_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const ShowFaviconDefinition = {
|
||
stateDefinition: {
|
||
name: "domainSettings",
|
||
},
|
||
key: "showFavicons",
|
||
};
|
||
class _42_move_enable_favicon_to_domain_settings_state_provider_EnableFaviconMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _42_move_enable_favicon_to_domain_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
// global state ("disableFavicon" -> "showFavicons")
|
||
const globalState = yield helper.get("global");
|
||
if ((globalState === null || globalState === void 0 ? void 0 : globalState.disableFavicon) != null) {
|
||
yield helper.setToGlobal(ShowFaviconDefinition, !globalState.disableFavicon);
|
||
// delete `disableFavicon` from state global
|
||
delete globalState.disableFavicon;
|
||
yield helper.set("global", globalState);
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _42_move_enable_favicon_to_domain_settings_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
// global state ("showFavicons" -> "disableFavicon")
|
||
const globalState = (yield helper.get("global")) || {};
|
||
const showFavicons = yield helper.getFromGlobal(ShowFaviconDefinition);
|
||
if (showFavicons != null) {
|
||
yield helper.set("global", Object.assign(Object.assign({}, globalState), { disableFavicon: !showFavicons }));
|
||
// remove the global state provider framework key for `showFavicons`
|
||
yield helper.setToGlobal(ShowFaviconDefinition, null);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/43-move-auto-confirm-finger-prints-to-state-provider.ts
|
||
var _43_move_auto_confirm_finger_prints_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const ORGANIZATION_MANAGEMENT_PREFERENCES = {
|
||
name: "organizationManagementPreferences",
|
||
};
|
||
const AUTO_CONFIRM_FINGERPRINTS = {
|
||
key: "autoConfirmFingerPrints",
|
||
stateDefinition: ORGANIZATION_MANAGEMENT_PREFERENCES,
|
||
};
|
||
class _43_move_auto_confirm_finger_prints_to_state_provider_AutoConfirmFingerPrintsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _43_move_auto_confirm_finger_prints_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
yield Promise.all(legacyAccounts.map((_a) => _43_move_auto_confirm_finger_prints_to_state_provider_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b, _c;
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.autoConfirmFingerPrints) != null) {
|
||
yield helper.setToUser(userId, AUTO_CONFIRM_FINGERPRINTS, account.settings.autoConfirmFingerPrints);
|
||
(_c = account === null || account === void 0 ? void 0 : account.settings) === null || _c === void 0 ? true : delete _c.autoConfirmFingerPrints;
|
||
yield helper.set(userId, account);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _43_move_auto_confirm_finger_prints_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId, account) {
|
||
return _43_move_auto_confirm_finger_prints_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
let updatedAccount = false;
|
||
const autoConfirmFingerPrints = yield helper.getFromUser(userId, AUTO_CONFIRM_FINGERPRINTS);
|
||
if (autoConfirmFingerPrints) {
|
||
if (!account) {
|
||
account = {};
|
||
}
|
||
updatedAccount = true;
|
||
account.settings.autoConfirmFingerPrints = autoConfirmFingerPrints;
|
||
yield helper.setToUser(userId, AUTO_CONFIRM_FINGERPRINTS, null);
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackUser(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/44-move-user-decryption-options-to-state-provider.ts
|
||
var _44_move_user_decryption_options_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const USER_DECRYPTION_OPTIONS = {
|
||
key: "decryptionOptions",
|
||
stateDefinition: {
|
||
name: "userDecryptionOptions",
|
||
},
|
||
};
|
||
class _44_move_user_decryption_options_to_state_provider_UserDecryptionOptionsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _44_move_user_decryption_options_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _44_move_user_decryption_options_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const value = account === null || account === void 0 ? void 0 : account.decryptionOptions;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, USER_DECRYPTION_OPTIONS, value);
|
||
delete account.decryptionOptions;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _44_move_user_decryption_options_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _44_move_user_decryption_options_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const value = yield helper.getFromUser(userId, USER_DECRYPTION_OPTIONS);
|
||
if (account) {
|
||
account.decryptionOptions = Object.assign(account.decryptionOptions, value);
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, USER_DECRYPTION_OPTIONS, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/45-merge-environment-state.ts
|
||
var _45_merge_environment_state_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _45_merge_environment_state_ENVIRONMENT_STATE = { name: "environment" };
|
||
const ENVIRONMENT_REGION = {
|
||
key: "region",
|
||
stateDefinition: _45_merge_environment_state_ENVIRONMENT_STATE,
|
||
};
|
||
const ENVIRONMENT_URLS = {
|
||
key: "urls",
|
||
stateDefinition: _45_merge_environment_state_ENVIRONMENT_STATE,
|
||
};
|
||
const ENVIRONMENT_ENVIRONMENT = {
|
||
key: "environment",
|
||
stateDefinition: _45_merge_environment_state_ENVIRONMENT_STATE,
|
||
};
|
||
class _45_merge_environment_state_MergeEnvironmentState extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _45_merge_environment_state_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _45_merge_environment_state_awaiter(this, void 0, void 0, function* () {
|
||
const region = yield helper.getFromUser(userId, ENVIRONMENT_REGION);
|
||
const urls = yield helper.getFromUser(userId, ENVIRONMENT_URLS);
|
||
if (region == null && urls == null) {
|
||
return;
|
||
}
|
||
yield helper.setToUser(userId, ENVIRONMENT_ENVIRONMENT, {
|
||
region,
|
||
urls,
|
||
});
|
||
yield helper.removeFromUser(userId, ENVIRONMENT_REGION);
|
||
yield helper.removeFromUser(userId, ENVIRONMENT_URLS);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
const region = yield helper.getFromGlobal(ENVIRONMENT_REGION);
|
||
const urls = yield helper.getFromGlobal(ENVIRONMENT_URLS);
|
||
if (region == null && urls == null) {
|
||
return;
|
||
}
|
||
yield helper.setToGlobal(ENVIRONMENT_ENVIRONMENT, {
|
||
region,
|
||
urls,
|
||
});
|
||
yield helper.removeFromGlobal(ENVIRONMENT_REGION);
|
||
yield helper.removeFromGlobal(ENVIRONMENT_URLS);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _45_merge_environment_state_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _45_merge_environment_state_awaiter(this, void 0, void 0, function* () {
|
||
const state = (yield helper.getFromUser(userId, ENVIRONMENT_ENVIRONMENT));
|
||
yield helper.setToUser(userId, ENVIRONMENT_REGION, state === null || state === void 0 ? void 0 : state.region);
|
||
yield helper.setToUser(userId, ENVIRONMENT_URLS, state === null || state === void 0 ? void 0 : state.urls);
|
||
yield helper.removeFromUser(userId, ENVIRONMENT_ENVIRONMENT);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
const state = (yield helper.getFromGlobal(ENVIRONMENT_ENVIRONMENT));
|
||
yield helper.setToGlobal(ENVIRONMENT_REGION, state === null || state === void 0 ? void 0 : state.region);
|
||
yield helper.setToGlobal(ENVIRONMENT_URLS, state === null || state === void 0 ? void 0 : state.urls);
|
||
yield helper.removeFromGlobal(ENVIRONMENT_ENVIRONMENT);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/46-delete-orphaned-biometric-prompt-data.ts
|
||
var _46_delete_orphaned_biometric_prompt_data_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const PROMPT_CANCELLED = {
|
||
key: "promptCancelled",
|
||
stateDefinition: { name: "biometricSettings" },
|
||
};
|
||
class _46_delete_orphaned_biometric_prompt_data_DeleteBiometricPromptCancelledData extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _46_delete_orphaned_biometric_prompt_data_awaiter(this, void 0, void 0, function* () {
|
||
yield Promise.all((yield helper.getAccounts()).map((_a) => _46_delete_orphaned_biometric_prompt_data_awaiter(this, [_a], void 0, function* ({ userId }) {
|
||
if (helper.getFromUser(userId, PROMPT_CANCELLED) != null) {
|
||
yield helper.removeFromUser(userId, PROMPT_CANCELLED);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _46_delete_orphaned_biometric_prompt_data_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/47-move-desktop-settings.ts
|
||
var _47_move_desktop_settings_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const DESKTOP_SETTINGS_STATE = { name: "desktopSettings" };
|
||
const WINDOW_KEY = { key: "window", stateDefinition: DESKTOP_SETTINGS_STATE };
|
||
const CLOSE_TO_TRAY_KEY = {
|
||
key: "closeToTray",
|
||
stateDefinition: DESKTOP_SETTINGS_STATE,
|
||
};
|
||
const MINIMIZE_TO_TRAY_KEY = {
|
||
key: "minimizeToTray",
|
||
stateDefinition: DESKTOP_SETTINGS_STATE,
|
||
};
|
||
const START_TO_TRAY_KEY = {
|
||
key: "startToTray",
|
||
stateDefinition: DESKTOP_SETTINGS_STATE,
|
||
};
|
||
const TRAY_ENABLED_KEY = {
|
||
key: "trayEnabled",
|
||
stateDefinition: DESKTOP_SETTINGS_STATE,
|
||
};
|
||
const OPEN_AT_LOGIN_KEY = {
|
||
key: "openAtLogin",
|
||
stateDefinition: DESKTOP_SETTINGS_STATE,
|
||
};
|
||
const ALWAYS_SHOW_DOCK_KEY = {
|
||
key: "alwaysShowDock",
|
||
stateDefinition: DESKTOP_SETTINGS_STATE,
|
||
};
|
||
const ALWAYS_ON_TOP_KEY = {
|
||
key: "alwaysOnTop",
|
||
stateDefinition: DESKTOP_SETTINGS_STATE,
|
||
};
|
||
class _47_move_desktop_settings_MoveDesktopSettingsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _47_move_desktop_settings_awaiter(this, void 0, void 0, function* () {
|
||
const legacyGlobal = yield helper.get("global");
|
||
let updatedGlobal = false;
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.window) !== undefined) {
|
||
yield helper.setToGlobal(WINDOW_KEY, legacyGlobal.window);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.window;
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.enableCloseToTray) != null) {
|
||
yield helper.setToGlobal(CLOSE_TO_TRAY_KEY, legacyGlobal.enableCloseToTray);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.enableCloseToTray;
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.enableMinimizeToTray) != null) {
|
||
yield helper.setToGlobal(MINIMIZE_TO_TRAY_KEY, legacyGlobal.enableMinimizeToTray);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.enableMinimizeToTray;
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.enableStartToTray) != null) {
|
||
yield helper.setToGlobal(START_TO_TRAY_KEY, legacyGlobal.enableStartToTray);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.enableStartToTray;
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.enableTray) != null) {
|
||
yield helper.setToGlobal(TRAY_ENABLED_KEY, legacyGlobal.enableTray);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.enableTray;
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.openAtLogin) != null) {
|
||
yield helper.setToGlobal(OPEN_AT_LOGIN_KEY, legacyGlobal.openAtLogin);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.openAtLogin;
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.alwaysShowDock) != null) {
|
||
yield helper.setToGlobal(ALWAYS_SHOW_DOCK_KEY, legacyGlobal.alwaysShowDock);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.alwaysShowDock;
|
||
}
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.enableAlwaysOnTop) != null) {
|
||
yield helper.setToGlobal(ALWAYS_ON_TOP_KEY, legacyGlobal.enableAlwaysOnTop);
|
||
updatedGlobal = true;
|
||
delete legacyGlobal.enableAlwaysOnTop;
|
||
}
|
||
if (updatedGlobal) {
|
||
yield helper.set("global", legacyGlobal);
|
||
}
|
||
function migrateAccount(userId, account) {
|
||
return _47_move_desktop_settings_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
// We only migrate the global setting for this, if we find it on the account object
|
||
// just delete it.
|
||
if (((_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.enableAlwaysOnTop) != null) {
|
||
delete account.settings.enableAlwaysOnTop;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => migrateAccount(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
throw IRREVERSIBLE;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/48-move-ddg-to-state-provider.ts
|
||
var _48_move_ddg_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const DDG_KEY = {
|
||
key: "enableDuckDuckGoBrowserIntegration",
|
||
stateDefinition: {
|
||
name: "autofillSettings",
|
||
},
|
||
};
|
||
class _48_move_ddg_to_state_provider_MoveDdgToStateProviderMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _48_move_ddg_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
// global state
|
||
const global = yield helper.get("global");
|
||
if ((global === null || global === void 0 ? void 0 : global.enableDuckDuckGoBrowserIntegration) == null) {
|
||
return;
|
||
}
|
||
yield helper.setToGlobal(DDG_KEY, global.enableDuckDuckGoBrowserIntegration);
|
||
delete global.enableDuckDuckGoBrowserIntegration;
|
||
yield helper.set("global", global);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _48_move_ddg_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const enableDdg = yield helper.getFromGlobal(DDG_KEY);
|
||
if (!enableDdg) {
|
||
return;
|
||
}
|
||
const global = (_a = (yield helper.get("global"))) !== null && _a !== void 0 ? _a : {};
|
||
global.enableDuckDuckGoBrowserIntegration = enableDdg;
|
||
yield helper.set("global", global);
|
||
yield helper.removeFromGlobal(DDG_KEY);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/49-move-account-server-configs.ts
|
||
var _49_move_account_server_configs_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _49_move_account_server_configs_CONFIG_DISK = { name: "config" };
|
||
const USER_SERVER_CONFIG = {
|
||
stateDefinition: _49_move_account_server_configs_CONFIG_DISK,
|
||
key: "serverConfig",
|
||
};
|
||
class _49_move_account_server_configs_AccountServerConfigMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _49_move_account_server_configs_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _49_move_account_server_configs_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if (((_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.serverConfig) != null) {
|
||
yield helper.setToUser(userId, USER_SERVER_CONFIG, account.settings.serverConfig);
|
||
delete account.settings.serverConfig;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _49_move_account_server_configs_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _49_move_account_server_configs_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const serverConfig = yield helper.getFromUser(userId, USER_SERVER_CONFIG);
|
||
if (serverConfig) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_a = account.settings) !== null && _a !== void 0 ? _a : (account.settings = {});
|
||
account.settings.serverConfig = serverConfig;
|
||
yield helper.setToUser(userId, USER_SERVER_CONFIG, null);
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/5-add-key-type-to-org-keys.ts
|
||
var _5_add_key_type_to_org_keys_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _5_add_key_type_to_org_keys_AddKeyTypeToOrgKeysMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _5_add_key_type_to_org_keys_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function updateOrgKey(userId, account) {
|
||
return _5_add_key_type_to_org_keys_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const encryptedOrgKeys = (_b = (_a = account === null || account === void 0 ? void 0 : account.keys) === null || _a === void 0 ? void 0 : _a.organizationKeys) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (encryptedOrgKeys == null) {
|
||
return;
|
||
}
|
||
const newOrgKeys = {};
|
||
Object.entries(encryptedOrgKeys).forEach(([orgId, encKey]) => {
|
||
newOrgKeys[orgId] = {
|
||
type: "organization",
|
||
key: encKey,
|
||
};
|
||
});
|
||
account.keys.organizationKeys.encrypted = newOrgKeys;
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||
Promise.all(accounts.map(({ userId, account }) => updateOrgKey(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _5_add_key_type_to_org_keys_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function updateOrgKey(userId, account) {
|
||
return _5_add_key_type_to_org_keys_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const encryptedOrgKeys = (_b = (_a = account === null || account === void 0 ? void 0 : account.keys) === null || _a === void 0 ? void 0 : _a.organizationKeys) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (encryptedOrgKeys == null) {
|
||
return;
|
||
}
|
||
const newOrgKeys = {};
|
||
Object.entries(encryptedOrgKeys).forEach(([orgId, encKey]) => {
|
||
newOrgKeys[orgId] = encKey.key;
|
||
});
|
||
account.keys.organizationKeys.encrypted = newOrgKeys;
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||
Promise.all(accounts.map((_a) => _5_add_key_type_to_org_keys_awaiter(this, [_a], void 0, function* ({ userId, account }) { return updateOrgKey(userId, account); })));
|
||
});
|
||
}
|
||
// Override is necessary because default implementation assumes `stateVersion` at the root, but for this version
|
||
// it is nested inside a global object.
|
||
updateVersion(helper, direction) {
|
||
return _5_add_key_type_to_org_keys_awaiter(this, void 0, void 0, function* () {
|
||
const endVersion = direction === "up" ? this.toVersion : this.fromVersion;
|
||
helper.currentVersion = endVersion;
|
||
const global = (yield helper.get("global")) || {};
|
||
yield helper.set("global", Object.assign(Object.assign({}, global), { stateVersion: endVersion }));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/50-move-key-connector-to-state-provider.ts
|
||
var _50_move_key_connector_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const usesKeyConnectorKeyDefinition = {
|
||
key: "usesKeyConnector",
|
||
stateDefinition: {
|
||
name: "keyConnector",
|
||
},
|
||
};
|
||
const convertAccountToKeyConnectorKeyDefinition = {
|
||
key: "convertAccountToKeyConnector",
|
||
stateDefinition: {
|
||
name: "keyConnector",
|
||
},
|
||
};
|
||
class _50_move_key_connector_to_state_provider_KeyConnectorMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _50_move_key_connector_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _50_move_key_connector_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const usesKeyConnector = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.usesKeyConnector;
|
||
const convertAccountToKeyConnector = (_b = account === null || account === void 0 ? void 0 : account.profile) === null || _b === void 0 ? void 0 : _b.convertAccountToKeyConnector;
|
||
if (usesKeyConnector == null && convertAccountToKeyConnector == null) {
|
||
return;
|
||
}
|
||
if (usesKeyConnector != null) {
|
||
yield helper.setToUser(userId, usesKeyConnectorKeyDefinition, usesKeyConnector);
|
||
delete account.profile.usesKeyConnector;
|
||
}
|
||
if (convertAccountToKeyConnector != null) {
|
||
yield helper.setToUser(userId, convertAccountToKeyConnectorKeyDefinition, convertAccountToKeyConnector);
|
||
delete account.profile.convertAccountToKeyConnector;
|
||
}
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _50_move_key_connector_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _50_move_key_connector_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const usesKeyConnector = yield helper.getFromUser(userId, usesKeyConnectorKeyDefinition);
|
||
const convertAccountToKeyConnector = yield helper.getFromUser(userId, convertAccountToKeyConnectorKeyDefinition);
|
||
if (usesKeyConnector == null && convertAccountToKeyConnector == null) {
|
||
return;
|
||
}
|
||
if (usesKeyConnector != null) {
|
||
account.profile.usesKeyConnector = usesKeyConnector;
|
||
yield helper.setToUser(userId, usesKeyConnectorKeyDefinition, null);
|
||
}
|
||
if (convertAccountToKeyConnector != null) {
|
||
account.profile.convertAccountToKeyConnector = convertAccountToKeyConnector;
|
||
yield helper.setToUser(userId, convertAccountToKeyConnectorKeyDefinition, null);
|
||
}
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/51-move-remembered-email-to-state-providers.ts
|
||
var _51_move_remembered_email_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const LOGIN_EMAIL_STATE = { name: "loginEmail" };
|
||
const STORED_EMAIL = {
|
||
key: "storedEmail",
|
||
stateDefinition: LOGIN_EMAIL_STATE,
|
||
};
|
||
class _51_move_remembered_email_to_state_providers_RememberedEmailMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _51_move_remembered_email_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyGlobal = yield helper.get("global");
|
||
// Move global data
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.rememberedEmail) != null) {
|
||
yield helper.setToGlobal(STORED_EMAIL, legacyGlobal.rememberedEmail);
|
||
}
|
||
// Delete legacy global data
|
||
legacyGlobal === null || legacyGlobal === void 0 ? true : delete legacyGlobal.rememberedEmail;
|
||
yield helper.set("global", legacyGlobal);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _51_move_remembered_email_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
let legacyGlobal = yield helper.get("global");
|
||
let updatedLegacyGlobal = false;
|
||
const globalStoredEmail = yield helper.getFromGlobal(STORED_EMAIL);
|
||
if (globalStoredEmail) {
|
||
if (!legacyGlobal) {
|
||
legacyGlobal = {};
|
||
}
|
||
updatedLegacyGlobal = true;
|
||
legacyGlobal.rememberedEmail = globalStoredEmail;
|
||
yield helper.setToGlobal(STORED_EMAIL, null);
|
||
}
|
||
if (updatedLegacyGlobal) {
|
||
yield helper.set("global", legacyGlobal);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/52-delete-installed-version.ts
|
||
var _52_delete_installed_version_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _52_delete_installed_version_DeleteInstalledVersion extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _52_delete_installed_version_awaiter(this, void 0, void 0, function* () {
|
||
const legacyGlobal = yield helper.get("global");
|
||
if ((legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.installedVersion) != null) {
|
||
delete legacyGlobal.installedVersion;
|
||
yield helper.set("global", legacyGlobal);
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
throw IRREVERSIBLE;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/53-migrate-device-trust-svc-to-state-providers.ts
|
||
var _53_migrate_device_trust_svc_to_state_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const DEVICE_KEY = {
|
||
key: "deviceKey", // matches KeyDefinition.key in DeviceTrustService
|
||
stateDefinition: {
|
||
name: "deviceTrust", // matches StateDefinition.name in StateDefinitions
|
||
},
|
||
};
|
||
const SHOULD_TRUST_DEVICE = {
|
||
key: "shouldTrustDevice",
|
||
stateDefinition: {
|
||
name: "deviceTrust",
|
||
},
|
||
};
|
||
class _53_migrate_device_trust_svc_to_state_providers_DeviceTrustServiceStateProviderMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _53_migrate_device_trust_svc_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _53_migrate_device_trust_svc_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
let updatedAccount = false;
|
||
// Migrate deviceKey
|
||
const existingDeviceKey = (_a = account === null || account === void 0 ? void 0 : account.keys) === null || _a === void 0 ? void 0 : _a.deviceKey;
|
||
if (existingDeviceKey != null) {
|
||
// Only migrate data that exists
|
||
yield helper.setToUser(userId, DEVICE_KEY, existingDeviceKey);
|
||
delete account.keys.deviceKey;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate shouldTrustDevice
|
||
const existingShouldTrustDevice = (_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.trustDeviceChoiceForDecryption;
|
||
if (existingShouldTrustDevice != null) {
|
||
yield helper.setToUser(userId, SHOULD_TRUST_DEVICE, existingShouldTrustDevice);
|
||
delete account.settings.trustDeviceChoiceForDecryption;
|
||
updatedAccount = true;
|
||
}
|
||
if (updatedAccount) {
|
||
// Save the migrated account
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _53_migrate_device_trust_svc_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _53_migrate_device_trust_svc_to_state_providers_awaiter(this, void 0, void 0, function* () {
|
||
// Rollback deviceKey
|
||
const migratedDeviceKey = yield helper.getFromUser(userId, DEVICE_KEY);
|
||
if ((account === null || account === void 0 ? void 0 : account.keys) && migratedDeviceKey != null) {
|
||
account.keys.deviceKey = migratedDeviceKey;
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, DEVICE_KEY, null);
|
||
// Rollback shouldTrustDevice
|
||
const migratedShouldTrustDevice = yield helper.getFromUser(userId, SHOULD_TRUST_DEVICE);
|
||
if ((account === null || account === void 0 ? void 0 : account.settings) && migratedShouldTrustDevice != null) {
|
||
account.settings.trustDeviceChoiceForDecryption = migratedShouldTrustDevice;
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, SHOULD_TRUST_DEVICE, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/54-move-encrypted-sends.ts
|
||
var _54_move_encrypted_sends_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var SendType;
|
||
(function (SendType) {
|
||
SendType[SendType["Text"] = 0] = "Text";
|
||
SendType[SendType["File"] = 1] = "File";
|
||
})(SendType || (SendType = {}));
|
||
const ENCRYPTED_SENDS = {
|
||
stateDefinition: {
|
||
name: "send",
|
||
},
|
||
key: "sends",
|
||
};
|
||
/**
|
||
* Only encrypted sends are stored on disk. Only the encrypted items need to be
|
||
* migrated from the previous sends state data.
|
||
*/
|
||
class _54_move_encrypted_sends_SendMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _54_move_encrypted_sends_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _54_move_encrypted_sends_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
const value = (_b = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.sends) === null || _b === void 0 ? void 0 : _b.encrypted;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, ENCRYPTED_SENDS, value);
|
||
delete account.data.sends;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _54_move_encrypted_sends_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _54_move_encrypted_sends_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, ENCRYPTED_SENDS);
|
||
if (account) {
|
||
account.data = Object.assign((_a = account.data) !== null && _a !== void 0 ? _a : {}, {
|
||
sends: {
|
||
encrypted: value,
|
||
},
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, ENCRYPTED_SENDS, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/55-move-master-key-state-to-provider.ts
|
||
var _55_move_master_key_state_to_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const FORCE_SET_PASSWORD_REASON_DEFINITION = {
|
||
key: "forceSetPasswordReason",
|
||
stateDefinition: {
|
||
name: "masterPassword",
|
||
},
|
||
};
|
||
const MASTER_KEY_HASH_DEFINITION = {
|
||
key: "masterKeyHash",
|
||
stateDefinition: {
|
||
name: "masterPassword",
|
||
},
|
||
};
|
||
const MASTER_KEY_ENCRYPTED_USER_KEY_DEFINITION = {
|
||
key: "masterKeyEncryptedUserKey",
|
||
stateDefinition: {
|
||
name: "masterPassword",
|
||
},
|
||
};
|
||
class _55_move_master_key_state_to_provider_MoveMasterKeyStateToProviderMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _55_move_master_key_state_to_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _55_move_master_key_state_to_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c;
|
||
const forceSetPasswordReason = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.forceSetPasswordReason;
|
||
if (forceSetPasswordReason != null) {
|
||
yield helper.setToUser(userId, FORCE_SET_PASSWORD_REASON_DEFINITION, forceSetPasswordReason);
|
||
delete account.profile.forceSetPasswordReason;
|
||
yield helper.set(userId, account);
|
||
}
|
||
const masterKeyHash = (_b = account === null || account === void 0 ? void 0 : account.profile) === null || _b === void 0 ? void 0 : _b.keyHash;
|
||
if (masterKeyHash != null) {
|
||
yield helper.setToUser(userId, MASTER_KEY_HASH_DEFINITION, masterKeyHash);
|
||
delete account.profile.keyHash;
|
||
yield helper.set(userId, account);
|
||
}
|
||
const masterKeyEncryptedUserKey = (_c = account === null || account === void 0 ? void 0 : account.keys) === null || _c === void 0 ? void 0 : _c.masterKeyEncryptedUserKey;
|
||
if (masterKeyEncryptedUserKey != null) {
|
||
yield helper.setToUser(userId, MASTER_KEY_ENCRYPTED_USER_KEY_DEFINITION, masterKeyEncryptedUserKey);
|
||
delete account.keys.masterKeyEncryptedUserKey;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _55_move_master_key_state_to_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _55_move_master_key_state_to_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c;
|
||
const forceSetPasswordReason = yield helper.getFromUser(userId, FORCE_SET_PASSWORD_REASON_DEFINITION);
|
||
const masterKeyHash = yield helper.getFromUser(userId, MASTER_KEY_HASH_DEFINITION);
|
||
const masterKeyEncryptedUserKey = yield helper.getFromUser(userId, MASTER_KEY_ENCRYPTED_USER_KEY_DEFINITION);
|
||
if (account != null) {
|
||
if (forceSetPasswordReason != null) {
|
||
account.profile = Object.assign((_a = account.profile) !== null && _a !== void 0 ? _a : {}, {
|
||
forceSetPasswordReason,
|
||
});
|
||
}
|
||
if (masterKeyHash != null) {
|
||
account.profile = Object.assign((_b = account.profile) !== null && _b !== void 0 ? _b : {}, {
|
||
keyHash: masterKeyHash,
|
||
});
|
||
}
|
||
if (masterKeyEncryptedUserKey != null) {
|
||
account.keys = Object.assign((_c = account.keys) !== null && _c !== void 0 ? _c : {}, {
|
||
masterKeyEncryptedUserKey,
|
||
});
|
||
}
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, FORCE_SET_PASSWORD_REASON_DEFINITION, null);
|
||
yield helper.setToUser(userId, MASTER_KEY_HASH_DEFINITION, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/56-move-auth-requests.ts
|
||
var _56_move_auth_requests_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const ADMIN_AUTH_REQUEST_KEY = {
|
||
stateDefinition: {
|
||
name: "authRequestLocal",
|
||
},
|
||
key: "adminAuthRequest",
|
||
};
|
||
const ACCEPT_AUTH_REQUESTS_KEY = {
|
||
stateDefinition: {
|
||
name: "authRequestLocal",
|
||
},
|
||
key: "acceptAuthRequests",
|
||
};
|
||
class _56_move_auth_requests_AuthRequestMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _56_move_auth_requests_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _56_move_auth_requests_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
let updatedAccount = false;
|
||
// Migrate admin auth request
|
||
const existingAdminAuthRequest = account === null || account === void 0 ? void 0 : account.adminAuthRequest;
|
||
if (existingAdminAuthRequest != null) {
|
||
yield helper.setToUser(userId, ADMIN_AUTH_REQUEST_KEY, existingAdminAuthRequest);
|
||
delete account.adminAuthRequest;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate approve login requests
|
||
const existingApproveLoginRequests = (_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.approveLoginRequests;
|
||
if (existingApproveLoginRequests != null) {
|
||
yield helper.setToUser(userId, ACCEPT_AUTH_REQUESTS_KEY, existingApproveLoginRequests);
|
||
delete account.settings.approveLoginRequests;
|
||
updatedAccount = true;
|
||
}
|
||
if (updatedAccount) {
|
||
// Save the migrated account
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _56_move_auth_requests_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _56_move_auth_requests_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
let updatedAccount = false;
|
||
// Rollback admin auth request
|
||
const migratedAdminAuthRequest = yield helper.getFromUser(userId, ADMIN_AUTH_REQUEST_KEY);
|
||
if (migratedAdminAuthRequest != null) {
|
||
account.adminAuthRequest = migratedAdminAuthRequest;
|
||
updatedAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, ADMIN_AUTH_REQUEST_KEY, null);
|
||
// Rollback approve login requests
|
||
const migratedAcceptAuthRequest = yield helper.getFromUser(userId, ACCEPT_AUTH_REQUESTS_KEY);
|
||
if (migratedAcceptAuthRequest != null) {
|
||
account.settings = Object.assign((_a = account.settings) !== null && _a !== void 0 ? _a : {}, {
|
||
approveLoginRequests: migratedAcceptAuthRequest,
|
||
});
|
||
updatedAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, ACCEPT_AUTH_REQUESTS_KEY, null);
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/57-move-cipher-service-to-state-provider.ts
|
||
var _57_move_cipher_service_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _57_move_cipher_service_to_state_provider_CIPHERS_DISK_LOCAL = {
|
||
key: "localData",
|
||
stateDefinition: {
|
||
name: "ciphersLocal",
|
||
},
|
||
};
|
||
const _57_move_cipher_service_to_state_provider_CIPHERS_DISK = {
|
||
key: "ciphers",
|
||
stateDefinition: {
|
||
name: "ciphers",
|
||
},
|
||
};
|
||
class _57_move_cipher_service_to_state_provider_CipherServiceMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _57_move_cipher_service_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _57_move_cipher_service_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c;
|
||
let updatedAccount = false;
|
||
//Migrate localData
|
||
const localData = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.localData;
|
||
if (localData != null) {
|
||
yield helper.setToUser(userId, _57_move_cipher_service_to_state_provider_CIPHERS_DISK_LOCAL, localData);
|
||
delete account.data.localData;
|
||
updatedAccount = true;
|
||
}
|
||
//Migrate ciphers
|
||
const ciphers = (_c = (_b = account === null || account === void 0 ? void 0 : account.data) === null || _b === void 0 ? void 0 : _b.ciphers) === null || _c === void 0 ? void 0 : _c.encrypted;
|
||
if (ciphers != null) {
|
||
yield helper.setToUser(userId, _57_move_cipher_service_to_state_provider_CIPHERS_DISK, ciphers);
|
||
delete account.data.ciphers;
|
||
updatedAccount = true;
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _57_move_cipher_service_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _57_move_cipher_service_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
//rollback localData
|
||
const localData = yield helper.getFromUser(userId, _57_move_cipher_service_to_state_provider_CIPHERS_DISK_LOCAL);
|
||
if (account.data && localData != null) {
|
||
account.data.localData = localData;
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, _57_move_cipher_service_to_state_provider_CIPHERS_DISK_LOCAL, null);
|
||
//rollback ciphers
|
||
const ciphers = yield helper.getFromUser(userId, _57_move_cipher_service_to_state_provider_CIPHERS_DISK);
|
||
if (account.data && ciphers != null) {
|
||
(_a = account.data).ciphers || (_a.ciphers = { encrypted: null });
|
||
account.data.ciphers.encrypted = ciphers;
|
||
yield helper.set(userId, account);
|
||
}
|
||
yield helper.setToUser(userId, _57_move_cipher_service_to_state_provider_CIPHERS_DISK, null);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/58-remove-refresh-token-migrated-state-provider-flag.ts
|
||
var _58_remove_refresh_token_migrated_state_provider_flag_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const REFRESH_TOKEN_MIGRATED_TO_SECURE_STORAGE = {
|
||
key: "refreshTokenMigratedToSecureStorage", // matches KeyDefinition.key
|
||
stateDefinition: {
|
||
name: "token", // matches StateDefinition.name in StateDefinitions
|
||
},
|
||
};
|
||
class _58_remove_refresh_token_migrated_state_provider_flag_RemoveRefreshTokenMigratedFlagMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _58_remove_refresh_token_migrated_state_provider_flag_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _58_remove_refresh_token_migrated_state_provider_flag_awaiter(this, void 0, void 0, function* () {
|
||
const refreshTokenMigratedFlag = yield helper.getFromUser(userId, REFRESH_TOKEN_MIGRATED_TO_SECURE_STORAGE);
|
||
if (refreshTokenMigratedFlag != null) {
|
||
// Only delete the flag if it exists
|
||
yield helper.removeFromUser(userId, REFRESH_TOKEN_MIGRATED_TO_SECURE_STORAGE);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _58_remove_refresh_token_migrated_state_provider_flag_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/59-move-kdf-config-to-state-provider.ts
|
||
var _59_move_kdf_config_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var KdfType;
|
||
(function (KdfType) {
|
||
KdfType[KdfType["PBKDF2_SHA256"] = 0] = "PBKDF2_SHA256";
|
||
KdfType[KdfType["Argon2id"] = 1] = "Argon2id";
|
||
})(KdfType || (KdfType = {}));
|
||
class KdfConfig {
|
||
}
|
||
const kdfConfigKeyDefinition = {
|
||
key: "kdfConfig",
|
||
stateDefinition: {
|
||
name: "kdfConfig",
|
||
},
|
||
};
|
||
class _59_move_kdf_config_to_state_provider_KdfConfigMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _59_move_kdf_config_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _59_move_kdf_config_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c, _d, _e, _f, _g, _h;
|
||
const iterations = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.kdfIterations;
|
||
const kdfType = (_b = account === null || account === void 0 ? void 0 : account.profile) === null || _b === void 0 ? void 0 : _b.kdfType;
|
||
const memory = (_c = account === null || account === void 0 ? void 0 : account.profile) === null || _c === void 0 ? void 0 : _c.kdfMemory;
|
||
const parallelism = (_d = account === null || account === void 0 ? void 0 : account.profile) === null || _d === void 0 ? void 0 : _d.kdfParallelism;
|
||
const kdfConfig = {
|
||
iterations: iterations,
|
||
kdfType: kdfType,
|
||
memory: memory,
|
||
parallelism: parallelism,
|
||
};
|
||
if (kdfConfig != null) {
|
||
yield helper.setToUser(userId, kdfConfigKeyDefinition, kdfConfig);
|
||
(_e = account === null || account === void 0 ? void 0 : account.profile) === null || _e === void 0 ? true : delete _e.kdfIterations;
|
||
(_f = account === null || account === void 0 ? void 0 : account.profile) === null || _f === void 0 ? true : delete _f.kdfType;
|
||
(_g = account === null || account === void 0 ? void 0 : account.profile) === null || _g === void 0 ? true : delete _g.kdfMemory;
|
||
(_h = account === null || account === void 0 ? void 0 : account.profile) === null || _h === void 0 ? true : delete _h.kdfParallelism;
|
||
}
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _59_move_kdf_config_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _59_move_kdf_config_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const kdfConfig = yield helper.getFromUser(userId, kdfConfigKeyDefinition);
|
||
if (kdfConfig != null) {
|
||
account.profile.kdfIterations = kdfConfig.iterations;
|
||
account.profile.kdfType = kdfConfig.kdfType;
|
||
account.profile.kdfMemory = kdfConfig.memory;
|
||
account.profile.kdfParallelism = kdfConfig.parallelism;
|
||
yield helper.setToUser(userId, kdfConfigKeyDefinition, null);
|
||
}
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/6-remove-legacy-etm-key.ts
|
||
var _6_remove_legacy_etm_key_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _6_remove_legacy_etm_key_RemoveLegacyEtmKeyMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _6_remove_legacy_etm_key_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function updateAccount(userId, account) {
|
||
return _6_remove_legacy_etm_key_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if ((_a = account === null || account === void 0 ? void 0 : account.keys) === null || _a === void 0 ? void 0 : _a.legacyEtmKey) {
|
||
delete account.keys.legacyEtmKey;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all(accounts.map(({ userId, account }) => updateAccount(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _6_remove_legacy_etm_key_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
// Override is necessary because default implementation assumes `stateVersion` at the root, but for this version
|
||
// it is nested inside a global object.
|
||
updateVersion(helper, direction) {
|
||
return _6_remove_legacy_etm_key_awaiter(this, void 0, void 0, function* () {
|
||
const endVersion = direction === "up" ? this.toVersion : this.fromVersion;
|
||
helper.currentVersion = endVersion;
|
||
const global = (yield helper.get("global")) || {};
|
||
yield helper.set("global", Object.assign(Object.assign({}, global), { stateVersion: endVersion }));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/60-known-accounts.ts
|
||
var _60_known_accounts_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const ACCOUNT_ACCOUNTS = {
|
||
stateDefinition: {
|
||
name: "account",
|
||
},
|
||
key: "accounts",
|
||
};
|
||
const ACCOUNT_ACTIVE_ACCOUNT_ID = {
|
||
stateDefinition: {
|
||
name: "account",
|
||
},
|
||
key: "activeAccountId",
|
||
};
|
||
const ACCOUNT_ACTIVITY = {
|
||
stateDefinition: {
|
||
name: "account",
|
||
},
|
||
key: "activity",
|
||
};
|
||
class _60_known_accounts_KnownAccountsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _60_known_accounts_awaiter(this, void 0, void 0, function* () {
|
||
yield this.migrateAuthenticatedAccounts(helper);
|
||
yield this.migrateActiveAccountId(helper);
|
||
yield this.migrateAccountActivity(helper);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _60_known_accounts_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
// authenticated account are removed, but the accounts record also contains logged out accounts. Best we can do is to add them all back
|
||
const userIds = (_a = (yield helper.getKnownUserIds())) !== null && _a !== void 0 ? _a : [];
|
||
yield helper.set("authenticatedAccounts", userIds);
|
||
yield helper.removeFromGlobal(ACCOUNT_ACCOUNTS);
|
||
// Active Account Id
|
||
const activeAccountId = yield helper.getFromGlobal(ACCOUNT_ACTIVE_ACCOUNT_ID);
|
||
if (activeAccountId) {
|
||
yield helper.set("activeUserId", activeAccountId);
|
||
}
|
||
yield helper.removeFromGlobal(ACCOUNT_ACTIVE_ACCOUNT_ID);
|
||
// Account Activity
|
||
const accountActivity = yield helper.getFromGlobal(ACCOUNT_ACTIVITY);
|
||
if (accountActivity) {
|
||
const toStore = Object.entries(accountActivity).reduce((agg, [userId, dateString]) => {
|
||
agg[userId] = new Date(dateString).getTime();
|
||
return agg;
|
||
}, {});
|
||
yield helper.set("accountActivity", toStore);
|
||
}
|
||
yield helper.removeFromGlobal(ACCOUNT_ACTIVITY);
|
||
});
|
||
}
|
||
migrateAuthenticatedAccounts(helper) {
|
||
return _60_known_accounts_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const authenticatedAccounts = (_a = (yield helper.get("authenticatedAccounts"))) !== null && _a !== void 0 ? _a : [];
|
||
const accounts = yield Promise.all(authenticatedAccounts.map((userId) => _60_known_accounts_awaiter(this, void 0, void 0, function* () {
|
||
const account = yield helper.get(userId);
|
||
return { userId, account };
|
||
})));
|
||
const accountsToStore = accounts.reduce((agg, { userId, account }) => {
|
||
var _a, _b;
|
||
if (account === null || account === void 0 ? void 0 : account.profile) {
|
||
agg[userId] = {
|
||
email: (_a = account.profile.email) !== null && _a !== void 0 ? _a : "",
|
||
emailVerified: (_b = account.profile.emailVerified) !== null && _b !== void 0 ? _b : false,
|
||
name: account.profile.name,
|
||
};
|
||
}
|
||
return agg;
|
||
}, {});
|
||
yield helper.setToGlobal(ACCOUNT_ACCOUNTS, accountsToStore);
|
||
yield helper.remove("authenticatedAccounts");
|
||
});
|
||
}
|
||
migrateAccountActivity(helper) {
|
||
return _60_known_accounts_awaiter(this, void 0, void 0, function* () {
|
||
const stored = yield helper.get("accountActivity");
|
||
const accountActivity = Object.entries(stored !== null && stored !== void 0 ? stored : {}).reduce((agg, [userId, dateMs]) => {
|
||
agg[userId] = JSON.stringify(new Date(dateMs));
|
||
return agg;
|
||
}, {});
|
||
yield helper.setToGlobal(ACCOUNT_ACTIVITY, accountActivity);
|
||
yield helper.remove("accountActivity");
|
||
});
|
||
}
|
||
migrateActiveAccountId(helper) {
|
||
return _60_known_accounts_awaiter(this, void 0, void 0, function* () {
|
||
const activeAccountId = yield helper.get("activeUserId");
|
||
yield helper.setToGlobal(ACCOUNT_ACTIVE_ACCOUNT_ID, activeAccountId);
|
||
yield helper.remove("activeUserId");
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/61-move-pin-state-to-providers.ts
|
||
var _61_move_pin_state_to_providers_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const PIN_STATE = { name: "pinUnlock" };
|
||
const PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT = {
|
||
stateDefinition: PIN_STATE,
|
||
key: "pinKeyEncryptedUserKeyPersistent",
|
||
};
|
||
const USER_KEY_ENCRYPTED_PIN = {
|
||
stateDefinition: PIN_STATE,
|
||
key: "userKeyEncryptedPin",
|
||
};
|
||
const OLD_PIN_KEY_ENCRYPTED_MASTER_KEY = {
|
||
stateDefinition: PIN_STATE,
|
||
key: "oldPinKeyEncryptedMasterKey",
|
||
};
|
||
class _61_move_pin_state_to_providers_PinStateMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _61_move_pin_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
const legacyAccounts = yield helper.getAccounts();
|
||
let updatedAccount = false;
|
||
function migrateAccount(userId, account) {
|
||
return _61_move_pin_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c, _d;
|
||
// Migrate pinKeyEncryptedUserKey (to `pinKeyEncryptedUserKeyPersistent`)
|
||
if (((_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.pinKeyEncryptedUserKey) != null) {
|
||
yield helper.setToUser(userId, PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT, account.settings.pinKeyEncryptedUserKey);
|
||
delete account.settings.pinKeyEncryptedUserKey;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate protectedPin (to `userKeyEncryptedPin`)
|
||
if (((_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? void 0 : _b.protectedPin) != null) {
|
||
yield helper.setToUser(userId, USER_KEY_ENCRYPTED_PIN, account.settings.protectedPin);
|
||
delete account.settings.protectedPin;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate pinProtected (to `oldPinKeyEncryptedMasterKey`)
|
||
if (((_d = (_c = account === null || account === void 0 ? void 0 : account.settings) === null || _c === void 0 ? void 0 : _c.pinProtected) === null || _d === void 0 ? void 0 : _d.encrypted) != null) {
|
||
yield helper.setToUser(userId, OLD_PIN_KEY_ENCRYPTED_MASTER_KEY, account.settings.pinProtected.encrypted);
|
||
delete account.settings.pinProtected;
|
||
updatedAccount = true;
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([
|
||
...legacyAccounts.map(({ userId, account }) => migrateAccount(userId, account)),
|
||
]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _61_move_pin_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _61_move_pin_state_to_providers_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
let updatedAccount = false;
|
||
const accountPinKeyEncryptedUserKeyPersistent = yield helper.getFromUser(userId, PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT);
|
||
const accountUserKeyEncryptedPin = yield helper.getFromUser(userId, USER_KEY_ENCRYPTED_PIN);
|
||
const accountOldPinKeyEncryptedMasterKey = yield helper.getFromUser(userId, OLD_PIN_KEY_ENCRYPTED_MASTER_KEY);
|
||
if (!account) {
|
||
account = {};
|
||
}
|
||
if (accountPinKeyEncryptedUserKeyPersistent != null) {
|
||
account.settings.pinKeyEncryptedUserKey = accountPinKeyEncryptedUserKeyPersistent;
|
||
yield helper.setToUser(userId, PIN_KEY_ENCRYPTED_USER_KEY_PERSISTENT, null);
|
||
updatedAccount = true;
|
||
}
|
||
if (accountUserKeyEncryptedPin != null) {
|
||
account.settings.protectedPin = accountUserKeyEncryptedPin;
|
||
yield helper.setToUser(userId, USER_KEY_ENCRYPTED_PIN, null);
|
||
updatedAccount = true;
|
||
}
|
||
if (accountOldPinKeyEncryptedMasterKey != null) {
|
||
account.settings = Object.assign((_a = account.settings) !== null && _a !== void 0 ? _a : {}, {
|
||
pinProtected: {
|
||
encrypted: accountOldPinKeyEncryptedMasterKey,
|
||
},
|
||
});
|
||
yield helper.setToUser(userId, OLD_PIN_KEY_ENCRYPTED_MASTER_KEY, null);
|
||
updatedAccount = true;
|
||
}
|
||
if (updatedAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackAccount(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/62-migrate-vault-timeout-settings-svc-to-state-provider.ts
|
||
var _62_migrate_vault_timeout_settings_svc_to_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const VAULT_TIMEOUT_SETTINGS_STATE_DEF_LIKE = {
|
||
name: "vaultTimeoutSettings",
|
||
};
|
||
const VAULT_TIMEOUT = {
|
||
key: "vaultTimeout", // matches KeyDefinition.key
|
||
stateDefinition: VAULT_TIMEOUT_SETTINGS_STATE_DEF_LIKE,
|
||
};
|
||
const VAULT_TIMEOUT_ACTION = {
|
||
key: "vaultTimeoutAction", // matches KeyDefinition.key
|
||
stateDefinition: VAULT_TIMEOUT_SETTINGS_STATE_DEF_LIKE,
|
||
};
|
||
// Define mapping of old values to new values for migration purposes
|
||
const vaultTimeoutTypeMigrateRecord = {
|
||
null: "never",
|
||
"-1": "onRestart",
|
||
"-2": "onLocked",
|
||
"-3": "onSleep",
|
||
"-4": "onIdle",
|
||
};
|
||
// define mapping of new values to old values for rollback purposes
|
||
const vaultTimeoutTypeRollbackRecord = {
|
||
never: null,
|
||
onRestart: -1,
|
||
onLocked: -2,
|
||
onSleep: -3,
|
||
onIdle: -4,
|
||
};
|
||
// FIXME: update to use a const object instead of a typescript enum
|
||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||
var _62_migrate_vault_timeout_settings_svc_to_state_provider_ClientType;
|
||
(function (ClientType) {
|
||
ClientType["Web"] = "web";
|
||
ClientType["Browser"] = "browser";
|
||
ClientType["Desktop"] = "desktop";
|
||
ClientType["Cli"] = "cli";
|
||
})(_62_migrate_vault_timeout_settings_svc_to_state_provider_ClientType || (_62_migrate_vault_timeout_settings_svc_to_state_provider_ClientType = {}));
|
||
class _62_migrate_vault_timeout_settings_svc_to_state_provider_VaultTimeoutSettingsServiceStateProviderMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _62_migrate_vault_timeout_settings_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const globalData = yield helper.get("global");
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _62_migrate_vault_timeout_settings_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c, _d;
|
||
let updatedAccount = false;
|
||
// Migrate vault timeout
|
||
let existingVaultTimeout = (_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.vaultTimeout;
|
||
if (helper.clientType === _62_migrate_vault_timeout_settings_svc_to_state_provider_ClientType.Cli && existingVaultTimeout === undefined) {
|
||
// The CLI does not set a vault timeout by default so we need to set it to null
|
||
// so that the migration can migrate null to "never" as the CLI does not have a vault timeout.
|
||
existingVaultTimeout = null;
|
||
}
|
||
if (existingVaultTimeout !== undefined) {
|
||
// check undefined so that we allow null values (previously meant never timeout)
|
||
// Only migrate data that exists
|
||
if (existingVaultTimeout === null || existingVaultTimeout < 0) {
|
||
// Map null or negative values to new string values
|
||
const newVaultTimeout = vaultTimeoutTypeMigrateRecord[existingVaultTimeout];
|
||
yield helper.setToUser(userId, VAULT_TIMEOUT, newVaultTimeout);
|
||
}
|
||
else {
|
||
// Persist positive numbers as is
|
||
yield helper.setToUser(userId, VAULT_TIMEOUT, existingVaultTimeout);
|
||
}
|
||
(_b = account === null || account === void 0 ? void 0 : account.settings) === null || _b === void 0 ? true : delete _b.vaultTimeout;
|
||
updatedAccount = true;
|
||
}
|
||
// Migrate vault timeout action
|
||
const existingVaultTimeoutAction = (_c = account === null || account === void 0 ? void 0 : account.settings) === null || _c === void 0 ? void 0 : _c.vaultTimeoutAction;
|
||
if (existingVaultTimeoutAction != null) {
|
||
// Only migrate data that exists
|
||
yield helper.setToUser(userId, VAULT_TIMEOUT_ACTION, existingVaultTimeoutAction);
|
||
(_d = account === null || account === void 0 ? void 0 : account.settings) === null || _d === void 0 ? true : delete _d.vaultTimeoutAction;
|
||
updatedAccount = true;
|
||
}
|
||
// Note: we are explicitly not worrying about mapping over the global fallback vault timeout / action
|
||
// into the new state provider framework. It was originally a fallback but hasn't been used for years
|
||
// so this migration will clean up the global properties fully.
|
||
if (updatedAccount) {
|
||
// Save the migrated account only if it was updated
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
// Delete global data (works for browser extension and web; CLI doesn't have these as global settings).
|
||
globalData === null || globalData === void 0 ? true : delete globalData.vaultTimeout;
|
||
globalData === null || globalData === void 0 ? true : delete globalData.vaultTimeoutAction;
|
||
yield helper.set("global", globalData);
|
||
// Remove desktop only settings. These aren't found by the above global key removal b/c of
|
||
// the different storage key format. This removal does not cause any issues on migrating for other clients.
|
||
yield helper.remove("global\\.vaultTimeout");
|
||
yield helper.remove("global\\.vaultTimeoutAction");
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _62_migrate_vault_timeout_settings_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function rollbackAccount(userId, account) {
|
||
return _62_migrate_vault_timeout_settings_svc_to_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
let updatedLegacyAccount = false;
|
||
// Rollback vault timeout
|
||
const migratedVaultTimeout = yield helper.getFromUser(userId, VAULT_TIMEOUT);
|
||
if ((account === null || account === void 0 ? void 0 : account.settings) && migratedVaultTimeout != null) {
|
||
if (typeof migratedVaultTimeout === "string") {
|
||
// Map new string values back to old values
|
||
account.settings.vaultTimeout = vaultTimeoutTypeRollbackRecord[migratedVaultTimeout];
|
||
}
|
||
else {
|
||
// persist numbers as is
|
||
account.settings.vaultTimeout = migratedVaultTimeout;
|
||
}
|
||
updatedLegacyAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, VAULT_TIMEOUT, null);
|
||
// Rollback vault timeout action
|
||
const migratedVaultTimeoutAction = yield helper.getFromUser(userId, VAULT_TIMEOUT_ACTION);
|
||
if ((account === null || account === void 0 ? void 0 : account.settings) && migratedVaultTimeoutAction != null) {
|
||
account.settings.vaultTimeoutAction = migratedVaultTimeoutAction;
|
||
updatedLegacyAccount = true;
|
||
}
|
||
yield helper.setToUser(userId, VAULT_TIMEOUT_ACTION, null);
|
||
if (updatedLegacyAccount) {
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/63-migrate-password-settings.ts
|
||
var _63_migrate_password_settings_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const NAVIGATION = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "generatorSettings",
|
||
};
|
||
const PASSWORD = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "passwordGeneratorSettings",
|
||
};
|
||
const PASSPHRASE = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "passphraseGeneratorSettings",
|
||
};
|
||
class _63_migrate_password_settings_PasswordOptionsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _63_migrate_password_settings_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _63_migrate_password_settings_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const legacyOptions = (_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.passwordGenerationOptions;
|
||
if (legacyOptions) {
|
||
const converted = convertSettings(legacyOptions);
|
||
yield storeSettings(helper, userId, converted);
|
||
yield deleteSettings(helper, userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _63_migrate_password_settings_awaiter(this, void 0, void 0, function* () {
|
||
// not supported
|
||
});
|
||
}
|
||
}
|
||
function convertSettings(options) {
|
||
const password = {
|
||
length: options.length,
|
||
ambiguous: options.ambiguous,
|
||
uppercase: options.uppercase,
|
||
minUppercase: options.minUppercase,
|
||
lowercase: options.lowercase,
|
||
minLowercase: options.minLowercase,
|
||
number: options.number,
|
||
minNumber: options.minNumber,
|
||
special: options.special,
|
||
minSpecial: options.minSpecial,
|
||
};
|
||
const generator = {
|
||
type: options.type,
|
||
};
|
||
const passphrase = {
|
||
numWords: options.numWords,
|
||
wordSeparator: options.wordSeparator,
|
||
capitalize: options.capitalize,
|
||
includeNumber: options.includeNumber,
|
||
};
|
||
return { generator, password, passphrase };
|
||
}
|
||
function storeSettings(helper, userId, converted) {
|
||
return _63_migrate_password_settings_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const existing = (_a = (yield helper.getFromUser(userId, NAVIGATION))) !== null && _a !== void 0 ? _a : {};
|
||
const updated = Object.assign(existing, converted.generator);
|
||
yield Promise.all([
|
||
helper.setToUser(userId, NAVIGATION, updated),
|
||
helper.setToUser(userId, PASSPHRASE, converted.passphrase),
|
||
helper.setToUser(userId, PASSWORD, converted.password),
|
||
]);
|
||
});
|
||
}
|
||
function deleteSettings(helper, userId, account) {
|
||
return _63_migrate_password_settings_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
(_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? true : delete _a.passwordGenerationOptions;
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/64-migrate-generator-history.ts
|
||
var _64_migrate_generator_history_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const HISTORY = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "localGeneratorHistoryBuffer",
|
||
};
|
||
class _64_migrate_generator_history_GeneratorHistoryMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _64_migrate_generator_history_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _64_migrate_generator_history_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const data = (_a = account === null || account === void 0 ? void 0 : account.data) === null || _a === void 0 ? void 0 : _a.passwordGenerationHistory;
|
||
if (data && data.encrypted) {
|
||
yield helper.setToUser(userId, HISTORY, data.encrypted);
|
||
delete account.data.passwordGenerationHistory;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _64_migrate_generator_history_awaiter(this, void 0, void 0, function* () {
|
||
// not supported
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/65-migrate-forwarder-settings.ts
|
||
var _65_migrate_forwarder_settings_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _65_migrate_forwarder_settings_NAVIGATION = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "generatorSettings",
|
||
};
|
||
const CATCHALL = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "catchallGeneratorSettings",
|
||
};
|
||
const EFF_USERNAME = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "effUsernameGeneratorSettings",
|
||
};
|
||
const SUBADDRESS = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "subaddressGeneratorSettings",
|
||
};
|
||
const ADDY_IO = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "addyIoBuffer",
|
||
};
|
||
const DUCK_DUCK_GO = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "duckDuckGoBuffer",
|
||
};
|
||
const FASTMAIL = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "fastmailBuffer",
|
||
};
|
||
const FIREFOX_RELAY = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "firefoxRelayBuffer",
|
||
};
|
||
const FORWARD_EMAIL = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "forwardEmailBuffer",
|
||
};
|
||
const SIMPLE_LOGIN = {
|
||
stateDefinition: {
|
||
name: "generator",
|
||
},
|
||
key: "simpleLoginBuffer",
|
||
};
|
||
class _65_migrate_forwarder_settings_ForwarderOptionsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _65_migrate_forwarder_settings_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _65_migrate_forwarder_settings_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const legacyOptions = (_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.usernameGenerationOptions;
|
||
if (legacyOptions) {
|
||
const converted = _65_migrate_forwarder_settings_convertSettings(legacyOptions);
|
||
yield _65_migrate_forwarder_settings_storeSettings(helper, userId, converted);
|
||
yield _65_migrate_forwarder_settings_deleteSettings(helper, userId, account);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _65_migrate_forwarder_settings_awaiter(this, void 0, void 0, function* () {
|
||
// not supported
|
||
});
|
||
}
|
||
}
|
||
function _65_migrate_forwarder_settings_convertSettings(options) {
|
||
const forwarders = {
|
||
addyIo: {
|
||
baseUrl: options.forwardedAnonAddyBaseUrl,
|
||
token: options.forwardedAnonAddyApiToken,
|
||
domain: options.forwardedAnonAddyDomain,
|
||
},
|
||
duckDuckGo: {
|
||
token: options.forwardedDuckDuckGoToken,
|
||
},
|
||
fastmail: {
|
||
token: options.forwardedFastmailApiToken,
|
||
},
|
||
firefoxRelay: {
|
||
token: options.forwardedFirefoxApiToken,
|
||
},
|
||
forwardEmail: {
|
||
token: options.forwardedForwardEmailApiToken,
|
||
domain: options.forwardedForwardEmailDomain,
|
||
},
|
||
simpleLogin: {
|
||
token: options.forwardedSimpleLoginApiKey,
|
||
baseUrl: options.forwardedSimpleLoginBaseUrl,
|
||
},
|
||
};
|
||
const generator = {
|
||
username: options.type,
|
||
forwarder: options.forwardedService,
|
||
};
|
||
const algorithms = {
|
||
effUsername: {
|
||
wordCapitalize: options.wordCapitalize,
|
||
wordIncludeNumber: options.wordIncludeNumber,
|
||
},
|
||
subaddress: {
|
||
subaddressType: options.subaddressType,
|
||
subaddressEmail: options.subaddressEmail,
|
||
},
|
||
catchall: {
|
||
catchallType: options.catchallType,
|
||
catchallDomain: options.catchallDomain,
|
||
},
|
||
};
|
||
return { generator, algorithms, forwarders };
|
||
}
|
||
function _65_migrate_forwarder_settings_storeSettings(helper, userId, converted) {
|
||
return _65_migrate_forwarder_settings_awaiter(this, void 0, void 0, function* () {
|
||
yield Promise.all([
|
||
helper.setToUser(userId, _65_migrate_forwarder_settings_NAVIGATION, converted.generator),
|
||
helper.setToUser(userId, CATCHALL, converted.algorithms.catchall),
|
||
helper.setToUser(userId, EFF_USERNAME, converted.algorithms.effUsername),
|
||
helper.setToUser(userId, SUBADDRESS, converted.algorithms.subaddress),
|
||
helper.setToUser(userId, ADDY_IO, converted.forwarders.addyIo),
|
||
helper.setToUser(userId, DUCK_DUCK_GO, converted.forwarders.duckDuckGo),
|
||
helper.setToUser(userId, FASTMAIL, converted.forwarders.fastmail),
|
||
helper.setToUser(userId, FIREFOX_RELAY, converted.forwarders.firefoxRelay),
|
||
helper.setToUser(userId, FORWARD_EMAIL, converted.forwarders.forwardEmail),
|
||
helper.setToUser(userId, SIMPLE_LOGIN, converted.forwarders.simpleLogin),
|
||
]);
|
||
});
|
||
}
|
||
function _65_migrate_forwarder_settings_deleteSettings(helper, userId, account) {
|
||
return _65_migrate_forwarder_settings_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
(_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? true : delete _a.usernameGenerationOptions;
|
||
yield helper.set(userId, account);
|
||
});
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/66-move-final-desktop-settings.ts
|
||
var _66_move_final_desktop_settings_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _66_move_final_desktop_settings_DESKTOP_SETTINGS_DISK = {
|
||
name: "desktopSettings",
|
||
};
|
||
const BROWSER_INTEGRATION_ENABLED = {
|
||
key: "browserIntegrationEnabled",
|
||
stateDefinition: _66_move_final_desktop_settings_DESKTOP_SETTINGS_DISK,
|
||
};
|
||
const BROWSER_INTEGRATION_FINGERPRINT_ENABLED = {
|
||
key: "browserIntegrationFingerprintEnabled",
|
||
stateDefinition: _66_move_final_desktop_settings_DESKTOP_SETTINGS_DISK,
|
||
};
|
||
const MINIMIZE_ON_COPY = {
|
||
key: "minimizeOnCopy",
|
||
stateDefinition: _66_move_final_desktop_settings_DESKTOP_SETTINGS_DISK,
|
||
};
|
||
class _66_move_final_desktop_settings_MoveFinalDesktopSettingsMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _66_move_final_desktop_settings_awaiter(this, void 0, void 0, function* () {
|
||
const legacyGlobal = yield helper.get("global");
|
||
const enableBrowserIntegrationValue = legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.enableBrowserIntegration;
|
||
const enableBrowserIntegrationFingerprintValue = legacyGlobal === null || legacyGlobal === void 0 ? void 0 : legacyGlobal.enableBrowserIntegrationFingerprint;
|
||
let updatedGlobal = false;
|
||
if (enableBrowserIntegrationValue != null) {
|
||
yield helper.setToGlobal(BROWSER_INTEGRATION_ENABLED, enableBrowserIntegrationValue);
|
||
delete legacyGlobal.enableBrowserIntegration;
|
||
updatedGlobal = true;
|
||
}
|
||
if (enableBrowserIntegrationFingerprintValue != null) {
|
||
yield helper.setToGlobal(BROWSER_INTEGRATION_FINGERPRINT_ENABLED, enableBrowserIntegrationFingerprintValue);
|
||
delete legacyGlobal.enableBrowserIntegrationFingerprint;
|
||
updatedGlobal = true;
|
||
}
|
||
if (updatedGlobal) {
|
||
yield helper.set("global", legacyGlobal);
|
||
}
|
||
function migrateAccount(userId, account) {
|
||
return _66_move_final_desktop_settings_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const minimizeOnCopyToClipboardValue = (_a = account === null || account === void 0 ? void 0 : account.settings) === null || _a === void 0 ? void 0 : _a.minimizeOnCopyToClipboard;
|
||
if (minimizeOnCopyToClipboardValue != null) {
|
||
yield helper.setToUser(userId, MINIMIZE_ON_COPY, minimizeOnCopyToClipboardValue);
|
||
delete account.settings.minimizeOnCopyToClipboard;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => migrateAccount(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _66_move_final_desktop_settings_awaiter(this, void 0, void 0, function* () {
|
||
const browserIntegrationEnabledValue = yield helper.getFromGlobal(BROWSER_INTEGRATION_ENABLED);
|
||
const browserIntegrationFingerprintEnabled = yield helper.getFromGlobal(BROWSER_INTEGRATION_FINGERPRINT_ENABLED);
|
||
if (browserIntegrationEnabledValue != null) {
|
||
let legacyGlobal = yield helper.get("global");
|
||
legacyGlobal !== null && legacyGlobal !== void 0 ? legacyGlobal : (legacyGlobal = {});
|
||
legacyGlobal.enableBrowserIntegration = browserIntegrationEnabledValue;
|
||
yield helper.set("global", legacyGlobal);
|
||
yield helper.removeFromGlobal(BROWSER_INTEGRATION_ENABLED);
|
||
}
|
||
if (browserIntegrationFingerprintEnabled != null) {
|
||
let legacyGlobal = yield helper.get("global");
|
||
legacyGlobal !== null && legacyGlobal !== void 0 ? legacyGlobal : (legacyGlobal = {});
|
||
legacyGlobal.enableBrowserIntegrationFingerprint = browserIntegrationFingerprintEnabled;
|
||
yield helper.set("global", legacyGlobal);
|
||
yield helper.removeFromGlobal(BROWSER_INTEGRATION_FINGERPRINT_ENABLED);
|
||
}
|
||
function rollbackAccount(userId, account) {
|
||
return _66_move_final_desktop_settings_awaiter(this, void 0, void 0, function* () {
|
||
const minimizeOnCopyToClipboardValue = yield helper.getFromUser(userId, MINIMIZE_ON_COPY);
|
||
if (minimizeOnCopyToClipboardValue != null) {
|
||
account !== null && account !== void 0 ? account : (account = { settings: {} });
|
||
account.settings.minimizeOnCopyToClipboard = minimizeOnCopyToClipboardValue;
|
||
yield helper.set(userId, account);
|
||
yield helper.removeFromUser(userId, MINIMIZE_ON_COPY);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackAccount(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/67-remove-unassigned-items-banner-dismissed.ts
|
||
var _67_remove_unassigned_items_banner_dismissed_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const SHOW_BANNER = {
|
||
key: "showBanner",
|
||
stateDefinition: { name: "unassignedItemsBanner" },
|
||
};
|
||
class _67_remove_unassigned_items_banner_dismissed_RemoveUnassignedItemsBannerDismissed extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _67_remove_unassigned_items_banner_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
yield Promise.all((yield helper.getAccounts()).map((_a) => _67_remove_unassigned_items_banner_dismissed_awaiter(this, [_a], void 0, function* ({ userId }) {
|
||
if (helper.getFromUser(userId, SHOW_BANNER) != null) {
|
||
yield helper.removeFromUser(userId, SHOW_BANNER);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _67_remove_unassigned_items_banner_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/68-move-last-sync-date.ts
|
||
var _68_move_last_sync_date_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _68_move_last_sync_date_LAST_SYNC_KEY = {
|
||
key: "lastSync",
|
||
stateDefinition: {
|
||
name: "sync",
|
||
},
|
||
};
|
||
class _68_move_last_sync_date_MoveLastSyncDate extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _68_move_last_sync_date_awaiter(this, void 0, void 0, function* () {
|
||
function migrateAccount(userId, account) {
|
||
return _68_move_last_sync_date_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = (_a = account === null || account === void 0 ? void 0 : account.profile) === null || _a === void 0 ? void 0 : _a.lastSync;
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, _68_move_last_sync_date_LAST_SYNC_KEY, value);
|
||
delete account.profile.lastSync;
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => migrateAccount(userId, account)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _68_move_last_sync_date_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackAccount(userId, account) {
|
||
return _68_move_last_sync_date_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const value = yield helper.getFromUser(userId, _68_move_last_sync_date_LAST_SYNC_KEY);
|
||
if (value != null) {
|
||
account !== null && account !== void 0 ? account : (account = {});
|
||
(_a = account.profile) !== null && _a !== void 0 ? _a : (account.profile = {});
|
||
account.profile.lastSync = value;
|
||
yield helper.set(userId, account);
|
||
yield helper.removeFromUser(userId, _68_move_last_sync_date_LAST_SYNC_KEY);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId, account }) => rollbackAccount(userId, account)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/69-migrate-incorrect-folder-key.ts
|
||
var _69_migrate_incorrect_folder_key_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const BAD_FOLDER_KEY = {
|
||
key: "folder", // We inadvertently changed the key from "folders" to "folder"
|
||
stateDefinition: {
|
||
name: "folder",
|
||
},
|
||
};
|
||
const GOOD_FOLDER_KEY = {
|
||
key: "folders", // We should keep the key as "folders"
|
||
stateDefinition: {
|
||
name: "folder",
|
||
},
|
||
};
|
||
class _69_migrate_incorrect_folder_key_MigrateIncorrectFolderKey extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _69_migrate_incorrect_folder_key_awaiter(this, void 0, void 0, function* () {
|
||
function migrateUser(userId) {
|
||
return _69_migrate_incorrect_folder_key_awaiter(this, void 0, void 0, function* () {
|
||
const value = yield helper.getFromUser(userId, BAD_FOLDER_KEY);
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, GOOD_FOLDER_KEY, value);
|
||
}
|
||
yield helper.removeFromUser(userId, BAD_FOLDER_KEY);
|
||
});
|
||
}
|
||
const users = yield helper.getKnownUserIds();
|
||
yield Promise.all(users.map((userId) => migrateUser(userId)));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _69_migrate_incorrect_folder_key_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackUser(userId) {
|
||
return _69_migrate_incorrect_folder_key_awaiter(this, void 0, void 0, function* () {
|
||
const value = yield helper.getFromUser(userId, GOOD_FOLDER_KEY);
|
||
if (value != null) {
|
||
yield helper.setToUser(userId, BAD_FOLDER_KEY, value);
|
||
}
|
||
yield helper.removeFromUser(userId, GOOD_FOLDER_KEY);
|
||
});
|
||
}
|
||
const users = yield helper.getKnownUserIds();
|
||
yield Promise.all(users.map((userId) => rollbackUser(userId)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/7-move-biometric-auto-prompt-to-account.ts
|
||
var _7_move_biometric_auto_prompt_to_account_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _7_move_biometric_auto_prompt_to_account_MoveBiometricAutoPromptToAccount extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _7_move_biometric_auto_prompt_to_account_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const global = yield helper.get("global");
|
||
const noAutoPromptBiometrics = (_a = global === null || global === void 0 ? void 0 : global.noAutoPromptBiometrics) !== null && _a !== void 0 ? _a : false;
|
||
const accounts = yield helper.getAccounts();
|
||
function updateAccount(userId, account) {
|
||
return _7_move_biometric_auto_prompt_to_account_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if (account == null) {
|
||
return;
|
||
}
|
||
if (noAutoPromptBiometrics) {
|
||
account.settings = Object.assign((_a = account === null || account === void 0 ? void 0 : account.settings) !== null && _a !== void 0 ? _a : {}, {
|
||
disableAutoBiometricsPrompt: true,
|
||
});
|
||
yield helper.set(userId, account);
|
||
}
|
||
});
|
||
}
|
||
delete global.noAutoPromptBiometrics;
|
||
yield Promise.all([
|
||
...accounts.map(({ userId, account }) => updateAccount(userId, account)),
|
||
helper.set("global", global),
|
||
]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _7_move_biometric_auto_prompt_to_account_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
// Override is necessary because default implementation assumes `stateVersion` at the root, but for this version
|
||
// it is nested inside a global object.
|
||
updateVersion(helper, direction) {
|
||
return _7_move_biometric_auto_prompt_to_account_awaiter(this, void 0, void 0, function* () {
|
||
const endVersion = direction === "up" ? this.toVersion : this.fromVersion;
|
||
helper.currentVersion = endVersion;
|
||
const global = (yield helper.get("global")) || {};
|
||
yield helper.set("global", Object.assign(Object.assign({}, global), { stateVersion: endVersion }));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/70-remove-ac-banner-dismissed.ts
|
||
var _70_remove_ac_banner_dismissed_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const SHOW_BANNER_KEY = {
|
||
key: "acBannersDismissed",
|
||
stateDefinition: { name: "showProviderClientVaultPrivacyBanner" },
|
||
};
|
||
class _70_remove_ac_banner_dismissed_RemoveAcBannersDismissed extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _70_remove_ac_banner_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
yield Promise.all((yield helper.getAccounts()).map((_a) => _70_remove_ac_banner_dismissed_awaiter(this, [_a], void 0, function* ({ userId }) {
|
||
if (helper.getFromUser(userId, SHOW_BANNER_KEY) != null) {
|
||
yield helper.removeFromUser(userId, SHOW_BANNER_KEY);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _70_remove_ac_banner_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/71-remove-new-customization-options-callout-dismissed.ts
|
||
var _71_remove_new_customization_options_callout_dismissed_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const SHOW_CALLOUT_KEY = {
|
||
key: "newCustomizationOptionsCalloutDismissed",
|
||
stateDefinition: { name: "bannersDismissed" },
|
||
};
|
||
class _71_remove_new_customization_options_callout_dismissed_RemoveNewCustomizationOptionsCalloutDismissed extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _71_remove_new_customization_options_callout_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
yield Promise.all((yield helper.getAccounts()).map((_a) => _71_remove_new_customization_options_callout_dismissed_awaiter(this, [_a], void 0, function* ({ userId }) {
|
||
if (helper.getFromUser(userId, SHOW_CALLOUT_KEY) != null) {
|
||
yield helper.removeFromUser(userId, SHOW_CALLOUT_KEY);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _71_remove_new_customization_options_callout_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/72-remove-account-deprovisioning-banner-dismissed.ts
|
||
var _72_remove_account_deprovisioning_banner_dismissed_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _72_remove_account_deprovisioning_banner_dismissed_SHOW_BANNER_KEY = {
|
||
key: "showAccountDeprovisioningBanner",
|
||
stateDefinition: { name: "accountDeprovisioningBanner" },
|
||
};
|
||
class _72_remove_account_deprovisioning_banner_dismissed_RemoveAccountDeprovisioningBannerDismissed extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _72_remove_account_deprovisioning_banner_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
yield Promise.all((yield helper.getAccounts()).map((_a) => _72_remove_account_deprovisioning_banner_dismissed_awaiter(this, [_a], void 0, function* ({ userId }) {
|
||
if (helper.getFromUser(userId, _72_remove_account_deprovisioning_banner_dismissed_SHOW_BANNER_KEY) != null) {
|
||
yield helper.removeFromUser(userId, _72_remove_account_deprovisioning_banner_dismissed_SHOW_BANNER_KEY);
|
||
}
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _72_remove_account_deprovisioning_banner_dismissed_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/73-add-master-password-unlock-data.ts
|
||
var _73_add_master_password_unlock_data_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const _73_add_master_password_unlock_data_ACCOUNT_ACCOUNTS = {
|
||
stateDefinition: {
|
||
name: "account",
|
||
},
|
||
key: "accounts",
|
||
};
|
||
const MASTER_PASSWORD_UNLOCK_KEY = {
|
||
key: "masterPasswordUnlockKey",
|
||
stateDefinition: { name: "masterPasswordUnlock" },
|
||
};
|
||
const MASTER_KEY_ENCRYPTED_USER_KEY = {
|
||
key: "masterKeyEncryptedUserKey",
|
||
stateDefinition: { name: "masterPassword" },
|
||
};
|
||
const _73_add_master_password_unlock_data_KDF_CONFIG_DISK = {
|
||
key: "kdfConfig",
|
||
stateDefinition: { name: "kdfConfig" },
|
||
};
|
||
class _73_add_master_password_unlock_data_AddMasterPasswordUnlockData extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _73_add_master_password_unlock_data_awaiter(this, void 0, void 0, function* () {
|
||
function migrateAccount(userId, account) {
|
||
return _73_add_master_password_unlock_data_awaiter(this, void 0, void 0, function* () {
|
||
const email = account === null || account === void 0 ? void 0 : account.email;
|
||
const kdfConfig = yield helper.getFromUser(userId, _73_add_master_password_unlock_data_KDF_CONFIG_DISK);
|
||
const masterKeyEncryptedUserKey = yield helper.getFromUser(userId, MASTER_KEY_ENCRYPTED_USER_KEY);
|
||
if ((yield helper.getFromUser(userId, MASTER_PASSWORD_UNLOCK_KEY)) == null &&
|
||
email != null &&
|
||
kdfConfig != null &&
|
||
masterKeyEncryptedUserKey != null) {
|
||
yield helper.setToUser(userId, MASTER_PASSWORD_UNLOCK_KEY, {
|
||
salt: email.trim().toLowerCase(),
|
||
kdf: kdfConfig,
|
||
masterKeyWrappedUserKey: masterKeyEncryptedUserKey,
|
||
});
|
||
}
|
||
});
|
||
}
|
||
const accountDictionary = yield helper.getFromGlobal(_73_add_master_password_unlock_data_ACCOUNT_ACCOUNTS);
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId }) => migrateAccount(userId, accountDictionary[userId])));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _73_add_master_password_unlock_data_awaiter(this, void 0, void 0, function* () {
|
||
function rollbackAccount(userId) {
|
||
return _73_add_master_password_unlock_data_awaiter(this, void 0, void 0, function* () {
|
||
if ((yield helper.getFromUser(userId, MASTER_PASSWORD_UNLOCK_KEY)) != null) {
|
||
yield helper.removeFromUser(userId, MASTER_PASSWORD_UNLOCK_KEY);
|
||
}
|
||
});
|
||
}
|
||
const accounts = yield helper.getAccounts();
|
||
yield Promise.all(accounts.map(({ userId }) => rollbackAccount(userId)));
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/74-remove-legacy-pin.ts
|
||
var _74_remove_legacy_pin_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const PinProtectedUserKey = {
|
||
key: "pinKeyEncryptedUserKeyPersistent",
|
||
stateDefinition: {
|
||
name: "pinUnlock",
|
||
},
|
||
};
|
||
class _74_remove_legacy_pin_RemoveLegacyPin extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _74_remove_legacy_pin_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield helper.getAccounts();
|
||
function migrateAccount(userId, account) {
|
||
return _74_remove_legacy_pin_awaiter(this, void 0, void 0, function* () {
|
||
const pinProtectedUserKey = yield helper.getFromUser(userId, PinProtectedUserKey);
|
||
if (pinProtectedUserKey != null) {
|
||
yield helper.removeFromUser(userId, PinProtectedUserKey);
|
||
}
|
||
});
|
||
}
|
||
yield Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]);
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _74_remove_legacy_pin_awaiter(this, void 0, void 0, function* () {
|
||
throw IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/8-move-state-version.ts
|
||
var _8_move_state_version_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _8_move_state_version_MoveStateVersionMigrator extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
migrate(helper) {
|
||
return _8_move_state_version_awaiter(this, void 0, void 0, function* () {
|
||
const global = yield helper.get("global");
|
||
if (global.stateVersion) {
|
||
yield helper.set("stateVersion", global.stateVersion);
|
||
delete global.stateVersion;
|
||
yield helper.set("global", global);
|
||
}
|
||
else {
|
||
throw new Error("Migration failed, state version not found");
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return _8_move_state_version_awaiter(this, void 0, void 0, function* () {
|
||
const version = yield helper.get("stateVersion");
|
||
const global = yield helper.get("global");
|
||
yield helper.set("global", Object.assign(Object.assign({}, global), { stateVersion: version }));
|
||
yield helper.set("stateVersion", undefined);
|
||
});
|
||
}
|
||
// Override is necessary because default implementation assumes `stateVersion` at the root, but this migration moves
|
||
// it from a `global` object to root.This makes for unique rollback versioning.
|
||
updateVersion(helper, direction) {
|
||
return _8_move_state_version_awaiter(this, void 0, void 0, function* () {
|
||
const endVersion = direction === "up" ? this.toVersion : this.fromVersion;
|
||
helper.currentVersion = endVersion;
|
||
if (direction === "up") {
|
||
yield helper.set("stateVersion", endVersion);
|
||
}
|
||
else {
|
||
const global = (yield helper.get("global")) || {};
|
||
yield helper.set("global", Object.assign(Object.assign({}, global), { stateVersion: endVersion }));
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/9-move-browser-settings-to-global.ts
|
||
var _9_move_browser_settings_to_global_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class _9_move_browser_settings_to_global_MoveBrowserSettingsToGlobal extends (/* unused pure expression or super */ null && (Migrator)) {
|
||
// Will first check if any of the accounts have a value from the given accountSelector
|
||
// if they do have a value it will set that value into global state but if multiple
|
||
// users have differing values it will prefer the false setting,
|
||
// if all users have true then it will take true.
|
||
tryAddSetting(accounts, accountSelector, globalSetter) {
|
||
const hasValue = accounts.some(({ account }) => {
|
||
return accountSelector(account) !== undefined;
|
||
});
|
||
if (hasValue) {
|
||
const value = !accounts.some(({ account }) => {
|
||
var _a;
|
||
return ((_a = accountSelector(account)) !== null && _a !== void 0 ? _a : false) === false;
|
||
});
|
||
globalSetter(value);
|
||
}
|
||
}
|
||
migrate(helper) {
|
||
return _9_move_browser_settings_to_global_awaiter(this, void 0, void 0, function* () {
|
||
const global = yield helper.get("global");
|
||
const accounts = yield helper.getAccounts();
|
||
const globalNeverDomainsValue = accounts.reduce((accumulator, { account }) => {
|
||
var _a, _b;
|
||
const normalizedNeverDomains = (_b = (_a = account.settings) === null || _a === void 0 ? void 0 : _a.neverDomains) !== null && _b !== void 0 ? _b : {};
|
||
for (const [id, value] of Object.entries(normalizedNeverDomains)) {
|
||
accumulator !== null && accumulator !== void 0 ? accumulator : (accumulator = {});
|
||
accumulator[id] = value;
|
||
}
|
||
return accumulator;
|
||
}, undefined);
|
||
const targetGlobalState = {};
|
||
if (globalNeverDomainsValue != null) {
|
||
targetGlobalState.neverDomains = globalNeverDomainsValue;
|
||
}
|
||
this.tryAddSetting(accounts, (a) => { var _a; return (_a = a.settings) === null || _a === void 0 ? void 0 : _a.disableAddLoginNotification; }, (v) => (targetGlobalState.disableAddLoginNotification = v));
|
||
this.tryAddSetting(accounts, (a) => { var _a; return (_a = a.settings) === null || _a === void 0 ? void 0 : _a.disableChangedPasswordNotification; }, (v) => (targetGlobalState.disableChangedPasswordNotification = v));
|
||
this.tryAddSetting(accounts, (a) => { var _a; return (_a = a.settings) === null || _a === void 0 ? void 0 : _a.disableContextMenuItem; }, (v) => (targetGlobalState.disableContextMenuItem = v));
|
||
yield helper.set("global", Object.assign(Object.assign({}, global), targetGlobalState));
|
||
yield Promise.all(accounts.map((_a) => _9_move_browser_settings_to_global_awaiter(this, [_a], void 0, function* ({ userId, account }) {
|
||
var _b, _c, _d, _e;
|
||
(_b = account.settings) === null || _b === void 0 ? true : delete _b.disableAddLoginNotification;
|
||
(_c = account.settings) === null || _c === void 0 ? true : delete _c.disableChangedPasswordNotification;
|
||
(_d = account.settings) === null || _d === void 0 ? true : delete _d.disableContextMenuItem;
|
||
(_e = account.settings) === null || _e === void 0 ? true : delete _e.neverDomains;
|
||
yield helper.set(userId, account);
|
||
})));
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
throw new Error("Method not implemented.");
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrations/min-version.ts
|
||
var min_version_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
function minVersionError(current) {
|
||
return `Your local data is too old to be migrated. Your current state version is ${current}, but minimum version is ${MIN_VERSION}.`;
|
||
}
|
||
class min_version_MinVersionMigrator extends migrator_Migrator {
|
||
constructor() {
|
||
super(0, MIN_VERSION);
|
||
}
|
||
// Overrides the default implementation to catch any version that may be passed in.
|
||
shouldMigrate(helper) {
|
||
return Promise.resolve(helper.currentVersion < MIN_VERSION);
|
||
}
|
||
migrate(helper) {
|
||
return min_version_awaiter(this, void 0, void 0, function* () {
|
||
if (helper.currentVersion < MIN_VERSION) {
|
||
throw new Error(minVersionError(helper.currentVersion));
|
||
}
|
||
});
|
||
}
|
||
rollback(helper) {
|
||
return min_version_awaiter(this, void 0, void 0, function* () {
|
||
throw migrator_IRREVERSIBLE;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migrate.ts
|
||
var migrate_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
const MIN_VERSION = 3;
|
||
const CURRENT_VERSION = 74;
|
||
function createMigrationBuilder() {
|
||
return MigrationBuilder.create()
|
||
.with(MinVersionMigrator)
|
||
.with(RemoveEverBeenUnlockedMigrator, 3, 4)
|
||
.with(AddKeyTypeToOrgKeysMigrator, 4, 5)
|
||
.with(RemoveLegacyEtmKeyMigrator, 5, 6)
|
||
.with(MoveBiometricAutoPromptToAccount, 6, 7)
|
||
.with(MoveStateVersionMigrator, 7, 8)
|
||
.with(MoveBrowserSettingsToGlobal, 8, 9)
|
||
.with(EverHadUserKeyMigrator, 9, 10)
|
||
.with(OrganizationKeyMigrator, 10, 11)
|
||
.with(MoveEnvironmentStateToProviders, 11, 12)
|
||
.with(ProviderKeyMigrator, 12, 13)
|
||
.with(MoveBiometricClientKeyHalfToStateProviders, 13, 14)
|
||
.with(FolderMigrator, 14, 15)
|
||
.with(LastSyncMigrator, 15, 16)
|
||
.with(EnablePasskeysMigrator, 16, 17)
|
||
.with(AutofillSettingsKeyMigrator, 17, 18)
|
||
.with(RequirePasswordOnStartMigrator, 18, 19)
|
||
.with(PrivateKeyMigrator, 19, 20)
|
||
.with(CollectionMigrator, 20, 21)
|
||
.with(CollapsedGroupingsMigrator, 21, 22)
|
||
.with(MoveBiometricPromptsToStateProviders, 22, 23)
|
||
.with(SmOnboardingTasksMigrator, 23, 24)
|
||
.with(ClearClipboardDelayMigrator, 24, 25)
|
||
.with(RevertLastSyncMigrator, 25, 26)
|
||
.with(BadgeSettingsMigrator, 26, 27)
|
||
.with(MoveBiometricUnlockToStateProviders, 27, 28)
|
||
.with(UserNotificationSettingsKeyMigrator, 28, 29)
|
||
.with(PolicyMigrator, 29, 30)
|
||
.with(EnableContextMenuMigrator, 30, 31)
|
||
.with(PreferredLanguageMigrator, 31, 32)
|
||
.with(AppIdMigrator, 32, 33)
|
||
.with(DomainSettingsMigrator, 33, 34)
|
||
.with(MoveThemeToStateProviderMigrator, 34, 35)
|
||
.with(VaultSettingsKeyMigrator, 35, 36)
|
||
.with(AvatarColorMigrator, 36, 37)
|
||
.with(TokenServiceStateProviderMigrator, 37, 38)
|
||
.with(MoveBillingAccountProfileMigrator, 38, 39)
|
||
.with(OrganizationMigrator, 39, 40)
|
||
.with(EventCollectionMigrator, 40, 41)
|
||
.with(EnableFaviconMigrator, 41, 42)
|
||
.with(AutoConfirmFingerPrintsMigrator, 42, 43)
|
||
.with(UserDecryptionOptionsMigrator, 43, 44)
|
||
.with(MergeEnvironmentState, 44, 45)
|
||
.with(DeleteBiometricPromptCancelledData, 45, 46)
|
||
.with(MoveDesktopSettingsMigrator, 46, 47)
|
||
.with(MoveDdgToStateProviderMigrator, 47, 48)
|
||
.with(AccountServerConfigMigrator, 48, 49)
|
||
.with(KeyConnectorMigrator, 49, 50)
|
||
.with(RememberedEmailMigrator, 50, 51)
|
||
.with(DeleteInstalledVersion, 51, 52)
|
||
.with(DeviceTrustServiceStateProviderMigrator, 52, 53)
|
||
.with(SendMigrator, 53, 54)
|
||
.with(MoveMasterKeyStateToProviderMigrator, 54, 55)
|
||
.with(AuthRequestMigrator, 55, 56)
|
||
.with(CipherServiceMigrator, 56, 57)
|
||
.with(RemoveRefreshTokenMigratedFlagMigrator, 57, 58)
|
||
.with(KdfConfigMigrator, 58, 59)
|
||
.with(KnownAccountsMigrator, 59, 60)
|
||
.with(PinStateMigrator, 60, 61)
|
||
.with(VaultTimeoutSettingsServiceStateProviderMigrator, 61, 62)
|
||
.with(PasswordOptionsMigrator, 62, 63)
|
||
.with(GeneratorHistoryMigrator, 63, 64)
|
||
.with(ForwarderOptionsMigrator, 64, 65)
|
||
.with(MoveFinalDesktopSettingsMigrator, 65, 66)
|
||
.with(RemoveUnassignedItemsBannerDismissed, 66, 67)
|
||
.with(MoveLastSyncDate, 67, 68)
|
||
.with(MigrateIncorrectFolderKey, 68, 69)
|
||
.with(RemoveAcBannersDismissed, 69, 70)
|
||
.with(RemoveNewCustomizationOptionsCalloutDismissed, 70, 71)
|
||
.with(RemoveAccountDeprovisioningBannerDismissed, 71, 72)
|
||
.with(AddMasterPasswordUnlockData, 72, 73)
|
||
.with(RemoveLegacyPin, 73, CURRENT_VERSION);
|
||
}
|
||
function currentVersion(storageService, logService) {
|
||
return migrate_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
let state = yield storageService.get("stateVersion");
|
||
if (state == null) {
|
||
// Pre v8
|
||
state = (_a = (yield storageService.get("global"))) === null || _a === void 0 ? void 0 : _a.stateVersion;
|
||
}
|
||
if (state == null) {
|
||
logService.info("No state version found, assuming empty state.");
|
||
return -1;
|
||
}
|
||
logService.info(`State version: ${state}`);
|
||
return state;
|
||
});
|
||
}
|
||
/**
|
||
* Waits for migrations to have a chance to run and will resolve the promise once they are.
|
||
*
|
||
* @param storageService Disk storage where the `stateVersion` will or is already saved in.
|
||
* @param logService Log service
|
||
*/
|
||
function waitForMigrations(storageService, logService) {
|
||
return migrate_awaiter(this, void 0, void 0, function* () {
|
||
const isReady = () => migrate_awaiter(this, void 0, void 0, function* () {
|
||
const version = yield currentVersion(storageService, logService);
|
||
// The saved version is what we consider the latest
|
||
// migrations should be complete, the state version
|
||
// shouldn't become larger than `CURRENT_VERSION` in
|
||
// any normal usage of the application but it is common
|
||
// enough in dev scenarios where we want to consider that
|
||
// ready as well and return true in that scenario.
|
||
return version >= CURRENT_VERSION;
|
||
});
|
||
const wait = (time) => migrate_awaiter(this, void 0, void 0, function* () {
|
||
// Wait exponentially
|
||
const nextTime = time * 2;
|
||
if (nextTime > 8192) {
|
||
// Don't wait longer than ~8 seconds in a single wait,
|
||
// if the migrations still haven't happened. They aren't
|
||
// likely to.
|
||
return;
|
||
}
|
||
return new Promise((resolve) => {
|
||
setTimeout(() => migrate_awaiter(this, void 0, void 0, function* () {
|
||
if (!(yield isReady())) {
|
||
logService.info(`Waiting for migrations to finish, waiting for ${nextTime}ms`);
|
||
yield wait(nextTime);
|
||
}
|
||
resolve();
|
||
}), time);
|
||
});
|
||
});
|
||
if (!(yield isReady())) {
|
||
// Wait for 2ms to start with
|
||
yield wait(2);
|
||
}
|
||
});
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/migration-helper.ts
|
||
var migration_helper_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
class MigrationHelper {
|
||
constructor(currentVersion, storageService, logService, type, clientType) {
|
||
this.currentVersion = currentVersion;
|
||
this.storageService = storageService;
|
||
this.logService = logService;
|
||
this.clientType = clientType;
|
||
this.type = type;
|
||
}
|
||
/**
|
||
* Gets a value from the storage service at the given key.
|
||
*
|
||
* This is a brute force method to just get a value from the storage service. If you can use {@link getFromGlobal} or {@link getFromUser}, you should.
|
||
* @param key location
|
||
* @returns the value at the location
|
||
*/
|
||
get(key) {
|
||
return this.storageService.get(key);
|
||
}
|
||
/**
|
||
* Sets a value in the storage service at the given key.
|
||
*
|
||
* This is a brute force method to just set a value in the storage service. If you can use {@link setToGlobal} or {@link setToUser}, you should.
|
||
* @param key location
|
||
* @param value the value to set
|
||
* @returns
|
||
*/
|
||
set(key, value) {
|
||
this.logService.info(`Setting ${key}`);
|
||
return this.storageService.save(key, value);
|
||
}
|
||
/**
|
||
* Remove a value in the storage service at the given key.
|
||
*
|
||
* This is a brute force method to just remove a value in the storage service. If you can use {@link removeFromGlobal} or {@link removeFromUser}, you should.
|
||
* @param key location
|
||
* @returns void
|
||
*/
|
||
remove(key) {
|
||
this.logService.info(`Removing ${key}`);
|
||
return this.storageService.remove(key);
|
||
}
|
||
/**
|
||
* Gets a globally scoped value from a location derived through the key definition
|
||
*
|
||
* This is for use with the state providers framework, DO NOT use for values stored with {@link StateService},
|
||
* use {@link get} for those.
|
||
* @param keyDefinition unique key definition
|
||
* @returns value from store
|
||
*/
|
||
getFromGlobal(keyDefinition) {
|
||
return this.get(this.getGlobalKey(keyDefinition));
|
||
}
|
||
/**
|
||
* Sets a globally scoped value to a location derived through the key definition
|
||
*
|
||
* This is for use with the state providers framework, DO NOT use for values stored with {@link StateService},
|
||
* use {@link set} for those.
|
||
* @param keyDefinition unique key definition
|
||
* @param value value to store
|
||
* @returns void
|
||
*/
|
||
setToGlobal(keyDefinition, value) {
|
||
return this.set(this.getGlobalKey(keyDefinition), value);
|
||
}
|
||
/**
|
||
* Remove a globally scoped location derived through the key definition
|
||
*
|
||
* This is for use with the state providers framework, DO NOT use for values stored with {@link StateService},
|
||
* use {@link remove} for those.
|
||
* @param keyDefinition unique key definition
|
||
* @returns void
|
||
*/
|
||
removeFromGlobal(keyDefinition) {
|
||
return this.remove(this.getGlobalKey(keyDefinition));
|
||
}
|
||
/**
|
||
* Gets a user scoped value from a location derived through the user id and key definition
|
||
*
|
||
* This is for use with the state providers framework, DO NOT use for values stored with {@link StateService},
|
||
* use {@link get} for those.
|
||
* @param userId userId to use in the key
|
||
* @param keyDefinition unique key definition
|
||
* @returns value from store
|
||
*/
|
||
getFromUser(userId, keyDefinition) {
|
||
return this.get(this.getUserKey(userId, keyDefinition));
|
||
}
|
||
/**
|
||
* Sets a user scoped value to a location derived through the user id and key definition
|
||
*
|
||
* This is for use with the state providers framework, DO NOT use for values stored with {@link StateService},
|
||
* use {@link set} for those.
|
||
* @param userId userId to use in the key
|
||
* @param keyDefinition unique key definition
|
||
* @param value value to store
|
||
* @returns void
|
||
*/
|
||
setToUser(userId, keyDefinition, value) {
|
||
return this.set(this.getUserKey(userId, keyDefinition), value);
|
||
}
|
||
/**
|
||
* Remove a user scoped location derived through the key definition
|
||
*
|
||
* This is for use with the state providers framework, DO NOT use for values stored with {@link StateService},
|
||
* use {@link remove} for those.
|
||
* @param keyDefinition unique key definition
|
||
* @returns void
|
||
*/
|
||
removeFromUser(userId, keyDefinition) {
|
||
return this.remove(this.getUserKey(userId, keyDefinition));
|
||
}
|
||
info(message) {
|
||
this.logService.info(message);
|
||
}
|
||
/**
|
||
* Helper method to read all Account objects stored by the State Service.
|
||
*
|
||
* This is useful from creating migrations off of this paradigm, but should not be used once a value is migrated to a state provider.
|
||
*
|
||
* @returns a list of all accounts that have been authenticated with state service, cast the expected type.
|
||
*/
|
||
getAccounts() {
|
||
return migration_helper_awaiter(this, void 0, void 0, function* () {
|
||
const userIds = yield this.getKnownUserIds();
|
||
return Promise.all(userIds.map((userId) => migration_helper_awaiter(this, void 0, void 0, function* () {
|
||
return ({
|
||
userId,
|
||
account: yield this.get(userId),
|
||
});
|
||
})));
|
||
});
|
||
}
|
||
/**
|
||
* Helper method to read known users ids.
|
||
*/
|
||
getKnownUserIds() {
|
||
return migration_helper_awaiter(this, void 0, void 0, function* () {
|
||
if (this.currentVersion < 60) {
|
||
return knownAccountUserIdsBuilderPre60(this.storageService);
|
||
}
|
||
else {
|
||
return knownAccountUserIdsBuilder(this.storageService);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Builds a user storage key appropriate for the current version.
|
||
*
|
||
* @param userId userId to use in the key
|
||
* @param keyDefinition state and key to use in the key
|
||
* @returns
|
||
*/
|
||
getUserKey(userId, keyDefinition) {
|
||
if (this.currentVersion < 9) {
|
||
return userKeyBuilderPre9();
|
||
}
|
||
else {
|
||
return userKeyBuilder(userId, keyDefinition);
|
||
}
|
||
}
|
||
/**
|
||
* Builds a global storage key appropriate for the current version.
|
||
*
|
||
* @param keyDefinition state and key to use in the key
|
||
* @returns
|
||
*/
|
||
getGlobalKey(keyDefinition) {
|
||
if (this.currentVersion < 9) {
|
||
return globalKeyBuilderPre9();
|
||
}
|
||
else {
|
||
return globalKeyBuilder(keyDefinition);
|
||
}
|
||
}
|
||
}
|
||
/**
|
||
* When this is updated, rename this function to `userKeyBuilderXToY` where `X` is the version number it
|
||
* became relevant, and `Y` prior to the version it was updated.
|
||
*
|
||
* Be sure to update the map in `MigrationHelper` to point to the appropriate function for the current version.
|
||
* @param userId The userId of the user you want the key to be for.
|
||
* @param keyDefinition the key definition of which data the key should point to.
|
||
* @returns
|
||
*/
|
||
function userKeyBuilder(userId, keyDefinition) {
|
||
return `user_${userId}_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`;
|
||
}
|
||
function userKeyBuilderPre9() {
|
||
throw Error("No key builder should be used for versions prior to 9.");
|
||
}
|
||
/**
|
||
* When this is updated, rename this function to `globalKeyBuilderXToY` where `X` is the version number
|
||
* it became relevant, and `Y` prior to the version it was updated.
|
||
*
|
||
* Be sure to update the map in `MigrationHelper` to point to the appropriate function for the current version.
|
||
* @param keyDefinition the key definition of which data the key should point to.
|
||
* @returns
|
||
*/
|
||
function globalKeyBuilder(keyDefinition) {
|
||
return `global_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`;
|
||
}
|
||
function globalKeyBuilderPre9() {
|
||
throw Error("No key builder should be used for versions prior to 9.");
|
||
}
|
||
function knownAccountUserIdsBuilderPre60(storageService) {
|
||
return migration_helper_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
return (_a = (yield storageService.get("authenticatedAccounts"))) !== null && _a !== void 0 ? _a : [];
|
||
});
|
||
}
|
||
function knownAccountUserIdsBuilder(storageService) {
|
||
return migration_helper_awaiter(this, void 0, void 0, function* () {
|
||
const accounts = yield storageService.get(globalKeyBuilder({ stateDefinition: { name: "account" }, key: "accounts" }));
|
||
return Object.keys(accounts !== null && accounts !== void 0 ? accounts : {});
|
||
});
|
||
}
|
||
|
||
;// ../../libs/state/src/state-migrations/index.ts
|
||
|
||
|
||
|
||
|
||
|
||
;// ../../libs/state/src/index.ts
|
||
// Root barrel for @bitwarden/state
|
||
|
||
|
||
|
||
|
||
|
||
;// ../../libs/state-internal/src/default-active-user-state.ts
|
||
var default_active_user_state_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
class default_active_user_state_DefaultActiveUserState {
|
||
constructor(keyDefinition, activeUserId$, singleUserStateProvider) {
|
||
this.keyDefinition = keyDefinition;
|
||
this.activeUserId$ = activeUserId$;
|
||
this.singleUserStateProvider = singleUserStateProvider;
|
||
this.combinedState$ = this.activeUserId$.pipe(switchMap((userId) => userId != null
|
||
? this.singleUserStateProvider.get(userId, this.keyDefinition).combinedState$
|
||
: NEVER));
|
||
// State should just be combined state without the user id
|
||
this.state$ = this.combinedState$.pipe(map(([_userId, state]) => state));
|
||
}
|
||
update(configureState_1) {
|
||
return default_active_user_state_awaiter(this, arguments, void 0, function* (configureState, options = {}) {
|
||
const userId = yield firstValueFrom(this.activeUserId$.pipe(timeout({
|
||
first: 1000,
|
||
with: () => throwError(() => new Error(`Timeout while retrieving active user for key ${this.keyDefinition.fullName}.`)),
|
||
})));
|
||
if (userId == null) {
|
||
throw new Error(`Error storing ${this.keyDefinition.fullName} for the active user: No active user at this time.`);
|
||
}
|
||
return [
|
||
userId,
|
||
yield this.singleUserStateProvider
|
||
.get(userId, this.keyDefinition)
|
||
.update(configureState, options),
|
||
];
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-active-user-state.provider.ts
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
class DefaultActiveUserStateProvider {
|
||
constructor(activeAccountAccessor, singleUserStateProvider) {
|
||
this.activeAccountAccessor = activeAccountAccessor;
|
||
this.singleUserStateProvider = singleUserStateProvider;
|
||
this.activeUserId$ = this.activeAccountAccessor.activeUserId$.pipe(
|
||
// To avoid going to storage when we don't need to, only get updates when there is a true change.
|
||
distinctUntilChanged((a, b) => (a == null || b == null ? a == b : a === b)));
|
||
}
|
||
get(keyDefinition) {
|
||
// All other providers cache the creation of their corresponding `State` objects, this instance
|
||
// doesn't need to do that since it calls `SingleUserStateProvider` it will go through their caching
|
||
// layer, because of that, the creation of this instance is quite simple and not worth caching.
|
||
return new DefaultActiveUserState(keyDefinition, this.activeUserId$, this.singleUserStateProvider);
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-derived-state.ts
|
||
var default_derived_state_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Default derived state
|
||
*/
|
||
class default_derived_state_DefaultDerivedState {
|
||
constructor(parentState$, deriveDefinition, dependencies) {
|
||
this.parentState$ = parentState$;
|
||
this.deriveDefinition = deriveDefinition;
|
||
this.dependencies = dependencies;
|
||
this.forcedValueSubject = new Subject();
|
||
this.storageKey = deriveDefinition.storageKey;
|
||
const derivedState$ = this.parentState$.pipe(concatMap((state) => default_derived_state_awaiter(this, void 0, void 0, function* () {
|
||
let derivedStateOrPromise = this.deriveDefinition.derive(state, this.dependencies);
|
||
if (derivedStateOrPromise instanceof Promise) {
|
||
derivedStateOrPromise = yield derivedStateOrPromise;
|
||
}
|
||
const derivedState = derivedStateOrPromise;
|
||
return derivedState;
|
||
})));
|
||
this.state$ = merge(this.forcedValueSubject, derivedState$).pipe(share({
|
||
connector: () => {
|
||
return new ReplaySubject(1);
|
||
},
|
||
resetOnRefCountZero: () => timer(this.deriveDefinition.cleanupDelayMs),
|
||
}));
|
||
}
|
||
forceValue(value) {
|
||
return default_derived_state_awaiter(this, void 0, void 0, function* () {
|
||
this.forcedValueSubject.next(value);
|
||
return value;
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-derived-state.provider.ts
|
||
|
||
class DefaultDerivedStateProvider {
|
||
constructor() {
|
||
/**
|
||
* The cache uses a WeakMap to maintain separate derived states per user.
|
||
* Each user's state Observable acts as a unique key, without needing to
|
||
* pass around `userId`. Also, when a user's state Observable is cleaned up
|
||
* (like during an account swap) their cache is automatically garbage
|
||
* collected.
|
||
*/
|
||
this.cache = new WeakMap();
|
||
}
|
||
get(parentState$, deriveDefinition, dependencies) {
|
||
let stateCache = this.cache.get(parentState$);
|
||
if (!stateCache) {
|
||
stateCache = {};
|
||
this.cache.set(parentState$, stateCache);
|
||
}
|
||
const cacheKey = deriveDefinition.buildCacheKey();
|
||
const existingDerivedState = stateCache[cacheKey];
|
||
if (existingDerivedState != null) {
|
||
// I have to cast out of the unknown generic but this should be safe if rules
|
||
// around domain token are made
|
||
return existingDerivedState;
|
||
}
|
||
const newDerivedState = this.buildDerivedState(parentState$, deriveDefinition, dependencies);
|
||
stateCache[cacheKey] = newDerivedState;
|
||
return newDerivedState;
|
||
}
|
||
buildDerivedState(parentState$, deriveDefinition, dependencies) {
|
||
return new DefaultDerivedState(parentState$, deriveDefinition, dependencies);
|
||
}
|
||
}
|
||
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/defer.js
|
||
function defer(observableFactory){return new Observable_Observable(function(subscriber){innerFrom(observableFactory()).subscribe(subscriber);});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/tap.js
|
||
function tap(observerOrNext,error,complete){var tapObserver=isFunction(observerOrNext)||error||complete?{next:observerOrNext,error:error,complete:complete}:observerOrNext;return tapObserver?operate(function(source,subscriber){var _a;(_a=tapObserver.subscribe)===null||_a===void 0?void 0:_a.call(tapObserver);var isUnsub=true;source.subscribe(createOperatorSubscriber(subscriber,function(value){var _a;(_a=tapObserver.next)===null||_a===void 0?void 0:_a.call(tapObserver,value);subscriber.next(value);},function(){var _a;isUnsub=false;(_a=tapObserver.complete)===null||_a===void 0?void 0:_a.call(tapObserver);subscriber.complete();},function(err){var _a;isUnsub=false;(_a=tapObserver.error)===null||_a===void 0?void 0:_a.call(tapObserver,err);subscriber.error(err);},function(){var _a,_b;if(isUnsub){(_a=tapObserver.unsubscribe)===null||_a===void 0?void 0:_a.call(tapObserver);}(_b=tapObserver.finalize)===null||_b===void 0?void 0:_b.call(tapObserver);}));}):identity;}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/timeout.js
|
||
var TimeoutError=createErrorClass(function(_super){return function TimeoutErrorImpl(info){if(info===void 0){info=null;}_super(this);this.message='Timeout has occurred';this.name='TimeoutError';this.info=info;};});function timeout_timeout(config,schedulerArg){var _a=isValidDate(config)?{first:config}:typeof config==='number'?{each:config}:config,first=_a.first,each=_a.each,_b=_a.with,_with=_b===void 0?timeoutErrorFactory:_b,_c=_a.scheduler,scheduler=_c===void 0?schedulerArg!==null&&schedulerArg!==void 0?schedulerArg:async_asyncScheduler:_c,_d=_a.meta,meta=_d===void 0?null:_d;if(first==null&&each==null){throw new TypeError('No timeout provided.');}return operate(function(source,subscriber){var originalSourceSubscription;var timerSubscription;var lastValue=null;var seen=0;var startTimer=function(delay){timerSubscription=executeSchedule(subscriber,scheduler,function(){try{originalSourceSubscription.unsubscribe();innerFrom(_with({meta:meta,lastValue:lastValue,seen:seen})).subscribe(subscriber);}catch(err){subscriber.error(err);}},delay);};originalSourceSubscription=source.subscribe(createOperatorSubscriber(subscriber,function(value){timerSubscription===null||timerSubscription===void 0?void 0:timerSubscription.unsubscribe();seen++;subscriber.next(lastValue=value);each>0&&startTimer(each);},undefined,undefined,function(){if(!(timerSubscription===null||timerSubscription===void 0?void 0:timerSubscription.closed)){timerSubscription===null||timerSubscription===void 0?void 0:timerSubscription.unsubscribe();}lastValue=null;}));!seen&&startTimer(first!=null?typeof first==='number'?first:+first-scheduler.now():each);});}function timeoutErrorFactory(info){throw new TimeoutError(info);}
|
||
;// ../../libs/state-internal/src/util.ts
|
||
var util_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
function getStoredValue(key, storage, deserializer) {
|
||
return util_awaiter(this, void 0, void 0, function* () {
|
||
if (storage.valuesRequireDeserialization) {
|
||
const jsonValue = yield storage.get(key);
|
||
return deserializer(jsonValue);
|
||
}
|
||
else {
|
||
const value = yield storage.get(key);
|
||
return value !== null && value !== void 0 ? value : null;
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Creates a {@link StorageKey}
|
||
* @param keyDefinition The key definition of which data the key should point to.
|
||
* @returns A key that is ready to be used in a storage service to get data.
|
||
*/
|
||
function util_globalKeyBuilder(keyDefinition) {
|
||
return `global_${keyDefinition.stateDefinition.name}_${keyDefinition.key}`;
|
||
}
|
||
function populateOptionsWithDefault(options) {
|
||
const { combineLatestWith = null, shouldUpdate = () => true, msTimeout = 1000 } = options;
|
||
return {
|
||
combineLatestWith: combineLatestWith,
|
||
shouldUpdate: shouldUpdate,
|
||
msTimeout: msTimeout,
|
||
};
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/state-base.ts
|
||
var state_base_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
class StateBase {
|
||
constructor(key, storageService, keyDefinition, logService) {
|
||
this.key = key;
|
||
this.storageService = storageService;
|
||
this.keyDefinition = keyDefinition;
|
||
this.logService = logService;
|
||
const storageUpdate$ = storageService.updates$.pipe(filter_filter((storageUpdate) => storageUpdate.key === key), switchMap_switchMap((storageUpdate) => state_base_awaiter(this, void 0, void 0, function* () {
|
||
if (storageUpdate.updateType === "remove") {
|
||
return null;
|
||
}
|
||
return yield getStoredValue(key, storageService, keyDefinition.deserializer);
|
||
})));
|
||
let state$ = merge_merge(defer(() => getStoredValue(key, storageService, keyDefinition.deserializer)), storageUpdate$);
|
||
if (keyDefinition.debug.enableRetrievalLogging) {
|
||
state$ = state$.pipe(tap({
|
||
next: (v) => {
|
||
this.logService.info(`Retrieving '${key}' from storage, value is ${v == null ? "null" : "non-null"}`);
|
||
},
|
||
}));
|
||
}
|
||
// If 0 cleanup is chosen, treat this as absolutely no cache
|
||
if (keyDefinition.cleanupDelayMs !== 0) {
|
||
state$ = state$.pipe(share_share({
|
||
connector: () => new ReplaySubject_ReplaySubject(1),
|
||
resetOnRefCountZero: () => timer_timer(keyDefinition.cleanupDelayMs),
|
||
}));
|
||
}
|
||
this.state$ = state$;
|
||
}
|
||
update(configureState_1) {
|
||
return state_base_awaiter(this, arguments, void 0, function* (configureState, options = {}) {
|
||
const normalizedOptions = populateOptionsWithDefault(options);
|
||
if (this.updatePromise != null) {
|
||
yield this.updatePromise;
|
||
}
|
||
try {
|
||
this.updatePromise = this.internalUpdate(configureState, normalizedOptions);
|
||
return yield this.updatePromise;
|
||
}
|
||
finally {
|
||
this.updatePromise = null;
|
||
}
|
||
});
|
||
}
|
||
internalUpdate(configureState, options) {
|
||
return state_base_awaiter(this, void 0, void 0, function* () {
|
||
const currentState = yield this.getStateForUpdate();
|
||
const combinedDependencies = options.combineLatestWith != null
|
||
? yield firstValueFrom_firstValueFrom(options.combineLatestWith.pipe(timeout_timeout(options.msTimeout)))
|
||
: null;
|
||
if (!options.shouldUpdate(currentState, combinedDependencies)) {
|
||
return currentState;
|
||
}
|
||
const newState = configureState(currentState, combinedDependencies);
|
||
yield this.doStorageSave(newState, currentState);
|
||
return newState;
|
||
});
|
||
}
|
||
doStorageSave(newState, oldState) {
|
||
return state_base_awaiter(this, void 0, void 0, function* () {
|
||
if (this.keyDefinition.debug.enableUpdateLogging) {
|
||
this.logService.info(`Updating '${this.key}' from ${oldState == null ? "null" : "non-null"} to ${newState == null ? "null" : "non-null"}`);
|
||
}
|
||
yield this.storageService.save(this.key, newState);
|
||
});
|
||
}
|
||
/** For use in update methods, does not wait for update to complete before yielding state.
|
||
* The expectation is that that await is already done
|
||
*/
|
||
getStateForUpdate() {
|
||
return state_base_awaiter(this, void 0, void 0, function* () {
|
||
return yield getStoredValue(this.key, this.storageService, this.keyDefinition.deserializer);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-global-state.ts
|
||
|
||
|
||
class default_global_state_DefaultGlobalState extends StateBase {
|
||
constructor(keyDefinition, chosenLocation, logService) {
|
||
super(util_globalKeyBuilder(keyDefinition), chosenLocation, keyDefinition, logService);
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-global-state.provider.ts
|
||
|
||
class DefaultGlobalStateProvider {
|
||
constructor(storageServiceProvider, logService) {
|
||
this.storageServiceProvider = storageServiceProvider;
|
||
this.logService = logService;
|
||
this.globalStateCache = {};
|
||
}
|
||
get(keyDefinition) {
|
||
const [location, storageService] = this.storageServiceProvider.get(keyDefinition.stateDefinition.defaultStorageLocation, keyDefinition.stateDefinition.storageLocationOverrides);
|
||
const cacheKey = this.buildCacheKey(location, keyDefinition);
|
||
const existingGlobalState = this.globalStateCache[cacheKey];
|
||
if (existingGlobalState != null) {
|
||
// The cast into the actual generic is safe because of rules around key definitions
|
||
// being unique.
|
||
return existingGlobalState;
|
||
}
|
||
const newGlobalState = new DefaultGlobalState(keyDefinition, storageService, this.logService);
|
||
this.globalStateCache[cacheKey] = newGlobalState;
|
||
return newGlobalState;
|
||
}
|
||
buildCacheKey(location, keyDefinition) {
|
||
return `${location}_${keyDefinition.fullName}`;
|
||
}
|
||
}
|
||
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/argsArgArrayOrObject.js
|
||
var isArray=Array.isArray;var getPrototypeOf=Object.getPrototypeOf,objectProto=Object.prototype,getKeys=Object.keys;function argsArgArrayOrObject(args){if(args.length===1){var first_1=args[0];if(isArray(first_1)){return{args:first_1,keys:null};}if(isPOJO(first_1)){var keys=getKeys(first_1);return{args:keys.map(function(key){return first_1[key];}),keys:keys};}}return{args:args,keys:null};}function isPOJO(obj){return obj&&typeof obj==='object'&&getPrototypeOf(obj)===objectProto;}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/mapOneOrManyArgs.js
|
||
var mapOneOrManyArgs_isArray=Array.isArray;function callOrApply(fn,args){return mapOneOrManyArgs_isArray(args)?fn.apply(void 0,__spreadArray([],__read(args))):fn(args);}function mapOneOrManyArgs(fn){return map_map(function(args){return callOrApply(fn,args);});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/util/createObject.js
|
||
function createObject(keys,values){return keys.reduce(function(result,key,i){return result[key]=values[i],result;},{});}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/combineLatest.js
|
||
function combineLatest_combineLatest(){var args=[];for(var _i=0;_i<arguments.length;_i++){args[_i]=arguments[_i];}var scheduler=popScheduler(args);var resultSelector=popResultSelector(args);var _a=argsArgArrayOrObject(args),observables=_a.args,keys=_a.keys;if(observables.length===0){return from([],scheduler);}var result=new Observable_Observable(combineLatestInit(observables,scheduler,keys?function(values){return createObject(keys,values);}:identity));return resultSelector?result.pipe(mapOneOrManyArgs(resultSelector)):result;}function combineLatestInit(observables,scheduler,valueTransform){if(valueTransform===void 0){valueTransform=identity;}return function(subscriber){maybeSchedule(scheduler,function(){var length=observables.length;var values=new Array(length);var active=length;var remainingFirstValues=length;var _loop_1=function(i){maybeSchedule(scheduler,function(){var source=from(observables[i],scheduler);var hasFirstValue=false;source.subscribe(createOperatorSubscriber(subscriber,function(value){values[i]=value;if(!hasFirstValue){hasFirstValue=true;remainingFirstValues--;}if(!remainingFirstValues){subscriber.next(valueTransform(values.slice()));}},function(){if(! --active){subscriber.complete();}}));},subscriber);};for(var i=0;i<length;i++){_loop_1(i);}},subscriber);};}function maybeSchedule(scheduler,execute,subscription){if(scheduler){executeSchedule(subscription,scheduler,execute);}else{execute();}}
|
||
;// ../../libs/state-internal/src/default-single-user-state.ts
|
||
var default_single_user_state_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
class default_single_user_state_DefaultSingleUserState extends StateBase {
|
||
constructor(userId, keyDefinition, chosenLocation, stateEventRegistrarService, logService) {
|
||
super(keyDefinition.buildKey(userId), chosenLocation, keyDefinition, logService);
|
||
this.userId = userId;
|
||
this.stateEventRegistrarService = stateEventRegistrarService;
|
||
this.combinedState$ = combineLatest_combineLatest([of_of(userId), this.state$]);
|
||
}
|
||
doStorageSave(newState, oldState) {
|
||
const _super = Object.create(null, {
|
||
doStorageSave: { get: () => super.doStorageSave }
|
||
});
|
||
return default_single_user_state_awaiter(this, void 0, void 0, function* () {
|
||
yield _super.doStorageSave.call(this, newState, oldState);
|
||
yield this.stateEventRegistrarService.registerEvents(this.keyDefinition);
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-single-user-state.provider.ts
|
||
|
||
class DefaultSingleUserStateProvider {
|
||
constructor(storageServiceProvider, stateEventRegistrarService, logService) {
|
||
this.storageServiceProvider = storageServiceProvider;
|
||
this.stateEventRegistrarService = stateEventRegistrarService;
|
||
this.logService = logService;
|
||
this.cache = {};
|
||
}
|
||
get(userId, keyDefinition) {
|
||
const [location, storageService] = this.storageServiceProvider.get(keyDefinition.stateDefinition.defaultStorageLocation, keyDefinition.stateDefinition.storageLocationOverrides);
|
||
const cacheKey = this.buildCacheKey(location, userId, keyDefinition);
|
||
const existingUserState = this.cache[cacheKey];
|
||
if (existingUserState != null) {
|
||
// I have to cast out of the unknown generic but this should be safe if rules
|
||
// around domain token are made
|
||
return existingUserState;
|
||
}
|
||
const newUserState = new DefaultSingleUserState(userId, keyDefinition, storageService, this.stateEventRegistrarService, this.logService);
|
||
this.cache[cacheKey] = newUserState;
|
||
return newUserState;
|
||
}
|
||
buildCacheKey(location, userId, keyDefinition) {
|
||
return `${location}_${keyDefinition.fullName}_${userId}`;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-state.provider.ts
|
||
var default_state_provider_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
class DefaultStateProvider {
|
||
constructor(activeUserStateProvider, singleUserStateProvider, globalStateProvider, derivedStateProvider) {
|
||
this.activeUserStateProvider = activeUserStateProvider;
|
||
this.singleUserStateProvider = singleUserStateProvider;
|
||
this.globalStateProvider = globalStateProvider;
|
||
this.derivedStateProvider = derivedStateProvider;
|
||
this.getActive = this.activeUserStateProvider.get.bind(this.activeUserStateProvider);
|
||
this.getUser = this.singleUserStateProvider.get.bind(this.singleUserStateProvider);
|
||
this.getGlobal = this.globalStateProvider.get.bind(this.globalStateProvider);
|
||
this.getDerived = this.derivedStateProvider.get.bind(this.derivedStateProvider);
|
||
this.activeUserId$ = this.activeUserStateProvider.activeUserId$;
|
||
}
|
||
getUserState$(userKeyDefinition, userId) {
|
||
if (userId) {
|
||
return this.getUser(userId, userKeyDefinition).state$;
|
||
}
|
||
else {
|
||
return this.activeUserId$.pipe(filter((userId) => userId != null), // Filter out null-ish user ids since we can't get state for a null user id
|
||
take(1), switchMap((userId) => this.getUser(userId, userKeyDefinition).state$));
|
||
}
|
||
}
|
||
getUserStateOrDefault$(userKeyDefinition, config) {
|
||
const { userId, defaultValue = null } = config;
|
||
if (userId) {
|
||
return this.getUser(userId, userKeyDefinition).state$;
|
||
}
|
||
else {
|
||
return this.activeUserId$.pipe(take(1), switchMap((userId) => userId != null ? this.getUser(userId, userKeyDefinition).state$ : of(defaultValue)));
|
||
}
|
||
}
|
||
setUserState(userKeyDefinition, value, userId) {
|
||
return default_state_provider_awaiter(this, void 0, void 0, function* () {
|
||
if (userId) {
|
||
return [userId, yield this.getUser(userId, userKeyDefinition).update(() => value)];
|
||
}
|
||
else {
|
||
return yield this.getActive(userKeyDefinition).update(() => value);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/inline-derived-state.ts
|
||
var inline_derived_state_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class InlineDerivedStateProvider {
|
||
get(parentState$, deriveDefinition, dependencies) {
|
||
return new InlineDerivedState(parentState$, deriveDefinition, dependencies);
|
||
}
|
||
}
|
||
class InlineDerivedState {
|
||
constructor(parentState$, deriveDefinition, dependencies) {
|
||
this.state$ = parentState$.pipe(concatMap((value) => inline_derived_state_awaiter(this, void 0, void 0, function* () { return yield deriveDefinition.derive(value, dependencies); })));
|
||
}
|
||
forceValue(value) {
|
||
// No need to force anything, we don't keep a cache
|
||
return Promise.resolve(value);
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/legacy/default-state.service.ts
|
||
var default_state_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
const keys = {
|
||
global: "global",
|
||
};
|
||
const partialKeys = {
|
||
userAutoKey: "_user_auto",
|
||
userBiometricKey: "_user_biometric",
|
||
};
|
||
const DDG_SHARED_KEY = "DuckDuckGoSharedKey";
|
||
class DefaultStateService {
|
||
constructor(storageService, secureStorageService, activeUserAccessor) {
|
||
this.storageService = storageService;
|
||
this.secureStorageService = secureStorageService;
|
||
this.activeUserAccessor = activeUserAccessor;
|
||
}
|
||
clean(options) {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.setUserKeyAutoUnlock(null, options);
|
||
yield this.clearUserKeyBiometric(options.userId);
|
||
});
|
||
}
|
||
/**
|
||
* user key when using the "never" option of vault timeout
|
||
*/
|
||
getUserKeyAutoUnlock(options) {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
if (options.userId == null) {
|
||
return null;
|
||
}
|
||
return yield this.secureStorageService.get(`${options.userId}${partialKeys.userAutoKey}`, {
|
||
userId: options.userId,
|
||
keySuffix: "auto",
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* user key when using the "never" option of vault timeout
|
||
*/
|
||
setUserKeyAutoUnlock(value, options) {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
if (options.userId == null) {
|
||
return;
|
||
}
|
||
yield this.saveSecureStorageKey(partialKeys.userAutoKey, value, options.userId, "auto");
|
||
});
|
||
}
|
||
clearUserKeyBiometric(userId) {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
if (userId == null) {
|
||
return;
|
||
}
|
||
yield this.saveSecureStorageKey(partialKeys.userBiometricKey, null, userId, "biometric");
|
||
});
|
||
}
|
||
getDuckDuckGoSharedKey() {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
const userId = yield this.getActiveUserIdFromStorage();
|
||
if (userId == null) {
|
||
return null;
|
||
}
|
||
return yield this.secureStorageService.get(DDG_SHARED_KEY);
|
||
});
|
||
}
|
||
setDuckDuckGoSharedKey(value) {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
const userId = yield this.getActiveUserIdFromStorage();
|
||
if (userId == null) {
|
||
return;
|
||
}
|
||
value == null
|
||
? yield this.secureStorageService.remove(DDG_SHARED_KEY)
|
||
: yield this.secureStorageService.save(DDG_SHARED_KEY, value);
|
||
});
|
||
}
|
||
setEnableDuckDuckGoBrowserIntegration(value) {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const globals = (_a = (yield this.storageService.get(keys.global))) !== null && _a !== void 0 ? _a : new GlobalState();
|
||
globals.enableDuckDuckGoBrowserIntegration = value;
|
||
yield this.storageService.save(keys.global, globals);
|
||
});
|
||
}
|
||
getActiveUserIdFromStorage() {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
return yield firstValueFrom(this.activeUserAccessor.activeUserId$);
|
||
});
|
||
}
|
||
saveSecureStorageKey(key, value, userId, keySuffix) {
|
||
return default_state_service_awaiter(this, void 0, void 0, function* () {
|
||
return value == null
|
||
? yield this.secureStorageService.remove(`${userId}${key}`, { keySuffix: keySuffix })
|
||
: yield this.secureStorageService.save(`${userId}${key}`, value, {
|
||
keySuffix: keySuffix,
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-state-event-registrar.service.ts
|
||
var default_state_event_registrar_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
const default_state_event_registrar_service_STATE_LOCK_EVENT = KeyDefinition.array(CLEAR_EVENT_DISK, "lock", {
|
||
deserializer: (e) => e,
|
||
});
|
||
const default_state_event_registrar_service_STATE_LOGOUT_EVENT = KeyDefinition.array(CLEAR_EVENT_DISK, "logout", {
|
||
deserializer: (e) => e,
|
||
});
|
||
class DefaultStateEventRegistrarService {
|
||
constructor(globalStateProvider, storageServiceProvider) {
|
||
this.storageServiceProvider = storageServiceProvider;
|
||
this.stateEventStateMap = {
|
||
lock: globalStateProvider.get(default_state_event_registrar_service_STATE_LOCK_EVENT),
|
||
logout: globalStateProvider.get(default_state_event_registrar_service_STATE_LOGOUT_EVENT),
|
||
};
|
||
}
|
||
registerEvents(keyDefinition) {
|
||
return default_state_event_registrar_service_awaiter(this, void 0, void 0, function* () {
|
||
for (const clearEvent of keyDefinition.clearOn) {
|
||
const eventState = this.stateEventStateMap[clearEvent];
|
||
// Determine the storage location for this
|
||
const [storageLocation] = this.storageServiceProvider.get(keyDefinition.stateDefinition.defaultStorageLocation, keyDefinition.stateDefinition.storageLocationOverrides);
|
||
const newEvent = {
|
||
state: keyDefinition.stateDefinition.name,
|
||
key: keyDefinition.key,
|
||
location: storageLocation,
|
||
};
|
||
// Only update the event state if the existing list doesn't have a matching entry
|
||
yield eventState.update((existingTickets) => {
|
||
existingTickets !== null && existingTickets !== void 0 ? existingTickets : (existingTickets = []);
|
||
existingTickets.push(newEvent);
|
||
return existingTickets;
|
||
}, {
|
||
shouldUpdate: (currentTickets) => {
|
||
return (
|
||
// If the current tickets are null, then it will for sure be added
|
||
currentTickets == null ||
|
||
// If an existing match couldn't be found, we also need to add one
|
||
currentTickets.findIndex((e) => e.state === newEvent.state &&
|
||
e.key === newEvent.key &&
|
||
e.location === newEvent.location) === -1);
|
||
},
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/default-state-event-runner.service.ts
|
||
var default_state_event_runner_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
|
||
class DefaultStateEventRunnerService {
|
||
constructor(globalStateProvider, storageServiceProvider) {
|
||
this.storageServiceProvider = storageServiceProvider;
|
||
this.stateEventMap = {
|
||
lock: globalStateProvider.get(STATE_LOCK_EVENT),
|
||
logout: globalStateProvider.get(STATE_LOGOUT_EVENT),
|
||
};
|
||
}
|
||
handleEvent(event, userId) {
|
||
return default_state_event_runner_service_awaiter(this, void 0, void 0, function* () {
|
||
let tickets = yield firstValueFrom(this.stateEventMap[event].state$);
|
||
tickets !== null && tickets !== void 0 ? tickets : (tickets = []);
|
||
const failures = [];
|
||
for (const ticket of tickets) {
|
||
try {
|
||
const [, service] = this.storageServiceProvider.get(ticket.location, {});
|
||
const ticketStorageKey = this.storageKeyFor(userId, ticket);
|
||
// Evaluate current value so we can avoid writing to state if we don't need to
|
||
const currentValue = yield service.get(ticketStorageKey);
|
||
if (currentValue != null) {
|
||
yield service.remove(ticketStorageKey);
|
||
}
|
||
}
|
||
catch (err) {
|
||
let errorMessage = "Unknown Error";
|
||
if (err != null &&
|
||
typeof err === "object" &&
|
||
"message" in err &&
|
||
typeof err.message === "string") {
|
||
errorMessage = err.message;
|
||
}
|
||
failures.push(`${errorMessage} in ${ticket.state} > ${ticket.key} located ${ticket.location}`);
|
||
}
|
||
}
|
||
if (failures.length > 0) {
|
||
// Throw aggregated error
|
||
throw new Error(`One or more errors occurred while handling event '${event}' for user ${userId}.\n${failures.join("\n")}`);
|
||
}
|
||
});
|
||
}
|
||
storageKeyFor(userId, ticket) {
|
||
const userKey = new UserKeyDefinition(new StateDefinition(ticket.state, ticket.location), ticket.key, {
|
||
deserializer: (v) => v,
|
||
clearOn: [],
|
||
});
|
||
return userKey.buildKey(userId);
|
||
}
|
||
}
|
||
|
||
;// ../../libs/state-internal/src/index.ts
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;// ../../libs/common/src/platform/state/index.ts
|
||
|
||
|
||
|
||
;// ../../libs/common/src/auth/services/account.service.ts
|
||
var account_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
|
||
const account_service_ACCOUNT_ACCOUNTS = KeyDefinition.record(ACCOUNT_DISK, "accounts", {
|
||
deserializer: (accountInfo) => (Object.assign(Object.assign({}, accountInfo), { creationDate: accountInfo.creationDate ? new Date(accountInfo.creationDate) : undefined })),
|
||
});
|
||
const account_service_ACCOUNT_ACTIVE_ACCOUNT_ID = new KeyDefinition(ACCOUNT_DISK, "activeAccountId", {
|
||
deserializer: (id) => id,
|
||
});
|
||
const account_service_ACCOUNT_ACTIVITY = KeyDefinition.record(ACCOUNT_DISK, "activity", {
|
||
deserializer: (activity) => new Date(activity),
|
||
});
|
||
const ACCOUNT_VERIFY_NEW_DEVICE_LOGIN = new user_key_definition_UserKeyDefinition(ACCOUNT_DISK, "verifyNewDeviceLogin", {
|
||
deserializer: (verifyDevices) => verifyDevices,
|
||
clearOn: ["logout"],
|
||
});
|
||
const LOGGED_OUT_INFO = {
|
||
email: "",
|
||
emailVerified: false,
|
||
name: undefined,
|
||
creationDate: undefined,
|
||
};
|
||
/**
|
||
* An rxjs map operator that extracts the UserId from an account, or throws if the account or UserId are null.
|
||
*/
|
||
const getUserId = map_map((account) => {
|
||
if (account == null) {
|
||
throw new Error("Null or undefined account");
|
||
}
|
||
return account.id;
|
||
});
|
||
/**
|
||
* An rxjs map operator that extracts the UserId from an account, or returns undefined if the account or UserId are null.
|
||
*/
|
||
const getOptionalUserId = map_map((account) => { var _a; return (_a = account === null || account === void 0 ? void 0 : account.id) !== null && _a !== void 0 ? _a : null; });
|
||
class AccountServiceImplementation {
|
||
constructor(messagingService, logService, globalStateProvider, singleUserStateProvider) {
|
||
this.messagingService = messagingService;
|
||
this.logService = logService;
|
||
this.globalStateProvider = globalStateProvider;
|
||
this.singleUserStateProvider = singleUserStateProvider;
|
||
this._showHeader$ = new BehaviorSubject(true);
|
||
this.showHeader$ = this._showHeader$.asObservable();
|
||
this.accountsState = this.globalStateProvider.get(account_service_ACCOUNT_ACCOUNTS);
|
||
this.activeAccountIdState = this.globalStateProvider.get(account_service_ACCOUNT_ACTIVE_ACCOUNT_ID);
|
||
this.accounts$ = this.accountsState.state$.pipe(map((accounts) => (accounts == null ? {} : accounts)));
|
||
this.activeAccount$ = this.activeAccountIdState.state$.pipe(combineLatestWith(this.accounts$), map(([id, accounts]) => (id ? Object.assign({ id }, accounts[id]) : null)), distinctUntilChanged((a, b) => (a === null || a === void 0 ? void 0 : a.id) === (b === null || b === void 0 ? void 0 : b.id) && this.accountInfoEqual(a, b)), shareReplay({ bufferSize: 1, refCount: false }));
|
||
this.accountActivity$ = this.globalStateProvider
|
||
.get(account_service_ACCOUNT_ACTIVITY)
|
||
.state$.pipe(map((activity) => activity !== null && activity !== void 0 ? activity : {}));
|
||
this.sortedUserIds$ = this.accountActivity$.pipe(map((activity) => {
|
||
return Object.entries(activity)
|
||
.map(([userId, lastActive]) => ({ userId, lastActive }))
|
||
.sort((a, b) => b.lastActive.getTime() - a.lastActive.getTime()) // later dates first
|
||
.map((a) => a.userId);
|
||
}));
|
||
this.nextUpAccount$ = combineLatest([
|
||
this.accounts$,
|
||
this.activeAccount$,
|
||
this.sortedUserIds$,
|
||
]).pipe(map(([accounts, activeAccount, sortedUserIds]) => {
|
||
const nextId = sortedUserIds.find((id) => id !== (activeAccount === null || activeAccount === void 0 ? void 0 : activeAccount.id) && accounts[id] != null);
|
||
return nextId ? Object.assign({ id: nextId }, accounts[nextId]) : null;
|
||
}));
|
||
this.accountVerifyNewDeviceLogin$ = this.activeAccountIdState.state$.pipe(switchMap((userId) => this.singleUserStateProvider.get(userId, ACCOUNT_VERIFY_NEW_DEVICE_LOGIN).state$));
|
||
}
|
||
addAccount(userId, accountData) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!Utils.isGuid(userId)) {
|
||
throw new Error("userId is required");
|
||
}
|
||
yield this.accountsState.update((accounts) => {
|
||
accounts || (accounts = {});
|
||
accounts[userId] = accountData;
|
||
return accounts;
|
||
});
|
||
yield this.setAccountActivity(userId, new Date());
|
||
});
|
||
}
|
||
setAccountName(userId, name) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.setAccountInfo(userId, { name });
|
||
});
|
||
}
|
||
setAccountEmail(userId, email) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.setAccountInfo(userId, { email });
|
||
});
|
||
}
|
||
setAccountEmailVerified(userId, emailVerified) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.setAccountInfo(userId, { emailVerified });
|
||
});
|
||
}
|
||
setAccountCreationDate(userId, creationDate) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.setAccountInfo(userId, { creationDate });
|
||
});
|
||
}
|
||
clean(userId) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.setAccountInfo(userId, LOGGED_OUT_INFO);
|
||
yield this.removeAccountActivity(userId);
|
||
});
|
||
}
|
||
switchAccount(userId) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
let updateActivity = false;
|
||
yield this.activeAccountIdState.update((_, __) => {
|
||
updateActivity = true;
|
||
return userId;
|
||
}, {
|
||
combineLatestWith: this.accountsState.state$.pipe(filter((accounts) => {
|
||
if (userId == null) {
|
||
// Don't worry about accounts when we are about to set active user to null
|
||
return true;
|
||
}
|
||
return (accounts === null || accounts === void 0 ? void 0 : accounts[userId]) != null;
|
||
}),
|
||
// If we don't get the desired account with enough time, just return empty as that will result in the same error
|
||
timeout({ first: 1000, with: () => of({}) })),
|
||
shouldUpdate: (id, accounts) => {
|
||
if (userId != null && (accounts === null || accounts === void 0 ? void 0 : accounts[userId]) == null) {
|
||
throw new Error("Account does not exist");
|
||
}
|
||
// update only if userId changes
|
||
return id !== userId;
|
||
},
|
||
});
|
||
if (updateActivity) {
|
||
yield this.setAccountActivity(userId, new Date());
|
||
}
|
||
});
|
||
}
|
||
setAccountActivity(userId, lastActivity) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!Utils.isGuid(userId)) {
|
||
// only store for valid userIds
|
||
return;
|
||
}
|
||
yield this.globalStateProvider.get(account_service_ACCOUNT_ACTIVITY).update((activity) => {
|
||
activity || (activity = {});
|
||
activity[userId] = lastActivity;
|
||
return activity;
|
||
}, {
|
||
shouldUpdate: (oldActivity) => { var _a; return ((_a = oldActivity === null || oldActivity === void 0 ? void 0 : oldActivity[userId]) === null || _a === void 0 ? void 0 : _a.getTime()) !== (lastActivity === null || lastActivity === void 0 ? void 0 : lastActivity.getTime()); },
|
||
});
|
||
});
|
||
}
|
||
setAccountVerifyNewDeviceLogin(userId, setVerifyNewDeviceLogin) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!Utils.isGuid(userId)) {
|
||
// only store for valid userIds
|
||
return;
|
||
}
|
||
yield this.singleUserStateProvider
|
||
.get(userId, ACCOUNT_VERIFY_NEW_DEVICE_LOGIN)
|
||
.update(() => setVerifyNewDeviceLogin, {
|
||
shouldUpdate: (previousValue) => previousValue !== setVerifyNewDeviceLogin,
|
||
});
|
||
});
|
||
}
|
||
removeAccountActivity(userId) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
yield this.globalStateProvider.get(account_service_ACCOUNT_ACTIVITY).update((activity) => {
|
||
if (activity == null) {
|
||
return activity;
|
||
}
|
||
delete activity[userId];
|
||
return activity;
|
||
}, { shouldUpdate: (oldActivity) => (oldActivity === null || oldActivity === void 0 ? void 0 : oldActivity[userId]) != null });
|
||
});
|
||
}
|
||
// TODO: update to use our own account status settings. Requires inverting direction of state service accounts flow
|
||
delete() {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
try {
|
||
(_a = this.messagingService) === null || _a === void 0 ? void 0 : _a.send("logout");
|
||
}
|
||
catch (e) {
|
||
this.logService.error(e);
|
||
throw e;
|
||
}
|
||
});
|
||
}
|
||
setShowHeader(visible) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
this._showHeader$.next(visible);
|
||
});
|
||
}
|
||
accountInfoEqual(a, b) {
|
||
var _a, _b;
|
||
if (a == null && b == null) {
|
||
return true;
|
||
}
|
||
if (a == null || b == null) {
|
||
return false;
|
||
}
|
||
return (a.email === b.email &&
|
||
a.emailVerified === b.emailVerified &&
|
||
a.name === b.name &&
|
||
((_a = a.creationDate) === null || _a === void 0 ? void 0 : _a.getTime()) === ((_b = b.creationDate) === null || _b === void 0 ? void 0 : _b.getTime()));
|
||
}
|
||
setAccountInfo(userId, update) {
|
||
return account_service_awaiter(this, void 0, void 0, function* () {
|
||
function newAccountInfo(oldAccountInfo) {
|
||
return Object.assign(Object.assign({}, oldAccountInfo), update);
|
||
}
|
||
yield this.accountsState.update((accounts) => {
|
||
accounts[userId] = newAccountInfo(accounts[userId]);
|
||
return accounts;
|
||
}, {
|
||
// Avoid unnecessary updates
|
||
// TODO: Faster comparison, maybe include a hash on the objects?
|
||
shouldUpdate: (accounts) => {
|
||
if ((accounts === null || accounts === void 0 ? void 0 : accounts[userId]) == null) {
|
||
throw new Error("Account does not exist");
|
||
}
|
||
return !this.accountInfoEqual(accounts[userId], newAccountInfo(accounts[userId]));
|
||
},
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
;// ../../libs/common/src/autofill/utils.ts
|
||
|
||
|
||
/**
|
||
* Takes a string or number value and returns a string value formatted as a valid 4-digit year
|
||
*
|
||
* @param {(string | number)} yearInput
|
||
* @return {*} {(Year | null)}
|
||
*/
|
||
function normalizeExpiryYearFormat(yearInput) {
|
||
// The input[type="number"] is returning a number, convert it to a string
|
||
// An empty field returns null, avoid casting `"null"` to a string
|
||
const yearInputIsEmpty = yearInput == null || yearInput === "";
|
||
let expirationYear = yearInputIsEmpty ? null : `${yearInput}`;
|
||
// Exit early if year is already formatted correctly or empty
|
||
if (yearInputIsEmpty || (expirationYear && /^[1-9]{1}\d{3}$/.test(expirationYear))) {
|
||
return expirationYear;
|
||
}
|
||
expirationYear = (expirationYear || "")
|
||
// For safety, because even input[type="number"] will allow decimals
|
||
.replace(/[^\d]/g, "")
|
||
// remove any leading zero padding (leave the last leading zero if it ends the string)
|
||
.replace(/^[0]+(?=.)/, "");
|
||
if (expirationYear === "") {
|
||
expirationYear = null;
|
||
}
|
||
// given the context of payment card expiry, a year character length of 3, or over 4
|
||
// is more likely to be a mistake than an intentional value for the far past or far future.
|
||
if (expirationYear && expirationYear.length !== 4) {
|
||
const paddedYear = ("00" + expirationYear).slice(-2);
|
||
const currentCentury = `${new Date().getFullYear()}`.slice(0, 2);
|
||
expirationYear = currentCentury + paddedYear;
|
||
}
|
||
return expirationYear;
|
||
}
|
||
/**
|
||
* Takes a cipher card view and returns "true" if the month and year affirmativey indicate
|
||
* the card is expired. Uncertain cases return "false".
|
||
*
|
||
* @param {CardView} cipherCard
|
||
* @return {*} {boolean}
|
||
*/
|
||
function isCardExpired(cipherCard) {
|
||
if (cipherCard) {
|
||
const { expMonth = null, expYear = null } = cipherCard;
|
||
if (!expYear) {
|
||
return false;
|
||
}
|
||
const now = new Date();
|
||
const normalizedYear = normalizeExpiryYearFormat(expYear);
|
||
const parsedYear = normalizedYear ? parseInt(normalizedYear, 10) : NaN;
|
||
const expiryYearIsBeforeCurrentYear = parsedYear < now.getFullYear();
|
||
const expiryYearIsAfterCurrentYear = parsedYear > now.getFullYear();
|
||
// If the expiry year is before the current year, skip checking the month, since it must be expired
|
||
if (normalizedYear && expiryYearIsBeforeCurrentYear) {
|
||
return true;
|
||
}
|
||
// If the expiry year is after the current year, skip checking the month, since it cannot be expired
|
||
if (normalizedYear && expiryYearIsAfterCurrentYear) {
|
||
return false;
|
||
}
|
||
if (normalizedYear && expMonth) {
|
||
const parsedMonthInteger = parseInt(expMonth, 10);
|
||
const parsedMonthIsValid = parsedMonthInteger && !isNaN(parsedMonthInteger);
|
||
// If the parsed month value is 0, we don't know when the expiry passes this year, so do not treat it as expired
|
||
if (!parsedMonthIsValid) {
|
||
return false;
|
||
}
|
||
// `Date` months are zero-indexed
|
||
const parsedMonth = parsedMonthInteger - 1;
|
||
// First day of the next month
|
||
const cardExpiry = new Date(parsedYear, parsedMonth + 1, 1);
|
||
return cardExpiry <= now;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Attempt to split a string into date segments on the basis of expected formats and delimiter symbols.
|
||
*
|
||
* @param {string} combinedExpiryValue
|
||
* @return {*} {string[]}
|
||
*/
|
||
function splitCombinedDateValues(combinedExpiryValue) {
|
||
var _a;
|
||
let sanitizedValue = combinedExpiryValue
|
||
.replace(IrrelevantExpiryCharactersPatternExpression, "")
|
||
.trim();
|
||
// Do this after initial value replace to avoid identifying leading whitespace as delimiter
|
||
const parsedDelimiter = ((_a = sanitizedValue.match(DelimiterPatternExpression)) === null || _a === void 0 ? void 0 : _a[0]) || null;
|
||
let dateParts = [sanitizedValue];
|
||
if (parsedDelimiter === null || parsedDelimiter === void 0 ? void 0 : parsedDelimiter.length) {
|
||
// If the parsed delimiter is a whitespace character, assign 's' (character class) instead
|
||
const delimiterPattern = /\s/.test(parsedDelimiter) ? "\\s" : "\\" + parsedDelimiter;
|
||
sanitizedValue = sanitizedValue
|
||
// Remove all other delimiter characters not identified as the delimiter
|
||
.replace(new RegExp(`[^\\d${delimiterPattern}]`, "g"), "")
|
||
// Also de-dupe the delimiter character
|
||
.replace(new RegExp(`[${delimiterPattern}]{2,}`, "g"), parsedDelimiter);
|
||
dateParts = sanitizedValue.split(parsedDelimiter);
|
||
}
|
||
return (dateParts
|
||
// remove values that have no length
|
||
.filter((splitValue) => splitValue === null || splitValue === void 0 ? void 0 : splitValue.length));
|
||
}
|
||
/**
|
||
* Given an array of split card expiry date parts,
|
||
* returns an array of those values ordered by year then month
|
||
*
|
||
* @param {string[]} splitDateInput
|
||
* @return {*} {([string | null, string | null])}
|
||
*/
|
||
function parseDelimitedYearMonthExpiry([firstPart, secondPart]) {
|
||
// Conditionals here are structured to avoid unnecessary evaluations and are ordered
|
||
// from more authoritative checks to checks yielding increasingly inferred conclusions
|
||
// If a 4-digit value is found (when there are multiple parts), it can't be month
|
||
if (ExpiryFullYearPatternExpression.test(firstPart)) {
|
||
return [firstPart, secondPart];
|
||
}
|
||
// If a 4-digit value is found (when there are multiple parts), it can't be month
|
||
if (ExpiryFullYearPatternExpression.test(secondPart)) {
|
||
return [secondPart, firstPart];
|
||
}
|
||
// If it's a two digit value that doesn't match against month pattern, assume it's a year
|
||
if (/\d{2}/.test(firstPart) && !MonthPatternExpression.test(firstPart)) {
|
||
return [firstPart, secondPart];
|
||
}
|
||
// If it's a two digit value that doesn't match against month pattern, assume it's a year
|
||
if (/\d{2}/.test(secondPart) && !MonthPatternExpression.test(secondPart)) {
|
||
return [secondPart, firstPart];
|
||
}
|
||
// Values are too ambiguous (e.g. "12/09"). For the most part,
|
||
// a month-looking value likely is, at the time of writing (year 2024).
|
||
let parsedYear = firstPart;
|
||
let parsedMonth = secondPart;
|
||
if (MonthPatternExpression.test(firstPart)) {
|
||
parsedYear = secondPart;
|
||
parsedMonth = firstPart;
|
||
}
|
||
return [parsedYear, parsedMonth];
|
||
}
|
||
/**
|
||
* Given a single string of integers, attempts to identify card expiry date portions within
|
||
* and return values ordered by year then month
|
||
*
|
||
* @param {string} dateInput
|
||
* @return {*} {([string | null, string | null])}
|
||
*/
|
||
function parseNonDelimitedYearMonthExpiry(dateInput) {
|
||
if (dateInput.length > 4) {
|
||
// e.g.
|
||
// "052024"
|
||
// "202405"
|
||
// "20245"
|
||
// "52024"
|
||
// If the value is over 5-characters long, it likely has a full year format in it
|
||
const [parsedYear, parsedMonth] = dateInput
|
||
.split(new RegExp(`(?=${ExpiryFullYearPattern})|(?<=${ExpiryFullYearPattern})`, "g"))
|
||
.sort((current, next) => (current.length > next.length ? -1 : 1));
|
||
return [parsedYear, parsedMonth];
|
||
}
|
||
if (dateInput.length === 4) {
|
||
// e.g.
|
||
// "0524"
|
||
// "2405"
|
||
// If the `sanitizedFirstPart` value is a length of 4, it must be split in half, since
|
||
// neither a year or month will be represented with three characters
|
||
const splitFirstPartFirstHalf = dateInput.slice(0, 2);
|
||
const splitFirstPartSecondHalf = dateInput.slice(-2);
|
||
let parsedYear = splitFirstPartSecondHalf;
|
||
let parsedMonth = splitFirstPartFirstHalf;
|
||
// If the first part doesn't match a month pattern, assume it's a year
|
||
if (!MonthPatternExpression.test(splitFirstPartFirstHalf)) {
|
||
parsedYear = splitFirstPartFirstHalf;
|
||
parsedMonth = splitFirstPartSecondHalf;
|
||
}
|
||
return [parsedYear, parsedMonth];
|
||
}
|
||
// e.g.
|
||
// "245"
|
||
// "202"
|
||
// "212"
|
||
// "022"
|
||
// "111"
|
||
// A valid year representation here must be two characters so try to find it first.
|
||
let parsedYear = null;
|
||
let parsedMonth = null;
|
||
// Split if there is a digit with a leading zero
|
||
const splitFirstPartOnLeadingZero = dateInput.split(/(?<=0[1-9]{1})|(?=0[1-9]{1})/);
|
||
// Assume a leading zero indicates a month in ambiguous cases (e.g. "202"), since we're
|
||
// dealing with expiry dates and the next two-digit year with a leading zero will be 2100
|
||
if (splitFirstPartOnLeadingZero.length > 1) {
|
||
parsedYear = splitFirstPartOnLeadingZero[0];
|
||
parsedMonth = splitFirstPartOnLeadingZero[1];
|
||
if (splitFirstPartOnLeadingZero[0].startsWith("0")) {
|
||
parsedMonth = splitFirstPartOnLeadingZero[0];
|
||
parsedYear = splitFirstPartOnLeadingZero[1];
|
||
}
|
||
}
|
||
else {
|
||
// Here, a year has to be two-digits, and a month can't be more than one, so assume the first two digits that are greater than the current year is the year representation.
|
||
parsedYear = dateInput.slice(0, 2);
|
||
parsedMonth = dateInput.slice(-1);
|
||
const currentYear = new Date().getFullYear();
|
||
const normalizedYearFormat = normalizeExpiryYearFormat(parsedYear);
|
||
const normalizedParsedYear = normalizedYearFormat && parseInt(normalizedYearFormat, 10);
|
||
const normalizedExpiryYearFormat = normalizeExpiryYearFormat(dateInput.slice(-2));
|
||
const normalizedParsedYearAlternative = normalizedExpiryYearFormat && parseInt(normalizedExpiryYearFormat, 10);
|
||
if (normalizedParsedYear &&
|
||
normalizedParsedYear < currentYear &&
|
||
normalizedParsedYearAlternative &&
|
||
normalizedParsedYearAlternative >= currentYear) {
|
||
parsedYear = dateInput.slice(-2);
|
||
parsedMonth = dateInput.slice(0, 1);
|
||
}
|
||
}
|
||
return [parsedYear, parsedMonth];
|
||
}
|
||
/**
|
||
* Attempt to parse year and month parts of a combined expiry date value.
|
||
*
|
||
* @param {string} combinedExpiryValue
|
||
* @return {*} {([string | null, string | null])}
|
||
*/
|
||
function parseYearMonthExpiry(combinedExpiryValue) {
|
||
var _a, _b;
|
||
let parsedYear = null;
|
||
let parsedMonth = null;
|
||
const dateParts = splitCombinedDateValues(combinedExpiryValue);
|
||
if (dateParts.length < 1) {
|
||
return [null, null];
|
||
}
|
||
const sanitizedFirstPart = ((_a = dateParts[0]) === null || _a === void 0 ? void 0 : _a.replace(IrrelevantExpiryCharactersPatternExpression, "")) || "";
|
||
const sanitizedSecondPart = ((_b = dateParts[1]) === null || _b === void 0 ? void 0 : _b.replace(IrrelevantExpiryCharactersPatternExpression, "")) || "";
|
||
// If there is only one date part, no delimiter was found in the passed value
|
||
if (dateParts.length === 1) {
|
||
const [parsedNonDelimitedYear, parsedNonDelimitedMonth] = parseNonDelimitedYearMonthExpiry(sanitizedFirstPart);
|
||
parsedYear = parsedNonDelimitedYear;
|
||
parsedMonth = parsedNonDelimitedMonth;
|
||
}
|
||
// There are multiple date parts
|
||
else {
|
||
const [parsedDelimitedYear, parsedDelimitedMonth] = parseDelimitedYearMonthExpiry([
|
||
sanitizedFirstPart,
|
||
sanitizedSecondPart,
|
||
]);
|
||
parsedYear = parsedDelimitedYear;
|
||
parsedMonth = parsedDelimitedMonth;
|
||
}
|
||
const normalizedParsedYear = parsedYear ? normalizeExpiryYearFormat(parsedYear) : null;
|
||
const normalizedParsedMonth = parsedMonth === null || parsedMonth === void 0 ? void 0 : parsedMonth.replace(/^0+/, "").slice(0, 2);
|
||
// Set "empty" values to null
|
||
parsedYear = (normalizedParsedYear === null || normalizedParsedYear === void 0 ? void 0 : normalizedParsedYear.length) ? normalizedParsedYear : null;
|
||
parsedMonth = (normalizedParsedMonth === null || normalizedParsedMonth === void 0 ? void 0 : normalizedParsedMonth.length) ? normalizedParsedMonth : null;
|
||
return [parsedYear, parsedMonth];
|
||
}
|
||
/**
|
||
* Takes a URL string and a NeverDomains object and determines if the passed URL's hostname is in `urlList`
|
||
*
|
||
* @param {string} url - representation of URL to check
|
||
* @param {NeverDomains} urlList - object with hostname key names
|
||
*/
|
||
function isUrlInList(url = "", urlList = {}) {
|
||
const urlListKeys = urlList && Object.keys(urlList);
|
||
if (urlListKeys.length && (url === null || url === void 0 ? void 0 : url.length)) {
|
||
let tabHostname;
|
||
try {
|
||
tabHostname = Utils.getHostname(url);
|
||
}
|
||
catch (_a) {
|
||
// If the input was invalid, exit early and return false
|
||
return false;
|
||
}
|
||
if (tabHostname) {
|
||
return urlListKeys.some((blockedHostname) => tabHostname.endsWith(blockedHostname));
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
;// ../../libs/common/src/models/domain/domain-service.ts
|
||
/*
|
||
See full documentation at:
|
||
https://bitwarden.com/help/uri-match-detection/#match-detection-options
|
||
|
||
Domain: "the top-level domain and second-level domain of the URI match the detected resource",
|
||
Host: "the hostname and (if specified) port of the URI matches the detected resource",
|
||
StartsWith: "the detected resource starts with the URI, regardless of what follows it",
|
||
Exact: "the URI matches the detected resource exactly",
|
||
RegularExpression: "the detected resource matches a specified regular expression",
|
||
Never: "never offer auto-fill for the item",
|
||
*/
|
||
const domain_service_UriMatchStrategy = {
|
||
Domain: 0,
|
||
Host: 1,
|
||
StartsWith: 2,
|
||
Exact: 3,
|
||
RegularExpression: 4,
|
||
Never: 5,
|
||
};
|
||
/**
|
||
* Normalizes UriMatchStrategySetting for SDK mapping.
|
||
* @param value - The URI match strategy from user data
|
||
* @returns Valid UriMatchType or undefined if invalid
|
||
*/
|
||
function normalizeUriMatchStrategyForSdk(value) {
|
||
if (value == null) {
|
||
return undefined;
|
||
}
|
||
switch (value) {
|
||
case 0: // Domain
|
||
case 1: // Host
|
||
case 2: // StartsWith
|
||
case 3: // Exact
|
||
case 4: // RegularExpression
|
||
case 5: // Never
|
||
return value;
|
||
default:
|
||
return undefined;
|
||
}
|
||
}
|
||
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/observable/interval.js
|
||
function interval(period,scheduler){if(period===void 0){period=0;}if(scheduler===void 0){scheduler=async_asyncScheduler;}if(period<0){period=0;}return timer_timer(period,period,scheduler);}
|
||
;// ../../node_modules/rxjs/dist/esm5/internal/operators/takeWhile.js
|
||
function takeWhile(predicate,inclusive){if(inclusive===void 0){inclusive=false;}return operate(function(source,subscriber){var index=0;source.subscribe(createOperatorSubscriber(subscriber,function(value){var result=predicate(value,index++);(result||inclusive)&&subscriber.next(value);!result&&subscriber.complete();}));});}
|
||
;// ./src/platform/browser/browser-popup-utils.ts
|
||
var browser_popup_utils_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
/**
|
||
*
|
||
* Value represents width in pixels
|
||
*/
|
||
const PopupWidthOptions = Object.freeze({
|
||
default: 380,
|
||
wide: 480,
|
||
"extra-wide": 600,
|
||
});
|
||
class browser_popup_utils_BrowserPopupUtils {
|
||
/**
|
||
* Identifies if the popup is within the sidebar.
|
||
*
|
||
* @param win - The passed window object.
|
||
*/
|
||
static inSidebar(win) {
|
||
return browser_popup_utils_BrowserPopupUtils.urlContainsSearchParams(win, "uilocation", "sidebar");
|
||
}
|
||
/**
|
||
* Identifies if the popup is within the popout.
|
||
*
|
||
* @param win - The passed window object.
|
||
*/
|
||
static inPopout(win) {
|
||
return browser_popup_utils_BrowserPopupUtils.urlContainsSearchParams(win, "uilocation", "popout");
|
||
}
|
||
/**
|
||
* Check if the current popup view is open inside of the current browser tab
|
||
* (it is possible in Chrome to open the extension in a tab)
|
||
*/
|
||
static isInTab() {
|
||
return browser_popup_utils_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const tabId = (_a = (yield browser_api_BrowserApi.getCurrentTab())) === null || _a === void 0 ? void 0 : _a.id;
|
||
if (tabId === undefined || tabId === null) {
|
||
return false;
|
||
}
|
||
const result = browser_api_BrowserApi.getExtensionViews({ tabId, type: "tab" });
|
||
return result.length > 0;
|
||
});
|
||
}
|
||
/**
|
||
* Identifies if the popup is within the single action popout.
|
||
*
|
||
* @param win - The passed window object.
|
||
* @param popoutKey - The single action popout key used to identify the popout.
|
||
*/
|
||
static inSingleActionPopout(win, popoutKey) {
|
||
return browser_popup_utils_BrowserPopupUtils.urlContainsSearchParams(win, "singleActionPopout", popoutKey);
|
||
}
|
||
/**
|
||
* Identifies if the popup is within the popup.
|
||
*
|
||
* @param win - The passed window object.
|
||
*/
|
||
static inPopup(win) {
|
||
return (win.location.href.indexOf("uilocation=") === -1 ||
|
||
win.location.href.indexOf("uilocation=popup") > -1);
|
||
}
|
||
/**
|
||
* Gets the scroll position of the popup.
|
||
*
|
||
* @param win - The passed window object.
|
||
* @param scrollingContainer - Element tag name of the scrolling container.
|
||
*/
|
||
static getContentScrollY(win, scrollingContainer = "main") {
|
||
const content = win.document.getElementsByTagName(scrollingContainer)[0];
|
||
return content.scrollTop;
|
||
}
|
||
/**
|
||
* Sets the scroll position of the popup.
|
||
*
|
||
* @param win - The passed window object.
|
||
* @param scrollYAmount - The amount to scroll the popup.
|
||
* @param options - Allows for setting the delay in ms to wait before scrolling the popup and the scrolling container tag name.
|
||
*/
|
||
static setContentScrollY(win_1, scrollYAmount_1) {
|
||
return browser_popup_utils_awaiter(this, arguments, void 0, function* (win, scrollYAmount, options = {
|
||
delay: 0,
|
||
containerSelector: "main",
|
||
}) {
|
||
const { delay, containerSelector } = options;
|
||
return new Promise((resolve) => win.setTimeout(() => {
|
||
const container = win.document.querySelector(containerSelector);
|
||
if (!isNaN(scrollYAmount) && container) {
|
||
container.scrollTop = scrollYAmount;
|
||
}
|
||
resolve();
|
||
}, delay));
|
||
});
|
||
}
|
||
/**
|
||
* Identifies if the background page needs to be initialized.
|
||
*/
|
||
static backgroundInitializationRequired() {
|
||
return !browser_api_BrowserApi.getBackgroundPage() || browser_api_BrowserApi.isManifestVersion(3);
|
||
}
|
||
/**
|
||
* Opens a popout window of any extension page. If the popout window is already open, it will be focused.
|
||
*
|
||
* @param extensionUrlPath - A relative path to the extension page. Example: "popup/index.html#/tabs/vault"
|
||
* @param options - Options for the popout window that overrides the default options.
|
||
*/
|
||
static openPopout(extensionUrlPath_1) {
|
||
return browser_popup_utils_awaiter(this, arguments, void 0, function* (extensionUrlPath, options = {}) {
|
||
const { senderWindowId, singleActionKey, forceCloseExistingWindows, windowOptions } = options;
|
||
const defaultPopoutWindowOptions = {
|
||
type: "popup",
|
||
focused: true,
|
||
width: Math.max(PopupWidthOptions.default, typeof document === "undefined" ? PopupWidthOptions.default : document.body.clientWidth),
|
||
height: 630,
|
||
};
|
||
const offsetRight = 15;
|
||
const offsetTop = 90;
|
||
const popupWidth = defaultPopoutWindowOptions.width;
|
||
const senderWindow = yield browser_api_BrowserApi.getWindow(senderWindowId);
|
||
const popoutWindowOptions = Object.assign(Object.assign(Object.assign({ left: senderWindow.left + senderWindow.width - popupWidth - offsetRight, top: senderWindow.top + offsetTop }, defaultPopoutWindowOptions), windowOptions), { url: browser_popup_utils_BrowserPopupUtils.buildPopoutUrl(extensionUrlPath, singleActionKey) });
|
||
if ((yield browser_popup_utils_BrowserPopupUtils.isSingleActionPopoutOpen(singleActionKey, popoutWindowOptions, forceCloseExistingWindows)) &&
|
||
!forceCloseExistingWindows) {
|
||
return;
|
||
}
|
||
const platform = yield browser_api_BrowserApi.getPlatformInfo();
|
||
const isMacOS = platform.os === "mac";
|
||
const isFullscreen = senderWindow.state === "fullscreen";
|
||
const isFullscreenAndMacOS = isFullscreen && isMacOS;
|
||
//macOS specific handling for improved UX when sender in fullscreen aka green button;
|
||
if (isFullscreenAndMacOS) {
|
||
yield browser_api_BrowserApi.updateWindowProperties(senderWindow.id, {
|
||
state: "maximized",
|
||
});
|
||
//wait for macOS animation to finish
|
||
yield new Promise((resolve) => setTimeout(resolve, 1000));
|
||
}
|
||
const newWindow = yield browser_api_BrowserApi.createWindow(popoutWindowOptions);
|
||
if (isFullscreenAndMacOS) {
|
||
yield browser_api_BrowserApi.updateWindowProperties(newWindow.id, {
|
||
focused: true,
|
||
});
|
||
}
|
||
return newWindow;
|
||
});
|
||
}
|
||
/**
|
||
* Closes the single action popout window.
|
||
*
|
||
* @param popoutKey - The single action popout key used to identify the popout.
|
||
* @param delayClose - The amount of time to wait before closing the popout. Defaults to 0.
|
||
*/
|
||
static closeSingleActionPopout(popoutKey_1) {
|
||
return browser_popup_utils_awaiter(this, arguments, void 0, function* (popoutKey, delayClose = 0) {
|
||
const extensionUrl = chrome.runtime.getURL("popup/index.html");
|
||
const tabs = yield browser_api_BrowserApi.tabsQuery({ url: `${extensionUrl}*` });
|
||
for (const tab of tabs) {
|
||
if (!tab.url.includes(`singleActionPopout=${popoutKey}`)) {
|
||
continue;
|
||
}
|
||
setTimeout(() => browser_api_BrowserApi.removeWindow(tab.windowId), delayClose);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Opens a popout window for the current page.
|
||
* If the current page is set for the current tab, then the
|
||
* popout window will be set for the vault items listing tab.
|
||
*
|
||
* @param win - The passed window object.
|
||
* @param href - The href to open in the popout window.
|
||
*/
|
||
static openCurrentPagePopout(win_1) {
|
||
return browser_popup_utils_awaiter(this, arguments, void 0, function* (win, href = null) {
|
||
const popoutUrl = href || win.location.href;
|
||
const parsedUrl = new URL(popoutUrl);
|
||
let hashRoute = parsedUrl.hash;
|
||
if (hashRoute.startsWith("#/tabs/current")) {
|
||
hashRoute = "#/tabs/vault";
|
||
}
|
||
yield browser_popup_utils_BrowserPopupUtils.openPopout(`${parsedUrl.pathname}${hashRoute}`);
|
||
if (browser_popup_utils_BrowserPopupUtils.inPopup(win)) {
|
||
browser_api_BrowserApi.closePopup(win);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Waits for all browser action popups to close, polling up to the specified timeout.
|
||
* Used before extension reload to prevent zombie popups with invalidated contexts.
|
||
*
|
||
* @param timeoutMs - Maximum time to wait in milliseconds. Defaults to 1 second.
|
||
* @returns Promise that resolves when all popups are closed or timeout is reached.
|
||
*/
|
||
static waitForAllPopupsClose() {
|
||
return browser_popup_utils_awaiter(this, arguments, void 0, function* (timeoutMs = 1000) {
|
||
yield firstValueFrom_firstValueFrom(interval(100).pipe(switchMap_switchMap(() => browser_api_BrowserApi.isPopupOpen()), takeWhile((isOpen) => isOpen, true), filter_filter((isOpen) => !isOpen), timeout_timeout({
|
||
first: timeoutMs,
|
||
with: () => of_of(true),
|
||
})));
|
||
});
|
||
}
|
||
/**
|
||
* Identifies if a single action window is open based on the passed popoutKey.
|
||
* Will focus the existing window, and close any other windows that might exist
|
||
* with the same popout key.
|
||
*
|
||
* @param popoutKey - The single action popout key used to identify the popout.
|
||
* @param windowInfo - The window info to use to update the existing window.
|
||
* @param forceCloseExistingWindows - Identifies if the existing windows should be closed.
|
||
*/
|
||
static isSingleActionPopoutOpen(popoutKey_1, windowInfo_1) {
|
||
return browser_popup_utils_awaiter(this, arguments, void 0, function* (popoutKey, windowInfo, forceCloseExistingWindows = false) {
|
||
if (!popoutKey) {
|
||
return false;
|
||
}
|
||
const extensionUrl = chrome.runtime.getURL("popup/index.html");
|
||
const popoutTabs = (yield browser_api_BrowserApi.tabsQuery({ url: `${extensionUrl}*` })).filter((tab) => tab.url.includes(`singleActionPopout=${popoutKey}`));
|
||
if (popoutTabs.length === 0) {
|
||
return false;
|
||
}
|
||
if (!forceCloseExistingWindows) {
|
||
// Update first, remove it from list
|
||
const tab = popoutTabs.shift();
|
||
yield browser_api_BrowserApi.updateWindowProperties(tab.windowId, {
|
||
focused: true,
|
||
width: windowInfo.width,
|
||
height: windowInfo.height,
|
||
top: windowInfo.top,
|
||
left: windowInfo.left,
|
||
});
|
||
}
|
||
popoutTabs.forEach((tab) => browser_api_BrowserApi.removeWindow(tab.windowId));
|
||
return true;
|
||
});
|
||
}
|
||
/**
|
||
* Identifies if the url contains the specified search param and value.
|
||
*
|
||
* @param win - The passed window object.
|
||
* @param searchParam - The search param to identify.
|
||
* @param searchValue - The search value to identify.
|
||
*/
|
||
static urlContainsSearchParams(win, searchParam, searchValue) {
|
||
return win.location.href.indexOf(`${searchParam}=${searchValue}`) > -1;
|
||
}
|
||
/**
|
||
* Builds the popout url path. Ensures that the uilocation param is set to
|
||
* `popout` and that the singleActionPopout param is set to the passed singleActionKey.
|
||
*
|
||
* @param extensionUrlPath - A relative path to the extension page. Example: "popup/index.html#/tabs/vault"
|
||
* @param singleActionKey - The single action popout key used to identify the popout.
|
||
*/
|
||
static buildPopoutUrl(extensionUrlPath, singleActionKey) {
|
||
const parsedUrl = new URL(chrome.runtime.getURL(extensionUrlPath));
|
||
parsedUrl.searchParams.set("uilocation", "popout");
|
||
if (singleActionKey) {
|
||
parsedUrl.searchParams.set("singleActionPopout", singleActionKey);
|
||
}
|
||
return parsedUrl.toString();
|
||
}
|
||
}
|
||
|
||
;// ./src/vault/popup/utils/vault-popout-window.ts
|
||
var vault_popout_window_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
const VaultPopoutType = {
|
||
viewVaultItem: "vault_viewVaultItem",
|
||
addEditVaultItem: "vault_AddEditVaultItem",
|
||
fido2Popout: "vault_Fido2Popout",
|
||
};
|
||
/**
|
||
* Opens a popout window that facilitates viewing a vault item.
|
||
*
|
||
* @param senderTab - The tab that sent the request.
|
||
* @param cipherOptions - The cipher id and action to perform.
|
||
*/
|
||
function openViewVaultItemPopout(senderTab, cipherOptions) {
|
||
return vault_popout_window_awaiter(this, void 0, void 0, function* () {
|
||
const { cipherId, action, forceCloseExistingWindows } = cipherOptions;
|
||
let promptWindowPath = "popup/index.html#/view-cipher";
|
||
let queryParamToken = "?";
|
||
const formatQueryString = (key, value) => {
|
||
const queryString = `${queryParamToken}${key}=${value}`;
|
||
queryParamToken = "&";
|
||
return queryString;
|
||
};
|
||
if (cipherId) {
|
||
promptWindowPath += formatQueryString("cipherId", cipherId);
|
||
}
|
||
if (senderTab.id) {
|
||
promptWindowPath += formatQueryString("senderTabId", String(senderTab.id));
|
||
}
|
||
if (action) {
|
||
promptWindowPath += formatQueryString("action", action);
|
||
}
|
||
yield browser_popup_utils_BrowserPopupUtils.openPopout(promptWindowPath, {
|
||
singleActionKey: `${VaultPopoutType.viewVaultItem}_${cipherId}`,
|
||
senderWindowId: senderTab.windowId,
|
||
forceCloseExistingWindows,
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Closes the view vault item popout window.
|
||
*
|
||
* @param singleActionKey - The single action popout key used to identify the popout.
|
||
* @param delayClose - The amount of time to wait before closing the popout. Defaults to 0.
|
||
*/
|
||
function closeViewVaultItemPopout(singleActionKey_1) {
|
||
return vault_popout_window_awaiter(this, arguments, void 0, function* (singleActionKey, delayClose = 0) {
|
||
yield BrowserPopupUtils.closeSingleActionPopout(singleActionKey, delayClose);
|
||
});
|
||
}
|
||
/**
|
||
* Opens a popout window that facilitates re-prompting for
|
||
* the password of a vault item.
|
||
*
|
||
* @param senderTab - The tab that sent the request.
|
||
* @param cipherOptions - The cipher id and action to perform.
|
||
*/
|
||
function openVaultItemPasswordRepromptPopout(senderTab, cipherOptions) {
|
||
return vault_popout_window_awaiter(this, void 0, void 0, function* () {
|
||
yield openViewVaultItemPopout(senderTab, Object.assign({ forceCloseExistingWindows: true }, cipherOptions));
|
||
yield browser_api_BrowserApi.tabSendMessageData(senderTab, "bgVaultItemRepromptPopoutOpened");
|
||
});
|
||
}
|
||
/**
|
||
* Opens a popout window that facilitates adding or editing a vault item.
|
||
*
|
||
* @param senderTab - The window id of the sender.
|
||
* @param cipherOptions - Options passed as query params to the popout.
|
||
*/
|
||
function openAddEditVaultItemPopout(senderTab_1) {
|
||
return vault_popout_window_awaiter(this, arguments, void 0, function* (senderTab, cipherOptions = {}) {
|
||
const { cipherId, cipherType } = cipherOptions;
|
||
const { url, windowId } = senderTab;
|
||
let singleActionKey = VaultPopoutType.addEditVaultItem;
|
||
let addEditCipherUrl = "popup/index.html#/edit-cipher";
|
||
let queryParamToken = "?";
|
||
const formatQueryString = (key, value) => {
|
||
const queryString = `${queryParamToken}${key}=${value}`;
|
||
queryParamToken = "&";
|
||
return queryString;
|
||
};
|
||
if (cipherId && !cipherType) {
|
||
singleActionKey += `_${cipherId}`;
|
||
addEditCipherUrl += formatQueryString("cipherId", cipherId);
|
||
}
|
||
if (cipherType && !cipherId) {
|
||
singleActionKey += `_${cipherType}`;
|
||
addEditCipherUrl += formatQueryString("type", String(cipherType));
|
||
}
|
||
if (senderTab.url) {
|
||
addEditCipherUrl += formatQueryString("uri", url);
|
||
}
|
||
const extensionUrl = chrome.runtime.getURL("popup/index.html");
|
||
const existingPopupTabs = yield BrowserApi.tabsQuery({ url: `${extensionUrl}*` });
|
||
const existingPopup = existingPopupTabs.find((tab) => { var _a; return (_a = tab.url) === null || _a === void 0 ? void 0 : _a.includes(`singleActionPopout=${singleActionKey}`); });
|
||
// Check if the an existing popup is already open
|
||
try {
|
||
yield chrome.runtime.sendMessage({
|
||
command: "reloadAddEditCipherData",
|
||
data: { cipherId, cipherType },
|
||
});
|
||
yield BrowserApi.updateWindowProperties(existingPopup.windowId, {
|
||
focused: true,
|
||
});
|
||
}
|
||
catch (_a) {
|
||
yield BrowserPopupUtils.openPopout(addEditCipherUrl, {
|
||
singleActionKey,
|
||
senderWindowId: windowId,
|
||
});
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Closes the add/edit vault item popout window.
|
||
*
|
||
* @param delayClose - The amount of time to wait before closing the popout. Defaults to 0.
|
||
*/
|
||
function closeAddEditVaultItemPopout() {
|
||
return vault_popout_window_awaiter(this, arguments, void 0, function* (delayClose = 0) {
|
||
yield BrowserPopupUtils.closeSingleActionPopout(VaultPopoutType.addEditVaultItem, delayClose);
|
||
});
|
||
}
|
||
/**
|
||
* Opens a popout window that facilitates FIDO2
|
||
* authentication and passkey management.
|
||
*
|
||
* @param senderTab - The tab that sent the request.
|
||
* @param options - Options passed as query params to the popout.
|
||
*/
|
||
function openFido2Popout(senderTab, options) {
|
||
return vault_popout_window_awaiter(this, void 0, void 0, function* () {
|
||
const { sessionId, fallbackSupported } = options;
|
||
const promptWindowPath = "popup/index.html#/fido2" +
|
||
`?sessionId=${sessionId}` +
|
||
`&fallbackSupported=${fallbackSupported}` +
|
||
`&senderTabId=${senderTab.id}` +
|
||
`&senderUrl=${encodeURIComponent(senderTab.url)}`;
|
||
const popoutWindow = yield BrowserPopupUtils.openPopout(promptWindowPath, {
|
||
singleActionKey: `${VaultPopoutType.fido2Popout}_${sessionId}`,
|
||
senderWindowId: senderTab.windowId,
|
||
forceCloseExistingWindows: true,
|
||
windowOptions: { height: 570 },
|
||
});
|
||
return popoutWindow.id;
|
||
});
|
||
}
|
||
/**
|
||
* Closes the FIDO2 popout window associated with the passed session ID.
|
||
*
|
||
* @param sessionId - The session ID of the popout to close.
|
||
*/
|
||
function closeFido2Popout(sessionId) {
|
||
return vault_popout_window_awaiter(this, void 0, void 0, function* () {
|
||
yield BrowserPopupUtils.closeSingleActionPopout(`${VaultPopoutType.fido2Popout}_${sessionId}`);
|
||
});
|
||
}
|
||
|
||
|
||
;// ./src/autofill/enums/autofill-message.enums.ts
|
||
const AutofillMessageCommand = {
|
||
collectPageDetails: "collectPageDetails",
|
||
collectPageDetailsResponse: "collectPageDetailsResponse",
|
||
};
|
||
const AutofillMessageSender = {
|
||
collectPageDetailsFromTabObservable: "collectPageDetailsFromTabObservable",
|
||
};
|
||
|
||
;// ./src/autofill/models/autofill-script.ts
|
||
const FillScriptActionTypes = {
|
||
fill_by_opid: "fill_by_opid",
|
||
click_on_opid: "click_on_opid",
|
||
focus_by_opid: "focus_by_opid",
|
||
};
|
||
class AutofillScript {
|
||
constructor() {
|
||
this.script = [];
|
||
this.properties = {};
|
||
}
|
||
}
|
||
|
||
;// ../../libs/messaging/src/message.listener.ts
|
||
|
||
/**
|
||
* A class that allows for listening to messages coming through the application,
|
||
* allows for listening of all messages or just the messages you care about.
|
||
*
|
||
* @note Consider NOT using messaging at all if you can. State Providers offer an observable stream of
|
||
* data that is persisted. This can serve messages that might have been used to notify of settings changes
|
||
* or vault data changes and those observables should be preferred over messaging.
|
||
*/
|
||
class MessageListener {
|
||
constructor(messageStream) {
|
||
this.messageStream = messageStream;
|
||
/**
|
||
* A stream of all messages sent through the application. It does not contain type information for the
|
||
* other properties on the messages. You are encouraged to instead subscribe to an individual message
|
||
* through {@link messages$}.
|
||
*/
|
||
this.allMessages$ = this.messageStream;
|
||
}
|
||
/**
|
||
* Creates an observable stream filtered to just the command given via the {@link CommandDefinition} and typed
|
||
* to the generic contained in the CommandDefinition. Be careful using this method unless all your messages are being
|
||
* sent through `MessageSender.send`, if that isn't the case you should have lower confidence in the message
|
||
* payload being the expected type.
|
||
*
|
||
* @param commandDefinition The CommandDefinition containing the information about the message type you care about.
|
||
*/
|
||
messages$(commandDefinition) {
|
||
return this.allMessages$.pipe(filter_filter((msg) => (msg === null || msg === void 0 ? void 0 : msg.command) === commandDefinition.command));
|
||
}
|
||
}
|
||
/**
|
||
* A helper property for returning a MessageListener that will never emit any messages and will immediately complete.
|
||
*/
|
||
MessageListener.EMPTY = new MessageListener(EMPTY);
|
||
|
||
;// ../../libs/messaging/src/message.sender.ts
|
||
class MultiMessageSender {
|
||
constructor(innerMessageSenders) {
|
||
this.innerMessageSenders = innerMessageSenders;
|
||
}
|
||
send(commandDefinition, payload = {}) {
|
||
for (const messageSender of this.innerMessageSenders) {
|
||
messageSender.send(commandDefinition, payload);
|
||
}
|
||
}
|
||
}
|
||
class MessageSender {
|
||
/**
|
||
* A helper method for combine multiple {@link MessageSender}'s.
|
||
* @param messageSenders The message senders that should be combined.
|
||
* @returns A message sender that will relay all messages to the given message senders.
|
||
*/
|
||
static combine(...messageSenders) {
|
||
return new MultiMessageSender(messageSenders);
|
||
}
|
||
}
|
||
/**
|
||
* A helper property for creating a {@link MessageSender} that sends to nowhere.
|
||
*/
|
||
MessageSender.EMPTY = new MultiMessageSender([]);
|
||
|
||
;// ../../libs/messaging/src/types.ts
|
||
/**
|
||
* A class for defining information about a message, this is helpful
|
||
* alonside `MessageSender` and `MessageListener` for providing a type
|
||
* safe(-ish) way of sending and receiving messages.
|
||
*/
|
||
class CommandDefinition {
|
||
constructor(command) {
|
||
this.command = command;
|
||
}
|
||
}
|
||
|
||
;// ../../libs/messaging/src/is-external-message.ts
|
||
const is_external_message_EXTERNAL_SOURCE_TAG = Symbol("externalSource");
|
||
const isExternalMessage = (message) => {
|
||
return (message === null || message === void 0 ? void 0 : message[is_external_message_EXTERNAL_SOURCE_TAG]) === true;
|
||
};
|
||
|
||
;// ../../libs/messaging/src/helpers.ts
|
||
|
||
|
||
const helpers_getCommand = (commandDefinition) => {
|
||
if (typeof commandDefinition === "string") {
|
||
return commandDefinition;
|
||
}
|
||
else {
|
||
return commandDefinition.command;
|
||
}
|
||
};
|
||
const tagAsExternal = () => {
|
||
return map((message) => {
|
||
return Object.assign(message, { [EXTERNAL_SOURCE_TAG]: true });
|
||
});
|
||
};
|
||
|
||
;// ../../libs/messaging/src/subject-message.sender.ts
|
||
|
||
class SubjectMessageSender {
|
||
constructor(messagesSubject) {
|
||
this.messagesSubject = messagesSubject;
|
||
}
|
||
send(commandDefinition, payload = {}) {
|
||
const command = getCommand(commandDefinition);
|
||
this.messagesSubject.next(Object.assign(payload !== null && payload !== void 0 ? payload : {}, { command: command }));
|
||
}
|
||
}
|
||
|
||
;// ../../libs/messaging/src/index.ts
|
||
|
||
|
||
|
||
|
||
// Internal implementations
|
||
|
||
|
||
|
||
;// ../../libs/common/src/platform/messaging/index.ts
|
||
|
||
|
||
;// ./src/autofill/services/abstractions/autofill.service.ts
|
||
|
||
|
||
const COLLECT_PAGE_DETAILS_RESPONSE_COMMAND = new CommandDefinition(AutofillMessageCommand.collectPageDetailsResponse);
|
||
class AutofillService {
|
||
}
|
||
|
||
;// ./src/autofill/services/autofill.service.ts
|
||
var autofill_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
// FIXME: Update this file to be type safe and remove this and next line
|
||
// @ts-strict-ignore
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// FIXME (PM-22628): Popup imports are forbidden in background
|
||
// eslint-disable-next-line no-restricted-imports
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
class autofill_service_AutofillService {
|
||
constructor(cipherService, autofillSettingsService, totpService, eventCollectionService, logService, domainSettingsService, userVerificationService, billingAccountProfileStateService, scriptInjectorService, accountService, authService, configService, userNotificationSettingsService, messageListener) {
|
||
this.cipherService = cipherService;
|
||
this.autofillSettingsService = autofillSettingsService;
|
||
this.totpService = totpService;
|
||
this.eventCollectionService = eventCollectionService;
|
||
this.logService = logService;
|
||
this.domainSettingsService = domainSettingsService;
|
||
this.userVerificationService = userVerificationService;
|
||
this.billingAccountProfileStateService = billingAccountProfileStateService;
|
||
this.scriptInjectorService = scriptInjectorService;
|
||
this.accountService = accountService;
|
||
this.authService = authService;
|
||
this.configService = configService;
|
||
this.userNotificationSettingsService = userNotificationSettingsService;
|
||
this.messageListener = messageListener;
|
||
this.openVaultItemPasswordRepromptPopout = openVaultItemPasswordRepromptPopout;
|
||
this.currentlyOpeningPasswordRepromptPopout = false;
|
||
this.autofillScriptPortsSet = new Set();
|
||
/**
|
||
* Handles incoming long-lived connections from injected autofill scripts.
|
||
* Stores the port in a set to facilitate disconnecting ports if the extension
|
||
* needs to re-inject the autofill scripts.
|
||
*
|
||
* @param port - The port that was connected
|
||
*/
|
||
this.handleInjectedScriptPortConnection = (port) => {
|
||
if (port.name !== AutofillPort.InjectedScript) {
|
||
return;
|
||
}
|
||
this.autofillScriptPortsSet.add(port);
|
||
port.onDisconnect.addListener(this.handleInjectScriptPortOnDisconnect);
|
||
};
|
||
/**
|
||
* Handles disconnecting ports that relate to injected autofill scripts.
|
||
|
||
* @param port - The port that was disconnected
|
||
*/
|
||
this.handleInjectScriptPortOnDisconnect = (port) => {
|
||
if (port.name !== AutofillPort.InjectedScript) {
|
||
return;
|
||
}
|
||
this.autofillScriptPortsSet.delete(port);
|
||
};
|
||
}
|
||
/**
|
||
* Collects page details from the specific tab. This method returns an observable that can
|
||
* be subscribed to in order to build the results from all collectPageDetailsResponse
|
||
* messages from the given tab.
|
||
*
|
||
* @param tab The tab to collect page details from
|
||
*/
|
||
collectPageDetailsFromTab$(tab) {
|
||
/** Replay Subject that can be utilized when `messages$` may not emit the page details. */
|
||
const pageDetailsFallback$ = new ReplaySubject_ReplaySubject(1);
|
||
const pageDetailsFromTab$ = this.messageListener
|
||
.messages$(COLLECT_PAGE_DETAILS_RESPONSE_COMMAND)
|
||
.pipe(filter_filter((message) => message.tab.id === tab.id &&
|
||
message.sender === AutofillMessageSender.collectPageDetailsFromTabObservable), scan((acc, message) => [
|
||
...acc,
|
||
{
|
||
frameId: message.webExtSender.frameId,
|
||
tab: message.tab,
|
||
details: message.details,
|
||
},
|
||
], []));
|
||
void browser_api_BrowserApi.tabSendMessage(tab, {
|
||
tab: tab,
|
||
command: AutofillMessageCommand.collectPageDetails,
|
||
sender: AutofillMessageSender.collectPageDetailsFromTabObservable,
|
||
}, null, true).catch(() => {
|
||
// When `tabSendMessage` throws an error the `pageDetailsFromTab$` will not emit,
|
||
// fallback to an empty array
|
||
pageDetailsFallback$.next([]);
|
||
});
|
||
// Fallback to empty array when:
|
||
// - In Safari, `tabSendMessage` doesn't throw an error for this case.
|
||
// - When opening the extension directly via the URL, `tabSendMessage` doesn't always respond nor throw an error in FireFox.
|
||
// Adding checks for the major 3 browsers here to be safe.
|
||
const urlHasBrowserProtocol = [
|
||
"moz-extension://",
|
||
"chrome-extension://",
|
||
"safari-web-extension://",
|
||
].some((protocol) => tab.url.startsWith(protocol));
|
||
if (!tab.url || urlHasBrowserProtocol) {
|
||
pageDetailsFallback$.next([]);
|
||
}
|
||
// Share the pageDetailsFromTab$ observable so that multiple subscribers don't trigger multiple executions.
|
||
const sharedPageDetailsFromTab$ = pageDetailsFromTab$.pipe(share_share());
|
||
// Create a timeout observable that emits an empty array if pageDetailsFromTab$ hasn't emitted within 1 second.
|
||
const pageDetailsTimeout$ = timer_timer(1000).pipe(map_map(() => []), takeUntil(sharedPageDetailsFromTab$));
|
||
// Merge the responses so that if pageDetailsFromTab$ emits, that value is used.
|
||
// Otherwise, if it doesn't emit in time, the timeout observable emits an empty array.
|
||
// Also, pageDetailsFallback$ will emit in error cases.
|
||
return merge_merge(sharedPageDetailsFromTab$, pageDetailsFallback$, pageDetailsTimeout$);
|
||
}
|
||
/**
|
||
* Triggers on installation of the extension Handles injecting
|
||
* content scripts into all tabs that are currently open, and
|
||
* sets up a listener to ensure content scripts can identify
|
||
* if the extension context has been disconnected.
|
||
*/
|
||
loadAutofillScriptsOnInstall() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
browser_api_BrowserApi.addListener(chrome.runtime.onConnect, this.handleInjectedScriptPortConnection);
|
||
void this.injectAutofillScriptsInAllTabs();
|
||
this.autofillSettingsService.inlineMenuVisibility$
|
||
.pipe(startWith(undefined), pairwise())
|
||
.subscribe(([previousSetting, currentSetting]) => this.handleInlineMenuVisibilitySettingsChange(previousSetting, currentSetting));
|
||
this.autofillSettingsService.showInlineMenuCards$
|
||
.pipe(startWith(undefined), pairwise())
|
||
.subscribe(([previousSetting, currentSetting]) => this.handleInlineMenuVisibilitySettingsChange(previousSetting, currentSetting));
|
||
this.autofillSettingsService.showInlineMenuIdentities$
|
||
.pipe(startWith(undefined), pairwise())
|
||
.subscribe(([previousSetting, currentSetting]) => this.handleInlineMenuVisibilitySettingsChange(previousSetting, currentSetting));
|
||
});
|
||
}
|
||
/**
|
||
* Triggers a complete reload of all autofill scripts on tabs open within
|
||
* the user's browsing session. This is done by first disconnecting all
|
||
* existing autofill content script ports, which cleans up existing object
|
||
* instances, and then re-injecting the autofill scripts into all tabs.
|
||
*/
|
||
reloadAutofillScripts() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
this.autofillScriptPortsSet.forEach((port) => {
|
||
port.disconnect();
|
||
this.autofillScriptPortsSet.delete(port);
|
||
});
|
||
void this.injectAutofillScriptsInAllTabs();
|
||
});
|
||
}
|
||
/**
|
||
* Injects the autofill scripts into the current tab and all frames
|
||
* found within the tab. Temporarily, will conditionally inject
|
||
* the refactor of the core autofill script if the feature flag
|
||
* is enabled.
|
||
* @param {chrome.tabs.Tab} tab
|
||
* @param {number} frameId
|
||
* @param {boolean} triggeringOnPageLoad
|
||
*/
|
||
injectAutofillScripts(tab_1) {
|
||
return autofill_service_awaiter(this, arguments, void 0, function* (tab, frameId = 0, triggeringOnPageLoad = true) {
|
||
// Autofill user settings loaded from state can await the active account state indefinitely
|
||
// if not guarded by an active account check (e.g. the user is logged in)
|
||
const activeAccount = yield firstValueFrom_firstValueFrom(this.accountService.activeAccount$);
|
||
const authStatus = yield firstValueFrom_firstValueFrom(this.authService.activeAccountStatus$);
|
||
const accountIsUnlocked = authStatus === AuthenticationStatus.Unlocked;
|
||
let autoFillOnPageLoadIsEnabled = false;
|
||
const injectedScripts = [yield this.getBootstrapAutofillContentScript(activeAccount)];
|
||
if (activeAccount && accountIsUnlocked) {
|
||
autoFillOnPageLoadIsEnabled = yield this.getAutofillOnPageLoad();
|
||
}
|
||
if (triggeringOnPageLoad && autoFillOnPageLoadIsEnabled) {
|
||
injectedScripts.push("autofiller.js");
|
||
}
|
||
if (!triggeringOnPageLoad) {
|
||
yield this.scriptInjectorService.inject({
|
||
tabId: tab.id,
|
||
injectDetails: { file: "content/content-message-handler.js", runAt: "document_start" },
|
||
});
|
||
}
|
||
injectedScripts.push("contextMenuHandler.js");
|
||
for (const injectedScript of injectedScripts) {
|
||
yield this.scriptInjectorService.inject({
|
||
tabId: tab.id,
|
||
injectDetails: {
|
||
file: `content/${injectedScript}`,
|
||
runAt: "document_start",
|
||
frame: frameId,
|
||
},
|
||
});
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Identifies the correct autofill script to inject based on whether the
|
||
* inline menu is enabled, and whether the user has the notification bar
|
||
* enabled.
|
||
*
|
||
* @param activeAccount - The active account
|
||
*/
|
||
getBootstrapAutofillContentScript(activeAccount) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
let inlineMenuVisibility = AutofillOverlayVisibility.Off;
|
||
if (activeAccount) {
|
||
inlineMenuVisibility = yield this.getInlineMenuVisibility();
|
||
}
|
||
const enableChangedPasswordPrompt = yield firstValueFrom_firstValueFrom(this.userNotificationSettingsService.enableChangedPasswordPrompt$);
|
||
const enableAddedLoginPrompt = yield firstValueFrom_firstValueFrom(this.userNotificationSettingsService.enableAddedLoginPrompt$);
|
||
const isNotificationBarEnabled = enableChangedPasswordPrompt || enableAddedLoginPrompt;
|
||
if (!inlineMenuVisibility && !isNotificationBarEnabled) {
|
||
return "bootstrap-autofill.js";
|
||
}
|
||
if (!inlineMenuVisibility && isNotificationBarEnabled) {
|
||
return "bootstrap-autofill-overlay-notifications.js";
|
||
}
|
||
if (inlineMenuVisibility && !isNotificationBarEnabled) {
|
||
return "bootstrap-autofill-overlay-menu.js";
|
||
}
|
||
return "bootstrap-autofill-overlay.js";
|
||
});
|
||
}
|
||
/**
|
||
* Gets all forms with password fields and formats the data
|
||
* for both forms and password input elements.
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @returns {FormData[]}
|
||
*/
|
||
getFormsWithPasswordFields(pageDetails) {
|
||
const formData = [];
|
||
const passwordFields = autofill_service_AutofillService.loadPasswordFields(pageDetails, true, true, false, true);
|
||
// TODO: this logic prevents multi-step account creation forms (that just start with email)
|
||
// from being passed on to the notification bar content script - even if autofill-init.js found the form and email field.
|
||
// ex: https://signup.live.com/
|
||
if (passwordFields.length === 0) {
|
||
return formData;
|
||
}
|
||
// Back up check for cases where there are several password fields detected,
|
||
// but they are not all part of the form b/c of bad HTML
|
||
// gather password fields that don't have an enclosing form
|
||
const passwordFieldsWithoutForm = passwordFields.filter((pf) => pf.form === undefined);
|
||
const formKeys = Object.keys(pageDetails.forms);
|
||
const formCount = formKeys.length;
|
||
// if we have 3 password fields and only 1 form, and there are password fields that are not within a form
|
||
// but there is at least one password field within the form, then most likely this is a poorly built password change form
|
||
if (passwordFields.length === 3 && formCount == 1 && passwordFieldsWithoutForm.length > 0) {
|
||
// Only one form so get the singular form key
|
||
const soloFormKey = formKeys[0];
|
||
const atLeastOnePasswordFieldWithinSoloForm = passwordFields.filter((pf) => pf.form !== null && pf.form === soloFormKey).length > 0;
|
||
if (atLeastOnePasswordFieldWithinSoloForm) {
|
||
// We have a form with at least one password field,
|
||
// so let's make an assumption that the password fields without a form are actually part of this form
|
||
passwordFieldsWithoutForm.forEach((pf) => {
|
||
pf.form = soloFormKey;
|
||
});
|
||
}
|
||
}
|
||
for (const formKey in pageDetails.forms) {
|
||
// eslint-disable-next-line
|
||
if (!pageDetails.forms.hasOwnProperty(formKey)) {
|
||
continue;
|
||
}
|
||
const formPasswordFields = passwordFields.filter((pf) => formKey === pf.form);
|
||
if (formPasswordFields.length > 0) {
|
||
let uf = this.findUsernameField(pageDetails, formPasswordFields[0], false, false, false);
|
||
if (uf == null) {
|
||
// not able to find any viewable username fields. maybe there are some "hidden" ones?
|
||
uf = this.findUsernameField(pageDetails, formPasswordFields[0], true, true, false);
|
||
}
|
||
formData.push({
|
||
form: pageDetails.forms[formKey],
|
||
password: formPasswordFields[0],
|
||
username: uf,
|
||
passwords: formPasswordFields,
|
||
});
|
||
}
|
||
}
|
||
return formData;
|
||
}
|
||
/**
|
||
* Gets the overlay's visibility setting from the autofill settings service.
|
||
*/
|
||
getInlineMenuVisibility() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
return yield firstValueFrom_firstValueFrom(this.autofillSettingsService.inlineMenuVisibility$);
|
||
});
|
||
}
|
||
/**
|
||
* Gets the setting for automatically copying TOTP upon autofill from the autofill settings service.
|
||
*/
|
||
getShouldAutoCopyTotp() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
return yield firstValueFrom_firstValueFrom(this.autofillSettingsService.autoCopyTotp$);
|
||
});
|
||
}
|
||
/**
|
||
* Gets the autofill on page load setting from the autofill settings service.
|
||
*/
|
||
getAutofillOnPageLoad() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
return yield firstValueFrom_firstValueFrom(this.autofillSettingsService.autofillOnPageLoad$);
|
||
});
|
||
}
|
||
/**
|
||
* Gets the default URI match strategy setting from the domain settings service.
|
||
*/
|
||
getDefaultUriMatchStrategy() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
return yield firstValueFrom_firstValueFrom(this.domainSettingsService.resolvedDefaultUriMatchStrategy$);
|
||
});
|
||
}
|
||
/**
|
||
* Autofill a given tab with a given login item
|
||
* @param {AutoFillOptions} options Instructions about the autofill operation, including tab and login item
|
||
* @returns {Promise<string | null>} The TOTP code of the successfully autofilled login, if any
|
||
*/
|
||
doAutoFill(options) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
const tab = options.tab;
|
||
if (!tab || !options.cipher || !options.pageDetails || !options.pageDetails.length) {
|
||
throw new Error("Nothing to autofill.");
|
||
}
|
||
let totp = null;
|
||
const activeAccount = yield firstValueFrom_firstValueFrom(this.accountService.activeAccount$);
|
||
const canAccessPremium = yield firstValueFrom_firstValueFrom(this.billingAccountProfileStateService.hasPremiumFromAnySource$(activeAccount.id));
|
||
const defaultUriMatch = yield this.getDefaultUriMatchStrategy();
|
||
if (!canAccessPremium) {
|
||
options.cipher.login.totp = null;
|
||
}
|
||
let didAutofill = false;
|
||
yield Promise.all(options.pageDetails.map((pd) => autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
// make sure we're still on correct tab
|
||
if (pd.tab.id !== tab.id || pd.tab.url !== tab.url) {
|
||
return;
|
||
}
|
||
// If we have a focused form, filter the page details to only include fields from that form
|
||
const details = options.focusedFieldForm
|
||
? Object.assign(Object.assign({}, pd.details), { fields: pd.details.fields.filter((f) => f.form === options.focusedFieldForm) }) : pd.details;
|
||
const fillScript = yield this.generateFillScript(details, {
|
||
skipUsernameOnlyFill: options.skipUsernameOnlyFill || false,
|
||
onlyEmptyFields: options.onlyEmptyFields || false,
|
||
fillNewPassword: options.fillNewPassword || false,
|
||
allowTotpAutofill: options.allowTotpAutofill || false,
|
||
autoSubmitLogin: options.autoSubmitLogin || false,
|
||
cipher: options.cipher,
|
||
tabUrl: tab.url,
|
||
defaultUriMatch: defaultUriMatch,
|
||
focusedFieldOpid: options.focusedFieldOpid,
|
||
inlineMenuFillType: options.inlineMenuFillType,
|
||
});
|
||
if (!fillScript || !fillScript.script || !fillScript.script.length) {
|
||
return;
|
||
}
|
||
if (fillScript.untrustedIframe &&
|
||
options.allowUntrustedIframe != undefined &&
|
||
!options.allowUntrustedIframe) {
|
||
this.logService.info("Autofill on page load was blocked due to an untrusted iframe.");
|
||
return;
|
||
}
|
||
// Add a small delay between operations
|
||
fillScript.properties.delay_between_operations = 20;
|
||
didAutofill = true;
|
||
if (!options.skipLastUsed) {
|
||
yield this.cipherService.updateLastUsedDate(options.cipher.id, activeAccount.id);
|
||
}
|
||
void browser_api_BrowserApi.tabSendMessage(tab, {
|
||
command: options.autoSubmitLogin ? "triggerAutoSubmitLogin" : "fillForm",
|
||
fillScript: fillScript,
|
||
url: tab.url,
|
||
pageDetailsUrl: pd.details.url,
|
||
}, { frameId: pd.frameId });
|
||
// Skip getting the TOTP code for clipboard in these cases
|
||
if (options.cipher.type !== CipherType.Login ||
|
||
totp !== null ||
|
||
!options.cipher.login.totp ||
|
||
(!canAccessPremium && !options.cipher.organizationUseTotp)) {
|
||
return;
|
||
}
|
||
const shouldAutoCopyTotp = yield this.getShouldAutoCopyTotp();
|
||
totp = shouldAutoCopyTotp
|
||
? (yield firstValueFrom_firstValueFrom(this.totpService.getCode$(options.cipher.login.totp))).code
|
||
: null;
|
||
})));
|
||
if (didAutofill) {
|
||
yield this.eventCollectionService.collect(EventType.Cipher_ClientAutofilled, options.cipher.id);
|
||
if (totp !== null) {
|
||
return totp;
|
||
}
|
||
else {
|
||
return null;
|
||
}
|
||
}
|
||
else {
|
||
throw new Error("Did not autofill.");
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Autofill the specified tab with the next login item from the cache
|
||
* @param {PageDetail[]} pageDetails The data scraped from the page
|
||
* @param {chrome.tabs.Tab} tab The tab to be autofilled
|
||
* @param {boolean} fromCommand Whether the autofill is triggered by a keyboard shortcut (`true`) or autofill on page load (`false`)
|
||
* @param {boolean} autoSubmitLogin Whether the autofill is for an auto-submit login
|
||
* @returns {Promise<string | null>} The TOTP code of the successfully autofilled login, if any
|
||
*/
|
||
doAutoFillOnTab(pageDetails_1, tab_1, fromCommand_1) {
|
||
return autofill_service_awaiter(this, arguments, void 0, function* (pageDetails, tab, fromCommand, autoSubmitLogin = false) {
|
||
var _a, _b;
|
||
let cipher;
|
||
const activeUserId = yield firstValueFrom_firstValueFrom(this.accountService.activeAccount$.pipe(getOptionalUserId));
|
||
if (activeUserId == null) {
|
||
return null;
|
||
}
|
||
if (fromCommand) {
|
||
cipher = yield this.cipherService.getNextCipherForUrl(tab.url, activeUserId);
|
||
}
|
||
else {
|
||
const lastLaunchedCipher = yield this.cipherService.getLastLaunchedForUrl(tab.url, activeUserId, true);
|
||
if (lastLaunchedCipher &&
|
||
Date.now().valueOf() - ((_b = (_a = lastLaunchedCipher.localData) === null || _a === void 0 ? void 0 : _a.lastLaunched) === null || _b === void 0 ? void 0 : _b.valueOf()) < 30000) {
|
||
cipher = lastLaunchedCipher;
|
||
}
|
||
else {
|
||
cipher = yield this.cipherService.getLastUsedForUrl(tab.url, activeUserId, true);
|
||
}
|
||
}
|
||
if (cipher == null || (cipher.reprompt === CipherRepromptType.Password && !fromCommand)) {
|
||
return null;
|
||
}
|
||
if (yield this.isPasswordRepromptRequired(cipher, tab)) {
|
||
if (fromCommand) {
|
||
this.cipherService.updateLastUsedIndexForUrl(tab.url);
|
||
}
|
||
return null;
|
||
}
|
||
const totpCode = yield this.doAutoFill({
|
||
tab: tab,
|
||
cipher: cipher,
|
||
pageDetails: pageDetails,
|
||
skipLastUsed: !fromCommand,
|
||
skipUsernameOnlyFill: !fromCommand,
|
||
onlyEmptyFields: !fromCommand,
|
||
fillNewPassword: fromCommand,
|
||
allowUntrustedIframe: fromCommand,
|
||
allowTotpAutofill: fromCommand,
|
||
autoSubmitLogin,
|
||
});
|
||
// Update last used index as autofill has succeeded
|
||
if (fromCommand) {
|
||
this.cipherService.updateLastUsedIndexForUrl(tab.url);
|
||
}
|
||
return totpCode;
|
||
});
|
||
}
|
||
/**
|
||
* Checks if the cipher requires password reprompt and opens the password reprompt popout if necessary.
|
||
*
|
||
* @param cipher - The cipher to autofill
|
||
* @param tab - The tab to autofill
|
||
* @param action - override for default action once reprompt is completed successfully
|
||
*/
|
||
isPasswordRepromptRequired(cipher, tab, action) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
const userHasMasterPasswordAndKeyHash = yield this.userVerificationService.hasMasterPasswordAndMasterKeyHash();
|
||
if (cipher.reprompt === CipherRepromptType.Password && userHasMasterPasswordAndKeyHash) {
|
||
if (!this.isDebouncingPasswordRepromptPopout()) {
|
||
yield this.openVaultItemPasswordRepromptPopout(tab, {
|
||
cipherId: cipher.id,
|
||
action: action !== null && action !== void 0 ? action : "autofill",
|
||
});
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
}
|
||
/**
|
||
* Autofill the active tab with the next cipher from the cache
|
||
* @param {PageDetail[]} pageDetails The data scraped from the page
|
||
* @param {boolean} fromCommand Whether the autofill is triggered by a keyboard shortcut (`true`) or autofill on page load (`false`)
|
||
* @returns {Promise<string | null>} The TOTP code of the successfully autofilled login, if any
|
||
*/
|
||
doAutoFillActiveTab(pageDetails, fromCommand, cipherType) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b, _c;
|
||
if (!((_c = (_b = (_a = pageDetails[0]) === null || _a === void 0 ? void 0 : _a.details) === null || _b === void 0 ? void 0 : _b.fields) === null || _c === void 0 ? void 0 : _c.length)) {
|
||
return null;
|
||
}
|
||
const tab = yield this.getActiveTab();
|
||
if (!tab || !tab.url) {
|
||
return null;
|
||
}
|
||
if (!cipherType || cipherType === CipherType.Login) {
|
||
return yield this.doAutoFillOnTab(pageDetails, tab, fromCommand);
|
||
}
|
||
let cipher;
|
||
let cacheKey = "";
|
||
const activeUserId = yield firstValueFrom_firstValueFrom(this.accountService.activeAccount$.pipe(getOptionalUserId));
|
||
if (activeUserId == null) {
|
||
return null;
|
||
}
|
||
if (cipherType === CipherType.Card) {
|
||
cacheKey = "cardCiphers";
|
||
cipher = yield this.cipherService.getNextCardCipher(activeUserId);
|
||
}
|
||
else {
|
||
cacheKey = "identityCiphers";
|
||
cipher = yield this.cipherService.getNextIdentityCipher(activeUserId);
|
||
}
|
||
if (!cipher || !cacheKey || (cipher.reprompt === CipherRepromptType.Password && !fromCommand)) {
|
||
return null;
|
||
}
|
||
if (yield this.isPasswordRepromptRequired(cipher, tab)) {
|
||
if (fromCommand) {
|
||
this.cipherService.updateLastUsedIndexForUrl(cacheKey);
|
||
}
|
||
return null;
|
||
}
|
||
const totpCode = yield this.doAutoFill({
|
||
tab: tab,
|
||
cipher: cipher,
|
||
pageDetails: pageDetails,
|
||
skipLastUsed: !fromCommand,
|
||
skipUsernameOnlyFill: !fromCommand,
|
||
onlyEmptyFields: !fromCommand,
|
||
fillNewPassword: false,
|
||
allowUntrustedIframe: fromCommand,
|
||
allowTotpAutofill: false,
|
||
});
|
||
if (fromCommand) {
|
||
this.cipherService.updateLastUsedIndexForUrl(cacheKey);
|
||
}
|
||
return totpCode;
|
||
});
|
||
}
|
||
/**
|
||
* Activates the autofill on page load org policy.
|
||
*/
|
||
setAutoFillOnPageLoadOrgPolicy() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
const autofillOnPageLoadOrgPolicy = yield firstValueFrom_firstValueFrom(this.autofillSettingsService.activateAutofillOnPageLoadFromPolicy$);
|
||
if (autofillOnPageLoadOrgPolicy) {
|
||
yield this.autofillSettingsService.setAutofillOnPageLoad(true);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Gets the active tab from the current window.
|
||
* Throws an error if no tab is found.
|
||
* @returns {Promise<chrome.tabs.Tab>}
|
||
* @private
|
||
*/
|
||
getActiveTab() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
const tab = yield browser_api_BrowserApi.getTabFromCurrentWindow();
|
||
if (!tab) {
|
||
throw new Error("No tab found.");
|
||
}
|
||
return tab;
|
||
});
|
||
}
|
||
/**
|
||
* Generates the autofill script for the specified page details and cipher.
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @param {GenerateFillScriptOptions} options
|
||
* @returns {Promise<AutofillScript | null>}
|
||
* @private
|
||
*/
|
||
generateFillScript(pageDetails, options) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!pageDetails || !options.cipher) {
|
||
return null;
|
||
}
|
||
let fillScript = new AutofillScript();
|
||
const filledFields = {};
|
||
const fields = options.cipher.fields;
|
||
if (fields && fields.length) {
|
||
const fieldNames = [];
|
||
fields.forEach((f) => {
|
||
if (autofill_service_AutofillService.hasValue(f.name)) {
|
||
fieldNames.push(f.name.toLowerCase());
|
||
}
|
||
});
|
||
pageDetails.fields.forEach((field) => {
|
||
// eslint-disable-next-line
|
||
if (filledFields.hasOwnProperty(field.opid)) {
|
||
return;
|
||
}
|
||
if (!field.viewable && field.tagName !== "span") {
|
||
return;
|
||
}
|
||
// Check if the input is an untyped/mistyped search input
|
||
if (autofill_service_AutofillService.isSearchField(field)) {
|
||
return;
|
||
}
|
||
const matchingIndex = this.findMatchingFieldIndex(field, fieldNames);
|
||
if (matchingIndex > -1) {
|
||
const matchingField = fields[matchingIndex];
|
||
let val;
|
||
if (matchingField.type === FieldType.Linked) {
|
||
// Assumption: Linked Field is not being used to autofill a boolean value
|
||
val = options.cipher.linkedFieldValue(matchingField.linkedId);
|
||
}
|
||
else {
|
||
val = matchingField.value;
|
||
if (val == null && matchingField.type === FieldType.Boolean) {
|
||
val = "false";
|
||
}
|
||
}
|
||
filledFields[field.opid] = field;
|
||
autofill_service_AutofillService.fillByOpid(fillScript, field, val);
|
||
}
|
||
});
|
||
}
|
||
switch (options.cipher.type) {
|
||
case CipherType.Login:
|
||
fillScript = yield this.generateLoginFillScript(fillScript, pageDetails, filledFields, options);
|
||
break;
|
||
case CipherType.Card:
|
||
fillScript = yield this.generateCardFillScript(fillScript, pageDetails, filledFields, options);
|
||
break;
|
||
case CipherType.Identity:
|
||
fillScript = yield this.generateIdentityFillScript(fillScript, pageDetails, filledFields, options);
|
||
break;
|
||
default:
|
||
return null;
|
||
}
|
||
return fillScript;
|
||
});
|
||
}
|
||
/**
|
||
* Generates the autofill script for the specified page details and login cipher item.
|
||
* @param {AutofillScript} fillScript
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @param {{[p: string]: AutofillField}} filledFields
|
||
* @param {GenerateFillScriptOptions} options
|
||
* @returns {Promise<AutofillScript | null>}
|
||
* @private
|
||
*/
|
||
generateLoginFillScript(fillScript, pageDetails, filledFields, options) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a, _b;
|
||
if (!options.cipher.login) {
|
||
return null;
|
||
}
|
||
const passwords = [];
|
||
const usernames = new Map();
|
||
const totps = [];
|
||
let pf = null;
|
||
let username = null;
|
||
let totp = null;
|
||
const login = options.cipher.login;
|
||
fillScript.savedUrls =
|
||
(_b = (_a = login === null || login === void 0 ? void 0 : login.uris) === null || _a === void 0 ? void 0 : _a.filter((u) => u.match != domain_service_UriMatchStrategy.Never).map((u) => u.uri)) !== null && _b !== void 0 ? _b : [];
|
||
fillScript.untrustedIframe = yield this.inUntrustedIframe(pageDetails.url, options);
|
||
const passwordFields = autofill_service_AutofillService.loadPasswordFields(pageDetails, false, false, options.onlyEmptyFields, options.fillNewPassword);
|
||
const loginPasswordFields = [];
|
||
const registrationPasswordFields = [];
|
||
passwordFields.forEach((passField) => {
|
||
if (this.isRegistrationPasswordField(pageDetails, passField)) {
|
||
registrationPasswordFields.push(passField);
|
||
}
|
||
else {
|
||
loginPasswordFields.push(passField);
|
||
}
|
||
});
|
||
// Prefer login fields over registration fields
|
||
const prioritizedPasswordFields = loginPasswordFields.length > 0 ? loginPasswordFields : registrationPasswordFields;
|
||
const focusedField = options.focusedFieldOpid &&
|
||
pageDetails.fields.find((f) => f.opid === options.focusedFieldOpid);
|
||
const focusedForm = focusedField === null || focusedField === void 0 ? void 0 : focusedField.form;
|
||
const isFocusedTotpField = focusedField &&
|
||
options.allowTotpAutofill &&
|
||
(focusedField.type === "text" ||
|
||
focusedField.type === "number" ||
|
||
focusedField.type === "tel") &&
|
||
(autofill_service_AutofillService.fieldIsFuzzyMatch(focusedField, [
|
||
...AutoFillConstants.TotpFieldNames,
|
||
...AutoFillConstants.AmbiguousTotpFieldNames,
|
||
]) ||
|
||
focusedField.autoCompleteType === "one-time-code") &&
|
||
!autofill_service_AutofillService.fieldIsFuzzyMatch(focusedField, [
|
||
...AutoFillConstants.RecoveryCodeFieldNames,
|
||
]);
|
||
const focusedUsernameField = focusedField &&
|
||
!isFocusedTotpField &&
|
||
login.username &&
|
||
(focusedField.type === "text" ||
|
||
focusedField.type === "email" ||
|
||
focusedField.type === "tel") &&
|
||
focusedField;
|
||
const passwordMatchesFocused = (pf) => {
|
||
var _a;
|
||
return !focusedField
|
||
? true
|
||
: focusedForm != null
|
||
? pf.form === focusedForm
|
||
: focusedUsernameField &&
|
||
pf.form == null &&
|
||
((_a = this.findUsernameField(pageDetails, pf, false, false, true)) === null || _a === void 0 ? void 0 : _a.opid) ===
|
||
focusedUsernameField.opid;
|
||
};
|
||
const getUsernameForPassword = (pf, withoutForm) => {
|
||
// use focused username if it matches this password, otherwise fall back to finding username field before password
|
||
if (focusedUsernameField && passwordMatchesFocused(pf)) {
|
||
return focusedUsernameField;
|
||
}
|
||
return this.findUsernameField(pageDetails, pf, false, false, withoutForm);
|
||
};
|
||
if (focusedUsernameField && !prioritizedPasswordFields.some(passwordMatchesFocused)) {
|
||
if (!Object.prototype.hasOwnProperty.call(filledFields, focusedUsernameField.opid)) {
|
||
filledFields[focusedUsernameField.opid] = focusedUsernameField;
|
||
autofill_service_AutofillService.fillByOpid(fillScript, focusedUsernameField, login.username);
|
||
if (options.autoSubmitLogin && focusedUsernameField.form) {
|
||
fillScript.autosubmit = [focusedUsernameField.form];
|
||
}
|
||
return autofill_service_AutofillService.setFillScriptForFocus({ [focusedUsernameField.opid]: focusedUsernameField }, fillScript);
|
||
}
|
||
}
|
||
for (const formKey in pageDetails.forms) {
|
||
// eslint-disable-next-line
|
||
if (!pageDetails.forms.hasOwnProperty(formKey)) {
|
||
continue;
|
||
}
|
||
prioritizedPasswordFields.forEach((passField) => {
|
||
if (focusedField && !passwordMatchesFocused(passField)) {
|
||
return;
|
||
}
|
||
pf = passField;
|
||
passwords.push(pf);
|
||
if (login.username) {
|
||
username = getUsernameForPassword(pf, false);
|
||
if (username) {
|
||
usernames.set(username.opid, username);
|
||
}
|
||
}
|
||
if (options.allowTotpAutofill && login.totp) {
|
||
totp =
|
||
isFocusedTotpField && passwordMatchesFocused(passField)
|
||
? focusedField
|
||
: this.findTotpField(pageDetails, pf, false, false, false);
|
||
if (totp) {
|
||
totps.push(totp);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
if (passwordFields.length && !passwords.length) {
|
||
// in the event that password fields exist but weren't processed within form elements.
|
||
const isPasswordGeneration = options.inlineMenuFillType === InlineMenuFillTypes.PasswordGeneration;
|
||
const isCurrentPasswordUpdate = options.inlineMenuFillType === InlineMenuFillTypes.CurrentPasswordUpdate;
|
||
// For password generation or current password update, include all password fields from the same form
|
||
// This ensures we have access to all fields regardless of their login/registration classification
|
||
if ((isPasswordGeneration || isCurrentPasswordUpdate) && focusedField) {
|
||
// Add all password fields from the same form as the focused field
|
||
const focusedFieldForm = focusedField.form;
|
||
// Check both login and registration fields to ensure we get all password fields
|
||
const allPasswordFields = [...loginPasswordFields, ...registrationPasswordFields];
|
||
allPasswordFields.forEach((passField) => {
|
||
if (passField.form === focusedFieldForm) {
|
||
passwords.push(passField);
|
||
}
|
||
});
|
||
}
|
||
// If we didn't add any passwords above (either not password generation/update or no matching fields),
|
||
// select matching password if focused, otherwise first in prioritized list.
|
||
if (!passwords.length) {
|
||
const passwordFieldToUse = focusedField
|
||
? prioritizedPasswordFields.find(passwordMatchesFocused) || prioritizedPasswordFields[0]
|
||
: prioritizedPasswordFields[0];
|
||
if (passwordFieldToUse) {
|
||
passwords.push(passwordFieldToUse);
|
||
}
|
||
}
|
||
// Handle username and TOTP for the first password field
|
||
const firstPasswordField = passwords[0];
|
||
if (firstPasswordField) {
|
||
if (login.username && firstPasswordField.elementNumber > 0) {
|
||
username = getUsernameForPassword(firstPasswordField, true);
|
||
if (username) {
|
||
usernames.set(username.opid, username);
|
||
}
|
||
}
|
||
if (options.allowTotpAutofill && login.totp && firstPasswordField.elementNumber > 0) {
|
||
totp =
|
||
isFocusedTotpField && passwordMatchesFocused(firstPasswordField)
|
||
? focusedField
|
||
: this.findTotpField(pageDetails, firstPasswordField, false, false, true);
|
||
if (totp) {
|
||
totps.push(totp);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (!passwordFields.length) {
|
||
// If there are no passwords, username or TOTP fields may be present.
|
||
// username and TOTP fields are mutually exclusive
|
||
pageDetails.fields.forEach((field) => {
|
||
if (!field.viewable) {
|
||
return;
|
||
}
|
||
const isFillableTotpField = options.allowTotpAutofill &&
|
||
["number", "tel", "text"].some((t) => t === field.type) &&
|
||
(autofill_service_AutofillService.fieldIsFuzzyMatch(field, [
|
||
...AutoFillConstants.TotpFieldNames,
|
||
...AutoFillConstants.AmbiguousTotpFieldNames,
|
||
]) ||
|
||
field.autoCompleteType === "one-time-code") &&
|
||
!autofill_service_AutofillService.fieldIsFuzzyMatch(field, [...AutoFillConstants.RecoveryCodeFieldNames]);
|
||
const isFillableUsernameField = !options.skipUsernameOnlyFill &&
|
||
["email", "tel", "text"].some((t) => t === field.type) &&
|
||
autofill_service_AutofillService.fieldIsFuzzyMatch(field, AutoFillConstants.UsernameFieldNames);
|
||
// Prefer more uniquely keyworded fields first.
|
||
switch (true) {
|
||
case isFillableTotpField:
|
||
totps.push(field);
|
||
return;
|
||
case isFillableUsernameField:
|
||
usernames.set(field.opid, field);
|
||
return;
|
||
default:
|
||
return;
|
||
}
|
||
});
|
||
}
|
||
const formElementsSet = new Set();
|
||
const usernamesToFill = focusedUsernameField ? [focusedUsernameField] : [...usernames.values()];
|
||
usernamesToFill.forEach((u) => {
|
||
if (Object.prototype.hasOwnProperty.call(filledFields, u.opid)) {
|
||
return;
|
||
}
|
||
filledFields[u.opid] = u;
|
||
autofill_service_AutofillService.fillByOpid(fillScript, u, login.username);
|
||
formElementsSet.add(u.form);
|
||
});
|
||
passwords.forEach((p) => {
|
||
// eslint-disable-next-line
|
||
if (filledFields.hasOwnProperty(p.opid)) {
|
||
return;
|
||
}
|
||
filledFields[p.opid] = p;
|
||
autofill_service_AutofillService.fillByOpid(fillScript, p, login.password);
|
||
formElementsSet.add(p.form);
|
||
});
|
||
if (options.autoSubmitLogin && formElementsSet.size) {
|
||
fillScript.autosubmit = Array.from(formElementsSet);
|
||
}
|
||
if (options.allowTotpAutofill && (login === null || login === void 0 ? void 0 : login.totp)) {
|
||
yield Promise.all(totps.map((t, i) => autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
if (Object.prototype.hasOwnProperty.call(filledFields, t.opid)) {
|
||
return;
|
||
}
|
||
filledFields[t.opid] = t;
|
||
const totpResponse = yield firstValueFrom_firstValueFrom(this.totpService.getCode$(login.totp));
|
||
let totpValue = totpResponse.code;
|
||
if (totpValue.length == totps.length) {
|
||
totpValue = totpValue.charAt(i);
|
||
}
|
||
autofill_service_AutofillService.fillByOpid(fillScript, t, totpValue);
|
||
})));
|
||
}
|
||
fillScript = autofill_service_AutofillService.setFillScriptForFocus(filledFields, fillScript);
|
||
return fillScript;
|
||
});
|
||
}
|
||
/**
|
||
* Generates the autofill script for the specified page details and credit card cipher item.
|
||
* @param {AutofillScript} fillScript
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @param {{[p: string]: AutofillField}} filledFields
|
||
* @param {GenerateFillScriptOptions} options
|
||
* @returns {AutofillScript|null}
|
||
* @private
|
||
*/
|
||
generateCardFillScript(fillScript, pageDetails, filledFields, options) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!options.cipher.card) {
|
||
return null;
|
||
}
|
||
const fillFields = {};
|
||
pageDetails.fields.forEach((f) => {
|
||
if (autofill_service_AutofillService.isExcludedFieldType(f, AutoFillConstants.ExcludedAutofillTypes)) {
|
||
return;
|
||
}
|
||
for (let i = 0; i < CreditCardAutoFillConstants.CardAttributes.length; i++) {
|
||
const attr = CreditCardAutoFillConstants.CardAttributes[i];
|
||
// eslint-disable-next-line
|
||
if (!f.hasOwnProperty(attr) || !f[attr] || !f.viewable) {
|
||
continue;
|
||
}
|
||
// ref https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill
|
||
// ref https://developers.google.com/web/fundamentals/design-and-ux/input/forms/
|
||
if (!fillFields.cardholderName &&
|
||
autofill_service_AutofillService.isFieldMatch(f[attr], CreditCardAutoFillConstants.CardHolderFieldNames, CreditCardAutoFillConstants.CardHolderFieldNameValues)) {
|
||
fillFields.cardholderName = f;
|
||
break;
|
||
}
|
||
else if (!fillFields.number &&
|
||
autofill_service_AutofillService.isFieldMatch(f[attr], CreditCardAutoFillConstants.CardNumberFieldNames, CreditCardAutoFillConstants.CardNumberFieldNameValues)) {
|
||
fillFields.number = f;
|
||
break;
|
||
}
|
||
else if (!fillFields.exp &&
|
||
autofill_service_AutofillService.isFieldMatch(f[attr], CreditCardAutoFillConstants.CardExpiryFieldNames, CreditCardAutoFillConstants.CardExpiryFieldNameValues)) {
|
||
fillFields.exp = f;
|
||
break;
|
||
}
|
||
else if (!fillFields.expMonth &&
|
||
autofill_service_AutofillService.isFieldMatch(f[attr], CreditCardAutoFillConstants.ExpiryMonthFieldNames)) {
|
||
fillFields.expMonth = f;
|
||
break;
|
||
}
|
||
else if (!fillFields.expYear &&
|
||
autofill_service_AutofillService.isFieldMatch(f[attr], CreditCardAutoFillConstants.ExpiryYearFieldNames)) {
|
||
fillFields.expYear = f;
|
||
break;
|
||
}
|
||
else if (!fillFields.code &&
|
||
autofill_service_AutofillService.isFieldMatch(f[attr], CreditCardAutoFillConstants.CVVFieldNames)) {
|
||
fillFields.code = f;
|
||
break;
|
||
}
|
||
else if (!fillFields.brand &&
|
||
autofill_service_AutofillService.isFieldMatch(f[attr], CreditCardAutoFillConstants.CardBrandFieldNames)) {
|
||
fillFields.brand = f;
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
const card = options.cipher.card;
|
||
this.makeScriptAction(fillScript, card, fillFields, filledFields, "cardholderName");
|
||
this.makeScriptAction(fillScript, card, fillFields, filledFields, "number");
|
||
this.makeScriptAction(fillScript, card, fillFields, filledFields, "code");
|
||
this.makeScriptAction(fillScript, card, fillFields, filledFields, "brand");
|
||
// There is an expiration month field and the cipher has an expiration month value
|
||
if (fillFields.expMonth && autofill_service_AutofillService.hasValue(card.expMonth)) {
|
||
let expMonth = card.expMonth;
|
||
if (fillFields.expMonth.selectInfo && fillFields.expMonth.selectInfo.options) {
|
||
let index = null;
|
||
const siOptions = fillFields.expMonth.selectInfo.options;
|
||
if (siOptions.length === 12) {
|
||
index = parseInt(card.expMonth, null) - 1;
|
||
}
|
||
else if (siOptions.length === 13) {
|
||
if (siOptions[0][0] != null &&
|
||
siOptions[0][0] !== "" &&
|
||
(siOptions[12][0] == null || siOptions[12][0] === "")) {
|
||
index = parseInt(card.expMonth, null) - 1;
|
||
}
|
||
else {
|
||
index = parseInt(card.expMonth, null);
|
||
}
|
||
}
|
||
if (index != null) {
|
||
const option = siOptions[index];
|
||
if (option.length > 1) {
|
||
expMonth = option[1];
|
||
}
|
||
}
|
||
}
|
||
else if ((this.fieldAttrsContain(fillFields.expMonth, "mm") ||
|
||
fillFields.expMonth.maxLength === 2) &&
|
||
expMonth.length === 1) {
|
||
expMonth = "0" + expMonth;
|
||
}
|
||
filledFields[fillFields.expMonth.opid] = fillFields.expMonth;
|
||
autofill_service_AutofillService.fillByOpid(fillScript, fillFields.expMonth, expMonth);
|
||
}
|
||
// There is an expiration year field and the cipher has an expiration year value
|
||
if (fillFields.expYear && autofill_service_AutofillService.hasValue(card.expYear)) {
|
||
let expYear = card.expYear;
|
||
if (fillFields.expYear.selectInfo && fillFields.expYear.selectInfo.options) {
|
||
for (let i = 0; i < fillFields.expYear.selectInfo.options.length; i++) {
|
||
const o = fillFields.expYear.selectInfo.options[i];
|
||
if (o[0] === card.expYear || o[1] === card.expYear) {
|
||
expYear = o[1];
|
||
break;
|
||
}
|
||
if (o[1].length === 2 &&
|
||
card.expYear.length === 4 &&
|
||
o[1] === card.expYear.substring(2)) {
|
||
expYear = o[1];
|
||
break;
|
||
}
|
||
const colonIndex = o[1].indexOf(":");
|
||
if (colonIndex > -1 && o[1].length > colonIndex + 1) {
|
||
const val = o[1].substring(colonIndex + 2);
|
||
if (val != null && val.trim() !== "" && val === card.expYear) {
|
||
expYear = o[1];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (this.fieldAttrsContain(fillFields.expYear, "yyyy") ||
|
||
fillFields.expYear.maxLength === 4) {
|
||
if (expYear.length === 2) {
|
||
expYear = normalizeExpiryYearFormat(expYear);
|
||
}
|
||
}
|
||
else if (this.fieldAttrsContain(fillFields.expYear, "yy") ||
|
||
fillFields.expYear.maxLength === 2) {
|
||
if (expYear.length === 4) {
|
||
expYear = expYear.substr(2);
|
||
}
|
||
}
|
||
filledFields[fillFields.expYear.opid] = fillFields.expYear;
|
||
autofill_service_AutofillService.fillByOpid(fillScript, fillFields.expYear, expYear);
|
||
}
|
||
// There is a single expiry date field (combined values) and the cipher has both expiration month and year
|
||
if (fillFields.exp &&
|
||
autofill_service_AutofillService.hasValue(card.expMonth) &&
|
||
autofill_service_AutofillService.hasValue(card.expYear)) {
|
||
const combinedExpiryFillValue = this.generateCombinedExpiryValue(card, fillFields.exp);
|
||
this.makeScriptActionWithValue(fillScript, combinedExpiryFillValue, fillFields.exp, filledFields);
|
||
}
|
||
return fillScript;
|
||
});
|
||
}
|
||
/**
|
||
* Determines whether an iframe is potentially dangerous ("untrusted") to autofill
|
||
* @param {string} pageUrl The url of the page/iframe, usually from AutofillPageDetails
|
||
* @param {GenerateFillScriptOptions} options The GenerateFillScript options
|
||
* @returns {boolean} `true` if the iframe is untrusted and a warning should be shown, `false` otherwise
|
||
* @private
|
||
*/
|
||
inUntrustedIframe(pageUrl, options) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
// If the pageUrl (from the content script) matches the tabUrl (from the sender tab), we are not in an iframe
|
||
// This also avoids a false positive if no URI is saved and the user triggers autofill anyway
|
||
if (pageUrl === options.tabUrl) {
|
||
return false;
|
||
}
|
||
// Check the pageUrl against cipher URIs using the configured match detection.
|
||
// Remember: if we are in this function, the tabUrl already matches a saved URI for the login.
|
||
// We need to verify the pageUrl also matches.
|
||
const equivalentDomains = yield firstValueFrom_firstValueFrom(this.domainSettingsService.getUrlEquivalentDomains(pageUrl));
|
||
const matchesUri = options.cipher.login.matchesUri(pageUrl, equivalentDomains, options.defaultUriMatch);
|
||
return !matchesUri;
|
||
});
|
||
}
|
||
/**
|
||
* Used when handling autofill on credit card fields. Determines whether
|
||
* the field has an attribute that matches the given value.
|
||
* @param {AutofillField} field
|
||
* @param {string} containsValue
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
fieldAttrsContain(field, containsValue) {
|
||
if (!field) {
|
||
return false;
|
||
}
|
||
let doesContainValue = false;
|
||
CreditCardAutoFillConstants.CardAttributesExtended.forEach((attributeName) => {
|
||
if (doesContainValue || !field[attributeName]) {
|
||
return;
|
||
}
|
||
let fieldValue = field[attributeName];
|
||
fieldValue = fieldValue.replace(/ /g, "").toLowerCase();
|
||
doesContainValue = fieldValue.indexOf(containsValue) > -1;
|
||
});
|
||
return doesContainValue;
|
||
}
|
||
/**
|
||
* Returns a string value representation of the combined card expiration month and year values
|
||
* in a format matching discovered guidance within the field attributes (typically provided for users).
|
||
*
|
||
* @param {CardView} cardCipher
|
||
* @param {AutofillField} field
|
||
*/
|
||
generateCombinedExpiryValue(cardCipher, field) {
|
||
/*
|
||
Some expectations of the passed stored card cipher view:
|
||
|
||
- At the time of writing, the stored card expiry year value (`expYear`)
|
||
can be any arbitrary string (no format validation). We may attempt some format
|
||
normalization here, but expect the user to have entered a string of integers
|
||
with a length of 2 or 4
|
||
|
||
- the `expiration` property cannot be used for autofill as it is an opinionated
|
||
format
|
||
|
||
- `expMonth` a stringified integer stored with no zero-padding and is not
|
||
zero-indexed (e.g. January is "1", not "01" or 0)
|
||
*/
|
||
var _a;
|
||
// Expiry format options
|
||
let useMonthPadding = true;
|
||
let useYearFull = false;
|
||
let delimiter = "/";
|
||
let orderByYear = false;
|
||
// Because users are allowed to store truncated years, we need to make assumptions
|
||
// about the full year format when called for
|
||
const currentCentury = `${new Date().getFullYear()}`.slice(0, 2);
|
||
// Note, we construct the output rather than doing string replacement against the
|
||
// format guidance pattern to avoid edge cases that would output invalid values
|
||
const [
|
||
// The guidance parsed from the field properties regarding expiry format
|
||
expectedExpiryDateFormat,
|
||
// The (localized) date pattern set that was used to parse the expiry format guidance
|
||
expiryDateFormatPatterns,] = this.getExpectedExpiryDateFormat(field);
|
||
if (expectedExpiryDateFormat) {
|
||
const { Month, MonthShort, Year } = expiryDateFormatPatterns;
|
||
const expiryDateDelimitersPattern = "\\" + CardExpiryDateDelimiters.join("\\");
|
||
// assign the delimiter from the expected format string
|
||
delimiter =
|
||
((_a = expectedExpiryDateFormat.match(new RegExp(`[${expiryDateDelimitersPattern}]`, "g"))) === null || _a === void 0 ? void 0 : _a[0]) ||
|
||
"";
|
||
// check if the expected format starts with a month form
|
||
// order matters here; check long form first, since short form will match against long
|
||
if (expectedExpiryDateFormat.indexOf(Month + delimiter) === 0) {
|
||
useMonthPadding = true;
|
||
orderByYear = false;
|
||
}
|
||
else if (expectedExpiryDateFormat.indexOf(MonthShort + delimiter) === 0) {
|
||
useMonthPadding = false;
|
||
orderByYear = false;
|
||
}
|
||
else {
|
||
orderByYear = true;
|
||
// short form can match against long form, but long won't match against short
|
||
const containsLongMonthPattern = new RegExp(`${Month}`, "i");
|
||
useMonthPadding = containsLongMonthPattern.test(expectedExpiryDateFormat);
|
||
}
|
||
const containsLongYearPattern = new RegExp(`${Year}`, "i");
|
||
useYearFull = containsLongYearPattern.test(expectedExpiryDateFormat);
|
||
}
|
||
const month = useMonthPadding
|
||
? // Ensure zero-padding
|
||
("0" + cardCipher.expMonth).slice(-2)
|
||
: // Handle zero-padded stored month values, even though they are not _expected_ to be as such
|
||
cardCipher.expMonth.replaceAll("0", "");
|
||
// Note: assumes the user entered an `expYear` value with a length of either 2 or 4
|
||
const year = (currentCentury + cardCipher.expYear).slice(useYearFull ? -4 : -2);
|
||
const combinedExpiryFillValue = (orderByYear ? [year, month] : [month, year]).join(delimiter);
|
||
return combinedExpiryFillValue;
|
||
}
|
||
/**
|
||
* Returns a string value representation of discovered guidance for a combined month and year expiration value from the field attributes
|
||
*
|
||
* @param {AutofillField} field
|
||
*/
|
||
getExpectedExpiryDateFormat(field) {
|
||
let expectedDateFormat = null;
|
||
let dateFormatPatterns = null;
|
||
const expiryDateDelimitersPattern = "\\" + CardExpiryDateDelimiters.join("\\");
|
||
CreditCardAutoFillConstants.CardExpiryDateFormats.find((dateFormat) => {
|
||
dateFormatPatterns = dateFormat;
|
||
const { Month, MonthShort, YearShort, Year } = dateFormat;
|
||
// Non-exhaustive coverage of field guidances. Some uncovered edge cases: ". " delimiter, space-delimited delimiters ("mm / yyyy").
|
||
// We should consider if added whitespace is for improved readability of user-guidance or actually desired in the filled value.
|
||
// e.g. "/((mm|m)[\/\-\.\ ]{0,1}(yyyy|yy))|((yyyy|yy)[\/\-\.\ ]{0,1}(mm|m))/gi"
|
||
const dateFormatPattern = new RegExp(`((${Month}|${MonthShort})[${expiryDateDelimitersPattern}]{0,1}(${Year}|${YearShort}))|((${Year}|${YearShort})[${expiryDateDelimitersPattern}]{0,1}(${Month}|${MonthShort}))`, "gi");
|
||
return CreditCardAutoFillConstants.CardAttributesExtended.find((attributeName) => {
|
||
var _a;
|
||
const fieldAttributeValue = (_a = field[attributeName]) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase();
|
||
const fieldAttributeMatch = fieldAttributeValue === null || fieldAttributeValue === void 0 ? void 0 : fieldAttributeValue.match(dateFormatPattern);
|
||
// break find as soon as a match is found
|
||
if (fieldAttributeMatch === null || fieldAttributeMatch === void 0 ? void 0 : fieldAttributeMatch.length) {
|
||
expectedDateFormat = fieldAttributeMatch[0];
|
||
// remove any irrelevant characters
|
||
const irrelevantExpiryCharactersPattern = new RegExp(
|
||
// "or digits" to ensure numbers are removed from guidance pattern, which aren't covered by ^\w
|
||
`[^\\w${expiryDateDelimitersPattern}]|[\\d]`, "gi");
|
||
expectedDateFormat.replaceAll(irrelevantExpiryCharactersPattern, "");
|
||
return true;
|
||
}
|
||
return false;
|
||
});
|
||
});
|
||
// @TODO if expectedDateFormat is still null, and there is a `pattern` attribute, cycle
|
||
// through generated formatted values, checking against the provided regex pattern
|
||
return [expectedDateFormat, dateFormatPatterns];
|
||
}
|
||
/**
|
||
* Generates the autofill script for the specified page details and identity cipher item.
|
||
*
|
||
* @param fillScript - Object to store autofill script, passed between method references
|
||
* @param pageDetails - The details of the page to autofill
|
||
* @param filledFields - The fields that have already been filled, passed between method references
|
||
* @param options - Contains data used to fill cipher items
|
||
*/
|
||
generateIdentityFillScript(fillScript, pageDetails, filledFields, options) {
|
||
const identity = options.cipher.identity;
|
||
if (!identity) {
|
||
return null;
|
||
}
|
||
for (let fieldsIndex = 0; fieldsIndex < pageDetails.fields.length; fieldsIndex++) {
|
||
const field = pageDetails.fields[fieldsIndex];
|
||
if (this.excludeFieldFromIdentityFill(field)) {
|
||
continue;
|
||
}
|
||
const keywordsList = this.getIdentityAutofillFieldKeywords(field);
|
||
const keywordsCombined = keywordsList.join(",");
|
||
if (this.shouldMakeIdentityTitleFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.title, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityNameFillScript(filledFields, keywordsList)) {
|
||
this.makeIdentityNameFillScript(fillScript, filledFields, field, identity);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityFirstNameFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.firstName, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityMiddleNameFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.middleName, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityLastNameFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.lastName, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityEmailFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.email, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityAddress1FillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.address1, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityAddress2FillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.address2, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityAddress3FillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.address3, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityAddressFillScript(filledFields, keywordsList)) {
|
||
this.makeIdentityAddressFillScript(fillScript, filledFields, field, identity);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityPostalCodeFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.postalCode, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityCityFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.city, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityStateFillScript(filledFields, keywordsCombined)) {
|
||
this.makeIdentityStateFillScript(fillScript, filledFields, field, identity);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityCountryFillScript(filledFields, keywordsCombined)) {
|
||
this.makeIdentityCountryFillScript(fillScript, filledFields, field, identity);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityPhoneFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.phone, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityUserNameFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.username, field, filledFields);
|
||
continue;
|
||
}
|
||
if (this.shouldMakeIdentityCompanyFillScript(filledFields, keywordsCombined)) {
|
||
this.makeScriptActionWithValue(fillScript, identity.company, field, filledFields);
|
||
}
|
||
}
|
||
return fillScript;
|
||
}
|
||
/**
|
||
* Identifies if the current field should be excluded from triggering autofill of the identity cipher.
|
||
*
|
||
* @param field - The field to check
|
||
*/
|
||
excludeFieldFromIdentityFill(field) {
|
||
return (autofill_service_AutofillService.isExcludedFieldType(field, [
|
||
"password",
|
||
...AutoFillConstants.ExcludedAutofillTypes,
|
||
]) ||
|
||
AutoFillConstants.ExcludedIdentityAutocompleteTypes.has(field.autoCompleteType) ||
|
||
!field.viewable);
|
||
}
|
||
/**
|
||
* Gathers all unique keyword identifiers from a field that can be used to determine what
|
||
* identity value should be filled.
|
||
*
|
||
* @param field - The field to gather keywords from
|
||
*/
|
||
getIdentityAutofillFieldKeywords(field) {
|
||
const keywords = new Set();
|
||
for (let index = 0; index < IdentityAutoFillConstants.IdentityAttributes.length; index++) {
|
||
const attribute = IdentityAutoFillConstants.IdentityAttributes[index];
|
||
if (field[attribute]) {
|
||
keywords.add(field[attribute]
|
||
.trim()
|
||
.toLowerCase()
|
||
.replace(/[^a-zA-Z0-9]+/g, ""));
|
||
}
|
||
}
|
||
return Array.from(keywords);
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity title
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityTitleFillScript(filledFields, keywords) {
|
||
return (!filledFields.title &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.TitleFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity name
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityNameFillScript(filledFields, keywords) {
|
||
return (!filledFields.name &&
|
||
keywords.some((keyword) => autofill_service_AutofillService.isFieldMatch(keyword, IdentityAutoFillConstants.FullNameFieldNames, IdentityAutoFillConstants.FullNameFieldNameValues)));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity first name
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityFirstNameFillScript(filledFields, keywords) {
|
||
return (!filledFields.firstName &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.FirstnameFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity middle name
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityMiddleNameFillScript(filledFields, keywords) {
|
||
return (!filledFields.middleName &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.MiddlenameFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity last name
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityLastNameFillScript(filledFields, keywords) {
|
||
return (!filledFields.lastName &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.LastnameFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity email
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityEmailFillScript(filledFields, keywords) {
|
||
return (!filledFields.email &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.EmailFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity address
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityAddressFillScript(filledFields, keywords) {
|
||
return (!filledFields.address &&
|
||
keywords.some((keyword) => autofill_service_AutofillService.isFieldMatch(keyword, IdentityAutoFillConstants.AddressFieldNames, IdentityAutoFillConstants.AddressFieldNameValues)));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity address1
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityAddress1FillScript(filledFields, keywords) {
|
||
return (!filledFields.address1 &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.Address1FieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity address2
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityAddress2FillScript(filledFields, keywords) {
|
||
return (!filledFields.address2 &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.Address2FieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity address3
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityAddress3FillScript(filledFields, keywords) {
|
||
return (!filledFields.address3 &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.Address3FieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity postal code
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityPostalCodeFillScript(filledFields, keywords) {
|
||
return (!filledFields.postalCode &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.PostalCodeFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity city
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityCityFillScript(filledFields, keywords) {
|
||
return (!filledFields.city &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.CityFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity state
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityStateFillScript(filledFields, keywords) {
|
||
return (!filledFields.state &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.StateFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity country
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityCountryFillScript(filledFields, keywords) {
|
||
return (!filledFields.country &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.CountryFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity phone
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityPhoneFillScript(filledFields, keywords) {
|
||
return (!filledFields.phone &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.PhoneFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity username
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityUserNameFillScript(filledFields, keywords) {
|
||
return (!filledFields.username &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.UserNameFieldNames));
|
||
}
|
||
/**
|
||
* Identifies if a fill script action for the identity company
|
||
* field should be created for the provided field.
|
||
*
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param keywords - The keywords from the field
|
||
*/
|
||
shouldMakeIdentityCompanyFillScript(filledFields, keywords) {
|
||
return (!filledFields.company &&
|
||
autofill_service_AutofillService.isFieldMatch(keywords, IdentityAutoFillConstants.CompanyFieldNames));
|
||
}
|
||
/**
|
||
* Creates an identity name fill script action for the provided field. This is used
|
||
* when filling a `full name` field, using the first, middle, and last name from the
|
||
* identity cipher item.
|
||
*
|
||
* @param fillScript - The autofill script to add the action to
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param field - The field to fill
|
||
* @param identity - The identity cipher item
|
||
*/
|
||
makeIdentityNameFillScript(fillScript, filledFields, field, identity) {
|
||
let name = "";
|
||
if (identity.firstName) {
|
||
name += identity.firstName;
|
||
}
|
||
if (identity.middleName) {
|
||
name += !name ? identity.middleName : ` ${identity.middleName}`;
|
||
}
|
||
if (identity.lastName) {
|
||
name += !name ? identity.lastName : ` ${identity.lastName}`;
|
||
}
|
||
this.makeScriptActionWithValue(fillScript, name, field, filledFields);
|
||
}
|
||
/**
|
||
* Creates an identity address fill script action for the provided field. This is used
|
||
* when filling a generic `address` field, using the address1, address2, and address3
|
||
* from the identity cipher item.
|
||
*
|
||
* @param fillScript - The autofill script to add the action to
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param field - The field to fill
|
||
* @param identity - The identity cipher item
|
||
*/
|
||
makeIdentityAddressFillScript(fillScript, filledFields, field, identity) {
|
||
if (!identity.address1) {
|
||
return;
|
||
}
|
||
let address = identity.address1;
|
||
if (identity.address2) {
|
||
address += `, ${identity.address2}`;
|
||
}
|
||
if (identity.address3) {
|
||
address += `, ${identity.address3}`;
|
||
}
|
||
this.makeScriptActionWithValue(fillScript, address, field, filledFields);
|
||
}
|
||
/**
|
||
* Creates an identity state fill script action for the provided field. This is used
|
||
* when filling a `state` field, using the state value from the identity cipher item.
|
||
* If the state value is a full name, it will be converted to an ISO code.
|
||
*
|
||
* @param fillScript - The autofill script to add the action to
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param field - The field to fill
|
||
* @param identity - The identity cipher item
|
||
*/
|
||
makeIdentityStateFillScript(fillScript, filledFields, field, identity) {
|
||
if (!identity.state) {
|
||
return;
|
||
}
|
||
if (identity.state.length <= 2) {
|
||
this.makeScriptActionWithValue(fillScript, identity.state, field, filledFields);
|
||
return;
|
||
}
|
||
const stateLower = identity.state.toLowerCase();
|
||
const isoState = IdentityAutoFillConstants.IsoStates[stateLower] ||
|
||
IdentityAutoFillConstants.IsoProvinces[stateLower];
|
||
if (isoState) {
|
||
this.makeScriptActionWithValue(fillScript, isoState, field, filledFields);
|
||
}
|
||
}
|
||
/**
|
||
* Creates an identity country fill script action for the provided field. This is used
|
||
* when filling a `country` field, using the country value from the identity cipher item.
|
||
* If the country value is a full name, it will be converted to an ISO code.
|
||
*
|
||
* @param fillScript - The autofill script to add the action to
|
||
* @param filledFields - The fields that have already been filled
|
||
* @param field - The field to fill
|
||
* @param identity - The identity cipher item
|
||
*/
|
||
makeIdentityCountryFillScript(fillScript, filledFields, field, identity) {
|
||
if (!identity.country) {
|
||
return;
|
||
}
|
||
if (identity.country.length <= 2) {
|
||
this.makeScriptActionWithValue(fillScript, identity.country, field, filledFields);
|
||
return;
|
||
}
|
||
const countryLower = identity.country.toLowerCase();
|
||
const isoCountry = IdentityAutoFillConstants.IsoCountries[countryLower];
|
||
if (isoCountry) {
|
||
this.makeScriptActionWithValue(fillScript, isoCountry, field, filledFields);
|
||
}
|
||
}
|
||
/**
|
||
* Accepts an HTMLInputElement type value and a list of
|
||
* excluded types and returns true if the type is excluded.
|
||
* @param {string} type
|
||
* @param {string[]} excludedTypes
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
static isExcludedType(type, excludedTypes) {
|
||
return excludedTypes.indexOf(type) > -1;
|
||
}
|
||
/**
|
||
* Identifies if a passed field contains text artifacts that identify it as a search field.
|
||
*
|
||
* @param field - The autofill field that we are validating as a search field
|
||
*/
|
||
static isSearchField(field) {
|
||
const matchFieldAttributeValues = [field.type, field.htmlName, field.htmlID, field.placeholder];
|
||
for (let attrIndex = 0; attrIndex < matchFieldAttributeValues.length; attrIndex++) {
|
||
if (!matchFieldAttributeValues[attrIndex]) {
|
||
continue;
|
||
}
|
||
// Separate camel case words and case them to lower case values
|
||
const camelCaseSeparatedFieldAttribute = matchFieldAttributeValues[attrIndex]
|
||
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||
.toLowerCase();
|
||
// Split the attribute by non-alphabetical characters to get the keywords
|
||
const attributeKeywords = camelCaseSeparatedFieldAttribute.split(/[^a-z]/gi);
|
||
for (let keywordIndex = 0; keywordIndex < attributeKeywords.length; keywordIndex++) {
|
||
if (autofill_service_AutofillService.searchFieldNamesSet.has(attributeKeywords[keywordIndex])) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
static isExcludedFieldType(field, excludedTypes) {
|
||
if (autofill_service_AutofillService.forCustomFieldsOnly(field)) {
|
||
return true;
|
||
}
|
||
if (this.isExcludedType(field.type, excludedTypes)) {
|
||
return true;
|
||
}
|
||
// Check if the input is an untyped/mistyped search input
|
||
return this.isSearchField(field);
|
||
}
|
||
/**
|
||
* Accepts the value of a field, a list of possible options that define if
|
||
* a field can be matched to a vault cipher, and a secondary optional list
|
||
* of options that define if a field can be matched to a vault cipher. Returns
|
||
* true if the field value matches one of the options.
|
||
* @param {string} value
|
||
* @param {string[]} options
|
||
* @param {string[]} containsOptions
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
static isFieldMatch(value, options, containsOptions) {
|
||
value = value
|
||
.trim()
|
||
.toLowerCase()
|
||
.replace(/[^a-zA-Z0-9]+/g, "");
|
||
for (let i = 0; i < options.length; i++) {
|
||
let option = options[i];
|
||
const checkValueContains = containsOptions == null || containsOptions.indexOf(option) > -1;
|
||
option = option.toLowerCase().replace(/-/g, "");
|
||
if (value === option || (checkValueContains && value.indexOf(option) > -1)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Helper method used to create a script action for a field. Conditionally
|
||
* accepts a fieldProp value that will be used in place of the dataProp value.
|
||
* @param {AutofillScript} fillScript
|
||
* @param cipherData
|
||
* @param {{[p: string]: AutofillField}} fillFields
|
||
* @param {{[p: string]: AutofillField}} filledFields
|
||
* @param {string} dataProp
|
||
* @param {string} fieldProp
|
||
* @private
|
||
*/
|
||
makeScriptAction(fillScript, cipherData, fillFields, filledFields, dataProp, fieldProp) {
|
||
fieldProp = fieldProp || dataProp;
|
||
this.makeScriptActionWithValue(fillScript, cipherData[dataProp], fillFields[fieldProp], filledFields);
|
||
}
|
||
/**
|
||
* Handles updating the list of filled fields and adding a script action
|
||
* to the fill script. If a select field is passed as part of the fill options,
|
||
* we iterate over the options to check if the passed value matches one of the
|
||
* options. If it does, we add a script action to select the option.
|
||
* @param {AutofillScript} fillScript
|
||
* @param dataValue
|
||
* @param {AutofillField} field
|
||
* @param {{[p: string]: AutofillField}} filledFields
|
||
* @private
|
||
*/
|
||
makeScriptActionWithValue(fillScript, dataValue, field, filledFields) {
|
||
let doFill = false;
|
||
if (autofill_service_AutofillService.hasValue(dataValue) && field) {
|
||
if (field.type === "select-one" && field.selectInfo && field.selectInfo.options) {
|
||
for (let i = 0; i < field.selectInfo.options.length; i++) {
|
||
const option = field.selectInfo.options[i];
|
||
for (let j = 0; j < option.length; j++) {
|
||
if (autofill_service_AutofillService.hasValue(option[j]) &&
|
||
option[j].toLowerCase() === dataValue.toLowerCase()) {
|
||
doFill = true;
|
||
if (option.length > 1) {
|
||
dataValue = option[1];
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
if (doFill) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
doFill = true;
|
||
}
|
||
}
|
||
if (doFill) {
|
||
filledFields[field.opid] = field;
|
||
autofill_service_AutofillService.fillByOpid(fillScript, field, dataValue);
|
||
}
|
||
}
|
||
static valueIsLikePassword(value) {
|
||
if (value == null) {
|
||
return false;
|
||
}
|
||
// Removes all whitespace, _ and - characters
|
||
const cleanedValue = value.toLowerCase().replace(/[\s_-]/g, "");
|
||
if (cleanedValue.indexOf("password") < 0) {
|
||
return false;
|
||
}
|
||
return !AutoFillConstants.PasswordFieldExcludeList.some((i) => cleanedValue.indexOf(i) > -1);
|
||
}
|
||
static fieldHasDisqualifyingAttributeValue(field) {
|
||
const checkedAttributeValues = [field.htmlID, field.htmlName, field.placeholder];
|
||
let valueIsOnExclusionList = false;
|
||
for (let i = 0; i < checkedAttributeValues.length; i++) {
|
||
const checkedAttributeValue = checkedAttributeValues[i];
|
||
const cleanedValue = checkedAttributeValue === null || checkedAttributeValue === void 0 ? void 0 : checkedAttributeValue.toLowerCase().replace(/[\s_-]/g, "");
|
||
valueIsOnExclusionList = Boolean(cleanedValue && AutoFillConstants.FieldIgnoreList.some((i) => cleanedValue.indexOf(i) > -1));
|
||
if (valueIsOnExclusionList) {
|
||
break;
|
||
}
|
||
}
|
||
return valueIsOnExclusionList;
|
||
}
|
||
/**
|
||
* Accepts a pageDetails object with a list of fields and returns a list of
|
||
* fields that are likely to be password fields.
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @param {boolean} canBeHidden
|
||
* @param {boolean} canBeReadOnly
|
||
* @param {boolean} mustBeEmpty
|
||
* @param {boolean} fillNewPassword
|
||
* @returns {AutofillField[]}
|
||
*/
|
||
static loadPasswordFields(pageDetails, canBeHidden, canBeReadOnly, mustBeEmpty, fillNewPassword) {
|
||
const arr = [];
|
||
pageDetails.fields.forEach((f) => {
|
||
const isPassword = f.type === "password";
|
||
if (!isPassword &&
|
||
autofill_service_AutofillService.isExcludedFieldType(f, AutoFillConstants.ExcludedAutofillLoginTypes)) {
|
||
return;
|
||
}
|
||
// If any attribute values match disqualifying values, the entire field should not be used
|
||
if (autofill_service_AutofillService.fieldHasDisqualifyingAttributeValue(f)) {
|
||
return;
|
||
}
|
||
// We want to avoid treating TOTP fields as password fields
|
||
if (autofill_service_AutofillService.fieldIsFuzzyMatch(f, AutoFillConstants.TotpFieldNames)) {
|
||
return;
|
||
}
|
||
const isLikePassword = () => {
|
||
if (f.type !== "text") {
|
||
return false;
|
||
}
|
||
const testedValues = [f.htmlID, f.htmlName, f.placeholder];
|
||
for (let i = 0; i < testedValues.length; i++) {
|
||
if (autofill_service_AutofillService.valueIsLikePassword(testedValues[i])) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
};
|
||
if (!f.disabled &&
|
||
(canBeReadOnly || !f.readonly) &&
|
||
(isPassword || isLikePassword()) &&
|
||
(canBeHidden || f.viewable) &&
|
||
(!mustBeEmpty || f.value == null || f.value.trim() === "") &&
|
||
(fillNewPassword || f.autoCompleteType !== "new-password")) {
|
||
arr.push(f);
|
||
}
|
||
});
|
||
return arr;
|
||
}
|
||
/**
|
||
* Determines if a password field is part of a registration/signup form.
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @param {AutofillField} passwordField
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isRegistrationPasswordField(pageDetails, passwordField) {
|
||
var _a, _b, _c, _d, _e, _f, _g, _h;
|
||
if (!passwordField.form || !pageDetails.forms) {
|
||
return false;
|
||
}
|
||
const form = pageDetails.forms[passwordField.form];
|
||
if (!form) {
|
||
return false;
|
||
}
|
||
const formIdentifierValues = [
|
||
(_b = (_a = form.htmlID) === null || _a === void 0 ? void 0 : _a.toLowerCase) === null || _b === void 0 ? void 0 : _b.call(_a),
|
||
(_d = (_c = form.htmlName) === null || _c === void 0 ? void 0 : _c.toLowerCase) === null || _d === void 0 ? void 0 : _d.call(_c),
|
||
(_f = (_e = passwordField === null || passwordField === void 0 ? void 0 : passwordField.htmlID) === null || _e === void 0 ? void 0 : _e.toLowerCase) === null || _f === void 0 ? void 0 : _f.call(_e),
|
||
(_h = (_g = passwordField === null || passwordField === void 0 ? void 0 : passwordField.htmlName) === null || _g === void 0 ? void 0 : _g.toLowerCase) === null || _h === void 0 ? void 0 : _h.call(_g),
|
||
].filter(Boolean);
|
||
return formIdentifierValues.some((value) => AutoFillConstants.RegistrationKeywords.some((keyword) => value.includes(keyword)));
|
||
}
|
||
/**
|
||
* Accepts a pageDetails object with a list of fields and returns a list of
|
||
* fields that are likely to be username fields.
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @param {AutofillField} passwordField
|
||
* @param {boolean} canBeHidden
|
||
* @param {boolean} canBeReadOnly
|
||
* @param {boolean} withoutForm
|
||
* @returns {AutofillField}
|
||
* @private
|
||
*/
|
||
findUsernameField(pageDetails, passwordField, canBeHidden, canBeReadOnly, withoutForm) {
|
||
let usernameField = null;
|
||
let usernameFieldInSameForm = null;
|
||
for (let i = 0; i < pageDetails.fields.length; i++) {
|
||
const f = pageDetails.fields[i];
|
||
if (autofill_service_AutofillService.forCustomFieldsOnly(f)) {
|
||
continue;
|
||
}
|
||
if (f.elementNumber >= passwordField.elementNumber) {
|
||
break;
|
||
}
|
||
const includesUsernameFieldName = this.findMatchingFieldIndex(f, AutoFillConstants.UsernameFieldNames) > -1;
|
||
// only consider fields in same form if both have non-null form values
|
||
// null forms are treated as separate
|
||
const isInSameForm = f.form != null && passwordField.form != null && f.form === passwordField.form;
|
||
// An email or tel field in the same form as the password field is likely a qualified
|
||
// candidate for autofill, even if visibility checks are unreliable
|
||
const isQualifiedUsernameField = isInSameForm && (f.type === "email" || f.type === "tel");
|
||
if (!f.disabled &&
|
||
(canBeReadOnly || !f.readonly) &&
|
||
(withoutForm || isInSameForm || includesUsernameFieldName) &&
|
||
(canBeHidden || f.viewable || isQualifiedUsernameField) &&
|
||
(f.type === "text" || f.type === "email" || f.type === "tel")) {
|
||
// Prioritize fields in the same form as the password field
|
||
if (isInSameForm) {
|
||
usernameFieldInSameForm = f;
|
||
if (includesUsernameFieldName) {
|
||
return f;
|
||
}
|
||
}
|
||
else {
|
||
usernameField = f;
|
||
}
|
||
}
|
||
}
|
||
// Prefer username field in same form, fall back to any username field
|
||
return usernameFieldInSameForm || usernameField;
|
||
}
|
||
/**
|
||
* Accepts a pageDetails object with a list of fields and returns a list of
|
||
* fields that are likely to be TOTP fields.
|
||
* @param {AutofillPageDetails} pageDetails
|
||
* @param {AutofillField} passwordField
|
||
* @param {boolean} canBeHidden
|
||
* @param {boolean} canBeReadOnly
|
||
* @param {boolean} withoutForm
|
||
* @returns {AutofillField}
|
||
* @private
|
||
*/
|
||
findTotpField(pageDetails, passwordField, canBeHidden, canBeReadOnly, withoutForm) {
|
||
let totpField = null;
|
||
for (let i = 0; i < pageDetails.fields.length; i++) {
|
||
const f = pageDetails.fields[i];
|
||
if (autofill_service_AutofillService.forCustomFieldsOnly(f)) {
|
||
continue;
|
||
}
|
||
const fieldIsDisqualified = autofill_service_AutofillService.fieldHasDisqualifyingAttributeValue(f);
|
||
if (!fieldIsDisqualified &&
|
||
!f.disabled &&
|
||
(canBeReadOnly || !f.readonly) &&
|
||
(withoutForm || f.form === passwordField.form) &&
|
||
(canBeHidden || f.viewable) &&
|
||
(f.type === "text" ||
|
||
f.type === "number" ||
|
||
// sites will commonly use tel in order to get the digit pad against semantic recommendations
|
||
f.type === "tel") &&
|
||
autofill_service_AutofillService.fieldIsFuzzyMatch(f, [
|
||
...AutoFillConstants.TotpFieldNames,
|
||
...AutoFillConstants.AmbiguousTotpFieldNames,
|
||
]) &&
|
||
!autofill_service_AutofillService.fieldIsFuzzyMatch(f, [...AutoFillConstants.RecoveryCodeFieldNames])) {
|
||
totpField = f;
|
||
if (this.findMatchingFieldIndex(f, [
|
||
...AutoFillConstants.TotpFieldNames,
|
||
...AutoFillConstants.AmbiguousTotpFieldNames,
|
||
]) > -1 ||
|
||
f.autoCompleteType === "one-time-code") {
|
||
// We found an exact match. No need to keep looking.
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
return totpField;
|
||
}
|
||
/**
|
||
* Accepts a field and returns the index of the first matching property
|
||
* present in a list of attribute names.
|
||
* @param {AutofillField} field
|
||
* @param {string[]} names
|
||
* @returns {number}
|
||
* @private
|
||
*/
|
||
findMatchingFieldIndex(field, names) {
|
||
for (let i = 0; i < names.length; i++) {
|
||
if (names[i].indexOf("=") > -1) {
|
||
if (this.fieldPropertyIsPrefixMatch(field, "htmlID", names[i], "id")) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsPrefixMatch(field, "htmlName", names[i], "name")) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsPrefixMatch(field, "label-left", names[i], "label")) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsPrefixMatch(field, "label-right", names[i], "label")) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsPrefixMatch(field, "label-tag", names[i], "label")) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsPrefixMatch(field, "label-aria", names[i], "label")) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsPrefixMatch(field, "placeholder", names[i], "placeholder")) {
|
||
return i;
|
||
}
|
||
}
|
||
if (this.fieldPropertyIsMatch(field, "htmlID", names[i])) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsMatch(field, "htmlName", names[i])) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsMatch(field, "label-left", names[i])) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsMatch(field, "label-right", names[i])) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsMatch(field, "label-tag", names[i])) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsMatch(field, "label-aria", names[i])) {
|
||
return i;
|
||
}
|
||
if (this.fieldPropertyIsMatch(field, "placeholder", names[i])) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
/**
|
||
* Accepts a field, property, name, and prefix and returns true if the field
|
||
* contains a value that matches the given prefixed property.
|
||
* @param field
|
||
* @param {string} property
|
||
* @param {string} name
|
||
* @param {string} prefix
|
||
* @param {string} separator
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
fieldPropertyIsPrefixMatch(field, property, name, prefix, separator = "=") {
|
||
if (name.indexOf(prefix + separator) === 0) {
|
||
const sepIndex = name.indexOf(separator);
|
||
const val = name.substring(sepIndex + 1);
|
||
return val != null && this.fieldPropertyIsMatch(field, property, val);
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Identifies if a given property within a field matches the value
|
||
* of the passed "name" parameter. If the name starts with "regex=",
|
||
* the value is tested against a case-insensitive regular expression.
|
||
* If the name starts with "csv=", the value is treated as a
|
||
* comma-separated list of values to match.
|
||
* @param field
|
||
* @param {string} property
|
||
* @param {string} name
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
fieldPropertyIsMatch(field, property, name) {
|
||
let fieldVal = field[property];
|
||
if (!autofill_service_AutofillService.hasValue(fieldVal)) {
|
||
return false;
|
||
}
|
||
fieldVal = fieldVal.trim().replace(/(?:\r\n|\r|\n)/g, "");
|
||
if (name.startsWith("regex=")) {
|
||
try {
|
||
const regexParts = name.split("=", 2);
|
||
if (regexParts.length === 2) {
|
||
const regex = new RegExp(regexParts[1], "i");
|
||
return regex.test(fieldVal);
|
||
}
|
||
}
|
||
catch (e) {
|
||
this.logService.error(e);
|
||
}
|
||
}
|
||
else if (name.startsWith("csv=")) {
|
||
const csvParts = name.split("=", 2);
|
||
if (csvParts.length === 2) {
|
||
const csvVals = csvParts[1].split(",");
|
||
for (let i = 0; i < csvVals.length; i++) {
|
||
const val = csvVals[i];
|
||
if (val != null && val.trim().toLowerCase() === fieldVal.toLowerCase()) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
return fieldVal.toLowerCase() === name;
|
||
}
|
||
static fieldIsFuzzyMatch(field, names, showMatch = false) {
|
||
const attrs = [
|
||
"htmlID",
|
||
"htmlName",
|
||
"label-tag",
|
||
"placeholder",
|
||
"label-left",
|
||
"label-right",
|
||
"label-top",
|
||
"label-aria",
|
||
"dataSetValues",
|
||
];
|
||
for (const attr of attrs) {
|
||
const value = field[attr];
|
||
if (!autofill_service_AutofillService.hasValue(value)) {
|
||
continue;
|
||
}
|
||
if (autofill_service_AutofillService.fuzzyMatch(names, value)) {
|
||
return showMatch ? [true, { attr, value }] : true;
|
||
}
|
||
}
|
||
return showMatch ? [false] : false;
|
||
}
|
||
/**
|
||
* Accepts a list of options and a value and returns
|
||
* true if the value matches any of the options.
|
||
* @param {string[]} options
|
||
* @param {string} value
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
static fuzzyMatch(options, value) {
|
||
if (options == null ||
|
||
options.length === 0 ||
|
||
value == null ||
|
||
typeof value !== "string" ||
|
||
value.length < 1) {
|
||
return false;
|
||
}
|
||
value = value
|
||
.replace(/(?:\r\n|\r|\n)/g, "")
|
||
.trim()
|
||
.toLowerCase();
|
||
for (let i = 0; i < options.length; i++) {
|
||
if (value.indexOf(options[i]) > -1) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Accepts a string and returns true if the
|
||
* string is not falsy and not empty.
|
||
* @param {string} str
|
||
* @returns {boolean}
|
||
*/
|
||
static hasValue(str) {
|
||
return Boolean(str && str !== "");
|
||
}
|
||
/**
|
||
* Sets the `focus_by_opid` autofill script
|
||
* action to the last field that was filled.
|
||
* @param {{[p: string]: AutofillField}} filledFields
|
||
* @param {AutofillScript} fillScript
|
||
* @returns {AutofillScript}
|
||
*/
|
||
static setFillScriptForFocus(filledFields, fillScript) {
|
||
let lastField = null;
|
||
let lastPasswordField = null;
|
||
for (const opid in filledFields) {
|
||
// eslint-disable-next-line
|
||
if (filledFields.hasOwnProperty(opid) && filledFields[opid].viewable) {
|
||
lastField = filledFields[opid];
|
||
if (filledFields[opid].type === "password") {
|
||
lastPasswordField = filledFields[opid];
|
||
}
|
||
}
|
||
}
|
||
// Prioritize password field over others.
|
||
if (lastPasswordField) {
|
||
fillScript.script.push(["focus_by_opid", lastPasswordField.opid]);
|
||
}
|
||
else if (lastField) {
|
||
fillScript.script.push(["focus_by_opid", lastField.opid]);
|
||
}
|
||
return fillScript;
|
||
}
|
||
/**
|
||
* Updates a fill script to place the `click_on_opid`, `focus_on_opid`, and `fill_by_opid`
|
||
* fill script actions associated with the provided field.
|
||
* @param {AutofillScript} fillScript
|
||
* @param {AutofillField} field
|
||
* @param {string} value
|
||
*/
|
||
static fillByOpid(fillScript, field, value) {
|
||
if (field.maxLength && value && value.length > field.maxLength) {
|
||
value = value.substr(0, value.length);
|
||
}
|
||
if (field.tagName !== "span") {
|
||
fillScript.script.push(["click_on_opid", field.opid]);
|
||
fillScript.script.push(["focus_by_opid", field.opid]);
|
||
}
|
||
fillScript.script.push(["fill_by_opid", field.opid, value]);
|
||
}
|
||
/**
|
||
* Identifies if the field is a custom field, a custom
|
||
* field is defined as a field that is a `span` element.
|
||
* @param {AutofillField} field
|
||
* @returns {boolean}
|
||
*/
|
||
static forCustomFieldsOnly(field) {
|
||
return field.tagName === "span";
|
||
}
|
||
/**
|
||
* Handles debouncing the opening of the master password reprompt popout.
|
||
*/
|
||
isDebouncingPasswordRepromptPopout() {
|
||
if (this.currentlyOpeningPasswordRepromptPopout) {
|
||
return true;
|
||
}
|
||
this.currentlyOpeningPasswordRepromptPopout = true;
|
||
clearTimeout(this.openPasswordRepromptPopoutDebounce);
|
||
this.openPasswordRepromptPopoutDebounce = setTimeout(() => {
|
||
this.currentlyOpeningPasswordRepromptPopout = false;
|
||
}, 100);
|
||
return false;
|
||
}
|
||
/**
|
||
* Queries all open tabs in the user's browsing session
|
||
* and injects the autofill scripts into the page.
|
||
*/
|
||
injectAutofillScriptsInAllTabs() {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
const tabs = yield browser_api_BrowserApi.tabsQuery({});
|
||
for (let index = 0; index < tabs.length; index++) {
|
||
const tab = tabs[index];
|
||
if ((tab === null || tab === void 0 ? void 0 : tab.id) && ((_a = tab.url) === null || _a === void 0 ? void 0 : _a.startsWith("http"))) {
|
||
const frames = yield browser_api_BrowserApi.getAllFrameDetails(tab.id);
|
||
if (frames) {
|
||
frames.forEach((frame) => this.injectAutofillScripts(tab, frame.frameId, false));
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Updates the autofill inline menu visibility settings in all active tabs
|
||
* when the inlineMenuVisibility, showInlineMenuCards, or showInlineMenuIdentities
|
||
* observables are updated.
|
||
*
|
||
* @param oldSettingValue - The previous setting value
|
||
* @param newSettingValue - The current setting value
|
||
*/
|
||
handleInlineMenuVisibilitySettingsChange(oldSettingValue, newSettingValue) {
|
||
return autofill_service_awaiter(this, void 0, void 0, function* () {
|
||
if (oldSettingValue == null || oldSettingValue === newSettingValue) {
|
||
return;
|
||
}
|
||
const isInlineMenuVisibilitySubSetting = typeof oldSettingValue === "boolean" || typeof newSettingValue === "boolean";
|
||
const inlineMenuPreviouslyDisabled = oldSettingValue === AutofillOverlayVisibility.Off;
|
||
const inlineMenuCurrentlyDisabled = newSettingValue === AutofillOverlayVisibility.Off;
|
||
if (!isInlineMenuVisibilitySubSetting &&
|
||
!inlineMenuPreviouslyDisabled &&
|
||
!inlineMenuCurrentlyDisabled) {
|
||
return;
|
||
}
|
||
yield this.reloadAutofillScripts();
|
||
});
|
||
}
|
||
}
|
||
autofill_service_AutofillService.searchFieldNamesSet = new Set(AutoFillConstants.SearchFieldNames);
|
||
/* harmony default export */ var autofill_service = (autofill_service_AutofillService);
|
||
|
||
;// ./src/autofill/services/inline-menu-field-qualification.service.ts
|
||
|
||
|
||
|
||
class InlineMenuFieldQualificationService {
|
||
/**
|
||
* Validates the provided field to indicate if the field is a new email field used for account creation/registration.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
isExplicitIdentityEmailField(field) {
|
||
const matchFieldAttributeValues = [field.type, field.htmlName, field.htmlID, field.placeholder];
|
||
for (let attrIndex = 0; attrIndex < matchFieldAttributeValues.length; attrIndex++) {
|
||
const attributeValueToMatch = matchFieldAttributeValues[attrIndex];
|
||
if (!attributeValueToMatch) {
|
||
continue;
|
||
}
|
||
for (let keywordIndex = 0; keywordIndex < matchFieldAttributeValues.length; keywordIndex++) {
|
||
if (this.newEmailFieldKeywords.has(attributeValueToMatch)) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Validates the provided form to indicate if the form is related to newsletter registration.
|
||
*
|
||
* @param parentForm - The form to validate
|
||
*/
|
||
isNewsletterForm(parentForm) {
|
||
if (!parentForm) {
|
||
return false;
|
||
}
|
||
const matchFieldAttributeValues = [
|
||
parentForm.type,
|
||
parentForm.htmlName,
|
||
parentForm.htmlID,
|
||
parentForm.placeholder,
|
||
];
|
||
for (let attrIndex = 0; attrIndex < matchFieldAttributeValues.length; attrIndex++) {
|
||
const attrValue = matchFieldAttributeValues[attrIndex];
|
||
if (!attrValue || typeof attrValue !== "string") {
|
||
continue;
|
||
}
|
||
const attrValueLower = attrValue.toLowerCase();
|
||
for (const keyword of this.newsletterFormKeywords) {
|
||
if (attrValueLower.includes(keyword.toLowerCase())) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
constructor() {
|
||
this.searchFieldNamesSet = new Set(AutoFillConstants.SearchFieldNames);
|
||
this.excludedAutofillFieldTypesSet = new Set(AutoFillConstants.ExcludedAutofillLoginTypes);
|
||
this.usernameFieldTypes = new Set(["text", "email", "number", "tel"]);
|
||
this.usernameAutocompleteValue = "username";
|
||
this.emailAutocompleteValue = "email";
|
||
this.webAuthnAutocompleteValue = "webauthn";
|
||
this.loginUsernameAutocompleteValues = new Set([
|
||
this.usernameAutocompleteValue,
|
||
this.emailAutocompleteValue,
|
||
this.webAuthnAutocompleteValue,
|
||
]);
|
||
this.fieldIgnoreListString = AutoFillConstants.FieldIgnoreList.join(",");
|
||
this.currentPasswordAutocompleteValue = "current-password";
|
||
this.newPasswordAutoCompleteValue = "new-password";
|
||
this.autofillFieldKeywordsMap = new WeakMap();
|
||
this.submitButtonKeywordsMap = new WeakMap();
|
||
this.accountCreationFieldKeywords = [
|
||
"register",
|
||
"registration",
|
||
"create password",
|
||
"create a password",
|
||
"create an account",
|
||
"create account password",
|
||
"create user password",
|
||
"confirm password",
|
||
"confirm account password",
|
||
"confirm user password",
|
||
"new user",
|
||
"new email",
|
||
"new e-mail",
|
||
"new password",
|
||
"new-password",
|
||
"neuer benutzer",
|
||
"neues passwort",
|
||
"neue e-mail",
|
||
"pwdcheck",
|
||
];
|
||
this.newEmailFieldKeywords = new Set(AutoFillConstants.NewEmailFieldKeywords);
|
||
this.newsletterFormKeywords = new Set(AutoFillConstants.NewsletterFormNames);
|
||
this.updatePasswordFieldKeywords = [
|
||
"update password",
|
||
"change password",
|
||
"current password",
|
||
"kennwort ändern",
|
||
];
|
||
this.creditCardFieldKeywords = [
|
||
...new Set([
|
||
...CreditCardAutoFillConstants.CardHolderFieldNames,
|
||
...CreditCardAutoFillConstants.CardNumberFieldNames,
|
||
...CreditCardAutoFillConstants.CardExpiryFieldNames,
|
||
...CreditCardAutoFillConstants.ExpiryMonthFieldNames,
|
||
...CreditCardAutoFillConstants.ExpiryYearFieldNames,
|
||
...CreditCardAutoFillConstants.CVVFieldNames,
|
||
...CreditCardAutoFillConstants.CardBrandFieldNames,
|
||
]),
|
||
];
|
||
this.creditCardNameAutocompleteValues = new Set([
|
||
"cc-name",
|
||
"cc-given-name,",
|
||
"cc-additional-name",
|
||
"cc-family-name",
|
||
]);
|
||
this.creditCardExpirationDateAutocompleteValue = "cc-exp";
|
||
this.creditCardExpirationMonthAutocompleteValue = "cc-exp-month";
|
||
this.creditCardExpirationYearAutocompleteValue = "cc-exp-year";
|
||
this.creditCardCvvAutocompleteValue = "cc-csc";
|
||
this.creditCardNumberAutocompleteValue = "cc-number";
|
||
this.creditCardTypeAutocompleteValue = "cc-type";
|
||
this.creditCardAutocompleteValues = new Set([
|
||
...this.creditCardNameAutocompleteValues,
|
||
this.creditCardExpirationDateAutocompleteValue,
|
||
this.creditCardExpirationMonthAutocompleteValue,
|
||
this.creditCardExpirationYearAutocompleteValue,
|
||
this.creditCardNumberAutocompleteValue,
|
||
this.creditCardCvvAutocompleteValue,
|
||
this.creditCardTypeAutocompleteValue,
|
||
]);
|
||
this.identityHonorificPrefixAutocompleteValue = "honorific-prefix";
|
||
this.identityFullNameAutocompleteValue = "name";
|
||
this.identityFirstNameAutocompleteValue = "given-name";
|
||
this.identityMiddleNameAutocompleteValue = "additional-name";
|
||
this.identityLastNameAutocompleteValue = "family-name";
|
||
this.identityNameAutocompleteValues = new Set([
|
||
this.identityFullNameAutocompleteValue,
|
||
this.identityHonorificPrefixAutocompleteValue,
|
||
this.identityFirstNameAutocompleteValue,
|
||
this.identityMiddleNameAutocompleteValue,
|
||
this.identityLastNameAutocompleteValue,
|
||
"honorific-suffix",
|
||
"nickname",
|
||
]);
|
||
this.identityCompanyAutocompleteValue = "organization";
|
||
this.identityStreetAddressAutocompleteValue = "street-address";
|
||
this.identityAddressLine1AutocompleteValue = "address-line1";
|
||
this.identityAddressLine2AutocompleteValue = "address-line2";
|
||
this.identityAddressLine3AutocompleteValue = "address-line3";
|
||
this.identityAddressCityAutocompleteValue = "address-level2";
|
||
this.identityAddressStateAutocompleteValue = "address-level1";
|
||
this.identityAddressAutoCompleteValues = new Set([
|
||
this.identityStreetAddressAutocompleteValue,
|
||
this.identityAddressLine1AutocompleteValue,
|
||
this.identityAddressLine2AutocompleteValue,
|
||
this.identityAddressLine3AutocompleteValue,
|
||
this.identityAddressCityAutocompleteValue,
|
||
this.identityAddressStateAutocompleteValue,
|
||
"shipping",
|
||
"billing",
|
||
"address-level4",
|
||
"address-level3",
|
||
]);
|
||
this.identityCountryAutocompleteValues = new Set(["country", "country-name"]);
|
||
this.identityPostalCodeAutocompleteValue = "postal-code";
|
||
this.identityPhoneAutocompleteValue = "tel";
|
||
this.identityPhoneNumberAutocompleteValues = new Set([
|
||
this.identityPhoneAutocompleteValue,
|
||
"tel-country-code",
|
||
"tel-area-code",
|
||
"tel-local",
|
||
"tel-extension",
|
||
]);
|
||
this.identityAutocompleteValues = new Set([
|
||
...this.identityNameAutocompleteValues,
|
||
...this.loginUsernameAutocompleteValues,
|
||
...this.identityCompanyAutocompleteValue,
|
||
...this.identityAddressAutoCompleteValues,
|
||
...this.identityCountryAutocompleteValues,
|
||
...this.identityPhoneNumberAutocompleteValues,
|
||
this.identityCompanyAutocompleteValue,
|
||
this.identityPostalCodeAutocompleteValue,
|
||
]);
|
||
this.totpFieldAutocompleteValue = "one-time-code";
|
||
this.premiumEnabled = false;
|
||
/**
|
||
* Validates the provided field as a credit card name field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForCardholderName = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.creditCardNameAutocompleteValues)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, CreditCardAutoFillConstants.CardHolderFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as a credit card number field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForCardNumber = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.creditCardNumberAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, CreditCardAutoFillConstants.CardNumberFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as a credit card expiration date field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForCardExpirationDate = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.creditCardExpirationDateAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, CreditCardAutoFillConstants.CardExpiryFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as a credit card expiration month field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForCardExpirationMonth = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.creditCardExpirationMonthAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, CreditCardAutoFillConstants.ExpiryMonthFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as a credit card expiration year field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForCardExpirationYear = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.creditCardExpirationYearAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, CreditCardAutoFillConstants.ExpiryYearFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as a credit card CVV field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForCardCvv = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.creditCardCvvAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, CreditCardAutoFillConstants.CVVFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity title type field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityTitle = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityHonorificPrefixAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.TitleFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity full name field.
|
||
*
|
||
* @param field
|
||
*/
|
||
this.isFieldForIdentityFirstName = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityFirstNameAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.FirstnameFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity middle name field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityMiddleName = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityMiddleNameAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.MiddlenameFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity last name field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityLastName = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityLastNameAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.LastnameFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity full name field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityFullName = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityFullNameAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.FullNameFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity address field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityAddress1 = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityAddressLine1AutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, [
|
||
...IdentityAutoFillConstants.AddressFieldNames,
|
||
...IdentityAutoFillConstants.Address1FieldNames,
|
||
], false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity address field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityAddress2 = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityAddressLine2AutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.Address2FieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity address field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityAddress3 = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityAddressLine3AutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.Address3FieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity city field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityCity = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityAddressCityAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.CityFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity state field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityState = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityAddressStateAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.StateFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity postal code field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityPostalCode = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityPostalCodeAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.PostalCodeFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity country field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityCountry = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityCountryAutocompleteValues)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.CountryFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity company field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityCompany = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityCompanyAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.CompanyFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity phone field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityPhone = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.identityPhoneAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.PhoneFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity email field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityEmail = (field) => {
|
||
if (this.isExplicitIdentityEmailField(field)) {
|
||
return true;
|
||
}
|
||
if (this.fieldContainsAutocompleteValues(field, this.emailAutocompleteValue) ||
|
||
field.type === "email" ||
|
||
field.htmlName === "email") {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.EmailFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as an identity username field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isFieldForIdentityUsername = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.usernameAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, IdentityAutoFillConstants.UserNameFieldNames, false);
|
||
};
|
||
/**
|
||
* Validates the provided field as a username field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isUsernameField = (field) => {
|
||
const fieldType = field.type;
|
||
if (!fieldType ||
|
||
!this.usernameFieldTypes.has(fieldType) ||
|
||
this.isExcludedFieldType(field, this.excludedAutofillFieldTypesSet) ||
|
||
this.fieldHasDisqualifyingAttributeValue(field) ||
|
||
this.isTotpField(field)) {
|
||
return false;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, AutoFillConstants.UsernameFieldNames);
|
||
};
|
||
/**
|
||
* Validates the provided field as an email field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isEmailField = (field) => {
|
||
if (field.type === "email") {
|
||
return true;
|
||
}
|
||
return (!this.isExcludedFieldType(field, this.excludedAutofillFieldTypesSet) &&
|
||
this.keywordsFoundInFieldData(field, AutoFillConstants.EmailFieldNames));
|
||
};
|
||
/**
|
||
* Validates the provided field as a current password field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isCurrentPasswordField = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.newPasswordAutoCompleteValue) ||
|
||
this.keywordsFoundInFieldData(field, this.accountCreationFieldKeywords)) {
|
||
return false;
|
||
}
|
||
return this.isPasswordField(field);
|
||
};
|
||
/**
|
||
* Validates the provided field as a current password field for an update password form.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isUpdateCurrentPasswordField = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.newPasswordAutoCompleteValue)) {
|
||
return false;
|
||
}
|
||
return (this.isPasswordField(field) &&
|
||
this.keywordsFoundInFieldData(field, this.updatePasswordFieldKeywords));
|
||
};
|
||
/**
|
||
* Validates the provided field as a new password field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isNewPasswordField = (field) => {
|
||
if (this.fieldContainsAutocompleteValues(field, this.currentPasswordAutocompleteValue)) {
|
||
return false;
|
||
}
|
||
return (this.isPasswordField(field) &&
|
||
this.keywordsFoundInFieldData(field, this.accountCreationFieldKeywords));
|
||
};
|
||
/**
|
||
* Validates the provided field as a password field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isPasswordField = (field) => {
|
||
const isInputPasswordType = field.type === "password";
|
||
if ((!isInputPasswordType &&
|
||
this.isExcludedFieldType(field, this.excludedAutofillFieldTypesSet)) ||
|
||
this.fieldHasDisqualifyingAttributeValue(field) ||
|
||
this.isTotpField(field)) {
|
||
return false;
|
||
}
|
||
return isInputPasswordType || this.isLikePasswordField(field);
|
||
};
|
||
/**
|
||
* Validates whether the provided field is a TOTP field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
this.isTotpField = (field) => {
|
||
if (autofill_service.fieldIsFuzzyMatch(field, [...AutoFillConstants.RecoveryCodeFieldNames])) {
|
||
return false;
|
||
}
|
||
if (this.fieldContainsAutocompleteValues(field, this.totpFieldAutocompleteValue)) {
|
||
return true;
|
||
}
|
||
return (!this.isExcludedFieldType(field, this.excludedAutofillFieldTypesSet) &&
|
||
this.keywordsFoundInFieldData(field, AutoFillConstants.TotpFieldNames));
|
||
};
|
||
/**
|
||
* Validates the provided field to indicate if the field is a submit button for a login form.
|
||
*
|
||
* @param element - The element to validate
|
||
*/
|
||
this.isElementLoginSubmitButton = (element) => {
|
||
const keywordValues = this.getSubmitButtonKeywords(element);
|
||
return SubmitLoginButtonNames.some((keyword) => keywordValues.indexOf(keyword) > -1);
|
||
};
|
||
/**
|
||
* Validates the provided field to indicate if the field is a submit button for a change password form.
|
||
*
|
||
* @param element - The element to validate
|
||
*/
|
||
this.isElementChangePasswordSubmitButton = (element) => {
|
||
const keywordValues = this.getSubmitButtonKeywords(element);
|
||
return SubmitChangePasswordButtonNames.some((keyword) => keywordValues.indexOf(keyword) > -1);
|
||
};
|
||
void sendExtensionMessage("getUserPremiumStatus").then((premiumStatus) => {
|
||
this.premiumEnabled = !!(premiumStatus === null || premiumStatus === void 0 ? void 0 : premiumStatus.result);
|
||
});
|
||
}
|
||
/**
|
||
* Validates the provided field as a field for a login form.
|
||
*
|
||
* @param field - The field to validate, should be a username or password field.
|
||
* @param pageDetails - The details of the page that the field is on.
|
||
*/
|
||
isFieldForLoginForm(field, pageDetails) {
|
||
/**
|
||
* Totp inline menu is available only for premium users.
|
||
*/
|
||
if (this.premiumEnabled) {
|
||
const isTotpField = this.isTotpField(field);
|
||
// Autofill does not fill totp inputs with a "password" `type` attribute value
|
||
const passwordType = field.type === "password";
|
||
if (isTotpField && !passwordType) {
|
||
return true;
|
||
}
|
||
}
|
||
const isCurrentPasswordField = this.isCurrentPasswordField(field);
|
||
if (isCurrentPasswordField) {
|
||
return this.isPasswordFieldForLoginForm(field, pageDetails);
|
||
}
|
||
const isUsernameField = this.isUsernameField(field);
|
||
if (!isUsernameField) {
|
||
return false;
|
||
}
|
||
return this.isUsernameFieldForLoginForm(field, pageDetails);
|
||
}
|
||
/**
|
||
* Validates the provided field as a field for a credit card form.
|
||
*
|
||
* @param field - The field to validate
|
||
* @param pageDetails - The details of the page that the field is on.
|
||
*/
|
||
isFieldForCreditCardForm(field, pageDetails) {
|
||
// If the field contains any of the standardized autocomplete attribute values
|
||
// for credit card fields, we should assume that the field is part of a credit card form.
|
||
if (this.fieldContainsAutocompleteValues(field, this.creditCardAutocompleteValues)) {
|
||
return true;
|
||
}
|
||
let parentForm;
|
||
const fieldForm = field.form;
|
||
if (fieldForm) {
|
||
parentForm = pageDetails.forms[fieldForm];
|
||
}
|
||
// If the field does not have a parent form
|
||
if (!parentForm) {
|
||
// If a credit card number field is not present on the page or there are multiple credit
|
||
// card number fields, this field is not part of a credit card form.
|
||
const numberFieldsInPageDetails = pageDetails.fields.filter(this.isFieldForCardNumber);
|
||
if (numberFieldsInPageDetails.length !== 1) {
|
||
return false;
|
||
}
|
||
// If a credit card CVV field is not present on the page or there are multiple credit card
|
||
// CVV fields, this field is not part of a credit card form.
|
||
const cvvFieldsInPageDetails = pageDetails.fields.filter(this.isFieldForCardCvv);
|
||
if (cvvFieldsInPageDetails.length !== 1) {
|
||
return false;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, this.creditCardFieldKeywords);
|
||
}
|
||
// If the field has a parent form, check the fields from that form exclusively
|
||
const fieldsFromSameForm = pageDetails.fields.filter((f) => f.form === field.form);
|
||
// If a credit card number field is not present on the page or there are multiple credit
|
||
// card number fields, this field is not part of a credit card form.
|
||
const numberFieldsInPageDetails = fieldsFromSameForm.filter(this.isFieldForCardNumber);
|
||
if (numberFieldsInPageDetails.length !== 1) {
|
||
return false;
|
||
}
|
||
// If a credit card CVV field is not present on the page or there are multiple credit card
|
||
// CVV fields, this field is not part of a credit card form.
|
||
const cvvFieldsInPageDetails = fieldsFromSameForm.filter(this.isFieldForCardCvv);
|
||
if (cvvFieldsInPageDetails.length !== 1) {
|
||
return false;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, [...this.creditCardFieldKeywords]);
|
||
}
|
||
/** Validates the provided field as a field for an account creation form.
|
||
*
|
||
* @param field - The field to validate
|
||
* @param pageDetails - The details of the page that the field is on.
|
||
*/
|
||
isFieldForAccountCreationForm(field, pageDetails) {
|
||
if (this.isExcludedFieldType(field, this.excludedAutofillFieldTypesSet) ||
|
||
this.isTotpField(field)) {
|
||
return false;
|
||
}
|
||
if (!this.isUsernameField(field) && !this.isPasswordField(field)) {
|
||
return false;
|
||
}
|
||
let parentForm;
|
||
const fieldForm = field.form;
|
||
if (fieldForm) {
|
||
parentForm = pageDetails.forms[fieldForm];
|
||
}
|
||
if (!parentForm) {
|
||
// If the field does not have a parent form, but we can identify that the page contains at least
|
||
// one new password field, we should assume that the field is part of an account creation form.
|
||
const newPasswordFields = pageDetails.fields.filter(this.isNewPasswordField);
|
||
if (newPasswordFields.length >= 1) {
|
||
return true;
|
||
}
|
||
// If no password fields are found on the page, check for keywords that indicate the field is
|
||
// part of an account creation form.
|
||
return this.keywordsFoundInFieldData(field, this.accountCreationFieldKeywords);
|
||
}
|
||
// If the field has a parent form, check the fields from that form exclusively
|
||
const fieldsFromSameForm = pageDetails.fields.filter((f) => f.form === field.form);
|
||
const newPasswordFields = fieldsFromSameForm.filter(this.isNewPasswordField);
|
||
if (newPasswordFields.length >= 1) {
|
||
return true;
|
||
}
|
||
return this.keywordsFoundInFieldData(field, this.accountCreationFieldKeywords);
|
||
}
|
||
/**
|
||
* Validates the provided field as a field for an identity form.
|
||
*
|
||
* @param field - The field to validate
|
||
* @param _pageDetails - Currently unused, will likely be required in the future
|
||
*/
|
||
isFieldForIdentityForm(field, _pageDetails) {
|
||
if (this.isExcludedFieldType(field, this.excludedAutofillFieldTypesSet)) {
|
||
return false;
|
||
}
|
||
return (
|
||
// Recognize explicit identity email fields (like id="new-email")
|
||
this.isFieldForIdentityEmail(field) ||
|
||
this.fieldContainsAutocompleteValues(field, this.identityAutocompleteValues));
|
||
}
|
||
/**
|
||
* Validates the provided field as a password field for a login form.
|
||
*
|
||
* @param field - The field to validate
|
||
* @param pageDetails - The details of the page that the field is on.
|
||
*/
|
||
isPasswordFieldForLoginForm(field, pageDetails) {
|
||
let parentForm;
|
||
const fieldForm = field.form;
|
||
if (fieldForm) {
|
||
parentForm = pageDetails.forms[fieldForm];
|
||
}
|
||
// If the provided field is set with an autocomplete value of "current-password", we should assume that
|
||
// the page developer intends for this field to be interpreted as a password field for a login form.
|
||
if (this.fieldContainsAutocompleteValues(field, this.currentPasswordAutocompleteValue)) {
|
||
if (!parentForm) {
|
||
return (pageDetails.fields.filter(this.isNewPasswordField).filter((f) => f.viewable).length === 0);
|
||
}
|
||
return (pageDetails.fields
|
||
.filter(this.isNewPasswordField)
|
||
.filter((f) => f.viewable && f.form === field.form).length === 0);
|
||
}
|
||
const usernameFieldsInPageDetails = pageDetails.fields.filter(this.isUsernameField);
|
||
const passwordFieldsInPageDetails = pageDetails.fields.filter(this.isCurrentPasswordField);
|
||
// If a single username and a single password field exists on the page, we
|
||
// should assume that this field is part of a login form.
|
||
if (usernameFieldsInPageDetails.length === 1 && passwordFieldsInPageDetails.length === 1) {
|
||
return true;
|
||
}
|
||
// If the field is not structured within a form, we need to identify if the field is present on
|
||
// a page with multiple password fields. If that isn't the case, we can assume this is a login form field.
|
||
if (!parentForm) {
|
||
// If no parent form is found, and multiple password fields are present, we should assume that
|
||
// the passed field belongs to a user account creation form.
|
||
if (passwordFieldsInPageDetails.length > 1) {
|
||
return false;
|
||
}
|
||
// If multiple username fields exist on the page, we should assume that
|
||
// the provided field is part of an account creation form.
|
||
const visibleUsernameFields = usernameFieldsInPageDetails.filter((f) => f.viewable);
|
||
if (visibleUsernameFields.length > 1) {
|
||
return false;
|
||
}
|
||
// If a single username field or less is present on the page, then we can assume that the
|
||
// provided field is for a login form.
|
||
return true;
|
||
}
|
||
// If the field has a form parent and there are multiple visible password fields
|
||
// in the form, this is not a login form field
|
||
const visiblePasswordFieldsInPageDetails = passwordFieldsInPageDetails.filter((f) => f.form === field.form && f.viewable);
|
||
if (visiblePasswordFieldsInPageDetails.length > 1) {
|
||
return false;
|
||
}
|
||
// If the form has any visible username fields, we should treat the field as part of a login form
|
||
const visibleUsernameFields = usernameFieldsInPageDetails.filter((f) => f.form === field.form && f.viewable);
|
||
if (visibleUsernameFields.length > 0) {
|
||
return true;
|
||
}
|
||
// If the field has a form parent and a username field exists this is a password field
|
||
return true;
|
||
}
|
||
/**
|
||
* Validates the provided field as a username field for a login form.
|
||
*
|
||
* @param field - The field to validate
|
||
* @param pageDetails - The details of the page that the field is on.
|
||
*/
|
||
isUsernameFieldForLoginForm(field, pageDetails) {
|
||
// If the provided field is set with an autocomplete of "username", we should assume that
|
||
// the page developer intends for this field to be interpreted as a username field.
|
||
// Exclude non-login email field from being treated as a login username field
|
||
if (this.isExplicitIdentityEmailField(field)) {
|
||
return false;
|
||
}
|
||
if (this.fieldContainsAutocompleteValues(field, this.loginUsernameAutocompleteValues)) {
|
||
const newPasswordFieldsInPageDetails = pageDetails.fields.filter((field) => field.viewable && this.isNewPasswordField(field));
|
||
return newPasswordFieldsInPageDetails.length === 0;
|
||
}
|
||
// If any keywords in the field's data indicates that this is a field for a "new" or "changed"
|
||
// username, we should assume that this field is not for a login form.
|
||
if (this.keywordsFoundInFieldData(field, this.accountCreationFieldKeywords)) {
|
||
return false;
|
||
}
|
||
// If the field is not explicitly set as a username field, we need to qualify
|
||
// the field based on the other fields that are present on the page.
|
||
let parentForm;
|
||
const fieldForm = field.form;
|
||
if (fieldForm) {
|
||
parentForm = pageDetails.forms[fieldForm];
|
||
}
|
||
const passwordFieldsInPageDetails = pageDetails.fields.filter(this.isCurrentPasswordField);
|
||
if (this.isNewsletterForm(parentForm)) {
|
||
return false;
|
||
}
|
||
// If the field is not structured within a form, we need to identify if the field is used in conjunction
|
||
// with a password field. If that's the case, then we should assume that it is a form field element.
|
||
if (!parentForm) {
|
||
// If a formless field is present in a webpage with a single password field, we
|
||
// should assume that it is part of a login workflow.
|
||
const visiblePasswordFieldsInPageDetails = passwordFieldsInPageDetails.filter((passwordField) => passwordField.viewable);
|
||
if (visiblePasswordFieldsInPageDetails.length === 1) {
|
||
return true;
|
||
}
|
||
// If more than a single password field exists on the page, we should assume that the field
|
||
// is part of an account creation form.
|
||
if (visiblePasswordFieldsInPageDetails.length > 1) {
|
||
return false;
|
||
}
|
||
// If no visible fields are found on the page, but we have a single password
|
||
// field we should assume that the field is part of a login form.
|
||
if (passwordFieldsInPageDetails.length === 1) {
|
||
return true;
|
||
}
|
||
// If the page does not contain any password fields, it might be part of a multistep login form.
|
||
return true;
|
||
}
|
||
// If the field is structured within a form, but no password fields are present in the form,
|
||
// we need to consider whether the field is part of a multistep login form.
|
||
if (passwordFieldsInPageDetails.length === 0) {
|
||
// If the form that contains a single field, we should assume that it is part
|
||
// of a multistep login form.
|
||
const fieldsWithinForm = pageDetails.fields.filter((pageDetailsField) => pageDetailsField.form === field.form);
|
||
if (fieldsWithinForm.length === 1) {
|
||
return true;
|
||
}
|
||
// If multiple fields exist within the form, we should check if a single visible field exists.
|
||
// If so, we should assume that the field is part of a login form.
|
||
return fieldsWithinForm.filter((field) => field.viewable).length === 1;
|
||
}
|
||
// If a single password field exists within the page details, and that password field is part of
|
||
// the same form as the provided field, we should assume that the field is part of a login form.
|
||
const visiblePasswordFieldsInPageDetails = passwordFieldsInPageDetails.filter((passwordField) => passwordField.form === field.form && passwordField.viewable);
|
||
if (visiblePasswordFieldsInPageDetails.length === 1) {
|
||
return true;
|
||
}
|
||
// If multiple visible password fields exist within the page details, we need to assume that the
|
||
// provided field is part of an account creation form.
|
||
if (visiblePasswordFieldsInPageDetails.length > 1) {
|
||
return false;
|
||
}
|
||
// If we have a single password field we should assume that the field is part of a login form.
|
||
if (passwordFieldsInPageDetails.length === 1) {
|
||
return true;
|
||
}
|
||
// If no visible password fields are found, this field might be part of a multipart form.
|
||
return true;
|
||
}
|
||
/**
|
||
* Validates the provided field as a field to indicate if the
|
||
* field potentially acts as a password field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
isLikePasswordField(field) {
|
||
if (field.type !== "text") {
|
||
return false;
|
||
}
|
||
const testedValues = [field.htmlID, field.htmlName, field.placeholder];
|
||
for (let i = 0; i < testedValues.length; i++) {
|
||
const attributeValueToMatch = testedValues[i];
|
||
if (!attributeValueToMatch) {
|
||
continue;
|
||
}
|
||
if (this.valueIsLikePassword(attributeValueToMatch)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Validates the provided value to indicate if the value is like a password.
|
||
*
|
||
* @param value - The value to validate
|
||
*/
|
||
valueIsLikePassword(value) {
|
||
if (value == null) {
|
||
return false;
|
||
}
|
||
// Removes all whitespace, _ and - characters
|
||
const cleanedValue = value.toLowerCase().replace(/[\s_-]/g, "");
|
||
if (cleanedValue.indexOf("password") < 0) {
|
||
return false;
|
||
}
|
||
return !AutoFillConstants.PasswordFieldExcludeList.some((i) => cleanedValue.indexOf(i) > -1);
|
||
}
|
||
/**
|
||
* Validates the provided field to indicate if the field has a
|
||
* disqualifying attribute that would impede autofill entirely.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
fieldHasDisqualifyingAttributeValue(field) {
|
||
const checkedAttributeValues = [field.htmlID, field.htmlName, field.placeholder];
|
||
for (let i = 0; i < checkedAttributeValues.length; i++) {
|
||
const checkedAttributeValue = checkedAttributeValues[i];
|
||
const cleanedValue = checkedAttributeValue === null || checkedAttributeValue === void 0 ? void 0 : checkedAttributeValue.toLowerCase().replace(/[\s_-]/g, "");
|
||
if (cleanedValue && this.fieldIgnoreListString.indexOf(cleanedValue) > -1) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Validates the provided field to indicate if the field is excluded from autofill.
|
||
*
|
||
* @param field - The field to validate
|
||
* @param excludedTypes - The set of excluded types
|
||
*/
|
||
isExcludedFieldType(field, excludedTypes) {
|
||
const fieldType = field.type;
|
||
if (fieldType && excludedTypes.has(fieldType)) {
|
||
return true;
|
||
}
|
||
return this.isSearchField(field);
|
||
}
|
||
/**
|
||
* Validates the provided field to indicate if the field is a search field.
|
||
*
|
||
* @param field - The field to validate
|
||
*/
|
||
isSearchField(field) {
|
||
const matchFieldAttributeValues = [field.type, field.htmlName, field.htmlID, field.placeholder];
|
||
for (let attrIndex = 0; attrIndex < matchFieldAttributeValues.length; attrIndex++) {
|
||
const attributeValueToMatch = matchFieldAttributeValues[attrIndex];
|
||
if (!attributeValueToMatch) {
|
||
continue;
|
||
}
|
||
// Separate camel case words and case them to lower case values
|
||
const camelCaseSeparatedFieldAttribute = attributeValueToMatch
|
||
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
||
.toLowerCase();
|
||
// Split the attribute by non-alphabetical characters to get the keywords
|
||
const attributeKeywords = camelCaseSeparatedFieldAttribute.split(/[^a-z]/gi);
|
||
for (let keywordIndex = 0; keywordIndex < attributeKeywords.length; keywordIndex++) {
|
||
if (this.searchFieldNamesSet.has(attributeKeywords[keywordIndex])) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
/**
|
||
* Gather the keywords from the provided element to validate the submit button.
|
||
*
|
||
* @param element - The element to validate
|
||
*/
|
||
getSubmitButtonKeywords(element) {
|
||
if (!this.submitButtonKeywordsMap.has(element)) {
|
||
const keywordsSet = getSubmitButtonKeywordsSet(element);
|
||
this.submitButtonKeywordsMap.set(element, Array.from(keywordsSet).join(","));
|
||
}
|
||
return this.submitButtonKeywordsMap.get(element) || "";
|
||
}
|
||
/**
|
||
* Validates the provided field to indicate if the field has any of the provided keywords.
|
||
*
|
||
* @param autofillFieldData - The field data to search for keywords
|
||
* @param keywords - The keywords to search for
|
||
* @param fuzzyMatchKeywords - Indicates if the keywords should be matched in a fuzzy manner
|
||
*/
|
||
keywordsFoundInFieldData(autofillFieldData, keywords, fuzzyMatchKeywords = true) {
|
||
const searchedValues = this.getAutofillFieldDataKeywords(autofillFieldData, fuzzyMatchKeywords);
|
||
const parsedKeywords = keywords.map((keyword) => keyword.replace(/-/g, ""));
|
||
if (typeof searchedValues === "string") {
|
||
return parsedKeywords.some((keyword) => searchedValues.indexOf(keyword) > -1);
|
||
}
|
||
return parsedKeywords.some((keyword) => searchedValues.has(keyword));
|
||
}
|
||
/**
|
||
* Retrieves the keywords from the provided autofill field data.
|
||
*
|
||
* @param autofillFieldData - The field data to search for keywords
|
||
* @param returnStringValue - Indicates if the method should return a string value
|
||
*/
|
||
getAutofillFieldDataKeywords(autofillFieldData, returnStringValue) {
|
||
if (!this.autofillFieldKeywordsMap.has(autofillFieldData)) {
|
||
const keywords = [
|
||
autofillFieldData.htmlID,
|
||
autofillFieldData.htmlName,
|
||
autofillFieldData.htmlClass,
|
||
autofillFieldData.type,
|
||
autofillFieldData.title,
|
||
autofillFieldData.placeholder,
|
||
autofillFieldData.autoCompleteType,
|
||
autofillFieldData.dataSetValues,
|
||
autofillFieldData["label-data"],
|
||
autofillFieldData["label-aria"],
|
||
autofillFieldData["label-left"],
|
||
autofillFieldData["label-right"],
|
||
autofillFieldData["label-tag"],
|
||
autofillFieldData["label-top"],
|
||
];
|
||
const keywordsSet = new Set();
|
||
for (let i = 0; i < keywords.length; i++) {
|
||
const attributeValue = keywords[i];
|
||
if (attributeValue && typeof attributeValue === "string") {
|
||
let keywordEl = attributeValue.toLowerCase();
|
||
keywordsSet.add(keywordEl);
|
||
// Remove hyphens from all potential keywords, we want to treat these as a single word.
|
||
keywordEl = keywordEl.replace(/-/g, "");
|
||
// Split the keyword by non-alphanumeric characters to get the keywords without treating a space as a separator.
|
||
keywordEl.split(/[^\p{L}\d]+/gu).forEach((keyword) => {
|
||
if (keyword) {
|
||
keywordsSet.add(keyword);
|
||
}
|
||
});
|
||
// Collapse all spaces and split by non-alphanumeric characters to get the keywords
|
||
keywordEl
|
||
.replace(/\s/g, "")
|
||
.split(/[^\p{L}\d]+/gu)
|
||
.forEach((keyword) => {
|
||
if (keyword) {
|
||
keywordsSet.add(keyword);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
const stringValue = Array.from(keywordsSet).join(",");
|
||
this.autofillFieldKeywordsMap.set(autofillFieldData, { keywordsSet, stringValue });
|
||
}
|
||
const mapValues = this.autofillFieldKeywordsMap.get(autofillFieldData);
|
||
return mapValues ? (returnStringValue ? mapValues.stringValue : mapValues.keywordsSet) : "";
|
||
}
|
||
/**
|
||
* Separates the provided field data into space-separated values and checks if any
|
||
* of the values are present in the provided set of autocomplete values.
|
||
*
|
||
* @param autofillFieldData - The field autocomplete value to validate
|
||
* @param compareValues - The set of autocomplete values to check against
|
||
*/
|
||
fieldContainsAutocompleteValues(autofillFieldData, compareValues) {
|
||
const fieldAutocompleteValue = autofillFieldData.autoCompleteType;
|
||
if (!fieldAutocompleteValue || typeof fieldAutocompleteValue !== "string") {
|
||
return false;
|
||
}
|
||
const autocompleteValueParts = fieldAutocompleteValue.split(" ");
|
||
if (typeof compareValues === "string") {
|
||
return autocompleteValueParts.indexOf(compareValues) > -1;
|
||
}
|
||
for (let index = 0; index < autocompleteValueParts.length; index++) {
|
||
if (compareValues.has(autocompleteValueParts[index])) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
|
||
;// ./src/autofill/services/collect-autofill-content.service.ts
|
||
var collect_autofill_content_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
class CollectAutofillContentService {
|
||
constructor(domElementVisibilityService, domQueryService, autofillOverlayContentService) {
|
||
this.domElementVisibilityService = domElementVisibilityService;
|
||
this.domQueryService = domQueryService;
|
||
this.autofillOverlayContentService = autofillOverlayContentService;
|
||
this.sendExtensionMessage = sendExtensionMessage;
|
||
this.getAttributeBoolean = getAttributeBoolean;
|
||
this.getPropertyOrAttribute = getPropertyOrAttribute;
|
||
this.noFieldsFound = false;
|
||
this.domRecentlyMutated = true;
|
||
this._autofillFormElements = new Map();
|
||
this.autofillFieldElements = new Map();
|
||
this.currentLocationHref = "";
|
||
this.elementInitializingIntersectionObserver = new Set();
|
||
this.mutationsQueue = [];
|
||
this.ownedExperienceTagNames = [];
|
||
this.updateAfterMutationTimeout = 1000;
|
||
this.nonInputFormFieldTags = new Set(["textarea", "select"]);
|
||
this.ignoredInputTypes = new Set([
|
||
"hidden",
|
||
"submit",
|
||
"reset",
|
||
"button",
|
||
"image",
|
||
"file",
|
||
]);
|
||
/**
|
||
* Builds an AutofillField object from the given form element. Will only return
|
||
* shared field values if the element is a span element. Will not return any label
|
||
* values if the element is a hidden input element.
|
||
*
|
||
* @param element - The form field element to build the AutofillField object from
|
||
* @param index - The index of the form field element
|
||
*/
|
||
this.buildAutofillFieldItem = (element, index) => collect_autofill_content_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if (element.closest("button[type='submit']")) {
|
||
return null;
|
||
}
|
||
element.opid = `__${index}`;
|
||
const existingAutofillField = this.autofillFieldElements.get(element);
|
||
if (index >= 0 && existingAutofillField) {
|
||
existingAutofillField.opid = element.opid;
|
||
existingAutofillField.elementNumber = index;
|
||
this.autofillFieldElements.set(element, existingAutofillField);
|
||
return existingAutofillField;
|
||
}
|
||
const autofillFieldBase = {
|
||
opid: element.opid,
|
||
elementNumber: index,
|
||
maxLength: this.getAutofillFieldMaxLength(element),
|
||
viewable: yield this.domElementVisibilityService.isElementViewable(element),
|
||
htmlID: this.getPropertyOrAttribute(element, "id"),
|
||
htmlName: this.getPropertyOrAttribute(element, "name"),
|
||
htmlClass: this.getPropertyOrAttribute(element, "class"),
|
||
tabindex: this.getPropertyOrAttribute(element, "tabindex"),
|
||
title: this.getPropertyOrAttribute(element, "title"),
|
||
tagName: this.getAttributeLowerCase(element, "tagName"),
|
||
dataSetValues: this.getDataSetValues(element),
|
||
};
|
||
if (!autofillFieldBase.viewable) {
|
||
this.elementInitializingIntersectionObserver.add(element);
|
||
(_a = this.intersectionObserver) === null || _a === void 0 ? void 0 : _a.observe(element);
|
||
}
|
||
if (elementIsSpanElement(element)) {
|
||
this.cacheAutofillFieldElement(index, element, autofillFieldBase);
|
||
return autofillFieldBase;
|
||
}
|
||
let autofillFieldLabels = {};
|
||
const elementType = this.getAttributeLowerCase(element, "type");
|
||
if (elementType !== "hidden") {
|
||
autofillFieldLabels = {
|
||
"label-tag": this.createAutofillFieldLabelTag(element),
|
||
"label-data": this.getPropertyOrAttribute(element, "data-label"),
|
||
"label-aria": this.getPropertyOrAttribute(element, "aria-label"),
|
||
"label-top": this.createAutofillFieldTopLabel(element),
|
||
"label-right": this.createAutofillFieldRightLabel(element),
|
||
"label-left": this.createAutofillFieldLeftLabel(element),
|
||
placeholder: this.getPropertyOrAttribute(element, "placeholder"),
|
||
};
|
||
}
|
||
const fieldFormElement = element.form;
|
||
const autofillField = Object.assign(Object.assign(Object.assign({}, autofillFieldBase), autofillFieldLabels), { rel: this.getPropertyOrAttribute(element, "rel"), type: elementType, value: this.getElementValue(element), checked: this.getAttributeBoolean(element, "checked"), autoCompleteType: this.getAutoCompleteAttribute(element), disabled: this.getAttributeBoolean(element, "disabled"), readonly: this.getAttributeBoolean(element, "readonly"), selectInfo: elementIsSelectElement(element)
|
||
? this.getSelectElementOptions(element)
|
||
: null, form: fieldFormElement ? this.getPropertyOrAttribute(fieldFormElement, "opid") : null, "aria-hidden": this.getAttributeBoolean(element, "aria-hidden", true), "aria-disabled": this.getAttributeBoolean(element, "aria-disabled", true), "aria-haspopup": this.getAttributeBoolean(element, "aria-haspopup", true), "data-stripe": this.getPropertyOrAttribute(element, "data-stripe") });
|
||
this.cacheAutofillFieldElement(index, element, autofillField);
|
||
return autofillField;
|
||
});
|
||
/**
|
||
* Map over all the label elements and creates a
|
||
* string of the text content of each label element.
|
||
* @param {Set<HTMLElement>} labelElementsSet
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
this.createLabelElementsTag = (labelElementsSet) => {
|
||
return Array.from(labelElementsSet)
|
||
.map((labelElement) => {
|
||
const textContent = labelElement
|
||
? labelElement.textContent || labelElement.innerText
|
||
: null;
|
||
return this.trimAndRemoveNonPrintableText(textContent || "");
|
||
})
|
||
.join("");
|
||
};
|
||
this.setupInitialTopLayerListeners = () => {
|
||
var _a;
|
||
const unownedTopLayerItems = (_a = this.autofillOverlayContentService) === null || _a === void 0 ? void 0 : _a.getUnownedTopLayerItems(true);
|
||
if (unownedTopLayerItems === null || unownedTopLayerItems === void 0 ? void 0 : unownedTopLayerItems.length) {
|
||
for (const unownedElement of unownedTopLayerItems) {
|
||
if (this.shouldListenToTopLayerCandidate(unownedElement)) {
|
||
this.setupTopLayerCandidateListener(unownedElement);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* Handles observed DOM mutations and identifies if a mutation is related to
|
||
* an autofill element. If so, it will update the autofill element data.
|
||
* @param {MutationRecord[]} mutations
|
||
* @private
|
||
*/
|
||
this.handleMutationObserverMutation = (mutations) => {
|
||
if (this.currentLocationHref !== globalThis.location.href) {
|
||
this.handleWindowLocationMutation();
|
||
return;
|
||
}
|
||
if (!this.mutationsQueue.length) {
|
||
requestIdleCallbackPolyfill(debounce(this.processMutations, 100), { timeout: 500 });
|
||
}
|
||
this.mutationsQueue.push(mutations);
|
||
};
|
||
/**
|
||
* Handles the processing of all mutations in the mutations queue. Will trigger
|
||
* within an idle callback to help with performance and prevent excessive updates.
|
||
*/
|
||
this.processMutations = () => {
|
||
const queueLength = this.mutationsQueue.length;
|
||
for (let queueIndex = 0; queueIndex < queueLength; queueIndex++) {
|
||
const mutations = this.mutationsQueue[queueIndex];
|
||
const processMutationRecords = () => {
|
||
this.processMutationRecords(mutations);
|
||
if (queueIndex === queueLength - 1 && this.domRecentlyMutated) {
|
||
this.updateAutofillElementsAfterMutation();
|
||
}
|
||
};
|
||
requestIdleCallbackPolyfill(processMutationRecords, { timeout: 500 });
|
||
}
|
||
this.mutationsQueue = [];
|
||
};
|
||
this.setupTopLayerCandidateListener = (element) => {
|
||
const ownedTags = this.autofillOverlayContentService.getOwnedInlineMenuTagNames() || [];
|
||
this.ownedExperienceTagNames = ownedTags;
|
||
if (!ownedTags.includes(element.tagName)) {
|
||
element.addEventListener("toggle", (event) => {
|
||
if (event.newState === "open") {
|
||
// Add a slight delay (but faster than a user's reaction), to ensure the layer
|
||
// positioning happens after any triggered toggle has completed.
|
||
setTimeout(this.autofillOverlayContentService.refreshMenuLayerPosition, 100);
|
||
}
|
||
});
|
||
}
|
||
};
|
||
this.isPopoverAttribute = (attr) => {
|
||
const popoverAttributes = new Set(["popover", "popovertarget", "popovertargetaction"]);
|
||
return attr && popoverAttributes.has(attr.toLowerCase());
|
||
};
|
||
this.shouldListenToTopLayerCandidate = (element) => {
|
||
return (!this.ownedExperienceTagNames.includes(element.tagName) &&
|
||
(element.tagName === "DIALOG" ||
|
||
Array.from(element.attributes || []).some((attribute) => this.isPopoverAttribute(attribute.name))));
|
||
};
|
||
/**
|
||
* Checks if a mutation record is related features that utilize the top layer.
|
||
* If so, it then calls `setupTopLayerElementListener` for future event
|
||
* listening on the relevant element.
|
||
*
|
||
* @param mutation - The MutationRecord to check
|
||
*/
|
||
this.handleTopLayerChanges = (mutation) => {
|
||
var _a;
|
||
// Check attribute mutations
|
||
if (mutation.type === "attributes" && this.isPopoverAttribute(mutation.attributeName)) {
|
||
this.setupTopLayerCandidateListener(mutation.target);
|
||
}
|
||
// Check added nodes for dialog or popover attributes
|
||
if (mutation.type === "childList" && ((_a = mutation.addedNodes) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
||
for (const node of mutation.addedNodes) {
|
||
const mutationElement = node;
|
||
if (this.shouldListenToTopLayerCandidate(mutationElement)) {
|
||
this.setupTopLayerCandidateListener(mutationElement);
|
||
}
|
||
}
|
||
}
|
||
return;
|
||
};
|
||
/**
|
||
* Handles observed form field elements that are not viewable in the viewport.
|
||
* Will re-evaluate the visibility of the element and set up the autofill
|
||
* overlay listeners on the field if it is viewable.
|
||
*
|
||
* @param entries - The entries observed by the IntersectionObserver
|
||
*/
|
||
this.handleFormElementIntersection = (entries) => collect_autofill_content_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
for (let entryIndex = 0; entryIndex < entries.length; entryIndex++) {
|
||
const entry = entries[entryIndex];
|
||
const formFieldElement = entry.target;
|
||
if (this.elementInitializingIntersectionObserver.has(formFieldElement)) {
|
||
this.elementInitializingIntersectionObserver.delete(formFieldElement);
|
||
continue;
|
||
}
|
||
const cachedAutofillFieldElement = this.autofillFieldElements.get(formFieldElement);
|
||
if (!cachedAutofillFieldElement) {
|
||
this.intersectionObserver.unobserve(entry.target);
|
||
continue;
|
||
}
|
||
const isViewable = yield this.domElementVisibilityService.isElementViewable(formFieldElement);
|
||
if (!isViewable) {
|
||
continue;
|
||
}
|
||
cachedAutofillFieldElement.viewable = true;
|
||
this.setupOverlayOnField(formFieldElement, cachedAutofillFieldElement);
|
||
(_a = this.intersectionObserver) === null || _a === void 0 ? void 0 : _a.unobserve(entry.target);
|
||
}
|
||
});
|
||
let inputQuery = "input:not([data-bwignore])";
|
||
for (const type of this.ignoredInputTypes) {
|
||
inputQuery += `:not([type="${type}"])`;
|
||
}
|
||
this.formFieldQueryString = `${inputQuery}, textarea:not([data-bwignore]), select:not([data-bwignore]), span[data-bwautofill]`;
|
||
}
|
||
get autofillFormElements() {
|
||
return this._autofillFormElements;
|
||
}
|
||
/**
|
||
* Builds the data for all forms and fields found within the page DOM.
|
||
* Sets up a mutation observer to verify DOM changes and returns early
|
||
* with cached data if no changes are detected.
|
||
* @returns {Promise<AutofillPageDetails>}
|
||
* @public
|
||
*/
|
||
getPageDetails() {
|
||
return collect_autofill_content_service_awaiter(this, void 0, void 0, function* () {
|
||
// Set up listeners on top-layer candidates that predate Mutation Observer setup
|
||
this.setupInitialTopLayerListeners();
|
||
if (!this.mutationObserver) {
|
||
this.setupMutationObserver();
|
||
}
|
||
if (!this.intersectionObserver) {
|
||
this.setupIntersectionObserver();
|
||
}
|
||
if (!this.domRecentlyMutated && this.noFieldsFound) {
|
||
return this.getFormattedPageDetails({}, []);
|
||
}
|
||
if (!this.domRecentlyMutated && this.autofillFieldElements.size) {
|
||
this.updateCachedAutofillFieldVisibility();
|
||
return this.getFormattedPageDetails(this.getFormattedAutofillFormsData(), this.getFormattedAutofillFieldsData());
|
||
}
|
||
const { formElements, formFieldElements } = this.queryAutofillFormAndFieldElements();
|
||
const autofillFormsData = this.buildAutofillFormsData(formElements);
|
||
const autofillFieldsData = (yield this.buildAutofillFieldsData(formFieldElements)).filter((field) => !!field);
|
||
this.sortAutofillFieldElementsMap();
|
||
if (!autofillFieldsData.length) {
|
||
this.noFieldsFound = true;
|
||
}
|
||
this.domRecentlyMutated = false;
|
||
const pageDetails = this.getFormattedPageDetails(autofillFormsData, autofillFieldsData);
|
||
this.setupOverlayListeners(pageDetails);
|
||
return pageDetails;
|
||
});
|
||
}
|
||
/**
|
||
* Find an AutofillField element by its opid, will only return the first
|
||
* element if there are multiple elements with the same opid. If no
|
||
* element is found, null will be returned.
|
||
* @param {string} opid
|
||
* @returns {FormFieldElement | null}
|
||
*/
|
||
getAutofillFieldElementByOpid(opid) {
|
||
const cachedFormFieldElements = Array.from(this.autofillFieldElements.keys());
|
||
const formFieldElements = (cachedFormFieldElements === null || cachedFormFieldElements === void 0 ? void 0 : cachedFormFieldElements.length)
|
||
? cachedFormFieldElements
|
||
: this.getAutofillFieldElements();
|
||
const fieldElementsWithOpid = formFieldElements.filter((fieldElement) => fieldElement.opid === opid);
|
||
if (!fieldElementsWithOpid.length) {
|
||
const elementIndex = parseInt(opid.split("__")[1], 10);
|
||
return formFieldElements[elementIndex] || null;
|
||
}
|
||
if (fieldElementsWithOpid.length > 1) {
|
||
// eslint-disable-next-line no-console
|
||
console.warn(`More than one element found with opid ${opid}`);
|
||
}
|
||
return fieldElementsWithOpid[0];
|
||
}
|
||
/**
|
||
* Sorts the AutofillFieldElements map by the elementNumber property.
|
||
* @private
|
||
*/
|
||
sortAutofillFieldElementsMap() {
|
||
if (!this.autofillFieldElements.size) {
|
||
return;
|
||
}
|
||
this.autofillFieldElements = new Map([...this.autofillFieldElements].sort((a, b) => a[1].elementNumber - b[1].elementNumber));
|
||
}
|
||
/**
|
||
* Formats and returns the AutofillPageDetails object
|
||
*
|
||
* @param autofillFormsData - The data for all the forms found in the page
|
||
* @param autofillFieldsData - The data for all the fields found in the page
|
||
*/
|
||
getFormattedPageDetails(autofillFormsData, autofillFieldsData) {
|
||
return {
|
||
title: document.title,
|
||
url: (document.defaultView || globalThis).location.href,
|
||
documentUrl: document.location.href,
|
||
forms: autofillFormsData,
|
||
fields: autofillFieldsData,
|
||
collectedTimestamp: Date.now(),
|
||
};
|
||
}
|
||
/**
|
||
* Re-checks the visibility for all form fields and updates the
|
||
* cached data to reflect the most recent visibility state.
|
||
*
|
||
* @private
|
||
*/
|
||
updateCachedAutofillFieldVisibility() {
|
||
this.autofillFieldElements.forEach((autofillField, element) => collect_autofill_content_service_awaiter(this, void 0, void 0, function* () {
|
||
const previouslyViewable = autofillField.viewable;
|
||
autofillField.viewable = yield this.domElementVisibilityService.isElementViewable(element);
|
||
if (!previouslyViewable && autofillField.viewable) {
|
||
this.setupOverlayOnField(element, autofillField);
|
||
}
|
||
}));
|
||
}
|
||
/**
|
||
* Queries the DOM for all the forms elements and
|
||
* returns a collection of AutofillForm objects.
|
||
* @returns {Record<string, AutofillForm>}
|
||
* @private
|
||
*/
|
||
buildAutofillFormsData(formElements) {
|
||
for (let index = 0; index < formElements.length; index++) {
|
||
const formElement = formElements[index];
|
||
formElement.opid = `__form__${index}`;
|
||
const existingAutofillForm = this._autofillFormElements.get(formElement);
|
||
if (existingAutofillForm) {
|
||
existingAutofillForm.opid = formElement.opid;
|
||
this._autofillFormElements.set(formElement, existingAutofillForm);
|
||
continue;
|
||
}
|
||
this._autofillFormElements.set(formElement, {
|
||
opid: formElement.opid,
|
||
htmlAction: this.getFormActionAttribute(formElement),
|
||
htmlName: this.getPropertyOrAttribute(formElement, "name"),
|
||
htmlClass: this.getPropertyOrAttribute(formElement, "class"),
|
||
htmlID: this.getPropertyOrAttribute(formElement, "id"),
|
||
htmlMethod: this.getPropertyOrAttribute(formElement, "method"),
|
||
});
|
||
}
|
||
return this.getFormattedAutofillFormsData();
|
||
}
|
||
/**
|
||
* Returns the action attribute of the form element. If the action attribute
|
||
* is a relative path, it will be converted to an absolute path.
|
||
* @param {ElementWithOpId<HTMLFormElement>} element
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
getFormActionAttribute(element) {
|
||
return new URL(this.getPropertyOrAttribute(element, "action"), globalThis.location.href).href;
|
||
}
|
||
/**
|
||
* Iterates over all known form elements and returns an AutofillForm object
|
||
* containing a key value pair of the form element's opid and the form data.
|
||
* @returns {Record<string, AutofillForm>}
|
||
* @private
|
||
*/
|
||
getFormattedAutofillFormsData() {
|
||
const autofillForms = {};
|
||
const autofillFormElements = Array.from(this._autofillFormElements);
|
||
for (let index = 0; index < autofillFormElements.length; index++) {
|
||
const [formElement, autofillForm] = autofillFormElements[index];
|
||
autofillForms[formElement.opid] = autofillForm;
|
||
}
|
||
return autofillForms;
|
||
}
|
||
/**
|
||
* Queries the DOM for all the field elements and
|
||
* returns a list of AutofillField objects.
|
||
* @returns {Promise<AutofillField[]>}
|
||
* @private
|
||
*/
|
||
buildAutofillFieldsData(formFieldElements) {
|
||
return collect_autofill_content_service_awaiter(this, void 0, void 0, function* () {
|
||
// Maximum number of form fields to process for autofill to prevent performance issues on pages with excessive fields
|
||
const autofillFieldsLimit = 200;
|
||
const autofillFieldElements = this.getAutofillFieldElements(autofillFieldsLimit, formFieldElements);
|
||
const autofillFieldDataPromises = autofillFieldElements.map(this.buildAutofillFieldItem);
|
||
return Promise.all(autofillFieldDataPromises);
|
||
});
|
||
}
|
||
/**
|
||
* Queries the DOM for all the field elements that can be autofilled,
|
||
* and returns a list limited to the given `fieldsLimit` number that
|
||
* is ordered by priority.
|
||
* @param {number} fieldsLimit - The maximum number of fields to return
|
||
* @param {FormFieldElement[]} previouslyFoundFormFieldElements - The list of all the field elements
|
||
* @returns {FormFieldElement[]}
|
||
* @private
|
||
*/
|
||
getAutofillFieldElements(fieldsLimit, previouslyFoundFormFieldElements) {
|
||
var _a;
|
||
let formFieldElements = previouslyFoundFormFieldElements;
|
||
if (!formFieldElements) {
|
||
formFieldElements = this.domQueryService.query(globalThis.document.documentElement, this.formFieldQueryString, (node) => this.isNodeFormFieldElement(node), this.mutationObserver);
|
||
}
|
||
if (!fieldsLimit || formFieldElements.length <= fieldsLimit) {
|
||
return formFieldElements;
|
||
}
|
||
const priorityFormFields = [];
|
||
const unimportantFormFields = [];
|
||
const unimportantFieldTypesSet = new Set(["checkbox", "radio"]);
|
||
for (const element of formFieldElements) {
|
||
if (priorityFormFields.length >= fieldsLimit) {
|
||
return priorityFormFields;
|
||
}
|
||
const fieldType = (_a = this.getPropertyOrAttribute(element, "type")) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
||
if (unimportantFieldTypesSet.has(fieldType)) {
|
||
unimportantFormFields.push(element);
|
||
continue;
|
||
}
|
||
priorityFormFields.push(element);
|
||
}
|
||
const numberUnimportantFieldsToInclude = fieldsLimit - priorityFormFields.length;
|
||
for (let index = 0; index < numberUnimportantFieldsToInclude; index++) {
|
||
priorityFormFields.push(unimportantFormFields[index]);
|
||
}
|
||
return priorityFormFields;
|
||
}
|
||
/**
|
||
* Caches the autofill field element and its data.
|
||
*
|
||
* @param index - The index of the autofill field element
|
||
* @param element - The autofill field element to cache
|
||
* @param autofillFieldData - The autofill field data to cache
|
||
*/
|
||
cacheAutofillFieldElement(index, element, autofillFieldData) {
|
||
// Always cache the element, even if index is -1 (for dynamically added fields)
|
||
this.autofillFieldElements.set(element, autofillFieldData);
|
||
}
|
||
/**
|
||
* Identifies the autocomplete attribute associated with an element and returns
|
||
* the value of the attribute if it is not set to "off".
|
||
* @param {ElementWithOpId<FormFieldElement>} element
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
getAutoCompleteAttribute(element) {
|
||
return (this.getPropertyOrAttribute(element, "x-autocompletetype") ||
|
||
this.getPropertyOrAttribute(element, "autocompletetype") ||
|
||
this.getPropertyOrAttribute(element, "autocomplete"));
|
||
}
|
||
/**
|
||
* Returns the attribute of an element as a lowercase value.
|
||
* @param {ElementWithOpId<FormFieldElement>} element
|
||
* @param {string} attributeName
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
getAttributeLowerCase(element, attributeName) {
|
||
var _a;
|
||
return (_a = this.getPropertyOrAttribute(element, attributeName)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
||
}
|
||
/**
|
||
* Returns the value of an element's property or attribute.
|
||
* @returns {AutofillField[]}
|
||
* @private
|
||
*/
|
||
getFormattedAutofillFieldsData() {
|
||
return Array.from(this.autofillFieldElements.values());
|
||
}
|
||
/**
|
||
* Creates a label tag used to autofill the element pulled from a label
|
||
* associated with the element's id, name, parent element or from an
|
||
* associated description term element if no other labels can be found.
|
||
* Returns a string containing all the `textContent` or `innerText`
|
||
* values of the label elements.
|
||
* @param {FillableFormFieldElement} element
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
createAutofillFieldLabelTag(element) {
|
||
var _a;
|
||
const labelElementsSet = new Set(element.labels);
|
||
if (labelElementsSet.size) {
|
||
return this.createLabelElementsTag(labelElementsSet);
|
||
}
|
||
const labelElements = this.queryElementLabels(element);
|
||
for (let labelIndex = 0; labelIndex < (labelElements === null || labelElements === void 0 ? void 0 : labelElements.length); labelIndex++) {
|
||
labelElementsSet.add(labelElements[labelIndex]);
|
||
}
|
||
let currentElement = element;
|
||
while (currentElement && currentElement !== document.documentElement) {
|
||
if (elementIsLabelElement(currentElement)) {
|
||
labelElementsSet.add(currentElement);
|
||
}
|
||
currentElement = (_a = currentElement.parentElement) === null || _a === void 0 ? void 0 : _a.closest("label");
|
||
}
|
||
if (!labelElementsSet.size &&
|
||
elementIsDescriptionDetailsElement(element.parentElement) &&
|
||
elementIsDescriptionTermElement(element.parentElement.previousElementSibling)) {
|
||
labelElementsSet.add(element.parentElement.previousElementSibling);
|
||
}
|
||
return this.createLabelElementsTag(labelElementsSet);
|
||
}
|
||
/**
|
||
* Queries the DOM for label elements associated with the given element
|
||
* by id or name. Returns a NodeList of label elements or null if none
|
||
* are found.
|
||
* @param {FillableFormFieldElement} element
|
||
* @returns {NodeListOf<HTMLLabelElement> | null}
|
||
* @private
|
||
*/
|
||
queryElementLabels(element) {
|
||
let labelQuerySelectors = element.id ? `label[for="${element.id}"]` : "";
|
||
if (element.name) {
|
||
const forElementNameSelector = `label[for="${element.name}"]`;
|
||
labelQuerySelectors = labelQuerySelectors
|
||
? `${labelQuerySelectors}, ${forElementNameSelector}`
|
||
: forElementNameSelector;
|
||
}
|
||
if (!labelQuerySelectors) {
|
||
return null;
|
||
}
|
||
return element.getRootNode().querySelectorAll(labelQuerySelectors.replace(/\n/g, ""));
|
||
}
|
||
/**
|
||
* Gets the maxLength property of the passed FormFieldElement and
|
||
* returns the value or null if the element does not have a
|
||
* maxLength property. If the element has a maxLength property
|
||
* greater than 999, it will return 999.
|
||
* @param {FormFieldElement} element
|
||
* @returns {number | null}
|
||
* @private
|
||
*/
|
||
getAutofillFieldMaxLength(element) {
|
||
const elementHasMaxLengthProperty = elementIsInputElement(element) || elementIsTextAreaElement(element);
|
||
const elementMaxLength = elementHasMaxLengthProperty && element.maxLength > -1 ? element.maxLength : 999;
|
||
return elementHasMaxLengthProperty ? Math.min(elementMaxLength, 999) : null;
|
||
}
|
||
/**
|
||
* Iterates over the next siblings of the passed element and
|
||
* returns a string of the text content of each element. Will
|
||
* stop iterating if it encounters a new section element.
|
||
* @param {FormFieldElement} element
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
createAutofillFieldRightLabel(element) {
|
||
const labelTextContent = [];
|
||
let currentElement = element;
|
||
while (currentElement && currentElement.nextSibling) {
|
||
currentElement = currentElement.nextSibling;
|
||
if (this.isNewSectionElement(currentElement)) {
|
||
break;
|
||
}
|
||
const textContent = this.getTextContentFromElement(currentElement);
|
||
if (textContent) {
|
||
labelTextContent.push(textContent);
|
||
}
|
||
}
|
||
return labelTextContent.join("");
|
||
}
|
||
/**
|
||
* Recursively gets the text content from an element's previous siblings
|
||
* and returns a string of the text content of each element.
|
||
* @param {FormFieldElement} element
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
createAutofillFieldLeftLabel(element) {
|
||
const labelTextContent = this.recursivelyGetTextFromPreviousSiblings(element);
|
||
return labelTextContent.reverse().join("");
|
||
}
|
||
/**
|
||
* Assumes that the input elements that are to be autofilled are within a
|
||
* table structure. Queries the previous sibling of the parent row that
|
||
* the input element is in and returns the text content of the cell that
|
||
* is in the same column as the input element.
|
||
* @param {FormFieldElement} element
|
||
* @returns {string | null}
|
||
* @private
|
||
*/
|
||
createAutofillFieldTopLabel(element) {
|
||
var _a, _b;
|
||
const tableDataElement = element.closest("td");
|
||
if (!tableDataElement) {
|
||
return null;
|
||
}
|
||
const tableDataElementIndex = tableDataElement.cellIndex;
|
||
if (tableDataElementIndex < 0) {
|
||
return null;
|
||
}
|
||
const parentSiblingTableRowElement = (_a = tableDataElement.closest("tr")) === null || _a === void 0 ? void 0 : _a.previousElementSibling;
|
||
return ((_b = parentSiblingTableRowElement === null || parentSiblingTableRowElement === void 0 ? void 0 : parentSiblingTableRowElement.cells) === null || _b === void 0 ? void 0 : _b.length) > tableDataElementIndex
|
||
? this.getTextContentFromElement(parentSiblingTableRowElement.cells[tableDataElementIndex])
|
||
: null;
|
||
}
|
||
/**
|
||
* Check if the element's tag indicates that a transition to a new section of the
|
||
* page is occurring. If so, we should not use the element or its children in order
|
||
* to get autofill context for the previous element.
|
||
* @param {HTMLElement} currentElement
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isNewSectionElement(currentElement) {
|
||
if (!currentElement) {
|
||
return true;
|
||
}
|
||
const transitionalElementTagsSet = new Set([
|
||
"html",
|
||
"body",
|
||
"button",
|
||
"form",
|
||
"head",
|
||
"iframe",
|
||
"input",
|
||
"option",
|
||
"script",
|
||
"select",
|
||
"table",
|
||
"textarea",
|
||
]);
|
||
return ("tagName" in currentElement &&
|
||
transitionalElementTagsSet.has(currentElement.tagName.toLowerCase()));
|
||
}
|
||
/**
|
||
* Gets the text content from a passed element, regardless of whether it is a
|
||
* text node, an element node or an HTMLElement.
|
||
* @param {Node | HTMLElement} element
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
getTextContentFromElement(element) {
|
||
if (element.nodeType === Node.TEXT_NODE) {
|
||
return this.trimAndRemoveNonPrintableText(element.nodeValue);
|
||
}
|
||
return this.trimAndRemoveNonPrintableText(element.textContent || element.innerText);
|
||
}
|
||
/**
|
||
* Removes non-printable characters from the passed text
|
||
* content and trims leading and trailing whitespace.
|
||
* @param {string} textContent
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
trimAndRemoveNonPrintableText(textContent) {
|
||
return (textContent || "")
|
||
.replace(/\p{C}+|\s+/gu, " ") // Strip out non-printable characters and replace multiple spaces with a single space
|
||
.trim(); // Trim leading and trailing whitespace
|
||
}
|
||
/**
|
||
* Get the text content from the previous siblings of the element. If
|
||
* no text content is found, recursively get the text content from the
|
||
* previous siblings of the parent element.
|
||
* @param {FormFieldElement} element
|
||
* @returns {string[]}
|
||
* @private
|
||
*/
|
||
recursivelyGetTextFromPreviousSiblings(element) {
|
||
const textContentItems = [];
|
||
let currentElement = element;
|
||
while (currentElement && currentElement.previousSibling) {
|
||
// Ensure we are capturing text content from nodes and elements.
|
||
currentElement = currentElement.previousSibling;
|
||
if (this.isNewSectionElement(currentElement)) {
|
||
return textContentItems;
|
||
}
|
||
const textContent = this.getTextContentFromElement(currentElement);
|
||
if (textContent) {
|
||
textContentItems.push(textContent);
|
||
}
|
||
}
|
||
if (!currentElement || textContentItems.length) {
|
||
return textContentItems;
|
||
}
|
||
// Prioritize capturing text content from elements rather than nodes.
|
||
currentElement = currentElement.parentElement || currentElement.parentNode;
|
||
if (!currentElement) {
|
||
return textContentItems;
|
||
}
|
||
let siblingElement = nodeIsElement(currentElement)
|
||
? currentElement.previousElementSibling
|
||
: currentElement.previousSibling;
|
||
while ((siblingElement === null || siblingElement === void 0 ? void 0 : siblingElement.lastChild) && !this.isNewSectionElement(siblingElement)) {
|
||
siblingElement = siblingElement.lastChild;
|
||
}
|
||
if (this.isNewSectionElement(siblingElement)) {
|
||
return textContentItems;
|
||
}
|
||
const textContent = this.getTextContentFromElement(siblingElement);
|
||
if (textContent) {
|
||
textContentItems.push(textContent);
|
||
return textContentItems;
|
||
}
|
||
return this.recursivelyGetTextFromPreviousSiblings(siblingElement);
|
||
}
|
||
/**
|
||
* Gets the value of the element. If the element is a checkbox, returns a checkmark if the
|
||
* checkbox is checked, or an empty string if it is not checked. If the element is a hidden
|
||
* input, returns the value of the input if it is less than 254 characters, or a truncated
|
||
* value if it is longer than 254 characters.
|
||
* @param {FormFieldElement} element
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
getElementValue(element) {
|
||
if (!elementIsFillableFormField(element)) {
|
||
const spanTextContent = element.textContent || element.innerText;
|
||
return spanTextContent || "";
|
||
}
|
||
const elementValue = element.value || "";
|
||
const elementType = String(element.type).toLowerCase();
|
||
if ("checked" in element && elementType === "checkbox") {
|
||
return element.checked ? "✓" : "";
|
||
}
|
||
if (elementType === "hidden") {
|
||
const inputValueMaxLength = 254;
|
||
return elementValue.length > inputValueMaxLength
|
||
? `${elementValue.substring(0, inputValueMaxLength)}...SNIPPED`
|
||
: elementValue;
|
||
}
|
||
return elementValue;
|
||
}
|
||
/**
|
||
* Captures the `data-*` attribute metadata to help with validating the autofill data.
|
||
*
|
||
* @param element - The form field element to capture the `data-*` attribute metadata from
|
||
*/
|
||
getDataSetValues(element) {
|
||
let datasetValues = "";
|
||
const dataset = element.dataset;
|
||
for (const key in dataset) {
|
||
datasetValues += `${key}: ${dataset[key]}, `;
|
||
}
|
||
return datasetValues;
|
||
}
|
||
/**
|
||
* Get the options from a select element and return them as an array
|
||
* of arrays indicating the select element option text and value.
|
||
* @param {HTMLSelectElement} element
|
||
* @returns {{options: (string | null)[][]}}
|
||
* @private
|
||
*/
|
||
getSelectElementOptions(element) {
|
||
const options = Array.from(element.options).map((option) => {
|
||
const optionText = option.text
|
||
? String(option.text)
|
||
.toLowerCase()
|
||
.replace(/[\s~`!@$%^&#*()\-_+=:;'"[\]|\\,<.>?]/gm, "") // Remove whitespace and punctuation
|
||
: null;
|
||
return [optionText, option.value];
|
||
});
|
||
return { options };
|
||
}
|
||
/**
|
||
* Queries all potential form and field elements from the DOM and returns
|
||
* a collection of form and field elements. Leverages the TreeWalker API
|
||
* to deep query Shadow DOM elements.
|
||
*/
|
||
queryAutofillFormAndFieldElements() {
|
||
const formElements = [];
|
||
const formFieldElements = [];
|
||
const queriedElements = this.domQueryService.query(globalThis.document.documentElement, `form, ${this.formFieldQueryString}`, (node) => {
|
||
if (nodeIsFormElement(node)) {
|
||
formElements.push(node);
|
||
return true;
|
||
}
|
||
if (this.isNodeFormFieldElement(node)) {
|
||
formFieldElements.push(node);
|
||
return true;
|
||
}
|
||
return false;
|
||
}, this.mutationObserver);
|
||
if (formElements.length || formFieldElements.length) {
|
||
return { formElements, formFieldElements };
|
||
}
|
||
for (let index = 0; index < queriedElements.length; index++) {
|
||
const element = queriedElements[index];
|
||
if (elementIsFormElement(element)) {
|
||
formElements.push(element);
|
||
continue;
|
||
}
|
||
if (this.isNodeFormFieldElement(element)) {
|
||
formFieldElements.push(element);
|
||
}
|
||
}
|
||
return { formElements, formFieldElements };
|
||
}
|
||
/**
|
||
* Checks if the passed node is a form field element.
|
||
* @param {Node} node
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isNodeFormFieldElement(node) {
|
||
if (!nodeIsElement(node)) {
|
||
return false;
|
||
}
|
||
const nodeTagName = node.tagName.toLowerCase();
|
||
const nodeIsSpanElementWithAutofillAttribute = nodeTagName === "span" && node.hasAttribute("data-bwautofill");
|
||
if (nodeIsSpanElementWithAutofillAttribute) {
|
||
return true;
|
||
}
|
||
const nodeHasBwIgnoreAttribute = node.hasAttribute("data-bwignore");
|
||
const nodeIsValidInputElement = nodeTagName === "input" && !this.ignoredInputTypes.has(node.type);
|
||
if (nodeIsValidInputElement && !nodeHasBwIgnoreAttribute) {
|
||
return true;
|
||
}
|
||
return this.nonInputFormFieldTags.has(nodeTagName) && !nodeHasBwIgnoreAttribute;
|
||
}
|
||
/**
|
||
* Sets up a mutation observer on the body of the document. Observes changes to
|
||
* DOM elements to ensure we have an updated set of autofill field data.
|
||
* @private
|
||
*/
|
||
setupMutationObserver() {
|
||
this.currentLocationHref = globalThis.location.href;
|
||
this.mutationObserver = new MutationObserver(this.handleMutationObserverMutation);
|
||
this.mutationObserver.observe(document.documentElement, {
|
||
attributes: true,
|
||
childList: true,
|
||
subtree: true,
|
||
});
|
||
}
|
||
/**
|
||
* Handles a mutation to the window location. Clears the autofill elements
|
||
* and updates the autofill elements after a timeout.
|
||
* @private
|
||
*/
|
||
handleWindowLocationMutation() {
|
||
this.currentLocationHref = globalThis.location.href;
|
||
this.domRecentlyMutated = true;
|
||
if (this.autofillOverlayContentService) {
|
||
this.autofillOverlayContentService.pageDetailsUpdateRequired = true;
|
||
this.autofillOverlayContentService.clearUserFilledFields();
|
||
void this.sendExtensionMessage("closeAutofillInlineMenu", { forceCloseInlineMenu: true });
|
||
}
|
||
this.noFieldsFound = false;
|
||
this._autofillFormElements.clear();
|
||
this.autofillFieldElements.clear();
|
||
this.updateAutofillElementsAfterMutation();
|
||
}
|
||
/**
|
||
* Triggers several flags that indicate that a collection of page details should
|
||
* occur again on a subsequent call after a mutation has been observed in the DOM.
|
||
*/
|
||
flagPageDetailsUpdateIsRequired() {
|
||
this.domRecentlyMutated = true;
|
||
if (this.autofillOverlayContentService) {
|
||
this.autofillOverlayContentService.pageDetailsUpdateRequired = true;
|
||
}
|
||
this.noFieldsFound = false;
|
||
}
|
||
/**
|
||
* Processes all mutation records encountered by the mutation observer.
|
||
*
|
||
* @param mutations - The mutation record to process
|
||
*/
|
||
processMutationRecords(mutations) {
|
||
for (let mutationIndex = 0; mutationIndex < mutations.length; mutationIndex++) {
|
||
const mutation = mutations[mutationIndex];
|
||
const processMutationRecord = () => this.processMutationRecord(mutation);
|
||
requestIdleCallbackPolyfill(processMutationRecord, { timeout: 500 });
|
||
}
|
||
}
|
||
/**
|
||
* Processes a single mutation record and updates the autofill elements if necessary.
|
||
* @param mutation
|
||
* @private
|
||
*/
|
||
processMutationRecord(mutation) {
|
||
this.handleTopLayerChanges(mutation);
|
||
if (mutation.type === "childList" &&
|
||
(this.isAutofillElementNodeMutated(mutation.removedNodes, true) ||
|
||
this.isAutofillElementNodeMutated(mutation.addedNodes))) {
|
||
this.flagPageDetailsUpdateIsRequired();
|
||
return;
|
||
}
|
||
if (mutation.type === "attributes") {
|
||
this.handleAutofillElementAttributeMutation(mutation);
|
||
}
|
||
}
|
||
/**
|
||
* Checks if the passed nodes either contain or are autofill elements.
|
||
*
|
||
* @param nodes - The nodes to check
|
||
* @param isRemovingNodes - Whether the nodes are being removed
|
||
*/
|
||
isAutofillElementNodeMutated(nodes, isRemovingNodes = false) {
|
||
if (!nodes.length) {
|
||
return false;
|
||
}
|
||
let isElementMutated = false;
|
||
let mutatedElements = [];
|
||
for (let index = 0; index < nodes.length; index++) {
|
||
const node = nodes[index];
|
||
if (!nodeIsElement(node)) {
|
||
continue;
|
||
}
|
||
if (nodeIsFormElement(node) || this.isNodeFormFieldElement(node)) {
|
||
mutatedElements.push(node);
|
||
}
|
||
const autofillElements = this.domQueryService.query(node, `form, ${this.formFieldQueryString}`, (walkerNode) => nodeIsFormElement(walkerNode) || this.isNodeFormFieldElement(walkerNode), this.mutationObserver, true);
|
||
if (autofillElements.length) {
|
||
mutatedElements = mutatedElements.concat(autofillElements);
|
||
}
|
||
if (mutatedElements.length) {
|
||
isElementMutated = true;
|
||
}
|
||
}
|
||
if (isRemovingNodes) {
|
||
for (let elementIndex = 0; elementIndex < mutatedElements.length; elementIndex++) {
|
||
const element = mutatedElements[elementIndex];
|
||
this.deleteCachedAutofillElement(element);
|
||
}
|
||
}
|
||
else if (this.autofillOverlayContentService) {
|
||
this.setupOverlayListenersOnMutatedElements(mutatedElements);
|
||
}
|
||
return isElementMutated;
|
||
}
|
||
/**
|
||
* Sets up the overlay listeners on the passed mutated elements. This ensures
|
||
* that the overlay can appear on elements that are injected into the DOM after
|
||
* the initial page load.
|
||
*
|
||
* @param mutatedElements - HTML elements that have been mutated
|
||
*/
|
||
setupOverlayListenersOnMutatedElements(mutatedElements) {
|
||
for (let elementIndex = 0; elementIndex < mutatedElements.length; elementIndex++) {
|
||
const node = mutatedElements[elementIndex];
|
||
const buildAutofillFieldItem = () => collect_autofill_content_service_awaiter(this, void 0, void 0, function* () {
|
||
if (!this.isNodeFormFieldElement(node) ||
|
||
this.autofillFieldElements.get(node)) {
|
||
return;
|
||
}
|
||
// We are setting this item to a -1 index because we do not know its position in the DOM.
|
||
// This value should be updated with the next call to collect page details.
|
||
const formFieldElement = node;
|
||
const autofillField = yield this.buildAutofillFieldItem(formFieldElement, -1);
|
||
// Set up overlay listeners for the new field if we have the overlay service
|
||
if (autofillField && this.autofillOverlayContentService) {
|
||
this.setupOverlayOnField(formFieldElement, autofillField);
|
||
if (this.domRecentlyMutated) {
|
||
this.updateAutofillElementsAfterMutation();
|
||
}
|
||
}
|
||
});
|
||
requestIdleCallbackPolyfill(buildAutofillFieldItem, { timeout: 1000 });
|
||
}
|
||
}
|
||
/**
|
||
* Deletes any cached autofill elements that have been
|
||
* removed from the DOM.
|
||
* @param {ElementWithOpId<HTMLFormElement> | ElementWithOpId<FormFieldElement>} element
|
||
* @private
|
||
*/
|
||
deleteCachedAutofillElement(element) {
|
||
if (elementIsFormElement(element) && this._autofillFormElements.has(element)) {
|
||
this._autofillFormElements.delete(element);
|
||
return;
|
||
}
|
||
if (this.autofillFieldElements.has(element)) {
|
||
this.autofillFieldElements.delete(element);
|
||
}
|
||
}
|
||
/**
|
||
* Updates the autofill elements after a DOM mutation has occurred.
|
||
* Is debounced to prevent excessive updates.
|
||
* @private
|
||
*/
|
||
updateAutofillElementsAfterMutation() {
|
||
if (this.updateAfterMutationIdleCallback) {
|
||
cancelIdleCallbackPolyfill(this.updateAfterMutationIdleCallback);
|
||
}
|
||
this.updateAfterMutationIdleCallback = requestIdleCallbackPolyfill(this.getPageDetails.bind(this), { timeout: this.updateAfterMutationTimeout });
|
||
}
|
||
/**
|
||
* Handles observed DOM mutations related to an autofill element attribute.
|
||
* @param {MutationRecord} mutation
|
||
* @private
|
||
*/
|
||
handleAutofillElementAttributeMutation(mutation) {
|
||
var _a;
|
||
const targetElement = mutation.target;
|
||
if (!nodeIsElement(targetElement)) {
|
||
return;
|
||
}
|
||
const attributeName = (_a = mutation.attributeName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
||
const autofillForm = this._autofillFormElements.get(targetElement);
|
||
if (autofillForm) {
|
||
this.updateAutofillFormElementData(attributeName, targetElement, autofillForm);
|
||
return;
|
||
}
|
||
const autofillField = this.autofillFieldElements.get(targetElement);
|
||
if (!autofillField) {
|
||
return;
|
||
}
|
||
this.updateAutofillFieldElementData(attributeName, targetElement, autofillField);
|
||
}
|
||
/**
|
||
* Updates the autofill form element data based on the passed attribute name.
|
||
* @param {string} attributeName
|
||
* @param {ElementWithOpId<HTMLFormElement>} element
|
||
* @param {AutofillForm} dataTarget
|
||
* @private
|
||
*/
|
||
updateAutofillFormElementData(attributeName, element, dataTarget) {
|
||
const updateAttribute = (dataTargetKey) => {
|
||
this.updateAutofillDataAttribute({ element, attributeName, dataTarget, dataTargetKey });
|
||
};
|
||
const updateActions = {
|
||
action: () => (dataTarget.htmlAction = this.getFormActionAttribute(element)),
|
||
name: () => updateAttribute("htmlName"),
|
||
id: () => updateAttribute("htmlID"),
|
||
method: () => updateAttribute("htmlMethod"),
|
||
};
|
||
if (!updateActions[attributeName]) {
|
||
return;
|
||
}
|
||
updateActions[attributeName]();
|
||
if (this._autofillFormElements.has(element)) {
|
||
this._autofillFormElements.set(element, dataTarget);
|
||
}
|
||
}
|
||
/**
|
||
* Updates the autofill field element data based on the passed attribute name.
|
||
*
|
||
* @param {string} attributeName
|
||
* @param {ElementWithOpId<FormFieldElement>} element
|
||
* @param {AutofillField} dataTarget
|
||
*/
|
||
updateAutofillFieldElementData(attributeName, element, dataTarget) {
|
||
const updateAttribute = (dataTargetKey) => {
|
||
this.updateAutofillDataAttribute({ element, attributeName, dataTarget, dataTargetKey });
|
||
};
|
||
const updateActions = {
|
||
maxlength: () => (dataTarget.maxLength = this.getAutofillFieldMaxLength(element)),
|
||
id: () => updateAttribute("htmlID"),
|
||
name: () => updateAttribute("htmlName"),
|
||
class: () => updateAttribute("htmlClass"),
|
||
tabindex: () => updateAttribute("tabindex"),
|
||
title: () => updateAttribute("tabindex"),
|
||
rel: () => updateAttribute("rel"),
|
||
tagname: () => (dataTarget.tagName = this.getAttributeLowerCase(element, "tagName")),
|
||
type: () => (dataTarget.type = this.getAttributeLowerCase(element, "type")),
|
||
value: () => (dataTarget.value = this.getElementValue(element)),
|
||
checked: () => (dataTarget.checked = this.getAttributeBoolean(element, "checked")),
|
||
disabled: () => (dataTarget.disabled = this.getAttributeBoolean(element, "disabled")),
|
||
readonly: () => (dataTarget.readonly = this.getAttributeBoolean(element, "readonly")),
|
||
autocomplete: () => (dataTarget.autoCompleteType = this.getAutoCompleteAttribute(element)),
|
||
"data-label": () => updateAttribute("label-data"),
|
||
"aria-label": () => updateAttribute("label-aria"),
|
||
"aria-hidden": () => (dataTarget["aria-hidden"] = this.getAttributeBoolean(element, "aria-hidden", true)),
|
||
"aria-disabled": () => (dataTarget["aria-disabled"] = this.getAttributeBoolean(element, "aria-disabled", true)),
|
||
"aria-haspopup": () => (dataTarget["aria-haspopup"] = this.getAttributeBoolean(element, "aria-haspopup", true)),
|
||
"data-stripe": () => updateAttribute("data-stripe"),
|
||
};
|
||
if (!updateActions[attributeName]) {
|
||
return;
|
||
}
|
||
updateActions[attributeName]();
|
||
if (this.autofillFieldElements.has(element)) {
|
||
this.autofillFieldElements.set(element, dataTarget);
|
||
}
|
||
}
|
||
/**
|
||
* Gets the attribute value for the passed element, and returns it. If the dataTarget
|
||
* and dataTargetKey are passed, it will set the value of the dataTarget[dataTargetKey].
|
||
* @param UpdateAutofillDataAttributeParams
|
||
* @returns {string}
|
||
* @private
|
||
*/
|
||
updateAutofillDataAttribute({ element, attributeName, dataTarget, dataTargetKey, }) {
|
||
const attributeValue = this.getPropertyOrAttribute(element, attributeName);
|
||
if (dataTarget && dataTargetKey) {
|
||
dataTarget[dataTargetKey] = attributeValue;
|
||
}
|
||
return attributeValue;
|
||
}
|
||
/**
|
||
* Sets up an IntersectionObserver to observe found form
|
||
* field elements that are not viewable in the viewport.
|
||
*/
|
||
setupIntersectionObserver() {
|
||
this.intersectionObserver = new IntersectionObserver(this.handleFormElementIntersection, {
|
||
root: null,
|
||
rootMargin: "0px",
|
||
threshold: 0.9999, // Safari doesn't seem to function properly with a threshold of 1,
|
||
});
|
||
}
|
||
/**
|
||
* Iterates over all cached field elements and sets up the inline menu listeners on each field.
|
||
*
|
||
* @param pageDetails - The page details to use for the inline menu listeners
|
||
*/
|
||
setupOverlayListeners(pageDetails) {
|
||
if (this.autofillOverlayContentService) {
|
||
this.autofillFieldElements.forEach((autofillField, formFieldElement) => {
|
||
this.setupOverlayOnField(formFieldElement, autofillField, pageDetails);
|
||
});
|
||
}
|
||
}
|
||
/**
|
||
* Sets up the inline menu listener on the passed field element.
|
||
*
|
||
* @param formFieldElement - The form field element to set up the inline menu listener on
|
||
* @param autofillField - The metadata for the form field
|
||
* @param pageDetails - The page details to use for the inline menu listeners
|
||
*/
|
||
setupOverlayOnField(formFieldElement, autofillField, pageDetails) {
|
||
if (this.autofillOverlayContentService) {
|
||
const autofillPageDetails = pageDetails ||
|
||
this.getFormattedPageDetails(this.getFormattedAutofillFormsData(), this.getFormattedAutofillFieldsData());
|
||
void this.autofillOverlayContentService.setupOverlayListeners(formFieldElement, autofillField, autofillPageDetails);
|
||
}
|
||
}
|
||
/**
|
||
* Validates whether a password field is within the document.
|
||
*/
|
||
isPasswordFieldWithinDocument() {
|
||
var _a;
|
||
return (((_a = this.domQueryService.query(globalThis.document.documentElement, `input[type="password"]`, (node) => nodeIsInputElement(node) && node.type === "password")) === null || _a === void 0 ? void 0 : _a.length) > 0);
|
||
}
|
||
/**
|
||
* Destroys the CollectAutofillContentService. Clears all
|
||
* timeouts and disconnects the mutation observer.
|
||
*/
|
||
destroy() {
|
||
var _a, _b;
|
||
if (this.updateAfterMutationIdleCallback) {
|
||
cancelIdleCallbackPolyfill(this.updateAfterMutationIdleCallback);
|
||
}
|
||
(_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
||
(_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
|
||
}
|
||
}
|
||
|
||
;// ./src/autofill/services/insert-autofill-content.service.ts
|
||
var insert_autofill_content_service_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
|
||
class InsertAutofillContentService {
|
||
/**
|
||
* InsertAutofillContentService constructor. Instantiates the
|
||
* DomElementVisibilityService and CollectAutofillContentService classes.
|
||
*/
|
||
constructor(domElementVisibilityService, collectAutofillContentService) {
|
||
this.domElementVisibilityService = domElementVisibilityService;
|
||
this.collectAutofillContentService = collectAutofillContentService;
|
||
this.autofillInsertActions = {
|
||
fill_by_opid: ({ opid, value }) => this.handleFillFieldByOpidAction(opid, value),
|
||
click_on_opid: ({ opid }) => this.handleClickOnFieldByOpidAction(opid),
|
||
focus_by_opid: ({ opid }) => this.handleFocusOnFieldByOpidAction(opid),
|
||
};
|
||
/**
|
||
* Runs the autofill action based on the action type and the opid.
|
||
* Each action is subsequently delayed by 20 milliseconds.
|
||
* @param {FillScript} [action, opid, value]
|
||
* @returns {Promise<void>}
|
||
* @private
|
||
*/
|
||
this.runFillScriptAction = ([action, opid, value]) => {
|
||
if (!opid || !this.autofillInsertActions[action]) {
|
||
return Promise.resolve();
|
||
}
|
||
const delayActionsInMilliseconds = 20;
|
||
return new Promise((resolve) => setTimeout(() => {
|
||
if (action === FillScriptActionTypes.fill_by_opid && !!(value === null || value === void 0 ? void 0 : value.length)) {
|
||
this.autofillInsertActions.fill_by_opid({ opid, value });
|
||
}
|
||
else if (action === FillScriptActionTypes.click_on_opid) {
|
||
this.autofillInsertActions.click_on_opid({ opid });
|
||
}
|
||
else if (action === FillScriptActionTypes.focus_by_opid) {
|
||
this.autofillInsertActions.focus_by_opid({ opid });
|
||
}
|
||
resolve();
|
||
}, delayActionsInMilliseconds));
|
||
};
|
||
}
|
||
/**
|
||
* Handles autofill of the forms on the current page based on the
|
||
* data within the passed fill script object.
|
||
* @param {AutofillScript} fillScript
|
||
* @returns {Promise<void>}
|
||
* @public
|
||
*/
|
||
fillForm(fillScript) {
|
||
return insert_autofill_content_service_awaiter(this, void 0, void 0, function* () {
|
||
var _a;
|
||
if (!((_a = fillScript.script) === null || _a === void 0 ? void 0 : _a.length) ||
|
||
currentlyInSandboxedIframe() ||
|
||
this.userCancelledInsecureUrlAutofill(fillScript.savedUrls) ||
|
||
this.userCancelledUntrustedIframeAutofill(fillScript)) {
|
||
return;
|
||
}
|
||
for (let index = 0; index < fillScript.script.length; index++) {
|
||
yield this.runFillScriptAction(fillScript.script[index]);
|
||
}
|
||
});
|
||
}
|
||
/**
|
||
* Checks if the autofill is occurring on a page that can be considered secure. If the page is not secure,
|
||
* the user is prompted to confirm that they want to autofill on the page.
|
||
* @param {string[] | null} savedUrls
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
userCancelledInsecureUrlAutofill(savedUrls) {
|
||
if (!(savedUrls === null || savedUrls === void 0 ? void 0 : savedUrls.some((url) => url.startsWith(`https://${globalThis.location.hostname}`))) ||
|
||
globalThis.location.protocol !== "http:" ||
|
||
!this.isPasswordFieldWithinDocument()) {
|
||
return false;
|
||
}
|
||
const confirmationWarning = [
|
||
chrome.i18n.getMessage("insecurePageWarning"),
|
||
chrome.i18n.getMessage("insecurePageWarningFillPrompt", [globalThis.location.hostname]),
|
||
].join("\n\n");
|
||
return !globalThis.confirm(confirmationWarning);
|
||
}
|
||
/**
|
||
* Checks if there is a password field within the current document. Includes
|
||
* password fields that are present within the shadow DOM.
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
isPasswordFieldWithinDocument() {
|
||
return this.collectAutofillContentService.isPasswordFieldWithinDocument();
|
||
}
|
||
/**
|
||
* Checking if the autofill is occurring within an untrusted iframe. If the page is within an untrusted iframe,
|
||
* the user is prompted to confirm that they want to autofill on the page. If the user cancels the autofill,
|
||
* the script will not continue.
|
||
*
|
||
* Note: confirm() is blocked by sandboxed iframes, but we don't want to fill sandboxed iframes anyway.
|
||
* If this occurs, confirm() returns false without displaying the dialog box, and autofill will be aborted.
|
||
* The browser may print a message to the console, but this is not a standard error that we can handle.
|
||
* @param {AutofillScript} fillScript
|
||
* @returns {boolean}
|
||
* @private
|
||
*/
|
||
userCancelledUntrustedIframeAutofill(fillScript) {
|
||
if (!fillScript.untrustedIframe) {
|
||
return false;
|
||
}
|
||
const confirmationWarning = [
|
||
chrome.i18n.getMessage("autofillIframeWarning"),
|
||
chrome.i18n.getMessage("autofillIframeWarningTip", [globalThis.location.hostname]),
|
||
].join("\n\n");
|
||
return !globalThis.confirm(confirmationWarning);
|
||
}
|
||
/**
|
||
* Queries the DOM for an element by opid and inserts the passed value into the element.
|
||
* @param {string} opid
|
||
* @param {string} value
|
||
* @private
|
||
*/
|
||
handleFillFieldByOpidAction(opid, value) {
|
||
const element = this.collectAutofillContentService.getAutofillFieldElementByOpid(opid);
|
||
this.insertValueIntoField(element, value);
|
||
}
|
||
/**
|
||
* Handles finding an element by opid and triggering a click event on the element.
|
||
* @param {string} opid
|
||
* @private
|
||
*/
|
||
handleClickOnFieldByOpidAction(opid) {
|
||
const element = this.collectAutofillContentService.getAutofillFieldElementByOpid(opid);
|
||
if (element) {
|
||
this.triggerClickOnElement(element);
|
||
}
|
||
}
|
||
/**
|
||
* Handles finding an element by opid and triggering click and focus events on the element.
|
||
* To ensure that we trigger a blur event correctly on a filled field, we first check if the
|
||
* element is already focused. If it is, we blur the element before focusing on it again.
|
||
*
|
||
* @param {string} opid - The opid of the element to focus on.
|
||
*/
|
||
handleFocusOnFieldByOpidAction(opid) {
|
||
const element = this.collectAutofillContentService.getAutofillFieldElementByOpid(opid);
|
||
if (!element) {
|
||
return;
|
||
}
|
||
if (document.activeElement === element) {
|
||
element.blur();
|
||
}
|
||
this.simulateUserMouseClickAndFocusEventInteractions(element, true);
|
||
}
|
||
/**
|
||
* Identifies the type of element passed and inserts the value into the element.
|
||
* Will trigger simulated events on the element to ensure that the element is
|
||
* properly updated.
|
||
* @param {FormFieldElement | null} element
|
||
* @param {string} value
|
||
* @private
|
||
*/
|
||
insertValueIntoField(element, value) {
|
||
if (!element || !value) {
|
||
return;
|
||
}
|
||
const elementCanBeReadonly = elementIsInputElement(element) || elementIsTextAreaElement(element);
|
||
const elementCanBeFilled = elementCanBeReadonly || elementIsSelectElement(element);
|
||
const elementValue = (element === null || element === void 0 ? void 0 : element.value) || (element === null || element === void 0 ? void 0 : element.innerText) || "";
|
||
const elementAlreadyHasTheValue = !!((elementValue === null || elementValue === void 0 ? void 0 : elementValue.length) && elementValue === value);
|
||
if (elementAlreadyHasTheValue ||
|
||
(elementCanBeReadonly && element.readOnly) ||
|
||
(elementCanBeFilled && element.disabled)) {
|
||
return;
|
||
}
|
||
if (!elementIsFillableFormField(element)) {
|
||
this.handleInsertValueAndTriggerSimulatedEvents(element, () => (element.innerText = value));
|
||
return;
|
||
}
|
||
const isFillableCheckboxOrRadioElement = elementIsInputElement(element) &&
|
||
new Set(["checkbox", "radio"]).has(element.type) &&
|
||
new Set(["true", "y", "1", "yes", "✓"]).has(String(value).toLowerCase());
|
||
if (isFillableCheckboxOrRadioElement) {
|
||
this.handleInsertValueAndTriggerSimulatedEvents(element, () => (element.checked = true));
|
||
return;
|
||
}
|
||
this.handleInsertValueAndTriggerSimulatedEvents(element, () => (element.value = value));
|
||
}
|
||
/**
|
||
* Simulates pre- and post-insert events on the element meant to mimic user interactions
|
||
* while inserting the autofill value into the element.
|
||
* @param {FormFieldElement} element
|
||
* @param {Function} valueChangeCallback
|
||
* @private
|
||
*/
|
||
handleInsertValueAndTriggerSimulatedEvents(element, valueChangeCallback) {
|
||
this.triggerPreInsertEventsOnElement(element);
|
||
valueChangeCallback();
|
||
this.triggerPostInsertEventsOnElement(element);
|
||
this.triggerFillAnimationOnElement(element);
|
||
}
|
||
/**
|
||
* Simulates a mouse click event on the element, including focusing the event, and
|
||
* the triggers a simulated keyboard event on the element. Will attempt to ensure
|
||
* that the initial element value is not arbitrarily changed by the simulated events.
|
||
* @param {FormFieldElement} element
|
||
* @private
|
||
*/
|
||
triggerPreInsertEventsOnElement(element) {
|
||
const initialElementValue = "value" in element ? element.value : "";
|
||
this.simulateUserMouseClickAndFocusEventInteractions(element);
|
||
this.simulateUserKeyboardEventInteractions(element);
|
||
if ("value" in element && initialElementValue !== element.value) {
|
||
element.value = initialElementValue;
|
||
}
|
||
}
|
||
/**
|
||
* Simulates a keyboard event on the element before assigning the autofilled value to the element, and then
|
||
* simulates an input change event on the element to trigger expected events after autofill occurs.
|
||
* @param {FormFieldElement} element
|
||
* @private
|
||
*/
|
||
triggerPostInsertEventsOnElement(element) {
|
||
const autofilledValue = "value" in element ? element.value : "";
|
||
this.simulateUserKeyboardEventInteractions(element);
|
||
if ("value" in element && autofilledValue !== element.value) {
|
||
element.value = autofilledValue;
|
||
}
|
||
this.simulateInputElementChangedEvent(element);
|
||
}
|
||
/**
|
||
* Identifies if a passed element can be animated and sets a class on the element
|
||
* to trigger a CSS animation. The animation is removed after a short delay.
|
||
* @param {FormFieldElement} element
|
||
* @private
|
||
*/
|
||
triggerFillAnimationOnElement(element) {
|
||
const skipAnimatingElement = elementIsFillableFormField(element) &&
|
||
!new Set(["email", "text", "password", "number", "tel", "url"]).has(element === null || element === void 0 ? void 0 : element.type);
|
||
if (this.domElementVisibilityService.isElementHiddenByCss(element) || skipAnimatingElement) {
|
||
return;
|
||
}
|
||
element.classList.add("com-bitwarden-browser-animated-fill");
|
||
setTimeout(() => element.classList.remove("com-bitwarden-browser-animated-fill"), 200);
|
||
}
|
||
/**
|
||
* Simulates a click event on the element.
|
||
* @param {HTMLElement} element
|
||
* @private
|
||
*/
|
||
triggerClickOnElement(element) {
|
||
if (!element || typeof element.click !== TYPE_CHECK.FUNCTION) {
|
||
return;
|
||
}
|
||
element.click();
|
||
}
|
||
/**
|
||
* Simulates a focus event on the element. Will optionally reset the value of the element
|
||
* if the element has a value property.
|
||
* @param {HTMLElement | undefined} element
|
||
* @param {boolean} shouldResetValue
|
||
* @private
|
||
*/
|
||
triggerFocusOnElement(element, shouldResetValue = false) {
|
||
if (!element || typeof element.focus !== TYPE_CHECK.FUNCTION) {
|
||
return;
|
||
}
|
||
let initialValue = "";
|
||
if (shouldResetValue && "value" in element) {
|
||
initialValue = String(element.value);
|
||
}
|
||
element.focus();
|
||
if (initialValue && "value" in element) {
|
||
element.value = initialValue;
|
||
}
|
||
}
|
||
/**
|
||
* Simulates a mouse click and focus event on the element.
|
||
* @param {FormFieldElement} element
|
||
* @param {boolean} shouldResetValue
|
||
* @private
|
||
*/
|
||
simulateUserMouseClickAndFocusEventInteractions(element, shouldResetValue = false) {
|
||
this.triggerClickOnElement(element);
|
||
this.triggerFocusOnElement(element, shouldResetValue);
|
||
}
|
||
/**
|
||
* Simulates several keyboard events on the element, mocking a user interaction with the element.
|
||
* @param {FormFieldElement} element
|
||
* @private
|
||
*/
|
||
simulateUserKeyboardEventInteractions(element) {
|
||
const simulatedKeyboardEvents = [EVENTS.KEYDOWN, EVENTS.KEYUP];
|
||
for (let index = 0; index < simulatedKeyboardEvents.length; index++) {
|
||
element.dispatchEvent(new KeyboardEvent(simulatedKeyboardEvents[index], { bubbles: true }));
|
||
}
|
||
}
|
||
/**
|
||
* Simulates an input change event on the element, mocking behavior that would occur if a user
|
||
* manually changed a value for the element.
|
||
* @param {FormFieldElement} element
|
||
* @private
|
||
*/
|
||
simulateInputElementChangedEvent(element) {
|
||
const simulatedInputEvents = [EVENTS.INPUT, EVENTS.CHANGE];
|
||
for (let index = 0; index < simulatedInputEvents.length; index++) {
|
||
element.dispatchEvent(new Event(simulatedInputEvents[index], { bubbles: true }));
|
||
}
|
||
}
|
||
}
|
||
/* harmony default export */ var insert_autofill_content_service = (InsertAutofillContentService);
|
||
|
||
;// ./src/autofill/content/autofill-init.ts
|
||
var autofill_init_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
};
|
||
|
||
|
||
|
||
|
||
class AutofillInit {
|
||
/**
|
||
* AutofillInit constructor. Initializes the DomElementVisibilityService,
|
||
* CollectAutofillContentService and InsertAutofillContentService classes.
|
||
*
|
||
* @param domQueryService - Service used to handle DOM queries.
|
||
* @param domElementVisibilityService - Used to check if an element is viewable.
|
||
* @param autofillOverlayContentService - The autofill overlay content service, potentially undefined.
|
||
* @param autofillInlineMenuContentService - The inline menu content service, potentially undefined.
|
||
* @param overlayNotificationsContentService - The overlay notifications content service, potentially undefined.
|
||
*/
|
||
constructor(domQueryService, domElementVisibilityService, autofillOverlayContentService, autofillInlineMenuContentService, overlayNotificationsContentService) {
|
||
this.autofillOverlayContentService = autofillOverlayContentService;
|
||
this.autofillInlineMenuContentService = autofillInlineMenuContentService;
|
||
this.overlayNotificationsContentService = overlayNotificationsContentService;
|
||
this.sendExtensionMessage = sendExtensionMessage;
|
||
this.extensionMessageHandlers = {
|
||
collectPageDetails: ({ message }) => this.collectPageDetails(message),
|
||
collectPageDetailsImmediately: ({ message }) => this.collectPageDetails(message, true),
|
||
fillForm: ({ message }) => this.fillForm(message),
|
||
};
|
||
/**
|
||
* Handles the extension messages sent to the content script.
|
||
*
|
||
* @param message - The extension message.
|
||
* @param sender - The message sender.
|
||
* @param sendResponse - The send response callback.
|
||
*/
|
||
this.handleExtensionMessage = (message, sender, sendResponse) => {
|
||
const command = message.command;
|
||
const handler = this.getExtensionMessageHandler(command);
|
||
if (!handler) {
|
||
return null;
|
||
}
|
||
const messageResponse = handler({ message, sender });
|
||
if (typeof messageResponse === "undefined") {
|
||
return null;
|
||
}
|
||
void Promise.resolve(messageResponse).then((response) => sendResponse(response));
|
||
return true;
|
||
};
|
||
this.collectAutofillContentService = new CollectAutofillContentService(domElementVisibilityService, domQueryService, this.autofillOverlayContentService);
|
||
this.insertAutofillContentService = new insert_autofill_content_service(domElementVisibilityService, this.collectAutofillContentService);
|
||
}
|
||
/**
|
||
* Initializes the autofill content script, setting up
|
||
* the extension message listeners. This method should
|
||
* be called once when the content script is loaded.
|
||
*/
|
||
init() {
|
||
var _a;
|
||
this.setupExtensionMessageListeners();
|
||
(_a = this.autofillOverlayContentService) === null || _a === void 0 ? void 0 : _a.init();
|
||
this.collectPageDetailsOnLoad();
|
||
}
|
||
/**
|
||
* Triggers a collection of the page details from the
|
||
* background script, ensuring that autofill is ready
|
||
* to act on the page.
|
||
*/
|
||
collectPageDetailsOnLoad() {
|
||
const sendCollectDetailsMessage = () => {
|
||
this.clearCollectPageDetailsOnLoadTimeout();
|
||
this.collectPageDetailsOnLoadTimeout = setTimeout(() => this.sendExtensionMessage("bgCollectPageDetails", { sender: "autofillInit" }), 750);
|
||
};
|
||
if (globalThis.document.readyState === "complete") {
|
||
sendCollectDetailsMessage();
|
||
}
|
||
globalThis.addEventListener(EVENTS.LOAD, sendCollectDetailsMessage);
|
||
}
|
||
/**
|
||
* Collects the page details and sends them to the
|
||
* extension background script. If the `sendDetailsInResponse`
|
||
* parameter is set to true, the page details will be
|
||
* returned to facilitate sending the details in the
|
||
* response to the extension message.
|
||
*
|
||
* @param message - The extension message.
|
||
* @param sendDetailsInResponse - Determines whether to send the details in the response.
|
||
*/
|
||
collectPageDetails(message_1) {
|
||
return autofill_init_awaiter(this, arguments, void 0, function* (message, sendDetailsInResponse = false) {
|
||
const pageDetails = yield this.collectAutofillContentService.getPageDetails();
|
||
if (sendDetailsInResponse) {
|
||
return pageDetails;
|
||
}
|
||
void this.sendExtensionMessage("collectPageDetailsResponse", {
|
||
tab: message.tab,
|
||
details: pageDetails,
|
||
sender: message.sender,
|
||
});
|
||
});
|
||
}
|
||
/**
|
||
* Fills the form with the given fill script.
|
||
*
|
||
* @param {AutofillExtensionMessage} message
|
||
*/
|
||
fillForm(_a) {
|
||
return autofill_init_awaiter(this, arguments, void 0, function* ({ fillScript, pageDetailsUrl }) {
|
||
if ((document.defaultView || window).location.href !== pageDetailsUrl || !fillScript) {
|
||
return;
|
||
}
|
||
this.blurFocusedFieldAndCloseInlineMenu();
|
||
yield this.sendExtensionMessage("updateIsFieldCurrentlyFilling", {
|
||
isFieldCurrentlyFilling: true,
|
||
});
|
||
yield this.insertAutofillContentService.fillForm(fillScript);
|
||
setTimeout(() => this.sendExtensionMessage("updateIsFieldCurrentlyFilling", {
|
||
isFieldCurrentlyFilling: false,
|
||
}), 250);
|
||
});
|
||
}
|
||
/**
|
||
* Blurs the most recently focused field and removes the inline menu. Used
|
||
* in cases where the background unlock or vault item reprompt popout
|
||
* is opened.
|
||
*/
|
||
blurFocusedFieldAndCloseInlineMenu() {
|
||
var _a;
|
||
(_a = this.autofillOverlayContentService) === null || _a === void 0 ? void 0 : _a.blurMostRecentlyFocusedField(true);
|
||
}
|
||
/**
|
||
* Clears the send collect details message timeout.
|
||
*/
|
||
clearCollectPageDetailsOnLoadTimeout() {
|
||
if (this.collectPageDetailsOnLoadTimeout) {
|
||
clearTimeout(this.collectPageDetailsOnLoadTimeout);
|
||
}
|
||
}
|
||
/**
|
||
* Sets up the extension message listeners for the content script.
|
||
*/
|
||
setupExtensionMessageListeners() {
|
||
chrome.runtime.onMessage.addListener(this.handleExtensionMessage);
|
||
}
|
||
/**
|
||
* Gets the extension message handler for the given command.
|
||
*
|
||
* @param command - The extension message command.
|
||
*/
|
||
getExtensionMessageHandler(command) {
|
||
var _a, _b, _c, _d, _e, _f;
|
||
if ((_b = (_a = this.autofillOverlayContentService) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b[command]) {
|
||
return this.autofillOverlayContentService.messageHandlers[command];
|
||
}
|
||
if ((_d = (_c = this.autofillInlineMenuContentService) === null || _c === void 0 ? void 0 : _c.messageHandlers) === null || _d === void 0 ? void 0 : _d[command]) {
|
||
return this.autofillInlineMenuContentService.messageHandlers[command];
|
||
}
|
||
if ((_f = (_e = this.overlayNotificationsContentService) === null || _e === void 0 ? void 0 : _e.messageHandlers) === null || _f === void 0 ? void 0 : _f[command]) {
|
||
return this.overlayNotificationsContentService.messageHandlers[command];
|
||
}
|
||
return this.extensionMessageHandlers[command];
|
||
}
|
||
/**
|
||
* Handles destroying the autofill init content script. Removes all
|
||
* listeners, timeouts, and object instances to prevent memory leaks.
|
||
*/
|
||
destroy() {
|
||
var _a, _b, _c;
|
||
this.clearCollectPageDetailsOnLoadTimeout();
|
||
chrome.runtime.onMessage.removeListener(this.handleExtensionMessage);
|
||
this.collectAutofillContentService.destroy();
|
||
(_a = this.autofillOverlayContentService) === null || _a === void 0 ? void 0 : _a.destroy();
|
||
(_b = this.autofillInlineMenuContentService) === null || _b === void 0 ? void 0 : _b.destroy();
|
||
(_c = this.overlayNotificationsContentService) === null || _c === void 0 ? void 0 : _c.destroy();
|
||
}
|
||
}
|
||
/* harmony default export */ var autofill_init = (AutofillInit);
|
||
|
||
;// ./src/autofill/content/bootstrap-autofill-overlay-notifications.ts
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
(function (windowContext) {
|
||
if (!windowContext.bitwardenAutofillInit) {
|
||
const domQueryService = new DomQueryService();
|
||
const domElementVisibilityService = new dom_element_visibility_service();
|
||
const inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();
|
||
const autofillOverlayContentService = new AutofillOverlayContentService(domQueryService, domElementVisibilityService, inlineMenuFieldQualificationService);
|
||
let overlayNotificationsContentService;
|
||
if (globalThis.self === globalThis.top) {
|
||
overlayNotificationsContentService = new OverlayNotificationsContentService();
|
||
}
|
||
windowContext.bitwardenAutofillInit = new autofill_init(domQueryService, domElementVisibilityService, autofillOverlayContentService, undefined, overlayNotificationsContentService);
|
||
setupAutofillInitDisconnectAction(windowContext);
|
||
windowContext.bitwardenAutofillInit.init();
|
||
}
|
||
})(window);
|
||
|
||
}();
|
||
/******/ })()
|
||
; |