File: //proc/25634/root/usr/syno/synoman/cacheSW.min.js
!function(){"use strict";function e(e,t,s){return t in e?Object.defineProperty(e,t,{value:s,enumerable:!0,configurable:!0,writable:!0}):e[t]=s,e}function t(){if(!0===self.WebrtcCache.EnableDebug){for(var e=arguments.length,t=new Array(e),s=0;s<e;s++)t[s]=arguments[s];console.log("[webrtc cache]",...t)}}function s(){for(var e=arguments.length,t=new Array(e),s=0;s<e;s++)t[s]=arguments[s];console.log("[webrtc cache]",...t)}null!==self.WebrtcCache&&void 0!==self.WebrtcCache||(self.WebrtcCache={}),self.WebrtcCache.EnableDebug=!1;class n{constructor(e,t,s,n,i){if(null==e)throw"clientId is null or undefined";if(null==t)throw"reqId is null or undefined";this.clientId=e,this.reqId=t,this.url=s,this.headers=new Map;for(const[e,t]of n.entries())this.headers.set(e,t);this.body=void 0===i?null:i}}class i extends n{constructor(e,t,s){if(!1==s instanceof Request)throw"invalid request";super(e,t,s.url,s.headers,s.body),this.method=s.method,this.redirect=s.redirect,this.cache=s.cache}}class a{constructor(e,t){this.port=e,this.properties={},t instanceof Object&&(this.properties=t)}setProperty(e,t){this.properties[e]=t}getProperty(e){const t=this.properties[e];if(t)return t}}class r{constructor(){this.pendingPortTable={},this.bindPortTable={}}pending(e,s){t("cache pending",e,s),this.pendingPortTable[e]=s,setTimeout((()=>{!0===this.unpending(e)&&t(`timeout: ${e} pending for window binding`)}),r.PENDING_TIMEOUT)}unpending(e){return!!this.pendingPortTable[e]&&(t(`cache unpending: ${e}`),delete this.pendingPortTable[e],!0)}bind(e,s,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;return!1==s in this.pendingPortTable?(t(`error: cannot find launcher clientId[${s}] for binding`),t(s),!1):(this.register(e,this.pendingPortTable[s],n,i),delete this.pendingPortTable[s],!0)}register(e,s,n){let i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;e in this.bindPortTable&&t(`warning: overwrite cache register port clientId[${e}]`),this.bindPortTable[e]=new a(s,i),s.onmessage=n,t("cache register",e,i,this.bindPortTable)}unregister(e){!1!=e in this.bindPortTable&&(this.bindPortTable[e].port.close(),delete this.bindPortTable[e],t("cache unregister",e))}async sendToClient(e,n){return null==e||null==n?(s("error: clientId or data is null"),!1):(await this.purgeInvalidChannel(),!1==e in this.bindPortTable?(t(`error: cannot find port of ${e}`,this.bindPortTable),!1):(this.bindPortTable[e].port.postMessage(n),!0))}async purgeInvalidChannel(){const e=new Set;(await self.clients.matchAll()).forEach((t=>{e.add(t.id)}));for(const t of Object.keys(this.bindPortTable))!1===e.has(t)&&this.unregister(t)}getTabProperty(e,t){if(!1!=e in this.bindPortTable)return this.bindPortTable[e].getProperty(t)}}e(r,"PENDING_TIMEOUT",1e3);class o extends r{constructor(){super(),this.reqId=0,this.requestTable=new Map}bind(e,t,s){const n={appName:s};super.bind(e,t,this.portMessageHandler.bind(this),n)}register(e,t,s){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;!0===this.requestTable.has(e)&&this.unregister(e),super.register(e,t,s,n),this.requestTable.set(e,new Map)}unregister(e){this.removeAllFetchRequestContexts(e),super.unregister(e),this.requestTable.delete(e)}portMessageHandler(e){const{data:t}=e;if(t.fetchAccept){const{clientId:e,reqId:s}=t.fetchAccept,n=this.getFetchRequestContext(e,s);if(null==n)throw"null or undefined context";n.success()}else if(t.fetchReject){const{clientId:e,reqId:s}=t.fetchReject,n=this.getFetchRequestContext(e,s);if(null==n)throw"null or undefined context";n.fail("fetch reject")}else{if(!t.fetchDone)throw"unknown fetch message channel command";{const{clientId:e,reqId:s,respInfo:n}=t.fetchDone,i=this.getFetchRequestContext(e,s);if(null==i)return;if(null!=n)try{i.success(function(e){const t={};if(null!==e.status&&void 0!==e.status&&(t.status=e.status),null!==e.statusText&&void 0!==e.statusText&&(t.statusText=e.statusText),null!==e.headers&&void 0!==e.headers){const s=new Headers;for(const[t,n]of e.headers.entries())s.append(t,n);t.headers=s}return new Response(e.body,t)}(n))}catch(e){i.fail(e)}else i.fail("fetch failure")}}}getFetchRequestContext(e,t){const n=this.requestTable.get(e);if(null==n)return s(`cannot find client table ${e}`),null;const i=n.get(t);return null==i?(s(`cannot find fetch context ${e} ${t}`),null):i}removeAllFetchRequestContexts(e){const t=this.requestTable.get(e);if(null!=t)for(const[s,n]of t.entries())n.abort(),this.requestTable.get(e).delete(s);else s(`cannot find client table ${e}`)}removeFetchRequestContext(e,t){null!==this.getFetchRequestContext(e,t)&&this.requestTable.get(e).delete(t)}async webrtcFetch(e,t){const s=this.reqId++,n=new i(e,s,t),a=new l(n),r=this.requestTable.get(e);if(null==r)throw`cannot find client table for ${e}`;r.set(s,a);try{return a.setTimeout(o.FETCH_ACCEPT_TIMEOUT),this.sendToClient(e,{fetchRequest:n}),await a.wait(`fetchAccept ${s}`),!0===o.ENABLE_FETCH_DONE_TIMEOUT?a.setTimeout(o.FETCH_DONE_TIMEOUT):a.setTimeout(),await a.wait(`fetchDone ${s}`)}catch(t){throw t.startsWith&&!0===t.startsWith("timeout fetchAccept")&&this.unregister(e),t}finally{this.removeFetchRequestContext(e,s)}}}e(o,"FETCH_ACCEPT_TIMEOUT",1e3),e(o,"FETCH_DONE_TIMEOUT",12e4),e(o,"ENABLE_FETCH_DONE_TIMEOUT",!1);class l{constructor(e){this.reqInfo=e,this.setTimeout()}setTimeout(e){this.state===l.STATE_START&&this.timeout&&this.timeoutId?s("warning: last timeout event is not done"):(this.timeout=e,this.promise=new Promise(((e,t)=>{this._resolve=e,this._reject=t})),this.state=l.STATE_READY,this.timeoutId=null,this.startDate=null)}abort(){this.state===l.STATE_START&&this.fail("abort")}success(e){this._finish(),this._resolve(e)}fail(e){this._finish(),this._reject(e)}_finish(){if(this.state=l.STATE_DONE,null!==this.timeoutId&&clearTimeout(this.timeoutId),null!==this.startDate&&void 0!==this.startDate){return new Date-this.startDate}return null}async wait(e){return l.STATE_DONE===this.state||(l.STATE_READY!==this.state?s(`${e} context is not in ready state`):this.timeout&&(this.state=l.STATE_START,this.startDate=new Date,this.timeoutId=setTimeout((()=>{this.fail(`timeout ${e}`)}),this.timeout))),this.promise}}e(l,"STATE_READY",0),e(l,"STATE_START",1),e(l,"STATE_DONE",2);const c=new o,h={SwVersion:"1.0",WebrtcFetchTypeList:["image"],StatisticsFetchTypeList:["video"],CacheName:"webrtc-cache",ExpireMaxAgeSeconds:604800,ExpireMaxEntries:500,ReportStatisticsPath:"scripts/synowebrtc/WebrtcCacher/ReportStatistics"};class u{constructor(){this.tabManager=null,this.enable=!0,this.lastUpload=new Date(0),this.reset(!1)}setTabManager(e){this.tabManager=e}reset(){let e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];this.stats={},!0===e&&(this.lastUpload=new Date)}update(e,t,s){if(!1===this.enable)return;if(!1==t instanceof Request||!1==s instanceof Response)throw"wrong type of request or response";if(!1===s.headers.has("content-length"))return;const n=t.destination,i=parseInt(s.headers.get("content-length"));if(0<i){let t="Unknown";if(null!==this.tabManager&&void 0!==this.tabManager){const s=this.tabManager.getTabProperty(e,"appName");s&&""!==s&&(t=s)}null!==this.stats[t]&&void 0!==this.stats[t]||(this.stats[t]={}),null!==this.stats[t][n]&&void 0!==this.stats[t][n]||(this.stats[t][n]=0),this.stats[t][n]+=i}}upload(){if(!1===this.enable)return!1;const e=new Date-this.lastUpload,s=JSON.stringify(this.stats);if(!(u.UPLOAD_INTERVAL>=e)&&"{}"!==s&&fetch){const e=self.registration.scope.includes("quickconnect.to")?"to":"cn";fetch("https://global.quickconnect."+e+u.UPLOAD_PATH,{method:"POST",body:s,keepalive:!0}).then((e=>e.json())).then((e=>{null!==e.enable&&void 0!==e.enable&&"boolean"==typeof e.enable&&(this.enable!==e.enable&&t("sw traffic statistics:",e.enable),this.enable=e.enable)})).catch((e=>{t("fail to upload result",e)})),this.reset()}}}e(u,"UPLOAD_INTERVAL",3e4),e(u,"UPLOAD_PATH","/quickconnect/serviceworker/statistics/traffic");const d=new u,b="/scripts/workbox/";importScripts("/scripts/workbox/workbox-sw.js"),workbox.setConfig({modulePathPrefix:b,debug:!1}),workbox.loadModule("workbox-strategies"),workbox.loadModule("workbox-expiration");class g extends workbox.strategies.Strategy{constructor(){super(...arguments),this.tabManager=null}handle(e){return this.checkFallback(e),this._synoptions=e,super.handle(e)}checkFallback(e){const{event:s}=e;s.clientId;let n=null;if(null!==this.tabManager&&void 0!==this.tabManager||(n="no tabManager"),n)throw t("fallback:",n),n}async _handle(e,s){s.fetch=f.prototype.fetch,s._strategy=this;let n=null,i=null;"no-store"!==e.cache&&"reload"!==e.cache&&(i=await s.cacheMatch(e));try{n=await this.fetchAndCachePolicy(s,e,i)}catch(e){throw t("fetch error",e),e}return n}async fetchAndCachePolicy(e,s){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;const i=s.clone();if(n&&n.headers.get("ETag")){const e=new Headers(i.headers);e.set("If-None-Match",n.headers.get("ETag")),Object.defineProperty(i,"headers",{get:()=>e})}const a=await e.fetch(i);let r=null,o=null;return"no-store"!==s.cache&&(304===a.status?(r=n,o="cache"):(r=a,o="network"),null!=r&&e.waitUntil(e.cachePut(s,r.clone()))),t(o,"result",s.url,r),r}setTabManager(e){this.tabManager=e}getTabManager(){return this.tabManager}}class f extends workbox.strategies.StrategyHandler{constructor(){super(...arguments)}async fetch(e){const{event:t}=this;let s="string"==typeof e?new Request(e):e;if("navigate"===s.mode&&t instanceof FetchEvent&&t.preloadResponse){const e=await t.preloadResponse;if(e)return e}const{event:n}=this._strategy._synoptions,i=n.clientId;let a;n.request.url;const r=this._strategy.getTabManager();return a=await r.webrtcFetch(i,s),a}}class p extends workbox.strategies.NetworkOnly{handle(e){const{request:t,event:s}=e,n=super.handle(e);return n.then((e=>{d.update(s.clientId,t,e)})),n}}var T=new class{constructor(){this.tabManager=c,d.setTabManager(this.tabManager)}start(){this.registerSwEvents(),this.registerMessageEvent(),this.registerRoute()}registerSwEvents(){self.addEventListener("install",(e=>{this.flushCache(),self.skipWaiting()})),self.addEventListener("activate",(e=>{e.waitUntil(self.clients.claim()),e.waitUntil((async()=>{self.registration.navigationPreload&&await self.registration.navigationPreload.enable()}))}))}registerMessageEvent(){self.onmessage=async e=>{if("ping"===e.data)return;const t=e.ports;if(t.length>0){const s=e.source.id,n=t[0];n.postMessage({bindRequest:{launcherClientId:s,version:h.SwVersion}}),this.tabManager.pending(s,n)}else if(e.data){const t=e.source.id;if(e.data.bindAccept){const s=e.data.bindAccept;this.tabManager.bind(t,s)}else if(e.data.bindAcceptV2){const{launcherClientId:s,appName:n}=e.data.bindAcceptV2;this.tabManager.bind(t,s,n)}else if(e.data.bindReject){const t=e.data.bindAccept;this.tabManager.unpending(t)}else e.data.unbind?this.tabManager.unregister(t):e.data.flushCache?this.flushCache():s("error: receive unknown postMessage command from window")}}}flushCache(){s("flush cache"),self.caches.delete(h.CacheName)}registerRoute(){const e=new workbox.strategies.NetworkOnly,t=new p,s=new g({cacheName:h.CacheName,plugins:[new workbox.expiration.ExpirationPlugin({maxAgeSeconds:h.ExpireMaxAgeSeconds,maxEntries:h.ExpireMaxEntries})]});s.setTabManager(this.tabManager),this.registerGetRoute(s,h.WebrtcFetchTypeList),this.registerGetRoute(t,h.StatisticsFetchTypeList,(e=>(!0===e.url.includes(h.ReportStatisticsPath)&&d.upload(),!1))),workbox.routing.setCatchHandler((async t=>e.handle(t)))}registerGetRoute(e,t){let s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;if(!1==e instanceof workbox.strategies.Strategy)throw"wrong type of strategy";workbox.routing.registerRoute((e=>{let{request:n}=e;return("function"!=typeof s||!0!==s(n))&&((null===n.body||void 0===n.body)&&t.includes(n.destination))}),e,"GET")}};T.start()}();