extension-background.js 55 KB

1
  1. !function(){"use strict";async function e(t,a){let n;try{n=await browser.downloads.download(t)}catch(n){if(n.message){const o=n.message.toLowerCase(),r=o.includes("illegal characters")||o.includes("invalid filename");if(r&&t.filename.startsWith("."))return t.filename=a+t.filename,e(t,a);if(r&&t.filename.includes(","))return t.filename=t.filename.replace(/,/g,a),e(t,a);if(r&&!t.filename.match(/^[\x00-\x7F]+$/))return t.filename=t.filename.replace(/[^\x00-\x7F]+/g,a),e(t,a);if((o.includes("'incognito'")||o.includes('"incognito"'))&&t.incognito)return delete t.incognito,e(t,a);if("conflictaction prompt not yet implemented"==o&&t.conflictAction)return delete t.conflictAction,e(t,a);if(o.includes("canceled"))return{};throw n}throw n}return new Promise(((e,t)=>{browser.downloads.onChanged.addListener((function a(o){o.id==n&&o.state&&("complete"==o.state.current&&(browser.downloads.search({id:n}).then((t=>e({filename:t[0]&&t[0].filename}))).catch((()=>e({}))),browser.downloads.onChanged.removeListener(a)),"interrupted"==o.state.current&&(o.error&&"USER_CANCELED"==o.error.current?e({}):t(new Error(o.state.current)),browser.downloads.onChanged.removeListener(a)))}))}))}let t,a,n;async function o(e){a&&delete a[e];const t=await s();if(t[e]){const a=t[e].autoSave;t[e]={autoSave:a},await i(t)}}function r(e){return a||(a={}),void 0===e||a[e]||(a[e]={}),a}async function s(e){if(!t){const e=await browser.storage.local.get();t=e.tabsData||{}}return async function(){if(!n){n=!0;const e=await browser.tabs.query({currentWindow:!0,highlighted:!0});Object.keys(t).filter((t=>{if("autoSaveAll"!=t&&"autoSaveUnpinned"!=t&&"profileName"!=t)return!e.find((e=>e.id==t))})).forEach((e=>delete t[e])),await browser.storage.local.set({tabsData:t})}}(),void 0===e||t[e]||(t[e]={}),t}async function i(e){t=e,await browser.storage.local.set({tabsData:e})}setTimeout((()=>s().then((e=>t=e))),0);const c="-",l="__Default_Settings__",d="__Disabled_Settings__",u="regexp:",f={removeHiddenElements:!0,removeUnusedStyles:!0,removeUnusedFonts:!0,removeFrames:!1,removeImports:!0,compressHTML:!0,compressCSS:!1,loadDeferredImages:!0,loadDeferredImagesMaxIdleTime:1500,loadDeferredImagesBlockCookies:!1,loadDeferredImagesBlockStorage:!1,loadDeferredImagesKeepZoomLevel:!1,filenameTemplate:"{page-title} ({date-locale} {time-locale}).html",infobarTemplate:"",includeInfobar:!1,confirmInfobarContent:!1,autoClose:!1,confirmFilename:!1,filenameConflictAction:"uniquify",filenameMaxLength:192,filenameMaxLengthUnit:"bytes",filenameReplacedCharacters:["~","+","\\\\","?","%","*",":","|",'"',"<",">","\0-",""],filenameReplacementCharacter:"_",contextMenuEnabled:!0,tabMenuEnabled:!0,browserActionMenuEnabled:!0,shadowEnabled:!0,logsEnabled:!0,progressBarEnabled:!0,maxResourceSizeEnabled:!1,maxResourceSize:10,displayInfobar:!0,displayStats:!1,backgroundSave:!/Mobile.*Firefox/.test(navigator.userAgent),defaultEditorMode:"normal",applySystemTheme:!0,autoSaveDelay:1,autoSaveLoad:!1,autoSaveUnload:!1,autoSaveLoadOrUnload:!0,autoSaveDiscard:!1,autoSaveRemove:!1,autoSaveRepeat:!1,autoSaveRepeatDelay:10,removeAlternativeFonts:!0,removeAlternativeMedias:!0,removeAlternativeImages:!0,groupDuplicateImages:!0,saveRawPage:!1,saveToClipboard:!1,addProof:!1,saveToGDrive:!1,saveToGitHub:!1,githubToken:"",githubUser:"",githubRepository:"SingleFile-Archives",githubBranch:"main",saveWithCompanion:!1,forceWebAuthFlow:!1,resolveFragmentIdentifierURLs:!1,userScriptEnabled:!1,openEditor:!1,openSavedPage:!1,autoOpenEditor:!1,saveCreatedBookmarks:!1,allowedBookmarkFolders:[],ignoredBookmarkFolders:[],replaceBookmarkURL:!0,saveFavicon:!0,includeBOM:!1,warnUnsavedPage:!0,autoSaveExternalSave:!1,insertMetaNoIndex:!1,insertMetaCSP:!0,passReferrerOnError:!1,insertSingleFileComment:!0,blockMixedContent:!1,saveOriginalURLs:!1,acceptHeaders:{font:"application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8",image:"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",stylesheet:"text/css,*/*;q=0.1",script:"*/*",document:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",video:"video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5",audio:"audio/webm,audio/ogg,audio/wav,audio/*;q=0.9,application/ogg;q=0.7,video/*;q=0.6,*/*;q=0.5"},moveStylesInHead:!1,networkTimeout:0,woleetKey:"",blockImages:!1,blockStylesheets:!1,blockFont:!1,blockScripts:!0,blockVideos:!0,blockAudios:!0},h=[{url:"file:",profile:"__Default_Settings__",autoSaveProfile:"__Disabled_Settings__"}];let m,w=b();async function b(){const{sync:e}=await browser.storage.local.get();m=e?browser.storage.sync:browser.storage.local;const t=await m.get();if(t.profiles)t.rules||(t.rules=h),Object.keys(t.profiles).forEach((e=>p(t.profiles[e]))),await m.remove(["profiles","rules"]),await m.set({profiles:t.profiles,rules:t.rules});else{const e=t;delete e.tabsData,p(e);const a={profiles:{},rules:h};a.profiles.__Default_Settings__=e,m.remove(Object.keys(f)),await m.set(a)}t.maxParallelWorkers||await m.set({maxParallelWorkers:navigator.hardwareConcurrency||4})}function p(e){g(e,"removeScripts","blockScripts"),g(e,"removeVideoSrc","blockVideos"),g(e,"removeAudioSrc","blockAudios"),Object.keys(f).forEach((t=>function(e,t){void 0===e[t]&&(e[t]=f[t])}(e,t)))}function g(e,t,a){void 0===e[t]&&void 0!==e[a]&&(e[t]=e[a],delete e[a])}async function y(e,t){const a=await v(),n=a.rules.filter((e=>I(e)));let o=n.sort(k).find((t=>e&&e.match(new RegExp(t.url.split(u)[1]))));if(!o){const n=a.rules.filter((e=>!I(e)));o=n.sort(k).find((a=>!t&&"*"==a.url||e&&e.includes(a.url)))}return o}async function v(){return await w,m.get(["profiles","rules","maxParallelWorkers"])}function k(e,t){return t.url.length-e.url.length}function I(e){return e.url.toLowerCase().startsWith(u)}async function x(t){if(t.method.endsWith(".deleteRules")&&await async function(e){const t=await v();t.rules=t.rules=e?t.rules.filter((t=>t.autoSaveProfile!=e&&t.profile!=e)):[],await m.set({rules:t.rules})}(t.profileName),t.method.endsWith(".deleteRule")&&await async function(e){if(!e)throw new Error("URL is empty");const t=await v();t.rules=t.rules.filter((t=>t.url!=e)),await m.set({rules:t.rules})}(t.url),t.method.endsWith(".addRule")&&await E(t.url,t.profileName,t.autoSaveProfileName),t.method.endsWith(".createProfile")&&await async function(e,t){const a=await v();if(Object.keys(a.profiles).includes(e))throw new Error("Duplicate profile name");a.profiles[e]=JSON.parse(JSON.stringify(a.profiles[t])),await m.set({profiles:a.profiles})}(t.profileName,t.fromProfileName||l),t.method.endsWith(".renameProfile")&&await async function(e,t){const[a,n]=await Promise.all([v(),s()]);if(!Object.keys(a.profiles).includes(e))throw new Error("Profile not found");if(Object.keys(a.profiles).includes(t))throw new Error("Duplicate profile name");if(e==l)throw new Error("Default settings cannot be renamed");n.profileName==e&&(n.profileName=t,await i(n));a.profiles[t]=a.profiles[e],a.rules.forEach((a=>{a.profile==e&&(a.profile=t),a.autoSaveProfile==e&&(a.autoSaveProfile=t)})),delete a.profiles[e],await m.set({profiles:a.profiles,rules:a.rules})}(t.profileName,t.newProfileName),t.method.endsWith(".deleteProfile")&&await async function(e){const[t,a]=await Promise.all([v(),s()]);if(!Object.keys(t.profiles).includes(e))throw new Error("Profile not found");if(e==l)throw new Error("Default settings cannot be deleted");a.profileName==e&&(delete a.profileName,await i(a));t.rules.forEach((t=>{t.profile==e&&(t.profile=l),t.autoSaveProfile==e&&(t.autoSaveProfile=l)})),delete t.profiles[e],await m.set({profiles:t.profiles,rules:t.rules})}(t.profileName),t.method.endsWith(".resetProfiles")&&await async function(){await w;const e=await s();delete e.profileName,await i(e),await m.remove(["profiles","rules","maxParallelWorkers"]),await browser.storage.local.set({sync:!1}),m=browser.storage.local,await b()}(),t.method.endsWith(".resetProfile")&&await async function(e){const t=await v();if(!Object.keys(t.profiles).includes(e))throw new Error("Profile not found");t.profiles[e]=f,await m.set({profiles:t.profiles})}(t.profileName),t.method.endsWith(".importConfig")&&await async function(e){await m.remove(["profiles","rules","maxParallelWorkers"]),await m.set({profiles:e.profiles,rules:e.rules,maxParallelWorkers:e.maxParallelWorkers}),await b()}(t.config),t.method.endsWith(".updateProfile")&&await async function(e,t){const a=await v();if(!Object.keys(a.profiles).includes(e))throw new Error("Profile not found");Object.keys(t).forEach((n=>a.profiles[e][n]=t[n])),await m.set({profiles:a.profiles})}(t.profileName,t.profile),t.method.endsWith(".updateRule")&&await P(t.url,t.newUrl,t.profileName,t.autoSaveProfileName),t.method.endsWith(".getConstants"))return{DISABLED_PROFILE_NAME:d,DEFAULT_PROFILE_NAME:l,CURRENT_PROFILE_NAME:c};if(t.method.endsWith(".getRules"))return async function(){return(await v()).rules}();if(t.method.endsWith(".getProfiles"))return S();if(t.method.endsWith(".exportConfig"))return async function(){const t=await v(),a=URL.createObjectURL(new Blob([JSON.stringify({profiles:t.profiles,rules:t.rules,maxParallelWorkers:t.maxParallelWorkers},null,2)],{type:"text/json"})),n={url:a,filename:`singlefile-settings-${(new Date).toISOString().replace(/:/g,"_")}.json`,saveAs:!0};try{await e(n,"_")}finally{URL.revokeObjectURL(a)}}();if(t.method.endsWith(".enableSync")){await browser.storage.local.set({sync:!0});const e=await browser.storage.sync.get();if(!e||!e.profiles){const e=await browser.storage.local.get();await browser.storage.sync.set({profiles:e.profiles,rules:e.rules,maxParallelWorkers:e.maxParallelWorkers})}return m=browser.storage.sync,{}}if(t.method.endsWith(".disableSync")){await browser.storage.local.set({sync:!1});const e=await browser.storage.sync.get();e&&e.profiles&&await browser.storage.local.set({profiles:e.profiles,rules:e.rules,maxParallelWorkers:e.maxParallelWorkers}),m=browser.storage.local}return t.method.endsWith(".isSync")?{sync:(await browser.storage.local.get()).sync}:{}}async function S(){return(await v()).profiles}async function T(e,t){const[a,n,o]=await Promise.all([v(),y(e),s()]),r=o.profileName||l;let i;if(n){const e=n[t?"autoSaveProfile":"profile"];i=e==c?r:e}else i=r;return Object.assign({profileName:i},a.profiles[i])}async function E(e,t,a){if(!e)throw new Error("URL is empty");const n=await v();if(n.rules.find((t=>t.url==e)))throw new Error("URL already exists");n.rules.push({url:e,profile:t,autoSaveProfile:a}),await m.set({rules:n.rules})}async function P(e,t,a,n){if(!e||!t)throw new Error("URL is empty");const o=await v(),r=o.rules.find((t=>t.url==e));if(!r)throw new Error("URL not found");if(o.rules.find((a=>a.url==t&&a.url!=e)))throw new Error("New URL already exists");r.url=t,r.profile=a,r.autoSaveProfile=n,await m.set({rules:o.rules})}async function M(){return(await m.get()).authInfo}async function L(e){await m.set({authInfo:e})}async function W(){let e=M();e.revokableAccessToken?L({revokableAccessToken:e.revokableAccessToken}):await m.remove(["authInfo"])}async function R(e){if(e){const[t,a]=await Promise.all([s(),y(e.url)]);return Boolean(t.autoSaveAll||t.autoSaveUnpinned&&!e.pinned||t[e.id]&&t[e.id].autoSave)&&(!a||a.autoSaveProfile!=d)}}const A=33554432,C="/src/extension/ui/pages/editor.html",U=new Map,_=new Map,B=browser.runtime.getURL(C);function D(e){return e.url==B}const O=new Map,j="x-single-file-request-id",N=8388608;async function q(e,t,a){for(let n=0;n*N<=a.array.length;n++){const o={method:"singlefile.fetchResponse",requestId:t,headers:a.headers,status:a.status,error:a.error};o.truncated=a.array.length>N,o.truncated?(o.finished=(n+1)*N>a.array.length,o.array=a.array.slice(n*N,(n+1)*N)):o.array=a.array,await browser.tabs.sendMessage(e,o)}return{}}function F(e,t={},a){return new Promise(((n,o)=>{const r=new XMLHttpRequest;if(r.withCredentials=!0,r.responseType="arraybuffer",r.onerror=e=>o(new Error(e.detail)),r.onreadystatechange=()=>{r.readyState==XMLHttpRequest.DONE&&(r.status||r.response.byteLength?401!=r.status&&403!=r.status&&404!=r.status||a?n({array:Array.from(new Uint8Array(r.response)),headers:{"content-type":r.getResponseHeader("Content-Type")},status:r.status}):F(e,t,!0).then(n).catch(o):o())},r.open("GET",e,!0),t.headers)for(const e of Object.entries(t.headers))r.setRequestHeader(e[0],e[1]);if(a){const e=String(Math.random()).substring(2);!function(e,t){O.set(e,t)}(e,t.referrer),r.setRequestHeader(j,e)}r.send()}))}browser.runtime.onMessage.addListener(((e,t)=>{if(e.method&&e.method.startsWith("singlefile.fetch"))return new Promise((a=>{(async function(e,t){if("singlefile.fetch"==e.method)try{const a=await F(e.url,{referrer:e.referrer,headers:e.headers});return q(t.tab.id,e.requestId,a)}catch(a){return q(t.tab.id,e.requestId,{error:a.message,arrray:[]})}else if("singlefile.fetchFrame"==e.method)return browser.tabs.sendMessage(t.tab.id,e)})(e,t).then(a).catch((e=>a({error:e&&e.toString()})))}))}));let z=!1;function H(e){return e.method.endsWith(".enableReferrerOnError")?(G(),{}):e.method.endsWith(".disableReferrerOnError")?(function(){try{browser.webRequest.onBeforeSendHeaders.removeListener(J)}catch(e){}z=!1}(),{}):void 0}function J(e){if(z){let t=e.requestHeaders.find((e=>e.name===j));if(t){e.requestHeaders=e.requestHeaders.filter((e=>e.name!==j));const a=O.get(t.value);if(a){O.delete(t.value);if(!e.requestHeaders.find((e=>"referer"===e.name.toLowerCase())))return e.requestHeaders.push({name:"Referer",value:a}),{requestHeaders:e.requestHeaders}}}}}function G(){if(!z){try{browser.webRequest.onBeforeSendHeaders.addListener(J,{urls:["<all_urls>"]},["blocking","requestHeaders","extraHeaders"])}catch(e){browser.webRequest.onBeforeSendHeaders.addListener(J,{urls:["<all_urls>"]},["blocking","requestHeaders"])}z=!0}}async function K(e){return(await browser.tabs.query(e)).sort(((e,t)=>e.index-t.index))}const $="/src/extension/ui/resources/icon_128.png",V="/src/extension/ui/resources/icon_128_wait",X=browser.i18n.getMessage("buttonDefaultTooltip"),Y=browser.i18n.getMessage("buttonBlockedTooltip"),Z=browser.i18n.getMessage("buttonInitializingBadge"),Q=browser.i18n.getMessage("buttonInitializingTooltip"),ee=browser.i18n.getMessage("buttonErrorBadge"),te=browser.i18n.getMessage("buttonBlockedBadge"),ae=browser.i18n.getMessage("buttonOKBadge"),ne=browser.i18n.getMessage("buttonSaveProgressTooltip"),oe=browser.i18n.getMessage("buttonUploadProgressTooltip"),re=browser.i18n.getMessage("buttonAutoSaveActiveBadge"),se=browser.i18n.getMessage("buttonAutoSaveActiveTooltip"),ie=[2,147,20,192],ce=[4,229,36,192],le={default:{setBadgeBackgroundColor:{color:ie},setBadgeText:{text:""},setTitle:{title:X},setIcon:{path:$}},inject:{setBadgeBackgroundColor:{color:ie},setBadgeText:{text:Z},setTitle:{title:Q}},execute:{setBadgeBackgroundColor:{color:ce},setBadgeText:{text:Z}},progress:{setBadgeBackgroundColor:{color:ce},setBadgeText:{text:""}},edit:{setBadgeBackgroundColor:{color:ie},setBadgeText:{text:""},setTitle:{title:X},setIcon:{path:$}},end:{setBadgeBackgroundColor:{color:ce},setBadgeText:{text:ae},setTitle:{title:X},setIcon:{path:$}},error:{setBadgeBackgroundColor:{color:[229,4,12,192]},setBadgeText:{text:ee},setTitle:{title:""},setIcon:{path:$}},forbidden:{setBadgeBackgroundColor:{color:[255,255,255,1]},setBadgeText:{text:te},setTitle:{title:Y},setIcon:{path:$}},autosave:{inject:{setBadgeBackgroundColor:{color:[64,64,64,192]},setBadgeText:{text:re},setTitle:{title:se},setIcon:{path:$}},default:{setBadgeBackgroundColor:{color:[208,208,208,192]},setBadgeText:{text:re},setTitle:{title:se},setIcon:{path:$}}}};let de;function ue(e,t){if(e.method.endsWith(".processInit")){delete r(t.tab.id)[t.tab.id].button,be(t.tab)}var a,n,o;return e.method.endsWith(".processProgress")&&e.maxIndex&&(a=t.tab.id,n=e.index,o=e.maxIndex,we(a,n,o,ne)),e.method.endsWith(".processEnd")&&he(t.tab.id),e.method.endsWith(".processError")&&(e.error&&console.error("Initialization error",e.error),fe(t.tab.id)),e.method.endsWith(".processCancelled")&&me(t.tab),Promise.resolve({})}function fe(e){pe(e,ye("error"))}function he(e,t){pe(e,t?ye("default",!0):ye("end"))}function me(e){be(e)}function we(e,t,a,n){const o=Math.max(Math.min(20,Math.floor(t/a*20)),0),r=Math.min(Math.floor(t/a*8),8),s=V+r+".png",i=ye("progress");i.setTitle={title:n+5*o+"%"},i.setIcon={path:s},pe(e,i)}async function be(e){const t=ye("default",await R(e));await pe(e.id,t)}async function pe(e,t){const a=r(e);if(t){a[e].button||(a[e].button={lastState:null});const n=a[e].button.lastState||{},o={};Object.keys(t).forEach((e=>{void 0!==t[e]&&JSON.stringify(n[e])!=JSON.stringify(t[e])&&(o[e]=t[e])})),Object.keys(o).length&&(a[e].button.lastState=t,await async function(e,t){for(const a of Object.keys(t))await ge(e,a,t[a])}(e,o))}}async function ge(e,t,a){if(browser.browserAction[t]){const n=JSON.parse(JSON.stringify(a));n.tabId=e,await browser.browserAction[t](n)}}function ye(e,t){return JSON.parse(JSON.stringify(t?le.autosave[e]:le[e]))}browser.browserAction.onClicked.addListener((async e=>{const t=await K({currentWindow:!0,highlighted:!0});t.length<=1?function(e){de.isSavingTab(e)?de.cancelTab(e.id):de.saveTabs([e])}(e):de.saveTabs(t)}));const ve=browser.menus,ke=ve&&ve.onClicked&&ve.create&&ve.update&&ve.removeAll,Ie="save-page",xe="edit-and-save-page",Se="save-with-profile",Te="save-selected-links",Ee="view-pendings",Pe="select-profile",Me="wasve-with-profile-",Le="select-profile-",We="associate-with-profile",Re="associate-with-profile-",Ae="save-selected",Ce="save-frame",Ue="save-tabs",_e="save-selected-tabs",Be="save-unpinned-tabs",De="save-all-tabs",Oe="batch-save-urls",je="button-save-selected-tabs",Ne="button-save-unpinned-tabs",qe="button-save-all-tabs",Fe="auto-save",ze="auto-save-disabled",He="auto-save-tab",Je="auto-save-unpinned",Ge="auto-save-all",Ke=browser.i18n.getMessage("menuCreateDomainRule"),$e=browser.i18n.getMessage("menuUpdateRule"),Ve=browser.i18n.getMessage("menuSavePage"),Xe=browser.i18n.getMessage("menuSaveWithProfile"),Ye=browser.i18n.getMessage("menuSaveSelectedLinks"),Ze=browser.i18n.getMessage("menuEditPage"),Qe=browser.i18n.getMessage("menuEditAndSavePage"),et=browser.i18n.getMessage("menuViewPendingSaves"),tt=browser.i18n.getMessage("menuSaveSelection"),at=browser.i18n.getMessage("menuSaveFrame"),nt=browser.i18n.getMessage("menuSaveTabs"),ot=browser.i18n.getMessage("menuSaveSelectedTabs"),rt=browser.i18n.getMessage("menuSaveUnpinnedTabs"),st=browser.i18n.getMessage("menuSaveAllTabs"),it=browser.i18n.getMessage("menuBatchSaveUrls"),ct=browser.i18n.getMessage("menuSelectProfile"),lt=browser.i18n.getMessage("profileDefaultSettings"),dt=browser.i18n.getMessage("menuAutoSave"),ut=browser.i18n.getMessage("menuAutoSaveDisabled"),ft=browser.i18n.getMessage("menuAutoSaveTab"),ht=browser.i18n.getMessage("menuAutoSaveUnpinnedTabs"),mt=browser.i18n.getMessage("menuAutoSaveAllTabs"),wt=[xe,Te,Ae,Ce,Fe,We],bt=new Map,pt=new Map;let gt,yt,vt,kt=!0,It=!0,xt=new Map;async function St(e){const[t,a]=await Promise.all([S(),s()]),n=await T(e&&e.url);if(ke&&n){const o=["page","frame","image","link","video","audio","selection"],r=[];if(n.browserActionMenuEnabled&&r.push("browser_action"),n.tabMenuEnabled)try{ve.create({id:"temporary-id",contexts:["tab"],title:"title"}),r.push("tab")}catch(e){n.tabMenuEnabled=!1}await ve.removeAll();const s=r.concat(...o),i=n.contextMenuEnabled?s:r;if(ve.create({id:Ie,contexts:i,title:Ve}),ve.create({id:xe,contexts:i,title:Qe}),ve.create({id:Te,contexts:n.contextMenuEnabled?r.concat(["selection"]):r,title:Ye}),Object.keys(t).length>1&&ve.create({id:Se,contexts:i,title:Xe}),n.contextMenuEnabled&&ve.create({id:"separator-1",contexts:o,type:"separator"}),ve.create({id:Ae,contexts:i,title:tt}),n.contextMenuEnabled&&ve.create({id:Ce,contexts:["frame"],title:at}),ve.create({id:Ue,contexts:r,title:nt}),ve.create({id:je,contexts:r,title:ot,parentId:Ue}),ve.create({id:Ne,contexts:r,title:rt,parentId:Ue}),ve.create({id:qe,contexts:r,title:st,parentId:Ue}),n.contextMenuEnabled&&(ve.create({id:_e,contexts:o,title:ot}),ve.create({id:Be,contexts:o,title:rt}),ve.create({id:De,contexts:o,title:st}),ve.create({id:"separator-2",contexts:o,type:"separator"})),Object.keys(t).length>1){ve.create({id:Pe,title:ct,contexts:i}),ve.create({id:"wasve-with-profile-default",contexts:i,title:lt,parentId:Se});const r="select-profile-default",s=!a.profileName||a.profileName==l;let d;ve.create({id:r,type:"radio",contexts:i,title:lt,checked:s,parentId:Pe}),bt.set(r,s),ve.create({id:We,title:Ke,contexts:i}),pt.set(We,Ke),e&&e.url&&(d=await y(e.url,!0));const u="associate-with-profile-current",f=!d||d.profile==c;ve.create({id:u,type:"radio",contexts:i,title:c,checked:f,parentId:We}),bt.set(u,f);const h="associate-with-profile-default",m=Boolean(d)&&d.profile==l;ve.create({id:h,type:"radio",contexts:i,title:lt,checked:m,parentId:We}),bt.set(h,m),xt=new Map,Object.keys(t).forEach(((e,t)=>{if(e!=l){let n=Me+t;ve.create({id:n,contexts:i,title:e,parentId:Se}),n=Le+t;let o=a.profileName==e;ve.create({id:n,type:"radio",contexts:i,title:e,checked:o,parentId:Pe}),bt.set(n,o),n=Re+t,o=Boolean(d)&&d.profile==e,ve.create({id:n,type:"radio",contexts:i,title:e,checked:o,parentId:We}),bt.set(n,o),xt.set(e,t)}})),n.contextMenuEnabled&&ve.create({id:"separator-3",contexts:o,type:"separator"})}ve.create({id:Fe,contexts:i,title:dt}),ve.create({id:ze,type:"radio",title:ut,contexts:i,checked:!0,parentId:Fe}),bt.set(ze,!0),ve.create({id:He,type:"radio",title:ft,contexts:i,checked:!1,parentId:Fe}),bt.set(He,!1),ve.create({id:Je,type:"radio",title:ht,contexts:i,checked:!1,parentId:Fe}),bt.set(Je,!1),ve.create({id:Ge,type:"radio",title:mt,contexts:i,checked:!1,parentId:Fe}),bt.set(Ge,!1),ve.create({id:"separator-4",contexts:i,type:"separator"}),ve.create({id:Oe,contexts:i,title:it}),ve.create({id:Ee,contexts:i,title:et})}gt=!0,yt&&(yt=!1,(await browser.tabs.query({})).forEach((async e=>await Et(e))))}async function Tt(e){const t=await s(e.id);await async function(){const e=await browser.tabs.query({});return Promise.all(e.map((async e=>{const[t,a]=await Promise.all([T(e.url,!0),R(e)]);try{await browser.tabs.sendMessage(e.id,{method:"content.init",autoSaveEnabled:a,options:t})}catch(e){}})))}(),await be(e);try{await browser.runtime.sendMessage({method:"options.refresh",profileName:t.profileName})}catch(e){}}async function Et(e){if(ke&&gt){const t=[],a=await s(e.id);if(a[e.id].editorDetected)Pt(!1);else if(Pt(!0),t.push(Lt(ze,!a[e.id].autoSave)),t.push(Lt(He,a[e.id].autoSave)),t.push(Lt(Je,Boolean(a.autoSaveUnpinned))),t.push(Lt(Ge,Boolean(a.autoSaveAll))),e&&e.url){const n=await T(e.url);t.push(async function(e,t){const a=kt;kt=t,(void 0===a||a!=t)&&await St(e)}(e,n.contextMenuEnabled)),t.push(Mt(xe,a[e.id].savedPageDetected?Ze:Qe)),t.push(ve.update(Ae,{visible:!n.saveRawPage})),t.push(ve.update(xe,{visible:!n.openEditor||a[e.id].savedPageDetected}));let o="associate-with-profile-default",r=Ke;const[s,i]=await Promise.all([S(),y(e.url)]);if(i){const e=xt.get(i.profile);e&&(o=Re+e,r=$e)}Object.keys(s).length>1&&(Object.keys(s).forEach(((e,a)=>{e==l?t.push(Lt("associate-with-profile-default","associate-with-profile-default"==o)):t.push(Lt(Re+a,o==Re+a))})),t.push(Mt(We,r)))}await Promise.all(t)}}async function Pt(e){const t=It;if(It=e,void 0===t||t!=e){const t=[];try{wt.forEach((a=>t.push(ve.update(a,{visible:e})))),await Promise.all(t)}catch(e){}}}function Mt(e,t){const a=pt.get(e);return pt.set(e,t),void 0===a||a!=t?ve.update(e,{title:t}):void 0}async function Lt(e,t){t=Boolean(t),bt.set(e,t),await ve.update(e,{checked:t})}Promise.resolve().then((async function(){ke&&(St(),ve.onClicked.addListener((async(e,t)=>{if(e.menuItemId==Ie&&(e.linkUrl?vt.saveUrls([e.linkUrl]):vt.saveTabs([t])),e.menuItemId==xe){(await s(t.id))[t.id].savedPageDetected?vt.openEditor(t):e.linkUrl?vt.saveUrls([e.linkUrl],{openEditor:!0}):vt.saveTabs([t],{openEditor:!0})}if(e.menuItemId==Te&&vt.saveSelectedLinks(t),e.menuItemId==Ee&&await browser.tabs.create({active:!0,url:"/src/extension/ui/pages/pendings.html"}),e.menuItemId==Ae&&vt.saveTabs([t],{selected:!0}),e.menuItemId==Ce&&vt.saveTabs([t],{frameId:e.frameId}),e.menuItemId==_e||e.menuItemId==je){const e=await K({currentWindow:!0,highlighted:!0});vt.saveTabs(e)}if(e.menuItemId==Be||e.menuItemId==Ne){const e=await K({currentWindow:!0,pinned:!1});vt.saveTabs(e)}if(e.menuItemId==De||e.menuItemId==qe){const e=await K({currentWindow:!0});vt.saveTabs(e)}if(e.menuItemId==Oe&&vt.batchSaveUrls(),e.menuItemId==He){const e=await s(t.id);e[t.id].autoSave=!0,await i(e),Tt(t)}if(e.menuItemId==ze){const e=await s();Object.keys(e).forEach((t=>{"object"==typeof e[t]&&e[t].autoSave&&(e[t].autoSave=!1)})),e.autoSaveUnpinned=e.autoSaveAll=!1,await i(e),Tt(t)}if(e.menuItemId==Ge){const a=await s();a.autoSaveAll=e.checked,await i(a),Tt(t)}if(e.menuItemId==Je){const a=await s();a.autoSaveUnpinned=e.checked,await i(a),Tt(t)}if(e.menuItemId.startsWith(Me)){const a=await S(),n=e.menuItemId.split(Me)[1];let o;if("default"==n)o=l;else{const e=Number(n);o=Object.keys(a)[e]}a[o].profileName=o,vt.saveTabs([t],a[o])}if(e.menuItemId.startsWith(Le)){const[a,n]=await Promise.all([S(),s()]),o=e.menuItemId.split(Le)[1];if("default"==o)n.profileName=l;else{const e=Number(o);n.profileName=Object.keys(a)[e]}await i(n),Tt(t)}if(e.menuItemId.startsWith(Re)){const[a,n]=await Promise.all([S(),y(t.url,!0)]),o=e.menuItemId.split(Re)[1];let r;if("default"==o)r=l;else if("current"==o)r=c;else{const e=Number(o);r=Object.keys(a)[e]}n?await P(n.url,n.url,r,r):(await Mt(We,$e),await E(new URL(t.url).hostname,r,r))}})),gt?yt=!0:(await browser.tabs.query({})).forEach((async e=>await Et(e))))}));const Wt=browser.commands;let Rt,At,Ct;function Ut(e,t){return e.method.endsWith(".refreshMenu")?function(e){if(e.method.endsWith("refreshMenu"))return St(),Promise.resolve({})}(e):ue(e,t)}function _t(e){!function(e){pe(e.id,ye("forbidden"))}(e)}function Bt(e,t,a){!function(e,t,a){let n;a?n=ye("inject",!0):(n=ye(1==t?"inject":"execute"),n.setTitle={title:Q+" ("+t+"/2)"},n.setIcon={path:V+"0.png"}),pe(e,n)}(e,t,a)}async function Dt(e,t,a){fe(e),t&&await browser.tabs.sendMessage(e,{method:"content.error",error:t.toString(),link:a})}function Ot(e){!function(e){pe(e,ye("edit"))}(e)}function jt(e,t){he(e,t)}function Nt(e,t,a){!function(e,t,a){we(e,t,a,oe)}(e,t,a)}function qt(e){Et(e)}Wt&&Wt.onCommand&&Wt.onCommand.addListener&&Wt.onCommand.addListener((async e=>{if("save-selected-tabs"==e){const e=await K({currentWindow:!0,highlighted:!0});Rt.saveTabs(e,{optionallySelected:!0})}if("save-all-tabs"==e){const e=await K({currentWindow:!0});Rt.saveTabs(e)}}));const Ft=["lib/chrome-browser-polyfill.js","lib/single-file.js"],zt=["lib/chrome-browser-polyfill.js","lib/single-file-frames.js"];async function Ht(e,t){let a;if(await async function(e){const t=e.extensionScriptFiles||[];At||Ct||([At,Ct]=await Promise.all([Jt(Ft.concat(t)),Jt(zt)]))}(t),!t.removeFrames)try{await browser.tabs.executeScript(e,{code:Ct,allFrames:!0,matchAboutBlank:!0,runAt:"document_start"})}catch(e){}try{await browser.tabs.executeScript(e,{code:At,allFrames:!1,runAt:"document_idle"}),a=!0}catch(e){}return a&&t.frameId&&await browser.tabs.executeScript(e,{code:"document.documentElement.dataset.requestedFrameId = true",frameId:t.frameId,matchAboutBlank:!0,runAt:"document_start"}),a}async function Jt(e){const t=e.map((async e=>{if("function"==typeof e)return"("+e.toString()+")();";{const t=await fetch(browser.runtime.getURL("../../../"+e));return(new TextDecoder).decode(await t.arrayBuffer())}}));let a="";for(const e of t)a+=await e;return a}const Gt="single-file-response-fetch",Kt=(e,t)=>window.fetch(e,t);let $t=0,Vt=new Map;async function Xt(e,t={}){try{let a=await Kt(e,{cache:"force-cache",headers:t.headers});return 401!=a.status&&403!=a.status&&404!=a.status||(a=await Qt(e)),a}catch(a){$t++;const n=new Promise(((e,t)=>Vt.set($t,{resolve:e,reject:t})));return await Zt({method:"singlefile.fetch",url:e,requestId:$t,referrer:t.referrer,headers:t.headers}),n}}async function Yt(e,t){const a=await Zt({method:"singlefile.fetchFrame",url:e,frameId:t.frameId,referrer:t.referrer,headers:t.headers});return{status:a.status,headers:new Map(a.headers),arrayBuffer:async()=>new Uint8Array(a.array).buffer}}async function Zt(e){const t=await browser.runtime.sendMessage(e);if(!t||t.error)throw new Error(t&&t.error&&t.error.toString());return t}function Qt(e){return new Promise(((t,a)=>{var n,o,r,s;n=new CustomEvent("single-file-request-fetch",{detail:e}),window.dispatchEvent(n),o=Gt,r=function n(o){var r,s,i;o.detail?o.detail.url==e&&(r=Gt,s=n,i=!1,window.removeEventListener(r,s,i),o.detail.response?t({status:o.detail.status,headers:new Map(o.detail.headers),arrayBuffer:async()=>o.detail.response}):a(o.detail.error)):a()},s=!1,window.addEventListener(o,r,s)}))}function ea(e,t){return Ht(e,t)}browser.runtime.onMessage.addListener((e=>"singlefile.fetchFrame"==e.method&&window.frameId&&window.frameId==e.frameId?async function(e){try{let t=await Kt(e.url,{cache:"force-cache",headers:e.headers});return 401!=t.status&&403!=t.status&&404!=t.status||(t=await Promise.race([Qt(e.url),new Promise(((e,t)=>setTimeout((()=>t()),5e3)))])),{status:t.status,headers:[...t.headers],array:Array.from(new Uint8Array(await t.arrayBuffer()))}}catch(e){return{error:e&&e.toString()}}}(e):"singlefile.fetchResponse"==e.method?async function(e){const t=Vt.get(e.requestId);t&&(e.error?(t.reject(new Error(e.error)),Vt.delete(e.requestId)):(e.truncated&&(t.array?t.array=t.array.concat(e.array):(t.array=e.array,Vt.set(e.requestId,t)),e.finished&&(e.array=t.array)),e.truncated&&!e.finished||(t.resolve({status:e.status,headers:{get:t=>e.headers&&e.headers[t]},arrayBuffer:async()=>new Uint8Array(e.array).buffer}),Vt.delete(e.requestId))));return{}}(e):void 0));const ta="Could not establish connection. Receiving end does not exist.",aa="The message port closed before a response was received.",na="Message manager disconnected",oa="Cannot access contents of url ",ra="pending",sa="processing",ia=["lib/infobar.js","lib/extension.js"],ca=[];let la,da=0;var ua;async function fa(){return browser.tabs.create({active:!0,url:"/src/extension/ui/pages/batch-save-urls.html"})}async function ha(e,t={}){await ba(),await Promise.all(e.map((async e=>{const a=await T(e);Object.keys(t).forEach((e=>a[e]=t[e])),a.autoClose=!0,a.extensionScriptFiles=ia,a.passReferrerOnError&&await G(),wa({tab:{url:e},status:ra,options:a,method:"content.save"})}))),pa()}async function ma(e,t={}){await ba(),await Promise.all(e.map((async e=>{const a=e.id,n=await T(e.url);if(Object.keys(t).forEach((e=>n[e]=t[e])),n.tabId=a,n.tabIndex=e.index,n.extensionScriptFiles=ia,n.passReferrerOnError&&await G(),t.autoSave){if(R(e)){ga(wa({status:sa,tab:e,options:n,method:"content.autosave"}))}}else{Bt(a,1);await ea(a,n)||D(e)?(Bt(a,2),wa({status:ra,tab:e,options:n,method:"content.save"})):_t(e)}}))),pa()}function wa(e){const t={id:da,status:e.status,tab:e.tab,options:e.options,method:e.method,done:function(){ca.splice(ca.findIndex((e=>e.id==this.id)),1),pa()}};return ca.push(t),da++,t}async function ba(){la||(la=(await v()).maxParallelWorkers)}function pa(){const e=ca.filter((e=>e.status==sa)).length;for(let t=0;t<Math.min(ca.length-e,la-e);t++){const e=ca.find((e=>e.status==ra));e&&ga(e)}}async function ga(e){const t=e.id;if(e.status=sa,!e.tab.id){let t;try{const a=await async function(e){const t=await browser.tabs.create(e);return new Promise(((e,a)=>{function n(a,r){a==t.id&&"complete"==r.status&&(e(t),browser.tabs.onUpdated.removeListener(n),browser.tabs.onRemoved.removeListener(o))}function o(e){e==t.id&&(a(e),browser.tabs.onRemoved.removeListener(o))}browser.tabs.onUpdated.addListener(n),browser.tabs.onRemoved.addListener(o)}))}({url:e.tab.url,active:!1});e.tab.id=e.options.tabId=a.id,e.tab.index=e.options.tabIndex=a.index,Bt(e.tab.id,1),t=await ea(e.tab.id,e.options)}catch(t){e.tab.id=t}if(!t)return void e.done();Bt(e.tab.id,2)}e.options.taskId=t;try{await browser.tabs.sendMessage(e.tab.id,{method:e.method,options:e.options})}catch(t){!t||t.message&&function(e){return e.message==aa||e.message==ta||e.message==na||e.message.startsWith(oa+JSON.stringify(B))}(t)||(console.log(t.message?t.message:t),Dt(e.tab.id,t.message,t.link),e.done())}}function ya(e){const t=ca.find((t=>t.id==e));t&&(t.options.autoClose&&!t.cancelled&&browser.tabs.remove(t.tab.id),t.done())}function va(e,t){const a=ca.find((t=>t.id==e));a&&(a.cancel=t)}function ka(e){Array.from(ca).filter((t=>t.tab.id==e&&!t.options.autoSave)).forEach(xa)}function Ia(e){return ca.find((t=>t.id==e))}function xa(e){const t=e.tab.id;e.cancelled=!0,browser.tabs.sendMessage(t,{method:"content.cancelSave",options:{loadDeferredImages:e.options.loadDeferredImages,loadDeferredImagesKeepZoomLevel:e.options.loadDeferredImagesKeepZoomLevel}}),e.cancel&&e.cancel(),"content.autosave"==e.method&&jt(t,!0),function(e){me(e)}(e.tab),e.done()}function Sa(e){return{id:e.id,tabId:e.tab.id,index:e.tab.index,url:e.tab.url,title:e.tab.title,cancelled:e.cancelled,status:e.status}}ua={isSavingTab:function(e){return Boolean(ca.find((t=>t.tab.id==e.id)))},saveTabs:ma,saveUrls:ha,cancelTab:ka,openEditor:function(e){browser.tabs.sendMessage(e.id,{method:"content.openEditor"})},saveSelectedLinks:async function(e){const t={extensionScriptFiles:ia,tabId:e.id,tabIndex:e.index};if(await ea(e.id,t)){const t=await browser.tabs.sendMessage(e.id,{method:"content.getSelectedLinks"});if(t.urls&&t.urls.length){const e=await fa(),a=(n,o)=>{"complete"==o.status&&n==e.id&&(browser.tabs.onUpdated.removeListener(a),browser.tabs.sendMessage(e.id,{method:"newUrls.addURLs",urls:t.urls}))};browser.tabs.onUpdated.addListener(a)}}else _t(e)},batchSaveUrls:fa},function(e){vt=e}(ua),function(e){de=e}(ua),function(e){Rt=e}(ua);async function Ta(e){const t=browser.runtime.connectNative("singlefile_companion");t.postMessage({method:"save",pageData:e}),await new Promise(((e,a)=>{t.onDisconnect.addListener((()=>{t.error?a(new Error(t.error.message+" (Companion)")):browser.runtime.lastError&&!browser.runtime.lastError.message.includes("Native host has exited")||e()}))}))}const Ea=new Set;async function Pa(e){return e.method.endsWith(".saveCreatedBookmarks")?(Ma(),{}):e.method.endsWith(".disable")?(async function(){let e;const t=await S();Object.keys(t).forEach((a=>e=e||!t[a].saveCreatedBookmarks)),e&&(browser.bookmarks.onCreated.removeListener(La),browser.bookmarks.onMoved.removeListener(Wa))}(),{}):void 0}async function Ma(){try{browser.bookmarks.onCreated.removeListener(La),browser.bookmarks.onMoved.removeListener(Wa)}catch(e){}let e;const t=await S();Object.keys(t).forEach((a=>{t[a].saveCreatedBookmarks&&(e=!0)})),e&&(browser.bookmarks.onCreated.addListener(La),browser.bookmarks.onMoved.addListener(Wa))}async function La(e,t){Ea.add(e),await Ra(e,t.url,t)}async function Wa(e,t){if(Ea.has(e)){const a=await browser.bookmarks.get(e);a[0]&&await Ra(e,a[0].url,t)}}async function Ra(e,t,a){const n=await browser.tabs.query({lastFocusedWindow:!0,active:!0}),o=await T(t);if(o.saveCreatedBookmarks){const s=await async function e(t,a=[]){if(t){const n=(await browser.bookmarks.get(t))[0];n&&n.title&&(a.unshift(n.title),await e(n.parentId,a))}return a}(a.parentId),i=o.allowedBookmarkFolders.toString(),c=s.find((e=>o.allowedBookmarkFolders.includes(e))),l=o.ignoredBookmarkFolders.toString(),d=s.find((e=>o.ignoredBookmarkFolders.includes(e)));if((i&&c||!i)&&(l&&!d||!l))if(n.length&&n[0].url==t)Ea.delete(e),ma(n,{bookmarkId:e,bookmarkFolders:s});else{const a=await browser.tabs.query({});if(a.length){const n=a.find((e=>e.url==t));n?(Ea.delete(e),ma([n],{bookmarkId:e,bookmarkFolders:s})):t&&("about:blank"==t?browser.bookmarks.onChanged.addListener((function t(a,n){a==e&&n.url&&(browser.bookmarks.onChanged.removeListener(t),r(n.url))})):r(t))}}}function r(t){Ea.delete(e),ha([t],{bookmarkId:e})}}Promise.resolve().then(Ma);async function Aa(e,t){let a=t||"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhYzZmZTMzMi0wODNjLTRjZmMtYmYxNC0xNWU5MTJmMWY4OWIiLCJpYXQiOjE1NzYxNzQzNDV9.n31j9ctJj7R1Vjwyc5yd1d6Cmg0NDnpwSaLWsqtZJQA";const n=await fetch("https://api.woleet.io/v1/anchor",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json",Authorization:"Bearer "+a},body:JSON.stringify({name:e,hash:e,public:!0})});if(401==n.status){const e=new Error("Your access token on Woleet is invalid. Go to __DOC_LINK__ to create your account.");throw e.link="https://app.woleet.io/",e}if(402==n.status){const e=new Error("You have no more credits on Woleet. Go to __DOC_LINK__ to recharge them.");throw e.link="https://app.woleet.io/",e}if(n.status>=400)throw new Error((n.statusText||"Error "+n.status)+" (Woleet)");return n.json()}const Ca="https://oauth2.googleapis.com/token",Ua="https://www.googleapis.com/drive/v3/files";let _a,Ba=!0;class Da{constructor(e){this.file=e.file,this.onProgress=e.onProgress,this.contentType=this.file.type||"application/octet-stream",this.metadata={name:e.filename,mimeType:this.contentType,parents:e.parents||["root"]},this.token=e.token,this.offset=0,this.chunkSize=e.chunkSize||524288}async upload(){const e=Ha(await fetch("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable",{method:"POST",headers:{Authorization:"Bearer "+this.token,"Content-Type":"application/json","X-Upload-Content-Length":this.file.size,"X-Upload-Content-Type":this.contentType},body:JSON.stringify(this.metadata)})).headers.get("Location");if(this.url=e,!this.cancelled)return this.onProgress&&this.onProgress(0,this.file.size),Fa(this)}}async function Oa(e,t){const a=await fetch(Ca,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id="+e.clientId+"&client_secret="+e.clientKey+"&grant_type=authorization_code&code="+t.code+"&redirect_uri="+browser.identity.getRedirectURL()}),n=await za(a);return e.accessToken=n.access_token,e.refreshToken=n.refresh_token,e.expirationDate=Date.now()+1e3*n.expires_in,{accessToken:e.accessToken,refreshToken:e.refreshToken,expirationDate:e.expirationDate}}function ja(e={}){return Boolean(browser.identity&&browser.identity.getAuthToken)&&!e.forceWebAuthFlow}async function Na(e,t,a=!0){const n=t.split("/");n.pop();const o=e.folderIds.get(n.join("/"));if(o)return o;let r="root";if(n.length){let o="";for(const s of n){o&&(o+="/"),o+=s;const n=e.folderIds.get(o);if(n)r=n;else try{r=await qa(e,s,r),e.folderIds.set(o,r)}catch(n){if("path_not_found"==n.message&&a)return e.folderIds.clear(),Na(e,t,!1);throw n}}}return r}async function qa(e,t,a){const n=await async function(e,t,a){return za(await fetch(Ua+"?q=mimeType = 'application/vnd.google-apps.folder' and name = '"+t+"' and trashed != true and '"+a+"' in parents",{headers:{Authorization:"Bearer "+e.accessToken}}))}(e,t,a);if(n.files.length)return n.files[0].id;{const n=await async function(e,t,a){return za(await fetch(Ua,{method:"POST",headers:{Authorization:"Bearer "+e.accessToken,"Content-Type":"application/json"},body:JSON.stringify({name:t,parents:[a],mimeType:"application/vnd.google-apps.folder"})}))}(e,t,a);return n.id}}async function Fa(e){let t=e.file,a=e.file.size;(e.offset||e.chunkSize)&&(e.chunkSize&&(a=Math.min(e.offset+e.chunkSize,e.file.size)),t=t.slice(e.offset,a));const n=await fetch(e.url,{method:"PUT",headers:{Authorization:"Bearer "+e.token,"Content-Type":e.contentType,"Content-Range":"bytes "+e.offset+"-"+(a-1)+"/"+e.file.size,"X-Upload-Content-Type":e.contentType},body:t});if(e.onProgress&&!e.cancelled&&e.onProgress(e.offset+e.chunkSize,e.file.size),200==n.status||201==n.status)return n.json();if(308==n.status){const t=n.headers.get("Range");if(t&&(e.offset=parseInt(t.match(/\d+/g).pop(),10)+1),e.cancelled)throw new Error("upload_cancelled");return Fa(e)}Ha(n)}async function za(e){e=Ha(e);const t=await e.json();if(t.error)throw new Error(t.error);return t}function Ha(e){if(200==e.status)return e;throw 404==e.status?new Error("path_not_found"):401==e.status?new Error("invalid_token"):new Error("unknown_error ("+e.status+")")}async function Ja(e,t,a,n,o,r){for(;_a;)await _a;const s=new AbortController;return _a=(async()=>{try{await async function({path:o,content:r,message:s=""},i){try{const c=await fetch(`https://api.github.com/repos/${t}/${a}/contents/${o.replace(/#/g,"%23")}`,{method:"PUT",headers:new Map([["Authorization",`token ${e}`],["Accept","application/vnd.github.v3+json"]]),body:JSON.stringify({content:btoa(unescape(encodeURIComponent(r))),message:s,branch:n}),signal:i}),l=await c.json();if(c.status<400)return l;throw new Error(l.message)}catch(e){if("AbortError"!=e.name)throw e}}({path:o,content:r},s.signal)}finally{_a=null}})(),{cancelPush:()=>s.abort(),pushPromise:_a}}const Ga=new Map,Ka="text/html",$a=/([{}()^$&.*?/+|[\\\\]|\]|-)/g,Va=browser.runtime.getManifest(),Xa=Va.optional_permissions&&Va.optional_permissions.includes("identity"),Ya=new class{constructor(e,t,a){this.clientId=e,this.clientKey=t,this.scopes=a,this.folderIds=new Map,setInterval((()=>this.folderIds.clear()),6e4)}async auth(e={interactive:!0}){if(e.requestPermissionIdentity&&Ba)try{await browser.permissions.request({permissions:["identity"]}),Ba=!1}catch(e){}return ja(e)?(this.accessToken=await browser.identity.getAuthToken({interactive:e.interactive}),{revokableAccessToken:this.accessToken}):(this.authURL="https://accounts.google.com/o/oauth2/v2/auth?client_id="+this.clientId+"&response_type=code&access_type=offline&redirect_uri="+browser.identity.getRedirectURL()+"&scope="+this.scopes.join(" "),e.code?Oa(this,e):async function(e,t){let a;try{if(browser.identity&&browser.identity.launchWebAuthFlow&&!t.forceWebAuthFlow){const a=await browser.identity.launchWebAuthFlow({interactive:t.interactive,url:e.authURL});return t.code=new URLSearchParams(new URL(a).search).get("code"),await Oa(e,t)}if(t.launchWebAuthFlow)return t.extractAuthCode(browser.identity.getRedirectURL()).then((e=>a=e)).catch((()=>{})),await t.launchWebAuthFlow({url:e.authURL});throw new Error("auth_not_supported")}catch(n){if(n.message&&("code_required"==n.message||n.message.includes("access"))){if(a)return t.code=a,await Oa(e,t);throw new Error("code_required")}throw n}}(this,e))}setAuthInfo(e,t){ja(t)||(e?(this.accessToken=e.accessToken,this.refreshToken=e.refreshToken,this.expirationDate=e.expirationDate):(delete this.accessToken,delete this.refreshToken,delete this.expirationDate))}async refreshAuthToken(){if(this.refreshToken){const e=await fetch(Ca,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id="+this.clientId+"&refresh_token="+this.refreshToken+"&grant_type=refresh_token"});if(400==e.status)throw new Error("unknown_token");const t=await za(e);return this.accessToken=t.access_token,t.refresh_token&&(this.refreshToken=t.refresh_token),t.expires_in&&(this.expirationDate=Date.now()+1e3*t.expires_in),{accessToken:this.accessToken,refreshToken:this.refreshToken,expirationDate:this.expirationDate}}}async revokeAuthToken(e){if(e){if(browser.identity&&browser.identity.removeCachedAuthToken)try{await browser.identity.removeCachedAuthToken({token:e})}catch(e){}const t=await fetch("https://accounts.google.com/o/oauth2/revoke",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"token="+e});try{await za(t)}catch(e){if("invalid_token"!=e.message)throw e}finally{delete this.accessToken,delete this.refreshToken,delete this.expirationDate}}}async upload(e,t,a,n=!0){const o=await Na(this,e),r=e.split("/").pop(),s=new Da({token:this.accessToken,file:t,parents:[o],filename:r,onProgress:a.onProgress});try{return{cancelUpload:()=>s.cancelled=!0,uploadPromise:s.upload()}}catch(o){if("path_not_found"==o.message&&n)return this.folderIds.clear(),this.upload(e,t,a,!1);throw o}}}("207618107333-h1220p1oasj3050kr5r416661adm091a.apps.googleusercontent.com","VQJ8Gq8Vxx72QyxPyeLtWvUt",["https://www.googleapis.com/auth/drive.file"]);async function Za(e,t){if(e.method.endsWith(".download"))return async function(e,t){let a;e.truncated?(a=Ga.get(t.id),a||(a=[],Ga.set(t.id,a)),a.push(e.content),e.finished&&Ga.delete(t.id)):e.content&&(a=[e.content]);e.truncated&&!e.finished||(e.openEditor?(Ot(t.id),await async function({tabIndex:e,content:t,filename:a}){const n={active:!0,url:C};null!=e&&(n.index=e);const o=await browser.tabs.create(n);U.set(o.id,{content:t,filename:a})}({tabIndex:t.index+1,filename:e.filename,content:a.join("")})):e.saveToClipboard?(e.content=a.join(""),function(e){const t="copy";function a(t){t.clipboardData.setData(Ka,e.content),t.clipboardData.setData("text/plain",e.content),t.preventDefault()}document.addEventListener(t,a),document.execCommand(t),document.removeEventListener(t,a)}(e),jt(t.id)):await async function(e,t,a,n){try{if(n.saveToGDrive?await(await tn(n.taskId,n.filename,new Blob(e,{type:Ka}),{forceWebAuthFlow:n.forceWebAuthFlow},{onProgress:(e,a)=>Nt(t.id,e,a)})).uploadPromise:n.saveToGitHub?await(await en(n.taskId,n.filename,e.join(""),n.githubToken,n.githubUser,n.githubRepository,n.githubBranch)).pushPromise:n.saveWithCompanion?await Ta({filename:n.filename,content:n.content,filenameConflictAction:n.filenameConflictAction}):(n.url=URL.createObjectURL(new Blob(e,{type:Ka})),await an(n,{confirmFilename:n.confirmFilename,incognito:a,filenameConflictAction:n.filenameConflictAction,filenameReplacementCharacter:n.filenameReplacementCharacter,includeInfobar:n.includeInfobar})),jt(t.id),n.openSavedPage){const a={active:!0,url:URL.createObjectURL(new Blob(e,{type:Ka}))};null!=t.index&&(a.index=t.index+1),browser.tabs.create(a)}}catch(e){e.message&&"upload_cancelled"==e.message||(console.error(e),Dt(t.id,e.message,e.link))}finally{n.url&&URL.revokeObjectURL(n.url)}}(a,t,t.incognito,e));return{}}(e,t.tab);if(e.method.endsWith(".disableGDrive")){const e=await M();return W(),await Ya.revokeAuthToken(e&&(e.accessToken||e.revokableAccessToken)),{}}if(e.method.endsWith(".end")){if(e.hash)try{await Aa(e.hash,e.woleetKey)}catch(e){Dt(t.tab.id,e.message,e.link)}return ya(e.taskId),{}}return e.method.endsWith(".getInfo")?ca.map(Sa):e.method.endsWith(".cancel")?(a=e.taskId,xa(ca.find((e=>e.id==a))),{}):e.method.endsWith(".cancelAll")?(Array.from(ca).forEach(xa),{}):e.method.endsWith(".saveUrls")?(ha(e.urls),{}):void 0;var a}async function Qa(e,t){let a=await M();const n={interactive:!0,forceWebAuthFlow:e.forceWebAuthFlow,requestPermissionIdentity:Xa,launchWebAuthFlow:e=>async function(e){const t=await browser.tabs.create({url:e.url,active:!0});return new Promise(((e,a)=>{browser.tabs.onRemoved.addListener((function e(n){n==t.id&&(browser.tabs.onRemoved.removeListener(e),a(new Error("code_required")))}))}))}(e),extractAuthCode:e=>function(e){return new Promise(((t,a)=>{browser.tabs.onUpdated.addListener((function n(o,r){if(r&&r.url.startsWith(e)){browser.tabs.onUpdated.removeListener(n);const e=new URLSearchParams(new URL(r.url).search).get("code");e?(browser.tabs.remove(o),t(e)):a()}}))}))}(e)};return Ya.setAuthInfo(a,n),a&&a.accessToken&&!t||(a=await Ya.auth(n),a?await L(a):await W()),a}async function en(e,t,a,n,o,r,s){const i=Ia(e);if(!i||!i.cancelled){const i=Ja(n,o,r,s,t,a);va(e,i.cancelPush);try{return await(await i).pushPromise,i}catch(e){throw new Error(e.message+" (GitHub)")}}}async function tn(e,t,a,n,o){try{await Qa(n);const r=Ia(e);if(!r||!r.cancelled){const n=await Ya.upload(t,a,o);return va(e,n.cancelUpload),n}}catch(r){if("invalid_token"!=r.message)throw new Error(r.message+" (Google Drive)");{let r;try{r=await Ya.refreshAuthToken()}catch(e){if("unknown_token"!=e.message)throw new Error(e.message+" (Google Drive)");r=await Qa(n,!0)}r?await L(r):await W(),await tn(e,t,a,n,o)}}}async function an(t,a){let n;if("skip"==a.filenameConflictAction){(await browser.downloads.search({filenameRegex:"(\\\\|/)"+(o=t.filename,o.replace($a,"\\$1")+"$"),exists:!0})).length?n=!0:a.filenameConflictAction="uniquify"}var o;if(!n){const n={url:t.url,saveAs:a.confirmFilename,filename:t.filename,conflictAction:a.filenameConflictAction};a.incognito&&(n.incognito=!0);const o=await e(n,a.filenameReplacementCharacter);o.filename&&t.bookmarkId&&t.replaceBookmarkURL&&(o.filename.startsWith("file:")||(o.filename.startsWith("/")&&(o.filename=o.filename.substring(1)),o.filename="file:///"+o.filename.replace(/#/g,"%23")),await async function(e,t){try{await browser.bookmarks.update(e,t)}catch(e){}}(t.bookmarkId,{url:o.filename}))}}const nn={},on={};async function rn(e,t){if("enableAutoSave"==e.method){const a=await s(t.id);a[t.id].autoSave=e.enabled,await i(a),async function(e){Promise.all([St(e),be(e)])}(t)}if("isAutoSaveEnabled"==e.method)return R(t)}async function sn(e,t){const a=t.id,n=await T(t.url,!0);if(n){let o;Bt(a,1,!0),n.content=e.content,n.url=e.url,n.frames=e.frames,n.canvases=e.canvases,n.fonts=e.fonts,n.stylesheets=e.stylesheets,n.images=e.images,n.posters=e.posters,n.videos=e.videos,n.usedFonts=e.usedFonts,n.shadowRoots=e.shadowRoots,n.imports=e.imports,n.referrer=e.referrer,n.updatedResources=e.updatedResources,n.visitDate=new Date(e.visitDate),n.backgroundTab=!0,n.autoSave=!0,n.incognito=t.incognito,n.tabId=a,n.tabIndex=t.index;try{if(n.autoSaveExternalSave)await async function(e){e.autoSaveExternalSave=!1;const t=browser.runtime.connectNative("singlefile_companion");t.postMessage({method:"externalSave",pageData:e}),await new Promise(((e,a)=>{t.onDisconnect.addListener((()=>{t.error?a(new Error(t.error.message+" (Companion)")):browser.runtime.lastError&&!browser.runtime.lastError.message.includes("Native host has exited")||e()}))}))}(n);else{if(o=await function(e,t,a,n={fetch:Xt,frameFetch:Yt}){return globalThis.singlefile.getPageData(e,n,t,a)}(n,null,null,{fetch:cn}),n.includeInfobar&&await infobar.includeScript(o),n.saveToGDrive){const t=new Blob([o.content],{type:"text/html"});await(await tn(e.taskId,o.filename,t,n,{})).uploadPromise}else if(n.saveToGitHub)await(await en(e.taskId,o.filename,o.content,n.githubToken,n.githubUser,n.githubRepository,n.githubBranch)).pushPromise;else if(n.saveWithCompanion)await Ta({filename:o.filename,content:o.content,filenameConflictAction:o.filenameConflictAction});else{const e=new Blob([o.content],{type:"text/html"});if(o.url=URL.createObjectURL(e),await an(o,n),n.openSavedPage){const n={active:!0,url:URL.createObjectURL(e),windowId:t.windowId},o=t.index;try{await browser.tabs.get(a),n.index=o+1}catch(e){n.index=o}browser.tabs.create(n)}}o.hash&&await Aa(o.hash,n.woleetKey)}}finally{e.taskId?ya(e.taskId):n.autoClose&&(browser.tabs.remove(on[a]||a),delete on[a]),o&&o.url&&URL.revokeObjectURL(o.url),jt(a,!0)}}}function cn(e,t={}){return new Promise(((a,n)=>{const o=new XMLHttpRequest;if(o.withCredentials=!0,o.responseType="arraybuffer",o.onerror=e=>n(new Error(e.detail)),o.onreadystatechange=()=>{o.readyState==XMLHttpRequest.DONE&&a({status:o.status,headers:{get:e=>o.getResponseHeader(e)},arrayBuffer:async()=>o.response})},o.open("GET",e,!0),t.headers)for(const e of Object.entries(t.headers))o.setRequestHeader(e[0],e[1]);o.send()}))}async function ln(e,t){if(e.method.endsWith(".init")&&(await async function(e,t){await o(e.id);const a=await s(e.id);a[e.id].savedPageDetected=t.savedPageDetected,await i(a)}(t.tab,e),Et(t.tab),function(e){ka(e.id)}(t.tab),async function(e){const[t,a]=await Promise.all([T(e.url,!0),R(e)]);t&&(t.autoSaveLoad||t.autoSaveLoadOrUnload)&&a&&ma([e],{autoSave:!0})}(t.tab)),e.method.endsWith(".getOptions"))return T(e.url);e.method.endsWith(".activate")&&await browser.tabs.update(e.tabId,{active:!0})}browser.tabs.onCreated.addListener((e=>function(e){!function(e){Et(e)}(e)}(e))),browser.tabs.onActivated.addListener((e=>async function(e){qt(await browser.tabs.get(e.tabId))}(e))),browser.tabs.onRemoved.addListener((e=>function(e){o(e),function(e){U.delete(e)}(e),ka(e),async function(e){const t=nn[e];t?t.autoSaveRemove&&(delete nn[e],await sn(t,t.tab)):nn[e]={removed:!0}}(e)}(e))),browser.tabs.onUpdated.addListener(((e,t)=>async function(e,t){if("complete"==t.status){setTimeout((async()=>{try{await browser.tabs.sendMessage(e,{method:"content.maybeInit"})}catch(e){}}),1500),function(e){delete nn[e]}(e);const t=await browser.tabs.get(e);if(D(t)){const e=await s(t.id);e[t.id].editorDetected=!0,await i(e),qt(t)}}t.discarded&&async function(e){const t=nn[e];t?(delete nn[e],await sn(t,t.tab)):nn[e]={discarded:!0}}(e)}(e,t))),browser.tabs.onReplaced.addListener(((e,t)=>function(e,t){!async function(e,t){nn[t]&&!nn[e]&&(nn[e]=nn[t],delete nn[t],on[t]=e);const a=await s();a[t]&&!a[e]&&(a[e]=a[t],delete a[t],await i(a))}(e,t)}(e,t))),browser.runtime.onMessage.addListener(((e,t)=>{if("singlefile.frameTree.initResponse"==e.method||"singlefile.frameTree.ackInitRequest"==e.method)return browser.tabs.sendMessage(t.tab.id,e,{frameId:0}),Promise.resolve({})}));const dn=new Map;function un(e,t){e.delete(t)}browser.runtime.onMessage.addListener(((e,t)=>{if("singlefile.lazyTimeout.setTimeout"==e.method){let a,n=dn.get(t.tab.id);if(n)if(a=n.get(t.frameId),a){const t=a.get(e.type);t&&clearTimeout(t)}else a=new Map;const o=setTimeout((async()=>{try{const a=dn.get(t.tab.id),n=a.get(t.frameId);a&&n&&un(n,e.type),await browser.tabs.sendMessage(t.tab.id,{method:"singlefile.lazyTimeout.onTimeout",type:e.type})}catch(e){}}),e.delay);return n||(n=new Map,a=new Map,n.set(t.frameId,a),dn.set(t.tab.id,n)),a.set(e.type,o),Promise.resolve({})}if("singlefile.lazyTimeout.clearTimeout"==e.method){let a=dn.get(t.tab.id);if(a){const n=a.get(t.frameId);if(n){const t=n.get(e.type);t&&clearTimeout(t),un(n,e.type)}}return Promise.resolve({})}})),browser.tabs.onRemoved.addListener((e=>dn.delete(e))),browser.runtime.onMessage.addListener(((e,t)=>e.method.startsWith("tabs.")?ln(e,t):e.method.startsWith("downloads.")?Za(e,t):e.method.startsWith("autosave.")?async function(e,t){if(e.method.endsWith(".save"))return e.autoSaveDiscard||e.autoSaveRemove?(t.tab?(e.tab=t.tab,nn[t.tab.id]=e):nn[e.tabId]&&(nn[e.tabId].removed&&e.autoSaveRemove||nn[e.tabId].discarded&&e.autoSaveDiscard)&&(delete nn[e.tabId],await sn(e,{id:e.tabId,index:e.tabIndex,url:t.url})),e.autoSaveUnload&&(delete nn[e.tabId],await sn(e,t.tab))):(delete nn[e.tabId],await sn(e,t.tab)),{}}(e,t):e.method.startsWith("ui.")?Ut(e,t):e.method.startsWith("config.")?x(e):e.method.startsWith("tabsData.")?function(e){return e.method.endsWith(".get")?s():e.method.endsWith(".set")?i(e.tabsData):void 0}(e):e.method.startsWith("devtools.")?async function(e){e.method.endsWith(".resourceCommitted")&&e.tabId&&e.url&&("stylesheet"==e.type||"script"==e.type)&&await browser.tabs.sendMessage(e.tabId,e)}(e):e.method.startsWith("editor.")?async function(e,t){if(e.method.endsWith(".getTabData")){const e=t.tab,a=U.get(e.id);if(a){const t=await T(a.url),n=JSON.stringify(a);for(let a=0;a*A<n.length;a++){const o={method:"editor.setTabData"};o.truncated=n.length>A,o.truncated?(o.finished=(a+1)*A>n.length,o.content=n.substring(a*A,(a+1)*A),o.finished&&(o.options=t)):(o.content=n,o.options=t),await browser.tabs.sendMessage(e.id,o)}}return{}}if(e.method.endsWith(".open")){let a;const n=t.tab;if(e.truncated?(a=_.get(n.id),a||(a=[],_.set(n.id,a)),a.push(e.content),e.finished&&_.delete(n.id)):e.content&&(a=[e.content]),!e.truncated||e.finished){const t={url:C};await browser.tabs.update(n.id,t),U.set(n.id,{url:n.url,content:a.join(""),filename:e.filename})}return{}}}(e,t):e.method.startsWith("bookmarks.")?Pa(e):e.method.startsWith("companion.")?async function(e){if(e.method.endsWith(".state"))return{enabled:!0}}(e):e.method.startsWith("requests.")?H(e):e.method.startsWith("bootstrap.")?async function(e,t){if(e.method.endsWith(".init")){const[e,a,n]=await Promise.all([T(t.tab.url,!0),T(t.tab.url),R(t.tab)]);return{optionsAutoSave:e,options:a,autoSaveEnabled:n,tabId:t.tab.id,tabIndex:t.tab.index}}}(e,t):void 0)),browser.runtime.onMessageExternal&&browser.runtime.onMessageExternal.addListener((async(e,t)=>{const a=(await browser.tabs.query({currentWindow:!0,active:!0}))[0];return!!a&&rn(e,a)}))}();