From 9a07d092c4d8dcad08d61aecb66607a0abc83654 Mon Sep 17 00:00:00 2001 From: jonathanKingston Date: Wed, 26 Apr 2023 12:19:59 +0000 Subject: [PATCH] Release build 4.13.0 [ci release] --- .eslintrc | 1 - CODEOWNERS | 5 +- .../ContentScopeScripts/dist/contentScope.js | 394 +++++++-- build/android/contentScope.js | 394 +++++++-- build/chrome-mv3/inject.js | 760 +++++++++++----- build/chrome/inject.js | 69 +- build/contentScope.js | 807 ++++++++++++----- build/firefox/inject.js | 761 +++++++++++----- build/integration/contentScope.js | 807 ++++++++++++----- .../integration/pages/duckplayer/js/index.js | 53 +- build/tracker-lookup.json | 1 + build/windows/contentScope.js | 486 ++++++++--- build/windows/pages/duckplayer/js/index.js | 53 +- inject/android.js | 6 +- inject/apple.js | 6 +- inject/chrome-mv3.js | 8 +- inject/chrome.js | 8 +- inject/integration.js | 10 +- inject/mozilla.js | 7 +- inject/windows.js | 6 +- .../page-objects/duckplayer-overlays.js | 3 + integration-test/test-pages.js | 2 +- .../config/script-overload.json | 4 + .../runtime-checks/pages/basic-run.html | 26 + .../runtime-checks/pages/script-overload.html | 31 + package-lock.json | 810 ++++++++---------- package.json | 17 +- packages/special-pages/package.json | 2 +- .../pages/duckplayer/src/js/index.js | 3 +- scripts/bundleTrackers.mjs | 33 + scripts/generateSJCL.js | 7 +- scripts/utils/build.js | 9 +- src/content-feature.js | 101 ++- src/content-scope-features.js | 4 +- src/dom-utils.js | 68 ++ src/features/click-to-load.js | 30 +- src/features/click-to-load/ctl-assets.js | 5 +- src/features/click-to-load/ctl-config.js | 264 +++--- src/features/cookie.js | 99 ++- src/features/duck-player.js | 2 +- .../components/ddg-video-overlay.js | 12 +- src/features/duckplayer/icon-overlay.js | 9 +- src/features/duckplayer/text.js | 2 +- src/features/navigator-interface.js | 54 +- src/features/runtime-checks.js | 16 + .../runtime-checks/script-overload.js | 13 +- src/globals.d.ts | 3 +- src/trackers.js | 3 +- src/utils.js | 96 ++- tsconfig.json | 5 +- unit-test/dom-utils.js | 29 + unit-test/script-overload-snapshots/out/1.js | 12 +- unit-test/script-overload-snapshots/out/2.js | 12 +- unit-test/script-overload-snapshots/out/3.js | 12 +- unit-test/utils.js | 7 +- unit-test/verify-artifacts.js | 79 +- 56 files changed, 4607 insertions(+), 1919 deletions(-) create mode 100644 build/tracker-lookup.json create mode 100644 scripts/bundleTrackers.mjs create mode 100644 src/dom-utils.js create mode 100644 unit-test/dom-utils.js diff --git a/.eslintrc b/.eslintrc index 91a34cbef..646c541d7 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,7 +11,6 @@ "$USER_PREFERENCES$": "readonly", "$USER_UNPROTECTED_DOMAINS$": "readonly", "$CONTENT_SCOPE$": "readonly", - "$TRACKER_LOOKUP$": "readonly", "$BUNDLED_CONFIG$": "readonly", "windowsInteropPostMessage": "readonly", "windowsInteropAddEventListener": "readonly", diff --git a/CODEOWNERS b/CODEOWNERS index 302e80a42..d1f6066f5 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -4,8 +4,9 @@ src/features/fingerprinting-* @jonathanKingston @englehardt src/canvas.js @jonathanKingston @englehardt src/element-hiding.js @jonathanKingston @dharb -src/features/click-to-load.js @kzar @ladamski -src/locales/click-to-load/ @kzar @ladamski +src/features/click-to-load.js @kzar @ladamski @franfaccin @jonathanKingston @shakyShane +src/features/click-to-load/ @kzar @ladamski @franfaccin @jonathanKingston @shakyShane +src/locales/click-to-load/ @kzar @ladamski @franfaccin @jonathanKingston @shakyShane # Platform owners inject/android.js @jonathanKingston @joshliebe diff --git a/Sources/ContentScopeScripts/dist/contentScope.js b/Sources/ContentScopeScripts/dist/contentScope.js index c78c33cf6..9eae1255a 100644 --- a/Sources/ContentScopeScripts/dist/contentScope.js +++ b/Sources/ContentScopeScripts/dist/contentScope.js @@ -86,7 +86,7 @@ * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ - function isThirdParty () { + function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -288,7 +288,7 @@ /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ function processAttr (configSetting, defaultValue) { @@ -449,6 +449,16 @@ * @property {string} sessionKey */ + /** + * Used to inialize extension code in the load phase + */ + function computeLimitedSiteObject () { + const topLevelHostname = getTabHostname(); + return { + domain: topLevelHostname + } + } + /** * Expansion point to add platform specific versioning logic * @param {UserPreferences} preferences @@ -506,16 +516,23 @@ } /** - * @param {{ features: Record; unprotectedTemporary: string[]; }} data + * @typedef RemoteConfig + * @property {Record} features + * @property {string[]} unprotectedTemporary + */ + + /** + * @param {RemoteConfig} data * @param {string[]} userList * @param {UserPreferences} preferences * @param {string[]} platformSpecificFeatures */ function processConfig (data, userList, preferences, platformSpecificFeatures = []) { const topLevelHostname = getTabHostname(); + const site = computeLimitedSiteObject(); const allowlisted = userList.filter(domain => domain === topLevelHostname).length > 0; const remoteFeatureNames = Object.keys(data.features); - const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); + platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); /** @type {Record} */ const output = { ...preferences }; if (output.platform) { @@ -524,37 +541,65 @@ output.platform.version = version; } } + const enabledFeatures = computeEnabledFeatures(data, topLevelHostname, preferences.platform?.version, platformSpecificFeatures); + const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary); + output.site = Object.assign(site, { + isBroken, + allowlisted, + enabledFeatures + }); + // TODO + output.cookie = {}; + + // Copy feature settings from remote config to preferences object + output.featureSettings = parseFeatureSettings(data, enabledFeatures); + output.trackerLookup = {"org":{"cdn77":{"rsc":{"1666210260":1}},"adsrvr":1,"ampproject":1,"browser-update":1,"flowplayer":1,"privacy-center":1,"webvisor":1,"framasoft":1,"do-not-tracker":1,"trackersimulator":1},"io":{"1dmp":1,"1rx":1,"4dex":1,"adnami":1,"aidata":1,"arcspire":1,"bidr":1,"branch":1,"center":1,"concert":1,"connectad":1,"cordial":1,"dcmn":1,"extole":1,"getblue":1,"hbrd":1,"imbox":1,"instana":1,"karte":1,"lytics":1,"marchex":1,"mediago":1,"mrf":1,"myfidevs":1,"narrative":1,"ntv":1,"optad360":1,"oracleinfinity":1,"oribi":1,"p-n":1,"personalizer":1,"pghub":1,"piano":1,"powr":1,"pzz":1,"searchspring":1,"segment":1,"siteimproveanalytics":1,"sjv":1,"sspinc":1,"t13":1,"webgains":1,"wovn":1,"yellowblue":1,"zprk":1,"reviews":1,"appconsent":1,"leadsmonitor":1},"com":{"2020mustang":1,"33across":1,"360yield":1,"3lift":1,"4dsply":1,"4jnzhl0d0":1,"4strokemedia":1,"5d2d04464c":1,"a-mx":1,"a2z":1,"aamsitecertifier":1,"absorbingband":1,"abstractedauthority":1,"abtasty":1,"acexedge":1,"acidpigs":1,"acsbapp":1,"acuityplatform":1,"ad-score":1,"ad-stir":1,"adalyser":1,"adapf":1,"adara":1,"adblade":1,"addthis":1,"addtoany":1,"adelixir":1,"adentifi":1,"adextrem":1,"adgrx":1,"adhese":1,"adition":1,"adkernel":1,"adlightning":1,"adlooxtracking":1,"admanmedia":1,"admedo":1,"adnium":1,"adnxs":1,"adobedtm":1,"adotmob":1,"adpone":1,"adpushup":1,"adroll":1,"adrta":1,"ads-twitter":1,"ads3-adnow":1,"adsafeprotected":1,"adstanding":1,"adswizz":1,"adsymptotic":1,"adtdp":1,"adtechus":1,"adtelligent":1,"adthrive":1,"adtlgc":1,"adtng":1,"adultfriendfinder":1,"advangelists":1,"adventive":1,"advertising":1,"aegpresents":1,"affinity":1,"affirm":1,"agilone":1,"agkn":1,"aimbase":1,"albacross":1,"alcmpn":1,"alexametrics":1,"alicdn":1,"alikeaddition":1,"aliveachiever":1,"aliyuncs":1,"alluringbucket":1,"aloofvest":1,"amazon-adsystem":1,"amazon":1,"amplitude":1,"analytics-egain":1,"aniview":1,"anymind360":1,"amazonaws":{"ap-southeast-2":1,"elb":{"eu-west-2":{"collect-prd-alb-539115803":1},"us-east-1":{"data-allstate-com-715826933":1,"prod-lb-8-1772099769":1,"proxy-mycigna-prod-678433465":1,"www-u45-pnc-com-902993410":1,"www-u46-pnc-com-13593657":1},"eu-west-1":{"devservicesalb-471015105":1,"petfre-content-1201188928":1},"us-east-2":{"elbpiwik-public-1781721271":1},"eu-central-1":{"prod-lb-6-388533732":1,"prod-lb-7-718125029":1,"prod-pub-alb-654989386":1}},"us-east-2":{"s3":{"hb-gretsch-talk":1,"hb-jetpunk":1,"hb-obv2":1}},"eu-central-1":{"s3":{"headless-ssr-prod-bucket":1}}},"app-us1":1,"appboycdn":1,"appdynamics":1,"aralego":1,"arkoselabs":1,"aswpsdkus":1,"atemda":1,"att":1,"attentivemobile":1,"attractionbanana":1,"audioeye":1,"audrte":1,"automaticside":1,"avanser":1,"avmws":1,"aweber":1,"aweprt":1,"azure":1,"b0e8":1,"bagbeam":1,"bandborder":1,"batch":1,"bawdybalance":1,"bc0a":1,"bdstatic":1,"bedsberry":1,"beginnerpancake":1,"benchmarkemail":1,"betweendigital":1,"bfmio":1,"bidderstack":1,"bidtheatre":1,"bimbolive":1,"bing":1,"bizographics":1,"bizrate":1,"bkrtx":1,"blismedia":1,"blogherads":1,"bluecava":1,"bluekai":1,"boatwizard":1,"boilingcredit":1,"boldchat":1,"booking":1,"borderfree":1,"bounceexchange":1,"brainlyads":1,"brand-display":1,"brandmetrics":1,"brealtime":1,"breinify":1,"brightedge":1,"brightfunnel":1,"brightspotcdn":1,"btloader":1,"btstatic":1,"bttrack":1,"btttag":1,"butterbulb":1,"buzzoola":1,"byside":1,"cabnnr":1,"calculatorstatement":1,"callrail":1,"calltracks":1,"capablecup":1,"captcha-delivery":1,"carpentercomparison":1,"cartstack":1,"carvecakes":1,"casalemedia":1,"cdn-btsg":1,"cdnwidget":1,"channeladvisor":1,"chartbeat":1,"chatango":1,"chaturbate":1,"cheqzone":1,"cherriescare":1,"chickensstation":1,"childlikecrowd":1,"childlikeform":1,"cintnetworks":1,"circlelevel":1,"civiccomputing":1,"ck-ie":1,"clcktrax":1,"clearbit":1,"clearbitjs":1,"clickagy":1,"clickcease":1,"clickcertain":1,"clicktripz":1,"clientgear":1,"clksite":1,"cloudflare":1,"cloudflareinsights":1,"cloudflarestream":1,"cloudmaestro":1,"cobaltgroup":1,"cobrowser":1,"cognitivlabs":1,"colossusssp":1,"comm100":1,"googleapis":{"commondatastorage":1,"storage":1},"company-target":1,"condenastdigital":1,"confusedcart":1,"connatix":1,"consentframework":1,"contextweb":1,"conversionruler":1,"convertkit":1,"convertlanguage":1,"cookieinformation":1,"cookiepro":1,"coveo":1,"cpmstar":1,"cquotient":1,"crabbychin":1,"crazyegg":1,"creative-serving":1,"creativecdn":1,"criteo":1,"crowdedmass":1,"crowdriff":1,"crownpeak":1,"crsspxl":1,"ctnsnet":1,"cubchannel":1,"cudasvc":1,"cuddlethehyena":1,"cumbersomecarpenter":1,"curalate":1,"curvedhoney":1,"cutechin":1,"cxense":1,"dailymotion":1,"damdoor":1,"dampdock":1,"dapperfloor":1,"datadoghq-browser-agent":1,"decisivebase":1,"deepintent":1,"defybrick":1,"delivra":1,"demandbase":1,"detectdiscovery":1,"devilishdinner":1,"dimelochat":1,"discreetfield":1,"disqus":1,"dmpxs":1,"dockdigestion":1,"dollardelta":1,"dotomi":1,"doubleverify":1,"drainpaste":1,"dramaticdirection":1,"driftt":1,"dtscdn":1,"dtscout":1,"dwin1":1,"dynamics":1,"dynamicyield":1,"dynatrace":1,"dyntrk":1,"ebaystatic":1,"ecal":1,"eccmp":1,"elasticchange":1,"elfsight":1,"elitrack":1,"eloqua":1,"en25":1,"encouragingthread":1,"ensighten":1,"enviousshape":1,"eqads":1,"ero-advertising":1,"esputnik":1,"evergage":1,"evgnet":1,"exdynsrv":1,"exelator":1,"exoclick":1,"exosrv":1,"expansioneggnog":1,"expertrec":1,"exponea":1,"exponential":1,"extole":1,"ezodn":1,"ezoic":1,"ezoiccdn":1,"facebook":1,"fadewaves":1,"fallaciousfifth":1,"farmergoldfish":1,"fastly-insights":1,"fearlessfaucet":1,"fiftyt":1,"financefear":1,"fitanalytics":1,"five9":1,"fksnk":1,"flashtalking":1,"flipp":1,"floweryflavor":1,"flutteringfireman":1,"flux-cdn":1,"fomo":1,"foresee":1,"forter":1,"fortunatemark":1,"fouanalytics":1,"fox":1,"fqtag":1,"frailfruit":1,"freezingbuilding":1,"fronttoad":1,"fullstory":1,"functionalfeather":1,"fuzzybasketball":1,"gammamaximum":1,"gbqofs":1,"geetest":1,"geistm":1,"geniusmonkey":1,"geoip-js":1,"getbread":1,"getcandid":1,"getclicky":1,"getdrip":1,"getelevar":1,"getpublica":1,"getrockerbox":1,"getshogun":1,"getsitecontrol":1,"glassdoor":1,"gloriousbeef":1,"godpvqnszo":1,"gondolagnome":1,"google-analytics":1,"google":1,"googleadservices":1,"googlehosted":1,"googleoptimize":1,"googlesyndication":1,"googletagmanager":1,"googletagservices":1,"govx":1,"greylabeldelivery":1,"groovehq":1,"gstatic":1,"guarantee-cdn":1,"guiltlessbasketball":1,"gumgum":1,"haltingbadge":1,"hammerhearing":1,"handsomelyhealth":1,"hawksearch":1,"heapanalytics":1,"hellobar":1,"hiconversion":1,"highwebmedia":1,"histats":1,"hlserve":1,"hocgeese":1,"hollowafterthought":1,"honorableland":1,"hotjar":1,"hp":1,"hs-banner":1,"htlbid":1,"htplayground":1,"hubspot":1,"iadvize":1,"ib-ibi":1,"id5-sync":1,"iesnare":1,"igodigital":1,"iheart":1,"iljmp":1,"illiweb":1,"impactcdn":1,"impactradius-event":1,"impactradius-go":1,"impossibleexpansion":1,"impressionmonster":1,"improvedcontactform":1,"improvedigital":1,"imrworldwide":1,"indexww":1,"infolinks":1,"infusionsoft":1,"inmobi":1,"inmoment":1,"inq":1,"inside-graph":1,"instagram":1,"intentiq":1,"intergient":1,"investingchannel":1,"invocacdn":1,"iplsc":1,"ipredictive":1,"iteratehq":1,"ivitrack":1,"j93557g":1,"jaavnacsdw":1,"jimstatic":1,"journity":1,"js7k":1,"juicyads":1,"justanswer":1,"justpremium":1,"kakao":1,"kampyle":1,"kargo":1,"kissmetrics":1,"klarnaservices":1,"klaviyo":1,"knottyswing":1,"kount":1,"krushmedia":1,"ktkjmp":1,"kxcdn":1,"ladesk":1,"ladsp":1,"laughablelizards":1,"leadsrx":1,"lendingtree":1,"levexis":1,"liadm":1,"licdn":1,"lightboxcdn":1,"lijit":1,"linkedin":1,"linksynergy":1,"list-manage":1,"listrakbi":1,"livechatinc":1,"livejasmin":1,"localytics":1,"loggly":1,"loop11":1,"lovelydrum":1,"luckyorange":1,"lunchroomlock":1,"maddeningpowder":1,"mailchimp":1,"mailchimpapp":1,"mailerlite":1,"maillist-manage":1,"marinsm":1,"marketiq":1,"marketo":1,"marriedbelief":1,"matheranalytics":1,"mathtag":1,"maxmind":1,"mczbf":1,"measlymiddle":1,"medallia":1,"media6degrees":1,"mediacategory":1,"mediavine":1,"mediawallahscript":1,"medtargetsystem":1,"megpxs":1,"metricode":1,"metricswpsh":1,"mfadsrvr":1,"mgid":1,"micpn":1,"microadinc":1,"minutemedia-prebid":1,"minutemediaservices":1,"mixpo":1,"mktoresp":1,"mktoweb":1,"ml314":1,"moatads":1,"mobtrakk":1,"monsido":1,"mookie1":1,"mountain":1,"mouseflow":1,"mpeasylink":1,"mql5":1,"mrtnsvr":1,"murdoog":1,"mxpnl":1,"mybestpro":1,"myfinance":1,"myregistry":1,"nappyattack":1,"navistechnologies":1,"neodatagroup":1,"nervoussummer":1,"newrelic":1,"newscgp":1,"nextdoor":1,"ninthdecimal":1,"nitrocdn":1,"noibu":1,"nondescriptnote":1,"nosto":1,"npttech":1,"nuance":1,"nxsttv":1,"omappapi":1,"omnisnippet1":1,"omnisrc":1,"omnitagjs":1,"oneall":1,"onesignal":1,"onetag-sys":1,"oo-syringe":1,"ooyala":1,"opecloud":1,"opentext":1,"opera":1,"opmnstr":1,"optimicdn":1,"optinmonster":1,"optmnstr":1,"optmstr":1,"optnmnstr":1,"optnmstr":1,"oraclecloud":1,"osano":1,"otm-r":1,"outbrain":1,"overconfidentfood":1,"ownlocal":1,"pamelarandom":1,"panickypancake":1,"panoramicplane":1,"parastorage":1,"pardot":1,"parsely":1,"partplanes":1,"patreon":1,"paypal":1,"pbstck":1,"pcmag":1,"peerius":1,"perfdrive":1,"perfectmarket":1,"permutive":1,"picreel":1,"pinimg":1,"pippio":1,"piwikpro":1,"pixlee":1,"pleasantpump":1,"plotrabbit":1,"pluckypocket":1,"pocketfaucet":1,"possibleboats":1,"postaffiliatepro":1,"postrelease":1,"potatoinvention":1,"prepareplanes":1,"pricespider":1,"pricklydebt":1,"profusesupport":1,"proofpoint":1,"protoawe":1,"providesupport":1,"pswec":1,"psyma":1,"ptengine":1,"publir":1,"pubmatic":1,"pubmine":1,"pubnation":1,"puffypurpose":1,"qualaroo":1,"qualtrics":1,"quantcast":1,"quantserve":1,"quantummetric":1,"quietknowledge":1,"quizzicalzephyr":1,"quora":1,"r42tag":1,"railwayreason":1,"rakuten":1,"rambunctiousflock":1,"rangeplayground":1,"realsrv":1,"rebelswing":1,"reconditerake":1,"reconditerespect":1,"recruitics":1,"reddit":1,"redditstatic":1,"rehabilitatereason":1,"reson8":1,"resonantrock":1,"responsiveads":1,"restrainstorm":1,"retargetly":1,"revcontent":1,"rezync":1,"rfihub":1,"rhetoricalloss":1,"richaudience":1,"righteouscrayon":1,"rightfulfall":1,"riotgames":1,"rkdms":1,"rlcdn":1,"rmtag":1,"rncdn5":1,"rnengage":1,"rogersmedia":1,"rokt":1,"route":1,"rubiconproject":1,"s-onetag":1,"saambaa":1,"sablesong":1,"sail-horizon":1,"salesforceliveagent":1,"samestretch":1,"satisfycork":1,"savoryorange":1,"scarabresearch":1,"scaredsnakes":1,"scarfsmash":1,"scatteredstream":1,"scene7":1,"scholarlyiq":1,"scintillatingsilver":1,"scorecardresearch":1,"screechingstove":1,"screenpopper":1,"sddan":1,"sdiapi":1,"seatsmoke":1,"securedvisit":1,"seedtag":1,"sefsdvc":1,"segment":1,"sekindo":1,"selectivesummer":1,"selfishsnake":1,"servebom":1,"servedbyadbutler":1,"servenobid":1,"serverbid":1,"serving-sys":1,"shakegoldfish":1,"shappify":1,"shareaholic":1,"sharethis":1,"sharethrough":1,"shopifyapps":1,"shopperapproved":1,"shrillspoon":1,"sibautomation":1,"sicksmash":1,"sift":1,"siftscience":1,"signifyd":1,"siteimprove":1,"siteimproveanalytics":1,"sitescout":1,"skillfuldrop":1,"sli-spark":1,"slickstream":1,"slopesoap":1,"smadex":1,"smartadserver":1,"smashquartz":1,"smashsurprise":1,"smg":1,"smilewanted":1,"smoggysnakes":1,"snapchat":1,"snapkit":1,"snigelweb":1,"socdm":1,"sojern":1,"songsterritory":1,"sonobi":1,"speedcurve":1,"sphereup":1,"spiceworks":1,"spookyexchange":1,"spookyskate":1,"spookysleet":1,"sportradar":1,"sportradarserving":1,"sportslocalmedia":1,"spotxchange":1,"springserve":1,"srvmath":1,"stackadapt":1,"stakingsmile":1,"statcounter":1,"steadfastseat":1,"steadfastsound":1,"steadfastsystem":1,"steelhousemedia":1,"steepsquirrel":1,"stereoproxy":1,"stereotypedsugar":1,"stickyadstv":1,"stiffgame":1,"straightnest":1,"stripchat":1,"stupendoussleet":1,"stupendoussnow":1,"stupidscene":1,"sulkycook":1,"sumo":1,"sumologic":1,"sundaysky":1,"superficialeyes":1,"superficialsquare":1,"survicate":1,"svonm":1,"symantec":1,"taboola":1,"tagcommander":1,"tailtarget":1,"talkable":1,"taobao":1,"tapad":1,"taptapnetworks":1,"taskanalytics":1,"tealiumiq":1,"technoratimedia":1,"techtarget":1,"tediousticket":1,"teenytinyshirt":1,"tendertest":1,"the-ozone-project":1,"theadex":1,"themoneytizer":1,"theplatform":1,"thestar":1,"thomastorch":1,"threetruck":1,"thrtle":1,"tidaltv":1,"tidiochat":1,"tiktok":1,"tinypass":1,"tiqcdn":1,"tiresomethunder":1,"trackjs":1,"trafficjunky":1,"travelaudience":1,"treasuredata":1,"tremorhub":1,"trendemon":1,"tribalfusion":1,"trovit":1,"trueleadid":1,"truoptik":1,"truste":1,"trustedsite":1,"trustpilot":1,"tsyndicate":1,"tubemogul":1,"turn":1,"tvpixel":1,"tvsquared":1,"tweakwise":1,"twitter":1,"tynt":1,"typicalteeth":1,"u5e":1,"ubembed":1,"uidapi":1,"ultraoranges":1,"unbecominglamp":1,"unbxdapi":1,"undertone":1,"uninterestedquarter":1,"unpkg":1,"unrulymedia":1,"unwieldyhealth":1,"unwieldyplastic":1,"upsellit":1,"urbanairship":1,"usabilla":1,"usbrowserspeed":1,"usemessages":1,"userreport":1,"uservoice":1,"valuecommerce":1,"vengefulgrass":1,"vidazoo":1,"videoplayerhub":1,"vidoomy":1,"viglink":1,"visualwebsiteoptimizer":1,"vivaclix":1,"vk":1,"vlitag":1,"vocento":1,"voicefive":1,"volatilevessel":1,"voraciousgrip":1,"voxmedia":1,"vrtcal":1,"w3counter":1,"walkme":1,"warmafterthought":1,"warmquiver":1,"webcontentassessor":1,"webengage":1,"webeyez":1,"webflow":1,"webtraxs":1,"webtrends-optimize":1,"webtrends":1,"wgplayer":1,"wisepops":1,"worldoftulo":1,"wpadmngr":1,"wpshsdk":1,"wpushsdk":1,"wsod":1,"wt-safetag":1,"wysistat":1,"xg4ken":1,"xiti":1,"xlirdr":1,"xlivrdr":1,"xnxx-cdn":1,"y-track":1,"yahoo":1,"yandex":1,"yieldmo":1,"yieldoptimizer":1,"yimg":1,"yotpo":1,"yottaa":1,"youtube-nocookie":1,"youtube":1,"zatnoh":1,"zemanta":1,"zendesk":1,"zeotap":1,"zeronaught":1,"zestycrime":1,"zonos":1,"zoominfo":1,"zopim":1,"adnxs-simple":1,"createsend1":1,"adventori":1,"facil-iti":1,"provenexpert":1,"veoxa":1,"getflowbox":1,"parchedsofa":1,"adtraction":1,"bannerflow":1,"aboardamusement":1,"absorbingcorn":1,"abstractedamount":1,"actoramusement":1,"actuallysnake":1,"adorableanger":1,"agreeabletouch":1,"aheadday":1,"ancientact":1,"annoyedairport":1,"annoyingacoustics":1,"aquaticowl":1,"aspiringattempt":1,"audioarctic":1,"awarealley":1,"awesomeagreement":1,"awzbijw":1,"basketballbelieve":1,"begintrain":1,"bestboundary":1,"blushingbeast":1,"boredcrown":1,"breadbalance":1,"breakfastboat":1,"bulbbait":1,"burnbubble":1,"bustlingbath":1,"callousbrake":1,"calmcactus":1,"capriciouscorn":1,"caringcast":1,"catschickens":1,"causecherry":1,"chunkycactus":1,"cloisteredcord":1,"closedcows":1,"colossalclouds":1,"colossalcoat":1,"comfortablecheese":1,"conditioncrush":1,"consciouscheese":1,"consciousdirt":1,"coverapparatus":1,"cratecamera":1,"critictruck":1,"curvycry":1,"cushionpig":1,"damageddistance":1,"debonairdust":1,"decisivedrawer":1,"decisiveducks":1,"detailedkitten":1,"diplomahawaii":1,"dk4ywix":1,"dq95d35":1,"energeticladybug":1,"enormousearth":1,"evanescentedge":1,"fadedsnow":1,"fancyactivity":1,"farshake":1,"fastenfather":1,"fatcoil":1,"faultycanvas":1,"firstfrogs":1,"flimsycircle":1,"flimsythought":1,"friendwool":1,"fumblingform":1,"futuristicfifth":1,"giddycoat":1,"giraffepiano":1,"glisteningguide":1,"grayreceipt":1,"greasysquare":1,"grouchypush":1,"haltinggold":1,"handyfield":1,"handyfireman":1,"hearthorn":1,"historicalbeam":1,"horsenectar":1,"hystericalcloth":1,"impulsejewel":1,"incompetentjoke":1,"internalsink":1,"lameletters":1,"livelumber":1,"livelylaugh":1,"lorenzourban":1,"lumpylumber":1,"maliciousmusic":1,"meatydime":1,"memorizeneck":1,"mightyspiders":1,"mixedreading":1,"modularmental":1,"motionlessbag":1,"movemeal":1,"nondescriptcrowd":1,"nostalgicneed":1,"nuttyorganization":1,"optimallimit":1,"outstandingincome":1,"outstandingsnails":1,"panickycurtain":1,"petiteumbrella":1,"placidperson":1,"plantdigestion":1,"punyplant":1,"rabbitbreath":1,"rabbitrifle":1,"raintwig":1,"rainyhand":1,"rainyrule":1,"rangecake":1,"raresummer":1,"readymoon":1,"rebelsubway":1,"receptivereaction":1,"regularplants":1,"repeatsweater":1,"replaceroute":1,"resonantbrush":1,"respectrain":1,"richstring":1,"roofrelation":1,"rusticprice":1,"scaredcomfort":1,"scaredsnake":1,"scientificshirt":1,"scintillatingscissors":1,"screechingfurniture":1,"seashoresociety":1,"secretturtle":1,"shakysurprise":1,"shallowblade":1,"shesubscriptions":1,"shockingship":1,"sillyscrew":1,"sincerebuffalo":1,"sinceresubstance":1,"singroot":1,"sixscissors":1,"soggysponge":1,"somberscarecrow":1,"sordidsmile":1,"sortsail":1,"sortsummer":1,"spellsalsa":1,"spotlessstamp":1,"spottednoise":1,"stalesummer":1,"steadycopper":1,"stepplane":1,"strangesink":1,"stretchsister":1,"strivesidewalk":1,"superficialspring":1,"swellstocking":1,"synonymousrule":1,"tangyamount":1,"tastelesstrees":1,"teenytinycellar":1,"teenytinytongue":1,"terriblethumb":1,"terrifictooth":1,"thirdrespect":1,"ticketaunt":1,"tremendousplastic":1,"troubledtail":1,"typicalairplane":1,"ubiquitousyard":1,"unbecominghall":1,"uncoveredexpert":1,"unequalbrake":1,"unknowncrate":1,"untidyrice":1,"unusedstone":1,"venusgloria":1,"verdantanswer":1,"verseballs":1,"wearbasin":1,"cautiouscredit":1,"confesschairs":1,"chinsnakes":1,"wellgroomedhydrant":1,"heavyplayground":1,"bravecalculator":1,"workoperation":1,"secondhandfall":1,"unablehope":1,"tastelesstrucks":1,"losslace":1,"barbarousbase":1,"supportwaves":1,"protestcopy":1,"automaticturkey":1,"stretchsquirrel":1,"equablekettle":1,"discreetquarter":1,"peacefullimit":1,"gulliblegrip":1,"swelteringsleep":1,"muteknife":1,"aliasanvil":1,"operationchicken":1,"courageousbaby":1,"flowerstreatment":1,"scissorsstatement":1,"furryfork":1,"synonymoussticks":1,"deerbeginner":1,"rhetoricalveil":1,"farsnails":1,"kaputquill":1,"digestiondrawer":1,"meltmilk":1,"endurablebulb":1,"sugarfriction":1,"combcompetition":1,"stakingshock":1,"stretchsneeze":1,"sinkbooks":1,"brotherslocket":1,"cautiouscamera":1,"materialparcel":1,"inputicicle":1,"chargecracker":1,"fewjuice":1,"tumbleicicle":1,"serpentshampoo":1,"nutritiousbean":1,"scrapesleep":1,"bleachbubble":1,"longingtrees":1,"leftliquid":1,"handsomehose":1,"powerfulcopper":1,"painstakingpickle":1,"swankysquare":1,"soundstocking":1,"disagreeabledrop":1,"cushiondrum":1,"ruralrobin":1,"gorgeousedge":1,"strivesquirrel":1,"currentcollar":1,"combativecar":1,"ambiguousafternoon":1,"harborcaption":1,"blushingbread":1,"suggestionbridge":1,"spectacularstamp":1,"skisofa":1,"predictplate":1,"shakyseat":1,"priceypies":1,"livelyreward":1,"stealsteel":1,"shiveringspot":1,"memorizematch":1,"knitstamp":1,"bushesbag":1,"mundanenail":1,"coldbalance":1,"shapecomb":1,"shiverscissors":1,"broadborder":1,"quirkysugar":1,"stingyspoon":1,"billowybelief":1,"crookedcreature":1,"acceptableauthority":1,"sadloaf":1,"separatesort":1,"pailpatch":1,"scribblestring":1,"exhibitsneeze":1,"largebrass":1,"combcattle":1,"materialisticmoon":1,"fixedfold":1,"restructureinvention":1,"scaredstomach":1,"cautiouscherries":1,"tritebadge":1,"motionflowers":1,"ballsbanana":1,"meddleplant":1,"simulateswing":1,"marketspiders":1,"grumpydime":1,"neatshade":1,"samplesamba":1,"samesticks":1,"buttonladybug":1,"mentorsticks":1,"scaredsong":1,"annoyingclover":1,"grainmass":1,"tempertrick":1,"quizzicalpartner":1,"franticroof":1,"cattlecommittee":1,"tangycover":1,"looseloaf":1,"psychedelicarithmetic":1,"radiateprose":1,"shamerain":1,"cleanhaircut":1,"badgevolcano":1,"laboredlocket":1,"zipperxray":1,"stingycrush":1,"sixauthority":1,"thinkitten":1,"strokesystem":1,"hatefulrequest":1},"net":{"2mdn":1,"2o7":1,"incapdns":{"x":{"3exvfbh":1,"5t48cjc":1,"7xjpy4d":1,"dzm868l":1,"ttk8bbo":1}},"3gl":1,"a-mo":1,"acint":1,"adform":1,"adhigh":1,"admixer":1,"adobedc":1,"adspeed":1,"azureedge":{"adv-cloudfilse":1,"afw-static":1,"bayleys-pri-cdn-endpoint":1,"cdne-nxtevo-prd01-ms":1,"discountcodeexpress":1,"fp-cdn":1,"lefigaro":1,"ocpd-content":1,"sdtagging":1,"trenord-europe-trenord-endpoint-prd":1},"adverticum":1,"edgekey":{"akamai-111035":1,"com":{"alicdn":1,"ebay":1,"mtvnservices":1,"nbcuni":1,"nintendo":1,"oneindia":1,"scene7":1,"turner":1,"ziffdavis":1,"ziffdavisinternational":1},"ame":1,"au":1,"br":1,"ca":1,"com-v1":1,"com-v2":1,"gov":1,"in":1,"io":1,"it":1,"net":1,"org":1,"ppll":1,"rakuten":1,"uk":1},"apicit":1,"appier":1,"akamaized":{"assets-momentum":1,"com":{"media-rockstargames-":1,"ntd":1,"vocento":1}},"aticdn":1,"azure":1,"azurefd":1,"bannerflow":1,"bf-tools":1,"bidswitch":1,"bitsngo":1,"blueconic":1,"boldapps":1,"buysellads":1,"cedexis":1,"certona":1,"fastly":{"map":{"cidgroup":1,"condenast":1,"ihrinferno":1,"prisa-us-eu":1,"scribd":1,"target-opus":1,"thriftbooks":1,"ticketmaster4":1,"twitch":1,"vox":1,"appnexus":1},"global":{"shared":{"d2":1,"s2":1},"sni":{"j":1}},"ssl":{"global":{"igao-prod-herokuapp-com":1,"mslc-prod-herokuapp-com":1}}},"confiant-integrations":1,"consentmanager":1,"contentsquare":1,"criteo":1,"crwdcntrl":1,"cloudfront":{"d16jny3kjm2a1j":1,"d16kgn4efacaad":1,"d19l6uotjzm32g":1,"d1af033869koo7":1,"d1bxz6tua5hq87":1,"d1cr9zxt7u0sgu":1,"d1egjda7ggd2ew":1,"d1eh9yux7w8iql":1,"d1gwclp1pmzk26":1,"d1nhstnts0iwzs":1,"d1p5cqqchvbqmy":1,"d1pq45hly7zfel":1,"d1rhs7mhgydok3":1,"d1rw50yn65615p":1,"d1s87id6169zda":1,"d1snv67wdds0p2":1,"d1tprjo2w7krrh":1,"d1vg5xiq7qffdj":1,"d1vo8zfysxy97v":1,"d1y068gyog18cq":1,"d214hhm15p4t1d":1,"d21gpk1vhmjuf5":1,"d244lyzgucnepm":1,"d27cwqlgojh9yd":1,"d2aioe7l2jay46":1,"d2bj4wnxqmm2tk":1,"d2droglu4qf8st":1,"d2eanzqpmoo3ec":1,"d2f4zoo8hyailp":1,"d2hs2r19gv871k":1,"d2j6syf6c0cltf":1,"d2jpq2u2vrjftk":1,"d2qlgd5odkppg5":1,"d2qrdklrsxowl2":1,"d2s6j0ghajv79z":1,"d2tyltutevw8th":1,"d2wo2i8fdcw8of":1,"d2xbocf5uqnw0w":1,"d2y7rifa1cwopa":1,"d2zah9y47r7bi2":1,"d30jydkdo8eo9b":1,"d355prp56x5ntt":1,"d35mt2i8wrf9y1":1,"d38aqfmkl3ge26":1,"d38xvr37kwwhcm":1,"d3fv2pqyjay52z":1,"d3gxe0jmvtuxbc":1,"d3i4yxtzktqr9n":1,"d3jruqy3qmm3fd":1,"d3nn82uaxijpm6":1,"d3o8vwpyaorolj":1,"d3ochae1kou2ub":1,"d3odp2r1osuwn0":1,"d3owq2fdwtdp2j":1,"d3txh7prdum3s8":1,"d3v7mj6iyaqfac":1,"d4egga2bwam6h":1,"d5yoctgpv4cpx":1,"d6tizftlrpuof":1,"d9k0w0y3delq8":1,"dbukjj6eu5tsf":1,"de2pmm85odupd":1,"de7iszmjjjuya":1,"dfx0d9twj2ai":1,"dj28g4s0yd4ph":1,"dn0qt3r0xannq":1,"dokumfe7mps0i":1,"dowpznhhyvkm4":1,"dsh7ky7308k4b":1,"dsx863kqtdxrt":1,"dtpw88eywzb7u":1,"duube1y6ojsji":1,"dzlkq6toxiazj":1,"dzz1zjxa9ulpk":1,"d2638j3z8ek976":1},"akadns":{"com":{"dellcdn":1,"febsec-fidelity":1},"line-zero":1},"demdex":1,"dotmetrics":1,"doubleclick":1,"durationmedia":1,"e-planning":1,"edgecastcdn":1,"emsecure":1,"episerver":1,"esm1":1,"eulerian":1,"everestjs":1,"everesttech":1,"eyeota":1,"ezoic":1,"facebook":1,"fastclick":1,"fbcdn":1,"fonts":1,"edgesuite":{"com":{"fox":1,"iq":1,"tiktokcdn-us":1,"vidio":1,"sky":1},"linkedin":1,"stls":1},"fuseplatform":1,"fwmrm":1,"go-mpulse":1,"hadronid":1,"hs-analytics":1,"hsleadflows":1,"im-apps":1,"impervadns":1,"iocnt":1,"iprom":1,"jsdelivr":1,"kanade-ad":1,"azurewebsites":{"keha-matomo-te-palvelut-prod":1,"neuterbot-client":1,"app-ch-sgtm-prod":1,"app-fnsp-matomo-analytics-prod":1},"krxd":1,"line-scdn":1,"listhub":1,"livecom":1,"livedoor":1,"liveperson":1,"lkqd":1,"llnwd":1,"lpsnmedia":1,"magnetmail":1,"marketo":1,"maxymiser":1,"media":1,"microad":1,"monetate":1,"mxptint":1,"myfonts":1,"myvisualiq":1,"naver":1,"b-cdn":{"nnwwwlive":1,"speedy":1},"nr-data":1,"omtrdc":1,"onecount":1,"online-metrix":1,"openx":1,"opta":1,"owneriq":1,"pages02":1,"pages03":1,"pages04":1,"pages05":1,"pages06":1,"pages08":1,"perimeterx":1,"pingdom":1,"pmdstatic":1,"popads":1,"popcash":1,"primecaster":1,"pro-market":1,"px-cloud":1,"akamaihd":{"pxlclnmdecom-a":1},"r9cdn":1,"rfihub":1,"sancdn":1,"sc-static":1,"semasio":1,"sensic":1,"trafficmanager":{"serviceschipotlecom":1},"sexad":1,"smaato":1,"spreadshirts":1,"storygize":1,"tfaforms":1,"trackcmp":1,"trackedlink":1,"truste-svc":1,"uuidksinc":1,"viafoura":1,"visilabs":1,"visx":1,"w55c":1,"wdsvc":1,"witglobal":1,"yandex":1,"yastatic":1,"yieldlab":1,"ywxi":1,"zdbb":1,"zencdn":1,"zucks":1,"eviltracker":1},"co":{"6sc":1,"ayads":1,"datadome":1,"idio":1,"increasingly":1,"jads":1,"nanorep":1,"nc0":1,"pcdn":1,"prmutv":1,"resetdigital":1,"t":1,"tctm":1,"zip":1},"de":{"71i":1,"adscale":1,"auswaertiges-amt":1,"fiduciagad":1,"ioam":1,"itzbund":1,"werk21system":1},"gt":{"ad":1},"jp":{"adingo":1,"admatrix":1,"auone":1,"co":{"dmm":1,"google":1,"rakuten":1,"yahoo":1},"fout":1,"gmossp-sp":1,"gssprt":1,"ne":{"hatena":1},"impact-ad":1,"microad":1,"nakanohito":1,"ptengine":1,"r10s":1,"reemo-ad":1,"rtoaster":1,"shinobi":1,"team-rec":1,"uncn":1,"yimg":1,"yjtag":1},"pl":{"adocean":1,"dreamlab":1,"gemius":1,"nsaudience":1,"onet":1,"salesmanago":1,"wp":1},"pro":{"adpartner":1,"piwik":1,"usocial":1},"ru":{"adriver":1,"digitaltarget":1,"mail":1,"mindbox":1,"rambler":1,"sape":1,"smi2":1,"tns-counter":1,"top100":1,"ulogin":1,"yandex":1},"re":{"adsco":1},"info":{"adxbid":1,"bitrix":1,"navistechnologies":1,"usergram":1,"webantenna":1},"tv":{"affec":1,"attn":1,"iris":1,"ispot":1,"samba":1,"teads":1,"twitch":1},"dev":{"amazon":1},"us":{"amung":1,"samplicio":1,"slgnt":1,"trkn":1},"media":{"andbeyond":1,"nextday":1,"townsquare":1,"underdog":1},"link":{"app":1},"cloud":{"avct":1,"coremedia":1,"egain":1,"matomo":1},"delivery":{"ay":1,"monu":1},"br":{"com":{"btg360":1,"clearsale":1,"jsuol":1,"shopconvert":1,"shoptarget":1,"soclminer":1},"org":{"ivcbrasil":1}},"ch":{"ch":1,"da-services":1,"google":1},"ms":{"clarity":1},"my":{"cnt":1},"se":{"codigo":1},"me":{"contentexchange":1,"grow":1,"line":1,"loopme":1,"t":1,"channel":1},"to":{"cpx":1,"tawk":1},"chat":{"crisp":1,"gorgias":1},"fr":{"d-bi":1,"open-system":1,"weborama":1},"uk":{"co":{"dailymail":1,"hsbc":1}},"id":{"net":{"detik":1}},"ai":{"e-volution":1,"m2":1,"nrich":1,"wknd":1},"be":{"geoedge":1},"au":{"com":{"google":1,"news":1,"nine":1,"realestate":1,"zipmoney":1,"telstra":1}},"stream":{"ibclick":1},"cz":{"imedia":1,"seznam":1,"trackad":1},"app":{"infusionsoft":1,"permutive":1,"shop":1},"tech":{"ingage":1,"primis":1},"eu":{"kameleoon":1,"medallia":1,"media01":1,"ocdn":1,"rqtrk":1,"slgnt":1,"usercentrics":1},"fi":{"kesko":1,"simpli":1},"live":{"lura":1},"services":{"marketingautomation":1},"sg":{"mediacorp":1},"bi":{"newsroom":1},"fm":{"pdst":1},"ad":{"pixel":1},"xyz":{"playground":1},"it":{"plug":1,"repstatic":1,"stbm":1},"cc":{"popin":1},"network":{"pub":1},"nl":{"rijksoverheid":1,"google":1},"fyi":{"sda":1},"pe":{"shop":1},"es":{"socy":1},"im":{"spot":1},"market":{"spotim":1},"am":{"tru":1},"at":{"waust":1},"gov":{"weather":1},"in":{"zoho":1},"ca":{"bc":{"gov":1}},"no":{"acdn":1,"uio":1},"example":{"ad-company":1},"site":{"ad-company":1,"third-party":{"bad":1,"broken":1}},"pw":{"zlp6s":1}}; + + return output + } + + /** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ + function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features); + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); const enabledFeatures = remoteFeatureNames.filter((featureName) => { const feature = data.features[featureName]; // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion - if (feature.minSupportedVersion && preferences.platform?.version) { - if (!isSupportedVersion(feature.minSupportedVersion, preferences.platform.version)) { + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { return false } } return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config - const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary); - output.site = { - domain: topLevelHostname, - isBroken, - allowlisted, - enabledFeatures - }; - // TODO - output.cookie = {}; + return enabledFeatures + } - // Copy feature settings from remote config to preferences object - output.featureSettings = {}; + /** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ + function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {}; + const remoteFeatureNames = Object.keys(data.features); remoteFeatureNames.forEach((featureName) => { if (!enabledFeatures.includes(featureName)) { return } - output.featureSettings[featureName] = data.features[featureName].settings; + featureSettings[featureName] = data.features[featureName].settings; }); - - return output + return featureSettings } function isGloballyDisabled (args) { @@ -1136,13 +1181,43 @@ return parseJSONPointer(fromPointer); } + /** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + + /** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName; - this._args = null; + this.#args = null; this.monitor = new PerformanceMonitor(); } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -1155,6 +1230,34 @@ return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -1171,10 +1274,11 @@ /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting(); + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName); if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -1194,17 +1298,22 @@ return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name); - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name); + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName); + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName); return result === 'enabled' } @@ -1213,9 +1322,11 @@ * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain; + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || []; return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -1225,7 +1336,7 @@ callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit'); - this._args = args; + this.#args = args; this.platform = args.platform; this.init(args); mark.end(); @@ -1238,14 +1349,23 @@ callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad'); - this._args = args; + this.#args = args; this.platform = args.platform; + this.#bundledConfig = args.bundledConfig; + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version); + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures); + } + this.#trackerLookup = args.trackerLookup; + this.#documentOriginIsTracker = args.documentOriginIsTracker; this.load(args); mark.end(); } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll(); } } @@ -1317,15 +1437,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property]; + let targetOut = target; + if (typeof property === 'string' && property in outputs) { + targetOut = outputs; + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -1382,7 +1504,6 @@ function wrapScriptCodeOverload (code, config) { const processedConfig = {}; for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value); } // Don't do anything if the config is empty @@ -1464,7 +1585,9 @@ // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -1688,6 +1811,13 @@ return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -1697,6 +1827,13 @@ return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -4104,6 +4241,34 @@ } } + /** + * Check if the current document origin is on the tracker list, using the provided lookup trie. + * @param {object} trackerLookup Trie lookup of tracker domains + * @returns {boolean} True iff the origin is a tracker. + */ + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { + const parts = originHostname.split('.').reverse(); + let node = trackerLookup; + for (const sub of parts) { + if (node[sub] === 1) { + return true + } else if (node[sub]) { + node = node[sub]; + } else { + return false + } + } + return false + } + + /** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ + // Initial cookie policy pre init let cookiePolicy = { debug: false, @@ -4112,12 +4277,18 @@ shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) }; + let trackerLookup = {}; let loadedPolicyResolve; @@ -4137,6 +4308,9 @@ }); } + /** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -4145,26 +4319,45 @@ return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } + /** + * @param {Set} scriptOrigins + * @returns {boolean} + */ + function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false; + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup, scriptOrigin)) { + matched = true; + } + } + return matched + } + + /** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true; } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup = this.trackerLookup; + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie; + const { exceptions, settings } = this.bundledConfig.features.cookie; const tabHostname = getTabHostname(); let tabExempted = true; @@ -4178,6 +4371,10 @@ }); cookiePolicy.shouldBlock = !frameExempted && !tabExempted; cookiePolicy.policy = settings.firstPartyCookiePolicy; + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy; + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || []; } // The cookie policy is injected into every frame immediately so that no cookie will @@ -4238,20 +4435,20 @@ try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy; + const { shouldBlock, policy, trackerPolicy } = cookiePolicy; + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy; if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext); return } - // extract cookie expiry from cookie string const cookie = new Cookie(value); // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge; + cookie.maxAge = chosenPolicy.maxAge; debugHelper('restrict', 'expiry', setCookieContext); @@ -4279,19 +4476,23 @@ } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + }; + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie; - args.cookie.debug = args.debug; - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie'); - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie'); - const policy = this.getFeatureSetting('firstPartyCookiePolicy'); - if (policy) { - cookiePolicy.policy = policy; - } + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie); + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy + }; } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false; + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy); } loadedPolicyResolve(); @@ -4573,31 +4774,41 @@ } } + function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }); + } catch { + // todo: Just ignore this exception? + } + } + class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }); - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args); } } + + init (args) { + injectNavigatorInterface(args); + } } let adLabelStrings = []; @@ -5094,12 +5305,14 @@ /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** @@ -5174,7 +5387,10 @@ } load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }); init(processedConfig); diff --git a/build/android/contentScope.js b/build/android/contentScope.js index 4dd3c175e..76f163ae8 100644 --- a/build/android/contentScope.js +++ b/build/android/contentScope.js @@ -86,7 +86,7 @@ * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ - function isThirdParty () { + function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -288,7 +288,7 @@ /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ function processAttr (configSetting, defaultValue) { @@ -449,6 +449,16 @@ * @property {string} sessionKey */ + /** + * Used to inialize extension code in the load phase + */ + function computeLimitedSiteObject () { + const topLevelHostname = getTabHostname(); + return { + domain: topLevelHostname + } + } + /** * Expansion point to add platform specific versioning logic * @param {UserPreferences} preferences @@ -506,16 +516,23 @@ } /** - * @param {{ features: Record; unprotectedTemporary: string[]; }} data + * @typedef RemoteConfig + * @property {Record} features + * @property {string[]} unprotectedTemporary + */ + + /** + * @param {RemoteConfig} data * @param {string[]} userList * @param {UserPreferences} preferences * @param {string[]} platformSpecificFeatures */ function processConfig (data, userList, preferences, platformSpecificFeatures = []) { const topLevelHostname = getTabHostname(); + const site = computeLimitedSiteObject(); const allowlisted = userList.filter(domain => domain === topLevelHostname).length > 0; const remoteFeatureNames = Object.keys(data.features); - const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); + platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); /** @type {Record} */ const output = { ...preferences }; if (output.platform) { @@ -524,37 +541,65 @@ output.platform.version = version; } } + const enabledFeatures = computeEnabledFeatures(data, topLevelHostname, preferences.platform?.version, platformSpecificFeatures); + const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary); + output.site = Object.assign(site, { + isBroken, + allowlisted, + enabledFeatures + }); + // TODO + output.cookie = {}; + + // Copy feature settings from remote config to preferences object + output.featureSettings = parseFeatureSettings(data, enabledFeatures); + output.trackerLookup = {"org":{"cdn77":{"rsc":{"1666210260":1}},"adsrvr":1,"ampproject":1,"browser-update":1,"flowplayer":1,"privacy-center":1,"webvisor":1,"framasoft":1,"do-not-tracker":1,"trackersimulator":1},"io":{"1dmp":1,"1rx":1,"4dex":1,"adnami":1,"aidata":1,"arcspire":1,"bidr":1,"branch":1,"center":1,"concert":1,"connectad":1,"cordial":1,"dcmn":1,"extole":1,"getblue":1,"hbrd":1,"imbox":1,"instana":1,"karte":1,"lytics":1,"marchex":1,"mediago":1,"mrf":1,"myfidevs":1,"narrative":1,"ntv":1,"optad360":1,"oracleinfinity":1,"oribi":1,"p-n":1,"personalizer":1,"pghub":1,"piano":1,"powr":1,"pzz":1,"searchspring":1,"segment":1,"siteimproveanalytics":1,"sjv":1,"sspinc":1,"t13":1,"webgains":1,"wovn":1,"yellowblue":1,"zprk":1,"reviews":1,"appconsent":1,"leadsmonitor":1},"com":{"2020mustang":1,"33across":1,"360yield":1,"3lift":1,"4dsply":1,"4jnzhl0d0":1,"4strokemedia":1,"5d2d04464c":1,"a-mx":1,"a2z":1,"aamsitecertifier":1,"absorbingband":1,"abstractedauthority":1,"abtasty":1,"acexedge":1,"acidpigs":1,"acsbapp":1,"acuityplatform":1,"ad-score":1,"ad-stir":1,"adalyser":1,"adapf":1,"adara":1,"adblade":1,"addthis":1,"addtoany":1,"adelixir":1,"adentifi":1,"adextrem":1,"adgrx":1,"adhese":1,"adition":1,"adkernel":1,"adlightning":1,"adlooxtracking":1,"admanmedia":1,"admedo":1,"adnium":1,"adnxs":1,"adobedtm":1,"adotmob":1,"adpone":1,"adpushup":1,"adroll":1,"adrta":1,"ads-twitter":1,"ads3-adnow":1,"adsafeprotected":1,"adstanding":1,"adswizz":1,"adsymptotic":1,"adtdp":1,"adtechus":1,"adtelligent":1,"adthrive":1,"adtlgc":1,"adtng":1,"adultfriendfinder":1,"advangelists":1,"adventive":1,"advertising":1,"aegpresents":1,"affinity":1,"affirm":1,"agilone":1,"agkn":1,"aimbase":1,"albacross":1,"alcmpn":1,"alexametrics":1,"alicdn":1,"alikeaddition":1,"aliveachiever":1,"aliyuncs":1,"alluringbucket":1,"aloofvest":1,"amazon-adsystem":1,"amazon":1,"amplitude":1,"analytics-egain":1,"aniview":1,"anymind360":1,"amazonaws":{"ap-southeast-2":1,"elb":{"eu-west-2":{"collect-prd-alb-539115803":1},"us-east-1":{"data-allstate-com-715826933":1,"prod-lb-8-1772099769":1,"proxy-mycigna-prod-678433465":1,"www-u45-pnc-com-902993410":1,"www-u46-pnc-com-13593657":1},"eu-west-1":{"devservicesalb-471015105":1,"petfre-content-1201188928":1},"us-east-2":{"elbpiwik-public-1781721271":1},"eu-central-1":{"prod-lb-6-388533732":1,"prod-lb-7-718125029":1,"prod-pub-alb-654989386":1}},"us-east-2":{"s3":{"hb-gretsch-talk":1,"hb-jetpunk":1,"hb-obv2":1}},"eu-central-1":{"s3":{"headless-ssr-prod-bucket":1}}},"app-us1":1,"appboycdn":1,"appdynamics":1,"aralego":1,"arkoselabs":1,"aswpsdkus":1,"atemda":1,"att":1,"attentivemobile":1,"attractionbanana":1,"audioeye":1,"audrte":1,"automaticside":1,"avanser":1,"avmws":1,"aweber":1,"aweprt":1,"azure":1,"b0e8":1,"bagbeam":1,"bandborder":1,"batch":1,"bawdybalance":1,"bc0a":1,"bdstatic":1,"bedsberry":1,"beginnerpancake":1,"benchmarkemail":1,"betweendigital":1,"bfmio":1,"bidderstack":1,"bidtheatre":1,"bimbolive":1,"bing":1,"bizographics":1,"bizrate":1,"bkrtx":1,"blismedia":1,"blogherads":1,"bluecava":1,"bluekai":1,"boatwizard":1,"boilingcredit":1,"boldchat":1,"booking":1,"borderfree":1,"bounceexchange":1,"brainlyads":1,"brand-display":1,"brandmetrics":1,"brealtime":1,"breinify":1,"brightedge":1,"brightfunnel":1,"brightspotcdn":1,"btloader":1,"btstatic":1,"bttrack":1,"btttag":1,"butterbulb":1,"buzzoola":1,"byside":1,"cabnnr":1,"calculatorstatement":1,"callrail":1,"calltracks":1,"capablecup":1,"captcha-delivery":1,"carpentercomparison":1,"cartstack":1,"carvecakes":1,"casalemedia":1,"cdn-btsg":1,"cdnwidget":1,"channeladvisor":1,"chartbeat":1,"chatango":1,"chaturbate":1,"cheqzone":1,"cherriescare":1,"chickensstation":1,"childlikecrowd":1,"childlikeform":1,"cintnetworks":1,"circlelevel":1,"civiccomputing":1,"ck-ie":1,"clcktrax":1,"clearbit":1,"clearbitjs":1,"clickagy":1,"clickcease":1,"clickcertain":1,"clicktripz":1,"clientgear":1,"clksite":1,"cloudflare":1,"cloudflareinsights":1,"cloudflarestream":1,"cloudmaestro":1,"cobaltgroup":1,"cobrowser":1,"cognitivlabs":1,"colossusssp":1,"comm100":1,"googleapis":{"commondatastorage":1,"storage":1},"company-target":1,"condenastdigital":1,"confusedcart":1,"connatix":1,"consentframework":1,"contextweb":1,"conversionruler":1,"convertkit":1,"convertlanguage":1,"cookieinformation":1,"cookiepro":1,"coveo":1,"cpmstar":1,"cquotient":1,"crabbychin":1,"crazyegg":1,"creative-serving":1,"creativecdn":1,"criteo":1,"crowdedmass":1,"crowdriff":1,"crownpeak":1,"crsspxl":1,"ctnsnet":1,"cubchannel":1,"cudasvc":1,"cuddlethehyena":1,"cumbersomecarpenter":1,"curalate":1,"curvedhoney":1,"cutechin":1,"cxense":1,"dailymotion":1,"damdoor":1,"dampdock":1,"dapperfloor":1,"datadoghq-browser-agent":1,"decisivebase":1,"deepintent":1,"defybrick":1,"delivra":1,"demandbase":1,"detectdiscovery":1,"devilishdinner":1,"dimelochat":1,"discreetfield":1,"disqus":1,"dmpxs":1,"dockdigestion":1,"dollardelta":1,"dotomi":1,"doubleverify":1,"drainpaste":1,"dramaticdirection":1,"driftt":1,"dtscdn":1,"dtscout":1,"dwin1":1,"dynamics":1,"dynamicyield":1,"dynatrace":1,"dyntrk":1,"ebaystatic":1,"ecal":1,"eccmp":1,"elasticchange":1,"elfsight":1,"elitrack":1,"eloqua":1,"en25":1,"encouragingthread":1,"ensighten":1,"enviousshape":1,"eqads":1,"ero-advertising":1,"esputnik":1,"evergage":1,"evgnet":1,"exdynsrv":1,"exelator":1,"exoclick":1,"exosrv":1,"expansioneggnog":1,"expertrec":1,"exponea":1,"exponential":1,"extole":1,"ezodn":1,"ezoic":1,"ezoiccdn":1,"facebook":1,"fadewaves":1,"fallaciousfifth":1,"farmergoldfish":1,"fastly-insights":1,"fearlessfaucet":1,"fiftyt":1,"financefear":1,"fitanalytics":1,"five9":1,"fksnk":1,"flashtalking":1,"flipp":1,"floweryflavor":1,"flutteringfireman":1,"flux-cdn":1,"fomo":1,"foresee":1,"forter":1,"fortunatemark":1,"fouanalytics":1,"fox":1,"fqtag":1,"frailfruit":1,"freezingbuilding":1,"fronttoad":1,"fullstory":1,"functionalfeather":1,"fuzzybasketball":1,"gammamaximum":1,"gbqofs":1,"geetest":1,"geistm":1,"geniusmonkey":1,"geoip-js":1,"getbread":1,"getcandid":1,"getclicky":1,"getdrip":1,"getelevar":1,"getpublica":1,"getrockerbox":1,"getshogun":1,"getsitecontrol":1,"glassdoor":1,"gloriousbeef":1,"godpvqnszo":1,"gondolagnome":1,"google-analytics":1,"google":1,"googleadservices":1,"googlehosted":1,"googleoptimize":1,"googlesyndication":1,"googletagmanager":1,"googletagservices":1,"govx":1,"greylabeldelivery":1,"groovehq":1,"gstatic":1,"guarantee-cdn":1,"guiltlessbasketball":1,"gumgum":1,"haltingbadge":1,"hammerhearing":1,"handsomelyhealth":1,"hawksearch":1,"heapanalytics":1,"hellobar":1,"hiconversion":1,"highwebmedia":1,"histats":1,"hlserve":1,"hocgeese":1,"hollowafterthought":1,"honorableland":1,"hotjar":1,"hp":1,"hs-banner":1,"htlbid":1,"htplayground":1,"hubspot":1,"iadvize":1,"ib-ibi":1,"id5-sync":1,"iesnare":1,"igodigital":1,"iheart":1,"iljmp":1,"illiweb":1,"impactcdn":1,"impactradius-event":1,"impactradius-go":1,"impossibleexpansion":1,"impressionmonster":1,"improvedcontactform":1,"improvedigital":1,"imrworldwide":1,"indexww":1,"infolinks":1,"infusionsoft":1,"inmobi":1,"inmoment":1,"inq":1,"inside-graph":1,"instagram":1,"intentiq":1,"intergient":1,"investingchannel":1,"invocacdn":1,"iplsc":1,"ipredictive":1,"iteratehq":1,"ivitrack":1,"j93557g":1,"jaavnacsdw":1,"jimstatic":1,"journity":1,"js7k":1,"juicyads":1,"justanswer":1,"justpremium":1,"kakao":1,"kampyle":1,"kargo":1,"kissmetrics":1,"klarnaservices":1,"klaviyo":1,"knottyswing":1,"kount":1,"krushmedia":1,"ktkjmp":1,"kxcdn":1,"ladesk":1,"ladsp":1,"laughablelizards":1,"leadsrx":1,"lendingtree":1,"levexis":1,"liadm":1,"licdn":1,"lightboxcdn":1,"lijit":1,"linkedin":1,"linksynergy":1,"list-manage":1,"listrakbi":1,"livechatinc":1,"livejasmin":1,"localytics":1,"loggly":1,"loop11":1,"lovelydrum":1,"luckyorange":1,"lunchroomlock":1,"maddeningpowder":1,"mailchimp":1,"mailchimpapp":1,"mailerlite":1,"maillist-manage":1,"marinsm":1,"marketiq":1,"marketo":1,"marriedbelief":1,"matheranalytics":1,"mathtag":1,"maxmind":1,"mczbf":1,"measlymiddle":1,"medallia":1,"media6degrees":1,"mediacategory":1,"mediavine":1,"mediawallahscript":1,"medtargetsystem":1,"megpxs":1,"metricode":1,"metricswpsh":1,"mfadsrvr":1,"mgid":1,"micpn":1,"microadinc":1,"minutemedia-prebid":1,"minutemediaservices":1,"mixpo":1,"mktoresp":1,"mktoweb":1,"ml314":1,"moatads":1,"mobtrakk":1,"monsido":1,"mookie1":1,"mountain":1,"mouseflow":1,"mpeasylink":1,"mql5":1,"mrtnsvr":1,"murdoog":1,"mxpnl":1,"mybestpro":1,"myfinance":1,"myregistry":1,"nappyattack":1,"navistechnologies":1,"neodatagroup":1,"nervoussummer":1,"newrelic":1,"newscgp":1,"nextdoor":1,"ninthdecimal":1,"nitrocdn":1,"noibu":1,"nondescriptnote":1,"nosto":1,"npttech":1,"nuance":1,"nxsttv":1,"omappapi":1,"omnisnippet1":1,"omnisrc":1,"omnitagjs":1,"oneall":1,"onesignal":1,"onetag-sys":1,"oo-syringe":1,"ooyala":1,"opecloud":1,"opentext":1,"opera":1,"opmnstr":1,"optimicdn":1,"optinmonster":1,"optmnstr":1,"optmstr":1,"optnmnstr":1,"optnmstr":1,"oraclecloud":1,"osano":1,"otm-r":1,"outbrain":1,"overconfidentfood":1,"ownlocal":1,"pamelarandom":1,"panickypancake":1,"panoramicplane":1,"parastorage":1,"pardot":1,"parsely":1,"partplanes":1,"patreon":1,"paypal":1,"pbstck":1,"pcmag":1,"peerius":1,"perfdrive":1,"perfectmarket":1,"permutive":1,"picreel":1,"pinimg":1,"pippio":1,"piwikpro":1,"pixlee":1,"pleasantpump":1,"plotrabbit":1,"pluckypocket":1,"pocketfaucet":1,"possibleboats":1,"postaffiliatepro":1,"postrelease":1,"potatoinvention":1,"prepareplanes":1,"pricespider":1,"pricklydebt":1,"profusesupport":1,"proofpoint":1,"protoawe":1,"providesupport":1,"pswec":1,"psyma":1,"ptengine":1,"publir":1,"pubmatic":1,"pubmine":1,"pubnation":1,"puffypurpose":1,"qualaroo":1,"qualtrics":1,"quantcast":1,"quantserve":1,"quantummetric":1,"quietknowledge":1,"quizzicalzephyr":1,"quora":1,"r42tag":1,"railwayreason":1,"rakuten":1,"rambunctiousflock":1,"rangeplayground":1,"realsrv":1,"rebelswing":1,"reconditerake":1,"reconditerespect":1,"recruitics":1,"reddit":1,"redditstatic":1,"rehabilitatereason":1,"reson8":1,"resonantrock":1,"responsiveads":1,"restrainstorm":1,"retargetly":1,"revcontent":1,"rezync":1,"rfihub":1,"rhetoricalloss":1,"richaudience":1,"righteouscrayon":1,"rightfulfall":1,"riotgames":1,"rkdms":1,"rlcdn":1,"rmtag":1,"rncdn5":1,"rnengage":1,"rogersmedia":1,"rokt":1,"route":1,"rubiconproject":1,"s-onetag":1,"saambaa":1,"sablesong":1,"sail-horizon":1,"salesforceliveagent":1,"samestretch":1,"satisfycork":1,"savoryorange":1,"scarabresearch":1,"scaredsnakes":1,"scarfsmash":1,"scatteredstream":1,"scene7":1,"scholarlyiq":1,"scintillatingsilver":1,"scorecardresearch":1,"screechingstove":1,"screenpopper":1,"sddan":1,"sdiapi":1,"seatsmoke":1,"securedvisit":1,"seedtag":1,"sefsdvc":1,"segment":1,"sekindo":1,"selectivesummer":1,"selfishsnake":1,"servebom":1,"servedbyadbutler":1,"servenobid":1,"serverbid":1,"serving-sys":1,"shakegoldfish":1,"shappify":1,"shareaholic":1,"sharethis":1,"sharethrough":1,"shopifyapps":1,"shopperapproved":1,"shrillspoon":1,"sibautomation":1,"sicksmash":1,"sift":1,"siftscience":1,"signifyd":1,"siteimprove":1,"siteimproveanalytics":1,"sitescout":1,"skillfuldrop":1,"sli-spark":1,"slickstream":1,"slopesoap":1,"smadex":1,"smartadserver":1,"smashquartz":1,"smashsurprise":1,"smg":1,"smilewanted":1,"smoggysnakes":1,"snapchat":1,"snapkit":1,"snigelweb":1,"socdm":1,"sojern":1,"songsterritory":1,"sonobi":1,"speedcurve":1,"sphereup":1,"spiceworks":1,"spookyexchange":1,"spookyskate":1,"spookysleet":1,"sportradar":1,"sportradarserving":1,"sportslocalmedia":1,"spotxchange":1,"springserve":1,"srvmath":1,"stackadapt":1,"stakingsmile":1,"statcounter":1,"steadfastseat":1,"steadfastsound":1,"steadfastsystem":1,"steelhousemedia":1,"steepsquirrel":1,"stereoproxy":1,"stereotypedsugar":1,"stickyadstv":1,"stiffgame":1,"straightnest":1,"stripchat":1,"stupendoussleet":1,"stupendoussnow":1,"stupidscene":1,"sulkycook":1,"sumo":1,"sumologic":1,"sundaysky":1,"superficialeyes":1,"superficialsquare":1,"survicate":1,"svonm":1,"symantec":1,"taboola":1,"tagcommander":1,"tailtarget":1,"talkable":1,"taobao":1,"tapad":1,"taptapnetworks":1,"taskanalytics":1,"tealiumiq":1,"technoratimedia":1,"techtarget":1,"tediousticket":1,"teenytinyshirt":1,"tendertest":1,"the-ozone-project":1,"theadex":1,"themoneytizer":1,"theplatform":1,"thestar":1,"thomastorch":1,"threetruck":1,"thrtle":1,"tidaltv":1,"tidiochat":1,"tiktok":1,"tinypass":1,"tiqcdn":1,"tiresomethunder":1,"trackjs":1,"trafficjunky":1,"travelaudience":1,"treasuredata":1,"tremorhub":1,"trendemon":1,"tribalfusion":1,"trovit":1,"trueleadid":1,"truoptik":1,"truste":1,"trustedsite":1,"trustpilot":1,"tsyndicate":1,"tubemogul":1,"turn":1,"tvpixel":1,"tvsquared":1,"tweakwise":1,"twitter":1,"tynt":1,"typicalteeth":1,"u5e":1,"ubembed":1,"uidapi":1,"ultraoranges":1,"unbecominglamp":1,"unbxdapi":1,"undertone":1,"uninterestedquarter":1,"unpkg":1,"unrulymedia":1,"unwieldyhealth":1,"unwieldyplastic":1,"upsellit":1,"urbanairship":1,"usabilla":1,"usbrowserspeed":1,"usemessages":1,"userreport":1,"uservoice":1,"valuecommerce":1,"vengefulgrass":1,"vidazoo":1,"videoplayerhub":1,"vidoomy":1,"viglink":1,"visualwebsiteoptimizer":1,"vivaclix":1,"vk":1,"vlitag":1,"vocento":1,"voicefive":1,"volatilevessel":1,"voraciousgrip":1,"voxmedia":1,"vrtcal":1,"w3counter":1,"walkme":1,"warmafterthought":1,"warmquiver":1,"webcontentassessor":1,"webengage":1,"webeyez":1,"webflow":1,"webtraxs":1,"webtrends-optimize":1,"webtrends":1,"wgplayer":1,"wisepops":1,"worldoftulo":1,"wpadmngr":1,"wpshsdk":1,"wpushsdk":1,"wsod":1,"wt-safetag":1,"wysistat":1,"xg4ken":1,"xiti":1,"xlirdr":1,"xlivrdr":1,"xnxx-cdn":1,"y-track":1,"yahoo":1,"yandex":1,"yieldmo":1,"yieldoptimizer":1,"yimg":1,"yotpo":1,"yottaa":1,"youtube-nocookie":1,"youtube":1,"zatnoh":1,"zemanta":1,"zendesk":1,"zeotap":1,"zeronaught":1,"zestycrime":1,"zonos":1,"zoominfo":1,"zopim":1,"adnxs-simple":1,"createsend1":1,"adventori":1,"facil-iti":1,"provenexpert":1,"veoxa":1,"getflowbox":1,"parchedsofa":1,"adtraction":1,"bannerflow":1,"aboardamusement":1,"absorbingcorn":1,"abstractedamount":1,"actoramusement":1,"actuallysnake":1,"adorableanger":1,"agreeabletouch":1,"aheadday":1,"ancientact":1,"annoyedairport":1,"annoyingacoustics":1,"aquaticowl":1,"aspiringattempt":1,"audioarctic":1,"awarealley":1,"awesomeagreement":1,"awzbijw":1,"basketballbelieve":1,"begintrain":1,"bestboundary":1,"blushingbeast":1,"boredcrown":1,"breadbalance":1,"breakfastboat":1,"bulbbait":1,"burnbubble":1,"bustlingbath":1,"callousbrake":1,"calmcactus":1,"capriciouscorn":1,"caringcast":1,"catschickens":1,"causecherry":1,"chunkycactus":1,"cloisteredcord":1,"closedcows":1,"colossalclouds":1,"colossalcoat":1,"comfortablecheese":1,"conditioncrush":1,"consciouscheese":1,"consciousdirt":1,"coverapparatus":1,"cratecamera":1,"critictruck":1,"curvycry":1,"cushionpig":1,"damageddistance":1,"debonairdust":1,"decisivedrawer":1,"decisiveducks":1,"detailedkitten":1,"diplomahawaii":1,"dk4ywix":1,"dq95d35":1,"energeticladybug":1,"enormousearth":1,"evanescentedge":1,"fadedsnow":1,"fancyactivity":1,"farshake":1,"fastenfather":1,"fatcoil":1,"faultycanvas":1,"firstfrogs":1,"flimsycircle":1,"flimsythought":1,"friendwool":1,"fumblingform":1,"futuristicfifth":1,"giddycoat":1,"giraffepiano":1,"glisteningguide":1,"grayreceipt":1,"greasysquare":1,"grouchypush":1,"haltinggold":1,"handyfield":1,"handyfireman":1,"hearthorn":1,"historicalbeam":1,"horsenectar":1,"hystericalcloth":1,"impulsejewel":1,"incompetentjoke":1,"internalsink":1,"lameletters":1,"livelumber":1,"livelylaugh":1,"lorenzourban":1,"lumpylumber":1,"maliciousmusic":1,"meatydime":1,"memorizeneck":1,"mightyspiders":1,"mixedreading":1,"modularmental":1,"motionlessbag":1,"movemeal":1,"nondescriptcrowd":1,"nostalgicneed":1,"nuttyorganization":1,"optimallimit":1,"outstandingincome":1,"outstandingsnails":1,"panickycurtain":1,"petiteumbrella":1,"placidperson":1,"plantdigestion":1,"punyplant":1,"rabbitbreath":1,"rabbitrifle":1,"raintwig":1,"rainyhand":1,"rainyrule":1,"rangecake":1,"raresummer":1,"readymoon":1,"rebelsubway":1,"receptivereaction":1,"regularplants":1,"repeatsweater":1,"replaceroute":1,"resonantbrush":1,"respectrain":1,"richstring":1,"roofrelation":1,"rusticprice":1,"scaredcomfort":1,"scaredsnake":1,"scientificshirt":1,"scintillatingscissors":1,"screechingfurniture":1,"seashoresociety":1,"secretturtle":1,"shakysurprise":1,"shallowblade":1,"shesubscriptions":1,"shockingship":1,"sillyscrew":1,"sincerebuffalo":1,"sinceresubstance":1,"singroot":1,"sixscissors":1,"soggysponge":1,"somberscarecrow":1,"sordidsmile":1,"sortsail":1,"sortsummer":1,"spellsalsa":1,"spotlessstamp":1,"spottednoise":1,"stalesummer":1,"steadycopper":1,"stepplane":1,"strangesink":1,"stretchsister":1,"strivesidewalk":1,"superficialspring":1,"swellstocking":1,"synonymousrule":1,"tangyamount":1,"tastelesstrees":1,"teenytinycellar":1,"teenytinytongue":1,"terriblethumb":1,"terrifictooth":1,"thirdrespect":1,"ticketaunt":1,"tremendousplastic":1,"troubledtail":1,"typicalairplane":1,"ubiquitousyard":1,"unbecominghall":1,"uncoveredexpert":1,"unequalbrake":1,"unknowncrate":1,"untidyrice":1,"unusedstone":1,"venusgloria":1,"verdantanswer":1,"verseballs":1,"wearbasin":1,"cautiouscredit":1,"confesschairs":1,"chinsnakes":1,"wellgroomedhydrant":1,"heavyplayground":1,"bravecalculator":1,"workoperation":1,"secondhandfall":1,"unablehope":1,"tastelesstrucks":1,"losslace":1,"barbarousbase":1,"supportwaves":1,"protestcopy":1,"automaticturkey":1,"stretchsquirrel":1,"equablekettle":1,"discreetquarter":1,"peacefullimit":1,"gulliblegrip":1,"swelteringsleep":1,"muteknife":1,"aliasanvil":1,"operationchicken":1,"courageousbaby":1,"flowerstreatment":1,"scissorsstatement":1,"furryfork":1,"synonymoussticks":1,"deerbeginner":1,"rhetoricalveil":1,"farsnails":1,"kaputquill":1,"digestiondrawer":1,"meltmilk":1,"endurablebulb":1,"sugarfriction":1,"combcompetition":1,"stakingshock":1,"stretchsneeze":1,"sinkbooks":1,"brotherslocket":1,"cautiouscamera":1,"materialparcel":1,"inputicicle":1,"chargecracker":1,"fewjuice":1,"tumbleicicle":1,"serpentshampoo":1,"nutritiousbean":1,"scrapesleep":1,"bleachbubble":1,"longingtrees":1,"leftliquid":1,"handsomehose":1,"powerfulcopper":1,"painstakingpickle":1,"swankysquare":1,"soundstocking":1,"disagreeabledrop":1,"cushiondrum":1,"ruralrobin":1,"gorgeousedge":1,"strivesquirrel":1,"currentcollar":1,"combativecar":1,"ambiguousafternoon":1,"harborcaption":1,"blushingbread":1,"suggestionbridge":1,"spectacularstamp":1,"skisofa":1,"predictplate":1,"shakyseat":1,"priceypies":1,"livelyreward":1,"stealsteel":1,"shiveringspot":1,"memorizematch":1,"knitstamp":1,"bushesbag":1,"mundanenail":1,"coldbalance":1,"shapecomb":1,"shiverscissors":1,"broadborder":1,"quirkysugar":1,"stingyspoon":1,"billowybelief":1,"crookedcreature":1,"acceptableauthority":1,"sadloaf":1,"separatesort":1,"pailpatch":1,"scribblestring":1,"exhibitsneeze":1,"largebrass":1,"combcattle":1,"materialisticmoon":1,"fixedfold":1,"restructureinvention":1,"scaredstomach":1,"cautiouscherries":1,"tritebadge":1,"motionflowers":1,"ballsbanana":1,"meddleplant":1,"simulateswing":1,"marketspiders":1,"grumpydime":1,"neatshade":1,"samplesamba":1,"samesticks":1,"buttonladybug":1,"mentorsticks":1,"scaredsong":1,"annoyingclover":1,"grainmass":1,"tempertrick":1,"quizzicalpartner":1,"franticroof":1,"cattlecommittee":1,"tangycover":1,"looseloaf":1,"psychedelicarithmetic":1,"radiateprose":1,"shamerain":1,"cleanhaircut":1,"badgevolcano":1,"laboredlocket":1,"zipperxray":1,"stingycrush":1,"sixauthority":1,"thinkitten":1,"strokesystem":1,"hatefulrequest":1},"net":{"2mdn":1,"2o7":1,"incapdns":{"x":{"3exvfbh":1,"5t48cjc":1,"7xjpy4d":1,"dzm868l":1,"ttk8bbo":1}},"3gl":1,"a-mo":1,"acint":1,"adform":1,"adhigh":1,"admixer":1,"adobedc":1,"adspeed":1,"azureedge":{"adv-cloudfilse":1,"afw-static":1,"bayleys-pri-cdn-endpoint":1,"cdne-nxtevo-prd01-ms":1,"discountcodeexpress":1,"fp-cdn":1,"lefigaro":1,"ocpd-content":1,"sdtagging":1,"trenord-europe-trenord-endpoint-prd":1},"adverticum":1,"edgekey":{"akamai-111035":1,"com":{"alicdn":1,"ebay":1,"mtvnservices":1,"nbcuni":1,"nintendo":1,"oneindia":1,"scene7":1,"turner":1,"ziffdavis":1,"ziffdavisinternational":1},"ame":1,"au":1,"br":1,"ca":1,"com-v1":1,"com-v2":1,"gov":1,"in":1,"io":1,"it":1,"net":1,"org":1,"ppll":1,"rakuten":1,"uk":1},"apicit":1,"appier":1,"akamaized":{"assets-momentum":1,"com":{"media-rockstargames-":1,"ntd":1,"vocento":1}},"aticdn":1,"azure":1,"azurefd":1,"bannerflow":1,"bf-tools":1,"bidswitch":1,"bitsngo":1,"blueconic":1,"boldapps":1,"buysellads":1,"cedexis":1,"certona":1,"fastly":{"map":{"cidgroup":1,"condenast":1,"ihrinferno":1,"prisa-us-eu":1,"scribd":1,"target-opus":1,"thriftbooks":1,"ticketmaster4":1,"twitch":1,"vox":1,"appnexus":1},"global":{"shared":{"d2":1,"s2":1},"sni":{"j":1}},"ssl":{"global":{"igao-prod-herokuapp-com":1,"mslc-prod-herokuapp-com":1}}},"confiant-integrations":1,"consentmanager":1,"contentsquare":1,"criteo":1,"crwdcntrl":1,"cloudfront":{"d16jny3kjm2a1j":1,"d16kgn4efacaad":1,"d19l6uotjzm32g":1,"d1af033869koo7":1,"d1bxz6tua5hq87":1,"d1cr9zxt7u0sgu":1,"d1egjda7ggd2ew":1,"d1eh9yux7w8iql":1,"d1gwclp1pmzk26":1,"d1nhstnts0iwzs":1,"d1p5cqqchvbqmy":1,"d1pq45hly7zfel":1,"d1rhs7mhgydok3":1,"d1rw50yn65615p":1,"d1s87id6169zda":1,"d1snv67wdds0p2":1,"d1tprjo2w7krrh":1,"d1vg5xiq7qffdj":1,"d1vo8zfysxy97v":1,"d1y068gyog18cq":1,"d214hhm15p4t1d":1,"d21gpk1vhmjuf5":1,"d244lyzgucnepm":1,"d27cwqlgojh9yd":1,"d2aioe7l2jay46":1,"d2bj4wnxqmm2tk":1,"d2droglu4qf8st":1,"d2eanzqpmoo3ec":1,"d2f4zoo8hyailp":1,"d2hs2r19gv871k":1,"d2j6syf6c0cltf":1,"d2jpq2u2vrjftk":1,"d2qlgd5odkppg5":1,"d2qrdklrsxowl2":1,"d2s6j0ghajv79z":1,"d2tyltutevw8th":1,"d2wo2i8fdcw8of":1,"d2xbocf5uqnw0w":1,"d2y7rifa1cwopa":1,"d2zah9y47r7bi2":1,"d30jydkdo8eo9b":1,"d355prp56x5ntt":1,"d35mt2i8wrf9y1":1,"d38aqfmkl3ge26":1,"d38xvr37kwwhcm":1,"d3fv2pqyjay52z":1,"d3gxe0jmvtuxbc":1,"d3i4yxtzktqr9n":1,"d3jruqy3qmm3fd":1,"d3nn82uaxijpm6":1,"d3o8vwpyaorolj":1,"d3ochae1kou2ub":1,"d3odp2r1osuwn0":1,"d3owq2fdwtdp2j":1,"d3txh7prdum3s8":1,"d3v7mj6iyaqfac":1,"d4egga2bwam6h":1,"d5yoctgpv4cpx":1,"d6tizftlrpuof":1,"d9k0w0y3delq8":1,"dbukjj6eu5tsf":1,"de2pmm85odupd":1,"de7iszmjjjuya":1,"dfx0d9twj2ai":1,"dj28g4s0yd4ph":1,"dn0qt3r0xannq":1,"dokumfe7mps0i":1,"dowpznhhyvkm4":1,"dsh7ky7308k4b":1,"dsx863kqtdxrt":1,"dtpw88eywzb7u":1,"duube1y6ojsji":1,"dzlkq6toxiazj":1,"dzz1zjxa9ulpk":1,"d2638j3z8ek976":1},"akadns":{"com":{"dellcdn":1,"febsec-fidelity":1},"line-zero":1},"demdex":1,"dotmetrics":1,"doubleclick":1,"durationmedia":1,"e-planning":1,"edgecastcdn":1,"emsecure":1,"episerver":1,"esm1":1,"eulerian":1,"everestjs":1,"everesttech":1,"eyeota":1,"ezoic":1,"facebook":1,"fastclick":1,"fbcdn":1,"fonts":1,"edgesuite":{"com":{"fox":1,"iq":1,"tiktokcdn-us":1,"vidio":1,"sky":1},"linkedin":1,"stls":1},"fuseplatform":1,"fwmrm":1,"go-mpulse":1,"hadronid":1,"hs-analytics":1,"hsleadflows":1,"im-apps":1,"impervadns":1,"iocnt":1,"iprom":1,"jsdelivr":1,"kanade-ad":1,"azurewebsites":{"keha-matomo-te-palvelut-prod":1,"neuterbot-client":1,"app-ch-sgtm-prod":1,"app-fnsp-matomo-analytics-prod":1},"krxd":1,"line-scdn":1,"listhub":1,"livecom":1,"livedoor":1,"liveperson":1,"lkqd":1,"llnwd":1,"lpsnmedia":1,"magnetmail":1,"marketo":1,"maxymiser":1,"media":1,"microad":1,"monetate":1,"mxptint":1,"myfonts":1,"myvisualiq":1,"naver":1,"b-cdn":{"nnwwwlive":1,"speedy":1},"nr-data":1,"omtrdc":1,"onecount":1,"online-metrix":1,"openx":1,"opta":1,"owneriq":1,"pages02":1,"pages03":1,"pages04":1,"pages05":1,"pages06":1,"pages08":1,"perimeterx":1,"pingdom":1,"pmdstatic":1,"popads":1,"popcash":1,"primecaster":1,"pro-market":1,"px-cloud":1,"akamaihd":{"pxlclnmdecom-a":1},"r9cdn":1,"rfihub":1,"sancdn":1,"sc-static":1,"semasio":1,"sensic":1,"trafficmanager":{"serviceschipotlecom":1},"sexad":1,"smaato":1,"spreadshirts":1,"storygize":1,"tfaforms":1,"trackcmp":1,"trackedlink":1,"truste-svc":1,"uuidksinc":1,"viafoura":1,"visilabs":1,"visx":1,"w55c":1,"wdsvc":1,"witglobal":1,"yandex":1,"yastatic":1,"yieldlab":1,"ywxi":1,"zdbb":1,"zencdn":1,"zucks":1,"eviltracker":1},"co":{"6sc":1,"ayads":1,"datadome":1,"idio":1,"increasingly":1,"jads":1,"nanorep":1,"nc0":1,"pcdn":1,"prmutv":1,"resetdigital":1,"t":1,"tctm":1,"zip":1},"de":{"71i":1,"adscale":1,"auswaertiges-amt":1,"fiduciagad":1,"ioam":1,"itzbund":1,"werk21system":1},"gt":{"ad":1},"jp":{"adingo":1,"admatrix":1,"auone":1,"co":{"dmm":1,"google":1,"rakuten":1,"yahoo":1},"fout":1,"gmossp-sp":1,"gssprt":1,"ne":{"hatena":1},"impact-ad":1,"microad":1,"nakanohito":1,"ptengine":1,"r10s":1,"reemo-ad":1,"rtoaster":1,"shinobi":1,"team-rec":1,"uncn":1,"yimg":1,"yjtag":1},"pl":{"adocean":1,"dreamlab":1,"gemius":1,"nsaudience":1,"onet":1,"salesmanago":1,"wp":1},"pro":{"adpartner":1,"piwik":1,"usocial":1},"ru":{"adriver":1,"digitaltarget":1,"mail":1,"mindbox":1,"rambler":1,"sape":1,"smi2":1,"tns-counter":1,"top100":1,"ulogin":1,"yandex":1},"re":{"adsco":1},"info":{"adxbid":1,"bitrix":1,"navistechnologies":1,"usergram":1,"webantenna":1},"tv":{"affec":1,"attn":1,"iris":1,"ispot":1,"samba":1,"teads":1,"twitch":1},"dev":{"amazon":1},"us":{"amung":1,"samplicio":1,"slgnt":1,"trkn":1},"media":{"andbeyond":1,"nextday":1,"townsquare":1,"underdog":1},"link":{"app":1},"cloud":{"avct":1,"coremedia":1,"egain":1,"matomo":1},"delivery":{"ay":1,"monu":1},"br":{"com":{"btg360":1,"clearsale":1,"jsuol":1,"shopconvert":1,"shoptarget":1,"soclminer":1},"org":{"ivcbrasil":1}},"ch":{"ch":1,"da-services":1,"google":1},"ms":{"clarity":1},"my":{"cnt":1},"se":{"codigo":1},"me":{"contentexchange":1,"grow":1,"line":1,"loopme":1,"t":1,"channel":1},"to":{"cpx":1,"tawk":1},"chat":{"crisp":1,"gorgias":1},"fr":{"d-bi":1,"open-system":1,"weborama":1},"uk":{"co":{"dailymail":1,"hsbc":1}},"id":{"net":{"detik":1}},"ai":{"e-volution":1,"m2":1,"nrich":1,"wknd":1},"be":{"geoedge":1},"au":{"com":{"google":1,"news":1,"nine":1,"realestate":1,"zipmoney":1,"telstra":1}},"stream":{"ibclick":1},"cz":{"imedia":1,"seznam":1,"trackad":1},"app":{"infusionsoft":1,"permutive":1,"shop":1},"tech":{"ingage":1,"primis":1},"eu":{"kameleoon":1,"medallia":1,"media01":1,"ocdn":1,"rqtrk":1,"slgnt":1,"usercentrics":1},"fi":{"kesko":1,"simpli":1},"live":{"lura":1},"services":{"marketingautomation":1},"sg":{"mediacorp":1},"bi":{"newsroom":1},"fm":{"pdst":1},"ad":{"pixel":1},"xyz":{"playground":1},"it":{"plug":1,"repstatic":1,"stbm":1},"cc":{"popin":1},"network":{"pub":1},"nl":{"rijksoverheid":1,"google":1},"fyi":{"sda":1},"pe":{"shop":1},"es":{"socy":1},"im":{"spot":1},"market":{"spotim":1},"am":{"tru":1},"at":{"waust":1},"gov":{"weather":1},"in":{"zoho":1},"ca":{"bc":{"gov":1}},"no":{"acdn":1,"uio":1},"example":{"ad-company":1},"site":{"ad-company":1,"third-party":{"bad":1,"broken":1}},"pw":{"zlp6s":1}}; + + return output + } + + /** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ + function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features); + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); const enabledFeatures = remoteFeatureNames.filter((featureName) => { const feature = data.features[featureName]; // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion - if (feature.minSupportedVersion && preferences.platform?.version) { - if (!isSupportedVersion(feature.minSupportedVersion, preferences.platform.version)) { + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { return false } } return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config - const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary); - output.site = { - domain: topLevelHostname, - isBroken, - allowlisted, - enabledFeatures - }; - // TODO - output.cookie = {}; + return enabledFeatures + } - // Copy feature settings from remote config to preferences object - output.featureSettings = {}; + /** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ + function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {}; + const remoteFeatureNames = Object.keys(data.features); remoteFeatureNames.forEach((featureName) => { if (!enabledFeatures.includes(featureName)) { return } - output.featureSettings[featureName] = data.features[featureName].settings; + featureSettings[featureName] = data.features[featureName].settings; }); - - return output + return featureSettings } function isGloballyDisabled (args) { @@ -1136,13 +1181,43 @@ return parseJSONPointer(fromPointer); } + /** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + + /** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName; - this._args = null; + this.#args = null; this.monitor = new PerformanceMonitor(); } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -1155,6 +1230,34 @@ return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -1171,10 +1274,11 @@ /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting(); + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName); if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -1194,17 +1298,22 @@ return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name); - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name); + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName); + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName); return result === 'enabled' } @@ -1213,9 +1322,11 @@ * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain; + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || []; return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -1225,7 +1336,7 @@ callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit'); - this._args = args; + this.#args = args; this.platform = args.platform; this.init(args); mark.end(); @@ -1238,14 +1349,23 @@ callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad'); - this._args = args; + this.#args = args; this.platform = args.platform; + this.#bundledConfig = args.bundledConfig; + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version); + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures); + } + this.#trackerLookup = args.trackerLookup; + this.#documentOriginIsTracker = args.documentOriginIsTracker; this.load(args); mark.end(); } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll(); } } @@ -1317,15 +1437,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property]; + let targetOut = target; + if (typeof property === 'string' && property in outputs) { + targetOut = outputs; + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -1382,7 +1504,6 @@ function wrapScriptCodeOverload (code, config) { const processedConfig = {}; for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value); } // Don't do anything if the config is empty @@ -1464,7 +1585,9 @@ // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -1688,6 +1811,13 @@ return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -1697,6 +1827,13 @@ return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -4104,6 +4241,34 @@ } } + /** + * Check if the current document origin is on the tracker list, using the provided lookup trie. + * @param {object} trackerLookup Trie lookup of tracker domains + * @returns {boolean} True iff the origin is a tracker. + */ + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { + const parts = originHostname.split('.').reverse(); + let node = trackerLookup; + for (const sub of parts) { + if (node[sub] === 1) { + return true + } else if (node[sub]) { + node = node[sub]; + } else { + return false + } + } + return false + } + + /** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ + // Initial cookie policy pre init let cookiePolicy = { debug: false, @@ -4112,12 +4277,18 @@ shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) }; + let trackerLookup = {}; let loadedPolicyResolve; @@ -4137,6 +4308,9 @@ }); } + /** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -4145,26 +4319,45 @@ return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } + /** + * @param {Set} scriptOrigins + * @returns {boolean} + */ + function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false; + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup, scriptOrigin)) { + matched = true; + } + } + return matched + } + + /** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true; } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup = this.trackerLookup; + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie; + const { exceptions, settings } = this.bundledConfig.features.cookie; const tabHostname = getTabHostname(); let tabExempted = true; @@ -4178,6 +4371,10 @@ }); cookiePolicy.shouldBlock = !frameExempted && !tabExempted; cookiePolicy.policy = settings.firstPartyCookiePolicy; + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy; + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || []; } // The cookie policy is injected into every frame immediately so that no cookie will @@ -4238,20 +4435,20 @@ try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy; + const { shouldBlock, policy, trackerPolicy } = cookiePolicy; + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy; if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext); return } - // extract cookie expiry from cookie string const cookie = new Cookie(value); // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge; + cookie.maxAge = chosenPolicy.maxAge; debugHelper('restrict', 'expiry', setCookieContext); @@ -4279,19 +4476,23 @@ } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + }; + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie; - args.cookie.debug = args.debug; - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie'); - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie'); - const policy = this.getFeatureSetting('firstPartyCookiePolicy'); - if (policy) { - cookiePolicy.policy = policy; - } + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie); + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy + }; } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false; + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy); } loadedPolicyResolve(); @@ -4573,31 +4774,41 @@ } } + function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }); + } catch { + // todo: Just ignore this exception? + } + } + class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }); - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args); } } + + init (args) { + injectNavigatorInterface(args); + } } let adLabelStrings = []; @@ -4988,12 +5199,14 @@ /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** @@ -5088,7 +5301,10 @@ } load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }); const messageSecret = processedConfig.messageSecret; diff --git a/build/chrome-mv3/inject.js b/build/chrome-mv3/inject.js index 3de08355b..a62006fcb 100644 --- a/build/chrome-mv3/inject.js +++ b/build/chrome-mv3/inject.js @@ -91,7 +91,7 @@ * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ - function isThirdParty () { + function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -293,7 +293,7 @@ /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ function processAttr (configSetting, defaultValue) { @@ -422,6 +422,133 @@ DDGReflect = globalObj.Reflect; } + function isUnprotectedDomain (topLevelHostname, featureList) { + let unprotectedDomain = false; + const domainParts = topLevelHostname.split('.'); + + // walk up the domain to see if it's unprotected + while (domainParts.length > 1 && !unprotectedDomain) { + const partialDomain = domainParts.join('.'); + + unprotectedDomain = featureList.filter(domain => domain.domain === partialDomain).length > 0; + + domainParts.shift(); + } + + return unprotectedDomain + } + + /** + * @typedef {object} Platform + * @property {'ios' | 'macos' | 'extension' | 'android' | 'windows'} name + * @property {string | number } [version] + */ + + /** + * @typedef {object} UserPreferences + * @property {Platform} platform + * @property {boolean} [debug] + * @property {boolean} [globalPrivacyControl] + * @property {number} [versionNumber] - Android version number only + * @property {string} [versionString] - Non Android version string + * @property {string} sessionKey + */ + + /** + * Used to inialize extension code in the load phase + */ + function computeLimitedSiteObject () { + const topLevelHostname = getTabHostname(); + return { + domain: topLevelHostname + } + } + + function parseVersionString (versionString) { + const [major = 0, minor = 0, patch = 0] = versionString.split('.').map(Number); + return { + major, + minor, + patch + } + } + + /** + * @param {string} minVersionString + * @param {string} applicationVersionString + * @returns {boolean} + */ + function satisfiesMinVersion (minVersionString, applicationVersionString) { + const { major: minMajor, minor: minMinor, patch: minPatch } = parseVersionString(minVersionString); + const { major, minor, patch } = parseVersionString(applicationVersionString); + + return (major > minMajor || + (major >= minMajor && minor > minMinor) || + (major >= minMajor && minor >= minMinor && patch >= minPatch)) + } + + /** + * @param {string | number | undefined} minSupportedVersion + * @param {string | number | undefined} currentVersion + * @returns {boolean} + */ + function isSupportedVersion (minSupportedVersion, currentVersion) { + if (typeof currentVersion === 'string' && typeof minSupportedVersion === 'string') { + if (satisfiesMinVersion(minSupportedVersion, currentVersion)) { + return true + } + } else if (typeof currentVersion === 'number' && typeof minSupportedVersion === 'number') { + if (minSupportedVersion <= currentVersion) { + return true + } + } + return false + } + + /** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ + function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features); + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); + const enabledFeatures = remoteFeatureNames.filter((featureName) => { + const feature = data.features[featureName]; + // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { + return false + } + } + return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) + }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config + return enabledFeatures + } + + /** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ + function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {}; + const remoteFeatureNames = Object.keys(data.features); + remoteFeatureNames.forEach((featureName) => { + if (!enabledFeatures.includes(featureName)) { + return + } + + featureSettings[featureName] = data.features[featureName].settings; + }); + return featureSettings + } + const windowsSpecificFeatures = ['windowsPermissionUsage']; function isWindowsSpecificFeature (featureName) { @@ -1009,13 +1136,43 @@ return parseJSONPointer(fromPointer); } + /** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + + /** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName; - this._args = null; + this.#args = null; this.monitor = new PerformanceMonitor(); } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -1028,6 +1185,34 @@ return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -1044,10 +1229,11 @@ /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting(); + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName); if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -1067,17 +1253,22 @@ return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name); - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name); + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName); + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName); return result === 'enabled' } @@ -1086,9 +1277,11 @@ * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain; + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || []; return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -1098,7 +1291,7 @@ callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit'); - this._args = args; + this.#args = args; this.platform = args.platform; this.init(args); mark.end(); @@ -1111,14 +1304,23 @@ callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad'); - this._args = args; + this.#args = args; this.platform = args.platform; + this.#bundledConfig = args.bundledConfig; + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version); + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures); + } + this.#trackerLookup = args.trackerLookup; + this.#documentOriginIsTracker = args.documentOriginIsTracker; this.load(args); mark.end(); } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll(); } } @@ -1190,15 +1392,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property]; + let targetOut = target; + if (typeof property === 'string' && property in outputs) { + targetOut = outputs; + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -1255,7 +1459,6 @@ function wrapScriptCodeOverload (code, config) { const processedConfig = {}; for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value); } // Don't do anything if the config is empty @@ -1337,7 +1540,9 @@ // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -1561,6 +1766,13 @@ return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -1570,6 +1782,13 @@ return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -3977,6 +4196,34 @@ } } + /** + * Check if the current document origin is on the tracker list, using the provided lookup trie. + * @param {object} trackerLookup Trie lookup of tracker domains + * @returns {boolean} True iff the origin is a tracker. + */ + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { + const parts = originHostname.split('.').reverse(); + let node = trackerLookup; + for (const sub of parts) { + if (node[sub] === 1) { + return true + } else if (node[sub]) { + node = node[sub]; + } else { + return false + } + } + return false + } + + /** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ + // Initial cookie policy pre init let cookiePolicy = { debug: false, @@ -3985,12 +4232,18 @@ shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) }; + let trackerLookup$1 = {}; let loadedPolicyResolve; @@ -4010,6 +4263,9 @@ }); } + /** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -4018,26 +4274,45 @@ return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } + /** + * @param {Set} scriptOrigins + * @returns {boolean} + */ + function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false; + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup$1, scriptOrigin)) { + matched = true; + } + } + return matched + } + + /** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true; } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup$1 = this.trackerLookup; + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie; + const { exceptions, settings } = this.bundledConfig.features.cookie; const tabHostname = getTabHostname(); let tabExempted = true; @@ -4051,6 +4326,10 @@ }); cookiePolicy.shouldBlock = !frameExempted && !tabExempted; cookiePolicy.policy = settings.firstPartyCookiePolicy; + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy; + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || []; } // The cookie policy is injected into every frame immediately so that no cookie will @@ -4111,20 +4390,20 @@ try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy; + const { shouldBlock, policy, trackerPolicy } = cookiePolicy; + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy; if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext); return } - // extract cookie expiry from cookie string const cookie = new Cookie(value); // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge; + cookie.maxAge = chosenPolicy.maxAge; debugHelper('restrict', 'expiry', setCookieContext); @@ -4152,19 +4431,23 @@ } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + }; + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie; - args.cookie.debug = args.debug; - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie'); - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie'); - const policy = this.getFeatureSetting('firstPartyCookiePolicy'); - if (policy) { - cookiePolicy.policy = policy; - } + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie); + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy + }; } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false; + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy); } loadedPolicyResolve(); @@ -4446,31 +4729,41 @@ } } + function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }); + } catch { + // todo: Just ignore this exception? + } + } + class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }); - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args); } } + + init (args) { + injectNavigatorInterface(args); + } } let adLabelStrings = []; @@ -4822,7 +5115,7 @@ } } - const logoImg = 'data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAA0aXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarZxpkhw5kqX/4xR1BOzLcQAFIDI36OP392BB5lY9Uy0yyWQyMsLpbgaovkVVYe781/+57l//+lcIPXeXS+t11Or5J4884uSL7r9/xvtv8Pn99/3T88/Pwl+/737/IPKtxJ/p+982f14/+X750xv9ep/11++7/vOT2H/eKPx+4/dP0ifr6/3ni+T78ft++LkQN873RR29/flS188b2a8r7n/8zr8v6/tD/+/+8o3GKu3CB6UYTwrJv//m7wqSfoc0+TPx35Aar/Np8HVJ0b1vxZ83Y0H+cnu//vT+zwv0l0X+9ZX7++r//upvix/nz/fT39ay/qwRX/zbH4Tyt++n3x8T//zB6fcVxb/+IIS4/3E7P7/v3f3e893dzJUVrT8R9RY7/HobXrhY8vT+WuVX43fh6/Z+DX51P72x5dubX/yyMEJkV64LOewwww3n/WnBuMQcT2RPYozGRul7nT0a0dgldlG/wo2NHdups5cWj2Mrc4q/ryW8zx3v8yx0PnkHXhoDb8bu/s+/3P/th/+bX+5ee0vs+++14rqiIovL0M7pv7yKDQn3Z9/KW+Bfv3623/8pfhSqmZdpmTs3OP363mKV8EdspbfPidcV/vxSKLi2f96AJeKzCxcTEjvga0gl1OBbjC0E1rGzQZMrjynHxQ6EUuLmImNOqUbXYo/6bP5OC++1scQa9W2wiY0oqabG3pBTbFbOhfhpuRNDs6SSSym1tNJdGWXWVHMttdZWBXKzpZZbabW11ttosycgsPTaW+999DniSGBgGXW00ccYc0Y3+aDJe01eP/nOiiutvMqqq62+xppG+Fi2YtWadRs2d9xpAxO77rb7Hnue4A5IcfIpp552+hlnXmLtpptvufW22++48/eu/ezqP379L3Yt/OxafDul17Xfu8Z3XWu/3iIITor2jB2LObDjTTtAQEftme8h56id0575EUmKErnIor1xO2jH2MJ8Qiw3/N67P3buP9o3V/p/tG/x/7VzTlv3/2PnHFv3z337N7u2xXP2duzLQq2pT2QfPz99utinSG3++z9H9vER0ogNiCz11FFYzM3HZH6SY2UHQOvr7LCJx9/pYxrz3JXnZbdYl+pjGens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'; + const logoImg = 'data:image/png;base64,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'; const loadingImages = { darkMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E', lightMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E' // 'data:application/octet-stream;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxzdHlsZT4KCQlAa2V5ZnJhbWVzIHJvdGF0ZSB7CgkJCWZyb20gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CgkJCX0KCQkJdG8gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMzU5ZGVnKTsKCQkJfQoJCX0KCTwvc3R5bGU+Cgk8ZyBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTAlIDUwJTsgYW5pbWF0aW9uOiByb3RhdGUgMXMgaW5maW5pdGUgcmV2ZXJzZSBsaW5lYXI7Ij4KCQk8cmVjdCB4PSIxOC4wOTY4IiB5PSIxNi4wODYxIiB3aWR0aD0iMyIgaGVpZ2h0PSI3IiByeD0iMS41IiB0cmFuc2Zvcm09InJvdGF0ZSgxMzYuMTYxIDE4LjA5NjggMTYuMDg2MSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+CQoJCTxyZWN0IHg9IjguNDk4NzgiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CgkJPHJlY3QgeD0iMTkuOTk3NiIgeT0iOC4zNzQ1MSIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgdHJhbnNmb3JtPSJyb3RhdGUoOTAgMTkuOTk3NiA4LjM3NDUxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjIiLz4KCQk8cmVjdCB4PSIxNi4xNzI3IiB5PSIxLjk5MTciIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgMTYuMTcyNyAxLjk5MTcpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuMyIvPgoJCTxyZWN0IHg9IjguOTEzMDkiIHk9IjYuODg1MDEiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDEzNi4xNjEgOC45MTMwOSA2Ljg4NTAxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KCQk8cmVjdCB4PSI2Ljc5NjAyIiB5PSIxMC45OTYiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgNi43OTYwMiAxMC45OTYpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuNyIvPgoJCTxyZWN0IHg9IjciIHk9IjguNjI1NDkiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDkwIDcgOC42MjU0OSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC44Ii8+CQkKCQk8cmVjdCB4PSI4LjQ5ODc4IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjkiLz4KCTwvZz4KPC9zdmc+Cg==' @@ -4835,117 +5128,128 @@ const videoPlayDark = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23222222%22%2F%3E%0A%3C%2Fsvg%3E%0A'; const videoPlayLight = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23FFFFFF%22%2F%3E%0A%3C%2Fsvg%3E'; - const ddgFont = 'data:application/octet-stream;base64,d09GRgABAAAAAFzgABMAAAAAxMQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABqAAAABwAAAAcZCfbMkdERUYAAAHEAAAALQAAADIDCwH4R1BPUwAAAfQAAAbeAAAkrOfEIAhHU1VCAAAI1AAAAgoAAAYUTOV1mE9TLzIAAArgAAAAWgAAAGBvZYm8Y21hcAAACzwAAAGIAAAB4hcHc2ZjdnQgAAAMxAAAACwAAAAsBNkGumZwZ20AAAzwAAABsQAAAmVTtC+nZ2FzcAAADqQAAAAIAAAACAAAABBnbHlmAAAOrAAARZYAAIZ0sNmfuWhlYWQAAFREAAAANAAAADYAiyjoaGhlYQAAVHgAAAAgAAAAJAdGA99obXR4AABUmAAAAjYAAAOqwg8hKGxvY2EAAFbQAAABzQAAAdgHVShObWF4cAAAWKAAAAAgAAAAIAIIAStuYW1lAABYwAAAAZwAAAN3s/mh+nBvc3QAAFpcAAAB8wAAAu6KrKjYcHJlcAAAXFAAAACIAAAAsxEhyEZ3ZWJmAABc2AAAAAYAAAAGwchSqQAAAAEAAAAAzD2izwAAAADJGsYbAAAAAM7Pckd42mNgZGBg4ANiLQYQYGJgYWBkqAPieoZGIK+J4RmQ/ZzhFVgGJM8AAF/9BQQAAAB42s1a629URRQ/baChVZAKVBvEFquyliKFapXS+oAg0RiN+gcYP+AXDTHGD8YPJhpfQdCESgJpk4IVYiUUYpHGNq3ULLRpzcqSdm3pSyptbFiyhGIbmqzH3zzu9u7t3t27r+I9md2ZuTNz5rzPzC5lEFEO3U8llPH2G+/tpiW0CD3ETOJNxlu73hV9pFp4lym/l1BmUZcYWVi5dpp2UgVm1LGfAzzITagNoj5I2VzDN3iC29jL3dzB0zzDHr7J/2CcX4xgLyX1ANeYXKuPT6H4eQx9Z1FmuBaYurmVp9Hqt8zqQ28WJf2ItcPaAVA4JfZgMz5gnRE3xr55PV0ofkUhT1IaHg5G6uN/+XqE3tlQLZgUzhmxknkN/gmcneEBux3Z79UxzuuGdNivv8ellvZHmTEGLRdyHbeXus1ciYP/FDrL46b+k2h7+LSsR1gTXAgAIGm+yt0pkvANWrCHzzkc18UDPCR2xh6U2WR0m4ec0ckXeVLhAZcnE9EmQ//DbAJWwTNOLCwx7eVr1nncO0dtcnbo3M7g3YPQ5dG0YOvjTl3r4X6r1sMOPIgxbmAfwFs34Ay3mK3UJAuPjFEjPOHc13LA5BH8PCzjjVxTeaOwORHimfAQjqj8ENT9gYj5FX+GuOblEfS9Kr1QLbfzMf6U/0brB0TUUUTOTsAeboqwzi1D2/mqA6xn1Cjezw3gnMD5pWwfgDXU8V5Zr02zT6h25sP5MKK8pJi/RSyYgH8YkTKZSuPemgyZ8vkEZgciUSRzkmmtQ0H7fCKktVNa98YieRg7y4TXCVo9k8IgMEOLhV+ajZbPGBEnYd61mq0vxXIZ5pO6dgX1cT5h4WUXX0b/cVkT0CjiiNTrWuSjw6jVo3RCx938Cx/hfbCxo/AP59gnZtlgjRjl+Up0P8vN8GDSC7BbeOdksl6+6XScsBD7PSeEu2vOE9plxFrDEsgolHwUJ6Hr9dZ8SUZkHyLzrCxeRRfk160iAh9D+Qs+tAdRvANSnRT+WeyXfdGzsPm6FWOnzcjRVP7mi5+/5vGg6lIke8P6Uzp38CvNgjf2KL3hNk3VqDjZACb5muaa/cljPCE6B0T+a8S1eP2AymF1vZ+/tnKbfxcyk5FbQAPXyd69OLN1hOTplj0D/Dl/BK7XwjpH1Zu47DMWnXXYn/IOLTLb6EnYQgIxR5wX59M0+URf2rP3IWv84W/Ar3benxZsoZMXnzXHJuQsF2ANR9WbtNHqDmvVCLzGbtLM5b0Oxx0CX2qSwnRx3h3GPplDf+Jg7q3E8txU3LQksdIp/d0I3+blhqhjB1XWF64JjjFNzsv7TqJvSHm3BTtve+I5dSfoE4KWfLcGOtTjxCdYdWhBOJIozi20PVTfTveQC/A04MmYM104S7ps78Rc9IK9Ds3rOY7cwGcfAeN4Ho3JqTZDh7D3MRWfbcd69c1rU8rkNAodqnZ2P5AijK3i/ofbnedQqs/JHQtkps7Zp+FdvXP5CtfjNNKAPOgGMLdIr9GLns4EtNiFOPwjX15QYzrsmLcHkZM3W7P6lOmKP+y8/J3zaMAHrblqtEzSwYoXxF2lcZaJOvJE9FvBKLdhllMLf48Muc8Zb1N1H8i/4RQ2kZ77vgXwfXGcecX9S/QMQJ+R2lKVAclz9mwMnCrS9qq73rgxBCPSOeuIzs746TTf2Ub8VWNMe8NeHgS47aJIPJ4+8i8Gsc6CTu4H0qhtC+u99ek3ZSu1y/jZHPe8Qfo/PLtvI+6i2yB3z22hNA94MyiLLlG57nkQNZFZP4xSRptQiJ4Jm/Os7FkPMD+ZtEj+ip9Nd8h2Pi2j5bKWRXejrKRVyNLzaTWtoaeogNaa8nfB8XVUjO8S5MEbJf830mbZL96sQ+sJZPZbqIK2UiVtoyrUzPOLHVFbgbLJ0veYpb1o3qwsWQwQ9XwNBbJdZIIS7KREg/Fs0DQoIJQKDVWoV0mqC2LufROgHFCmP10oGbSYJtBv/HviIVnbLCUgcAo+ltPjoTXKNbUbAOpZjFKIFbLl+sZ3jm6ptih3QppLIc+7oB+59ICcu1mv8Yjkv4AVWg5l8rMUUKxLCeVB/vdCA9aDb6Vh8+1kF/6fkFWSc9anMAyyQ/s2Q3YIhHYu1ZCr926G4hDM6VVpWG8x9qEgX+p4NnpyY8pOyF3oTpH+XBPmYQSdKzRk0n1ay3LA8wxwfRk0cjksaDEsaCUtgf2sBtY10JgcyNsFSorB01zYTSnml+EEnEc7aCcwPE8vwopfopcx4hV6HTLYBdhK7wMq6QNAFX1MX8Aa9wB2UDXgOTpAhzC7ho5gdj010mvURD9jdiv9Sm+Sm87BM/tolN75D8aGd70AAHjajZTPShxBEMa/6u7dGAkiWedPJipLCEFElpCTD6CwiIJkg+51YzAJ6EbUFZGERMjBJ/DsA4hP4APkmEPIIeSUS/48geSi1TWzk57Jjs5hu2eKX331dU/VggAM4yHaoI3ObhdDMBzB5aXsBAUNs77dWUO08fplBw/ebL/oYmqnt7WDBhNKKPuLeZ1k3cIopvAYs3iFLeyjyvHb/HSMc/ygIWrQMzqgE4kTncUa9EnePfpKFypSc6qrTtRn9VfX9Zxe1x/1mf6iL0xkZs1zc2ROzfe4qvkW75VqrFN5Ij40xhChnjis8ErwZK3J6peiwkIqKEW5WkEh5ZeiXK3xUr6KqXulqPs5KnZ6N2Gq6bev4T0+4JC//B2m3qKHPekGj/lA8sJcHmGeaeKaE1J7ENHKEErc2fesCknezWRrIDmOR8mpZhy27VD/bn6RMzRn1DEtOa76ojzns2yFEJNSl3jO4viqo+kl9ewNRJJN4r2vu5qj7Nkm/ztbO/kS/Zo+uySeQSTRptNlXsFtN9OpGOT5aUYh5os8u2yz0HMz9exf4zko4Tko8LySUbjes8uW8RxklKZzvaM4ajND7gVKe2ewZr9z8jkN/tn/42E+k+3nP6ywgGX8ln0JvzhjGT95XRJ+QXpYMV/ntYoRnkjNk+nzbNo9lEk9TJ8V30kgvMIm3klkHq0rJwFI+wAAeNpjYGLcyjiBgZWBhWkPUxcDA0MPhGa8y2DE6MvAwMTAysYMolgWMDC9D2B48JsBCnJziosZHBh4f7Mwi/3XY2Bg7mZUUWBgnA+SY3zMNBtIKTCwAABBMREMAAB42mNgYGBmgGAZBkYGELgD5DGC+SwMB4C0DoMCkMUDZPEy1DH8ZwxmrGA6xnRHgUtBREFKQU5BSUFNQV/BSiFeYY2ikuqf3yz//4PN4QXqW8AYBFXNoCCgIKEgA1VtCVfNCFTN+P/b/yf/D/8v/O/7j+Hv6wcnHhx+cODB/gd7Hux8sPHBigctDyzuH771ivUZ1IVEA0Y2BrgWRiaoP1EUMDCwsLKxc3BycfPw8vELCAoJi4iKiUtISknLyMrJKygqKauoqqlraGpp6+jq6RsYGhmbmJqZW1haWdvY2tk7ODo5u7i6uXt4enn7+Pr5BwQGBYeEhoVHREZFx8TGxSckJjG0d3T1TJk5f8nipcuXrVi1ZvXadRvWb9y0ZdvW7Tt37N2zbz9DcWpa1r3KRYU5T8uzGTpnM5QwMGRUgF2XW8uwcndTSj6InVd3P7m5bcbhI9eu375z4+YuhkNHGZ48fPT8BUPVrbsMrb0tfd0TJk7qnzadYerceXMYjh0vAmqqBmIARoqKjwAAAeMCmwBKADAANwA+AEUASwA8AEsATwBTAEIAWABRACcAQABHADoAIQJ5eNpdUbtOW0EQ3Q0PA4HE2CA52hSzmZDGe6EFCcTVjWJkO4XlCGk3cpGLcQEfQIFEDdqvGaChpEibBiEXSHxCPiESM2uIojQ7O7NzzpkzS8qRqnfpa89T5ySQwt0GzTb9Tki1swD3pOvrjYy0gwdabGb0ynX7/gsGm9GUO2oA5T1vKQ8ZTTuBWrSn/tH8Cob7/B/zOxi0NNP01DoJ6SEE5ptxS4PvGc26yw/6gtXhYjAwpJim4i4/plL+tzTnasuwtZHRvIMzEfnJNEBTa20Emv7UIdXzcRRLkMumsTaYmLL+JBPBhcl0VVO1zPjawV2ys+hggyrNgQfYw1Z5DB4ODyYU0rckyiwNEfZiq8QIEZMcCjnl3Mn+pED5SBLGvElKO+OGtQbGkdfAoDZPs/88m01tbx3C+FkcwXe/GUs6+MiG2hgRYjtiKYAJREJGVfmGGs+9LAbkUvvPQJSA5fGPf50ItO7YRDyXtXUOMVYIen7b3PLLirtWuc6LQndvqmqo0inN+17OvscDnh4Lw0FjwZvP+/5Kgfo8LK40aA4EQ3o3ev+iteqIq7wXPrIn07+xWgAAAAABAAH//wAPeNrFvQl4HGeVKFp/Ve+bunpV75vULanV3VIvarV2y4tsyZYdy3sc2/Ge2FlIQhYIIRDIBgnOxiSsAQIz4c7cVLU6IQnLhLDNsEyGC2OYCfAuy+SNGBgYEjITHm6/c/6/qhdZdhIe77tO1F29VZ1z/vOf/ZzieC7GcaSP/xAncHouKxMuN1bVa1y/zss67Y/GqgIPh5ws4NtafLuq17n/OFYl+H5BjImpgpiIEeO/feMb/IfOHI3xuziO58bOvsp9lv8wZ+Ss3KVc1cBx6ZogcE5NumriuTSRbDmJO13TWvAt5WnRouUMadlqXJKsOdliXFqMWk22dM1s4aKatNxB0rLFKjoWBd6g7/JWONkkiA7JUhkYLBeH8h63SxdPOgtCYiyajcb6Y4Z99omMNxr1emIx/j31KIdwDZGPkDj/ac7AiVyeA+S4tGQu1PQCZ9CkpY48kRwUMJuFM8I1nXBNGyc6ZK2xUuEGBp30QvpEsqweDPmTgUB34L5A0g9P/A3OQMD54nds7Imj1/TAQwVoEeAi3Bqu6gdaSO5CVc+uXdUSLi0brYWCrNEuyR3hfL7GEb/WmpbFILzJwZtObx4gi+bkGEkDFJOkUE6UC+WCnv7pE/QvUYY/+pFHPDF90n7l2MTYlWPj4yc6rlh9lf0tcHTV2MT45iunr3yy9I3iU/Cv+I3Sk/Cv9A2EU+D6zn6EjwocF+d6uQHuFFeNIaThgiwIS1JfvhoTTOnFqVjUmK7aEXZrQXbDJ6l81e7GT+w2IyzsYE4ynZYTliUpYZejJF0VrMl8Pi9HjEvVDncfHEoRu5wBwgYsS3IenhMmWEZSkQMZILTTAYSG84qOKSNHTA5nINkzAKuNWHu8paymVBwqlwpuj1efTLnDAqy63p0oJZ0u+NRGnBOkVEym+gY3nEjmJrp81+0dv2ljfnRXbmJt/PjJ8VOeibGhNZ9bNb5qfN/kVssrJnuka7hr01Ht3kssm8cnrf9s9WXWZjdeZdi920BeSaYd39ZU6nH9dG8m7wAaabnI2Vf4LwD/mDg35+O6uCz3Qa4KC5yuJuBB7tEsVb1AG8pYslOzVMuEEgIsZQYObUZ6aNMsESmHXCabgdXNdtkORNDBoc4u++GwGw677XIfHEaNS/IAPNvNoqNmMAoeH5BC7uuGV95QPNFJt0HGA3TzRysV2WmDIx1XqVBOLSh7ouzy5IeAKom4zkkKpHzuJ3FdZM+6mYsvvnf32PCukUqmf7ibfLZc3/41eHfPnnt3j1bg3T3D5OzM/v0z6y65ZN3AqlUD+VWrzrzAf/jMkb9Y9i7yUhfQ6QjQKQ4UqnBXctUg0iiKNErqlqoGJE9ZB4QYoYRImCm7aAHVHBzm7HIRDs2GJXkU39ICgwgVqSjWDNFkvx2wlsyOqivcU0FmKSdFx1Oc1uwL9w9STgEMy8mSgqaN13u8Hu9Q2auDg0QypUtQxAv5cjKVTAHLuLyUaYA8XfNrC5fOrN7mH0mno5mudH9w1WBffsvxcHrrlRe/9aLN5dnpaX82mStc0rNqdX8iNfQ/Z/Z075yc3r12oquS83v6C+nsqp3Ba0aKs/7+rZfuG1s7vTZaKoVWk2RuTXQs05UqcwRlEHcflUFRJoEU8UMkY07mAF8tbAwT3enOZWJGlS/Ai4TrP1vhXuL/BnjRyRHJTAmpg59a6E/LxbLXRly4T/rvyZQKhVLmnpf/+/n4Zc/+8vPHEl+G34vw+2/D783095acJJyWjfB7K/09I0qqDCTUi6VisZS5997Hjn3+rdc/ezz+5df+8BxHYYiT95I84CJyJa6qRVw6QI0gLiBHO05L2jywPecC2arLM2naARJco7fiIiKC5VTZmyroy169V5/yJsr6+NGjngParO6A9+hR7wFdVnuA/LRYTE1ce+1Eqljsmbz22km4bog7SE7zIwD7Vk7icpK+IBPtElyuCkIDZBFnAilFODwkAoolC4olic/LRthdmnzVaMLPjHr4msmIhybOmFZQd5YKIGEK7gQIltBzleeeq8CmeeGF4j/9E8W5cvZdcM3DnJ2bAJxRs5moZiOSmJMMpyUuX7NaOAfoNfYkOwBvqwG2pmBHfjUhO1srlMRl5EZ1Q+orvm5BY3IHIh5/d7brgL3UyYf6o72J/ov8cN0w910C7Aq7K444y0S/hH9E0lC2qQlMZ2nZ8gMG4d9+d3qarRPVxwCzHtdJ36KNW46JZMhJZJlSlo30dEPIiCAyULdGsx58iOJ5ubO/Ij38EwCTh0NAUHfyFuQABQ43aORfj/7axX/lzDjowgLIhUHKLyFuhqvaUCB4hCXKOnJQAGTCCIPsBP3htMs+oJwJWDICzz4nUNCmRQoGQeItEqOJo9vdUZzgC/kwD1s9Ec+SIVeY5CdIMUviukJo9Mj0qqOjodDo0VXTR0aHw1tu3BLGB2K99foj4+NHrr/1+qPj40frp65bWLju1HVbtzJ6ueFBCzpbx3VzVQ3KLkLNFn1O0pyWBQDJACAJGqq5KB+DFSTq3X+5YeEE+c1fnznCZ96C5ymhAQD4erl1XNWC2BoBW6od3IhtZ05y0F0rmfJVhw4Z0WEBRgTEOdiMlFEkt7jI6RxeiiwoOIVZYu5YaUKggktfSr595uL3PvoYmakPHb/2RP/WyrXT/Fi+fHTfJc+8a3Z666VXbO8bm9jGcAudfYW8CjD1cPu5ahJh0gBMfgWmWocp6Qc11YHg9cLOUpW5FIqeFmUHHDtycggo0IcwmoAEsOcSIImlDlGKArSOqrczVKlQlR0GaIcUGD2Nw5TK8GECj7ADQoPhgyMbFnZvGjWZR9bs3D51ZC67/QOH3rlruHzo1pNbbj5Y7BlYPTI2QjaScrk0flHx2P6F6c0m7Y4N209MIImBGXkbrJcJ7M1dXNWIK8ajOOLMRt6aljRgSIGtostTy9N4WrLkZQOgIuSrBrr9DTqQBEYDFQooCToQOTNH11fiRbpfyyVSEJlYAKM3SsLX7Nu38MtfPr6W/E1954bHH99A9iJ9p4HH/QCLn7uKq/qQvmBAVa1IXzvQ12n0WYG+TqRvICdZTsuiZakqWvDSYocxLYl2WQfM5QESB+FZBC6QzQToqxMXBaPTR5W+ESwksBPNFg9qQ6coicxEatJYBAZxK4ROxKcLa69ds2P7mj1T4+Th+ufHDuy6+fZjH9pf3rV1fNXmSTc5PvtvY9cePHyjskfDwB9B4JDLuWonYhAFDDQ8Y9+aI9mpAQwcCoeA2rECKUN5yWqXEwCxmzGHnEBr3ahxoJkCTCzrdbh5k1F418q5O9CUMTrQYtEziwVZG9RVIm4DtvCqjA57mvc2+UhXGH7HnmvX9Y1sn9iZIr7LRve//dbLV8MW36Hfunn9RTvWDO4hG/c9fGjLxJr5a9eKxp6pq45e/M7hS2/qmL1q59C62TLdAxF4eInu7ziT4XR/I4/gHsfNzYEnRM0O1AcxN0mQCPlG/Td7iZW/aLZy5mP8RWjnFIFWDqCVm0twBe4gV3UhtXxALSOebxDPV6QkguWUdLiDuuDAY1eWdknK4ntmoFgJ3sh2iY7PGYw2p8sXFeg6D/pEx5OczixGexu2TRY081DLBlLsGaBPlqRsvNMV5r2KZNAVL14zte3Op+/atmrNxXd9+66Fi1dNXTy5KhBYNWWOFntdrt5idGFicuvjk3tdjovGt+3evW38Iodr7+TWQwf3Fqemij3jPkHwjRNnMOOzagSbLxPMj41Rv2bw7O/5IP8ZyifHFekmqtItCXzij1rQ4PU3+SSEfGKX3YCqQWGSELpXto4KckjNIgr+BMXbLypvM34xuDlF/qGyDPNg15FEHKyTQh7tlBS+UqgA5AG8B2+9bA0whcorU7u6iO/46P6btwGDXOzXbd08s5V8e8+twwdvnNn3F8gsW65Z7UBmuWzd7FBm9updzHejepP8EvRmBzfarjnNhFk7VHPaUWtJhryiNUG8qPpTbNOffJsejbZoU/IZplR5sC9u4yS4pgge42bFwjCza7rxmn7lmkG0NmTOAQ6jjdkb7Eny5uUQmlrU5BBxz5nR5LC1mBylhs0hNHznSmdS0BlU6yPOvOj99qFOIeTxghWSucjHDygONdUj3B6wwdbAHuKcpW63lbhD5Jn6HeQmUiy9OPm5pyYAlxD3PXKa/D2NLfiZ1QJmGhgsWu0S2huKeVGGHdYNf3iCGfLM94rFL5dKy65RLmVISQtfubF+J3lmz8RTn5t8kapXx9lXyROwBwOwBy/jqCNWizB6oQrA3UikLmqOBvOyybBUi7FFMtllj2Jud6OhAaZpjbf6wsiBUkxctDgjcTz0OCQDENEXAUbktNYAY0TVvQBRpQd6TmiY3HUoK+zYfPfuE+PrxwPjqUBPricwXrl04ggQNNbPTx7dPV3Y3DcSDbr9sYFwPpoI9/l6SlvrVsWu4rnE2Wf5f+dv4YrcFPcLruqHdZcChUW332NLyxNAwnyultFwbsDCmJPsBTkG7w3npVSuJtC3ibSKGmN9zPrus1Pru2RYkkp2uQusRR39QJ4maWnI/+zEp373E86dNkn+rE0aeU4rB6yv2aTgc9KIfdE34nemF0fxsQqP0bujdyd04GlWJF+FW/QFR0az8I886fMHlONsVpryE7mrBNLMKNg9qcxAnmktdPFzA7CrJ2JUrjmtXX2qXFPFfTJH6HZmPOotFwSd29VQbOwYvDl1w08SuuETv/nY+6Tja3sGeRLYnl277dTF2dUd1jUVPuBKrvvoLad+8KmbL93tOHjlnU++UM7tnAiZSj0bjr/y6C8/d/tV78jFdcnBPRuOPtQfn6j/p8XoC+zZe/PH//memz457J988p7BiT13hzJvxXUBw4K/C/SGHiyNfq7KYYREKFDlUdMZOALiTofsZs5RN0wmsAclE+BXAM87kYrpyzHBSCzHiHX/aL02ukAC96AL/eCDPyHHUJ/Mw/kn4fw2sBgj3CF2BbTFmH6KgFTt9NLLdOJlolSqdoBU7cxLHWyNQZdIQVQqyNcxeCMIfE0Z2IsH5orUKcJLKeKQtAiYGGu1xVKMzmlSggN8nie9O46sGSxtOrbnx98emV41+u2/K4+ND/0d/+F9G8cWTIYDYxcdmp0oDU7Pju0bp7oV7Yc7QS+4gXuZPrSpWsGIQHuohW8B6LzUygVWepJwWp3ooJwwZB9CM4AuKhPouNaFr93/6CXrQgeHr3zggSuHD4ZmLv3o/U+SgS+/J5UeeuRXj5T6U+/B9UH63Qn0w/jesEI9o0o9Ea9O43vo50pGO/p7lExOBEQ0iipJFFZsEGP+F4988YuP3Hff9XffeeN9/Ie/dOq+L8w+eNXVD1J88ZoCXNOMHk37FcGwrmkZW2jx4pbGxdEFpe6p0QwmH59nvqjigBao7cb+mydP1j9GLq5/mhzkPzz7g9mXZluvaQT5QK+58vVMK1wP3GHlYub2i4mNS9EL1f+RruXL/ClYSx93nWIJtq5lzenqFFRb1q8uq2Sxo9ajFg845KKHWrZOuGBAMWerRqETHQaPKOmALzFsBeaDB96SjS507bQ683l4oZQANYH88PX7PnZkOnpsBPmhvD/0r2T42Mfvq5H8c+/o7cs/8qsPpUN3zv7ntSqt3kbXZ1LZsXq2YyVtoSaYKLWE5urg/uHzGJcDKxDoJusbMRFgDDEmoqcHxFogty8s1OHE9Z+SyJkjJF//B07lB+4TcD2Bi7WsjeIdU98R/7SNM84voAhgvzWDbwYSAbyYtGJRoe+gV0PmOhahoc6JHjwA8PsrTbsfzoXy05wuz4xvWLh+38lVk9ObJsl369njVyh0WE/pMLCMDppCO/IUXWr/yoKxwnaESApGkhD0bkA8dbz+S5I9dmY1IP+XZHf9K/VPkv6N/5tdg/wArqFVpSOFn+GvU/GvCpQTBS2whL5JWDzzEJDiidkGHfkX4VwW9J3puXTGQgvEVno+heH0GEMF0tjgWY8eE69BwwdxqAoGc0XBIkBw9YSEIM7f8MI/3rDw8/jPAAcTeRU89u4zL+Jf49rX0/2lXFvStVzZ1CpDBOXKZgwIoAjh0VOT9BWVggbl2gQ5h4jz28mtC1vqbwdM/4s3wnVdZ35FbU2Um38Pe80IknOG5Uxkq7rbnE3JacJogRI1ZkJUtpvgQgYBMXZa2QbimhvIYweuEFpUaOHpB+5/5pn7Hzh4+1VX3nHHlVfd/jTp++pX66e/SnZf/8gj19/w8MOqLE1TGoiYt2hKGZCjNQPbN4Z2kWrKI0VsbVIVQdNqKqqqcenSxEcaysVy6dVvOfDME6Ozs6NP8B++7rPX1f+LLMxcPUPp8VNKDytYgbuW+xeBZqzIBhe22eVOhR4YK+q0YZ7IaME8ES4Gaj/qRxtMIHYCIhCI07cSCKOPKpEwJNlKqL1TI6vmjyKxZob3j+wbbyHYpWvya/NItPixwaNzVyPhGN3ydA+7uZ0K9xgZ99AAi8VGSWdRVlRxn23UfXYopMNFdcBKgrmKi2pD2PUG6iS1a21nQki0kvOS6w5vqB387HtVil558Y6juvpviRHounU90JVwSeCzINjLXdznmbVM96jIs1Ackbpzku207AOYfCwSEQWAksxO/I/7nj+JdqIN5KNkfE4O2F6TQs/Bi0WT2egEG9W+GAyEwFCEx6ahWIUP4Yl70mgyB4IhZiKStlfUYPTZWLwFAx2ih5rhUYfsdCEJPAIajARc46iaDmIur5baiTRuALZhWMNsyMHt77hoY//a7dvW9r/70EO78htuHNs0uvPYztGb3vHJfZP712YTAwFPILluYOuxS8a3jOYSWU+se+vI1muY7EEj3E/tvBGuqmuND0hCngZKQRTDQlW1NGanBaVa1WnxUIfRI6MSR465EyBuouQP31/gL5qdPfMERg2ofIE1uBLO38FVlCioTpGTwCrUnWSiUhKoGqIBAtSpBhT6VhtLRqK896hyP5qcXzj41MGF99VffR8RyMP1yy+5/PJLyAfrl73zvvvoNVXbVYd6ieLE8dR8bYY8OB2VX3BulJQkYdz/05/ur798DGTVc/wUVVIEbFNOOEzl8qNqTNMMchlPtkgEja7LS4UzigFkmedTv7mbuhYcuBa8XStxdpkA2/B22WJ77dnxJ3+jpR8LWZnwBol/ziab9K9pJfNzzz4/p3xmzMpmk0EywWda/EzznMBVea0J2WgKJBEvaLTATZZs4x/wE6egAf8LCTNJ2PY++MjaRx7Y+6U9DzywBzD6Pt9P/47w/jMvAV6ACv9Oqh+Tyq41FKgHCXYC6kemFXmU6RoTlWdEoCcncHYL0fz+yNe/duQVIhz+p38iO8ja+u+Juf6F+uMkWP9Fg/6XUdt0gEUSmvQ30jirjuV9ZJ2ergIsh75tOYCVjJe+8MKl9T+AxVD/Jhmqv7P+EvHjuQfg3J1UVmcVXalXI3YCMwSptSfrWUQTDEV41iEOJRLD8FbMPUBuqN9Ffgp/t6zlLbNrz7yi6OGes9Pcz0AO67kyp5iZ4GxyDR8e3Uy9hTNr0I6VtcYl9ZWQVzaCF6Om8Nfz7K23fkk4XD5jKr+R3IFYcCZGfz3KP3FmnKP5qmnuWxQOsHkZagAHsC6nwKE/DZes6djFdcBlxiWJwE61qwDp1XiDFzRxCS2BW2999tk7+FfLf/wIw9VJNpGP0j0ico2QP90bA4OwBE5Yaefjlb+auOMO+OJ8vUq89SX43dkzZz/Bl8/+EHDxcpJAQWJgYaiD/hrj9QI/cubrPRR3vh9o+gX4fg9+v0YEzqZJt1BBzeTIBFeKqyA1vIn5Byv8F04B2wyAnfhV8huuk0twJ7mqE7kJ09ByULtUtdGKAt1STYh5bFZKJhoAAZHiM1Cpjn6iNpzPyw4Di334kKvNlgqGkkFx2jzUXRcws6wF8SsZRfqp4qd7W8P4QMlmSrWEUnjgyJpjlTVD2ycTm65bOD43fmj10U2ri3vS6T3F1Q9uXJjeOTC0urhly0K9Vl69Y0N2dOzisVHAaQ5kop36vn5uu2JvmBEnh56JRlYq4dWzwDlgYwPo+Y58HtU/jSmaWcjcjXlwrRnVhtcBBqDBKqgGoNgIM6TcpTBTnACyfm5u8vD+G284cGTCdVF6/bZt69MXuWCTnd3+vmuvu2vb+tui/ccfuyxD4145oP13gfYO9G9FaqUBgALCZkDYnNQqMQMsLlxAg1Xxb20dzOJoqiuQ3tS5zd1+4upV+eymjRdf/HAuv+rqE+/9l1PbspNwxcnsNmob4jVfadKG5jcsKm10tOIAr+9r0sZuXpLsduR3WeuGlTYYGG2MdrRJLUgbH9KGM2krzYVFE5Uu55DibqHrlbvhwOHJubmJIwdumN8207/F7b4oPfOf175vOyFnjqzfdtfXHzveH30xlmFw8lpKGx9Gw+0IolmnUMcLLOk02KnHqGUeIwAKiyY585LBjuSSdQAmuokuAxruZnuF5j2YyoOvKtoPEx5cI2oUIjFcSSUmFKPeYu7OoyfeUb9Ju29uz2jX7PUn795MxsnWjesXfnf5Aw9c7Zw5MD44e88HJg4dZPseACVbaRx/D4tZUKJS0AnG3joKIIyXJDFPTTYXzSQ7DWi1VZ0uVPtOESwAlxMPXWgB0NCGmcDeNSoWKMsrNxc/RArUOrBvmVs10RMJxLpTBw/OkU9Md88udA92Dma7p+v7ySc4Zf3HyMtAVx/oppOKJx7CpSfq0ncBeOacLGJRRYpyoB8I62dU1UYVDuiBF36iRtxdsNfNIqsi6WwE3LuAylWidVO2YNxaYp5lkgbch8ZpfC7VwiE6YJFDk3PvPjy1pzdZPrp6V2DH4IHebTOwiVxb+tcvvOulO7dvqKevOhTpHZ6emV2bHPjDRceyse/FMkcZ/efg4cfA3w41hqJazBRD2absK2AXkFjonjvsVFUaDXSXySYH1WccrdaiSRvM1GEKCeSTyLa4ODcX3Ff40NxwqXezF/Z2bPBD9f9BJsby/ZH6x4HGE3DdT/H30Jq1jVzVROUPLr4hhzF/l4b54OQ0qpiwJq08LVp1xJDGuDJqWauBuueyteGRYYIauRQJKMD+mgi73OGw2yXO8Wv7wuG+0Jkfkp/XQ3Sdz3707BiFwQp6ZB6sBLw8WB6Cbgn4riYqUHSySIBhaTGs67Clay4KCM2WG8GCk0UP7hbBQjWHpBdB44MCKrcGCZowHQpEkl19c7NrR69RIHu0Ekn3844z/zEzLxgpiI01eoXaR/n2+EFVQ7h0I4JgaEYQNO0RBGcB3JWU3j03V99/+gcH/ucWWIQZQl6s//c/b767wQfcB88fOwHi4l8zdjI314ydwG/5H8MeiWA2isVNvRgvIAoXSZaCHNCjsFEDpxHGSxHmPHrhlZf51R0GFjrtjFC2krwibmM7VhtycqANK8pkHm+D1Sinqc9zc449A6Vps2dP/o653V3rXXO7EzNu8vN1waF8T9fQ/fVPkfWH+8P1j+ETcqFK5x9RGdq6F8iffy/kYS8U+zZ7AJ7Y4Efqf0PGxgvKXkA5bgUY9CAZZ5m1KptVLdeBEIhUxqDwNihxVFB4aqXLoqDT81SsdJgxHKHRcqruo8mRFPotWHeWu+2Ht932w9LOB3fseHDn7T+8774f3l+fv+KKj5y8gsm9ubPreTvAgXpvG9diDjTIAeYA2KLnswiMrRaBrmERLBqMgpVC5FVXkJoEPtJmEgR25A/ccMOBo+NgE8xso+Lsaf7D65PZu/7t7u31s2Q8lrnsseOZKIO1/+x68tsmrFYVVj1pUc8gIyispKGhqcWPGtqoaGgT1dBWVUMvEk6NhrKECDVcAVq+RQD333Agv8M/Nzd+5EDPwkz/RU7nRf0zt/zbXdnk+jNHCNlOtqD18i/RjMJfZfJr8HcG1T1GVOOKxnOUwBrbyDZqw7Ry0lDBrfLQ6n02e3yLSH4+v2uTMBCqfxb5Nwa2yieBDnGML8RofQmoUTue3o3aKZGTrKflTjh9J4vbhQHxLiW+UHv+YGt8wa9/DbNQjfiC374Y8Aed6So8rhxf8AeCLfGFxisaX+i0sviCXlzU2N0xjC+EHbLDSUtONTS+YHU4w0p8Qak5yArtAQaBWo+xlG9nbmhsYueuiUsXrliXKFwyOIIvDu95+9RQqCfbHe12+sbzo1vWFcfTsVDM6V9VnNpK97cJ6BPhj4GtcUCxHy0KR4OjSc0Mfb6tdq1hcQCH0EC+q1G75jK2WxwW0OJSR0XiRJrubVSyic2kWUk0bZk7eNDXGXN4YpXSEFgc73nPdP37wbhrODJSJmNUBgGMPyI/ZzIIOZkBqlMBNRVUGQTyGIMUIAEkYx6ZhsogK3otIoZAdUrmuUyjFciw1MZEC2JurlwC8TM3F7648KF7yfb682P5vgg5VA+tiWeZTBfg4f8GOFpiFuSCMQshIVz0iUe3/v1W0KnXkfczvcp8+/8F57Fw72UxC/Tt8VSLBETV8ojFC7+ePCdiIbCIhfDas+ODyse6rGTIoqOp179mQzGo1b/GybwWeO9zHOG1Or3B0hKPIACrRUkHtgUmLPPXv3PqndfPf2jullvmAO53knfRvxB5T/3mBvzkRYC/PTZBLhCbKKcK3nJB7wWFa3nmiZ23377ziWd33nfff//700//+39//etIW7ApkbZ2zDUoZEWqWph4R2EODKVnJiwnyjw9MaOyTs+KL4YmCaX373qOhn0Wh9cft0QZ5c98/gCvX2PwhDYg/EV4eAyu1RKfAJmAdoMs6N9YfKJITPVXycn6K8Q+Qo5NV+p/sYrRRnt2mnuZ/wwX5bZwrLLYrAXLNyd7WZiCYMF1LCeFTmM2x2VEq12Oo48RUpiU82LleQgsYoKFVJIZvMcO6hSV0NotDo0SN7XYXXpwNlwe+jIJHyS1vsBcfnw8kMpmU4Hx8fxc4MV8KvydsblyJvG9NS7Xmu/Fs+W50X8Ip9S436+499KYh5drWDXGJfqnVWMl4nyZ1UuymMdZFbcOxM0GSEVpgAHMQNmr4KY5jbsvaETrhuIWxNJEzEF00vaFYIUaMfqKZHPIRifi5qWWfLFM8aD5XopbwU0R1aWJ2IqWjyJ6RzbOsEpkynNj3wmnANl/GJ1juAXIZ8iLtO5tG6sFRoOrU4v1gpK/IJu0Dd/Ub6SeiYXQbg+q9Cx+ZF1a/E/tFw7T1LIBDFlJy6plnRNCPiygFLMJiXgW/vQBrT1cXJfzOoLuVeKwtiNc7Epkvc6ge9JJ/ia/aX0yVRlOPacvbISj4eHU36o1Peu5z4L+08Nu2s9RzYwV2FgRYshRM3Z5EeyiSYsmPpYOG3Oyybi0GDMaWGdKTEOTtvBmq9WjN9BdQ01/avAIzoJzLNYfi2a9HRN28ijWgcTO/D3530pfSu7sR8h3+RLn4UJYc4fCVnIVcCtK/rxaHOg0KoasUEBjTArkqzozjTlrUE2EKW29ZmrFYoRH8GOEBznLjA0Y1CO1YCMBZ1RiEeWWZgqRlsi7E2BPlF0er2gjubfsHd03lu+ZmuzNjxwY3fuW+TWjo2t+d/B91g0zhrnskKF+j244O2fYfbHlfYfXHbaSk9ZDGEM7+zL5I/jSJe6vuGofYpIryF3C0mKmqw+oGNPTnhFaH2fXL9U40me0pqVO2uoC2BJpCN0baSCPVcBVnVONqmNBcAErxgxL1VAB3w35Qe+V4S0nej18DpilIMqREjyHHDVvZyCWocsRy4BHG+kZwGACCLJQAbxcO3jBVZ3FSr1c0JNZXqk3YdlmNxbRgeLE8nd8W61DoHEvWnLmvDzoDr5n75rLg6tta/tHtznEHt0H36bf6AvEdgYjRUvX4I7cga6+jeGptR3EMhQNrIpvvXa01BMfWDfiH/APGoa8rvkhY6+vY3Uu2zMR2pwJhykvBLgpvsJfAs9d3DUcVttGgGSJnKzRs+yM77QcBK0btFMfBbskkrjjfWgrur0BpXqJ19ldrFNiUW+0dlBCRNCetNldtGg0IS4arezrGscix+sMrLCp7EVzp+zVI+4sL5bSp7CjouxV7fZAbn5i+46x+ex8LrspuwmOJ+dymzLZyM4P7oT/+Vx2czYLn05uW1i1MTOXzW3MbJpa2DH+wMyRI/ceOtwWD/dgbYGtJR5es4s2zopuj2wHljDnay43fQPMIxeGfIFHvJikkhx5mjsz5KtWGzKEFYspdPmqzYqvbHZ45cpT585qU2Pq7jZzAct5WUlvAmwl+KMR9p//4A9/+MMC/J1WAu2LxROlt72tdKKI+b2GDNfDblUi4KhaBOzhoU/NuLcoUHleLrvIWP2r5A58hHPEzz5BPgl7pI8b5k5zVRetUwPUenMsWlvBwmBJzMtpXOi8lKaZOKmQl5PwRjwvjzBT5Tdnnjcye9lklwzPyRnra9Lgc/Bi0WgygL2csS9mM4PO9GIOH6tw3FK+latU4VtoOD+VGzQYTRnVWCHLXlPjOW1Rk3NPCR0uX6QLC1KlpEP2eKmrImAXDhE93uQQ86zKnqb9rPTjtBrRehaGdbrCBPtzsNnERuLJsQOlKTSkV+WvvXThrePx/N6BcXy9d+/xHddo+1MDes3CeHEiLwyuz/bGU27f+GB+lbVr58j8TGasvyuScPinijt7EzvWzpO3+7utFp50TaR6rHZMkZz9HZ8hYf5uzgBWzyiH5fwdBQzugBhHPmNH1Lll3Yn4vpb6aFhcGWXNHLCygiLXk6pHawsmA4Fk8B+CyWAwye914osAoe9hXVf/2d/zP+H/kl43xd2nVJJaaKke6wGy0+NaMqoXrPDEXrn89JVLKenroWCZWEmfiWaLayH2KkTT7jUtq+rrxfJPsG6mTLxObxZwwydZWW0U3rRisgw3hIfzJrrUstqox66LJh12T3TInozyxWbljbtZhtX/TRL+5jfrP/tm5Gmiefrp+h833rRzz7DPuTqx7sjRtV2rXP7Knp1k/gP0O98i9vofn8Yv1k8+9bbpTn/kyOZNx6N+3zSVc71kgozzd9IcxvXgKaIeZsWL1BfFgFdQLXFkXXNKDsO4LIdhvFAOA3tFaFchyESZc2GJkaB8T6kmbs1mhMg52Yze1ZnVPdnYaI+vuLmyvtKzun/NSDo2HAoNx9LkM4NDfeVwIts9NFT5XiI9PBDuSg4nuyl+YW6SPEIe47RgZ8AhtcWpRR5+dO7RR+fs9PFlWa7V4I/WurJaWS03oFbKqt1MVL/rWO+JEexm2omp4Rr1MzTTXAqRZ8rkwdKrX2b22J/eL6SBFTlDvgXyyQgeYJTr5f5W6VQT1QWpWdlRJCcFCrUYW7ZIDOGKgJ2CMqs312DcPmpTmRmrmuna1aLsVSwvRe24frVO9gb8stOOMVS1RDWNCt7M3JCoKFkqUrdjURRCVHOhkUhDJRHw7atmzlahK41Bu15Qhx2mTqVHSG165JkKS8SFkpIJgmVJuEtqqV/i5l27336zdODkwydObNykORTNZMRVPZP9q+3BgLia3CTd/Pbdu24m0YdPwjfqL7zcG0t0X3rgwDv8DmeA0Z3jx8gJ/iTLBTL/g/kgjVygiB7NCX5sAGUS5yUyMQOtzfD99ZzSHKShpmaHhvUIwa63MOpY2K5XSIMRXwfWhhhp7Y+749z+z0SzOwC52TuTL6xfX8jPDPaFI/39kXAfn86vX58vzMwUIul0JNzfz9G6bY6c5mcAhw7s36YeG6vclswFTPyCu1HV0IIHjQ3MUq2GlkHojawWHlQzKELs5G6qZgG4wtRQzWjPgcpk1fEFpEdr0x2WgdPGu2KRrMHWu9OnGW0HyafJdmGUc3HTHKY7DBrajsQjndxY4o35Z4Stg8LWAfYA1niz1BGyjkNc5LQdrtYSbp2+gK1UrAdUP5i/dGzh8JFv1X9882X5xIYU/8fJ8crwVesHM7suy3Z1FxkcfeRjZCfA0cVt4tA0EwAOA3jhDBzqlXXTIH0UwOnAalzwedBM42gJB+zrKDKqVZRCAJOj6nL7mSGqKE2lX2rldqm+aP/6dP54XKePHiwkpzKR8p6pLUOJ+MTWtcfI/5UcSkbXkjyZCscHuyZGBntyOiHfX5xSeFPNO0eRN8+fdwYmBVn14PzjfP+pU0p8/ex6vgt8eD9WNXnRrrcDK+iWJGueBYWMhZZIrJ/Fpv1K/YoS2zSAmyehUSpKLmBYLTjeko+63S4WjBVdSojIpcSraGtHyj03d2XvvGcuZzboPI5d9sDW/jn/02CcPX91P0aM7h3hV2l2dA8O/EjxRcGfehutUVF3FHBK1UDlpsEEvKfN0zin6XTNyDaW0V4jFs4ERySHRWy6pja1UXo4MAwgJuh/8cCRmcXM7swM+at7j5wh/P86kyV/SfssuS+Bb5nGSQpoXSi9Im+ywTLW/xP0D6O0RmIV9x0qGdZwqBCZfsSMlF0RrTQXVHM25AHL2qP/bBCrxORENrODvrMhe7mb7IWqqCEinImMr6vb2xGLZPx2d6h7rH/yE8mQ15kQndumzd3hrn6s+yGf5p4QSpwONAsoo0YzpPE8zZC2k6Wxaf4bV9avJtNrQab0gL6/AvQ91jeu5tTt4qSbp1HbaGzWNhpfp7axmcJKtQi4nt0bZnfvnt0QKucGhocHcmXy0ffv3//+/Z8uTE8XaHf6Cro5VfDqacRMH34U1fJa+jhZU5Uz1Yk2zC/R2hDs/u/k3sesOMmpVIYaCjWzR0+sNFts1mC2uOqh/rnHinLRp5IL46UuQvt0nMbz5JBRcPkVqsrExJK1BqOVGTUeRZoRUcZK6gbJsb+/u+RU5WiqUKKLMEo+O1zfTshfL4yMjN55J59ha3LmvzF5drifcP/P4OHDg18HqYA4/peCY4S7lc02wO5qp2apgaU15MECRquGdSA0kUKA7XDoylf9dkTD7wE0Ym1o+MWawWi2OikeTg8TByHxSY3ZLvgj2BNIsO5Rq2tHy0hWEtat2A0MHmwX3G1Ykp3LxLgGfC9OmOU/ATK8hytwQ9wzXLUbsR0s0BkOUrIgOwBrK2HSo9Zb7LbC4mYKci8sbi5fLfYijsW0ETZ4Aj9jnFw+R/CjhZOHBS/l5UF41Z+vDubxp4M5WPD8IB7me4FSw0CpPLa7JVPpIiVQsRcI1FehSmMRlAa6Vn+i1jiXNy6kR97JiMorLEPWnk+t1P+4jIno/oqcHSOfJ7/mAlw3dwVXjaBt38VibL6c7MIsU5KqCWyBVBpeMXMcw8L7WpD1ZwVzcgoDG0pOQycuagzhLhbTqBnBBWWtgl3YMsAZPaxB0FvE1kc6t8AmtPQKORt9bpGe4UqPfyzVXSp1jw8fGh+cv3v3iYdpa1ast291XzIbCLoCiVxiONU1GEqVLiod3c1HvbGY1xONwh6hdZTCIRo/tJ3bBWRpdgF15FCScTKxKEkQtQvIWfAmhLZOoOH5Byv3NrqBhEOn6mbsCOLarmda6XqGFa63QtcRyvtlnUcVVO9q99G9oObbryVe8Fpg5jgvcC3MOyy73G371x8sLGxpveLllzeueQlcMwKeyi3LrxlVryl5AT3YecAWZg3LIxpO1yJMfUeYU+FierAL2CaCgEXRGayBee2lnXwuhxTDpBTsMSleke0Y9zdEQCoFRdnmr7SuEOszxW1VYD3I6Ai3r9naQraz2xmwuwOZQtbX7cCjSGMN+R+MzYbioXRaearr6YJqFHwHaU+pA6ypk8sxtjcw7shJvgI2f2Icwp2ntpXxNM6VwDesVI3UOllgIkij6YCYHXUFnMqBqr9TScPZ4QNHC36NwHRMUE2PFsw20miGG3mEBTQYRr+l8Yy6iRz7H0pko4nPDZRnXLCG15yXa0DZ1zqZBRPK1WyKBQMqxHy65mbr6KZapGZn64iqw+8WHU8R3mpzOE10vyscJ4c6YfXs5soy3mvs85a5N8s48eDIlpHK1kpPfCAe83XGGxz5Qu/ISG/PyEhPZyLR6YvHmSwDJS+8g9ZqOzBjS7OHXKG9yctmtyCONtp/ZWn0Xzkx1Y1hPLUFy6pmbhuNX6xIUKNtrE+z9StWAowKop48Sk6rPWD1ufprF7/nJ0ormNI3iH1aa2nPXYZ7d0vPXZpTRxEBsEjyOCN+KlfzKsTPtjbRoBfuZ5TP4SAiC0aQjILN5faGIn1pSv1UHNwXf7S3QjNKsrsPIyo20VHTcmoHn7N4bgdfB2kWXrYaoVlyTmff/oc6mA061d2wS923P0E2PdzS7XerJkXt0rBipo6av6j2rAggv8ywWptfrxvP/nrdeFhxb+SoqbWsK49gMW6zM69+M1bmsjUB2c34phWWmT8HLMthAIneCsOvqDinMPDfo05bKwyO14fB+XowuFaCASV9KxiPqmK+AQlIebW3VQC5h/OGAtzNF4YGgfEXsL8eJZ0nT9vdLwjdotXIGdI1kclGI63/qfmYbMR2eGzvlG3OyvKl5BTxp4rBVlw+QOVgVZGBDCEmBIOqAOTPYtufBDTGfIA6LUZLq9YM1DjG/kEsw9VraBENRo9R/YOPmweu6V0AhjmToWVsPDcJmzn2ps4FJrIezzUJq9+3gORWTkZhewUez8D50J7vVboODPR8ZtpyYGLzomSTHms+eSwFRvjYqmKDiYWtZmqBLWTz3MLZnwGsNqrHcEU3sI41mtdDz9DRiKvbYPFcquOrBNSVnhaMBVoJXTRcJjflL3VGAl5eVVNhSu8tCx1sKdganOlHYJQXbM+Z4OEx6vf7uGNKvZi1ZeIOjkwRwIj3FGROh13TtArZTKtrMJPkzlet1GWzdoJpbqbi2oyxKivraUX6BxrNkXpRSR4qDcNpInrVOCKa2aYDtG/4Fwuscfjxx0l6nBSwe5ikf4r9w0vjyh69HuwfIxfj7j2n2xDtZXBDpHCOOVzx1t5DzEvElDgqY3gPe+Vp9iUmlOy0xFdkdwwLqH2V1t5E2eHDPrMYyPOwKNuxUsDqkN2e9q7Fle0htZcxsYIl1NrfuNwWovKA9jsCbxrpLL3ZFTse/St1PAaUqMCiQfCw4uU30vSINvc5jY+bYAee0/xIPn7q/wR8OMtxOXxfhF19Lnwd1FZvhS94HvhCK8EXboHP92bgQ6FwDojXMgmxIpTUvmdwXkLhzHB3rgCn1J2Tw8DjfTnZhzyebYXaA1ydYVydoRnvWpy9ijcxQmsFk/xPGqxOn9B9Dk5yuBt43JMB3u4T5WBP5fxYrsjn5yC9ewWGP5cCzmVcr1FoMUhpEQIJf/1K1IBF6yrUfEx6RvPUVW7SwwsUCDBBGrBjVUctQaUnDlBU6YFucySAK2x1Cm94hR3LNOE5WO9vUYfnYtvfphgJN8U9SBZ5gxJhK3vZjD/91IMPdj/4UDc8PvTgMw89mHzooSS8fOihpkwAO9YFHN3FXctVHahTaINkRFA7XZBOfqVTFWShG+W2nVY9mVmnquzmqDktxcXP6QSb6DR0hljYgJZEYRUEekl+sWZ2cl4aUdA5ZK2hmRKEvaiETVL6RBlcCS+h3MGIlQLK7J1zT/dVJp65/9KNnun+a3ZsID3Da2A3lOeuvGOebHroq32Ridw92x76aia26uBnb5kjT0cfrn808cj1756jNQSv8FfC3u0AzTm2Ugeoa6UOULfSAbpotdkdygDFZU2gKOWajaDHQLyd0wzK/0SxDf9/gwEN0wYMPwARdi4M82igtsLgWRkG70owdLbA4DwvDNQwbYBxLxNTK0KCBqqgwDIIsHRyUZzdthwaBCZSqDnZxgzkaeVdEzqwD2putjEVLzbMNma4CTkyqVtUBhnKYSx6s+pW7OZVNmOiaZc2UHk77jGna5Huw3MROtG2D9nMmsuAxgawivLLO0+tjc5Tm9J5KvO0Oezc3lMBI0hK/6md+hrNHlTyjLKeyswAC+zguZYOjprZSi17M5hggqs5csOtup8yb83n1ckhaGXRrJ3LSqsYWd25amO5G6NpFp5pmx5ww3U7tl97/4/WXb1eyVe9wk/zn+YGuR8qkLhph6ROaYzNYC48TwEYNCxJg9T/pWXvFjZ9Vw+HeipiaZ9kQSm5mXt+mJXcJOxS7DnZpn9Nsj+32AGsiDJ4MZ6IOdNVeNlSnw7v0fp0W4c9Fk+o9emtr2iJTfcgoNtZkSxiVePLoIfdB5YZaCtJD552EJclEwS21zs6fVSOF8RicwyVUpmeTJVbKtcneGVqkjh32Y71x3LDudFt20cv3T290J30bhoYGsWX2aHsWGpwmrw8d2xtpXs4lAkEYw7/quLE9p5kMZwaTES7Xb7xge6RcI872jWer1txv9AeVP4LsFuCXIp7S2sXarStC7W72YXaw8bAGegYOFrBEVe6UHuVWXBVs8VXoTUcT2ENhz8QfNOtqDS6esF21AGQi+8/b0sqf82p+jGlLbUNzwTg+dY31G3bc95u295llSoUy67uFCohh0NK/ulttyh2L9R6uwB79nztt+TyU6eW49r3BnFNnxfX/hVxTfYouKb+P+GK4v1C6BqYwL8QxkzuM5yfApwHuFHuo604F9twrqg4w/LKMbBXMzk5iPbqmCpEFn2DGIMYYAbqICVHVds1lGcEqXWz4No4VrQgr1tsbIR1xYk1AUiGlvIkOdYDR74BoE1GlCPpC/P8yvHqC+6C8RWM2NB5dwV5aVk8+5C6RcCuZTS8G2gYBxu/hJMhmlRMtlEx3aBiNCcVC7UgU6cDrPAXh4EjHRNIxzDTpgmFrXoYFSWHXSpET4u1HFOvuVytwOIHWAqcC4MbIBg9tiSLV6ZXIu2FCcn0Lo6UV4mnWsYrEHE1U8YBk0q4r1K1fK5QcbCawPqcwn93MAWt0u4XdM+luSHur9/AroNNV8uxYG4xV0spwdxy607EYG4/Y8R+uzwIr3rZq95luxSzjoP9GOoFsgVjyVRf2sbKplfkymIONFB3T29Xc27f62xWR2vXH1NHF9q4fTQ6LyrB+fPu3w9uHRnZWjmohurpPhbmyG+4JFg5oGuVbG60IPfpaK08klFyFpCSUjlfK3R2IzELWqDrQHdDmo1QXysFNEzR2xRI2jztVSvQsjQcS+9RxtKniCrZMrTesJvWozlkMV7BWfVVZ4DW+HgcciiMm7yzDzvMQuF4KovfLIgy0SqUBaUntrZbN8npXd7gnmr2Xo9Tn6SbNbwPHJu7enLD2L7Vic23TO2zjt1w5Nr6fdod67aVu9ZffmfFf2J6a2L96MRC8ZLR9WQ/6Saz66c3bfjgtqkdOSRusXTZ/W9xzuwbL8xeV5x6LFOez1vGy7OTBw9xbObBajrzoA/zc+qoA8mfq0UYE3Y1a/2YOjCbaXAP7N2alwk9VAZxM7KZATuTXf5giioCLw5XBqcMK4OCFalLrHpDSSScyyE7UhWsY6G5hZ4WfmuZnnD+xEL7VIWxQ3alsiXZyCp4DtzwuysakxY26fraUgrjxvdTn5TONACd6KDdGSeWTzUIwMb0sqkGXu2S2oaBjbFeOtWgU5lqgGYk7aN0YtXik4LZ7nJ7FNdz+XgD73nHG7DM8cojDtaCVfPxFcYc8KOn6r/AUQetuPgAl2OvN6EhfJ4JDRFlQgNi4Q+E2JStqtUWrLzJMQ1YFnveUQ2HwGBZPq7hx8xOacUjyh1+PTxi58EjruBRQzwUNN78rIlJQo2R8+LhY5bICqiAAaJRcLmb4hKHHfaBC2ODyPQWaiGmNrvz6o5rYoeuZ4Spzggb9trDNGVPE3PcjX7WpSR34WBbs93LIkVvAnHn8ir485JA31oev5wQxNpeLs/xZ/GWNI/TOsWWPAhpyYMYzpdTqcAm6J7jv3DqzPfpWAWeGwYB5n9T51JzKsPAgMk5rIBUTkZhw2l9v4fzteVUSEtOxfA6ORUX44d+eubLL2+eWzj7IsCqB14w0ulxG1qnUOhzkquRU7Hnldlx7U0KOH4CUxVYPe1kNpG3tV8BBUhLVqVbsV2unnO29S2ceRoh4jc01oPNA+C/CByaQAnYmD+CU+NqQrxTtCqNnF2to0dQTLjNrDqfTh2hI+wi4ud4ncbqMHayIrB4iDa5uzUYqBVxrr1Ob6VxHVYW6U1i+1GWB/GudCWxkj/l1jW5m5+bGLzqA47rzb6IoXd15qS449l3X3FiiM0UuPX779u9a+tkX1Fvd2knehMDvcmPffGa+16dO358bvb4cTpjAOctgP3vgL1313kmLkjxnBwAiz+Vkz2ahs/TmL8g9aE9yoowschBmbrcHMwghfELkaYmDIMxsKjz2OKUBIE4Nin0AXFSouzrrqw8s0FY0cZvneQQXsGiXz7dgR9YIRfD1vcLNJfn4haUiQ8d6sQHp57FanDAq7kx4BUnPuAAbQuhA4YlERw8nZ43mlmdhrNjpdEPAnPOW8c/jMOW/UTrCAj+707Vv66MgWiFzd4CW/s0CvdK0yg8yjQKChVYHCjftSLo39cdS0HVUutoiuMgCdrGU/y6qYdU2Lw4NWYF2DpXgs2nwPYkhc31RmZlqGqmFa4QEyXLQaN5FwbbUxS2Hu6eFWDDRmKfhqZfXBo2pL8JKYYzexgf99DbFbS0GqlYYJQs2KP0GQkmW4eZTmdsR0X2RXEmDYaxukXZm6ishFx5Rd5uw1W7AnO3If6fyxlbo9DgbkoDHxfjbluJCrBA0ULNxSRrME9zrO108DAh67Fjbg91a5TpVpUOmGP1iBiZM3VgBzBLvujMNuGNLOy5arQVbXOr6mzDl4SW6U2B3hfpZ/wYHOE+LmKPBPY2I/DK7H1XTimqoJtGS++EgtlkMU9DrqyXSNO8XQEtsY6HyNfqv/UjBH4/KIxgkpSLxWfxugHyCH3imnIE/AQnncavdDKzUSjhtnFVPn2jn8sFdHaxXlaToixcHMvQxMQnddYOwctigGGlENQnPmkwgTWeYNYzHYhaVtM2nrasjZP2vChZm9xtJzePeIcy6247uTDqHxpYNR9/MTk0u3Oyb3h2R/J3J+/rDVXWX33y/kxsfObKdQXiDl/xUvyK+Q1FdRbNK6AnmB+w9bxTMbznmYqBboCgmP9WcVFkxv+FB2Sgsd82JCNCq0TbB2WAsPxzwYdTOxZFJ2sPtoiS+/XgA3q3wfcBEJPnwDes1CI14fNxu88Ln/888AXa6FcD+nl9FEyH5Hl9MFFwtkG6hgnOlYCl5UrAywxetMsxF/mO80CMACcKNQ/bZJG8mpUEDBadAkaxOpnwaENnMW6xGpoJolwtzqw1TF6Gsa5RpPfKuSBWDZNOFRttCBYV247JjXPwPL5MdMD60HkgsD6oZVeYCOLOsZzMG5gIgubz8qkgIqYBl00G4QdPnWqZ86TMN2yb88T/+eY8iW9qzpOwcJZbadCToNDpbqCTH/y1Q8spheok1lAnoTwtVBZPt+gQ1KVRtt5diuLAZo4gEJTeIO4NUPictT+H3le2rf85lL/03PUvnH1FE6D3KkugteBQ7zxB45ABZQy9bFIrFeLCUs1s8wgsq6da/srYaAww6jDA2MFubdZBu1o6RGNaMuThwGpMU0HvxNojgY6ro3cG5Jw+HL8EigA1pq4z0lKu4C21lsbiFmidgFWondrwri7yVP2jZG/9MWDz2a53bTi1746rN98UCt20+eqnSd9X1kzeRGv4bpxcS/7xPx5emP/R/NaG3hIeBL0V5lJclvsI83CkUAEtX6qwsO0xpcfejVqPnd70oEfL7uMJSEfNtMWji96pc0nqyeNcL9qDbWD37+xCCygkYCuWKBsCFWxOrZqd9CYINpEWW4G9jPs+FqdfqnFuTwBNKanHIXWhW1AlEUMzRIh3eCLLvfIUGwrG/CKtEiS67WTf+lzI5Dm0CTzzt2kvmds93rXxuoXDvom7TpZ23b9z5/1kmEzw6KSDcRHM9HmLO1TvfKF8N9n0sStObtl84iMsfsRyyYP0/ho+bm97NhmLWDsLNQvjfBerrTPRm+nSOsDGlH6cmYTV+l62CQIXnnnML8+Eq0noE6158LZs9On2Gk3a90iM1GdP0/tFCoVG66OeutGCBW/B2XLjLzQqRKY4lIJW6qzTc/WRCtjVXm4Hhy0X2IPqUrrYWK8ui3jiGBYzYGlp9uqaseFA6KDxJezV5by0sUvWYX+6oOYmxJVrkFYosTvXlWvr++Zaurr/pPf5An3fe07/uLZx26Yw725+X0i8/vcFrfL9HPkK92l6L8g1yp2YO3J4K02XcvtQ7vSy+2iiULHSskU9nRPUwfocBVHSsMIdvOOpPq92BSZzma7uzm6BmHh3EG9qxXf0b/GH7aVOEuqP9LJ7eZLnOQlgoPfyxDtT17R/2r08nefcy7Mz2XIvT/LTtpt5/h+8jyjeA/srZCOle4I7olDeXcBekxi9Ezayri+vWOfKtSWNensC9H4ctCSbCnArvcEG3sGvQuuqZDetLtVTYW5xhNWGALo0hcbSlM95ZwgXK8lrtQKFu+tRtnj4OhiF1+2Ll2hbSR7XkWyh6xjDCb64kjiXgC0mFUXxdpoiNrAjwe1BIwypm2ilrhxGxeSKqXSWreHKSqtcvvCy3wwYaIyM+7KJdiaItHME3vftXWQL5QeKg5bNgFKYgpYb/Vlw8L4+Dm3s047DgQugADy9nruDRMm+1v5nE+t/NrX1P5tY/7PpnP7n9VO7pqZ2fR0fJkGSjJ19lb8eaGIEjzKEliG1SvSBQqFmpXSReU8+T99tNFmHW24trw5vsbNXdtYx5WOd1xHlRsmNhiHV20023xuL0lbsl6IebyyOz/SueOp95T1efIVPyl3xmBycJEbaW4xz7XWtnfV69f7tjSkgL7PZH83fxNTfSHy+pmn8jM7SZe3VrF053GxRxvtZgt/9Uf4zXC9WkCfVO3aa1bu1cCRptqZxChvO2Arma3odfcNTkPUYE8jTER0aar5VNT51uoiky0sau9SLbax460ZXvhqiPa+hoBH70ehojl6NcnsxDo2cRBcwnqhXUgh0rkiyWE6UCuzmntQmwVH4OpcXHqkVrhgvkTTPp0vhJ29k3UDb3x0gufrXBIGM1r/rv207u+fXTU+Gfl0MRsPFq+/AXqB9m4verLu4ZT/e/+uOa5gdK5K/JZ+i9+5wcTcqdywwWoBjOJarFBo3icZ7vhpsYj6fp8EQ3Wml43/lu3oofQtKjyGGLDDMzm5vTWONHS4spLewcr4Sa7P1lnAMIxzoEym3+PBE8Jb01FQ6OGeY49/l9z///PM/evTRHz0F/5TZIfDwr+RfgfNTLbNZ1fkMAr07gvKk6NRBMSbiT+oBtGNxjvmX6BzzCEj3T7FeMClaaIwzl3wYiA5TKU/PLXfECs3h5l1vZLg5DmKL4v1dcQB11GtLY8MuDqBGheDF2zTrsK8ggfwQpurA7MKbfnkwPSj5RNmLFrDOcYGh6ENtI7PtWzZOZQNOZycdkf5aY4A2G5YuVizqsPTH2gdq85QeMqWHj7tBoYaH9Xeff8K7/40SARfdp8QmPCrezbHv3guNfSfn4EV05yJU36/222gQF/5fKC5prsRVuJeUTr/eoQJbXylYoEscy0s5XOVic5UXO7zd5S4vxbEqelKU5UfeKJ59oGQ683IvfK0rX+3tw896U/C1PioN+jxGWlUyBGSoIE8MZYAn8ownsFKir8ETmV44CoIekvNDeCvIosodi8ZIP94jUsqJVUNmsMIYJHxe8hXeENu0Ttb/Vhux/7CMiVom7l+Yp+ge47+jrEOO+4K6Cv2wChmVr5pLwfJIQP5CoZ36A39m6mNWKQfMONhG8H6V4IwtZWOElZMZwpU3SVvyOhQl+tclpcLN/y/8zhRhAAB42mNgZGBgYGI46m+dtDye3+YrgzzzC6AIw7nzRe4w+v/c/5Ys0szlQC4HUC0QAAB68A0oeNpjYGRgYO7+d4eBgSXw/9z/x1mkGYAiKOAVAKAJByt42m2Tz2sTQRTHv+9NVFpLulX8AaGpbSVJQzQJmwZXQquCoI2uFH/hzYN4UXpQRPQmiAfxpHj05h9g9dCDXhSxerAgeigEhRbsQcWAFewlrt8ZtzWVLnzyJvvmvZn5fmflIvrBR47CPaL8WUBNTqOqIbbqOPLaQJ/ewE5Mo4olFEiPnMCALKKXcwMpIO1qcoCegy/HsUWPYFh3oVd3Ywf7HNBj8NWwz0FUOC7b+a6WPVaYwSbTjUG9iw69glAfsuYZY0Ay5A3/v0aIJkJpYKOeYfyN0Awx95K0mK/H8SzjGDK6l+vbHuxpLiOpd9Cll9j/MEpYRM7umbFHHmGzVqIW5nmGbpR0FHVposhYVB9FScHTEY5zqGMOI5iLHqi6cd3wnWZJjfmaiwUZY/079EsGnTYnX2D0E7pkgXAss6hIAuvwnmdIcP1fSK1ob9ddz/2cQsru1c35QL296IfpZO/rGJIppGWJmlF7+Y5BuUDvBrDN6XgTZZJ3Zxnm2s+Rcnq/Zf+vSMp9npv1RpE0WTKBvNymN1b3NTBPsMF5EcRexKAZzdCLUcafZF5nedZlH/6D+9rnxtaLdqwX1rOT1M3qvgbmGkpOE3819GCa+u9h/EYaTv9/PqxCIt7F5Xwbzpfa35gYh29ecA73JB3UMyBPAXO1LWap4UdyL2aCTJIyc9aLGH43abPffRdFe8/dXb+FKgkc53FIH9OTSdczbbF9dQp98or34TPft+BZzHZ48P4A/getbwAAeNpjYGDQgsMyhg2MLIzTmLSYdjDdYfrDLMccxTyD+QrzJxY5FjOWLpZ1LD9Yk1hXsHGwVbHNY5dh72M/wSHDocfhx5HAcYpzGucxLg2uNK4FXLe4+bgLuFdwH+P+wqPG48PTxXOEl4fXh3cF7w++Lr5dfF/4Jfhb+LfwPxIQELARCBFoE1gksEvglqCL4AzBS0JqQk1Cl4SdhFuEj4mIiLiJpIicEOUS9RNdIvpDTENshziXuJ94kfgl8T8SRhIJEtskzkmqSFYA4SEpDakT0jbSM6R3yZTJbJK1kV0je0T2jRyX3Aq5A/Jc8mHys+S/KYgoZCksUzinKKJoolilOEWJTalGWUt5hvIFFTYVB5UdqgqqE1QfqaWprVF7p26ivkD9mPo7DRmNNI0DmjaaPZp3tAy0tmnraLtp79L+o2On06LzQVdNN0dPRm+CPpt+g4GSwQHDFCMhowlG34yjjA+YeJkUmMwwOWYqZNpgxmQWYDbP7I15nvkzCzWLKRZPLE0se6xYrJysZlizWDfZiNkU2cyweYEDfrFlsOWxVbG1sa2z3WP7wy7J7oi9mr2f/QogPGT/yP6RQ4bDMYdnjnmOV5xmOFsBAOTolU0AAAAAAQAAAOsAQQAFAAAAAAACAAEAAgAWAAABAADmAAAAAHjarZLPSsNAEMa/pFUpatGDIr0YTypo0j8q2Jv452YpVSwIHtKaxmLTSJPGeuojePDgc4gvoW/ll8mmFMSezJDd3+x8Ozs7CYA1TYeG+Jkek7WEM0IJZ7E54XnOBqNaNkevjy3FGlWvinVG3hRnpjhLS3kOBbwrnueOD8ULuMWn4hwK2rLiRRxp24qXyHeK84i0NOcKNvSc4lXk9bS2L6zrluJvFPXzcX3gj7qebdT8yDYartFw3GHPHhhNp9Xx++EYp/DxhBcM0IWLB4S89A7a2OV8CZvrj6QrRj0q+whk3ONaGUXaIUzyCXo0YypLIJ7D2eEccbyn0sRY3htZDaiOs8W5TMlWYazOiI+RnGgzVqMXCXUla0whNTYzOqJJavTRmVmzOSMWVxyyD1VYtGcxc5I7+JWpzdn7510B9vmGGPJecV9SvYUL2R+yaptdjntqiT6g16XKkTMcRl3pedwVR3aYcppH3V9dbVDp8syeVN2k12Ifk/MMlOS7XDPLkN4Zo21ZLXMs4ph3KNKr4oBfLvkjSqj8ABsYggF42m3QR2wTURDG8f8kjp04vfdC7+Bd2yl0O8nSe+8EktiGkAQHA6EFBKGDQEjcQLQLIHoVCDgAojdRBBw408UBuIKTfdyYy0/znubTaIigvf60ksb/6gtIhESKhUgsRGHFRjQx2IkljngSSCSJZFJIDSekk0EmWWSTQy555FNAIUV0oCOd6EwXutKN7vSgJ73oTR/60g8HGjpOXLgppoRSyujPAAYyiMEMYSgevJRTQSUGwxjOCEYyitGMYSzjGM8EJjKJyUxhKtOYzgxmMovZzGEu85hPlURxlE20coP9fGQzu9nBAY5zTKxs5z0b2Sc2iWaXxLCV23wQOwc5wS9+8psjnOIB9zjNAhayh2oeUcN9HvKMxzzhKZ+o5SXPecEZfPxgL294xWv84Qt+YxuLCLCYJdRRzyEaWEojQZoIsYzlrOAzK1lFM6tZyxqucpgW1rGeDXzlO9c4yzmu85Z3EitxEi8JkihJkiwpkippki4ZkilZnOcCl7nCHS5yibts4aRkc5NbkiO57JQ8yZcCKZQiq6+uudGvmei2UH3A4XBUmHocStV71b/XqXQry9rUw4NKTakrnUqX0q0sVpYoS5X/8jymmsrVNHttwBcK1lRXNfnNJ90wdRuWylCwob1xG+VtGl5zj7C60ql0/QV2FaEtAHja28H4v3UDYy+D9waOgIiNjIx9kRvd2LQjFDcIRHpvEAkCMhoiZTewacdEMGxgVnDdwKztsoFdwXUTczGTNpjDBuSwG0A5rEAOmxKUwwLksAZBOIwbOKCaOYGiHPpM2huZ3cqAXC4F110MHPX/GeAi3EAFXDPgXB4gl9sTxo3cIKINAPUfNB0AAVKpwccAAA=='; - const ddgFontBold = 'data:application/octet-stream;base64,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'; - var localesJSON = `{"bg":{"facebook.json":{"informationalModalMessageTitle":"При влизане разрешавате на Facebook да Ви проследява","informationalModalMessageBody":"След като влезете, DuckDuckGo не може да блокира проследяването от Facebook в съдържанието на този сайт.","informationalModalConfirmButtonText":"Вход","informationalModalRejectButtonText":"Назад","loginButtonText":"Вход във Facebook","loginBodyText":"Facebook проследява Вашата активност в съответния сайт, когато го използвате за вход.","buttonTextUnblockContent":"Разблокиране на съдържанието","buttonTextUnblockComment":"Разблокиране на коментара","buttonTextUnblockComments":"Разблокиране на коментарите","buttonTextUnblockPost":"Разблокиране на публикацията","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockContent":"DuckDuckGo блокира това съдържание, за да предотврати проследяване от Facebook","infoTitleUnblockComment":"DuckDuckGo блокира този коментар, за да предотврати проследяване от Facebook","infoTitleUnblockComments":"DuckDuckGo блокира тези коментари, за да предотврати проследяване от Facebook","infoTitleUnblockPost":"DuckDuckGo блокира тази публикация, за да предотврати проследяване от Facebook","infoTitleUnblockVideo":"DuckDuckGo блокира това видео, за да предотврати проследяване от Facebook","infoTextUnblockContent":"Блокирахме проследяването от Facebook при зареждане на страницата. Ако разблокирате това съдържание, Facebook ще следи Вашата активност."},"shared.json":{"learnMore":"Научете повече","readAbout":"Прочетете за тази защита на поверителността"},"youtube.json":{"informationalModalMessageTitle":"Активиране на всички прегледи в YouTube?","informationalModalMessageBody":"Показването на преглед позволява на Google (собственик на YouTube) да види част от информацията за Вашето устройство, но все пак осигурява повече поверителност отколкото при възпроизвеждане на видеоклипа.","informationalModalConfirmButtonText":"Активиране на всички прегледи","informationalModalRejectButtonText":"Не, благодаря","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockVideo":"DuckDuckGo блокира този видеоклип в YouTube, за да предотврати проследяване от Google","infoTextUnblockVideo":"Блокирахме проследяването от Google (собственик на YouTube) при зареждане на страницата. Ако разблокирате този видеоклип, Google ще следи Вашата активност.","infoPreviewToggleText":"Прегледите са деактивирани за осигуряване на допълнителна поверителност","infoPreviewToggleEnabledText":"Прегледите са активирани","infoPreviewInfoText":"Научете повече за вградената защита от социални медии на DuckDuckGo"}},"cs":{"facebook.json":{"informationalModalMessageTitle":"Když se přihlásíš přes Facebook, bude tě moct sledovat","informationalModalMessageBody":"Po přihlášení už DuckDuckGo nemůže bránit Facebooku, aby tě na téhle stránce sledoval.","informationalModalConfirmButtonText":"Přihlásit se","informationalModalRejectButtonText":"Zpět","loginButtonText":"Přihlásit se pomocí Facebooku","loginBodyText":"Facebook sleduje tvou aktivitu na webu, když se přihlásíš jeho prostřednictvím.","buttonTextUnblockContent":"Odblokovat obsah","buttonTextUnblockComment":"Odblokovat komentář","buttonTextUnblockComments":"Odblokovat komentáře","buttonTextUnblockPost":"Odblokovat příspěvek","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockContent":"DuckDuckGo zablokoval tenhle obsah, aby Facebooku zabránil tě sledovat","infoTitleUnblockComment":"Služba DuckDuckGo zablokovala tento komentář, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockComments":"Služba DuckDuckGo zablokovala tyto komentáře, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockPost":"DuckDuckGo zablokoval tenhle příspěvek, aby Facebooku zabránil tě sledovat","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video, aby Facebooku zabránil tě sledovat","infoTextUnblockContent":"Při načítání stránky jsme Facebooku zabránili, aby tě sledoval. Když tenhle obsah odblokuješ, Facebook bude mít přístup ke tvé aktivitě."},"shared.json":{"learnMore":"Více informací","readAbout":"Přečti si o téhle ochraně soukromí"},"youtube.json":{"informationalModalMessageTitle":"Zapnout všechny náhledy YouTube?","informationalModalMessageBody":"Zobrazování náhledů umožní společnosti Google (která vlastní YouTube) zobrazit některé informace o tvém zařízení, ale pořád jde o diskrétnější volbu, než je přehrávání videa.","informationalModalConfirmButtonText":"Zapnout všechny náhledy","informationalModalRejectButtonText":"Ne, děkuji","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video z YouTube, aby Googlu zabránil tě sledovat","infoTextUnblockVideo":"Zabránili jsme společnosti Google (která vlastní YouTube), aby tě při načítání stránky sledovala. Pokud toto video odblokuješ, Google získá přístup ke tvé aktivitě.","infoPreviewToggleText":"Náhledy jsou pro větší soukromí vypnuté","infoPreviewToggleEnabledText":"Náhledy jsou zapnuté","infoPreviewInfoText":"Další informace o ochraně DuckDuckGo před sledováním prostřednictvím vloženého obsahu ze sociálních médií"}},"da":{"facebook.json":{"informationalModalMessageTitle":"Når du logger ind med Facebook, kan de spore dig","informationalModalMessageBody":"Når du er logget ind, kan DuckDuckGo ikke blokere for, at indhold fra Facebook sporer dig på dette websted.","informationalModalConfirmButtonText":"Log på","informationalModalRejectButtonText":"Gå tilbage","loginButtonText":"Log ind med Facebook","loginBodyText":"Facebook sporer din aktivitet på et websted, når du bruger dem til at logge ind.","buttonTextUnblockContent":"Fjern blokering af indhold","buttonTextUnblockComment":"Fjern blokering af kommentar","buttonTextUnblockComments":"Fjern blokering af kommentarer","buttonTextUnblockPost":"Fjern blokering af indlæg","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockContent":"DuckDuckGo har blokeret dette indhold for at forhindre Facebook i at spore dig","infoTitleUnblockComment":"DuckDuckGo har blokeret denne kommentar for at forhindre Facebook i at spore dig","infoTitleUnblockComments":"DuckDuckGo har blokeret disse kommentarer for at forhindre Facebook i at spore dig","infoTitleUnblockPost":"DuckDuckGo blokerede dette indlæg for at forhindre Facebook i at spore dig","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne video for at forhindre Facebook i at spore dig","infoTextUnblockContent":"Vi blokerede for, at Facebook sporede dig, da siden blev indlæst. Hvis du ophæver blokeringen af dette indhold, vil Facebook kende din aktivitet."},"shared.json":{"learnMore":"Mere info","readAbout":"Læs om denne beskyttelse af privatlivet"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Med forhåndsvisninger kan Google (som ejer YouTube) se nogle af enhedens oplysninger, men det er stadig mere privat end at afspille videoen.","informationalModalConfirmButtonText":"Aktivér alle forhåndsvisninger","informationalModalRejectButtonText":"Nej tak.","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne YouTube-video for at forhindre Google i at spore dig","infoTextUnblockVideo":"Vi blokerede Google (som ejer YouTube) fra at spore dig, da siden blev indlæst. Hvis du fjerner blokeringen af denne video, vil Google få kendskab til din aktivitet.","infoPreviewToggleText":"Forhåndsvisninger er deaktiveret for at give yderligere privatliv","infoPreviewToggleEnabledText":"Forhåndsvisninger er deaktiveret","infoPreviewInfoText":"Få mere at vide på om DuckDuckGos indbyggede beskyttelse på sociale medier"}},"de":{"facebook.json":{"informationalModalMessageTitle":"Wenn du dich bei Facebook anmeldest, kann Facebook dich tracken","informationalModalMessageBody":"Sobald du angemeldet bist, kann DuckDuckGo nicht mehr verhindern, dass Facebook-Inhalte dich auf dieser Website tracken.","informationalModalConfirmButtonText":"Anmelden","informationalModalRejectButtonText":"Zurück","loginButtonText":"Mit Facebook anmelden","loginBodyText":"Facebook trackt deine Aktivität auf einer Website, wenn du dich über Facebook dort anmeldest.","buttonTextUnblockContent":"Blockierung aufheben","buttonTextUnblockComment":"Blockierung aufheben","buttonTextUnblockComments":"Blockierung aufheben","buttonTextUnblockPost":"Blockierung aufheben","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockContent":"DuckDuckGo hat diesen Inhalt blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComment":"DuckDuckGo hat diesen Kommentar blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComments":"DuckDuckGo hat diese Kommentare blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockPost":"DuckDuckGo hat diesen Beitrag blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockVideo":"DuckDuckGo hat dieses Video blockiert, um zu verhindern, dass Facebook dich trackt","infoTextUnblockContent":"Wir haben Facebook daran gehindert, dich zu tracken, als die Seite geladen wurde. Wenn du die Blockierung für diesen Inhalt aufhebst, kennt Facebook deine Aktivitäten."},"shared.json":{"learnMore":"Mehr erfahren","readAbout":"Weitere Informationen über diesen Datenschutz"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-Vorschauen aktivieren?","informationalModalMessageBody":"Durch das Anzeigen von Vorschauen kann Google (dem YouTube gehört) einige Informationen zu deinem Gerät sehen. Dies ist aber immer noch privater als das Abspielen des Videos.","informationalModalConfirmButtonText":"Alle Vorschauen aktivieren","informationalModalRejectButtonText":"Nein, danke","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockVideo":"DuckDuckGo hat dieses YouTube-Video blockiert, um zu verhindern, dass Google dich trackt.","infoTextUnblockVideo":"Wir haben Google (dem YouTube gehört) daran gehindert, dich beim Laden der Seite zu tracken. Wenn du die Blockierung für dieses Video aufhebst, kennt Google deine Aktivitäten.","infoPreviewToggleText":"Vorschau für mehr Privatsphäre deaktiviert","infoPreviewToggleEnabledText":"Vorschau aktiviert","infoPreviewInfoText":"Erfahre mehr über den DuckDuckGo-Schutz vor eingebetteten Social Media-Inhalten"}},"el":{"facebook.json":{"informationalModalMessageTitle":"Η σύνδεση μέσω Facebook τους επιτρέπει να σας παρακολουθούν","informationalModalMessageBody":"Μόλις συνδεθείτε, το DuckDuckGo δεν μπορεί να εμποδίσει το περιεχόμενο του Facebook από το να σας παρακολουθεί σε αυτόν τον ιστότοπο.","informationalModalConfirmButtonText":"Σύνδεση","informationalModalRejectButtonText":"Επιστροφή","loginButtonText":"Σύνδεση μέσω Facebook","loginBodyText":"Το Facebook παρακολουθεί τη δραστηριότητά σας σε έναν ιστότοπο όταν τον χρησιμοποιείτε για να συνδεθείτε.","buttonTextUnblockContent":"Άρση αποκλεισμού περιεχομένου","buttonTextUnblockComment":"Άρση αποκλεισμού σχολίου","buttonTextUnblockComments":"Άρση αποκλεισμού σχολίων","buttonTextUnblockPost":"Άρση αποκλεισμού ανάρτησης","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockContent":"Το DuckDuckGo απέκλεισε το περιεχόμενο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComment":"Το DuckDuckGo απέκλεισε το σχόλιο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComments":"Το DuckDuckGo απέκλεισε τα σχόλια αυτά για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockPost":"Το DuckDuckGo απέκλεισε την ανάρτηση αυτή για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTextUnblockContent":"Αποκλείσαμε το Facebook από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το περιεχόμενο, το Facebook θα γνωρίζει τη δραστηριότητά σας."},"shared.json":{"learnMore":"Μάθετε περισσότερα","readAbout":"Διαβάστε σχετικά με την παρούσα προστασίας προσωπικών δεδομένων"},"youtube.json":{"informationalModalMessageTitle":"Ενεργοποίηση όλων των προεπισκοπήσεων του YouTube;","informationalModalMessageBody":"Η προβολή των προεπισκοπήσεων θα επιτρέψει στην Google (στην οποία ανήκει το YouTube) να βλέπει ορισμένες από τις πληροφορίες της συσκευής σας, ωστόσο εξακολουθεί να είναι πιο ιδιωτική από την αναπαραγωγή του βίντεο.","informationalModalConfirmButtonText":"Ενεργοποίηση όλων των προεπισκοπήσεων","informationalModalRejectButtonText":"Όχι, ευχαριστώ","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό στο YouTube για να εμποδίσει την Google από το να σας παρακολουθεί","infoTextUnblockVideo":"Αποκλείσαμε την Google (στην οποία ανήκει το YouTube) από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το βίντεο, η Google θα γνωρίζει τη δραστηριότητά σας.","infoPreviewToggleText":"Οι προεπισκοπήσεις απενεργοποιήθηκαν για πρόσθετη προστασία των προσωπικών δεδομένων","infoPreviewToggleEnabledText":"Οι προεπισκοπήσεις ενεργοποιήθηκαν","infoPreviewInfoText":"Μάθετε περισσότερα για την ενσωματωμένη προστασία κοινωνικών μέσων DuckDuckGo"}},"en":{"facebook.json":{"informationalModalMessageTitle":"Logging in with Facebook lets them track you","informationalModalMessageBody":"Once you're logged in, DuckDuckGo can't block Facebook content from tracking you on this site.","informationalModalConfirmButtonText":"Log In","informationalModalRejectButtonText":"Go back","loginButtonText":"Log in with Facebook","loginBodyText":"Facebook tracks your activity on a site when you use them to login.","buttonTextUnblockContent":"Unblock Content","buttonTextUnblockComment":"Unblock Comment","buttonTextUnblockComments":"Unblock Comments","buttonTextUnblockPost":"Unblock Post","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockContent":"DuckDuckGo blocked this content to prevent Facebook from tracking you","infoTitleUnblockComment":"DuckDuckGo blocked this comment to prevent Facebook from tracking you","infoTitleUnblockComments":"DuckDuckGo blocked these comments to prevent Facebook from tracking you","infoTitleUnblockPost":"DuckDuckGo blocked this post to prevent Facebook from tracking you","infoTitleUnblockVideo":"DuckDuckGo blocked this video to prevent Facebook from tracking you","infoTextUnblockContent":"We blocked Facebook from tracking you when the page loaded. If you unblock this content, Facebook will know your activity."},"shared.json":{"learnMore":"Learn More","readAbout":"Read about this privacy protection"},"youtube.json":{"informationalModalMessageTitle":"Enable all YouTube previews?","informationalModalMessageBody":"Showing previews will allow Google (which owns YouTube) to see some of your device’s information, but is still more private than playing the video.","informationalModalConfirmButtonText":"Enable All Previews","informationalModalRejectButtonText":"No Thanks","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockVideo":"DuckDuckGo blocked this YouTube video to prevent Google from tracking you","infoTextUnblockVideo":"We blocked Google (which owns YouTube) from tracking you when the page loaded. If you unblock this video, Google will know your activity.","infoPreviewToggleText":"Previews disabled for additional privacy","infoPreviewToggleEnabledText":"Previews enabled","infoPreviewInfoText":"Learn more about DuckDuckGo Embedded Social Media Protection"}},"es":{"facebook.json":{"informationalModalMessageTitle":"Al iniciar sesión en Facebook, les permites que te rastreen","informationalModalMessageBody":"Una vez que hayas iniciado sesión, DuckDuckGo no puede bloquear el contenido de Facebook para que no te rastree en este sitio.","informationalModalConfirmButtonText":"Iniciar sesión","informationalModalRejectButtonText":"Volver atrás","loginButtonText":"Iniciar sesión con Facebook","loginBodyText":"Facebook rastrea tu actividad en un sitio web cuando lo usas para iniciar sesión.","buttonTextUnblockContent":"Desbloquear contenido","buttonTextUnblockComment":"Desbloquear comentario","buttonTextUnblockComments":"Desbloquear comentarios","buttonTextUnblockPost":"Desbloquear publicación","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockContent":"DuckDuckGo ha bloqueado este contenido para evitar que Facebook te rastree","infoTitleUnblockComment":"DuckDuckGo ha bloqueado este comentario para evitar que Facebook te rastree","infoTitleUnblockComments":"DuckDuckGo ha bloqueado estos comentarios para evitar que Facebook te rastree","infoTitleUnblockPost":"DuckDuckGo ha bloqueado esta publicación para evitar que Facebook te rastree","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo para evitar que Facebook te rastree","infoTextUnblockContent":"Hemos bloqueado el rastreo de Facebook cuando se ha cargado la página. Si desbloqueas este contenido, Facebook tendrá conocimiento de tu actividad."},"shared.json":{"learnMore":"Más información","readAbout":"Lee acerca de esta protección de privacidad"},"youtube.json":{"informationalModalMessageTitle":"¿Habilitar todas las vistas previas de YouTube?","informationalModalMessageBody":"Mostrar vistas previas permitirá a Google (que es el propietario de YouTube) ver parte de la información de tu dispositivo, pero sigue siendo más privado que reproducir el vídeo.","informationalModalConfirmButtonText":"Habilitar todas las vistas previas","informationalModalRejectButtonText":"No, gracias","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo de YouTube para evitar que Google te rastree","infoTextUnblockVideo":"Hemos bloqueado el rastreo de Google (que es el propietario de YouTube) al cargarse la página. Si desbloqueas este vídeo, Goggle tendrá conocimiento de tu actividad.","infoPreviewToggleText":"Vistas previas desactivadas para mayor privacidad","infoPreviewToggleEnabledText":"Vistas previas activadas","infoPreviewInfoText":"Más información sobre la protección integrada de redes sociales DuckDuckGo"}},"et":{"facebook.json":{"informationalModalMessageTitle":"Kui logid Facebookiga sisse, saab Facebook sind jälgida","informationalModalMessageBody":"Kui oled sisse logitud, ei saa DuckDuckGo blokeerida Facebooki sisu sind jälgimast.","informationalModalConfirmButtonText":"Logi sisse","informationalModalRejectButtonText":"Mine tagasi","loginButtonText":"Logi sisse Facebookiga","loginBodyText":"Kui logid sisse Facebookiga, saab Facebook sinu tegevust saidil jälgida.","buttonTextUnblockContent":"Deblokeeri sisu","buttonTextUnblockComment":"Deblokeeri kommentaar","buttonTextUnblockComments":"Deblokeeri kommentaarid","buttonTextUnblockPost":"Deblokeeri postitus","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockContent":"DuckDuckGo blokeeris selle sisu, et Facebook ei saaks sind jälgida","infoTitleUnblockComment":"DuckDuckGo blokeeris selle kommentaari, et Facebook ei saaks sind jälgida","infoTitleUnblockComments":"DuckDuckGo blokeeris need kommentaarid, et Facebook ei saaks sind jälgida","infoTitleUnblockPost":"DuckDuckGo blokeeris selle postituse, et Facebook ei saaks sind jälgida","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle video, et Facebook ei saaks sind jälgida","infoTextUnblockContent":"Blokeerisime lehe laadimise ajal Facebooki jaoks sinu jälgimise. Kui sa selle sisu deblokeerid, saab Facebook sinu tegevust jälgida."},"shared.json":{"learnMore":"Loe edasi","readAbout":"Loe selle privaatsuskaitse kohta"},"youtube.json":{"informationalModalMessageTitle":"Kas lubada kõik YouTube’i eelvaated?","informationalModalMessageBody":"Eelvaate näitamine võimaldab Google’il (kellele YouTube kuulub) näha osa sinu seadme teabest, kuid see on siiski privaatsem kui video esitamine.","informationalModalConfirmButtonText":"Luba kõik eelvaated","informationalModalRejectButtonText":"Ei aitäh","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle YouTube’i video, et takistada Google’it sind jälgimast","infoTextUnblockVideo":"Me blokeerisime lehe laadimise ajal Google’i (kellele YouTube kuulub) jälgimise. Kui sa selle video deblokeerid, saab Google sinu tegevusest teada.","infoPreviewToggleText":"Eelvaated on täiendava privaatsuse tagamiseks keelatud","infoPreviewToggleEnabledText":"Eelvaated on lubatud","infoPreviewInfoText":"Lisateave DuckDuckGo sisseehitatud sotsiaalmeediakaitse kohta"}},"fi":{"facebook.json":{"informationalModalMessageTitle":"Kun kirjaudut sisään Facebook-tunnuksilla, Facebook voi seurata sinua","informationalModalMessageBody":"Kun olet kirjautunut sisään, DuckDuckGo ei voi estää Facebook-sisältöä seuraamasta sinua tällä sivustolla.","informationalModalConfirmButtonText":"Kirjaudu sisään","informationalModalRejectButtonText":"Edellinen","loginButtonText":"Kirjaudu sisään Facebook-tunnuksilla","loginBodyText":"Facebook seuraa toimintaasi sivustolla, kun kirjaudut sisään sen kautta.","buttonTextUnblockContent":"Poista sisällön esto","buttonTextUnblockComment":"Poista kommentin esto","buttonTextUnblockComments":"Poista kommenttien esto","buttonTextUnblockPost":"Poista julkaisun esto","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockContent":"DuckDuckGo esti tämän sisällön estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComment":"DuckDuckGo esti tämän kommentin estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComments":"DuckDuckGo esti nämä kommentit estääkseen Facebookia seuraamasta sinua","infoTitleUnblockPost":"DuckDuckGo esti tämän julkaisun estääkseen Facebookia seuraamasta sinua","infoTitleUnblockVideo":"DuckDuckGo esti tämän videon estääkseen Facebookia seuraamasta sinua","infoTextUnblockContent":"Estimme Facebookia seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän sisällön eston, Facebook saa tietää toimintasi."},"shared.json":{"learnMore":"Lue lisää","readAbout":"Lue tästä yksityisyydensuojasta"},"youtube.json":{"informationalModalMessageTitle":"Otetaanko käyttöön kaikki YouTube-esikatselut?","informationalModalMessageBody":"Kun sallit esikatselun, Google (joka omistaa YouTuben) voi nähdä joitakin laitteesi tietoja, mutta se on silti yksityisempää kuin videon toistaminen.","informationalModalConfirmButtonText":"Ota käyttöön kaikki esikatselut","informationalModalRejectButtonText":"Ei kiitos","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockVideo":"DuckDuckGo esti tämän YouTube-videon, jotta Google ei voi seurata sinua","infoTextUnblockVideo":"Estimme Googlea (joka omistaa YouTuben) seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän videon eston, Google tietää toimintasi.","infoPreviewToggleText":"Esikatselut on poistettu käytöstä yksityisyyden lisäämiseksi","infoPreviewToggleEnabledText":"Esikatselut käytössä","infoPreviewInfoText":"Lue lisää DuckDuckGon upotetusta sosiaalisen median suojauksesta"}},"fr":{"facebook.json":{"informationalModalMessageTitle":"L'identification via Facebook leur permet de vous pister","informationalModalMessageBody":"Une fois que vous êtes connecté(e), DuckDuckGo ne peut pas empêcher le contenu Facebook de vous pister sur ce site.","informationalModalConfirmButtonText":"Connexion","informationalModalRejectButtonText":"Revenir en arrière","loginButtonText":"S'identifier avec Facebook","loginBodyText":"Facebook piste votre activité sur un site lorsque vous l'utilisez pour vous identifier.","buttonTextUnblockContent":"Débloquer le contenu","buttonTextUnblockComment":"Débloquer le commentaire","buttonTextUnblockComments":"Débloquer les commentaires","buttonTextUnblockPost":"Débloquer la publication","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockContent":"DuckDuckGo a bloqué ce contenu pour empêcher Facebook de vous suivre","infoTitleUnblockComment":"DuckDuckGo a bloqué ce commentaire pour empêcher Facebook de vous suivre","infoTitleUnblockComments":"DuckDuckGo a bloqué ces commentaires pour empêcher Facebook de vous suivre","infoTitleUnblockPost":"DuckDuckGo a bloqué cette publication pour empêcher Facebook de vous pister","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo pour empêcher Facebook de vous pister","infoTextUnblockContent":"Nous avons empêché Facebook de vous pister lors du chargement de la page. Si vous débloquez ce contenu, Facebook connaîtra votre activité."},"shared.json":{"learnMore":"En savoir plus","readAbout":"En savoir plus sur cette protection de la confidentialité"},"youtube.json":{"informationalModalMessageTitle":"Activer tous les aperçus YouTube ?","informationalModalMessageBody":"L'affichage des aperçus permettra à Google (propriétaire de YouTube) de voir certaines informations de votre appareil, mais cela reste davantage confidentiel qu'en lisant la vidéo.","informationalModalConfirmButtonText":"Activer tous les aperçus","informationalModalRejectButtonText":"Non merci","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo YouTube pour empêcher Google de vous pister","infoTextUnblockVideo":"Nous avons empêché Google (propriétaire de YouTube) de vous pister lors du chargement de la page. Si vous débloquez cette vidéo, Google connaîtra votre activité.","infoPreviewToggleText":"Aperçus désactivés pour plus de confidentialité","infoPreviewToggleEnabledText":"Aperçus activés","infoPreviewInfoText":"En savoir plus sur la protection intégrée DuckDuckGo des réseaux sociaux"}},"hr":{"facebook.json":{"informationalModalMessageTitle":"Prijava putem Facebooka omogućuje im da te prate","informationalModalMessageBody":"Nakon što se prijaviš, DuckDuckGo ne može blokirati Facebookov sadržaj da te prati na Facebooku.","informationalModalConfirmButtonText":"Prijavljivanje","informationalModalRejectButtonText":"Vrati se","loginButtonText":"Prijavi se putem Facebooka","loginBodyText":"Facebook prati tvoju aktivnost na toj web lokaciji kad je koristiš za prijavu.","buttonTextUnblockContent":"Deblokiranje sadržaja","buttonTextUnblockComment":"Deblokiranje komentara","buttonTextUnblockComments":"Deblokiranje komentara","buttonTextUnblockPost":"Deblokiranje objave","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockContent":"DuckDuckGo je blokirao ovaj sadržaj kako bi spriječio Facebook da te prati","infoTitleUnblockComment":"DuckDuckGo je blokirao ovaj komentar kako bi spriječio Facebook da te prati","infoTitleUnblockComments":"DuckDuckGo je blokirao ove komentare kako bi spriječio Facebook da te prati","infoTitleUnblockPost":"DuckDuckGo je blokirao ovu objavu kako bi spriječio Facebook da te prati","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj video kako bi spriječio Facebook da te prati","infoTextUnblockContent":"Blokirali smo Facebook da te prati kad se stranica učita. Ako deblokiraš ovaj sadržaj, Facebook će znati tvoju aktivnost."},"shared.json":{"learnMore":"Saznajte više","readAbout":"Pročitaj više o ovoj zaštiti privatnosti"},"youtube.json":{"informationalModalMessageTitle":"Omogućiti sve YouTube pretpreglede?","informationalModalMessageBody":"Prikazivanje pretpregleda omogućit će Googleu (u čijem je vlasništvu YouTube) da vidi neke podatke o tvom uređaju, ali je i dalje privatnija opcija od reprodukcije videozapisa.","informationalModalConfirmButtonText":"Omogući sve pretpreglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj YouTube videozapis kako bi spriječio Google da te prati","infoTextUnblockVideo":"Blokirali smo Google (u čijem je vlasništvu YouTube) da te prati kad se stranica učita. Ako deblokiraš ovaj videozapis, Google će znati tvoju aktivnost.","infoPreviewToggleText":"Pretpregledi su onemogućeni radi dodatne privatnosti","infoPreviewToggleEnabledText":"Pretpregledi su omogućeni","infoPreviewInfoText":"Saznaj više o uključenoj DuckDuckGo zaštiti od društvenih medija"}},"hu":{"facebook.json":{"informationalModalMessageTitle":"A Facebookkal való bejelentkezéskor a Facebook nyomon követhet","informationalModalMessageBody":"Miután bejelentkezel, a DuckDuckGo nem fogja tudni blokkolni a Facebook-tartalmat, amely nyomon követ ezen az oldalon.","informationalModalConfirmButtonText":"Bejelentkezés","informationalModalRejectButtonText":"Visszalépés","loginButtonText":"Bejelentkezés Facebookkal","loginBodyText":"Ha a Facebookkal jelentkezel be, nyomon követik a webhelyen végzett tevékenységedet.","buttonTextUnblockContent":"Tartalom feloldása","buttonTextUnblockComment":"Hozzászólás feloldása","buttonTextUnblockComments":"Hozzászólások feloldása","buttonTextUnblockPost":"Bejegyzés feloldása","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockContent":"A DuckDuckGo blokkolta ezt a tartalmat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComment":"A DuckDuckGo blokkolta ezt a hozzászólást, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComments":"A DuckDuckGo blokkolta ezeket a hozzászólásokat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockPost":"A DuckDuckGo blokkolta ezt a bejegyzést, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockVideo":"A DuckDuckGo blokkolta ezt a videót, hogy megakadályozza a Facebookot a nyomon követésedben","infoTextUnblockContent":"Az oldal betöltésekor blokkoltuk a Facebookot a nyomon követésedben. Ha feloldod ezt a tartalmat, a Facebook tudni fogja, hogy milyen tevékenységet végzel."},"shared.json":{"learnMore":"További részletek","readAbout":"Tudj meg többet erről az adatvédelemről"},"youtube.json":{"informationalModalMessageTitle":"Engedélyezed minden YouTube-videó előnézetét?","informationalModalMessageBody":"Az előnézetek megjelenítésével a Google (a YouTube tulajdonosa) láthatja a készülék néhány adatát, de ez adatvédelmi szempontból még mindig előnyösebb, mint a videó lejátszása.","informationalModalConfirmButtonText":"Minden előnézet engedélyezése","informationalModalRejectButtonText":"Nem, köszönöm","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockVideo":"A DuckDuckGo blokkolta a YouTube-videót, hogy a Google ne követhessen nyomon","infoTextUnblockVideo":"Blokkoltuk, hogy a Google (a YouTube tulajdonosa) nyomon követhessen az oldal betöltésekor. Ha feloldod a videó blokkolását, a Google tudni fogja, hogy milyen tevékenységet végzel.","infoPreviewToggleText":"Az előnézetek a fokozott adatvédelem érdekében letiltva","infoPreviewToggleEnabledText":"Az előnézetek engedélyezve","infoPreviewInfoText":"További tudnivalók a DuckDuckGo beágyazott közösségi média elleni védelméről"}},"it":{"facebook.json":{"informationalModalMessageTitle":"L'accesso con Facebook consente di tracciarti","informationalModalMessageBody":"Dopo aver effettuato l'accesso, DuckDuckGo non può bloccare il tracciamento dei contenuti di Facebook su questo sito.","informationalModalConfirmButtonText":"Accedi","informationalModalRejectButtonText":"Torna indietro","loginButtonText":"Accedi con Facebook","loginBodyText":"Facebook tiene traccia della tua attività su un sito quando lo usi per accedere.","buttonTextUnblockContent":"Sblocca contenuti","buttonTextUnblockComment":"Sblocca commento","buttonTextUnblockComments":"Sblocca commenti","buttonTextUnblockPost":"Sblocca post","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockContent":"DuckDuckGo ha bloccato questo contenuto per impedire a Facebook di tracciarti","infoTitleUnblockComment":"DuckDuckGo ha bloccato questo commento per impedire a Facebook di tracciarti","infoTitleUnblockComments":"DuckDuckGo ha bloccato questi commenti per impedire a Facebook di tracciarti","infoTitleUnblockPost":"DuckDuckGo ha bloccato questo post per impedire a Facebook di tracciarti","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video per impedire a Facebook di tracciarti","infoTextUnblockContent":"Abbiamo impedito a Facebook di tracciarti al caricamento della pagina. Se sblocchi questo contenuto, Facebook conoscerà la tua attività."},"shared.json":{"learnMore":"Ulteriori informazioni","readAbout":"Leggi di più su questa protezione della privacy"},"youtube.json":{"informationalModalMessageTitle":"Abilitare tutte le anteprime di YouTube?","informationalModalMessageBody":"La visualizzazione delle anteprime consentirà a Google (che possiede YouTube) di vedere alcune delle informazioni del tuo dispositivo, ma è comunque più privato rispetto alla riproduzione del video.","informationalModalConfirmButtonText":"Abilita tutte le anteprime","informationalModalRejectButtonText":"No, grazie","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video di YouTube per impedire a Google di tracciarti","infoTextUnblockVideo":"Abbiamo impedito a Google (che possiede YouTube) di tracciarti quando la pagina è stata caricata. Se sblocchi questo video, Google conoscerà la tua attività.","infoPreviewToggleText":"Anteprime disabilitate per una maggiore privacy","infoPreviewToggleEnabledText":"Anteprime abilitate","infoPreviewInfoText":"Scopri di più sulla protezione dai social media integrata di DuckDuckGo"}},"lt":{"facebook.json":{"informationalModalMessageTitle":"Prisijungę prie „Facebook“ galite būti sekami","informationalModalMessageBody":"Kai esate prisijungę, „DuckDuckGo“ negali užblokuoti „Facebook“ turinio, todėl esate sekami šioje svetainėje.","informationalModalConfirmButtonText":"Prisijungti","informationalModalRejectButtonText":"Grįžti atgal","loginButtonText":"Prisijunkite su „Facebook“","loginBodyText":"„Facebook“ seka jūsų veiklą svetainėje, kai prisijungiate su šia svetaine.","buttonTextUnblockContent":"Atblokuoti turinį","buttonTextUnblockComment":"Atblokuoti komentarą","buttonTextUnblockComments":"Atblokuoti komentarus","buttonTextUnblockPost":"Atblokuoti įrašą","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockContent":"„DuckDuckGo“ užblokavo šį turinį, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComment":"„DuckDuckGo“ užblokavo šį komentarą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComments":"„DuckDuckGo“ užblokavo šiuos komentarus, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockPost":"„DuckDuckGo“ užblokavo šį įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį vaizdo įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTextUnblockContent":"Užblokavome „Facebook“, kad negalėtų jūsų sekti, kai puslapis buvo įkeltas. Jei atblokuosite šį turinį, „Facebook“ žinos apie jūsų veiklą."},"shared.json":{"learnMore":"Sužinoti daugiau","readAbout":"Skaitykite apie šią privatumo apsaugą"},"youtube.json":{"informationalModalMessageTitle":"Įjungti visas „YouTube“ peržiūras?","informationalModalMessageBody":"Peržiūrų rodymas leis „Google“ (kuriai priklauso „YouTube“) matyti tam tikrą jūsų įrenginio informaciją, tačiau ji vis tiek bus privatesnė nei leidžiant vaizdo įrašą.","informationalModalConfirmButtonText":"Įjungti visas peržiūras","informationalModalRejectButtonText":"Ne, dėkoju","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį „YouTube“ vaizdo įrašą, kad „Google“ negalėtų jūsų sekti","infoTextUnblockVideo":"Užblokavome „Google“ (kuriai priklauso „YouTube“) galimybę sekti jus, kai puslapis buvo įkeltas. Jei atblokuosite šį vaizdo įrašą, „Google“ sužinos apie jūsų veiklą.","infoPreviewToggleText":"Peržiūros išjungtos dėl papildomo privatumo","infoPreviewToggleEnabledText":"Peržiūros įjungtos","infoPreviewInfoText":"Sužinokite daugiau apie „DuckDuckGo“ įdėtąją socialinės žiniasklaidos apsaugą"}},"lv":{"facebook.json":{"informationalModalMessageTitle":"Ja pieteiksies ar Facebook, viņi varēs tevi izsekot","informationalModalMessageBody":"Kad tu piesakies, DuckDuckGo nevar novērst, ka Facebook saturs tevi izseko šajā vietnē.","informationalModalConfirmButtonText":"Pieteikties","informationalModalRejectButtonText":"Atgriezties","loginButtonText":"Pieteikties ar Facebook","loginBodyText":"Facebook izseko tavas aktivitātes vietnē, kad esi pieteicies ar Facebook.","buttonTextUnblockContent":"Atbloķēt saturu","buttonTextUnblockComment":"Atbloķēt komentāru","buttonTextUnblockComments":"Atbloķēt komentārus","buttonTextUnblockPost":"Atbloķēt ziņu","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockContent":"DuckDuckGo bloķēja šo saturu, lai neļautu Facebook tevi izsekot","infoTitleUnblockComment":"DuckDuckGo bloķēja šo komentāru, lai neļautu Facebook tevi izsekot","infoTitleUnblockComments":"DuckDuckGo bloķēja šos komentārus, lai neļautu Facebook tevi izsekot","infoTitleUnblockPost":"DuckDuckGo bloķēja šo ziņu, lai neļautu Facebook tevi izsekot","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo videoklipu, lai neļautu Facebook tevi izsekot","infoTextUnblockContent":"Mēs bloķējām Facebook iespēju tevi izsekot, ielādējot lapu. Ja atbloķēsi šo saturu, Facebook redzēs, ko tu dari."},"shared.json":{"learnMore":"Uzzināt vairāk","readAbout":"Lasi par šo privātuma aizsardzību"},"youtube.json":{"informationalModalMessageTitle":"Vai iespējot visus YouTube priekšskatījumus?","informationalModalMessageBody":"Priekšskatījumu rādīšana ļaus Google (kam pieder YouTube) redzēt daļu tavas ierīces informācijas, taču tas tāpat ir privātāk par videoklipa atskaņošanu.","informationalModalConfirmButtonText":"Iespējot visus priekšskatījumus","informationalModalRejectButtonText":"Nē, paldies","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo YouTube videoklipu, lai neļautu Google tevi izsekot","infoTextUnblockVideo":"Mēs neļāvām Google (kam pieder YouTube) tevi izsekot, kad lapa tika ielādēta. Ja atbloķēsi šo videoklipu, Google zinās, ko tu dari.","infoPreviewToggleText":"Priekšskatījumi ir atspējoti, lai nodrošinātu papildu konfidencialitāti","infoPreviewToggleEnabledText":"Priekšskatījumi ir iespējoti","infoPreviewInfoText":"Uzzini vairāk par DuckDuckGo iegulto sociālo mediju aizsardzību"}},"nb":{"facebook.json":{"informationalModalMessageTitle":"Når du logger på med Facebook, kan de spore deg","informationalModalMessageBody":"Når du er logget på, kan ikke DuckDuckGo hindre Facebook-innhold i å spore deg på dette nettstedet.","informationalModalConfirmButtonText":"Logg inn","informationalModalRejectButtonText":"Gå tilbake","loginButtonText":"Logg på med Facebook","loginBodyText":"Når du logger på med Facebook, sporer de aktiviteten din på nettstedet.","buttonTextUnblockContent":"Opphev blokkering av innhold","buttonTextUnblockComment":"Opphev blokkering av kommentar","buttonTextUnblockComments":"Opphev blokkering av kommentarer","buttonTextUnblockPost":"Opphev blokkering av innlegg","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockContent":"DuckDuckGo blokkerte dette innholdet for å hindre Facebook i å spore deg","infoTitleUnblockComment":"DuckDuckGo blokkerte denne kommentaren for å hindre Facebook i å spore deg","infoTitleUnblockComments":"DuckDuckGo blokkerte disse kommentarene for å hindre Facebook i å spore deg","infoTitleUnblockPost":"DuckDuckGo blokkerte dette innlegget for å hindre Facebook i å spore deg","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne videoen for å hindre Facebook i å spore deg","infoTextUnblockContent":"Vi hindret Facebook i å spore deg da siden ble lastet. Hvis du opphever blokkeringen av dette innholdet, får Facebook vite om aktiviteten din."},"shared.json":{"learnMore":"Finn ut mer","readAbout":"Les om denne personvernfunksjonen"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Forhåndsvisninger gjør det mulig for Google (som eier YouTube) å se enkelte opplysninger om enheten din, men det er likevel mer privat enn å spille av videoen.","informationalModalConfirmButtonText":"Aktiver alle forhåndsvisninger","informationalModalRejectButtonText":"Nei takk","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne YouTube-videoen for å hindre Google i å spore deg","infoTextUnblockVideo":"Vi blokkerte Google (som eier YouTube) mot å spore deg da siden ble lastet. Hvis du opphever blokkeringen av denne videoen, får Google vite om aktiviteten din.","infoPreviewToggleText":"Forhåndsvisninger er deaktivert for å gi deg ekstra personvern","infoPreviewToggleEnabledText":"Forhåndsvisninger er aktivert","infoPreviewInfoText":"Finn ut mer om DuckDuckGos innebygde beskyttelse for sosiale medier"}},"nl":{"facebook.json":{"informationalModalMessageTitle":"Als je inlogt met Facebook, kunnen zij je volgen","informationalModalMessageBody":"Als je eenmaal bent ingelogd, kan DuckDuckGo niet voorkomen dat Facebook je op deze site volgt.","informationalModalConfirmButtonText":"Inloggen","informationalModalRejectButtonText":"Terug","loginButtonText":"Inloggen met Facebook","loginBodyText":"Facebook volgt je activiteit op een site als je Facebook gebruikt om in te loggen.","buttonTextUnblockContent":"Inhoud deblokkeren","buttonTextUnblockComment":"Opmerking deblokkeren","buttonTextUnblockComments":"Opmerkingen deblokkeren","buttonTextUnblockPost":"Bericht deblokkeren","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockContent":"DuckDuckGo heeft deze inhoud geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComment":"DuckDuckGo heeft deze opmerking geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComments":"DuckDuckGo heeft deze opmerkingen geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockPost":"DuckDuckGo heeft dit bericht geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockVideo":"DuckDuckGo heeft deze video geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTextUnblockContent":"We hebben voorkomen dat Facebook je volgde toen de pagina werd geladen. Als je deze inhoud deblokkeert, kan Facebook je activiteit zien."},"shared.json":{"learnMore":"Meer informatie","readAbout":"Lees meer over deze privacybescherming"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-voorbeelden inschakelen?","informationalModalMessageBody":"Bij het tonen van voorbeelden kan Google (eigenaar van YouTube) een deel van de informatie over je apparaat zien, maar blijft je privacy beter beschermd dan als je de video zou afspelen.","informationalModalConfirmButtonText":"Alle voorbeelden inschakelen","informationalModalRejectButtonText":"Nee, bedankt","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockVideo":"DuckDuckGo heeft deze YouTube-video geblokkeerd om te voorkomen dat Google je kan volgen","infoTextUnblockVideo":"We hebben voorkomen dat Google (eigenaar van YouTube) je volgde toen de pagina werd geladen. Als je deze video deblokkeert, kan Google je activiteit zien.","infoPreviewToggleText":"Voorbeelden uitgeschakeld voor extra privacy","infoPreviewToggleEnabledText":"Voorbeelden ingeschakeld","infoPreviewInfoText":"Meer informatie over DuckDuckGo's bescherming tegen ingesloten social media"}},"pl":{"facebook.json":{"informationalModalMessageTitle":"Jeśli zalogujesz się za pośrednictwem Facebooka, będzie on mógł śledzić Twoją aktywność","informationalModalMessageBody":"Po zalogowaniu się DuckDuckGo nie może zablokować możliwości śledzenia Cię przez Facebooka na tej stronie.","informationalModalConfirmButtonText":"Zaloguj się","informationalModalRejectButtonText":"Wróć","loginButtonText":"Zaloguj się za pośrednictwem Facebooka","loginBodyText":"Facebook śledzi Twoją aktywność na stronie, gdy logujesz się za jego pośrednictwem.","buttonTextUnblockContent":"Odblokuj treść","buttonTextUnblockComment":"Odblokuj komentarz","buttonTextUnblockComments":"Odblokuj komentarze","buttonTextUnblockPost":"Odblokuj post","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockContent":"DuckDuckGo zablokował tę treść, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComment":"DuckDuckGo zablokował ten komentarz, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComments":"DuckDuckGo zablokował te komentarze, aby Facebook nie mógł Cię śledzić","infoTitleUnblockPost":"DuckDuckGo zablokował ten post, aby Facebook nie mógł Cię śledzić","infoTitleUnblockVideo":"DuckDuckGo zablokował tę treść wideo, aby Facebook nie mógł Cię śledzić.","infoTextUnblockContent":"Zablokowaliśmy Facebookowi możliwość śledzenia Cię podczas ładowania strony. Jeśli odblokujesz tę treść, Facebook uzyska informacje o Twojej aktywności."},"shared.json":{"learnMore":"Dowiedz się więcej","readAbout":"Dowiedz się więcej o tej ochronie prywatności"},"youtube.json":{"informationalModalMessageTitle":"Włączyć wszystkie podglądy w YouTube?","informationalModalMessageBody":"Wyświetlanie podglądu pozwala Google (który jest właścicielem YouTube) zobaczyć niektóre informacje o Twoim urządzeniu, ale nadal jest to bardziej prywatne niż odtwarzanie filmu.","informationalModalConfirmButtonText":"Włącz wszystkie podglądy","informationalModalRejectButtonText":"Nie, dziękuję","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockVideo":"DuckDuckGo zablokował ten film w YouTube, aby uniemożliwić Google śledzenie Twojej aktywności","infoTextUnblockVideo":"Zablokowaliśmy możliwość śledzenia Cię przez Google (właściciela YouTube) podczas ładowania strony. Jeśli odblokujesz ten film, Google zobaczy Twoją aktywność.","infoPreviewToggleText":"Podglądy zostały wyłączone, aby zapewnić większą ptywatność","infoPreviewToggleEnabledText":"Podglądy włączone","infoPreviewInfoText":"Dowiedz się więcej o zabezpieczeniu osadzonych treści społecznościowych DuckDuckGo"}},"pt":{"facebook.json":{"informationalModalMessageTitle":"Iniciar sessão no Facebook permite que este te rastreie","informationalModalMessageBody":"Depois de iniciares sessão, o DuckDuckGo não poderá bloquear o rastreio por parte do conteúdo do Facebook neste site.","informationalModalConfirmButtonText":"Iniciar sessão","informationalModalRejectButtonText":"Retroceder","loginButtonText":"Iniciar sessão com o Facebook","loginBodyText":"O Facebook rastreia a tua atividade num site quando o usas para iniciares sessão.","buttonTextUnblockContent":"Desbloquear Conteúdo","buttonTextUnblockComment":"Desbloquear Comentário","buttonTextUnblockComments":"Desbloquear Comentários","buttonTextUnblockPost":"Desbloquear Publicação","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockContent":"O DuckDuckGo bloqueou este conteúdo para evitar que o Facebook te rastreie","infoTitleUnblockComment":"O DuckDuckGo bloqueou este comentário para evitar que o Facebook te rastreie","infoTitleUnblockComments":"O DuckDuckGo bloqueou estes comentários para evitar que o Facebook te rastreie","infoTitleUnblockPost":"O DuckDuckGo bloqueou esta publicação para evitar que o Facebook te rastreie","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo para evitar que o Facebook te rastreie","infoTextUnblockContent":"Bloqueámos o rastreio por parte do Facebook quando a página foi carregada. Se desbloqueares este conteúdo, o Facebook fica a saber a tua atividade."},"shared.json":{"learnMore":"Saiba mais","readAbout":"Ler mais sobre esta proteção de privacidade"},"youtube.json":{"informationalModalMessageTitle":"Ativar todas as pré-visualizações do YouTube?","informationalModalMessageBody":"Mostrar visualizações permite à Google (que detém o YouTube) ver algumas das informações do teu dispositivo, mas ainda é mais privado do que reproduzir o vídeo.","informationalModalConfirmButtonText":"Ativar todas as pré-visualizações","informationalModalRejectButtonText":"Não, obrigado","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo do YouTube para impedir que a Google te rastreie","infoTextUnblockVideo":"Bloqueámos o rastreio por parte da Google (que detém o YouTube) quando a página foi carregada. Se desbloqueares este vídeo, a Google fica a saber a tua atividade.","infoPreviewToggleText":"Pré-visualizações desativadas para privacidade adicional","infoPreviewToggleEnabledText":"Pré-visualizações ativadas","infoPreviewInfoText":"Saiba mais sobre a Proteção contra conteúdos de redes sociais incorporados do DuckDuckGo"}},"ro":{"facebook.json":{"informationalModalMessageTitle":"Conectarea cu Facebook îi permite să te urmărească","informationalModalMessageBody":"Odată ce te-ai conectat, DuckDuckGo nu poate împiedica conținutul Facebook să te urmărească pe acest site.","informationalModalConfirmButtonText":"Autentificare","informationalModalRejectButtonText":"Înapoi","loginButtonText":"Conectează-te cu Facebook","loginBodyText":"Facebook urmărește activitatea ta pe un site atunci când îl utilizezi pentru a te conecta.","buttonTextUnblockContent":"Deblochează conținutul","buttonTextUnblockComment":"Deblochează comentariul","buttonTextUnblockComments":"Deblochează comentariile","buttonTextUnblockPost":"Deblochează postarea","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockContent":"DuckDuckGo a blocat acest conținut pentru a împiedica Facebook să te urmărească","infoTitleUnblockComment":"DuckDuckGo a blocat acest comentariu pentru a împiedica Facebook să te urmărească","infoTitleUnblockComments":"DuckDuckGo a blocat aceste comentarii pentru a împiedica Facebook să te urmărească","infoTitleUnblockPost":"DuckDuckGo a blocat această postare pentru a împiedica Facebook să te urmărească","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip pentru a împiedica Facebook să te urmărească","infoTextUnblockContent":"Am împiedicat Facebook să te urmărească atunci când pagina a fost încărcată. Dacă deblochezi acest conținut, Facebook îți va cunoaște activitatea."},"shared.json":{"learnMore":"Află mai multe","readAbout":"Citește despre această protecție a confidențialității"},"youtube.json":{"informationalModalMessageTitle":"Activezi toate previzualizările YouTube?","informationalModalMessageBody":"Afișarea previzualizărilor va permite ca Google (care deține YouTube) să vadă unele dintre informațiile despre dispozitivul tău, dar este totuși mai privată decât redarea videoclipului.","informationalModalConfirmButtonText":"Activează toate previzualizările","informationalModalRejectButtonText":"Nu, mulțumesc","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip de pe YouTube pentru a împiedica Google să te urmărească","infoTextUnblockVideo":"Am împiedicat Google (care deține YouTube) să te urmărească atunci când s-a încărcat pagina. Dacă deblochezi acest videoclip, Google va cunoaște activitatea ta.","infoPreviewToggleText":"Previzualizările au fost dezactivate pentru o confidențialitate suplimentară","infoPreviewToggleEnabledText":"Previzualizări activate","infoPreviewInfoText":"Află mai multe despre Protecția integrată DuckDuckGo pentru rețelele sociale"}},"ru":{"facebook.json":{"informationalModalMessageTitle":"Вход через Facebook позволяет этой социальной сети отслеживать вас","informationalModalMessageBody":"После входа DuckDuckGo не сможет блокировать отслеживание ваших действий с контентом на Facebook.","informationalModalConfirmButtonText":"Войти","informationalModalRejectButtonText":"Вернуться","loginButtonText":"Войти через Facebook","loginBodyText":"При использовании учетной записи Facebook для входа на сайты эта социальная сеть сможет отслеживать на них ваши действия.","buttonTextUnblockContent":"Разблокировать","buttonTextUnblockComment":"Разблокировать","buttonTextUnblockComments":"Разблокировать","buttonTextUnblockPost":"Разблокировать","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockContent":"DuckDuckGo заблокировал этот контент, чтобы вас не отслеживал Facebook","infoTitleUnblockComment":"DuckDuckGo заблокировал этот комментарий, чтобы вас не отслеживал Facebook","infoTitleUnblockComments":"DuckDuckGo заблокировал эти комментарии, чтобы вас не отслеживал Facebook","infoTitleUnblockPost":"DuckDuckGo заблокировал эту публикацию, чтобы вас не отслеживал Facebook","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео, чтобы вас не отслеживал Facebook","infoTextUnblockContent":"Во время загрузки страницы мы помешали Facebook отследить ваши действия. Если разблокировать этот контент, Facebook сможет фиксировать вашу активность."},"shared.json":{"learnMore":"Узнать больше","readAbout":"Подробнее об этом виде защиты конфиденциальности"},"youtube.json":{"informationalModalMessageTitle":"Включить предпросмотр видео из YouTube?","informationalModalMessageBody":"Активация предварительного просмотра позволит Google (владельцу YouTube) получить некоторые сведения о вашем устройстве, однако это более безопасный вариант, чем воспроизведение видео целиком.","informationalModalConfirmButtonText":"Включить предпросмотр","informationalModalRejectButtonText":"Нет, спасибо","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео из YouTube, чтобы вас не отслеживал Google","infoTextUnblockVideo":"Во время загрузки страницы мы помешали Google (владельцу YouTube) отследить ваши действия. Если разблокировать видео, Google сможет фиксировать вашу активность.","infoPreviewToggleText":"Предварительный просмотр отключен для дополнительной защиты конфиденциальности","infoPreviewToggleEnabledText":"Предварительный просмотр включен","infoPreviewInfoText":"Подробнее о защите DuckDuckGo от внедренного контента соцсетей"}},"sk":{"facebook.json":{"informationalModalMessageTitle":"Prihlásenie cez Facebook mu umožní sledovať vás","informationalModalMessageBody":"DuckDuckGo po prihlásení nemôže na tejto lokalite zablokovať sledovanie vašej osoby obsahom Facebooku.","informationalModalConfirmButtonText":"Prihlásiť sa","informationalModalRejectButtonText":"Prejsť späť","loginButtonText":"Prihláste sa pomocou služby Facebook","loginBodyText":"Keď použijete prihlasovanie cez Facebook, Facebook bude na lokalite sledovať vašu aktivitu.","buttonTextUnblockContent":"Odblokovať obsah","buttonTextUnblockComment":"Odblokovať komentár","buttonTextUnblockComments":"Odblokovať komentáre","buttonTextUnblockPost":"Odblokovať príspevok","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockContent":"DuckDuckGo zablokoval tento obsah, aby vás Facebook nesledoval","infoTitleUnblockComment":"DuckDuckGo zablokoval tento komentár, aby zabránil sledovaniu zo strany Facebooku","infoTitleUnblockComments":"DuckDuckGo zablokoval tieto komentáre, aby vás Facebook nesledoval","infoTitleUnblockPost":"DuckDuckGo zablokoval tento príspevok, aby vás Facebook nesledoval","infoTitleUnblockVideo":"DuckDuckGo zablokoval toto video, aby vás Facebook nesledoval","infoTextUnblockContent":"Pri načítaní stránky sme zablokovali Facebook, aby vás nesledoval. Ak tento obsah odblokujete, Facebook bude vedieť o vašej aktivite."},"shared.json":{"learnMore":"Zistite viac","readAbout":"Prečítajte si o tejto ochrane súkromia"},"youtube.json":{"informationalModalMessageTitle":"Chcete povoliť všetky ukážky zo služby YouTube?","informationalModalMessageBody":"Zobrazenie ukážok umožní spoločnosti Google (ktorá vlastní YouTube) vidieť niektoré informácie o vašom zariadení, ale stále je to súkromnejšie ako prehrávanie videa.","informationalModalConfirmButtonText":"Povoliť všetky ukážky","informationalModalRejectButtonText":"Nie, ďakujem","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockVideo":"DuckDuckGo toto video v službe YouTube zablokoval s cieľom predísť tomu, aby vás spoločnosť Google mohla sledovať","infoTextUnblockVideo":"Zablokovali sme pre spoločnosť Google (ktorá vlastní YouTube), aby vás nemohla sledovať, keď sa stránka načíta. Ak toto video odblokujete, Google bude poznať vašu aktivitu.","infoPreviewToggleText":"Ukážky sú zakázané s cieľom zvýšiť ochranu súkromia","infoPreviewToggleEnabledText":"Ukážky sú povolené","infoPreviewInfoText":"Získajte viac informácií o DuckDuckGo, vloženej ochrane sociálnych médií"}},"sl":{"facebook.json":{"informationalModalMessageTitle":"Če se prijavite s Facebookom, vam Facebook lahko sledi","informationalModalMessageBody":"Ko ste enkrat prijavljeni, DuckDuckGo ne more blokirati Facebookove vsebine, da bi vam sledila na tem spletnem mestu.","informationalModalConfirmButtonText":"Prijava","informationalModalRejectButtonText":"Pojdi nazaj","loginButtonText":"Prijavite se s Facebookom","loginBodyText":"Če se prijavite s Facebookom, bo nato spremljal vaša dejanja na spletnem mestu.","buttonTextUnblockContent":"Odblokiraj vsebino","buttonTextUnblockComment":"Odblokiraj komentar","buttonTextUnblockComments":"Odblokiraj komentarje","buttonTextUnblockPost":"Odblokiraj objavo","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockContent":"DuckDuckGo je blokiral to vsebino, da bi Facebooku preprečil sledenje","infoTitleUnblockComment":"DuckDuckGo je blokiral ta komentar, da bi Facebooku preprečil sledenje","infoTitleUnblockComments":"DuckDuckGo je blokiral te komentarje, da bi Facebooku preprečil sledenje","infoTitleUnblockPost":"DuckDuckGo je blokiral to objavo, da bi Facebooku preprečil sledenje","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek, da bi Facebooku preprečil sledenje","infoTextUnblockContent":"Ko se je stran naložila, smo Facebooku preprečili, da bi vam sledil. Če to vsebino odblokirate, bo Facebook izvedel za vaša dejanja."},"shared.json":{"learnMore":"Več","readAbout":"Preberite več o tej zaščiti zasebnosti"},"youtube.json":{"informationalModalMessageTitle":"Želite omogočiti vse YouTubove predoglede?","informationalModalMessageBody":"Prikaz predogledov omogoča Googlu (ki je lastnik YouTuba) vpogled v nekatere podatke o napravi, vendar je še vedno bolj zasebno kot predvajanje videoposnetka.","informationalModalConfirmButtonText":"Omogoči vse predoglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek v YouTubu, da bi Googlu preprečil sledenje","infoTextUnblockVideo":"Googlu (ki je lastnik YouTuba) smo preprečili, da bi vam sledil, ko se je stran naložila. Če odblokirate ta videoposnetek, bo Google izvedel za vašo dejavnost.","infoPreviewToggleText":"Predogledi so zaradi dodatne zasebnosti onemogočeni","infoPreviewToggleEnabledText":"Predogledi so omogočeni","infoPreviewInfoText":"Več o vgrajeni zaščiti družbenih medijev DuckDuckGo"}},"sv":{"facebook.json":{"informationalModalMessageTitle":"Om du loggar in med Facebook kan de spåra dig","informationalModalMessageBody":"När du väl är inloggad kan DuckDuckGo inte hindra Facebooks innehåll från att spåra dig på den här webbplatsen.","informationalModalConfirmButtonText":"Logga in","informationalModalRejectButtonText":"Gå tillbaka","loginButtonText":"Logga in med Facebook","loginBodyText":"Facebook spårar din aktivitet på en webbplats om du använder det för att logga in.","buttonTextUnblockContent":"Avblockera innehåll","buttonTextUnblockComment":"Avblockera kommentar","buttonTextUnblockComments":"Avblockera kommentarer","buttonTextUnblockPost":"Avblockera inlägg","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockContent":"DuckDuckGo blockerade det här innehållet för att förhindra att Facebook spårar dig","infoTitleUnblockComment":"DuckDuckGo blockerade den här kommentaren för att förhindra att Facebook spårar dig","infoTitleUnblockComments":"DuckDuckGo blockerade de här kommentarerna för att förhindra att Facebook spårar dig","infoTitleUnblockPost":"DuckDuckGo blockerade det här inlägget för att förhindra att Facebook spårar dig","infoTitleUnblockVideo":"DuckDuckGo blockerade den här videon för att förhindra att Facebook spårar dig","infoTextUnblockContent":"Vi hindrade Facebook från att spåra dig när sidan lästes in. Om du avblockerar det här innehållet kommer Facebook att känna till din aktivitet."},"shared.json":{"learnMore":"Läs mer","readAbout":"Läs mer om detta integritetsskydd"},"youtube.json":{"informationalModalMessageTitle":"Aktivera alla förhandsvisningar för YouTube?","informationalModalMessageBody":"Genom att visa förhandsvisningar kan Google (som äger YouTube) se en del av enhetens information, men det är ändå mer privat än att spela upp videon.","informationalModalConfirmButtonText":"Aktivera alla förhandsvisningar","informationalModalRejectButtonText":"Nej tack","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockVideo":"DuckDuckGo blockerade den här YouTube-videon för att förhindra att Google spårar dig","infoTextUnblockVideo":"Vi hindrade Google (som äger YouTube) från att spåra dig när sidan laddades. Om du tar bort blockeringen av videon kommer Google att känna till din aktivitet.","infoPreviewToggleText":"Förhandsvisningar har inaktiverats för ytterligare integritet","infoPreviewToggleEnabledText":"Förhandsvisningar aktiverade","infoPreviewInfoText":"Läs mer om DuckDuckGos skydd mot inbäddade sociala medier"}},"tr":{"facebook.json":{"informationalModalMessageTitle":"Facebook ile giriş yapmak, sizi takip etmelerini sağlar","informationalModalMessageBody":"Giriş yaptıktan sonra, DuckDuckGo Facebook içeriğinin sizi bu sitede izlemesini engelleyemez.","informationalModalConfirmButtonText":"Oturum Aç","informationalModalRejectButtonText":"Geri dön","loginButtonText":"Facebook ile giriş yapın","loginBodyText":"Facebook, giriş yapmak için kullandığınızda bir sitedeki etkinliğinizi izler.","buttonTextUnblockContent":"İçeriğin Engelini Kaldır","buttonTextUnblockComment":"Yorumun Engelini Kaldır","buttonTextUnblockComments":"Yorumların Engelini Kaldır","buttonTextUnblockPost":"Gönderinin Engelini Kaldır","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockContent":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu içeriği engelledi","infoTitleUnblockComment":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumu engelledi","infoTitleUnblockComments":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumları engelledi","infoTitleUnblockPost":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu gönderiyi engelledi","infoTitleUnblockVideo":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu videoyu engelledi","infoTextUnblockContent":"Sayfa yüklendiğinde Facebook'un sizi izlemesini engelledik. Bu içeriğin engelini kaldırırsanız Facebook etkinliğinizi öğrenecektir."},"shared.json":{"learnMore":"Daha Fazla Bilgi","readAbout":"Bu gizlilik koruması hakkında bilgi edinin"},"youtube.json":{"informationalModalMessageTitle":"Tüm YouTube önizlemeleri etkinleştirilsin mi?","informationalModalMessageBody":"Önizlemelerin gösterilmesi Google'ın (YouTube'un sahibi) cihazınızın bazı bilgilerini görmesine izin verir, ancak yine de videoyu oynatmaktan daha özeldir.","informationalModalConfirmButtonText":"Tüm Önizlemeleri Etkinleştir","informationalModalRejectButtonText":"Hayır Teşekkürler","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockVideo":"DuckDuckGo, Google'ın sizi izlemesini önlemek için bu YouTube videosunu engelledi","infoTextUnblockVideo":"Sayfa yüklendiğinde Google'ın (YouTube'un sahibi) sizi izlemesini engelledik. Bu videonun engelini kaldırırsanız, Google etkinliğinizi öğrenecektir.","infoPreviewToggleText":"Ek gizlilik için önizlemeler devre dışı bırakıldı","infoPreviewToggleEnabledText":"Önizlemeler etkinleştirildi","infoPreviewInfoText":"DuckDuckGo Yerleşik Sosyal Medya Koruması hakkında daha fazla bilgi edinin"}}}`; /********************************************************* * Style Definitions *********************************************************/ - const styles = { - fontStyle: ` + /** + * Get CSS style defintions for CTL, using the provided AssetConfig for any non-embedded assets + * (e.g. fonts.) + * @param {import('../../content-feature.js').AssetConfig} [assets] + */ + function getStyles (assets) { + let fontStyle = ''; + let regularFontFamily = "system, -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'"; + let boldFontFamily = regularFontFamily; + if (assets?.regularFontUrl && assets?.boldFontUrl) { + fontStyle = ` @font-face{ font-family: DuckDuckGoPrivacyEssentials; - src: url(${ddgFont}); + src: url(${assets.regularFontUrl}); } @font-face{ font-family: DuckDuckGoPrivacyEssentialsBold; font-weight: bold; - src: url(${ddgFontBold}); + src: url(${assets.boldFontUrl}); } - `, - darkMode: { - background: ` + `; + regularFontFamily = 'DuckDuckGoPrivacyEssentials'; + boldFontFamily = 'DuckDuckGoPrivacyEssentialsBold'; + } + return { + fontStyle, + darkMode: { + background: ` background: #111111; `, - textFont: ` + textFont: ` color: rgba(255, 255, 255, 0.9); `, - buttonFont: ` + buttonFont: ` color: #111111; `, - linkFont: ` + linkFont: ` color: #7295F6; `, - buttonBackground: ` + buttonBackground: ` background: #5784FF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #557FF3; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #3969EF; `, - toggleButtonText: ` + toggleButtonText: ` color: #EEEEEE; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #5784FF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - lightMode: { - background: ` + } + }, + lightMode: { + background: ` background: #FFFFFF; `, - textFont: ` + textFont: ` color: #222222; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; `, - linkFont: ` + linkFont: ` color: #3969EF; `, - buttonBackground: ` + buttonBackground: ` background: #3969EF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #2B55CA; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #1E42A4; `, - toggleButtonText: ` + toggleButtonText: ` color: #666666; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #3969EF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - loginMode: { - buttonBackground: ` + } + }, + loginMode: { + buttonBackground: ` background: #666666; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; ` - }, - cancelMode: { - buttonBackground: ` + }, + cancelMode: { + buttonBackground: ` background: rgba(34, 34, 34, 0.1); `, - buttonFont: ` + buttonFont: ` color: #222222; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: rgba(0, 0, 0, 0.12); `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: rgba(0, 0, 0, 0.18); ` - }, - button: ` + }, + button: ` border-radius: 8px; padding: 11px 22px; @@ -4954,7 +5258,7 @@ border-color: #3969EF; border: none; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; font-size: 14px; position: relative; @@ -4962,7 +5266,7 @@ box-shadow: none; z-index: 2147483646; `, - circle: ` + circle: ` border-radius: 50%; width: 18px; height: 18px; @@ -4972,14 +5276,14 @@ top: -8px; right: -8px; `, - loginIcon: ` + loginIcon: ` position: absolute; top: -13px; right: -10px; height: 28px; width: 28px; `, - rectangle: ` + rectangle: ` width: 12px; height: 3px; background: #666666; @@ -4987,7 +5291,7 @@ top: 42.5%; margin: auto; `, - textBubble: ` + textBubble: ` background: #FFFFFF; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 16px; @@ -4998,9 +5302,9 @@ position: absolute; line-height: normal; `, - textBubbleWidth: 360, // Should match the width rule in textBubble - textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble - textArrow: ` + textBubbleWidth: 360, // Should match the width rule in textBubble + textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble + textArrow: ` display: inline-block; background: #FFFFFF; border: solid rgba(0, 0, 0, 0.1); @@ -5011,23 +5315,23 @@ position: relative; top: -9px; `, - arrowDefaultLocationPercent: 50, - hoverTextTitle: ` + arrowDefaultLocationPercent: 50, + hoverTextTitle: ` padding: 0px 12px 12px; margin-top: -5px; `, - hoverTextBody: ` - font-family: DuckDuckGoPrivacyEssentials; + hoverTextBody: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: auto; padding: 17px; text-align: left; `, - hoverContainer: ` + hoverContainer: ` padding-bottom: 10px; `, - buttonTextContainer: ` + buttonTextContainer: ` display: flex; flex-direction: row; align-items: center; @@ -5035,10 +5339,10 @@ padding: 0; margin: 0; `, - headerRow: ` + headerRow: ` `, - block: ` + block: ` box-sizing: border-box; border: 1px solid rgba(0,0,0,0.1); border-radius: 12px; @@ -5048,27 +5352,27 @@ display: flex; flex-direction: column; - font-family: DuckDuckGoPrivacyEssentials; + font-family: ${regularFontFamily}; line-height: 1; `, - youTubeDialogBlock: ` + youTubeDialogBlock: ` height: calc(100% - 30px); max-width: initial; min-height: initial; `, - imgRow: ` + imgRow: ` display: flex; flex-direction: column; margin: 20px 0px; `, - content: ` + content: ` display: flex; flex-direction: column; padding: 16px 0; flex: 1 1 1px; `, - feedbackLink: ` - font-family: DuckDuckGoPrivacyEssentials; + feedbackLink: ` + font-family: ${regularFontFamily}; font-style: normal; font-weight: 400; font-size: 12px; @@ -5076,13 +5380,13 @@ color: #ABABAB; text-decoration: none; `, - feedbackRow: ` + feedbackRow: ` height: 30px; display: flex; justify-content: flex-end; align-items: center; `, - titleBox: ` + titleBox: ` display: flex; padding: 12px; max-height: 44px; @@ -5091,8 +5395,8 @@ margin: 0; margin-bottom: 4px; `, - title: ` - font-family: DuckDuckGoPrivacyEssentials; + title: ` + font-family: ${regularFontFamily}; line-height: 1.4; font-size: 14px; margin: auto 10px; @@ -5104,7 +5408,7 @@ border: none; padding: 0; `, - buttonRow: ` + buttonRow: ` display: flex; height: 100% flex-direction: row; @@ -5112,8 +5416,8 @@ height: 100%; align-items: flex-start; `, - modalContentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + modalContentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; line-height: 21px; @@ -5122,8 +5426,8 @@ border: none; padding: 0px 32px; `, - modalContentText: ` - font-family: DuckDuckGoPrivacyEssentials; + modalContentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: 0px auto 14px; @@ -5131,7 +5435,7 @@ border: none; padding: 0; `, - modalButtonRow: ` + modalButtonRow: ` border: none; padding: 0; margin: auto; @@ -5140,17 +5444,17 @@ flex-direction: column; align-items: center; `, - modalButton: ` + modalButton: ` width: 100%; display: flex; justify-content: center; align-items: center; `, - modalIcon: ` + modalIcon: ` display: block; `, - contentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + contentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; margin: 20px auto 10px; @@ -5158,25 +5462,25 @@ text-align: center; margin-top: auto; `, - contentText: ` - font-family: DuckDuckGoPrivacyEssentials; + contentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; padding: 0px 40px; text-align: center; margin: 0 auto auto; `, - icon: ` + icon: ` height: 80px; width: 80px; margin: auto; `, - closeIcon: ` + closeIcon: ` height: 12px; width: 12px; margin: auto; `, - closeButton: ` + closeButton: ` display: flex; justify-content: center; align-items: center; @@ -5186,7 +5490,7 @@ background: transparent; cursor: pointer; `, - logo: ` + logo: ` flex-basis: 0%; min-width: 20px; height: 21px; @@ -5194,17 +5498,17 @@ padding: 0; margin: 0; `, - logoImg: ` + logoImg: ` height: 21px; width: 21px; `, - loadingImg: ` + loadingImg: ` display: block; margin: 0px 8px 0px 0px; height: 14px; width: 14px; `, - modal: ` + modal: ` width: 340px; padding: 0; margin: auto; @@ -5218,14 +5522,14 @@ border-radius: 12px; border: none; `, - modalContent: ` + modalContent: ` padding: 24px; display: flex; flex-direction: column; border: none; margin: 0; `, - overlay: ` + overlay: ` height: 100%; width: 100%; background-color: #666666; @@ -5238,7 +5542,7 @@ padding: 0; margin: 0; `, - modalContainer: ` + modalContainer: ` height: 100vh; width: 100vw; box-sizing: border-box; @@ -5249,16 +5553,16 @@ margin: 0; padding: 0; `, - headerLinkContainer: ` + headerLinkContainer: ` flex-basis: 100%; display: grid; justify-content: flex-end; `, - headerLink: ` + headerLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; text-decoration: none; cursor: pointer; min-width: 100px; @@ -5266,15 +5570,15 @@ float: right; display: none; `, - generalLink: ` + generalLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; cursor: pointer; text-decoration: none; `, - wrapperDiv: ` + wrapperDiv: ` display: inline-block; border: 0; padding: 0; @@ -5282,12 +5586,12 @@ max-width: 600px; min-height: 300px; `, - toggleButtonWrapper: ` + toggleButtonWrapper: ` display: flex; align-items: center; cursor: pointer; `, - toggleButton: ` + toggleButton: ` cursor: pointer; position: relative; width: 30px; @@ -5299,19 +5603,19 @@ background-color: transparent; text-align: left; `, - toggleButtonBg: ` + toggleButtonBg: ` right: 0; width: 30px; height: 16px; overflow: visible; border-radius: 10px; `, - toggleButtonText: ` + toggleButtonText: ` display: inline-block; margin: 0 0 0 7px; padding: 0; `, - toggleButtonKnob: ` + toggleButtonKnob: ` position: absolute; display: inline-block; width: 14px; @@ -5322,15 +5626,15 @@ top: calc(50% - 14px/2 - 1px); box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.05), 0px 1px 1px rgba(0, 0, 0, 0.1); `, - toggleButtonKnobState: { - active: ` + toggleButtonKnobState: { + active: ` right: 1px; `, - inactive: ` + inactive: ` left: 1px; ` - }, - placeholderWrapperDiv: ` + }, + placeholderWrapperDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5340,7 +5644,7 @@ min-height: 300px; margin: auto; `, - youTubeWrapperDiv: ` + youTubeWrapperDiv: ` position: relative; overflow: hidden; max-width: initial; @@ -5348,7 +5652,7 @@ min-height: 300px; height: 100%; `, - youTubeDialogDiv: ` + youTubeDialogDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5356,14 +5660,14 @@ min-height: initial; height: calc(100% - 30px); `, - youTubeDialogBottomRow: ` + youTubeDialogBottomRow: ` display: flex; flex-direction: column; align-items: center; justify-content: flex-end; margin-top: auto; `, - youTubePlaceholder: ` + youTubePlaceholder: ` display: flex; flex-direction: column; justify-content: flex-start; @@ -5372,7 +5676,7 @@ height: 100%; background: rgba(45, 45, 45, 0.8); `, - youTubePreviewWrapperImg: ` + youTubePreviewWrapperImg: ` position: absolute; display: flex; justify-content: center; @@ -5380,20 +5684,20 @@ width: 100%; height: 100%; `, - youTubePreviewImg: ` + youTubePreviewImg: ` min-width: 100%; min-height: 100%; height: auto; `, - youTubeTopSection: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + youTubeTopSection: ` + font-family: ${boldFontFamily}; flex: 1; display: flex; justify-content: space-between; position: relative; padding: 18px 12px 0; `, - youTubeTitle: ` + youTubeTitle: ` font-size: 14px; font-weight: bold; line-height: 14px; @@ -5405,13 +5709,13 @@ text-overflow: ellipsis; box-sizing: border-box; `, - youTubePlayButtonRow: ` + youTubePlayButtonRow: ` flex: 2; display: flex; align-items: center; justify-content: center; `, - youTubePlayButton: ` + youTubePlayButton: ` display: flex; justify-content: center; align-items: center; @@ -5420,7 +5724,7 @@ padding: 0px 24px; border-radius: 8px; `, - youTubePreviewToggleRow: ` + youTubePreviewToggleRow: ` flex: 1; display: flex; flex-direction: column; @@ -5428,15 +5732,19 @@ align-items: center; padding: 0 12px 18px; `, - youTubePreviewToggleText: ` + youTubePreviewToggleText: ` color: #EEEEEE; font-weight: 400; `, - youTubePreviewInfoText: ` + youTubePreviewInfoText: ` color: #ABABAB; ` - }; + } + } + /** + * @param {string} locale UI locale + */ function getConfig (locale) { const locales = JSON.parse(localesJSON); const fbStrings = locales[locale]['facebook.json']; @@ -5873,6 +6181,7 @@ // @see {getConfig} let config = null; let sharedStrings = null; + let styles = null; // TODO: Remove these redundant data structures and refactor the related code. // There should be no need to have the entity configuration stored in two @@ -6335,6 +6644,16 @@ ]; elementToReplace.style.setProperty('display', 'none', 'important'); + // When iframes are blocked by the declarativeNetRequest API, they are + // collapsed (hidden) automatically. Unfortunately however, there's a bug + // that stops them from being uncollapsed (shown again) if they are removed + // from the DOM after they are collapsed. As a workaround, have the iframe + // load a benign data URI, so that it's uncollapsed, before removing it from + // the DOM. See https://crbug.com/1428971 + const originalSrc = elementToReplace.src; + elementToReplace.src = + 'data:text/plain;charset=utf-8;base64,' + btoa('https://crbug.com/1428971'); + // Add the placeholder element to the page. elementToReplace.parentElement.insertBefore( placeholderElement, elementToReplace @@ -6354,6 +6673,7 @@ // placeholder) can finally be removed from the DOM. elementToReplace.remove(); elementToReplace.style.setProperty('display', ...originalDisplay); + elementToReplace.src = originalSrc; }); } @@ -6744,10 +7064,10 @@ * Creates an anchor element with no destination. It is expected that a click * handler is added to the element later. * @param {string} linkText - * @param {displayMode} [mode='lightMode'] + * @param {displayMode} mode * @returns {HTMLAnchorElement} */ - function makeTextButton (linkText, mode) { + function makeTextButton (linkText, mode = 'lightMode') { const linkElement = document.createElement('a'); linkElement.style.cssText = styles.headerLink + styles[mode].linkFont; linkElement.textContent = linkText; @@ -7471,6 +7791,8 @@ const localizedConfig = getConfig(locale); config = localizedConfig.config; sharedStrings = localizedConfig.sharedStrings; + // update styles if asset config was sent + styles = getStyles(this.assetConfig); for (const entity of Object.keys(config)) { // Strip config entities that are first-party, or aren't enabled in the @@ -7539,6 +7861,16 @@ } await afterPageLoad; + // On some websites, the "ddg-ctp-ready" event is occasionally + // dispatched too early, before the listener is ready to receive it. + // To counter that, catch "ddg-ctp-surrogate-load" events dispatched + // _after_ page, so the "ddg-ctp-ready" event can be dispatched again. + window.addEventListener( + 'ddg-ctp-surrogate-load', () => { + originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready')); + } + ); + // Then wait for any in-progress element replacements, before letting // the surrogate scripts know to start. window.setTimeout(() => { @@ -7612,12 +7944,14 @@ /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** @@ -7690,27 +8024,6 @@ }); } - /** - * Check if the current document origin is on the tracker list, using the provided lookup trie. - * @param {object} trackerLookup Trie lookup of tracker domains - * @returns {boolean} True iff the origin is a tracker. - */ - function isTrackerOrigin (trackerLookup) { - const originHostname = document.location.hostname; - const parts = originHostname.split('.').reverse(); - let node = trackerLookup; - for (const sub of parts) { - if (node[sub] === 1) { - return true - } else if (node[sub]) { - node = node[sub]; - } else { - return false - } - } - return false - } - /** * @module Chrome MV3 integration * @category Content Scope Scripts Integrations @@ -7718,12 +8031,15 @@ const secret = (crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32).toString().replace('0.', ''); + const trackerLookup = $TRACKER_LOOKUP$; + load({ platform: { name: 'extension' }, - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - documentOriginIsTracker: isTrackerOrigin($TRACKER_LOOKUP$), + trackerLookup, + documentOriginIsTracker: isTrackerOrigin(trackerLookup), + site: computeLimitedSiteObject(), // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f bundledConfig: $BUNDLED_CONFIG$ }); diff --git a/build/chrome/inject.js b/build/chrome/inject.js index fe3c33637..10e67800e 100644 --- a/build/chrome/inject.js +++ b/build/chrome/inject.js @@ -7,8 +7,7 @@ * @param {object} trackerLookup Trie lookup of tracker domains * @returns {boolean} True iff the origin is a tracker. */ - function isTrackerOrigin (trackerLookup) { - const originHostname = document.location.hostname; + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { const parts = originHostname.split('.').reverse(); let node = trackerLookup; for (const sub of parts) { @@ -23,6 +22,63 @@ return false } + /* global cloneInto, exportFunction, false */ + typeof window === 'undefined' ? null : window.dispatchEvent.bind(window); + + /** + * Best guess effort of the tabs hostname; where possible always prefer the args.site.domain + * @returns {string|null} inferred tab hostname + */ + function getTabHostname () { + let framingOrigin = null; + try { + // @ts-expect-error - globalThis.top is possibly 'null' here + framingOrigin = globalThis.top.location.href; + } catch { + framingOrigin = globalThis.document.referrer; + } + + // Not supported in Firefox + if ('ancestorOrigins' in globalThis.location && globalThis.location.ancestorOrigins.length) { + // ancestorOrigins is reverse order, with the last item being the top frame + framingOrigin = globalThis.location.ancestorOrigins.item(globalThis.location.ancestorOrigins.length - 1); + } + + try { + // @ts-expect-error - framingOrigin is possibly 'null' here + framingOrigin = new URL(framingOrigin).hostname; + } catch { + framingOrigin = null; + } + return framingOrigin + } + + /** + * @typedef {object} Platform + * @property {'ios' | 'macos' | 'extension' | 'android' | 'windows'} name + * @property {string | number } [version] + */ + + /** + * @typedef {object} UserPreferences + * @property {Platform} platform + * @property {boolean} [debug] + * @property {boolean} [globalPrivacyControl] + * @property {number} [versionNumber] - Android version number only + * @property {string} [versionString] - Non Android version string + * @property {string} sessionKey + */ + + /** + * Used to inialize extension code in the load phase + */ + function computeLimitedSiteObject () { + const topLevelHostname = getTabHostname(); + return { + domain: topLevelHostname + } + } + /** * @module Chrome integration * @category Content Scope Scripts Integrations @@ -62,20 +118,23 @@ } function init () { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - const documentOriginIsTracker = isTrackerOrigin($TRACKER_LOOKUP$); + const trackerLookup = $TRACKER_LOOKUP$; + const documentOriginIsTracker = isTrackerOrigin(trackerLookup); // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f const bundledConfig = $BUNDLED_CONFIG$; const randomMethodName = '_d' + randomString(); const randomPassword = '_p' + randomString(); const reusableMethodName = '_rm' + randomString(); const reusableSecret = '_r' + randomString(); + const siteObject = computeLimitedSiteObject(); const initialScript = ` - ${decodeURI("/*!%20%C2%A9%20DuckDuckGo%20ContentScopeScripts%20protections%20https://github.com/duckduckgo/content-scope-scripts/%20*/%0Avar%20contentScopeFeatures%20=%20(function%20(exports)%20%7B%0A%20%20%20%20'use%20strict';%0A%0A%20%20%20%20/*%20global%20cloneInto,%20exportFunction,%20false%20*/%0A%0A%20%20%20%20//%20Only%20use%20globalThis%20for%20testing%20this%20breaks%20window.wrappedJSObject%20code%20in%20Firefox%0A%20%20%20%20//%20eslint-disable-next-line%20no-global-assign%0A%20%20%20%20let%20globalObj%20=%20typeof%20window%20===%20'undefined'%20?%20globalThis%20:%20window;%0A%20%20%20%20let%20Error$1%20=%20globalObj.Error;%0A%20%20%20%20let%20messageSecret;%0A%20%20%20%20const%20CapturedSet%20=%20globalObj.Set;%0A%20%20%20%20//%20Capture%20prototype%20to%20prevent%20overloading%0A%20%20%20%20const%20createSet%20=%20()%20=%3E%20new%20CapturedSet();%0A%0A%20%20%20%20//%20save%20a%20reference%20to%20original%20CustomEvent%20amd%20dispatchEvent%20so%20they%20can't%20be%20overriden%20to%20forge%20messages%0A%20%20%20%20const%20OriginalCustomEvent%20=%20typeof%20CustomEvent%20===%20'undefined'%20?%20null%20:%20CustomEvent;%0A%20%20%20%20const%20originalWindowDispatchEvent%20=%20typeof%20window%20===%20'undefined'%20?%20null%20:%20window.dispatchEvent.bind(window);%0A%20%20%20%20function%20registerMessageSecret%20(secret)%20%7B%0A%20%20%20%20%20%20%20%20messageSecret%20=%20secret;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@returns%20%7BHTMLElement%7D%20the%20element%20to%20inject%20the%20script%20into%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getInjectionElement%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20document.head%20%7C%7C%20document.documentElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20script%20element%20with%20the%20given%20code%20to%20avoid%20Firefox%20CSP%20restrictions.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20css%0A%20%20%20%20%20*%20@returns%20%7BHTMLLinkElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createStyleElement%20(css)%20%7B%0A%20%20%20%20%20%20%20%20const%20style%20=%20document.createElement('link');%0A%20%20%20%20%20%20%20%20style.href%20=%20'data:text/css,'%20+%20encodeURIComponent(css);%0A%20%20%20%20%20%20%20%20style.setAttribute('rel',%20'stylesheet');%0A%20%20%20%20%20%20%20%20style.setAttribute('type',%20'text/css');%0A%20%20%20%20%20%20%20%20return%20style%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Injects%20a%20script%20into%20the%20page,%20avoiding%20CSP%20restrictions%20if%20possible.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20injectGlobalStyles%20(css)%20%7B%0A%20%20%20%20%20%20%20%20const%20style%20=%20createStyleElement(css);%0A%20%20%20%20%20%20%20%20getInjectionElement().appendChild(style);%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20linear%20feedback%20shift%20register%20to%20find%20a%20random%20approximation%0A%20%20%20%20function%20nextRandom%20(v)%20%7B%0A%20%20%20%20%20%20%20%20return%20Math.abs((v%20%3E%3E%201)%20%7C%20(((v%20%3C%3C%2062)%20%5E%20(v%20%3C%3C%2061))%20&%20(~(~0%20%3C%3C%2063)%20%3C%3C%2062)))%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20exemptionLists%20=%20%7B%7D;%0A%20%20%20%20function%20shouldExemptUrl%20(type,%20url)%20%7B%0A%20%20%20%20%20%20%20%20for%20(const%20regex%20of%20exemptionLists%5Btype%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(regex.test(url))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20debug%20=%20false;%0A%0A%20%20%20%20function%20initStringExemptionLists%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20%7B%20stringExemptionLists%20%7D%20=%20args;%0A%20%20%20%20%20%20%20%20debug%20=%20args.debug;%0A%20%20%20%20%20%20%20%20for%20(const%20type%20in%20stringExemptionLists)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20exemptionLists%5Btype%5D%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20stringExemption%20of%20stringExemptionLists%5Btype%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exemptionLists%5Btype%5D.push(new%20RegExp(stringExemption));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Best%20guess%20effort%20if%20the%20document%20is%20being%20framed%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%20if%20we%20infer%20the%20document%20is%20framed%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isBeingFramed%20()%20%7B%0A%20%20%20%20%20%20%20%20if%20('ancestorOrigins'%20in%20globalThis.location)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20globalThis.location.ancestorOrigins.length%20%3E%200%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20globalThis.top%20!==%20globalThis.window%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Best%20guess%20effort%20if%20the%20document%20is%20third%20party%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%20if%20we%20infer%20the%20document%20is%20third%20party%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isThirdParty%20()%20%7B%0A%20%20%20%20%20%20%20%20if%20(!isBeingFramed())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20getTabHostname()%20is%20string%7Cnull%20here%0A%20%20%20%20%20%20%20%20return%20!matchHostname(globalThis.location.hostname,%20getTabHostname())%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Best%20guess%20effort%20of%20the%20tabs%20hostname;%20where%20possible%20always%20prefer%20the%20args.site.domain%0A%20%20%20%20%20*%20@returns%20%7Bstring%7Cnull%7D%20inferred%20tab%20hostname%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getTabHostname%20()%20%7B%0A%20%20%20%20%20%20%20%20let%20framingOrigin%20=%20null;%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20globalThis.top%20is%20possibly%20'null'%20here%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20globalThis.top.location.href;%0A%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20globalThis.document.referrer;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Not%20supported%20in%20Firefox%0A%20%20%20%20%20%20%20%20if%20('ancestorOrigins'%20in%20globalThis.location%20&&%20globalThis.location.ancestorOrigins.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20ancestorOrigins%20is%20reverse%20order,%20with%20the%20last%20item%20being%20the%20top%20frame%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20globalThis.location.ancestorOrigins.item(globalThis.location.ancestorOrigins.length%20-%201);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20framingOrigin%20is%20possibly%20'null'%20here%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20new%20URL(framingOrigin).hostname;%0A%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20null;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20framingOrigin%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Returns%20true%20if%20hostname%20is%20a%20subset%20of%20exceptionDomain%20or%20an%20exact%20match.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20hostname%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20exceptionDomain%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20matchHostname%20(hostname,%20exceptionDomain)%20%7B%0A%20%20%20%20%20%20%20%20return%20hostname%20===%20exceptionDomain%20%7C%7C%20hostname.endsWith(%60.$%7BexceptionDomain%7D%60)%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20lineTest%20=%20/(%5C()?(https?:%5B%5E)%5D+):%5B0-9%5D+:%5B0-9%5D+(%5C))?/;%0A%20%20%20%20function%20getStackTraceUrls%20(stack)%20%7B%0A%20%20%20%20%20%20%20%20const%20urls%20=%20createSet();%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20errorLines%20=%20stack.split('%5Cn');%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Should%20cater%20for%20Chrome%20and%20Firefox%20stacks,%20we%20only%20care%20about%20https?%20resources.%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20line%20of%20errorLines)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20res%20=%20line.match(lineTest);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(res)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urls.add(new%20URL(res%5B2%5D,%20location.href));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Fall%20through%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20urls%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20getStackTraceOrigins%20(stack)%20%7B%0A%20%20%20%20%20%20%20%20const%20urls%20=%20getStackTraceUrls(stack);%0A%20%20%20%20%20%20%20%20const%20origins%20=%20createSet();%0A%20%20%20%20%20%20%20%20for%20(const%20url%20of%20urls)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20origins.add(url.hostname);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20origins%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Checks%20the%20stack%20trace%20if%20there%20are%20known%20libraries%20that%20are%20broken.%0A%20%20%20%20function%20shouldExemptMethod%20(type)%20%7B%0A%20%20%20%20%20%20%20%20//%20Short%20circuit%20stack%20tracing%20if%20we%20don't%20have%20checks%0A%20%20%20%20%20%20%20%20if%20(!(type%20in%20exemptionLists)%20%7C%7C%20exemptionLists%5Btype%5D.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20const%20errorFiles%20=%20getStackTraceUrls(stack);%0A%20%20%20%20%20%20%20%20for%20(const%20path%20of%20errorFiles)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldExemptUrl(type,%20path.href))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Iterate%20through%20the%20key,%20passing%20an%20item%20index%20and%20a%20byte%20to%20be%20modified%0A%20%20%20%20function%20iterateDataKey%20(key,%20callback)%20%7B%0A%20%20%20%20%20%20%20%20let%20item%20=%20key.charCodeAt(0);%0A%20%20%20%20%20%20%20%20for%20(const%20i%20in%20key)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20byte%20=%20key.charCodeAt(i);%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(let%20j%20=%208;%20j%20%3E=%200;%20j--)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20res%20=%20callback(item,%20byte);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Exit%20early%20if%20callback%20returns%20null%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(res%20===%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20find%20next%20item%20to%20perturb%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20item%20=%20nextRandom(item);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Right%20shift%20as%20we%20use%20the%20least%20significant%20bit%20of%20it%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20byte%20=%20byte%20%3E%3E%201;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isFeatureBroken%20(args,%20feature)%20%7B%0A%20%20%20%20%20%20%20%20return%20isWindowsSpecificFeature(feature)%0A%20%20%20%20%20%20%20%20%20%20%20%20?%20!args.site.enabledFeatures.includes(feature)%0A%20%20%20%20%20%20%20%20%20%20%20%20:%20args.site.isBroken%20%7C%7C%20args.site.allowlisted%20%7C%7C%20!args.site.enabledFeatures.includes(feature)%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20For%20each%20property%20defined%20on%20the%20object,%20update%20it%20with%20the%20target%20value.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20overrideProperty%20(name,%20prop)%20%7B%0A%20%20%20%20%20%20%20%20//%20Don't%20update%20if%20existing%20value%20is%20undefined%20or%20null%0A%20%20%20%20%20%20%20%20if%20(!(prop.origValue%20===%20undefined))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20When%20re-defining%20properties,%20we%20bind%20the%20overwritten%20functions%20to%20null.%20This%20prevents%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20sites%20from%20using%20toString%20to%20see%20if%20the%20function%20has%20been%20overwritten%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20without%20this%20bind%20call,%20a%20site%20could%20run%20something%20like%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20%60Object.getOwnPropertyDescriptor(Screen.prototype,%20%22availTop%22).get.toString()%60%20and%20see%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20the%20contents%20of%20the%20function.%20Appending%20.bind(null)%20to%20the%20function%20definition%20will%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20have%20the%20same%20toString%20call%20return%20the%20default%20%5Bnative%20code%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(prop.object,%20name,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20no-extra-bind%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20(()%20=%3E%20prop.targetValue).bind(null)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20prop.origValue%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20defineProperty%20(object,%20propertyName,%20descriptor)%20%7B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(object,%20propertyName,%20descriptor);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20camelcase%20(dashCaseText)%20%7B%0A%20%20%20%20%20%20%20%20return%20dashCaseText.replace(/-(.)/g,%20(match,%20letter)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20letter.toUpperCase()%0A%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20We%20use%20this%20method%20to%20detect%20M1%20macs%20and%20set%20appropriate%20API%20values%20to%20prevent%20sites%20from%20detecting%20fingerprinting%20protections%0A%20%20%20%20function%20isAppleSilicon%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20canvas%20=%20document.createElement('canvas');%0A%20%20%20%20%20%20%20%20const%20gl%20=%20canvas.getContext('webgl');%0A%0A%20%20%20%20%20%20%20%20//%20Best%20guess%20if%20the%20device%20is%20an%20Apple%20Silicon%0A%20%20%20%20%20%20%20%20//%20https://stackoverflow.com/a/65412357%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'null'%0A%20%20%20%20%20%20%20%20return%20gl.getSupportedExtensions().indexOf('WEBGL_compressed_texture_etc')%20!==%20-1%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Take%20configSeting%20which%20should%20be%20an%20array%20of%20possible%20values.%0A%20%20%20%20%20*%20If%20a%20value%20contains%20a%20criteria%20that%20is%20a%20match%20for%20this%20environment%20then%20return%20that%20value.%0A%20%20%20%20%20*%20Otherwise%20return%20the%20first%20value%20that%20doesn't%20have%20a%20criteria.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7B*%5B%5D%7D%20configSetting%20-%20Config%20setting%20which%20should%20contain%20a%20list%20of%20possible%20values%0A%20%20%20%20%20*%20@returns%20%7B*%7Cundefined%7D%20-%20The%20value%20from%20the%20list%20that%20best%20matches%20the%20criteria%20in%20the%20config%0A%20%20%20%20%20*/%0A%20%20%20%20function%20processAttrByCriteria%20(configSetting)%20%7B%0A%20%20%20%20%20%20%20%20let%20bestOption;%0A%20%20%20%20%20%20%20%20for%20(const%20item%20of%20configSetting)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(item.criteria)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(item.criteria.arch%20===%20'AppleSilicon'%20&&%20isAppleSilicon())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bestOption%20=%20item;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bestOption%20=%20item;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20bestOption%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20functionMap%20=%20%7B%0A%20%20%20%20%20%20%20%20/**%20Useful%20for%20debugging%20APIs%20in%20the%20wild,%20shouldn't%20be%20used%20*/%0A%20%20%20%20%20%20%20%20debug:%20(...args)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20console.log('debugger',%20...args);%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20no-debugger%0A%20%20%20%20%20%20%20%20%20%20%20%20debugger%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20noop:%20()%20=%3E%20%7B%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Handles%20the%20processing%20of%20a%20config%20setting.%0A%20%20%20%20%20*%20@param%20%7B*%7D%20configSetting%0A%20%20%20%20%20*%20@param%20%7B*%7D%20defaultValue%0A%20%20%20%20%20*%20@returns%0A%20%20%20%20%20*/%0A%20%20%20%20function%20processAttr%20(configSetting,%20defaultValue)%20%7B%0A%20%20%20%20%20%20%20%20if%20(configSetting%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20configSettingType%20=%20typeof%20configSetting;%0A%20%20%20%20%20%20%20%20switch%20(configSettingType)%20%7B%0A%20%20%20%20%20%20%20%20case%20'object':%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(Array.isArray(configSetting))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configSetting%20=%20processAttrByCriteria(configSetting);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!configSetting.type)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting.type%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting.functionName%20&&%20functionMap%5BconfigSetting.functionName%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20functionMap%5BconfigSetting.functionName%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting.type%20===%20'undefined')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20undefined%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20configSetting.value%0A%20%20%20%20%20%20%20%20default:%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20getStack%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20Error$1().stack%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@template%20%7Bobject%7D%20P%0A%20%20%20%20%20*%20@typedef%20%7Bobject%7D%20ProxyObject%3CP%3E%0A%20%20%20%20%20*%20@property%20%7B(target?:%20object,%20thisArg?:%20P,%20args?:%20object)%20=%3E%20void%7D%20apply%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@template%20%5BP=object%5D%0A%20%20%20%20%20*/%0A%20%20%20%20class%20DDGProxy%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureName%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BP%7D%20objectScope%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20property%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BProxyObject%3CP%3E%7D%20proxyObject%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20constructor%20(featureName,%20objectScope,%20property,%20proxyObject)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.objectScope%20=%20objectScope;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.property%20=%20property;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.featureName%20=%20featureName;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.camelFeatureName%20=%20camelcase(this.featureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20outputHandler%20=%20(...args)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20isExempt%20=%20shouldExemptMethod(this.camelFeatureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(debug)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20postDebugMessage(this.camelFeatureName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isProxy:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20action:%20isExempt%20?%20'ignore'%20:%20'restrict',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind:%20this.property,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack:%20getStack(),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args:%20JSON.stringify(args%5B2%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20normal%20return%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(isExempt)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20proxyObject.apply(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20getMethod%20=%20(target,%20prop,%20receiver)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(prop%20===%20'toString')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20method%20=%20Reflect.get(target,%20prop,%20receiver).bind(target);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(method,%20'toString',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20String.toString.bind(String.toString),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20method%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.get(target,%20prop,%20receiver)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this._native%20=%20objectScope%5Bproperty%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20handler%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20handler.apply%20=%20outputHandler;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20handler.get%20=%20getMethod;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.internal%20=%20new%20globalObj.Proxy(objectScope%5Bproperty%5D,%20handler);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Actually%20apply%20the%20proxy%20to%20the%20native%20property%0A%20%20%20%20%20%20%20%20overload%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.objectScope%5Bthis.property%5D%20=%20this.internal;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20postDebugMessage%20(feature,%20message)%20%7B%0A%20%20%20%20%20%20%20%20if%20(message.stack)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20%5B...getStackTraceOrigins(message.stack)%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20message.scriptOrigins%20=%20scriptOrigins;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20globalObj.postMessage(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20action:%20feature,%0A%20%20%20%20%20%20%20%20%20%20%20%20message%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20DDGReflect;%0A%20%20%20%20let%20DDGPromise;%0A%0A%20%20%20%20//%20Exports%20for%20usage%20where%20we%20have%20to%20cross%20the%20xray%20boundary:%20https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20DDGPromise%20=%20globalObj.Promise;%0A%20%20%20%20%20%20%20%20DDGReflect%20=%20globalObj.Reflect;%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20windowsSpecificFeatures%20=%20%5B'windowsPermissionUsage'%5D;%0A%0A%20%20%20%20function%20isWindowsSpecificFeature%20(featureName)%20%7B%0A%20%20%20%20%20%20%20%20return%20windowsSpecificFeatures.includes(featureName)%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20createCustomEvent%20(eventName,%20eventDetail)%20%7B%0A%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20possibly%20null%0A%20%20%20%20%20%20%20%20return%20new%20OriginalCustomEvent(eventName,%20eventDetail)%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20sendMessage%20(messageType,%20options)%20%7B%0A%20%20%20%20%20%20%20%20//%20FF%20&%20Chrome%0A%20%20%20%20%20%20%20%20return%20originalWindowDispatchEvent(createCustomEvent('sendMessageProxy'%20+%20messageSecret,%20%7B%20detail:%20%7B%20messageType,%20options%20%7D%20%7D))%0A%20%20%20%20%20%20%20%20//%20TBD%20other%20platforms%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20baseFeatures%20=%20/**%20@type%20%7Bconst%7D%20*/(%5B%0A%20%20%20%20%20%20%20%20'runtimeChecks',%0A%20%20%20%20%20%20%20%20'fingerprintingAudio',%0A%20%20%20%20%20%20%20%20'fingerprintingBattery',%0A%20%20%20%20%20%20%20%20'fingerprintingCanvas',%0A%20%20%20%20%20%20%20%20'cookie',%0A%20%20%20%20%20%20%20%20'googleRejected',%0A%20%20%20%20%20%20%20%20'gpc',%0A%20%20%20%20%20%20%20%20'fingerprintingHardware',%0A%20%20%20%20%20%20%20%20'referrer',%0A%20%20%20%20%20%20%20%20'fingerprintingScreenSize',%0A%20%20%20%20%20%20%20%20'fingerprintingTemporaryStorage',%0A%20%20%20%20%20%20%20%20'navigatorInterface',%0A%20%20%20%20%20%20%20%20'elementHiding',%0A%20%20%20%20%20%20%20%20'exceptionHandler'%0A%20%20%20%20%5D);%0A%0A%20%20%20%20const%20otherFeatures%20=%20/**%20@type%20%7Bconst%7D%20*/(%5B%0A%20%20%20%20%20%20%20%20'clickToLoad',%0A%20%20%20%20%20%20%20%20'windowsPermissionUsage',%0A%20%20%20%20%20%20%20%20'webCompat',%0A%20%20%20%20%20%20%20%20'duckPlayer'%0A%20%20%20%20%5D);%0A%0A%20%20%20%20/**%20@typedef%20%7BbaseFeatures%5Bnumber%5D%7CotherFeatures%5Bnumber%5D%7D%20FeatureName%20*/%0A%20%20%20%20/**%20@type%20%7BRecord%3Cstring,%20FeatureName%5B%5D%3E%7D%20*/%0A%20%20%20%20const%20platformSupport%20=%20%7B%0A%20%20%20%20%20%20%20%20apple:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'webCompat'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20android:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20windows:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'windowsPermissionUsage',%0A%20%20%20%20%20%20%20%20%20%20%20%20'duckPlayer'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20firefox:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'clickToLoad'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20chrome:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'clickToLoad'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20'chrome-mv3':%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'clickToLoad'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20integration:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20...otherFeatures%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Performance%20monitor,%20holds%20reference%20to%20PerformanceMark%20instances.%0A%20%20%20%20%20*/%0A%20%20%20%20class%20PerformanceMonitor%20%7B%0A%20%20%20%20%20%20%20%20constructor%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.marks%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Create%20performance%20marker%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20name%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPerformanceMark%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20mark%20(name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20mark%20=%20new%20PerformanceMark(name);%0A%20%20%20%20%20%20%20%20%20%20%20%20this.marks.push(mark);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20mark%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Measure%20all%20performance%20markers%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20measureAll%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.marks.forEach((mark)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mark.measure();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Tiny%20wrapper%20around%20performance.mark%20and%20performance.measure%0A%20%20%20%20%20*/%0A%20%20%20%20class%20PerformanceMark%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20name%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20constructor%20(name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.name%20=%20name;%0A%20%20%20%20%20%20%20%20%20%20%20%20performance.mark(this.name%20+%20'Start');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20end%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20performance.mark(this.name%20+%20'End');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20measure%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20performance.measure(this.name,%20this.name%20+%20'Start',%20this.name%20+%20'End');%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20_typeof$2(obj)%20%7B%20%22@babel/helpers%20-%20typeof%22;%20return%20_typeof$2%20=%20%22function%22%20==%20typeof%20Symbol%20&&%20%22symbol%22%20==%20typeof%20Symbol.iterator%20?%20function%20(obj)%20%7B%20return%20typeof%20obj;%20%7D%20:%20function%20(obj)%20%7B%20return%20obj%20&&%20%22function%22%20==%20typeof%20Symbol%20&&%20obj.constructor%20===%20Symbol%20&&%20obj%20!==%20Symbol.prototype%20?%20%22symbol%22%20:%20typeof%20obj;%20%7D,%20_typeof$2(obj);%20%7D%0A%20%20%20%20function%20isJSONArray(value)%20%7B%0A%20%20%20%20%20%20return%20Array.isArray(value);%0A%20%20%20%20%7D%0A%20%20%20%20function%20isJSONObject(value)%20%7B%0A%20%20%20%20%20%20return%20value%20!==%20null%20&&%20_typeof$2(value)%20===%20'object'%20&&%20value.constructor%20===%20Object%20//%20do%20not%20match%20on%20classes%20or%20Array%0A%20%20%20%20%20%20;%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20_typeof$1(obj)%20%7B%20%22@babel/helpers%20-%20typeof%22;%20return%20_typeof$1%20=%20%22function%22%20==%20typeof%20Symbol%20&&%20%22symbol%22%20==%20typeof%20Symbol.iterator%20?%20function%20(obj)%20%7B%20return%20typeof%20obj;%20%7D%20:%20function%20(obj)%20%7B%20return%20obj%20&&%20%22function%22%20==%20typeof%20Symbol%20&&%20obj.constructor%20===%20Symbol%20&&%20obj%20!==%20Symbol.prototype%20?%20%22symbol%22%20:%20typeof%20obj;%20%7D,%20_typeof$1(obj);%20%7D%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20deep%20equality%20of%20two%20JSON%20values,%20objects,%20or%20arrays%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20isEqual(a,%20b)%20%7B%0A%20%20%20%20%20%20//%20FIXME:%20this%20function%20will%20return%20false%20for%20two%20objects%20with%20the%20same%20keys%0A%20%20%20%20%20%20//%20%20but%20different%20order%20of%20keys%0A%20%20%20%20%20%20return%20JSON.stringify(a)%20===%20JSON.stringify(b);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Get%20all%20but%20the%20last%20items%20from%20an%20array%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20initial(array)%20%7B%0A%20%20%20%20%20%20return%20array.slice(0,%20array.length%20-%201);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Get%20the%20last%20item%20from%20an%20array%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20last(array)%20%7B%0A%20%20%20%20%20%20return%20array%5Barray.length%20-%201%5D;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20whether%20a%20value%20is%20an%20Object%20or%20an%20Array%20(and%20not%20a%20primitive%20JSON%20value)%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20isObjectOrArray(value)%20%7B%0A%20%20%20%20%20%20return%20_typeof$1(value)%20===%20'object'%20&&%20value%20!==%20null;%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20_typeof(obj)%20%7B%20%22@babel/helpers%20-%20typeof%22;%20return%20_typeof%20=%20%22function%22%20==%20typeof%20Symbol%20&&%20%22symbol%22%20==%20typeof%20Symbol.iterator%20?%20function%20(obj)%20%7B%20return%20typeof%20obj;%20%7D%20:%20function%20(obj)%20%7B%20return%20obj%20&&%20%22function%22%20==%20typeof%20Symbol%20&&%20obj.constructor%20===%20Symbol%20&&%20obj%20!==%20Symbol.prototype%20?%20%22symbol%22%20:%20typeof%20obj;%20%7D,%20_typeof(obj);%20%7D%0A%20%20%20%20function%20ownKeys(object,%20enumerableOnly)%20%7B%20var%20keys%20=%20Object.keys(object);%20if%20(Object.getOwnPropertySymbols)%20%7B%20var%20symbols%20=%20Object.getOwnPropertySymbols(object);%20enumerableOnly%20&&%20(symbols%20=%20symbols.filter(function%20(sym)%20%7B%20return%20Object.getOwnPropertyDescriptor(object,%20sym).enumerable;%20%7D)),%20keys.push.apply(keys,%20symbols);%20%7D%20return%20keys;%20%7D%0A%20%20%20%20function%20_objectSpread(target)%20%7B%20for%20(var%20i%20=%201;%20i%20%3C%20arguments.length;%20i++)%20%7B%20var%20source%20=%20null%20!=%20arguments%5Bi%5D%20?%20arguments%5Bi%5D%20:%20%7B%7D;%20i%20%25%202%20?%20ownKeys(Object(source),%20!0).forEach(function%20(key)%20%7B%20_defineProperty(target,%20key,%20source%5Bkey%5D);%20%7D)%20:%20Object.getOwnPropertyDescriptors%20?%20Object.defineProperties(target,%20Object.getOwnPropertyDescriptors(source))%20:%20ownKeys(Object(source)).forEach(function%20(key)%20%7B%20Object.defineProperty(target,%20key,%20Object.getOwnPropertyDescriptor(source,%20key));%20%7D);%20%7D%20return%20target;%20%7D%0A%20%20%20%20function%20_defineProperty(obj,%20key,%20value)%20%7B%20key%20=%20_toPropertyKey(key);%20if%20(key%20in%20obj)%20%7B%20Object.defineProperty(obj,%20key,%20%7B%20value:%20value,%20enumerable:%20true,%20configurable:%20true,%20writable:%20true%20%7D);%20%7D%20else%20%7B%20obj%5Bkey%5D%20=%20value;%20%7D%20return%20obj;%20%7D%0A%20%20%20%20function%20_toPropertyKey(arg)%20%7B%20var%20key%20=%20_toPrimitive(arg,%20%22string%22);%20return%20_typeof(key)%20===%20%22symbol%22%20?%20key%20:%20String(key);%20%7D%0A%20%20%20%20function%20_toPrimitive(input,%20hint)%20%7B%20if%20(_typeof(input)%20!==%20%22object%22%20%7C%7C%20input%20===%20null)%20return%20input;%20var%20prim%20=%20input%5BSymbol.toPrimitive%5D;%20if%20(prim%20!==%20undefined)%20%7B%20var%20res%20=%20prim.call(input,%20hint%20%7C%7C%20%22default%22);%20if%20(_typeof(res)%20!==%20%22object%22)%20return%20res;%20throw%20new%20TypeError(%22@@toPrimitive%20must%20return%20a%20primitive%20value.%22);%20%7D%20return%20(hint%20===%20%22string%22%20?%20String%20:%20Number)(input);%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Shallow%20clone%20of%20an%20Object,%20Array,%20or%20value%0A%20%20%20%20%20*%20Symbols%20are%20cloned%20too.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shallowClone(value)%20%7B%0A%20%20%20%20%20%20if%20(isJSONArray(value))%20%7B%0A%20%20%20%20%20%20%20%20//%20copy%20array%20items%0A%20%20%20%20%20%20%20%20var%20copy%20=%20value.slice();%0A%0A%20%20%20%20%20%20%20%20//%20copy%20all%20symbols%0A%20%20%20%20%20%20%20%20Object.getOwnPropertySymbols(value).forEach(function%20(symbol)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20copy%5Bsymbol%5D%20=%20value%5Bsymbol%5D;%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20return%20copy;%0A%20%20%20%20%20%20%7D%20else%20if%20(isJSONObject(value))%20%7B%0A%20%20%20%20%20%20%20%20//%20copy%20object%20properties%0A%20%20%20%20%20%20%20%20var%20_copy%20=%20_objectSpread(%7B%7D,%20value);%0A%0A%20%20%20%20%20%20%20%20//%20copy%20all%20symbols%0A%20%20%20%20%20%20%20%20Object.getOwnPropertySymbols(value).forEach(function%20(symbol)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20_copy%5Bsymbol%5D%20=%20value%5Bsymbol%5D;%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20return%20_copy;%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20return%20value;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Update%20a%20value%20in%20an%20object%20in%20an%20immutable%20way.%0A%20%20%20%20%20*%20If%20the%20value%20is%20unchanged,%20the%20original%20object%20will%20be%20returned%0A%20%20%20%20%20*/%0A%20%20%20%20function%20applyProp(object,%20key,%20value)%20%7B%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20if%20(object%5Bkey%5D%20===%20value)%20%7B%0A%20%20%20%20%20%20%20%20//%20return%20original%20object%20unchanged%20when%20the%20new%20value%20is%20identical%20to%20the%20old%20one%0A%20%20%20%20%20%20%20%20return%20object;%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20var%20updatedObject%20=%20shallowClone(object);%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20updatedObject%5Bkey%5D%20=%20value;%0A%20%20%20%20%20%20%20%20return%20updatedObject;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20get%20a%20nested%20property%20in%20an%20object%20or%20array%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@return%20Returns%20the%20field%20when%20found,%20or%20undefined%20when%20the%20path%20doesn't%20exist%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getIn(object,%20path)%20%7B%0A%20%20%20%20%20%20var%20value%20=%20object;%0A%20%20%20%20%20%20var%20i%20=%200;%0A%20%20%20%20%20%20while%20(i%20%3C%20path.length)%20%7B%0A%20%20%20%20%20%20%20%20if%20(isJSONObject(value))%20%7B%0A%20%20%20%20%20%20%20%20%20%20value%20=%20value%5Bpath%5Bi%5D%5D;%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(isJSONArray(value))%20%7B%0A%20%20%20%20%20%20%20%20%20%20value%20=%20value%5BparseInt(path%5Bi%5D)%5D;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20value%20=%20undefined;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20i++;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20return%20value;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20replace%20a%20nested%20property%20in%20an%20object%20with%20a%20new%20value%0A%20%20%20%20%20*%20without%20mutating%20the%20object%20itself.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20object%0A%20%20%20%20%20*%20@param%20path%0A%20%20%20%20%20*%20@param%20value%0A%20%20%20%20%20*%20@param%20%5BcreatePath=false%5D%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20If%20true,%20%60path%60%20will%20be%20created%20when%20(partly)%20missing%20in%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20the%20object.%20For%20correctly%20creating%20nested%20Arrays%20or%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Objects,%20the%20function%20relies%20on%20%60path%60%20containing%20number%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20in%20case%20of%20array%20indexes.%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20If%20false%20(default),%20an%20error%20will%20be%20thrown%20when%20the%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20path%20doesn't%20exist.%0A%20%20%20%20%20*%20@return%20Returns%20a%20new,%20updated%20object%20or%20array%0A%20%20%20%20%20*/%0A%20%20%20%20function%20setIn(object,%20path,%20value)%20%7B%0A%20%20%20%20%20%20var%20createPath%20=%20arguments.length%20%3E%203%20&&%20arguments%5B3%5D%20!==%20undefined%20?%20arguments%5B3%5D%20:%20false;%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20value;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20updatedValue%20=%20setIn(object%20?%20object%5Bkey%5D%20:%20undefined,%20path.slice(1),%20value,%20createPath);%0A%20%20%20%20%20%20if%20(isJSONObject(object)%20%7C%7C%20isJSONArray(object))%20%7B%0A%20%20%20%20%20%20%20%20return%20applyProp(object,%20key,%20updatedValue);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20if%20(createPath)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20newObject%20=%20IS_INTEGER_REGEX.test(key)%20?%20%5B%5D%20:%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20newObject%5Bkey%5D%20=%20updatedValue;%0A%20%20%20%20%20%20%20%20%20%20return%20newObject;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Path%20does%20not%20exist');%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20var%20IS_INTEGER_REGEX%20=%20/%5E%5Cd+$/;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20replace%20a%20nested%20property%20in%20an%20object%20with%20a%20new%20value%0A%20%20%20%20%20*%20without%20mutating%20the%20object%20itself.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@return%20%20Returns%20a%20new,%20updated%20object%20or%20array%0A%20%20%20%20%20*/%0A%20%20%20%20function%20updateIn(object,%20path,%20callback)%20%7B%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20callback(object);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(!isObjectOrArray(object))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Path%20doesn%5C't%20exist');%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20updatedValue%20=%20updateIn(object%5Bkey%5D,%20path.slice(1),%20callback);%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20applyProp(object,%20key,%20updatedValue);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20delete%20a%20nested%20property%20in%20an%20object%0A%20%20%20%20%20*%20without%20mutating%20the%20object%20itself.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@return%20Returns%20a%20new,%20updated%20object%20or%20array%0A%20%20%20%20%20*/%0A%20%20%20%20function%20deleteIn(object,%20path)%20%7B%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20object;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(!isObjectOrArray(object))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Path%20does%20not%20exist');%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(path.length%20===%201)%20%7B%0A%20%20%20%20%20%20%20%20var%20_key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20%20%20if%20(!(_key%20in%20object))%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20key%20doesn't%20exist.%20return%20object%20unchanged%0A%20%20%20%20%20%20%20%20%20%20return%20object;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20updatedObject%20=%20shallowClone(object);%0A%20%20%20%20%20%20%20%20%20%20if%20(isJSONArray(updatedObject))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20updatedObject.splice(parseInt(_key),%201);%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20if%20(isJSONObject(updatedObject))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20delete%20updatedObject%5B_key%5D;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20return%20updatedObject;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20updatedValue%20=%20deleteIn(object%5Bkey%5D,%20path.slice(1));%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20applyProp(object,%20key,%20updatedValue);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Insert%20a%20new%20item%20in%20an%20array%20at%20a%20specific%20index.%0A%20%20%20%20%20*%20Example%20usage:%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%20%20%20%20insertAt(%7Barr:%20%5B1,2,3%5D%7D,%20%5B'arr',%20'2'%5D,%20'inserted')%20%20//%20%5B1,2,'inserted',3%5D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20insertAt(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20var%20parentPath%20=%20path.slice(0,%20path.length%20-%201);%0A%20%20%20%20%20%20var%20index%20=%20path%5Bpath.length%20-%201%5D;%0A%20%20%20%20%20%20return%20updateIn(document,%20parentPath,%20function%20(items)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!Array.isArray(items))%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20TypeError('Array%20expected%20at%20path%20'%20+%20JSON.stringify(parentPath));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20updatedItems%20=%20shallowClone(items);%0A%20%20%20%20%20%20%20%20updatedItems.splice(parseInt(index),%200,%20value);%0A%20%20%20%20%20%20%20%20return%20updatedItems;%0A%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20whether%20a%20path%20exists%20in%20a%20JSON%20object%0A%20%20%20%20%20*%20@return%20Returns%20true%20if%20the%20path%20exists,%20else%20returns%20false%0A%20%20%20%20%20*/%0A%20%20%20%20function%20existsIn(document,%20path)%20%7B%0A%20%20%20%20%20%20if%20(document%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20true;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(document%20===%20null)%20%7B%0A%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20existsIn(document%5Bpath%5B0%5D%5D,%20path.slice(1));%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Parse%20a%20JSON%20Pointer%0A%20%20%20%20%20*/%0A%20%20%20%20function%20parseJSONPointer(pointer)%20%7B%0A%20%20%20%20%20%20var%20path%20=%20pointer.split('/');%0A%20%20%20%20%20%20path.shift();%20//%20remove%20the%20first%20empty%20entry%0A%0A%20%20%20%20%20%20return%20path.map(function%20(p)%20%7B%0A%20%20%20%20%20%20%20%20return%20p.replace(/~1/g,%20'/').replace(/~0/g,%20'~');%0A%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Compile%20a%20JSON%20Pointer%0A%20%20%20%20%20*/%0A%20%20%20%20function%20compileJSONPointer(path)%20%7B%0A%20%20%20%20%20%20return%20path.map(compileJSONPointerProp).join('');%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Compile%20a%20single%20path%20property%20from%20a%20JSONPath%0A%20%20%20%20%20*/%0A%20%20%20%20function%20compileJSONPointerProp(pathProp)%20%7B%0A%20%20%20%20%20%20return%20'/'%20+%20String(pathProp).replace(/~/g,%20'~0').replace(/%5C//g,%20'~1');%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Apply%20a%20patch%20to%20a%20JSON%20object%0A%20%20%20%20%20*%20The%20original%20JSON%20object%20will%20not%20be%20changed,%0A%20%20%20%20%20*%20instead,%20the%20patch%20is%20applied%20in%20an%20immutable%20way%0A%20%20%20%20%20*/%0A%20%20%20%20function%20immutableJSONPatch(document,%20operations,%20options)%20%7B%0A%20%20%20%20%20%20var%20updatedDocument%20=%20document;%0A%20%20%20%20%20%20for%20(var%20i%20=%200;%20i%20%3C%20operations.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20validateJSONPatchOperation(operations%5Bi%5D);%0A%20%20%20%20%20%20%20%20var%20operation%20=%20operations%5Bi%5D;%0A%0A%20%20%20%20%20%20%20%20//%20TODO:%20test%20before%0A%20%20%20%20%20%20%20%20if%20(options%20&&%20options.before)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20result%20=%20options.before(updatedDocument,%20operation);%0A%20%20%20%20%20%20%20%20%20%20if%20(result%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(result.document%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20result.document;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(result.json%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20deprecated%20since%20v5.0.0.%20Cleanup%20this%20warning%20some%20day%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Deprecation%20warning:%20returned%20object%20property%20%22.json%22%20has%20been%20renamed%20to%20%22.document%22');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(result.operation%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20operation%20=%20result.operation;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20previousDocument%20=%20updatedDocument;%0A%20%20%20%20%20%20%20%20var%20path%20=%20parsePath(updatedDocument,%20operation.path);%0A%20%20%20%20%20%20%20%20if%20(operation.op%20===%20'add')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20add(updatedDocument,%20path,%20operation.value);%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'remove')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20remove(updatedDocument,%20path);%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'replace')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20replace(updatedDocument,%20path,%20operation.value);%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'copy')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20copy(updatedDocument,%20path,%20parseFrom(operation.from));%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'move')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20move(updatedDocument,%20path,%20parseFrom(operation.from));%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'test')%20%7B%0A%20%20%20%20%20%20%20%20%20%20test(updatedDocument,%20path,%20operation.value);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Unknown%20JSONPatch%20operation%20'%20+%20JSON.stringify(operation));%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20TODO:%20test%20after%0A%20%20%20%20%20%20%20%20if%20(options%20&&%20options.after)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20_result%20=%20options.after(updatedDocument,%20operation,%20previousDocument);%0A%20%20%20%20%20%20%20%20%20%20if%20(_result%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20_result;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20return%20updatedDocument;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Replace%20an%20existing%20item%0A%20%20%20%20%20*/%0A%20%20%20%20function%20replace(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20return%20setIn(document,%20path,%20value);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Remove%20an%20item%20or%20property%0A%20%20%20%20%20*/%0A%20%20%20%20function%20remove(document,%20path)%20%7B%0A%20%20%20%20%20%20return%20deleteIn(document,%20path);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Add%20an%20item%20or%20property%0A%20%20%20%20%20*/%0A%20%20%20%20function%20add(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20if%20(isArrayItem(document,%20path))%20%7B%0A%20%20%20%20%20%20%20%20return%20insertAt(document,%20path,%20value);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20return%20setIn(document,%20path,%20value);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Copy%20a%20value%0A%20%20%20%20%20*/%0A%20%20%20%20function%20copy(document,%20path,%20from)%20%7B%0A%20%20%20%20%20%20var%20value%20=%20getIn(document,%20from);%0A%20%20%20%20%20%20if%20(isArrayItem(document,%20path))%20%7B%0A%20%20%20%20%20%20%20%20return%20insertAt(document,%20path,%20value);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20var%20_value%20=%20getIn(document,%20from);%0A%20%20%20%20%20%20%20%20return%20setIn(document,%20path,%20_value);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Move%20a%20value%0A%20%20%20%20%20*/%0A%20%20%20%20function%20move(document,%20path,%20from)%20%7B%0A%20%20%20%20%20%20var%20value%20=%20getIn(document,%20from);%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20removedJson%20=%20deleteIn(document,%20from);%0A%20%20%20%20%20%20return%20isArrayItem(removedJson,%20path)%20?%20insertAt(removedJson,%20path,%20value)%20:%20setIn(removedJson,%20path,%20value);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20whether%20the%20data%20contains%20the%20provided%20value%20at%20the%20specified%20path.%0A%20%20%20%20%20*%20Throws%20an%20error%20when%20the%20test%20fails%0A%20%20%20%20%20*/%0A%20%20%20%20function%20test(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20if%20(value%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error(%22Test%20failed:%20no%20value%20provided%20(path:%20%5C%22%22.concat(compileJSONPointer(path),%20%22%5C%22)%22));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(!existsIn(document,%20path))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error(%22Test%20failed:%20path%20not%20found%20(path:%20%5C%22%22.concat(compileJSONPointer(path),%20%22%5C%22)%22));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20actualValue%20=%20getIn(document,%20path);%0A%20%20%20%20%20%20if%20(!isEqual(actualValue,%20value))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error(%22Test%20failed,%20value%20differs%20(path:%20%5C%22%22.concat(compileJSONPointer(path),%20%22%5C%22)%22));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20function%20isArrayItem(document,%20path)%20%7B%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20parent%20=%20getIn(document,%20initial(path));%0A%20%20%20%20%20%20return%20Array.isArray(parent);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Resolve%20the%20path%20index%20of%20an%20array,%20resolves%20indexes%20'-'%0A%20%20%20%20%20*%20@returns%20Returns%20the%20resolved%20path%0A%20%20%20%20%20*/%0A%20%20%20%20function%20resolvePathIndex(document,%20path)%20%7B%0A%20%20%20%20%20%20if%20(last(path)%20!==%20'-')%20%7B%0A%20%20%20%20%20%20%20%20return%20path;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20parentPath%20=%20initial(path);%0A%20%20%20%20%20%20var%20parent%20=%20getIn(document,%20parentPath);%0A%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20parentPath.concat(parent.length);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Validate%20a%20JSONPatch%20operation.%0A%20%20%20%20%20*%20Throws%20an%20error%20when%20there%20is%20an%20issue%0A%20%20%20%20%20*/%0A%20%20%20%20function%20validateJSONPatchOperation(operation)%20%7B%0A%20%20%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20%20%20var%20ops%20=%20%5B'add',%20'remove',%20'replace',%20'copy',%20'move',%20'test'%5D;%0A%20%20%20%20%20%20if%20(!ops.includes(operation.op))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Unknown%20JSONPatch%20op%20'%20+%20JSON.stringify(operation.op));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(typeof%20operation.path%20!==%20'string')%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Required%20property%20%22path%22%20missing%20or%20not%20a%20string%20in%20operation%20'%20+%20JSON.stringify(operation));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(operation.op%20===%20'copy'%20%7C%7C%20operation.op%20===%20'move')%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20operation.from%20!==%20'string')%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Required%20property%20%22from%22%20missing%20or%20not%20a%20string%20in%20operation%20'%20+%20JSON.stringify(operation));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20function%20parsePath(document,%20pointer)%20%7B%0A%20%20%20%20%20%20return%20resolvePathIndex(document,%20parseJSONPointer(pointer));%0A%20%20%20%20%7D%0A%20%20%20%20function%20parseFrom(fromPointer)%20%7B%0A%20%20%20%20%20%20return%20parseJSONPointer(fromPointer);%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20constructor%20(featureName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.name%20=%20featureName;%0A%20%20%20%20%20%20%20%20%20%20%20%20this._args%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.monitor%20=%20new%20PerformanceMonitor();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bimport('./utils').Platform%7D%20platform%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20set%20platform%20(platform)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this._platform%20=%20platform;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20platform%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'Platform%20%7C%20undefined'%20is%20not%20assignable%20to%20type%20'Platform'%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._platform%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Get%20the%20value%20of%20a%20config%20setting.%0A%20%20%20%20%20%20%20%20%20*%20If%20the%20value%20is%20not%20set,%20return%20the%20default%20value.%0A%20%20%20%20%20%20%20%20%20*%20If%20the%20value%20is%20not%20an%20object,%20return%20the%20value.%0A%20%20%20%20%20%20%20%20%20*%20If%20the%20value%20is%20an%20object,%20check%20its%20type%20property.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20attrName%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bany%7D%20defaultValue%20-%20The%20default%20value%20to%20use%20if%20the%20config%20setting%20is%20not%20set%0A%20%20%20%20%20%20%20%20%20*%20@returns%20The%20value%20of%20the%20config%20setting%20or%20the%20default%20value%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getFeatureAttr%20(attrName,%20defaultValue)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20configSetting%20=%20this.getFeatureSetting(attrName);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20processAttr(configSetting,%20defaultValue)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureKeyName%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bany%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getFeatureSetting%20(featureKeyName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20result%20=%20this._getFeatureSetting();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(featureKeyName%20===%20'domains')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('domains%20is%20a%20reserved%20feature%20setting%20key%20name')%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domainMatch%20=%20%5B...this.matchDomainFeatureSetting('domains')%5D.sort((a,%20b)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20a.domain.length%20-%20b.domain.length%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20match%20of%20domainMatch)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(match.patchSettings%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20=%20immutableJSONPatch(result,%20match.patchSettings);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.error('Error%20applying%20patch%20settings',%20e);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20result?.%5BfeatureKeyName%5D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20_getFeatureSetting%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20camelFeatureName%20=%20camelcase(this.name);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._args.featureSettings?.%5BcamelFeatureName%5D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureKeyName%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getFeatureSettingEnabled%20(featureKeyName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20result%20=%20this.getFeatureSetting(featureKeyName);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20result%20===%20'enabled'%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureKeyName%0A%20%20%20%20%20%20%20%20%20*%20@return%20%7Bany%5B%5D%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20matchDomainFeatureSetting%20(featureKeyName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domains%20=%20this._getFeatureSetting()?.%5BfeatureKeyName%5D%20%7C%7C%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20domains.filter((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20matchHostname(this._args.site.domain,%20rule.domain)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20callInit%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20mark%20=%20this.monitor.mark(this.name%20+%20'CallInit');%0A%20%20%20%20%20%20%20%20%20%20%20%20this._args%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.platform%20=%20args.platform;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.init(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.measure();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20load%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20callLoad%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20mark%20=%20this.monitor.mark(this.name%20+%20'CallLoad');%0A%20%20%20%20%20%20%20%20%20%20%20%20this._args%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.platform%20=%20args.platform;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.load(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20measure%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this._args.debug)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.monitor.measureAll();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20update%20()%20%7B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Indent%20a%20code%20block%20using%20braces%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20string%0A%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20removeIndent%20(string)%20%7B%0A%20%20%20%20%20%20%20%20const%20lines%20=%20string.split('%5Cn');%0A%20%20%20%20%20%20%20%20const%20indentSize%20=%202;%0A%20%20%20%20%20%20%20%20let%20currentIndent%20=%200;%0A%20%20%20%20%20%20%20%20const%20indentedLines%20=%20lines.map((line)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(line.trim().startsWith('%7D'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentIndent%20-=%20indentSize;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20indentedLine%20=%20'%20'.repeat(currentIndent)%20+%20line.trim();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(line.trim().endsWith('%7B'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentIndent%20+=%20indentSize;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20indentedLine%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20return%20indentedLines.filter(a%20=%3E%20a.trim()).join('%5Cn')%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20lookup%20=%20%7B%7D;%0A%20%20%20%20function%20getOrGenerateIdentifier%20(path)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!(path%20in%20lookup))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20lookup%5Bpath%5D%20=%20generateAlphaIdentifier(Object.keys(lookup).length%20+%201);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20lookup%5Bpath%5D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20generateAlphaIdentifier%20(num)%20%7B%0A%20%20%20%20%20%20%20%20if%20(num%20%3C%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Input%20must%20be%20a%20positive%20integer')%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20charCodeOffset%20=%2097;%0A%20%20%20%20%20%20%20%20let%20identifier%20=%20'';%0A%20%20%20%20%20%20%20%20while%20(num%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20num--;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20remainder%20=%20num%20%25%2026;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20charCode%20=%20remainder%20+%20charCodeOffset;%0A%20%20%20%20%20%20%20%20%20%20%20%20identifier%20=%20String.fromCharCode(charCode)%20+%20identifier;%0A%20%20%20%20%20%20%20%20%20%20%20%20num%20=%20Math.floor(num%20/%2026);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20'_ddg_'%20+%20identifier%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7B*%7D%20scope%0A%20%20%20%20%20*%20@param%20%7BRecord%3Cstring,%20any%3E%7D%20outputs%0A%20%20%20%20%20*%20@returns%20%7BProxy%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20constructProxy%20(scope,%20outputs)%20%7B%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Expected%202%20arguments,%20but%20got%201%0A%20%20%20%20%20%20%20%20if%20(Object.is(scope))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Should%20not%20happen,%20but%20just%20in%20case%20fail%20safely%0A%20%20%20%20%20%20%20%20%20%20%20%20console.error('Runtime%20checks:%20Scope%20must%20be%20an%20object',%20scope,%20outputs);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20scope%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20new%20Proxy(scope,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20get%20(target,%20property,%20receiver)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20targetObj%20=%20target%5Bproperty%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20targetObj%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20(...args)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(target%5Bproperty%5D,%20target,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20property%20===%20'string'%20&&%20property%20in%20outputs)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.get(outputs,%20property,%20receiver)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.get(target,%20property,%20receiver)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20valToString%20(val)%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20val%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20val.toString()%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20JSON.stringify(val)%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Output%20scope%20variable%20definitions%20to%20arbitrary%20depth%0A%20%20%20%20%20*/%0A%20%20%20%20function%20stringifyScope%20(scope,%20scopePath)%20%7B%0A%20%20%20%20%20%20%20%20let%20output%20=%20'';%0A%20%20%20%20%20%20%20%20for%20(const%20%5Bkey,%20value%5D%20of%20scope)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20varOutName%20=%20getOrGenerateIdentifier(%5B...scopePath,%20key%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(value%20instanceof%20Map)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxyName%20=%20getOrGenerateIdentifier(%5B'_proxyFor_',%20varOutName%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7BproxyName%7D%20=%20$%7BscopePath.join('?.')%7D?.$%7Bkey%7D%20?%20$%7BscopePath.join('.')%7D.$%7Bkey%7D%20:%20Object.bind(null);%0A%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20keys%20=%20Array.from(value.keys());%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20stringifyScope(value,%20%5B...scopePath,%20key%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxyOut%20=%20keys.map((keyName)%20=%3E%20%60$%7BkeyName%7D:%20$%7BgetOrGenerateIdentifier(%5B...scopePath,%20key,%20keyName%5D)%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7BvarOutName%7D%20=%20constructProxy($%7BproxyName%7D,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20$%7BproxyOut.join(',%5Cn')%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20we're%20at%20the%20top%20level,%20we%20need%20to%20add%20the%20window%20and%20globalThis%20variables%20(Eg:%20let%20navigator%20=%20parentScope_navigator)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(scopePath.length%20===%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7Bkey%7D%20=%20$%7BvarOutName%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7BvarOutName%7D%20=%20$%7BvalToString(value)%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20output%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Code%20generates%20wrapping%20variables%20for%20code%20that%20is%20injected%20into%20the%20page%0A%20%20%20%20%20*%20@param%20%7B*%7D%20code%0A%20%20%20%20%20*%20@param%20%7B*%7D%20config%0A%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20wrapScriptCodeOverload%20(code,%20config)%20%7B%0A%20%20%20%20%20%20%20%20const%20processedConfig%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20for%20(const%20%5Bkey,%20value%5D%20of%20Object.entries(config))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Expected%202%20arguments,%20but%20got%201%0A%20%20%20%20%20%20%20%20%20%20%20%20processedConfig%5Bkey%5D%20=%20processAttr(value);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20//%20Don't%20do%20anything%20if%20the%20config%20is%20empty%0A%20%20%20%20%20%20%20%20if%20(Object.keys(processedConfig).length%20===%200)%20return%20code%0A%0A%20%20%20%20%20%20%20%20let%20prepend%20=%20'';%0A%20%20%20%20%20%20%20%20const%20aggregatedLookup%20=%20new%20Map();%0A%20%20%20%20%20%20%20%20let%20currentScope%20=%20null;%0A%20%20%20%20%20%20%20%20/*%20Convert%20the%20config%20into%20a%20map%20of%20scopePath%20-%3E%20%7B%20key:%20value%20%7D%20*/%0A%20%20%20%20%20%20%20%20for%20(const%20%5Bkey,%20value%5D%20of%20Object.entries(processedConfig))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20path%20=%20key.split('.');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20currentScope%20=%20aggregatedLookup;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20pathOut%20=%20path%5Bpath.length%20-%201%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Traverse%20the%20path%20and%20create%20the%20nested%20objects%0A%20%20%20%20%20%20%20%20%20%20%20%20path.slice(0,%20-1).forEach((pathPart,%20index)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!currentScope.has(pathPart))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentScope.set(pathPart,%20new%20Map());%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentScope%20=%20currentScope.get(pathPart);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20currentScope.set(pathOut,%20value);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20prepend%20+=%20stringifyScope(aggregatedLookup,%20%5B'parentScope'%5D);%0A%20%20%20%20%20%20%20%20//%20Stringify%20top%20level%20keys%0A%20%20%20%20%20%20%20%20const%20keysOut%20=%20%5B...aggregatedLookup.keys()%5D.map((keyName)%20=%3E%20%60$%7BkeyName%7D:%20$%7BgetOrGenerateIdentifier(%5B'parentScope',%20keyName%5D)%7D%60).join(',%5Cn');%0A%20%20%20%20%20%20%20%20prepend%20+=%20%60%0A%20%20%20%20const%20window%20=%20constructProxy(parentScope,%20%7B%0A%20%20%20%20%20%20%20%20$%7BkeysOut%7D%0A%20%20%20%20%7D);%0A%20%20%20%20const%20globalThis%20=%20constructProxy(parentScope,%20%7B%0A%20%20%20%20%20%20%20%20$%7BkeysOut%7D%0A%20%20%20%20%7D);%0A%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20return%20removeIndent(%60(function%20(parentScope)%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20DuckDuckGo%20Runtime%20Checks%20injected%20code.%0A%20%20%20%20%20%20%20%20%20*%20If%20you're%20reading%20this,%20you're%20probably%20trying%20to%20debug%20a%20site%20that%20is%20breaking%20due%20to%20our%20runtime%20checks.%0A%20%20%20%20%20%20%20%20%20*%20Please%20raise%20an%20issues%20on%20our%20GitHub%20repo:%20https://github.com/duckduckgo/content-scope-scripts/%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20$%7BconstructProxy.toString()%7D%0A%20%20%20%20%20%20%20%20$%7Bprepend%7D%0A%20%20%20%20%20%20%20%20$%7Bcode%7D%0A%20%20%20%20%7D)(globalThis)%0A%20%20%20%20%60)%0A%20%20%20%20%7D%0A%0A%20%20%20%20/*%20global%20TrustedScriptURL,%20TrustedScript%20*/%0A%0A%20%20%20%20let%20stackDomains%20=%20%5B%5D;%0A%20%20%20%20let%20matchAllStackDomains%20=%20false;%0A%20%20%20%20let%20taintCheck%20=%20false;%0A%20%20%20%20let%20initialCreateElement;%0A%20%20%20%20let%20tagModifiers%20=%20%7B%7D;%0A%20%20%20%20let%20shadowDomEnabled%20=%20false;%0A%20%20%20%20let%20scriptOverload%20=%20%7B%7D;%0A%20%20%20%20//%20Ignore%20monitoring%20properties%20that%20are%20only%20relevant%20once%20and%20already%20handled%0A%20%20%20%20const%20defaultIgnoreMonitorList%20=%20%5B'onerror',%20'onload'%5D;%0A%20%20%20%20let%20ignoreMonitorList%20=%20defaultIgnoreMonitorList;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20tagName%0A%20%20%20%20%20*%20@param%20%7B'property'%20%7C%20'attribute'%20%7C%20'handler'%20%7C%20'listener'%7D%20filterName%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20key%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shouldFilterKey%20(tagName,%20filterName,%20key)%20%7B%0A%20%20%20%20%20%20%20%20if%20(filterName%20===%20'attribute')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20key%20=%20key.toLowerCase();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20tagModifiers?.%5BtagName%5D?.filters?.%5BfilterName%5D?.includes(key)%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20elementRemovalTimeout;%0A%20%20%20%20const%20featureName%20=%20'runtimeChecks';%0A%20%20%20%20const%20taintSymbol%20=%20Symbol(featureName);%0A%20%20%20%20const%20supportedSinks%20=%20%5B'src'%5D;%0A%20%20%20%20//%20Store%20the%20original%20methods%20so%20we%20can%20call%20them%20without%20any%20side%20effects%0A%20%20%20%20const%20defaultElementMethods%20=%20%7B%0A%20%20%20%20%20%20%20%20setAttribute:%20HTMLElement.prototype.setAttribute,%0A%20%20%20%20%20%20%20%20getAttribute:%20HTMLElement.prototype.getAttribute,%0A%20%20%20%20%20%20%20%20removeAttribute:%20HTMLElement.prototype.removeAttribute,%0A%20%20%20%20%20%20%20%20remove:%20HTMLElement.prototype.remove,%0A%20%20%20%20%20%20%20%20removeChild:%20HTMLElement.prototype.removeChild%0A%20%20%20%20%7D;%0A%20%20%20%20const%20supportedTrustedTypes%20=%20'TrustedScriptURL'%20in%20window;%0A%0A%20%20%20%20class%20DDGRuntimeChecks%20extends%20HTMLElement%20%7B%0A%20%20%20%20%20%20%20%20#tagName%0A%20%20%20%20%20%20%20%20#el%0A%20%20%20%20%20%20%20%20#listeners%0A%20%20%20%20%20%20%20%20#connected%0A%20%20%20%20%20%20%20%20#sinks%0A%0A%20%20%20%20%20%20%20%20constructor%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20super();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#tagName%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#el%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#connected%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#sinks%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shadowDomEnabled)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20shadow%20=%20this.attachShadow(%7B%20mode:%20'open'%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20style%20=%20createStyleElement(%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20:host%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shadow.appendChild(style);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20This%20method%20is%20called%20once%20and%20externally%20so%20has%20to%20remain%20public.%0A%20%20%20%20%20%20%20%20%20**/%0A%20%20%20%20%20%20%20%20setTagName%20(tagName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#tagName%20=%20tagName;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Clear%20the%20method%20so%20it%20can't%20be%20called%20again%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS2790:%20The%20operand%20of%20a%20'delete'%20operator%20must%20be%20optional.%0A%20%20%20%20%20%20%20%20%20%20%20%20delete%20this.setTagName;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20connectedCallback%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Solves%20re-entrancy%20issues%20from%20React%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#connected)%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#connected%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this._transplantElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Restore%20the%20'this'%20object%20with%20the%20DDGRuntimeChecks%20prototype%20as%20sometimes%20pages%20will%20overwrite%20it.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.setPrototypeOf(this,%20DDGRuntimeChecks.prototype);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this._transplantElement();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20_monitorProperties%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Mutation%20oberver%20and%20observedAttributes%20don't%20work%20on%20property%20accessors%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20So%20instead%20we%20need%20to%20monitor%20all%20properties%20on%20the%20prototypes%20and%20forward%20them%20to%20the%20real%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20propertyNames%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20proto%20=%20Object.getPrototypeOf(el);%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20(proto%20&&%20proto%20!==%20Object.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20propertyNames.push(...Object.getOwnPropertyNames(proto));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proto%20=%20Object.getPrototypeOf(proto);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20classMethods%20=%20Object.getOwnPropertyNames(Object.getPrototypeOf(this));%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Filter%20away%20the%20methods%20we%20don't%20want%20to%20monitor%20from%20our%20own%20class%0A%20%20%20%20%20%20%20%20%20%20%20%20propertyNames%20=%20propertyNames.filter(prop%20=%3E%20!classMethods.includes(prop));%0A%20%20%20%20%20%20%20%20%20%20%20%20propertyNames.forEach(prop%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(prop%20===%20'constructor')%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20May%20throw,%20but%20this%20is%20best%20effort%20monitoring.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(this,%20prop,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el%5Bprop%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20set%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'property',%20prop))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(ignoreMonitorList.includes(prop))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5Bprop%5D%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20computeScriptOverload%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Short%20circuit%20if%20we%20don't%20have%20any%20script%20text%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el.textContent%20===%20'')%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Short%20circuit%20if%20we're%20in%20a%20trusted%20script%20environment%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TrustedScript%20is%20not%20defined%20in%20the%20TS%20lib%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedTrustedTypes%20&&%20el.textContent%20instanceof%20TrustedScript)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20el.textContent%20=%20wrapScriptCodeOverload(el.textContent,%20scriptOverload);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20The%20element%20has%20been%20moved%20to%20the%20DOM,%20so%20we%20can%20now%20reflect%20all%20changes%20to%20a%20real%20element.%0A%20%20%20%20%20%20%20%20%20*%20This%20is%20to%20allow%20us%20to%20interrogate%20the%20real%20element%20before%20it%20is%20moved%20to%20the%20DOM.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20_transplantElement%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Creeate%20the%20real%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20initialCreateElement.call(document,%20this.#tagName);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(taintCheck)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Add%20a%20symbol%20to%20the%20element%20so%20we%20can%20identify%20it%20as%20a%20runtime%20checked%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(el,%20taintSymbol,%20%7B%20value:%20true,%20configurable:%20false,%20enumerable:%20false,%20writable:%20false%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20attrs%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20attribute%20of%20this.getAttributeNames())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20attribute))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defaultElementMethods.setAttribute.call(el,%20attribute,%20this.getAttribute(attribute));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20props%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20props%20=%20Object.keys(this);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Nonce%20isn't%20enumerable%20so%20we%20need%20to%20add%20it%20manually%0A%20%20%20%20%20%20%20%20%20%20%20%20props.push('nonce');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20prop%20of%20props)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'property',%20prop))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5Bprop%5D%20=%20this%5Bprop%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20sink%20of%20supportedSinks)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#sinks%5Bsink%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5Bsink%5D%20=%20this.#sinks%5Bsink%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20listeners%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5B...args%5D%20of%20this.#listeners)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'listener',%20args%5B0%5D))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.addEventListener(...args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners%20=%20%5B%5D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20'on'%20event%20handlers%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20propName%20in%20this)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(propName.startsWith('on'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'handler',%20propName))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20prop%20=%20this%5BpropName%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20prop%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5BpropName%5D%20=%20prop;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Move%20all%20children%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20(this.firstChild)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.appendChild(this.firstChild);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#tagName%20===%20'script')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.computeScriptOverload(el);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Move%20the%20new%20element%20to%20the%20DOM%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.insertAdjacentElement('afterend',%20el);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%20console.warn(e);%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20this._monitorProperties(el);%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO%20pollyfill%20WeakRef%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#el%20=%20new%20WeakRef(el);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Delay%20removal%20of%20the%20custom%20element%20so%20if%20the%20script%20calls%20removeChild%20it%20will%20still%20be%20in%20the%20DOM%20and%20not%20throw.%0A%20%20%20%20%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.remove();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20elementRemovalTimeout);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20_getElement%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#el?.deref()%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Calls%20a%20method%20on%20the%20real%20element%20if%20it%20exists,%20otherwise%20calls%20the%20method%20on%20the%20DDGRuntimeChecks%20element.%0A%20%20%20%20%20%20%20%20%20*%20@template%20%7Bkeyof%20defaultElementMethods%7D%20E%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BE%7D%20method%0A%20%20%20%20%20%20%20%20%20*%20@param%20%20%7B...Parameters%3CdefaultElementMethods%5BE%5D%3E%7D%20args%0A%20%20%20%20%20%20%20%20%20*%20@return%20%7BReturnType%3CdefaultElementMethods%5BE%5D%3E%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20_callMethod%20(method,%20...args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultElementMethods%5Bmethod%5D.call(el,%20...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TS%20doesn't%20like%20the%20spread%20operator%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20super%5Bmethod%5D(...args)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/*%20Native%20DOM%20element%20methods%20we're%20capturing%20to%20supplant%20values%20into%20the%20constructed%20node%20or%20store%20data%20for.%20*/%0A%0A%20%20%20%20%20%20%20%20set%20src%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.src%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#sinks.src%20=%20value;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20src%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el.src%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TrustedScriptURL%20is%20not%20defined%20in%20the%20TS%20lib%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedTrustedTypes%20&&%20this.#sinks.src%20instanceof%20TrustedScriptURL)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#sinks.src.toString()%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#sinks.src%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20getAttribute%20(name,%20value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20name))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedSinks.includes(name))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Use%20Reflect%20to%20avoid%20infinite%20recursion%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.get(DDGRuntimeChecks.prototype,%20name,%20this)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('getAttribute',%20name,%20value)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20setAttribute%20(name,%20value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20name))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedSinks.includes(name))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Use%20Reflect%20to%20avoid%20infinite%20recursion%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.set(DDGRuntimeChecks.prototype,%20name,%20value,%20this)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('setAttribute',%20name,%20value)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20removeAttribute%20(name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20name))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedSinks.includes(name))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20this%5Bname%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('removeAttribute',%20name)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20addEventListener%20(...args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'listener',%20args%5B0%5D))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el.addEventListener(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners.push(%5B...args%5D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20removeEventListener%20(...args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'listener',%20args%5B0%5D))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el.removeEventListener(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners%20=%20this.#listeners.filter((listener)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20listener%5B0%5D%20!==%20args%5B0%5D%20%7C%7C%20listener%5B1%5D%20!==%20args%5B1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20toString%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20interfaceName%20=%20this.#tagName.charAt(0).toUpperCase()%20+%20this.#tagName.slice(1);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%60%5Bobject%20HTML$%7BinterfaceName%7DElement%5D%60%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20tagName%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#tagName.toUpperCase()%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20nodeName%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.tagName%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20remove%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('remove')%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TS%20node%20return%20here%0A%20%20%20%20%20%20%20%20removeChild%20(child)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('removeChild',%20child)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Overrides%20the%20instanceof%20checks%20to%20make%20the%20custom%20element%20interface%20pass%20an%20instanceof%20check%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20elementInterface%0A%20%20%20%20%20*/%0A%20%20%20%20function%20overloadInstanceOfChecks%20(elementInterface)%20%7B%0A%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20Proxy(elementInterface%5BSymbol.hasInstance%5D,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20apply%20(fn,%20scope,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(args%5B0%5D%20instanceof%20DDGRuntimeChecks)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(fn,%20scope,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20//%20May%20throw,%20but%20we%20can%20ignore%20it%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(elementInterface,%20Symbol.hasInstance,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20proxy%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%20catch%20%7B%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Returns%20true%20if%20the%20tag%20should%20be%20intercepted%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20tagName%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shouldInterrogate%20(tagName)%20%7B%0A%20%20%20%20%20%20%20%20const%20interestingTags%20=%20%5B'script'%5D;%0A%20%20%20%20%20%20%20%20if%20(!interestingTags.includes(tagName))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(matchAllStackDomains)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20isInterrogatingDebugMessage('matchedAllStackDomain');%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(taintCheck%20&&%20document.currentScript?.%5BtaintSymbol%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20isInterrogatingDebugMessage('taintCheck');%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20%5B...getStackTraceOrigins(stack)%5D;%0A%20%20%20%20%20%20%20%20const%20interestingHost%20=%20scriptOrigins.find(origin%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20stackDomains.some(rule%20=%3E%20matchHostname(origin,%20rule.domain))%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20const%20isInterestingHost%20=%20!!interestingHost;%0A%20%20%20%20%20%20%20%20if%20(isInterestingHost)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20isInterrogatingDebugMessage('matchedStackDomain',%20interestingHost,%20stack,%20scriptOrigins);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20isInterestingHost%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isInterrogatingDebugMessage%20(matchType,%20matchedStackDomain,%20stack,%20scriptOrigins)%20%7B%0A%20%20%20%20%20%20%20%20postDebugMessage('runtimeChecks',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20matchedStackDomain,%0A%20%20%20%20%20%20%20%20%20%20%20%20matchType,%0A%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins,%0A%20%20%20%20%20%20%20%20%20%20%20%20stack%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20overrideCreateElement%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20Document.prototype,%20'createElement',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20apply%20(fn,%20scope,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.length%20%3E=%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20String()%20is%20used%20to%20coerce%20the%20value%20to%20a%20string%20(For:%20ProseMirror/prosemirror-model/src/to_dom.ts)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20initialTagName%20=%20String(args%5B0%5D).toLowerCase();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldInterrogate(initialTagName))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args%5B0%5D%20=%20'ddg-runtime-checks';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20Reflect.apply(fn,%20scope,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.setTagName(initialTagName);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(fn,%20scope,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20proxy.overload();%0A%20%20%20%20%20%20%20%20initialCreateElement%20=%20proxy._native;%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20RuntimeChecks%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20load%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20This%20shouldn't%20happen,%20but%20if%20it%20does%20we%20don't%20want%20to%20break%20the%20page%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TS%20node%20return%20here%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20customElements.define('ddg-runtime-checks',%20DDGRuntimeChecks);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20enabled%20=%20this.getFeatureSettingEnabled('matchAllDomains');%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!enabled)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enabled%20=%20this.matchDomainFeatureSetting('domains').length%20%3E%200;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!enabled)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20taintCheck%20=%20this.getFeatureSettingEnabled('taintCheck');%0A%20%20%20%20%20%20%20%20%20%20%20%20matchAllStackDomains%20=%20this.getFeatureSettingEnabled('matchAllStackDomains');%0A%20%20%20%20%20%20%20%20%20%20%20%20stackDomains%20=%20this.getFeatureSetting('stackDomains')%20%7C%7C%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20elementRemovalTimeout%20=%20this.getFeatureSetting('elementRemovalTimeout')%20%7C%7C%201000;%0A%20%20%20%20%20%20%20%20%20%20%20%20tagModifiers%20=%20this.getFeatureSetting('tagModifiers')%20%7C%7C%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20shadowDomEnabled%20=%20this.getFeatureSettingEnabled('shadowDom')%20%7C%7C%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20scriptOverload%20=%20this.getFeatureSetting('scriptOverload')%20%7C%7C%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20ignoreMonitorList%20=%20this.getFeatureSetting('ignoreMonitorList')%20%7C%7C%20defaultIgnoreMonitorList;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideCreateElement();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.getFeatureSettingEnabled('overloadInstanceOf'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20overloadInstanceOfChecks(HTMLScriptElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.getFeatureSettingEnabled('injectGlobalStyles'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20injectGlobalStyles(%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ddg-runtime-checks%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20@ts-nocheck%0A%20%20%20%20%20%20%20%20const%20sjcl%20=%20(()%20=%3E%20%7B%0A%20%20%20%20/*jslint%20indent:%202,%20bitwise:%20false,%20nomen:%20false,%20plusplus:%20false,%20white:%20false,%20regexp:%20false%20*/%0A%20%20%20%20/*global%20document,%20window,%20escape,%20unescape,%20module,%20require,%20Uint32Array%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20The%20Stanford%20Javascript%20Crypto%20Library,%20top-level%20namespace.%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*/%0A%20%20%20%20var%20sjcl%20=%20%7B%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Symmetric%20ciphers.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20cipher:%20%7B%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Hash%20functions.%20%20Right%20now%20only%20SHA256%20is%20implemented.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20hash:%20%7B%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Key%20exchange%20functions.%20%20Right%20now%20only%20SRP%20is%20implemented.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20keyexchange:%20%7B%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Cipher%20modes%20of%20operation.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20mode:%20%7B%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Miscellaneous.%20%20HMAC%20and%20PBKDF2.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20misc:%20%7B%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Bit%20array%20encoders%20and%20decoders.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20*%20@description%0A%20%20%20%20%20%20%20*%20The%20members%20of%20this%20namespace%20are%20functions%20which%20translate%20between%0A%20%20%20%20%20%20%20*%20SJCL's%20bitArrays%20and%20other%20objects%20(usually%20strings).%20%20Because%20it%0A%20%20%20%20%20%20%20*%20isn't%20always%20clear%20which%20direction%20is%20encoding%20and%20which%20is%20decoding,%0A%20%20%20%20%20%20%20*%20the%20method%20names%20are%20%22fromBits%22%20and%20%22toBits%22.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20codec:%20%7B%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Exceptions.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20exception:%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Ciphertext%20is%20corrupt.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20corrupt:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22CORRUPT:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Invalid%20parameter.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20invalid:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22INVALID:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Bug%20or%20missing%20feature%20in%20SJCL.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20bug:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22BUG:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Something%20isn't%20ready.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20notReady:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22NOT%20READY:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%20%20%20%20/**%20@fileOverview%20Arrays%20of%20bits,%20encoded%20as%20arrays%20of%20Numbers.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Arrays%20of%20bits,%20encoded%20as%20arrays%20of%20Numbers.%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*%20@description%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20These%20objects%20are%20the%20currency%20accepted%20by%20SJCL's%20crypto%20functions.%0A%20%20%20%20%20*%20%3C/p%3E%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20Most%20of%20our%20crypto%20primitives%20operate%20on%20arrays%20of%204-byte%20words%20internally,%0A%20%20%20%20%20*%20but%20many%20of%20them%20can%20take%20arguments%20that%20are%20not%20a%20multiple%20of%204%20bytes.%0A%20%20%20%20%20*%20This%20library%20encodes%20arrays%20of%20bits%20(whose%20size%20need%20not%20be%20a%20multiple%20of%208%0A%20%20%20%20%20*%20bits)%20as%20arrays%20of%2032-bit%20words.%20%20The%20bits%20are%20packed,%20big-endian,%20into%20an%0A%20%20%20%20%20*%20array%20of%20words,%2032%20bits%20at%20a%20time.%20%20Since%20the%20words%20are%20double-precision%0A%20%20%20%20%20*%20floating%20point%20numbers,%20they%20fit%20some%20extra%20data.%20%20We%20use%20this%20(in%20a%20private,%0A%20%20%20%20%20*%20possibly-changing%20manner)%20to%20encode%20the%20number%20of%20bits%20actually%20%20present%0A%20%20%20%20%20*%20in%20the%20last%20word%20of%20the%20array.%0A%20%20%20%20%20*%20%3C/p%3E%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20Because%20bitwise%20ops%20clear%20this%20out-of-band%20data,%20these%20arrays%20can%20be%20passed%0A%20%20%20%20%20*%20to%20ciphers%20like%20AES%20which%20want%20arrays%20of%20words.%0A%20%20%20%20%20*%20%3C/p%3E%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.bitArray%20=%20%7B%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Array%20slices%20in%20units%20of%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array%20to%20slice.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20bstart%20The%20offset%20to%20the%20start%20of%20the%20slice,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20bend%20The%20offset%20to%20the%20end%20of%20the%20slice,%20in%20bits.%20%20If%20this%20is%20undefined,%0A%20%20%20%20%20%20%20*%20slice%20until%20the%20end%20of%20the%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20requested%20slice.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20bitSlice:%20function%20(a,%20bstart,%20bend)%20%7B%0A%20%20%20%20%20%20%20%20a%20=%20sjcl.bitArray._shiftRight(a.slice(bstart/32),%2032%20-%20(bstart%20&%2031)).slice(1);%0A%20%20%20%20%20%20%20%20return%20(bend%20===%20undefined)%20?%20a%20:%20sjcl.bitArray.clamp(a,%20bend-bstart);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Extract%20a%20number%20packed%20into%20a%20bit%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array%20to%20slice.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20bstart%20The%20offset%20to%20the%20start%20of%20the%20slice,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20blength%20The%20length%20of%20the%20number%20to%20extract.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20requested%20slice.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20extract:%20function(a,%20bstart,%20blength)%20%7B%0A%20%20%20%20%20%20%20%20//%20FIXME:%20this%20Math.floor%20is%20not%20necessary%20at%20all,%20but%20for%20some%20reason%0A%20%20%20%20%20%20%20%20//%20seems%20to%20suppress%20a%20bug%20in%20the%20Chromium%20JIT.%0A%20%20%20%20%20%20%20%20var%20x,%20sh%20=%20Math.floor((-bstart-blength)%20&%2031);%0A%20%20%20%20%20%20%20%20if%20((bstart%20+%20blength%20-%201%20%5E%20bstart)%20&%20-32)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20it%20crosses%20a%20boundary%0A%20%20%20%20%20%20%20%20%20%20x%20=%20(a%5Bbstart/32%7C0%5D%20%3C%3C%20(32%20-%20sh))%20%5E%20(a%5Bbstart/32+1%7C0%5D%20%3E%3E%3E%20sh);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20within%20a%20single%20word%0A%20%20%20%20%20%20%20%20%20%20x%20=%20a%5Bbstart/32%7C0%5D%20%3E%3E%3E%20sh;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20x%20&%20((1%3C%3Cblength)%20-%201);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Concatenate%20two%20bit%20arrays.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a1%20The%20first%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a2%20The%20second%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20concatenation%20of%20a1%20and%20a2.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20concat:%20function%20(a1,%20a2)%20%7B%0A%20%20%20%20%20%20%20%20if%20(a1.length%20===%200%20%7C%7C%20a2.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20a1.concat(a2);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20last%20=%20a1%5Ba1.length-1%5D,%20shift%20=%20sjcl.bitArray.getPartial(last);%0A%20%20%20%20%20%20%20%20if%20(shift%20===%2032)%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20a1.concat(a2);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20sjcl.bitArray._shiftRight(a2,%20shift,%20last%7C0,%20a1.slice(0,a1.length-1));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Find%20the%20length%20of%20an%20array%20of%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20length%20of%20a,%20in%20bits.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20bitLength:%20function%20(a)%20%7B%0A%20%20%20%20%20%20%20%20var%20l%20=%20a.length,%20x;%0A%20%20%20%20%20%20%20%20if%20(l%20===%200)%20%7B%20return%200;%20%7D%0A%20%20%20%20%20%20%20%20x%20=%20a%5Bl%20-%201%5D;%0A%20%20%20%20%20%20%20%20return%20(l-1)%20*%2032%20+%20sjcl.bitArray.getPartial(x);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Truncate%20an%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20len%20The%20length%20to%20truncate%20to,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20A%20new%20array,%20truncated%20to%20len%20bits.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20clamp:%20function%20(a,%20len)%20%7B%0A%20%20%20%20%20%20%20%20if%20(a.length%20*%2032%20%3C%20len)%20%7B%20return%20a;%20%7D%0A%20%20%20%20%20%20%20%20a%20=%20a.slice(0,%20Math.ceil(len%20/%2032));%0A%20%20%20%20%20%20%20%20var%20l%20=%20a.length;%0A%20%20%20%20%20%20%20%20len%20=%20len%20&%2031;%0A%20%20%20%20%20%20%20%20if%20(l%20%3E%200%20&&%20len)%20%7B%0A%20%20%20%20%20%20%20%20%20%20a%5Bl-1%5D%20=%20sjcl.bitArray.partial(len,%20a%5Bl-1%5D%20&%200x80000000%20%3E%3E%20(len-1),%201);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20a;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Make%20a%20partial%20word%20for%20a%20bit%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20len%20The%20number%20of%20bits%20in%20the%20word.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20x%20The%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20%5B_end=0%5D%20Pass%201%20if%20x%20has%20already%20been%20shifted%20to%20the%20high%20side.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20partial%20word.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20partial:%20function%20(len,%20x,%20_end)%20%7B%0A%20%20%20%20%20%20%20%20if%20(len%20===%2032)%20%7B%20return%20x;%20%7D%0A%20%20%20%20%20%20%20%20return%20(_end%20?%20x%7C0%20:%20x%20%3C%3C%20(32-len))%20+%20len%20*%200x10000000000;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Get%20the%20number%20of%20bits%20used%20by%20a%20partial%20word.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20x%20The%20partial%20word.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20number%20of%20bits%20used%20by%20the%20partial%20word.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20getPartial:%20function%20(x)%20%7B%0A%20%20%20%20%20%20%20%20return%20Math.round(x/0x10000000000)%20%7C%7C%2032;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Compare%20two%20arrays%20for%20equality%20in%20a%20predictable%20amount%20of%20time.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20first%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20b%20The%20second%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7Bboolean%7D%20true%20if%20a%20==%20b;%20false%20otherwise.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20equal:%20function%20(a,%20b)%20%7B%0A%20%20%20%20%20%20%20%20if%20(sjcl.bitArray.bitLength(a)%20!==%20sjcl.bitArray.bitLength(b))%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20x%20=%200,%20i;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Ca.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20x%20%7C=%20a%5Bi%5D%5Eb%5Bi%5D;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20(x%20===%200);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%20Shift%20an%20array%20right.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array%20to%20shift.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20shift%20The%20number%20of%20bits%20to%20shift.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20%5Bcarry=0%5D%20A%20byte%20to%20carry%20in%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20%5Bout=%5B%5D%5D%20An%20array%20to%20prepend%20to%20the%20output.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_shiftRight:%20function%20(a,%20shift,%20carry,%20out)%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20last2=0,%20shift2;%0A%20%20%20%20%20%20%20%20if%20(out%20===%20undefined)%20%7B%20out%20=%20%5B%5D;%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20for%20(;%20shift%20%3E=%2032;%20shift%20-=%2032)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(carry);%0A%20%20%20%20%20%20%20%20%20%20carry%20=%200;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(shift%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20out.concat(a);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Ca.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(carry%20%7C%20a%5Bi%5D%3E%3E%3Eshift);%0A%20%20%20%20%20%20%20%20%20%20carry%20=%20a%5Bi%5D%20%3C%3C%20(32-shift);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20last2%20=%20a.length%20?%20a%5Ba.length-1%5D%20:%200;%0A%20%20%20%20%20%20%20%20shift2%20=%20sjcl.bitArray.getPartial(last2);%0A%20%20%20%20%20%20%20%20out.push(sjcl.bitArray.partial(shift+shift2%20&%2031,%20(shift%20+%20shift2%20%3E%2032)%20?%20carry%20:%20out.pop(),1));%0A%20%20%20%20%20%20%20%20return%20out;%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%20xor%20a%20block%20of%204%20words%20together.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_xor4:%20function(x,y)%20%7B%0A%20%20%20%20%20%20%20%20return%20%5Bx%5B0%5D%5Ey%5B0%5D,x%5B1%5D%5Ey%5B1%5D,x%5B2%5D%5Ey%5B2%5D,x%5B3%5D%5Ey%5B3%5D%5D;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%20byteswap%20a%20word%20array%20inplace.%0A%20%20%20%20%20%20%20*%20(does%20not%20handle%20partial%20words)%0A%20%20%20%20%20%20%20*%20@param%20%7Bsjcl.bitArray%7D%20a%20word%20array%0A%20%20%20%20%20%20%20*%20@return%20%7Bsjcl.bitArray%7D%20byteswapped%20array%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20byteswapM:%20function(a)%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20v,%20m%20=%200xff00;%0A%20%20%20%20%20%20%20%20for%20(i%20=%200;%20i%20%3C%20a.length;%20++i)%20%7B%0A%20%20%20%20%20%20%20%20%20%20v%20=%20a%5Bi%5D;%0A%20%20%20%20%20%20%20%20%20%20a%5Bi%5D%20=%20(v%20%3E%3E%3E%2024)%20%7C%20((v%20%3E%3E%3E%208)%20&%20m)%20%7C%20((v%20&%20m)%20%3C%3C%208)%20%7C%20(v%20%3C%3C%2024);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20a;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%20%20%20%20/**%20@fileOverview%20Bit%20array%20codec%20implementations.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20UTF-8%20strings%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.codec.utf8String%20=%20%7B%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20bitArray%20to%20a%20UTF-8%20string.%20*/%0A%20%20%20%20%20%20fromBits:%20function%20(arr)%20%7B%0A%20%20%20%20%20%20%20%20var%20out%20=%20%22%22,%20bl%20=%20sjcl.bitArray.bitLength(arr),%20i,%20tmp;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Cbl/8;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20if%20((i&3)%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%20arr%5Bi/4%5D;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20out%20+=%20String.fromCharCode(tmp%20%3E%3E%3E%208%20%3E%3E%3E%208%20%3E%3E%3E%208);%0A%20%20%20%20%20%20%20%20%20%20tmp%20%3C%3C=%208;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20decodeURIComponent(escape(out));%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20UTF-8%20string%20to%20a%20bitArray.%20*/%0A%20%20%20%20%20%20toBits:%20function%20(str)%20%7B%0A%20%20%20%20%20%20%20%20str%20=%20unescape(encodeURIComponent(str));%0A%20%20%20%20%20%20%20%20var%20out%20=%20%5B%5D,%20i,%20tmp=0;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Cstr.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20tmp%20=%20tmp%20%3C%3C%208%20%7C%20str.charCodeAt(i);%0A%20%20%20%20%20%20%20%20%20%20if%20((i&3)%20===%203)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20out.push(tmp);%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%200;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(i&3)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(sjcl.bitArray.partial(8*(i&3),%20tmp));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20out;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%20%20%20%20/**%20@fileOverview%20Bit%20array%20codec%20implementations.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hexadecimal%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.codec.hex%20=%20%7B%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20bitArray%20to%20a%20hex%20string.%20*/%0A%20%20%20%20%20%20fromBits:%20function%20(arr)%20%7B%0A%20%20%20%20%20%20%20%20var%20out%20=%20%22%22,%20i;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Carr.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out%20+=%20((arr%5Bi%5D%7C0)+0xF00000000000).toString(16).substr(4);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20out.substr(0,%20sjcl.bitArray.bitLength(arr)/4);//.replace(/(.%7B8%7D)/g,%20%22$1%20%22);%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20hex%20string%20to%20a%20bitArray.%20*/%0A%20%20%20%20%20%20toBits:%20function%20(str)%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20out=%5B%5D,%20len;%0A%20%20%20%20%20%20%20%20str%20=%20str.replace(/%5Cs%7C0x/g,%20%22%22);%0A%20%20%20%20%20%20%20%20len%20=%20str.length;%0A%20%20%20%20%20%20%20%20str%20=%20str%20+%20%2200000000%22;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Cstr.length;%20i+=8)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(parseInt(str.substr(i,8),16)%5E0);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20sjcl.bitArray.clamp(out,%20len*4);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%20@fileOverview%20Javascript%20SHA-256%20implementation.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20An%20older%20version%20of%20this%20implementation%20is%20available%20in%20the%20public%0A%20%20%20%20%20*%20domain,%20but%20this%20one%20is%20(c)%20Emily%20Stark,%20Mike%20Hamburg,%20Dan%20Boneh,%0A%20%20%20%20%20*%20Stanford%20University%202008-2010%20and%20BSD-licensed%20for%20liability%0A%20%20%20%20%20*%20reasons.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20Special%20thanks%20to%20Aldo%20Cortesi%20for%20pointing%20out%20several%20bugs%20in%0A%20%20%20%20%20*%20this%20code.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Context%20for%20a%20SHA-256%20operation%20in%20progress.%0A%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.hash.sha256%20=%20function%20(hash)%20%7B%0A%20%20%20%20%20%20if%20(!this._key%5B0%5D)%20%7B%20this._precompute();%20%7D%0A%20%20%20%20%20%20if%20(hash)%20%7B%0A%20%20%20%20%20%20%20%20this._h%20=%20hash._h.slice(0);%0A%20%20%20%20%20%20%20%20this._buffer%20=%20hash._buffer.slice(0);%0A%20%20%20%20%20%20%20%20this._length%20=%20hash._length;%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20this.reset();%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hash%20a%20string%20or%20an%20array%20of%20words.%0A%20%20%20%20%20*%20@static%0A%20%20%20%20%20*%20@param%20%7BbitArray%7CString%7D%20data%20the%20data%20to%20hash.%0A%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20hash%20value,%20an%20array%20of%2016%20big-endian%20words.%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.hash.sha256.hash%20=%20function%20(data)%20%7B%0A%20%20%20%20%20%20return%20(new%20sjcl.hash.sha256()).update(data).finalize();%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.hash.sha256.prototype%20=%20%7B%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20The%20hash's%20block%20size,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@constant%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20blockSize:%20512,%0A%20%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Reset%20the%20hash%20state.%0A%20%20%20%20%20%20%20*%20@return%20this%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20reset:function%20()%20%7B%0A%20%20%20%20%20%20%20%20this._h%20=%20this._init.slice(0);%0A%20%20%20%20%20%20%20%20this._buffer%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20this._length%20=%200;%0A%20%20%20%20%20%20%20%20return%20this;%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Input%20several%20words%20to%20the%20hash.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7CString%7D%20data%20the%20data%20to%20hash.%0A%20%20%20%20%20%20%20*%20@return%20this%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20update:%20function%20(data)%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20data%20===%20%22string%22)%20%7B%0A%20%20%20%20%20%20%20%20%20%20data%20=%20sjcl.codec.utf8String.toBits(data);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20i,%20b%20=%20this._buffer%20=%20sjcl.bitArray.concat(this._buffer,%20data),%0A%20%20%20%20%20%20%20%20%20%20%20%20ol%20=%20this._length,%0A%20%20%20%20%20%20%20%20%20%20%20%20nl%20=%20this._length%20=%20ol%20+%20sjcl.bitArray.bitLength(data);%0A%20%20%20%20%20%20%20%20if%20(nl%20%3E%209007199254740991)%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20sjcl.exception.invalid(%22Cannot%20hash%20more%20than%202%5E53%20-%201%20bits%22);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20(typeof%20Uint32Array%20!==%20'undefined')%20%7B%0A%20%20%20%20%09var%20c%20=%20new%20Uint32Array(b);%0A%20%20%20%20%20%20%20%20%09var%20j%20=%200;%0A%20%20%20%20%20%20%20%20%09for%20(i%20=%20512+ol%20-%20((512+ol)%20&%20511);%20i%20%3C=%20nl;%20i+=%20512)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%09%20%20%20%20this._block(c.subarray(16%20*%20j,%2016%20*%20(j+1)));%0A%20%20%20%20%20%20%20%20%20%20%09%20%20%20%20j%20+=%201;%0A%20%20%20%20%20%20%20%20%09%7D%0A%20%20%20%20%20%20%20%20%09b.splice(0,%2016%20*%20j);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09for%20(i%20=%20512+ol%20-%20((512+ol)%20&%20511);%20i%20%3C=%20nl;%20i+=%20512)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%09%20%20%20%20this._block(b.splice(0,16));%0A%20%20%20%20%20%20%20%20%20%20%09%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20this;%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Complete%20hashing%20and%20output%20the%20hash%20value.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20hash%20value,%20an%20array%20of%208%20big-endian%20words.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20finalize:function%20()%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20b%20=%20this._buffer,%20h%20=%20this._h;%0A%0A%20%20%20%20%20%20%20%20//%20Round%20out%20and%20push%20the%20buffer%0A%20%20%20%20%20%20%20%20b%20=%20sjcl.bitArray.concat(b,%20%5Bsjcl.bitArray.partial(1,1)%5D);%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20//%20Round%20out%20the%20buffer%20to%20a%20multiple%20of%2016%20words,%20less%20the%202%20length%20words.%0A%20%20%20%20%20%20%20%20for%20(i%20=%20b.length%20+%202;%20i%20&%2015;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20b.push(0);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20//%20append%20the%20length%0A%20%20%20%20%20%20%20%20b.push(Math.floor(this._length%20/%200x100000000));%0A%20%20%20%20%20%20%20%20b.push(this._length%20%7C%200);%0A%0A%20%20%20%20%20%20%20%20while%20(b.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this._block(b.splice(0,16));%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20this.reset();%0A%20%20%20%20%20%20%20%20return%20h;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20The%20SHA-256%20initialization%20vector,%20to%20be%20precomputed.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_init:%5B%5D,%0A%20%20%20%20%20%20/*%0A%20%20%20%20%20%20_init:%5B0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19%5D,%0A%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20The%20SHA-256%20hash%20key,%20to%20be%20precomputed.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_key:%5B%5D,%0A%20%20%20%20%20%20/*%0A%20%20%20%20%20%20_key:%0A%20%20%20%20%20%20%20%20%5B0x428a2f98,%200x71374491,%200xb5c0fbcf,%200xe9b5dba5,%200x3956c25b,%200x59f111f1,%200x923f82a4,%200xab1c5ed5,%0A%20%20%20%20%20%20%20%20%200xd807aa98,%200x12835b01,%200x243185be,%200x550c7dc3,%200x72be5d74,%200x80deb1fe,%200x9bdc06a7,%200xc19bf174,%0A%20%20%20%20%20%20%20%20%200xe49b69c1,%200xefbe4786,%200x0fc19dc6,%200x240ca1cc,%200x2de92c6f,%200x4a7484aa,%200x5cb0a9dc,%200x76f988da,%0A%20%20%20%20%20%20%20%20%200x983e5152,%200xa831c66d,%200xb00327c8,%200xbf597fc7,%200xc6e00bf3,%200xd5a79147,%200x06ca6351,%200x14292967,%0A%20%20%20%20%20%20%20%20%200x27b70a85,%200x2e1b2138,%200x4d2c6dfc,%200x53380d13,%200x650a7354,%200x766a0abb,%200x81c2c92e,%200x92722c85,%0A%20%20%20%20%20%20%20%20%200xa2bfe8a1,%200xa81a664b,%200xc24b8b70,%200xc76c51a3,%200xd192e819,%200xd6990624,%200xf40e3585,%200x106aa070,%0A%20%20%20%20%20%20%20%20%200x19a4c116,%200x1e376c08,%200x2748774c,%200x34b0bcb5,%200x391c0cb3,%200x4ed8aa4a,%200x5b9cca4f,%200x682e6ff3,%0A%20%20%20%20%20%20%20%20%200x748f82ee,%200x78a5636f,%200x84c87814,%200x8cc70208,%200x90befffa,%200xa4506ceb,%200xbef9a3f7,%200xc67178f2%5D,%0A%20%20%20%20%20%20*/%0A%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Function%20to%20precompute%20_init%20and%20_key.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_precompute:%20function%20()%20%7B%0A%20%20%20%20%20%20%20%20var%20i%20=%200,%20prime%20=%202,%20factor,%20isPrime;%0A%0A%20%20%20%20%20%20%20%20function%20frac(x)%20%7B%20return%20(x-Math.floor(x))%20*%200x100000000%20%7C%200;%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20(;%20i%3C64;%20prime++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20isPrime%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20for%20(factor=2;%20factor*factor%20%3C=%20prime;%20factor++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(prime%20%25%20factor%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20isPrime%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20break;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20if%20(isPrime)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%3C8)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20this._init%5Bi%5D%20=%20frac(Math.pow(prime,%201/2));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this._key%5Bi%5D%20=%20frac(Math.pow(prime,%201/3));%0A%20%20%20%20%20%20%20%20%20%20%20%20i++;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Perform%20one%20cycle%20of%20SHA-256.%0A%20%20%20%20%20%20%20*%20@param%20%7BUint32Array%7CbitArray%7D%20w%20one%20block%20of%20words.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_block:function%20(w)%20%7B%20%20%0A%20%20%20%20%20%20%20%20var%20i,%20tmp,%20a,%20b,%0A%20%20%20%20%20%20%20%20%20%20h%20=%20this._h,%0A%20%20%20%20%20%20%20%20%20%20k%20=%20this._key,%0A%20%20%20%20%20%20%20%20%20%20h0%20=%20h%5B0%5D,%20h1%20=%20h%5B1%5D,%20h2%20=%20h%5B2%5D,%20h3%20=%20h%5B3%5D,%0A%20%20%20%20%20%20%20%20%20%20h4%20=%20h%5B4%5D,%20h5%20=%20h%5B5%5D,%20h6%20=%20h%5B6%5D,%20h7%20=%20h%5B7%5D;%0A%0A%20%20%20%20%20%20%20%20/*%20Rationale%20for%20placement%20of%20%7C0%20:%0A%20%20%20%20%20%20%20%20%20*%20If%20a%20value%20can%20overflow%20is%20original%2032%20bits%20by%20a%20factor%20of%20more%20than%20a%20few%0A%20%20%20%20%20%20%20%20%20*%20million%20(2%5E23%20ish),%20there%20is%20a%20possibility%20that%20it%20might%20overflow%20the%0A%20%20%20%20%20%20%20%20%20*%2053-bit%20mantissa%20and%20lose%20precision.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20To%20avoid%20this,%20we%20clamp%20back%20to%2032%20bits%20by%20%7C'ing%20with%200%20on%20any%20value%20that%0A%20%20%20%20%20%20%20%20%20*%20propagates%20around%20the%20loop,%20and%20on%20the%20hash%20state%20h%5B%5D.%20%20I%20don't%20believe%0A%20%20%20%20%20%20%20%20%20*%20that%20the%20clamps%20on%20h4%20and%20on%20h0%20are%20strictly%20necessary,%20but%20it's%20close%0A%20%20%20%20%20%20%20%20%20*%20(for%20h4%20anyway),%20and%20better%20safe%20than%20sorry.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20The%20clamps%20on%20h%5B%5D%20are%20necessary%20for%20the%20output%20to%20be%20correct%20even%20in%20the%0A%20%20%20%20%20%20%20%20%20*%20common%20case%20and%20for%20short%20inputs.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3C64;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20load%20up%20the%20input%20word%20for%20this%20round%0A%20%20%20%20%20%20%20%20%20%20if%20(i%3C16)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%20w%5Bi%5D;%0A%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%20%20=%20w%5B(i+1%20)%20&%2015%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20b%20%20%20=%20w%5B(i+14)%20&%2015%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%20w%5Bi&15%5D%20=%20((a%3E%3E%3E7%20%20%5E%20a%3E%3E%3E18%20%5E%20a%3E%3E%3E3%20%20%5E%20a%3C%3C25%20%5E%20a%3C%3C14)%20+%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(b%3E%3E%3E17%20%5E%20b%3E%3E%3E19%20%5E%20b%3E%3E%3E10%20%5E%20b%3C%3C15%20%5E%20b%3C%3C13)%20+%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w%5Bi&15%5D%20+%20w%5B(i+9)%20&%2015%5D)%20%7C%200;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20tmp%20=%20(tmp%20+%20h7%20+%20(h4%3E%3E%3E6%20%5E%20h4%3E%3E%3E11%20%5E%20h4%3E%3E%3E25%20%5E%20h4%3C%3C26%20%5E%20h4%3C%3C21%20%5E%20h4%3C%3C7)%20+%20%20(h6%20%5E%20h4&(h5%5Eh6))%20+%20k%5Bi%5D);%20//%20%7C%200;%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20//%20shift%20register%0A%20%20%20%20%20%20%20%20%20%20h7%20=%20h6;%20h6%20=%20h5;%20h5%20=%20h4;%0A%20%20%20%20%20%20%20%20%20%20h4%20=%20h3%20+%20tmp%20%7C%200;%0A%20%20%20%20%20%20%20%20%20%20h3%20=%20h2;%20h2%20=%20h1;%20h1%20=%20h0;%0A%0A%20%20%20%20%20%20%20%20%20%20h0%20=%20(tmp%20+%20%20((h1&h2)%20%5E%20(h3&(h1%5Eh2)))%20+%20(h1%3E%3E%3E2%20%5E%20h1%3E%3E%3E13%20%5E%20h1%3E%3E%3E22%20%5E%20h1%3C%3C30%20%5E%20h1%3C%3C19%20%5E%20h1%3C%3C10))%20%7C%200;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20h%5B0%5D%20=%20h%5B0%5D+h0%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B1%5D%20=%20h%5B1%5D+h1%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B2%5D%20=%20h%5B2%5D+h2%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B3%5D%20=%20h%5B3%5D+h3%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B4%5D%20=%20h%5B4%5D+h4%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B5%5D%20=%20h%5B5%5D+h5%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B6%5D%20=%20h%5B6%5D+h6%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B7%5D%20=%20h%5B7%5D+h7%20%7C%200;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%0A%20%20%20%20/**%20@fileOverview%20HMAC%20implementation.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%20HMAC%20with%20the%20specified%20hash%20function.%0A%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20*%20@param%20%7BbitArray%7D%20key%20the%20key%20for%20HMAC.%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20%5BHash=sjcl.hash.sha256%5D%20The%20hash%20function%20to%20use.%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.misc.hmac%20=%20function%20(key,%20Hash)%20%7B%0A%20%20%20%20%20%20this._hash%20=%20Hash%20=%20Hash%20%7C%7C%20sjcl.hash.sha256;%0A%20%20%20%20%20%20var%20exKey%20=%20%5B%5B%5D,%5B%5D%5D,%20i,%0A%20%20%20%20%20%20%20%20%20%20bs%20=%20Hash.prototype.blockSize%20/%2032;%0A%20%20%20%20%20%20this._baseHash%20=%20%5Bnew%20Hash(),%20new%20Hash()%5D;%0A%0A%20%20%20%20%20%20if%20(key.length%20%3E%20bs)%20%7B%0A%20%20%20%20%20%20%20%20key%20=%20Hash.hash(key);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20for%20(i=0;%20i%3Cbs;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20exKey%5B0%5D%5Bi%5D%20=%20key%5Bi%5D%5E0x36363636;%0A%20%20%20%20%20%20%20%20exKey%5B1%5D%5Bi%5D%20=%20key%5Bi%5D%5E0x5C5C5C5C;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20this._baseHash%5B0%5D.update(exKey%5B0%5D);%0A%20%20%20%20%20%20this._baseHash%5B1%5D.update(exKey%5B1%5D);%0A%20%20%20%20%20%20this._resultHash%20=%20new%20Hash(this._baseHash%5B0%5D);%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%20HMAC%20with%20the%20specified%20hash%20function.%20%20Also%20called%20encrypt%20since%20it's%20a%20prf.%0A%20%20%20%20%20*%20@param%20%7BbitArray%7CString%7D%20data%20The%20data%20to%20mac.%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.misc.hmac.prototype.encrypt%20=%20sjcl.misc.hmac.prototype.mac%20=%20function%20(data)%20%7B%0A%20%20%20%20%20%20if%20(!this._updated)%20%7B%0A%20%20%20%20%20%20%20%20this.update(data);%0A%20%20%20%20%20%20%20%20return%20this.digest(data);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20sjcl.exception.invalid(%22encrypt%20on%20already%20updated%20hmac%20called!%22);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.misc.hmac.prototype.reset%20=%20function%20()%20%7B%0A%20%20%20%20%20%20this._resultHash%20=%20new%20this._hash(this._baseHash%5B0%5D);%0A%20%20%20%20%20%20this._updated%20=%20false;%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.misc.hmac.prototype.update%20=%20function%20(data)%20%7B%0A%20%20%20%20%20%20this._updated%20=%20true;%0A%20%20%20%20%20%20this._resultHash.update(data);%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.misc.hmac.prototype.digest%20=%20function%20()%20%7B%0A%20%20%20%20%20%20var%20w%20=%20this._resultHash.finalize(),%20result%20=%20new%20(this._hash)(this._baseHash%5B1%5D).update(w).finalize();%0A%0A%20%20%20%20%20%20this.reset();%0A%0A%20%20%20%20%20%20return%20result;%0A%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20return%20sjcl;%0A%20%20%20%20%20%20%7D)();%0A%0A%20%20%20%20function%20getDataKeySync%20(sessionKey,%20domainKey,%20inputData)%20%7B%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20new-cap%0A%20%20%20%20%20%20%20%20const%20hmac%20=%20new%20sjcl.misc.hmac(sjcl.codec.utf8String.toBits(sessionKey%20+%20domainKey),%20sjcl.hash.sha256);%0A%20%20%20%20%20%20%20%20return%20sjcl.codec.hex.fromBits(hmac.encrypt(inputData))%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingAudio%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20sessionKey,%20site%20%7D%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domainKey%20=%20site.domain;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureName%20=%20'fingerprinting-audio';%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20In%20place%20modify%20array%20data%20to%20remove%20fingerprinting%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20transformArrayData%20(channelData,%20domainKey,%20sessionKey,%20thisArg)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20%7B%20audioKey%20%7D%20=%20getCachedResponse(thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!audioKey)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20cdSum%20=%200;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20k%20in%20channelData)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cdSum%20+=%20channelData%5Bk%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20the%20buffer%20is%20blank,%20skip%20adding%20data%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cdSum%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20audioKey%20=%20getDataKeySync(sessionKey,%20domainKey,%20cdSum);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setCache(thisArg,%20args,%20audioKey);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20iterateDataKey(audioKey,%20(item,%20byte)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20itemAudioIndex%20=%20item%20%25%20channelData.length;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20factor%20=%20byte%20*%200.0000001;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(byte%20%5E%200x1)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20factor%20=%200%20-%20factor;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20channelData%5BitemAudioIndex%5D%20=%20channelData%5BitemAudioIndex%5D%20+%20factor;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20copyFromChannelProxy%20=%20new%20DDGProxy(featureName,%20AudioBuffer.prototype,%20'copyFromChannel',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%5Bsource,%20channelNumber,%20startInChannel%5D%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20This%20is%20implemented%20in%20a%20different%20way%20to%20canvas%20purely%20because%20calling%20the%20function%20copied%20the%20original%20value,%20which%20is%20not%20ideal%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(//%20If%20channelNumber%20is%20longer%20than%20arrayBuffer%20number%20of%20channels%20then%20call%20the%20default%20method%20to%20throw%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20channelNumber%20%3E%20thisArg.numberOfChannels%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20startInChannel%20is%20longer%20than%20the%20arrayBuffer%20length%20then%20call%20the%20default%20method%20to%20throw%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20startInChannel%20%3E%20thisArg.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20normal%20return%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Call%20the%20protected%20getChannelData%20we%20implement,%20slice%20from%20the%20startInChannel%20value%20and%20assign%20to%20the%20source%20array%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20thisArg.getChannelData(channelNumber).slice(startInChannel).forEach((val,%20index)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20source%5Bindex%5D%20=%20val;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20copyFromChannelProxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cacheExpiry%20=%2060;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cacheData%20=%20new%20WeakMap();%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20getCachedResponse%20(thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20data%20=%20cacheData.get(thisArg);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20timeNow%20=%20Date.now();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(data%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.args%20===%20JSON.stringify(args)%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.expires%20%3E%20timeNow)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.expires%20=%20timeNow%20+%20cacheExpiry;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cacheData.set(thisArg,%20data);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20data%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%20audioKey:%20null%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20setCache%20(thisArg,%20args,%20audioKey)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cacheData.set(thisArg,%20%7B%20args:%20JSON.stringify(args),%20expires:%20Date.now()%20+%20cacheExpiry,%20audioKey%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20getChannelDataProxy%20=%20new%20DDGProxy(featureName,%20AudioBuffer.prototype,%20'getChannelData',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20normal%20return%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20channelData%20=%20DDGReflect.apply(target,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Anything%20we%20do%20here%20should%20be%20caught%20and%20ignored%20silently%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transformArrayData(channelData,%20domainKey,%20sessionKey,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20channelData%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20getChannelDataProxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20audioMethods%20=%20%5B'getByteTimeDomainData',%20'getFloatTimeDomainData',%20'getByteFrequencyData',%20'getFloatFrequencyData'%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20audioMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20AnalyserNode.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DDGReflect.apply(target,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Anything%20we%20do%20here%20should%20be%20caught%20and%20ignored%20silently%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transformArrayData(args%5B0%5D,%20domainKey,%20sessionKey,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Overwrites%20the%20Battery%20API%20if%20present%20in%20the%20browser.%0A%20%20%20%20%20*%20It%20will%20return%20the%20values%20defined%20in%20the%20getBattery%20function%20to%20the%20client,%0A%20%20%20%20%20*%20as%20well%20as%20prevent%20any%20script%20from%20listening%20to%20events.%0A%20%20%20%20%20*/%0A%20%20%20%20class%20FingerprintingBattery%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(globalThis.navigator.getBattery)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20BatteryManager%20=%20globalThis.BatteryManager;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20spoofedValues%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20charging:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20chargingTime:%200,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20dischargingTime:%20Infinity,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20level:%201%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20eventProperties%20=%20%5B'onchargingchange',%20'onchargingtimechange',%20'ondischargingtimechange',%20'onlevelchange'%5D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5Bprop,%20val%5D%20of%20Object.entries(spoofedValues))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(BatteryManager.prototype,%20prop,%20%7B%20get:%20()%20=%3E%20val%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20eventProp%20of%20eventProperties)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(BatteryManager.prototype,%20eventProp,%20%7B%20get:%20()%20=%3E%20null%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20var%20commonjsGlobal%20=%20typeof%20globalThis%20!==%20'undefined'%20?%20globalThis%20:%20typeof%20window%20!==%20'undefined'%20?%20window%20:%20typeof%20global%20!==%20'undefined'%20?%20global%20:%20typeof%20self%20!==%20'undefined'%20?%20self%20:%20%7B%7D;%0A%0A%20%20%20%20function%20getDefaultExportFromCjs%20(x)%20%7B%0A%20%20%20%20%09return%20x%20&&%20x.__esModule%20&&%20Object.prototype.hasOwnProperty.call(x,%20'default')%20?%20x%5B'default'%5D%20:%20x;%0A%20%20%20%20%7D%0A%0A%20%20%20%20var%20alea$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20alea$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20port%20of%20an%20algorithm%20by%20Johannes%20Baag%C3%B8e%20%3Cbaagoe@baagoe.com%3E,%202010%0A%20%20%20%20%09//%20http://baagoe.com/en/RandomMusings/javascript/%0A%20%20%20%20%09//%20https://github.com/nquinlan/better-random-numbers-for-javascript-mirror%0A%20%20%20%20%09//%20Original%20work%20is%20under%20MIT%20license%20-%0A%0A%20%20%20%20%09//%20Copyright%20(C)%202010%20by%20Johannes%20Baag%C3%B8e%20%3Cbaagoe@baagoe.org%3E%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20Permission%20is%20hereby%20granted,%20free%20of%20charge,%20to%20any%20person%20obtaining%20a%20copy%0A%20%20%20%20%09//%20of%20this%20software%20and%20associated%20documentation%20files%20(the%20%22Software%22),%20to%20deal%0A%20%20%20%20%09//%20in%20the%20Software%20without%20restriction,%20including%20without%20limitation%20the%20rights%0A%20%20%20%20%09//%20to%20use,%20copy,%20modify,%20merge,%20publish,%20distribute,%20sublicense,%20and/or%20sell%0A%20%20%20%20%09//%20copies%20of%20the%20Software,%20and%20to%20permit%20persons%20to%20whom%20the%20Software%20is%0A%20%20%20%20%09//%20furnished%20to%20do%20so,%20subject%20to%20the%20following%20conditions:%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20The%20above%20copyright%20notice%20and%20this%20permission%20notice%20shall%20be%20included%20in%0A%20%20%20%20%09//%20all%20copies%20or%20substantial%20portions%20of%20the%20Software.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20THE%20SOFTWARE%20IS%20PROVIDED%20%22AS%20IS%22,%20WITHOUT%20WARRANTY%20OF%20ANY%20KIND,%20EXPRESS%20OR%0A%20%20%20%20%09//%20IMPLIED,%20INCLUDING%20BUT%20NOT%20LIMITED%20TO%20THE%20WARRANTIES%20OF%20MERCHANTABILITY,%0A%20%20%20%20%09//%20FITNESS%20FOR%20A%20PARTICULAR%20PURPOSE%20AND%20NONINFRINGEMENT.%20IN%20NO%20EVENT%20SHALL%20THE%0A%20%20%20%20%09//%20AUTHORS%20OR%20COPYRIGHT%20HOLDERS%20BE%20LIABLE%20FOR%20ANY%20CLAIM,%20DAMAGES%20OR%20OTHER%0A%20%20%20%20%09//%20LIABILITY,%20WHETHER%20IN%20AN%20ACTION%20OF%20CONTRACT,%20TORT%20OR%20OTHERWISE,%20ARISING%20FROM,%0A%20%20%20%20%09//%20OUT%20OF%20OR%20IN%20CONNECTION%20WITH%20THE%20SOFTWARE%20OR%20THE%20USE%20OR%20OTHER%20DEALINGS%20IN%0A%20%20%20%20%09//%20THE%20SOFTWARE.%0A%0A%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20Alea(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20mash%20=%20Mash();%0A%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t%20=%202091639%20*%20me.s0%20+%20me.c%20*%202.3283064365386963e-10;%20//%202%5E-32%0A%20%20%20%20%09%20%20%20%20me.s0%20=%20me.s1;%0A%20%20%20%20%09%20%20%20%20me.s1%20=%20me.s2;%0A%20%20%20%20%09%20%20%20%20return%20me.s2%20=%20t%20-%20(me.c%20=%20t%20%7C%200);%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20//%20Apply%20the%20seeding%20algorithm%20from%20Baagoe.%0A%20%20%20%20%09%20%20me.c%20=%201;%0A%20%20%20%20%09%20%20me.s0%20=%20mash('%20');%0A%20%20%20%20%09%20%20me.s1%20=%20mash('%20');%0A%20%20%20%20%09%20%20me.s2%20=%20mash('%20');%0A%20%20%20%20%09%20%20me.s0%20-=%20mash(seed);%0A%20%20%20%20%09%20%20if%20(me.s0%20%3C%200)%20%7B%20me.s0%20+=%201;%20%7D%0A%20%20%20%20%09%20%20me.s1%20-=%20mash(seed);%0A%20%20%20%20%09%20%20if%20(me.s1%20%3C%200)%20%7B%20me.s1%20+=%201;%20%7D%0A%20%20%20%20%09%20%20me.s2%20-=%20mash(seed);%0A%20%20%20%20%09%20%20if%20(me.s2%20%3C%200)%20%7B%20me.s2%20+=%201;%20%7D%0A%20%20%20%20%09%20%20mash%20=%20null;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.c%20=%20f.c;%0A%20%20%20%20%09%20%20t.s0%20=%20f.s0;%0A%20%20%20%20%09%20%20t.s1%20=%20f.s1;%0A%20%20%20%20%09%20%20t.s2%20=%20f.s2;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20Alea(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.int32%20=%20function()%20%7B%20return%20(xg.next()%20*%200x100000000)%20%7C%200;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20return%20prng()%20+%20(prng()%20*%200x200000%20%7C%200)%20*%201.1102230246251565e-16;%20//%202%5E-53%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20Mash()%20%7B%0A%20%20%20%20%09%20%20var%20n%20=%200xefc8249d;%0A%0A%20%20%20%20%09%20%20var%20mash%20=%20function(data)%20%7B%0A%20%20%20%20%09%20%20%20%20data%20=%20String(data);%0A%20%20%20%20%09%20%20%20%20for%20(var%20i%20=%200;%20i%20%3C%20data.length;%20i++)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20n%20+=%20data.charCodeAt(i);%0A%20%20%20%20%09%20%20%20%20%20%20var%20h%20=%200.02519603282416938%20*%20n;%0A%20%20%20%20%09%20%20%20%20%20%20n%20=%20h%20%3E%3E%3E%200;%0A%20%20%20%20%09%20%20%20%20%20%20h%20-=%20n;%0A%20%20%20%20%09%20%20%20%20%20%20h%20*=%20n;%0A%20%20%20%20%09%20%20%20%20%20%20n%20=%20h%20%3E%3E%3E%200;%0A%20%20%20%20%09%20%20%20%20%20%20h%20-=%20n;%0A%20%20%20%20%09%20%20%20%20%20%20n%20+=%20h%20*%200x100000000;%20//%202%5E32%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20return%20(n%20%3E%3E%3E%200)%20*%202.3283064365386963e-10;%20//%202%5E-32%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20return%20mash;%0A%20%20%20%20%09%7D%0A%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.alea%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(alea$1));%0A%0A%20%20%20%20var%20aleaExports%20=%20alea$1.exports;%0A%0A%20%20%20%20var%20xor128$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xor128$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22xor128%22%20prng%20algorithm%20by%0A%20%20%20%20%09//%20George%20Marsaglia.%20%20See%20http://www.jstatsoft.org/v08/i14/paper%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20strseed%20=%20'';%0A%0A%20%20%20%20%09%20%20me.x%20=%200;%0A%20%20%20%20%09%20%20me.y%20=%200;%0A%20%20%20%20%09%20%20me.z%20=%200;%0A%20%20%20%20%09%20%20me.w%20=%200;%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t%20=%20me.x%20%5E%20(me.x%20%3C%3C%2011);%0A%20%20%20%20%09%20%20%20%20me.x%20=%20me.y;%0A%20%20%20%20%09%20%20%20%20me.y%20=%20me.z;%0A%20%20%20%20%09%20%20%20%20me.z%20=%20me.w;%0A%20%20%20%20%09%20%20%20%20return%20me.w%20%5E=%20(me.w%20%3E%3E%3E%2019)%20%5E%20t%20%5E%20(t%20%3E%3E%3E%208);%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Integer%20seed.%0A%20%20%20%20%09%20%20%20%20me.x%20=%20seed;%0A%20%20%20%20%09%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20//%20String%20seed.%0A%20%20%20%20%09%20%20%20%20strseed%20+=%20seed;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20Mix%20in%20string%20seed,%20then%20discard%20an%20initial%20batch%20of%2064%20values.%0A%20%20%20%20%09%20%20for%20(var%20k%20=%200;%20k%20%3C%20strseed.length%20+%2064;%20k++)%20%7B%0A%20%20%20%20%09%20%20%20%20me.x%20%5E=%20strseed.charCodeAt(k)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.x%20=%20f.x;%0A%20%20%20%20%09%20%20t.y%20=%20f.y;%0A%20%20%20%20%09%20%20t.z%20=%20f.z;%0A%20%20%20%20%09%20%20t.w%20=%20f.w;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xor128%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xor128$1));%0A%0A%20%20%20%20var%20xor128Exports%20=%20xor128$1.exports;%0A%0A%20%20%20%20var%20xorwow$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xorwow$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22xorwow%22%20prng%20algorithm%20by%0A%20%20%20%20%09//%20George%20Marsaglia.%20%20See%20http://www.jstatsoft.org/v08/i14/paper%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20strseed%20=%20'';%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t%20=%20(me.x%20%5E%20(me.x%20%3E%3E%3E%202));%0A%20%20%20%20%09%20%20%20%20me.x%20=%20me.y;%20me.y%20=%20me.z;%20me.z%20=%20me.w;%20me.w%20=%20me.v;%0A%20%20%20%20%09%20%20%20%20return%20(me.d%20=%20(me.d%20+%20362437%20%7C%200))%20+%0A%20%20%20%20%09%20%20%20%20%20%20%20(me.v%20=%20(me.v%20%5E%20(me.v%20%3C%3C%204))%20%5E%20(t%20%5E%20(t%20%3C%3C%201)))%20%7C%200;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20me.x%20=%200;%0A%20%20%20%20%09%20%20me.y%20=%200;%0A%20%20%20%20%09%20%20me.z%20=%200;%0A%20%20%20%20%09%20%20me.w%20=%200;%0A%20%20%20%20%09%20%20me.v%20=%200;%0A%0A%20%20%20%20%09%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Integer%20seed.%0A%20%20%20%20%09%20%20%20%20me.x%20=%20seed;%0A%20%20%20%20%09%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20//%20String%20seed.%0A%20%20%20%20%09%20%20%20%20strseed%20+=%20seed;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20Mix%20in%20string%20seed,%20then%20discard%20an%20initial%20batch%20of%2064%20values.%0A%20%20%20%20%09%20%20for%20(var%20k%20=%200;%20k%20%3C%20strseed.length%20+%2064;%20k++)%20%7B%0A%20%20%20%20%09%20%20%20%20me.x%20%5E=%20strseed.charCodeAt(k)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20if%20(k%20==%20strseed.length)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20me.d%20=%20me.x%20%3C%3C%2010%20%5E%20me.x%20%3E%3E%3E%204;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.x%20=%20f.x;%0A%20%20%20%20%09%20%20t.y%20=%20f.y;%0A%20%20%20%20%09%20%20t.z%20=%20f.z;%0A%20%20%20%20%09%20%20t.w%20=%20f.w;%0A%20%20%20%20%09%20%20t.v%20=%20f.v;%0A%20%20%20%20%09%20%20t.d%20=%20f.d;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xorwow%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xorwow$1));%0A%0A%20%20%20%20var%20xorwowExports%20=%20xorwow$1.exports;%0A%0A%20%20%20%20var%20xorshift7$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xorshift7$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22xorshift7%22%20algorithm%20by%0A%20%20%20%20%09//%20Fran%C3%A7ois%20Panneton%20and%20Pierre%20L'ecuyer:%0A%20%20%20%20%09//%20%22On%20the%20Xorgshift%20Random%20Number%20Generators%22%0A%20%20%20%20%09//%20http://saluc.engr.uconn.edu/refs/crypto/rng/panneton05onthexorshift.pdf%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this;%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Update%20xor%20generator.%0A%20%20%20%20%09%20%20%20%20var%20X%20=%20me.x,%20i%20=%20me.i,%20t,%20v;%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5Bi%5D;%20t%20%5E=%20(t%20%3E%3E%3E%207);%20v%20=%20t%20%5E%20(t%20%3C%3C%2024);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%201)%20&%207%5D;%20v%20%5E=%20t%20%5E%20(t%20%3E%3E%3E%2010);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%203)%20&%207%5D;%20v%20%5E=%20t%20%5E%20(t%20%3E%3E%3E%203);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%204)%20&%207%5D;%20v%20%5E=%20t%20%5E%20(t%20%3C%3C%207);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%207)%20&%207%5D;%20t%20=%20t%20%5E%20(t%20%3C%3C%2013);%20v%20%5E=%20t%20%5E%20(t%20%3C%3C%209);%0A%20%20%20%20%09%20%20%20%20X%5Bi%5D%20=%20v;%0A%20%20%20%20%09%20%20%20%20me.i%20=%20(i%20+%201)%20&%207;%0A%20%20%20%20%09%20%20%20%20return%20v;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20function%20init(me,%20seed)%20%7B%0A%20%20%20%20%09%20%20%20%20var%20j,%20X%20=%20%5B%5D;%0A%0A%20%20%20%20%09%20%20%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Seed%20state%20array%20using%20a%2032-bit%20integer.%0A%20%20%20%20%09%20%20%20%20%20%20X%5B0%5D%20=%20seed;%0A%20%20%20%20%09%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Seed%20state%20using%20a%20string.%0A%20%20%20%20%09%20%20%20%20%20%20seed%20=%20''%20+%20seed;%0A%20%20%20%20%09%20%20%20%20%20%20for%20(j%20=%200;%20j%20%3C%20seed.length;%20++j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20X%5Bj%20&%207%5D%20=%20(X%5Bj%20&%207%5D%20%3C%3C%2015)%20%5E%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20%20%20(seed.charCodeAt(j)%20+%20X%5B(j%20+%201)%20&%207%5D%20%3C%3C%2013);%0A%20%20%20%20%09%20%20%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Enforce%20an%20array%20length%20of%208,%20not%20all%20zeroes.%0A%20%20%20%20%09%20%20%20%20while%20(X.length%20%3C%208)%20X.push(0);%0A%20%20%20%20%09%20%20%20%20for%20(j%20=%200;%20j%20%3C%208%20&&%20X%5Bj%5D%20===%200;%20++j);%0A%20%20%20%20%09%20%20%20%20if%20(j%20==%208)%20X%5B7%5D%20=%20-1;%20else%20X%5Bj%5D;%0A%0A%20%20%20%20%09%20%20%20%20me.x%20=%20X;%0A%20%20%20%20%09%20%20%20%20me.i%20=%200;%0A%0A%20%20%20%20%09%20%20%20%20//%20Discard%20an%20initial%20256%20values.%0A%20%20%20%20%09%20%20%20%20for%20(j%20=%20256;%20j%20%3E%200;%20--j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20init(me,%20seed);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.x%20=%20f.x.slice();%0A%20%20%20%20%09%20%20t.i%20=%20f.i;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20if%20(seed%20==%20null)%20seed%20=%20+(new%20Date);%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(state.x)%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xorshift7%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xorshift7$1));%0A%0A%20%20%20%20var%20xorshift7Exports%20=%20xorshift7$1.exports;%0A%0A%20%20%20%20var%20xor4096$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xor4096$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20Richard%20Brent's%20Xorgens%20xor4096%20algorithm.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20This%20fast%20non-cryptographic%20random%20number%20generator%20is%20designed%20for%0A%20%20%20%20%09//%20use%20in%20Monte-Carlo%20algorithms.%20It%20combines%20a%20long-period%20xorshift%0A%20%20%20%20%09//%20generator%20with%20a%20Weyl%20generator,%20and%20it%20passes%20all%20common%20batteries%0A%20%20%20%20%09//%20of%20stasticial%20tests%20for%20randomness%20while%20consuming%20only%20a%20few%20nanoseconds%0A%20%20%20%20%09//%20for%20each%20prng%20generated.%20%20For%20background%20on%20the%20generator,%20see%20Brent's%0A%20%20%20%20%09//%20paper:%20%22Some%20long-period%20random%20number%20generators%20using%20shifts%20and%20xors.%22%0A%20%20%20%20%09//%20http://arxiv.org/pdf/1004.3115v1.pdf%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20Usage:%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20var%20xor4096%20=%20require('xor4096');%0A%20%20%20%20%09//%20random%20=%20xor4096(1);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Seed%20with%20int32%20or%20string.%0A%20%20%20%20%09//%20assert.equal(random(),%200.1520436450538547);%20//%20(0,%201)%20range,%2053%20bits.%0A%20%20%20%20%09//%20assert.equal(random.int32(),%201806534897);%20%20%20//%20signed%20int32,%2032%20bits.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20For%20nonzero%20numeric%20keys,%20this%20impelementation%20provides%20a%20sequence%0A%20%20%20%20%09//%20identical%20to%20that%20by%20Brent's%20xorgens%203%20implementaion%20in%20C.%20%20This%0A%20%20%20%20%09//%20implementation%20also%20provides%20for%20initalizing%20the%20generator%20with%0A%20%20%20%20%09//%20string%20seeds,%20or%20for%20saving%20and%20restoring%20the%20state%20of%20the%20generator.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20On%20Chrome,%20this%20prng%20benchmarks%20about%202.1%20times%20slower%20than%0A%20%20%20%20%09//%20Javascript's%20built-in%20Math.random().%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this;%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20w%20=%20me.w,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20X%20=%20me.X,%20i%20=%20me.i,%20t,%20v;%0A%20%20%20%20%09%20%20%20%20//%20Update%20Weyl%20generator.%0A%20%20%20%20%09%20%20%20%20me.w%20=%20w%20=%20(w%20+%200x61c88647)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20//%20Update%20xor%20generator.%0A%20%20%20%20%09%20%20%20%20v%20=%20X%5B(i%20+%2034)%20&%20127%5D;%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5Bi%20=%20((i%20+%201)%20&%20127)%5D;%0A%20%20%20%20%09%20%20%20%20v%20%5E=%20v%20%3C%3C%2013;%0A%20%20%20%20%09%20%20%20%20t%20%5E=%20t%20%3C%3C%2017;%0A%20%20%20%20%09%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2015;%0A%20%20%20%20%09%20%20%20%20t%20%5E=%20t%20%3E%3E%3E%2012;%0A%20%20%20%20%09%20%20%20%20//%20Update%20Xor%20generator%20array%20state.%0A%20%20%20%20%09%20%20%20%20v%20=%20X%5Bi%5D%20=%20v%20%5E%20t;%0A%20%20%20%20%09%20%20%20%20me.i%20=%20i;%0A%20%20%20%20%09%20%20%20%20//%20Result%20is%20the%20combination.%0A%20%20%20%20%09%20%20%20%20return%20(v%20+%20(w%20%5E%20(w%20%3E%3E%3E%2016)))%20%7C%200;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20function%20init(me,%20seed)%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t,%20v,%20i,%20j,%20w,%20X%20=%20%5B%5D,%20limit%20=%20128;%0A%20%20%20%20%09%20%20%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Numeric%20seeds%20initialize%20v,%20which%20is%20used%20to%20generates%20X.%0A%20%20%20%20%09%20%20%20%20%20%20v%20=%20seed;%0A%20%20%20%20%09%20%20%20%20%20%20seed%20=%20null;%0A%20%20%20%20%09%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20String%20seeds%20are%20mixed%20into%20v%20and%20X%20one%20character%20at%20a%20time.%0A%20%20%20%20%09%20%20%20%20%20%20seed%20=%20seed%20+%20'%5C0';%0A%20%20%20%20%09%20%20%20%20%20%20v%20=%200;%0A%20%20%20%20%09%20%20%20%20%20%20limit%20=%20Math.max(limit,%20seed.length);%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Initialize%20circular%20array%20and%20weyl%20value.%0A%20%20%20%20%09%20%20%20%20for%20(i%20=%200,%20j%20=%20-32;%20j%20%3C%20limit;%20++j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Put%20the%20unicode%20characters%20into%20the%20array,%20and%20shuffle%20them.%0A%20%20%20%20%09%20%20%20%20%20%20if%20(seed)%20v%20%5E=%20seed.charCodeAt((j%20+%2032)%20%25%20seed.length);%0A%20%20%20%20%09%20%20%20%20%20%20//%20After%2032%20shuffles,%20take%20v%20as%20the%20starting%20w%20value.%0A%20%20%20%20%09%20%20%20%20%20%20if%20(j%20===%200)%20w%20=%20v;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3C%3C%2010;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2015;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3C%3C%204;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2013;%0A%20%20%20%20%09%20%20%20%20%20%20if%20(j%20%3E=%200)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20w%20=%20(w%20+%200x61c88647)%20%7C%200;%20%20%20%20%20//%20Weyl.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20t%20=%20(X%5Bj%20&%20127%5D%20%5E=%20(v%20+%20w));%20%20//%20Combine%20xor%20and%20weyl%20to%20init%20array.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20i%20=%20(0%20==%20t)%20?%20i%20+%201%20:%200;%20%20%20%20%20//%20Count%20zeroes.%0A%20%20%20%20%09%20%20%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20We%20have%20detected%20all%20zeroes;%20make%20the%20key%20nonzero.%0A%20%20%20%20%09%20%20%20%20if%20(i%20%3E=%20128)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20X%5B(seed%20&&%20seed.length%20%7C%7C%200)%20&%20127%5D%20=%20-1;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Run%20the%20generator%20512%20times%20to%20further%20mix%20the%20state%20before%20using%20it.%0A%20%20%20%20%09%20%20%20%20//%20Factoring%20this%20as%20a%20function%20slows%20the%20main%20generator,%20so%20it%20is%20just%0A%20%20%20%20%09%20%20%20%20//%20unrolled%20here.%20%20The%20weyl%20generator%20is%20not%20advanced%20while%20warming%20up.%0A%20%20%20%20%09%20%20%20%20i%20=%20127;%0A%20%20%20%20%09%20%20%20%20for%20(j%20=%204%20*%20128;%20j%20%3E%200;%20--j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20v%20=%20X%5B(i%20+%2034)%20&%20127%5D;%0A%20%20%20%20%09%20%20%20%20%20%20t%20=%20X%5Bi%20=%20((i%20+%201)%20&%20127)%5D;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3C%3C%2013;%0A%20%20%20%20%09%20%20%20%20%20%20t%20%5E=%20t%20%3C%3C%2017;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2015;%0A%20%20%20%20%09%20%20%20%20%20%20t%20%5E=%20t%20%3E%3E%3E%2012;%0A%20%20%20%20%09%20%20%20%20%20%20X%5Bi%5D%20=%20v%20%5E%20t;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Storing%20state%20as%20object%20members%20is%20faster%20than%20using%20closure%20variables.%0A%20%20%20%20%09%20%20%20%20me.w%20=%20w;%0A%20%20%20%20%09%20%20%20%20me.X%20=%20X;%0A%20%20%20%20%09%20%20%20%20me.i%20=%20i;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20init(me,%20seed);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.i%20=%20f.i;%0A%20%20%20%20%09%20%20t.w%20=%20f.w;%0A%20%20%20%20%09%20%20t.X%20=%20f.X.slice();%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20if%20(seed%20==%20null)%20seed%20=%20+(new%20Date);%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(state.X)%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xor4096%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20window%20object%20or%20global%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xor4096$1));%0A%0A%20%20%20%20var%20xor4096Exports%20=%20xor4096$1.exports;%0A%0A%20%20%20%20var%20tychei$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20tychei$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22Tyche-i%22%20prng%20algorithm%20by%0A%20%20%20%20%09//%20Samuel%20Neves%20and%20Filipe%20Araujo.%0A%20%20%20%20%09//%20See%20https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20strseed%20=%20'';%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20b%20=%20me.b,%20c%20=%20me.c,%20d%20=%20me.d,%20a%20=%20me.a;%0A%20%20%20%20%09%20%20%20%20b%20=%20(b%20%3C%3C%2025)%20%5E%20(b%20%3E%3E%3E%207)%20%5E%20c;%0A%20%20%20%20%09%20%20%20%20c%20=%20(c%20-%20d)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20d%20=%20(d%20%3C%3C%2024)%20%5E%20(d%20%3E%3E%3E%208)%20%5E%20a;%0A%20%20%20%20%09%20%20%20%20a%20=%20(a%20-%20b)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.b%20=%20b%20=%20(b%20%3C%3C%2020)%20%5E%20(b%20%3E%3E%3E%2012)%20%5E%20c;%0A%20%20%20%20%09%20%20%20%20me.c%20=%20c%20=%20(c%20-%20d)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.d%20=%20(d%20%3C%3C%2016)%20%5E%20(c%20%3E%3E%3E%2016)%20%5E%20a;%0A%20%20%20%20%09%20%20%20%20return%20me.a%20=%20(a%20-%20b)%20%7C%200;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20/*%20The%20following%20is%20non-inverted%20tyche,%20which%20has%20better%20internal%0A%20%20%20%20%09%20%20%20*%20bit%20diffusion,%20but%20which%20is%20about%2025%25%20slower%20than%20tyche-i%20in%20JS.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20a%20=%20me.a,%20b%20=%20me.b,%20c%20=%20me.c,%20d%20=%20me.d;%0A%20%20%20%20%09%20%20%20%20a%20=%20(me.a%20+%20me.b%20%7C%200)%20%3E%3E%3E%200;%0A%20%20%20%20%09%20%20%20%20d%20=%20me.d%20%5E%20a;%20d%20=%20d%20%3C%3C%2016%20%5E%20d%20%3E%3E%3E%2016;%0A%20%20%20%20%09%20%20%20%20c%20=%20me.c%20+%20d%20%7C%200;%0A%20%20%20%20%09%20%20%20%20b%20=%20me.b%20%5E%20c;%20b%20=%20b%20%3C%3C%2012%20%5E%20d%20%3E%3E%3E%2020;%0A%20%20%20%20%09%20%20%20%20me.a%20=%20a%20=%20a%20+%20b%20%7C%200;%0A%20%20%20%20%09%20%20%20%20d%20=%20d%20%5E%20a;%20me.d%20=%20d%20=%20d%20%3C%3C%208%20%5E%20d%20%3E%3E%3E%2024;%0A%20%20%20%20%09%20%20%20%20me.c%20=%20c%20=%20c%20+%20d%20%7C%200;%0A%20%20%20%20%09%20%20%20%20b%20=%20b%20%5E%20c;%0A%20%20%20%20%09%20%20%20%20return%20me.b%20=%20(b%20%3C%3C%207%20%5E%20b%20%3E%3E%3E%2025);%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20*/%0A%0A%20%20%20%20%09%20%20me.a%20=%200;%0A%20%20%20%20%09%20%20me.b%20=%200;%0A%20%20%20%20%09%20%20me.c%20=%202654435769%20%7C%200;%0A%20%20%20%20%09%20%20me.d%20=%201367130551;%0A%0A%20%20%20%20%09%20%20if%20(seed%20===%20Math.floor(seed))%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Integer%20seed.%0A%20%20%20%20%09%20%20%20%20me.a%20=%20(seed%20/%200x100000000)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.b%20=%20seed%20%7C%200;%0A%20%20%20%20%09%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20//%20String%20seed.%0A%20%20%20%20%09%20%20%20%20strseed%20+=%20seed;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20Mix%20in%20string%20seed,%20then%20discard%20an%20initial%20batch%20of%2064%20values.%0A%20%20%20%20%09%20%20for%20(var%20k%20=%200;%20k%20%3C%20strseed.length%20+%2020;%20k++)%20%7B%0A%20%20%20%20%09%20%20%20%20me.b%20%5E=%20strseed.charCodeAt(k)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.a%20=%20f.a;%0A%20%20%20%20%09%20%20t.b%20=%20f.b;%0A%20%20%20%20%09%20%20t.c%20=%20f.c;%0A%20%20%20%20%09%20%20t.d%20=%20f.d;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.tychei%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(tychei$1));%0A%0A%20%20%20%20var%20tycheiExports%20=%20tychei$1.exports;%0A%0A%20%20%20%20var%20seedrandom$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20/*%0A%20%20%20%20Copyright%202019%20David%20Bau.%0A%0A%20%20%20%20Permission%20is%20hereby%20granted,%20free%20of%20charge,%20to%20any%20person%20obtaining%0A%20%20%20%20a%20copy%20of%20this%20software%20and%20associated%20documentation%20files%20(the%0A%20%20%20%20%22Software%22),%20to%20deal%20in%20the%20Software%20without%20restriction,%20including%0A%20%20%20%20without%20limitation%20the%20rights%20to%20use,%20copy,%20modify,%20merge,%20publish,%0A%20%20%20%20distribute,%20sublicense,%20and/or%20sell%20copies%20of%20the%20Software,%20and%20to%0A%20%20%20%20permit%20persons%20to%20whom%20the%20Software%20is%20furnished%20to%20do%20so,%20subject%20to%0A%20%20%20%20the%20following%20conditions:%0A%0A%20%20%20%20The%20above%20copyright%20notice%20and%20this%20permission%20notice%20shall%20be%0A%20%20%20%20included%20in%20all%20copies%20or%20substantial%20portions%20of%20the%20Software.%0A%0A%20%20%20%20THE%20SOFTWARE%20IS%20PROVIDED%20%22AS%20IS%22,%20WITHOUT%20WARRANTY%20OF%20ANY%20KIND,%0A%20%20%20%20EXPRESS%20OR%20IMPLIED,%20INCLUDING%20BUT%20NOT%20LIMITED%20TO%20THE%20WARRANTIES%20OF%0A%20%20%20%20MERCHANTABILITY,%20FITNESS%20FOR%20A%20PARTICULAR%20PURPOSE%20AND%20NONINFRINGEMENT.%0A%20%20%20%20IN%20NO%20EVENT%20SHALL%20THE%20AUTHORS%20OR%20COPYRIGHT%20HOLDERS%20BE%20LIABLE%20FOR%20ANY%0A%20%20%20%20CLAIM,%20DAMAGES%20OR%20OTHER%20LIABILITY,%20WHETHER%20IN%20AN%20ACTION%20OF%20CONTRACT,%0A%20%20%20%20TORT%20OR%20OTHERWISE,%20ARISING%20FROM,%20OUT%20OF%20OR%20IN%20CONNECTION%20WITH%20THE%0A%20%20%20%20SOFTWARE%20OR%20THE%20USE%20OR%20OTHER%20DEALINGS%20IN%20THE%20SOFTWARE.%0A%0A%20%20%20%20*/%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09(function%20(global,%20pool,%20math)%20%7B%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20The%20following%20constants%20are%20related%20to%20IEEE%20754%20limits.%0A%20%20%20%20%09//%0A%0A%20%20%20%20%09var%20width%20=%20256,%20%20%20%20%20%20%20%20//%20each%20RC4%20output%20is%200%20%3C=%20x%20%3C%20256%0A%20%20%20%20%09%20%20%20%20chunks%20=%206,%20%20%20%20%20%20%20%20%20//%20at%20least%20six%20RC4%20outputs%20for%20each%20double%0A%20%20%20%20%09%20%20%20%20digits%20=%2052,%20%20%20%20%20%20%20%20//%20there%20are%2052%20significant%20digits%20in%20a%20double%0A%20%20%20%20%09%20%20%20%20rngname%20=%20'random',%20//%20rngname:%20name%20for%20Math.random%20and%20Math.seedrandom%0A%20%20%20%20%09%20%20%20%20startdenom%20=%20math.pow(width,%20chunks),%0A%20%20%20%20%09%20%20%20%20significance%20=%20math.pow(2,%20digits),%0A%20%20%20%20%09%20%20%20%20overflow%20=%20significance%20*%202,%0A%20%20%20%20%09%20%20%20%20mask%20=%20width%20-%201,%0A%20%20%20%20%09%20%20%20%20nodecrypto;%20%20%20%20%20%20%20%20%20//%20node.js%20crypto%20module,%20initialized%20at%20the%20bottom.%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20seedrandom()%0A%20%20%20%20%09//%20This%20is%20the%20seedrandom%20function%20described%20above.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20seedrandom(seed,%20options,%20callback)%20%7B%0A%20%20%20%20%09%20%20var%20key%20=%20%5B%5D;%0A%20%20%20%20%09%20%20options%20=%20(options%20==%20true)%20?%20%7B%20entropy:%20true%20%7D%20:%20(options%20%7C%7C%20%7B%7D);%0A%0A%20%20%20%20%09%20%20//%20Flatten%20the%20seed%20string%20or%20build%20one%20from%20local%20entropy%20if%20needed.%0A%20%20%20%20%09%20%20var%20shortseed%20=%20mixkey(flatten(%0A%20%20%20%20%09%20%20%20%20options.entropy%20?%20%5Bseed,%20tostring(pool)%5D%20:%0A%20%20%20%20%09%20%20%20%20(seed%20==%20null)%20?%20autoseed()%20:%20seed,%203),%20key);%0A%0A%20%20%20%20%09%20%20//%20Use%20the%20seed%20to%20initialize%20an%20ARC4%20generator.%0A%20%20%20%20%09%20%20var%20arc4%20=%20new%20ARC4(key);%0A%0A%20%20%20%20%09%20%20//%20This%20function%20returns%20a%20random%20double%20in%20%5B0,%201)%20that%20contains%0A%20%20%20%20%09%20%20//%20randomness%20in%20every%20bit%20of%20the%20mantissa%20of%20the%20IEEE%20754%20value.%0A%20%20%20%20%09%20%20var%20prng%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20n%20=%20arc4.g(chunks),%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Start%20with%20a%20numerator%20n%20%3C%202%20%5E%2048%0A%20%20%20%20%09%20%20%20%20%20%20%20%20d%20=%20startdenom,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20and%20denominator%20d%20=%202%20%5E%2048.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20x%20=%200;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20and%20no%20'extra%20last%20byte'.%0A%20%20%20%20%09%20%20%20%20while%20(n%20%3C%20significance)%20%7B%20%20%20%20%20%20%20%20%20%20//%20Fill%20up%20all%20significant%20digits%20by%0A%20%20%20%20%09%20%20%20%20%20%20n%20=%20(n%20+%20x)%20*%20width;%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20shifting%20numerator%20and%0A%20%20%20%20%09%20%20%20%20%20%20d%20*=%20width;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20denominator%20and%20generating%20a%0A%20%20%20%20%09%20%20%20%20%20%20x%20=%20arc4.g(1);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20new%20least-significant-byte.%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20while%20(n%20%3E=%20overflow)%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%20//%20To%20avoid%20rounding%20up,%20before%20adding%0A%20%20%20%20%09%20%20%20%20%20%20n%20/=%202;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20last%20byte,%20shift%20everything%0A%20%20%20%20%09%20%20%20%20%20%20d%20/=%202;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20right%20using%20integer%20math%20until%0A%20%20%20%20%09%20%20%20%20%20%20x%20%3E%3E%3E=%201;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20we%20have%20exactly%20the%20desired%20bits.%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20return%20(n%20+%20x)%20/%20d;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Form%20the%20number%20within%20%5B0,%201).%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20prng.int32%20=%20function()%20%7B%20return%20arc4.g(4)%20%7C%200;%20%7D;%0A%20%20%20%20%09%20%20prng.quick%20=%20function()%20%7B%20return%20arc4.g(4)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20prng;%0A%0A%20%20%20%20%09%20%20//%20Mix%20the%20randomness%20into%20accumulated%20entropy.%0A%20%20%20%20%09%20%20mixkey(tostring(arc4.S),%20pool);%0A%0A%20%20%20%20%09%20%20//%20Calling%20convention:%20what%20to%20return%20as%20a%20function%20of%20prng,%20seed,%20is_math.%0A%20%20%20%20%09%20%20return%20(options.pass%20%7C%7C%20callback%20%7C%7C%0A%20%20%20%20%09%20%20%20%20%20%20function(prng,%20seed,%20is_math_call,%20state)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20//%20Load%20the%20arc4%20state%20from%20the%20given%20state%20if%20it%20has%20an%20S%20array.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20if%20(state.S)%20%7B%20copy(state,%20arc4);%20%7D%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20//%20Only%20provide%20the%20.state%20method%20if%20requested%20via%20options.state.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(arc4,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20If%20called%20as%20a%20method%20of%20Math%20(Math.seedrandom()),%20mutate%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20Math.random%20because%20that%20is%20how%20seedrandom.js%20has%20worked%20since%20v1.0.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20if%20(is_math_call)%20%7B%20math%5Brngname%5D%20=%20prng;%20return%20seed;%20%7D%0A%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20Otherwise,%20it%20is%20a%20newer%20calling%20convention,%20so%20return%20the%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20prng%20directly.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20else%20return%20prng;%0A%20%20%20%20%09%20%20%20%20%20%20%7D)(%0A%20%20%20%20%09%20%20prng,%0A%20%20%20%20%09%20%20shortseed,%0A%20%20%20%20%09%20%20'global'%20in%20options%20?%20options.global%20:%20(this%20==%20math),%0A%20%20%20%20%09%20%20options.state);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20ARC4%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20An%20ARC4%20implementation.%20%20The%20constructor%20takes%20a%20key%20in%20the%20form%20of%0A%20%20%20%20%09//%20an%20array%20of%20at%20most%20(width)%20integers%20that%20should%20be%200%20%3C=%20x%20%3C%20(width).%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20The%20g(count)%20method%20returns%20a%20pseudorandom%20integer%20that%20concatenates%0A%20%20%20%20%09//%20the%20next%20(count)%20outputs%20from%20ARC4.%20%20Its%20return%20value%20is%20a%20number%20x%0A%20%20%20%20%09//%20that%20is%20in%20the%20range%200%20%3C=%20x%20%3C%20(width%20%5E%20count).%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20ARC4(key)%20%7B%0A%20%20%20%20%09%20%20var%20t,%20keylen%20=%20key.length,%0A%20%20%20%20%09%20%20%20%20%20%20me%20=%20this,%20i%20=%200,%20j%20=%20me.i%20=%20me.j%20=%200,%20s%20=%20me.S%20=%20%5B%5D;%0A%0A%20%20%20%20%09%20%20//%20The%20empty%20key%20%5B%5D%20is%20treated%20as%20%5B0%5D.%0A%20%20%20%20%09%20%20if%20(!keylen)%20%7B%20key%20=%20%5Bkeylen++%5D;%20%7D%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20S%20using%20the%20standard%20key%20scheduling%20algorithm.%0A%20%20%20%20%09%20%20while%20(i%20%3C%20width)%20%7B%0A%20%20%20%20%09%20%20%20%20s%5Bi%5D%20=%20i++;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20for%20(i%20=%200;%20i%20%3C%20width;%20i++)%20%7B%0A%20%20%20%20%09%20%20%20%20s%5Bi%5D%20=%20s%5Bj%20=%20mask%20&%20(j%20+%20key%5Bi%20%25%20keylen%5D%20+%20(t%20=%20s%5Bi%5D))%5D;%0A%20%20%20%20%09%20%20%20%20s%5Bj%5D%20=%20t;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20The%20%22g%22%20method%20returns%20the%20next%20(count)%20outputs%20as%20one%20number.%0A%20%20%20%20%09%20%20(me.g%20=%20function(count)%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Using%20instance%20members%20instead%20of%20closure%20state%20nearly%20doubles%20speed.%0A%20%20%20%20%09%20%20%20%20var%20t,%20r%20=%200,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20i%20=%20me.i,%20j%20=%20me.j,%20s%20=%20me.S;%0A%20%20%20%20%09%20%20%20%20while%20(count--)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20t%20=%20s%5Bi%20=%20mask%20&%20(i%20+%201)%5D;%0A%20%20%20%20%09%20%20%20%20%20%20r%20=%20r%20*%20width%20+%20s%5Bmask%20&%20((s%5Bi%5D%20=%20s%5Bj%20=%20mask%20&%20(j%20+%20t)%5D)%20+%20(s%5Bj%5D%20=%20t))%5D;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20me.i%20=%20i;%20me.j%20=%20j;%0A%20%20%20%20%09%20%20%20%20return%20r;%0A%20%20%20%20%09%20%20%20%20//%20For%20robust%20unpredictability,%20the%20function%20call%20below%20automatically%0A%20%20%20%20%09%20%20%20%20//%20discards%20an%20initial%20batch%20of%20values.%20%20This%20is%20called%20RC4-drop%5B256%5D.%0A%20%20%20%20%09%20%20%20%20//%20See%20http://google.com/search?q=rsa+fluhrer+response&btnI%0A%20%20%20%20%09%20%20%7D)(width);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20copy()%0A%20%20%20%20%09//%20Copies%20internal%20state%20of%20ARC4%20to%20or%20from%20a%20plain%20object.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.i%20=%20f.i;%0A%20%20%20%20%09%20%20t.j%20=%20f.j;%0A%20%20%20%20%09%20%20t.S%20=%20f.S.slice();%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20flatten()%0A%20%20%20%20%09//%20Converts%20an%20object%20tree%20to%20nested%20arrays%20of%20strings.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20flatten(obj,%20depth)%20%7B%0A%20%20%20%20%09%20%20var%20result%20=%20%5B%5D,%20typ%20=%20(typeof%20obj),%20prop;%0A%20%20%20%20%09%20%20if%20(depth%20&&%20typ%20==%20'object')%20%7B%0A%20%20%20%20%09%20%20%20%20for%20(prop%20in%20obj)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20try%20%7B%20result.push(flatten(obj%5Bprop%5D,%20depth%20-%201));%20%7D%20catch%20(e)%20%7B%7D%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20(result.length%20?%20result%20:%20typ%20==%20'string'%20?%20obj%20:%20obj%20+%20'%5C0');%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20mixkey()%0A%20%20%20%20%09//%20Mixes%20a%20string%20seed%20into%20a%20key%20that%20is%20an%20array%20of%20integers,%20and%0A%20%20%20%20%09//%20returns%20a%20shortened%20string%20seed%20that%20is%20equivalent%20to%20the%20result%20key.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20mixkey(seed,%20key)%20%7B%0A%20%20%20%20%09%20%20var%20stringseed%20=%20seed%20+%20'',%20smear,%20j%20=%200;%0A%20%20%20%20%09%20%20while%20(j%20%3C%20stringseed.length)%20%7B%0A%20%20%20%20%09%20%20%20%20key%5Bmask%20&%20j%5D%20=%0A%20%20%20%20%09%20%20%20%20%20%20mask%20&%20((smear%20%5E=%20key%5Bmask%20&%20j%5D%20*%2019)%20+%20stringseed.charCodeAt(j++));%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20tostring(key);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20autoseed()%0A%20%20%20%20%09//%20Returns%20an%20object%20for%20autoseeding,%20using%20window.crypto%20and%20Node%20crypto%0A%20%20%20%20%09//%20module%20if%20available.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20autoseed()%20%7B%0A%20%20%20%20%09%20%20try%20%7B%0A%20%20%20%20%09%20%20%20%20var%20out;%0A%20%20%20%20%09%20%20%20%20if%20(nodecrypto%20&&%20(out%20=%20nodecrypto.randomBytes))%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20The%20use%20of%20'out'%20to%20remember%20randomBytes%20makes%20tight%20minified%20code.%0A%20%20%20%20%09%20%20%20%20%20%20out%20=%20out(width);%0A%20%20%20%20%09%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20out%20=%20new%20Uint8Array(width);%0A%20%20%20%20%09%20%20%20%20%20%20(global.crypto%20%7C%7C%20global.msCrypto).getRandomValues(out);%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20return%20tostring(out);%0A%20%20%20%20%09%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%09%20%20%20%20var%20browser%20=%20global.navigator,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20plugins%20=%20browser%20&&%20browser.plugins;%0A%20%20%20%20%09%20%20%20%20return%20%5B+new%20Date,%20global,%20plugins,%20global.screen,%20tostring(pool)%5D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20tostring()%0A%20%20%20%20%09//%20Converts%20an%20array%20of%20charcodes%20to%20a%20string%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20tostring(a)%20%7B%0A%20%20%20%20%09%20%20return%20String.fromCharCode.apply(0,%20a);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20When%20seedrandom.js%20is%20loaded,%20we%20immediately%20mix%20a%20few%20bits%0A%20%20%20%20%09//%20from%20the%20built-in%20RNG%20into%20the%20entropy%20pool.%20%20Because%20we%20do%0A%20%20%20%20%09//%20not%20want%20to%20interfere%20with%20deterministic%20PRNG%20state%20later,%0A%20%20%20%20%09//%20seedrandom%20will%20not%20call%20math.random%20on%20its%20own%20again%20after%0A%20%20%20%20%09//%20initialization.%0A%20%20%20%20%09//%0A%20%20%20%20%09mixkey(math.random(),%20pool);%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20Nodejs%20and%20AMD%20support:%20export%20the%20implementation%20as%20a%20module%20using%0A%20%20%20%20%09//%20either%20convention.%0A%20%20%20%20%09//%0A%20%20%20%20%09if%20(module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20seedrandom;%0A%20%20%20%20%09%20%20//%20When%20in%20node.js,%20try%20using%20crypto%20package%20for%20autoseeding.%0A%20%20%20%20%09%20%20try%20%7B%0A%20%20%20%20%09%20%20%20%20nodecrypto%20=%20require('crypto');%0A%20%20%20%20%09%20%20%7D%20catch%20(ex)%20%7B%7D%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20//%20When%20included%20as%20a%20plain%20script,%20set%20up%20Math.seedrandom%20global.%0A%20%20%20%20%09%20%20math%5B'seed'%20+%20rngname%5D%20=%20seedrandom;%0A%20%20%20%20%09%7D%0A%0A%0A%20%20%20%20%09//%20End%20anonymous%20scope,%20and%20pass%20initial%20values.%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20//%20global:%20%60self%60%20in%20browsers%20(including%20strict%20mode%20and%20web%20workers),%0A%20%20%20%20%09%20%20//%20otherwise%20%60this%60%20in%20Node%20and%20other%20environments%0A%20%20%20%20%09%20%20(typeof%20self%20!==%20'undefined')%20?%20self%20:%20commonjsGlobal,%0A%20%20%20%20%09%20%20%5B%5D,%20%20%20%20%20//%20pool:%20entropy%20pool%20starts%20empty%0A%20%20%20%20%09%20%20Math%20%20%20%20//%20math:%20package%20containing%20random,%20pow,%20and%20seedrandom%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(seedrandom$1));%0A%0A%20%20%20%20var%20seedrandomExports%20=%20seedrandom$1.exports;%0A%0A%20%20%20%20//%20A%20library%20of%20seedable%20RNGs%20implemented%20in%20Javascript.%0A%20%20%20%20//%0A%20%20%20%20//%20Usage:%0A%20%20%20%20//%0A%20%20%20%20//%20var%20seedrandom%20=%20require('seedrandom');%0A%20%20%20%20//%20var%20random%20=%20seedrandom(1);%20//%20or%20any%20seed.%0A%20%20%20%20//%20var%20x%20=%20random();%20%20%20%20%20%20%20//%200%20%3C=%20x%20%3C%201.%20%20Every%20bit%20is%20random.%0A%20%20%20%20//%20var%20x%20=%20random.quick();%20//%200%20%3C=%20x%20%3C%201.%20%2032%20bits%20of%20randomness.%0A%0A%20%20%20%20//%20alea,%20a%2053-bit%20multiply-with-carry%20generator%20by%20Johannes%20Baag%C3%B8e.%0A%20%20%20%20//%20Period:%20~2%5E116%0A%20%20%20%20//%20Reported%20to%20pass%20all%20BigCrush%20tests.%0A%20%20%20%20var%20alea%20=%20aleaExports;%0A%0A%20%20%20%20//%20xor128,%20a%20pure%20xor-shift%20generator%20by%20George%20Marsaglia.%0A%20%20%20%20//%20Period:%202%5E128-1.%0A%20%20%20%20//%20Reported%20to%20fail:%20MatrixRank%20and%20LinearComp.%0A%20%20%20%20var%20xor128%20=%20xor128Exports;%0A%0A%20%20%20%20//%20xorwow,%20George%20Marsaglia's%20160-bit%20xor-shift%20combined%20plus%20weyl.%0A%20%20%20%20//%20Period:%202%5E192-2%5E32%0A%20%20%20%20//%20Reported%20to%20fail:%20CollisionOver,%20SimpPoker,%20and%20LinearComp.%0A%20%20%20%20var%20xorwow%20=%20xorwowExports;%0A%0A%20%20%20%20//%20xorshift7,%20by%20Fran%C3%A7ois%20Panneton%20and%20Pierre%20L'ecuyer,%20takes%0A%20%20%20%20//%20a%20different%20approach:%20it%20adds%20robustness%20by%20allowing%20more%20shifts%0A%20%20%20%20//%20than%20Marsaglia's%20original%20three.%20%20It%20is%20a%207-shift%20generator%0A%20%20%20%20//%20with%20256%20bits,%20that%20passes%20BigCrush%20with%20no%20systmatic%20failures.%0A%20%20%20%20//%20Period%202%5E256-1.%0A%20%20%20%20//%20No%20systematic%20BigCrush%20failures%20reported.%0A%20%20%20%20var%20xorshift7%20=%20xorshift7Exports;%0A%0A%20%20%20%20//%20xor4096,%20by%20Richard%20Brent,%20is%20a%204096-bit%20xor-shift%20with%20a%0A%20%20%20%20//%20very%20long%20period%20that%20also%20adds%20a%20Weyl%20generator.%20It%20also%20passes%0A%20%20%20%20//%20BigCrush%20with%20no%20systematic%20failures.%20%20Its%20long%20period%20may%0A%20%20%20%20//%20be%20useful%20if%20you%20have%20many%20generators%20and%20need%20to%20avoid%0A%20%20%20%20//%20collisions.%0A%20%20%20%20//%20Period:%202%5E4128-2%5E32.%0A%20%20%20%20//%20No%20systematic%20BigCrush%20failures%20reported.%0A%20%20%20%20var%20xor4096%20=%20xor4096Exports;%0A%0A%20%20%20%20//%20Tyche-i,%20by%20Samuel%20Neves%20and%20Filipe%20Araujo,%20is%20a%20bit-shifting%20random%0A%20%20%20%20//%20number%20generator%20derived%20from%20ChaCha,%20a%20modern%20stream%20cipher.%0A%20%20%20%20//%20https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf%0A%20%20%20%20//%20Period:%20~2%5E127%0A%20%20%20%20//%20No%20systematic%20BigCrush%20failures%20reported.%0A%20%20%20%20var%20tychei%20=%20tycheiExports;%0A%0A%20%20%20%20//%20The%20original%20ARC4-based%20prng%20included%20in%20this%20library.%0A%20%20%20%20//%20Period:%20~2%5E1600%0A%20%20%20%20var%20sr%20=%20seedrandomExports;%0A%0A%20%20%20%20sr.alea%20=%20alea;%0A%20%20%20%20sr.xor128%20=%20xor128;%0A%20%20%20%20sr.xorwow%20=%20xorwow;%0A%20%20%20%20sr.xorshift7%20=%20xorshift7;%0A%20%20%20%20sr.xor4096%20=%20xor4096;%0A%20%20%20%20sr.tychei%20=%20tychei;%0A%0A%20%20%20%20var%20seedrandom%20=%20sr;%0A%0A%20%20%20%20var%20Seedrandom%20=%20/*@__PURE__*/getDefaultExportFromCjs(seedrandom);%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BHTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20domainKey%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20sessionKey%0A%20%20%20%20%20*%20@param%20%7Bany%7D%20getImageDataProxy%0A%20%20%20%20%20*%20@param%20%7BCanvasRenderingContext2D%20%7C%20WebGL2RenderingContext%20%7C%20WebGLRenderingContext%7D%20ctx?%0A%20%20%20%20%20*/%0A%20%20%20%20function%20computeOffScreenCanvas%20(canvas,%20domainKey,%20sessionKey,%20getImageDataProxy,%20ctx)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!ctx)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'null'%20is%20not%20assignable%20to%20type%20'CanvasRenderingContext2D%20%7C%20WebGL2RenderingContext%20%7C%20WebGLRenderingContext'.%0A%20%20%20%20%20%20%20%20%20%20%20%20ctx%20=%20canvas.getContext('2d');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Make%20a%20off-screen%20canvas%20and%20put%20the%20data%20there%0A%20%20%20%20%20%20%20%20const%20offScreenCanvas%20=%20document.createElement('canvas');%0A%20%20%20%20%20%20%20%20offScreenCanvas.width%20=%20canvas.width;%0A%20%20%20%20%20%20%20%20offScreenCanvas.height%20=%20canvas.height;%0A%20%20%20%20%20%20%20%20const%20offScreenCtx%20=%20offScreenCanvas.getContext('2d');%0A%0A%20%20%20%20%20%20%20%20let%20rasterizedCtx%20=%20ctx;%0A%20%20%20%20%20%20%20%20//%20If%20we're%20not%20a%202d%20canvas%20we%20need%20to%20rasterise%20first%20into%202d%0A%20%20%20%20%20%20%20%20const%20rasterizeToCanvas%20=%20!(ctx%20instanceof%20CanvasRenderingContext2D);%0A%20%20%20%20%20%20%20%20if%20(rasterizeToCanvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'CanvasRenderingContext2D%20%7C%20null'%20is%20not%20assignable%20to%20type%20'CanvasRenderingContext2D%20%7C%20WebGL2RenderingContext%20%7C%20WebGLRenderingContext'.%0A%20%20%20%20%20%20%20%20%20%20%20%20rasterizedCtx%20=%20offScreenCtx;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20'offScreenCtx'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20offScreenCtx.drawImage(canvas,%200,%200);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20We%20*always*%20compute%20the%20random%20pixels%20on%20the%20complete%20pixel%20set,%20then%20pass%20back%20the%20subset%20later%0A%20%20%20%20%20%20%20%20let%20imageData%20=%20getImageDataProxy._native.apply(rasterizedCtx,%20%5B0,%200,%20canvas.width,%20canvas.height%5D);%0A%20%20%20%20%20%20%20%20imageData%20=%20modifyPixelData(imageData,%20sessionKey,%20domainKey,%20canvas.width);%0A%0A%20%20%20%20%20%20%20%20if%20(rasterizeToCanvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'null'%20is%20not%20assignable%20to%20type%20'CanvasRenderingContext2D'.%0A%20%20%20%20%20%20%20%20%20%20%20%20clearCanvas(offScreenCtx);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20'offScreenCtx'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20offScreenCtx.putImageData(imageData,%200,%200);%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20offScreenCanvas,%20offScreenCtx%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Clears%20the%20pixels%20from%20the%20canvas%20context%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7BCanvasRenderingContext2D%7D%20canvasContext%0A%20%20%20%20%20*/%0A%20%20%20%20function%20clearCanvas%20(canvasContext)%20%7B%0A%20%20%20%20%20%20%20%20//%20Save%20state%20and%20clean%20the%20pixels%20from%20the%20canvas%0A%20%20%20%20%20%20%20%20canvasContext.save();%0A%20%20%20%20%20%20%20%20canvasContext.globalCompositeOperation%20=%20'destination-out';%0A%20%20%20%20%20%20%20%20canvasContext.fillStyle%20=%20'rgb(255,255,255)';%0A%20%20%20%20%20%20%20%20canvasContext.fillRect(0,%200,%20canvasContext.canvas.width,%20canvasContext.canvas.height);%0A%20%20%20%20%20%20%20%20canvasContext.restore();%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BImageData%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20sessionKey%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20domainKey%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20width%0A%20%20%20%20%20*/%0A%20%20%20%20function%20modifyPixelData%20(imageData,%20domainKey,%20sessionKey,%20width)%20%7B%0A%20%20%20%20%20%20%20%20const%20d%20=%20imageData.data;%0A%20%20%20%20%20%20%20%20const%20length%20=%20d.length%20/%204;%0A%20%20%20%20%20%20%20%20let%20checkSum%20=%200;%0A%20%20%20%20%20%20%20%20const%20mappingArray%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20for%20(let%20i%20=%200;%20i%20%3C%20length;%20i%20+=%204)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!shouldIgnorePixel(d,%20i)%20&&%20!adjacentSame(d,%20i,%20width))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mappingArray.push(i);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20checkSum%20+=%20d%5Bi%5D%20+%20d%5Bi%20+%201%5D%20+%20d%5Bi%20+%202%5D%20+%20d%5Bi%20+%203%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20windowHash%20=%20getDataKeySync(sessionKey,%20domainKey,%20checkSum);%0A%20%20%20%20%20%20%20%20const%20rng%20=%20new%20Seedrandom(windowHash);%0A%20%20%20%20%20%20%20%20for%20(let%20i%20=%200;%20i%20%3C%20mappingArray.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20rand%20=%20rng();%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20byte%20=%20Math.floor(rand%20*%2010);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20channel%20=%20byte%20%25%203;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20pixelCanvasIndex%20=%20mappingArray%5Bi%5D%20+%20channel;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20d%5BpixelCanvasIndex%5D%20=%20d%5BpixelCanvasIndex%5D%20%5E%20(byte%20&%200x1);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20imageData%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Ignore%20pixels%20that%20have%20neighbours%20that%20are%20the%20same%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7BUint8ClampedArray%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20width%0A%20%20%20%20%20*/%0A%20%20%20%20function%20adjacentSame%20(imageData,%20index,%20width)%20%7B%0A%20%20%20%20%20%20%20%20const%20widthPixel%20=%20width%20*%204;%0A%20%20%20%20%20%20%20%20const%20x%20=%20index%20%25%20widthPixel;%0A%20%20%20%20%20%20%20%20const%20maxLength%20=%20imageData.length;%0A%0A%20%20%20%20%20%20%20%20//%20Pixels%20not%20on%20the%20right%20border%20of%20the%20canvas%0A%20%20%20%20%20%20%20%20if%20(x%20%3C%20widthPixel)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20right%20=%20index%20+%204;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!pixelsSame(imageData,%20index,%20right))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalRightUp%20=%20right%20-%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalRightUp%20%3E%200%20&&%20!pixelsSame(imageData,%20index,%20diagonalRightUp))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalRightDown%20=%20right%20+%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalRightDown%20%3C%20maxLength%20&&%20!pixelsSame(imageData,%20index,%20diagonalRightDown))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Pixels%20not%20on%20the%20left%20border%20of%20the%20canvas%0A%20%20%20%20%20%20%20%20if%20(x%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20left%20=%20index%20-%204;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!pixelsSame(imageData,%20index,%20left))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalLeftUp%20=%20left%20-%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalLeftUp%20%3E%200%20&&%20!pixelsSame(imageData,%20index,%20diagonalLeftUp))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalLeftDown%20=%20left%20+%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalLeftDown%20%3C%20maxLength%20&&%20!pixelsSame(imageData,%20index,%20diagonalLeftDown))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20up%20=%20index%20-%20widthPixel;%0A%20%20%20%20%20%20%20%20if%20(up%20%3E%200%20&&%20!pixelsSame(imageData,%20index,%20up))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20down%20=%20index%20+%20widthPixel;%0A%20%20%20%20%20%20%20%20if%20(down%20%3C%20maxLength%20&&%20!pixelsSame(imageData,%20index,%20down))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Check%20that%20a%20pixel%20at%20index%20and%20index2%20match%20all%20channels%0A%20%20%20%20%20*%20@param%20%7BUint8ClampedArray%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index2%0A%20%20%20%20%20*/%0A%20%20%20%20function%20pixelsSame%20(imageData,%20index,%20index2)%20%7B%0A%20%20%20%20%20%20%20%20return%20imageData%5Bindex%5D%20===%20imageData%5Bindex2%5D%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20imageData%5Bindex%20+%201%5D%20===%20imageData%5Bindex2%20+%201%5D%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20imageData%5Bindex%20+%202%5D%20===%20imageData%5Bindex2%20+%202%5D%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20imageData%5Bindex%20+%203%5D%20===%20imageData%5Bindex2%20+%203%5D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Returns%20true%20if%20pixel%20should%20be%20ignored%0A%20%20%20%20%20*%20@param%20%7BUint8ClampedArray%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shouldIgnorePixel%20(imageData,%20index)%20%7B%0A%20%20%20%20%20%20%20%20//%20Transparent%20pixels%0A%20%20%20%20%20%20%20%20if%20(imageData%5Bindex%20+%203%5D%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingCanvas%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20sessionKey,%20site%20%7D%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domainKey%20=%20site.domain;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureName%20=%20'fingerprinting-canvas';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20supportsWebGl%20=%20this.getFeatureSettingEnabled('webGl');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeCanvases%20=%20new%20WeakSet();%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20canvasContexts%20=%20new%20WeakMap();%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20canvasCache%20=%20new%20WeakMap();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20Clear%20cache%20as%20canvas%20has%20changed%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7BOffscreenCanvas%20%7C%20HTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20clearCache%20(canvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvasCache.delete(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7BOffscreenCanvas%20%7C%20HTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20treatAsUnsafe%20(canvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unsafeCanvases.add(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearCache(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20HTMLCanvasElement.prototype,%20'getContext',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20context%20=%20DDGReflect.apply(target,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvasContexts.set(thisArg,%20context);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20context%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20proxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Known%20data%20methods%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20safeMethods%20=%20%5B'putImageData',%20'drawImage'%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20safeMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20safeMethodProxy%20=%20new%20DDGProxy(featureName,%20CanvasRenderingContext2D.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Don't%20apply%20escape%20hatch%20for%20canvases%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(methodName%20===%20'drawImage'%20&&%20args%5B0%5D%20&&%20args%5B0%5D%20instanceof%20HTMLCanvasElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20treatAsUnsafe(args%5B0%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearCache(thisArg.canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20safeMethodProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeMethods%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'strokeRect',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'bezierCurveTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'quadraticCurveTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'arcTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'ellipse',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'rect',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fill',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'stroke',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'lineTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'beginPath',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'closePath',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'arc',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fillText',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fillRect',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'strokeText',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createConicGradient',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createLinearGradient',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createRadialGradient',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createPattern'%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20unsafeMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Some%20methods%20are%20browser%20specific%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(methodName%20in%20CanvasRenderingContext2D.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeProxy%20=%20new%20DDGProxy(featureName,%20CanvasRenderingContext2D.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20treatAsUnsafe(thisArg.canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unsafeProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportsWebGl)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeGlMethods%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'commit',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'compileShader',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'shaderSource',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'attachShader',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createProgram',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'linkProgram',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'drawElements',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'drawArrays'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20glContexts%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WebGLRenderingContext%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('WebGL2RenderingContext'%20in%20globalThis)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20glContexts.push(WebGL2RenderingContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20context%20of%20glContexts)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20unsafeGlMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Some%20methods%20are%20browser%20specific%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(methodName%20in%20context.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeProxy%20=%20new%20DDGProxy(featureName,%20context.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20treatAsUnsafe(thisArg.canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unsafeProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Using%20proxies%20here%20to%20swallow%20calls%20to%20toString%20etc%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20getImageDataProxy%20=%20new%20DDGProxy(featureName,%20CanvasRenderingContext2D.prototype,%20'getImageData',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!unsafeCanvases.has(thisArg.canvas))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Anything%20we%20do%20here%20should%20be%20caught%20and%20ignored%20silently%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20offScreenCtx%20%7D%20=%20getCachedOffScreenCanvasOrCompute(thisArg.canvas,%20domainKey,%20sessionKey);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Call%20the%20original%20method%20on%20the%20modified%20off-screen%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20offScreenCtx,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20getImageDataProxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20Get%20cached%20offscreen%20if%20one%20exists,%20otherwise%20compute%20one%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20domainKey%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20sessionKey%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20getCachedOffScreenCanvasOrCompute%20(canvas,%20domainKey,%20sessionKey)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20result;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(canvasCache.has(canvas))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20=%20canvasCache.get(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20ctx%20=%20canvasContexts.get(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20=%20computeOffScreenCanvas(canvas,%20domainKey,%20sessionKey,%20getImageDataProxy,%20ctx);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvasCache.set(canvas,%20result);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20result%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20canvasMethods%20=%20%5B'toDataURL',%20'toBlob'%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20canvasMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20HTMLCanvasElement.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Short%20circuit%20for%20low%20risk%20canvas%20calls%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!unsafeCanvases.has(thisArg))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20offScreenCanvas%20%7D%20=%20getCachedOffScreenCanvasOrCompute(thisArg,%20domainKey,%20sessionKey);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Call%20the%20original%20method%20on%20the%20modified%20off-screen%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20offScreenCanvas,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Something%20we%20did%20caused%20an%20exception,%20fall%20back%20to%20the%20native%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Cookie%20%7B%0A%20%20%20%20%20%20%20%20constructor%20(cookieString)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parts%20=%20cookieString.split(';');%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parse();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20parse%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20EXTRACT_ATTRIBUTES%20=%20new%20Set(%5B'max-age',%20'expires',%20'domain'%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20this.attrIdx%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parts.forEach((part,%20index)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20kv%20=%20part.split('=',%201);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20attribute%20=%20kv%5B0%5D.trim();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20value%20=%20part.slice(kv%5B0%5D.length%20+%201);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(index%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.name%20=%20attribute;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.value%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(EXTRACT_ATTRIBUTES.has(attribute.toLowerCase()))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this%5Battribute.toLowerCase()%5D%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.attrIdx%5Battribute.toLowerCase()%5D%20=%20index;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20getExpiry%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20expires%20is%20not%20defined%20in%20the%20type%20definition%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this.maxAge%20&&%20!this.expires)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20NaN%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20expiry%20=%20this.maxAge%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20?%20parseInt(this.maxAge)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20expires%20is%20not%20defined%20in%20the%20type%20definition%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20:%20(new%20Date(this.expires)%20-%20new%20Date())%20/%201000;%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20expiry%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20maxAge%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this%5B'max-age'%5D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20set%20maxAge%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.attrIdx%5B'max-age'%5D%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.parts.splice(this.attrIdx%5B'max-age'%5D,%201,%20%60max-age=$%7Bvalue%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.parts.push(%60max-age=$%7Bvalue%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parse();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20toString%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.parts.join(';')%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Initial%20cookie%20policy%20pre%20init%0A%20%20%20%20let%20cookiePolicy%20=%20%7B%0A%20%20%20%20%20%20%20%20debug:%20false,%0A%20%20%20%20%20%20%20%20isFrame:%20isBeingFramed(),%0A%20%20%20%20%20%20%20%20isTracker:%20false,%0A%20%20%20%20%20%20%20%20shouldBlock:%20true,%0A%20%20%20%20%20%20%20%20shouldBlockTrackerCookie:%20true,%0A%20%20%20%20%20%20%20%20shouldBlockNonTrackerCookie:%20false,%0A%20%20%20%20%20%20%20%20isThirdParty:%20isThirdParty(),%0A%20%20%20%20%20%20%20%20policy:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20threshold:%20604800,%20//%207%20days%0A%20%20%20%20%20%20%20%20%20%20%20%20maxAge:%20604800%20//%207%20days%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20let%20loadedPolicyResolve;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7B'ignore'%20%7C%20'block'%20%7C%20'restrict'%7D%20action%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20reason%0A%20%20%20%20%20*%20@param%20%7Bany%7D%20ctx%0A%20%20%20%20%20*/%0A%20%20%20%20function%20debugHelper%20(action,%20reason,%20ctx)%20%7B%0A%20%20%20%20%20%20%20%20cookiePolicy.debug%20&&%20postDebugMessage('jscookie',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20action,%0A%20%20%20%20%20%20%20%20%20%20%20%20reason,%0A%20%20%20%20%20%20%20%20%20%20%20%20stack:%20ctx.stack,%0A%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20globalThis.document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins:%20%5B...ctx.scriptOrigins%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20value:%20ctx.value%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20shouldBlockTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.shouldBlock%20&&%20cookiePolicy.shouldBlockTrackerCookie%20&&%20isTrackingCookie()%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20shouldBlockNonTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.shouldBlock%20&&%20cookiePolicy.shouldBlockNonTrackerCookie%20&&%20isNonTrackingCookie()%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.isFrame%20&&%20cookiePolicy.isTracker%20&&%20cookiePolicy.isThirdParty%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isNonTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.isFrame%20&&%20!cookiePolicy.isTracker%20&&%20cookiePolicy.isThirdParty%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20CookieFeature%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20load%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Feature%20is%20only%20relevant%20to%20the%20extension%20and%20windows,%20we%20should%20skip%20for%20other%20platforms%20for%20now%20as%20the%20config%20testing%20is%20broken.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.platform.name%20!==%20'extension'%20&&%20this.platform.name%20!==%20'windows')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.documentOriginIsTracker)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.isTracker%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.bundledConfig)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20use%20the%20bundled%20config%20to%20get%20a%20best-effort%20at%20the%20policy,%20before%20the%20background%20sends%20the%20real%20one%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20exceptions,%20settings%20%7D%20=%20args.bundledConfig.features.cookie;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20tabHostname%20=%20getTabHostname();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20tabExempted%20=%20true;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(tabHostname%20!=%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tabExempted%20=%20exceptions.some((exception)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20matchHostname(tabHostname,%20exception.domain)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20frameExempted%20=%20settings.excludedCookieDomains.some((exception)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20matchHostname(globalThis.location.hostname,%20exception.domain)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.shouldBlock%20=%20!frameExempted%20&&%20!tabExempted;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.policy%20=%20settings.firstPartyCookiePolicy;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20cookie%20policy%20is%20injected%20into%20every%20frame%20immediately%20so%20that%20no%20cookie%20will%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20be%20missed.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20document%20=%20globalThis.document;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cookieSetter%20=%20Object.getOwnPropertyDescriptor(globalThis.Document.prototype,%20'cookie').set;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cookieGetter%20=%20Object.getOwnPropertyDescriptor(globalThis.Document.prototype,%20'cookie').get;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20loadPolicy%20=%20new%20Promise((resolve)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadedPolicyResolve%20=%20resolve;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Create%20the%20then%20callback%20now%20-%20this%20ensures%20that%20Promise.prototype.then%20changes%20won't%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20this%20call.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20loadPolicyThen%20=%20loadPolicy.then.bind(loadPolicy);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20getCookiePolicy%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20getStackTraceOrigins(stack);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20getCookieContext%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20'getter'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldBlockTrackingCookie()%20%7C%7C%20shouldBlockNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('block',%20'3p%20frame',%20getCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20''%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(isTrackingCookie()%20%7C%7C%20isNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'3p%20frame',%20getCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'cookieSetter'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20cookieGetter.call(document)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20setCookiePolicy%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20getStackTraceOrigins(stack);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20setCookieContext%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldBlockTrackingCookie()%20%7C%7C%20shouldBlockNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('block',%20'3p%20frame',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(isTrackingCookie()%20%7C%7C%20isNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'3p%20frame',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20call%20the%20native%20document.cookie%20implementation.%20This%20will%20set%20the%20cookie%20immediately%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20if%20the%20value%20is%20valid.%20We%20will%20override%20this%20set%20later%20if%20the%20policy%20dictates%20that%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20the%20expiry%20should%20be%20changed.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'cookieSetter'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookieSetter.call(document,%20value);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20wait%20for%20config%20before%20doing%20same-site%20tests%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadPolicyThen(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20shouldBlock,%20policy%20%7D%20=%20cookiePolicy;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!shouldBlock)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'disabled',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20extract%20cookie%20expiry%20from%20cookie%20string%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20cookie%20=%20new%20Cookie(value);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20apply%20cookie%20policy%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cookie.getExpiry()%20%3E%20policy.threshold)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20check%20if%20the%20cookie%20still%20exists%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(document.cookie.split(';').findIndex(kv%20=%3E%20kv.trim().startsWith(cookie.parts%5B0%5D.trim()))%20!==%20-1)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookie.maxAge%20=%20policy.maxAge;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('restrict',%20'expiry',%20setCookieContext);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'cookieSetter'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookieSetter.apply(document,%20%5Bcookie.toString()%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'dissappeared',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'expiry',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'error',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20suppress%20error%20in%20cookie%20override%20to%20avoid%20breakage%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.warn('Error%20in%20cookie%20override',%20e);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(document,%20'cookie',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20set:%20setCookiePolicy,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20getCookiePolicy%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.cookie)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy%20=%20args.cookie;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args.cookie.debug%20=%20args.debug;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.shouldBlockTrackerCookie%20=%20this.getFeatureSettingEnabled('trackerCookie');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.shouldBlockNonTrackerCookie%20=%20this.getFeatureSettingEnabled('nonTrackerCookie');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20policy%20=%20this.getFeatureSetting('firstPartyCookiePolicy');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(policy)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.policy%20=%20policy;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20no%20cookie%20information%20-%20disable%20protections%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.shouldBlock%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20loadedPolicyResolve();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20GoogleRejected%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('browsingTopics'%20in%20Document.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Document.prototype.browsingTopics;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('joinAdInterestGroup'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.joinAdInterestGroup;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('leaveAdInterestGroup'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.leaveAdInterestGroup;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('updateAdInterestGroups'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.updateAdInterestGroups;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('runAdAuction'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.runAdAuction;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('adAuctionComponents'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.adAuctionComponents;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Throw%20away%20this%20exception,%20it's%20likely%20a%20confict%20with%20another%20extension%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Set%20Global%20Privacy%20Control%20property%20on%20DOM%0A%20%20%20%20class%20GlobalPrivacyControl%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20GPC%20on,%20set%20DOM%20property%20prototype%20to%20true%20if%20not%20already%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.globalPrivacyControlValue)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(navigator.globalPrivacyControl)%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'globalPrivacyControl',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20()%20=%3E%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20GPC%20off%20&%20unsupported%20by%20browser,%20set%20DOM%20property%20prototype%20to%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20this%20may%20be%20overwritten%20by%20the%20user%20agent%20or%20other%20extensions%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20navigator.globalPrivacyControl%20!==%20'undefined')%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'globalPrivacyControl',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20()%20=%3E%20false,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Ignore%20exceptions%20that%20could%20be%20caused%20by%20conflicting%20with%20other%20extensions%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingHardware%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20Navigator%20=%20globalThis.Navigator;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20navigator%20=%20globalThis.navigator;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('keyboard',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Navigator.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20navigator.keyboard,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS2554:%20Expected%202%20arguments,%20but%20got%201.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('keyboard')%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('hardwareConcurrency',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Navigator.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20navigator.hardwareConcurrency,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('hardwareConcurrency',%202)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('deviceMemory',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Navigator.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20navigator.deviceMemory,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('deviceMemory',%208)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Referrer%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Unfortunately,%20we%20only%20have%20limited%20information%20about%20the%20referrer%20and%20current%20frame.%20A%20single%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20page%20may%20load%20many%20requests%20and%20sub%20frames,%20all%20with%20different%20referrers.%20Since%20we%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.referrer%20&&%20//%20make%20sure%20the%20referrer%20was%20set%20correctly%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args.referrer.referrer%20!==%20undefined%20&&%20//%20referrer%20value%20will%20be%20undefined%20when%20it%20should%20be%20unchanged.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document.referrer%20&&%20//%20don't%20change%20the%20value%20if%20it%20isn't%20set%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document.referrer%20!==%20''%20&&%20//%20don't%20add%20referrer%20information%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20new%20URL(document.URL).hostname%20!==%20new%20URL(document.referrer).hostname)%20%7B%20//%20don't%20replace%20the%20referrer%20for%20the%20current%20host.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20trimmedReferer%20=%20document.referrer;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(new%20URL(document.referrer).hostname%20===%20args.referrer.referrerHost)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20make%20sure%20the%20real%20referrer%20&%20replacement%20referrer%20match%20if%20we're%20going%20to%20replace%20it%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trimmedReferer%20=%20args.referrer.referrer;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20if%20we%20don't%20have%20a%20matching%20referrer,%20just%20trim%20it%20to%20origin.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trimmedReferer%20=%20new%20URL(document.referrer).origin%20+%20'/';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('referrer',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Document.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20document.referrer,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20trimmedReferer%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20normalize%20window%20dimensions,%20if%20more%20than%20one%20monitor%20is%20in%20play.%0A%20%20%20%20%20*%20%20X/Y%20values%20are%20set%20in%20the%20browser%20based%20on%20distance%20to%20the%20main%20monitor%20top%20or%20left,%20which%0A%20%20%20%20%20*%20can%20mean%20second%20or%20more%20monitors%20have%20very%20large%20or%20negative%20values.%20This%20function%20maps%20a%20given%0A%20%20%20%20%20*%20given%20coordinate%20value%20to%20the%20proper%20place%20on%20the%20main%20screen.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20normalizeWindowDimension%20(value,%20targetDimension)%20%7B%0A%20%20%20%20%20%20%20%20if%20(value%20%3E%20targetDimension)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20value%20%25%20targetDimension%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(value%20%3C%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20targetDimension%20+%20value%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20value%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20setWindowPropertyValue%20(property,%20value)%20%7B%0A%20%20%20%20%20%20%20%20//%20Here%20we%20don't%20update%20the%20prototype%20getter%20because%20the%20values%20are%20updated%20dynamically%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(globalThis,%20property,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20()%20=%3E%20value,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20set:%20()%20=%3E%20%7B%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20origPropertyValues%20=%20%7B%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Fix%20window%20dimensions.%20The%20extension%20runs%20in%20a%20different%20JS%20context%20than%20the%0A%20%20%20%20%20*%20page,%20so%20we%20can%20inject%20the%20correct%20screen%20values%20as%20the%20window%20is%20resized,%0A%20%20%20%20%20*%20ensuring%20that%20no%20information%20is%20leaked%20as%20the%20dimensions%20change,%20but%20also%20that%20the%0A%20%20%20%20%20*%20values%20change%20correctly%20for%20valid%20use%20cases.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20setWindowDimensions%20()%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20window%20=%20globalThis;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20top%20=%20globalThis.top;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20normalizedY%20=%20normalizeWindowDimension(window.screenY,%20window.screen.height);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20normalizedX%20=%20normalizeWindowDimension(window.screenX,%20window.screen.width);%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(normalizedY%20%3C=%20origPropertyValues.availTop)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenY',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenTop',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenY',%20normalizedY);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenTop',%20normalizedY);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(top.window.outerHeight%20%3E=%20origPropertyValues.availHeight%20-%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerHeight',%20top.window.screen.height);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerHeight',%20top.window.outerHeight);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20top%20not%20accessible%20to%20certain%20iFrames,%20so%20ignore.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(normalizedX%20%3C=%20origPropertyValues.availLeft)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenX',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenLeft',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenX',%20normalizedX);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenLeft',%20normalizedX);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(top.window.outerWidth%20%3E=%20origPropertyValues.availWidth%20-%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerWidth',%20top.window.screen.width);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerWidth',%20top.window.outerWidth);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20top%20not%20accessible%20to%20certain%20iFrames,%20so%20ignore.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20in%20a%20cross%20domain%20iFrame,%20top.window%20is%20not%20accessible.%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingScreenSize%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20Screen%20=%20globalThis.Screen;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20screen%20=%20globalThis.screen;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availTop%20=%20overrideProperty('availTop',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availTop,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('availTop',%200)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availLeft%20=%20overrideProperty('availLeft',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availLeft,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('availLeft',%200)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availWidth%20=%20overrideProperty('availWidth',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availWidth,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20screen.width%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availHeight%20=%20overrideProperty('availHeight',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availHeight,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20screen.height%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('colorDepth',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.colorDepth,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('colorDepth',%2024)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('pixelDepth',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.pixelDepth,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('pixelDepth',%2024)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('resize',%20function%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowDimensions();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20setWindowDimensions();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingTemporaryStorage%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20navigator%20=%20globalThis.navigator;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20Navigator%20=%20globalThis.Navigator;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20Temporary%20storage%20can%20be%20used%20to%20determine%20hard%20disk%20usage%20and%20size.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20This%20will%20limit%20the%20max%20storage%20to%204GB%20without%20completely%20disabling%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20feature.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(navigator.webkitTemporaryStorage)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20org%20=%20navigator.webkitTemporaryStorage.queryUsageAndQuota;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20tStorage%20=%20navigator.webkitTemporaryStorage;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tStorage.queryUsageAndQuota%20=%20function%20queryUsageAndQuota%20(callback,%20err)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20modifiedCallback%20=%20function%20(usedBytes,%20grantedBytes)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20maxBytesGranted%20=%204%20*%201024%20*%201024%20*%201024;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20spoofedGrantedBytes%20=%20Math.min(grantedBytes,%20maxBytesGranted);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20callback(usedBytes,%20spoofedGrantedBytes);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20org.call(navigator.webkitTemporaryStorage,%20modifiedCallback,%20err);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'webkitTemporaryStorage',%20%7B%20get:%20()%20=%3E%20tStorage%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20NavigatorInterface%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(navigator.duckduckgo)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!args.platform%20%7C%7C%20!args.platform.name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'duckduckgo',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20platform:%20args.platform.name,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isDuckDuckGo%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGPromise.resolve(true)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20false,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20writable:%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20todo:%20Just%20ignore%20this%20exception?%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20adLabelStrings%20=%20%5B%5D;%0A%20%20%20%20const%20parser%20=%20new%20DOMParser();%0A%20%20%20%20let%20hiddenElements%20=%20new%20WeakMap();%0A%20%20%20%20let%20appliedRules%20=%20new%20Set();%0A%20%20%20%20let%20shouldInjectStyleTag%20=%20false;%0A%20%20%20%20let%20mediaAndFormSelectors%20=%20'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hide%20DOM%20element%20if%20rule%20conditions%20met%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20rule%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20%5BpreviousElement%5D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20collapseDomNode%20(element,%20rule,%20previousElement)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20type%20=%20rule.type;%0A%20%20%20%20%20%20%20%20const%20alreadyHidden%20=%20hiddenElements.has(element);%0A%0A%20%20%20%20%20%20%20%20if%20(alreadyHidden)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20switch%20(type)%20%7B%0A%20%20%20%20%20%20%20%20case%20'hide':%0A%20%20%20%20%20%20%20%20%20%20%20%20hideNode(element);%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20case%20'hide-empty':%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(isDomNodeEmpty(element))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hideNode(element);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20appliedRules.add(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20case%20'closest-empty':%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20hide%20the%20outermost%20empty%20node%20so%20that%20we%20may%20unhide%20if%20ad%20loads%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(isDomNodeEmpty(element))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20collapseDomNode(element.parentNode,%20rule,%20element);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(previousElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hideNode(previousElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20appliedRules.add(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Unhide%20previously%20hidden%20DOM%20element%20if%20content%20loaded%20into%20it%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20rule%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20%5BpreviousElement%5D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20expandNonEmptyDomNode%20(element,%20rule,%20previousElement)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20type%20=%20rule.type;%0A%0A%20%20%20%20%20%20%20%20const%20alreadyHidden%20=%20hiddenElements.has(element);%0A%0A%20%20%20%20%20%20%20%20switch%20(type)%20%7B%0A%20%20%20%20%20%20%20%20case%20'hide':%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20only%20care%20about%20rule%20types%20that%20specifically%20apply%20to%20empty%20elements%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20case%20'hide-empty':%0A%20%20%20%20%20%20%20%20case%20'closest-empty':%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(alreadyHidden%20&&%20!isDomNodeEmpty(element))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unhideNode(element);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(type%20===%20'closest-empty')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20iterate%20upwards%20from%20matching%20DOM%20elements%20until%20we%20arrive%20at%20previously%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20hidden%20element.%20Unhide%20element%20if%20it%20contains%20visible%20content.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20expandNonEmptyDomNode(element.parentNode,%20rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hide%20DOM%20element%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20hideNode%20(element)%20%7B%0A%20%20%20%20%20%20%20%20//%20maintain%20a%20reference%20to%20each%20hidden%20element%20along%20with%20the%20properties%0A%20%20%20%20%20%20%20%20//%20that%20are%20being%20overwritten%0A%20%20%20%20%20%20%20%20const%20cachedDisplayProperties%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20display:%20element.style.display,%0A%20%20%20%20%20%20%20%20%20%20%20%20'min-height':%20element.style.minHeight,%0A%20%20%20%20%20%20%20%20%20%20%20%20height:%20element.style.height%0A%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20hiddenElements.set(element,%20cachedDisplayProperties);%0A%0A%20%20%20%20%20%20%20%20//%20apply%20styles%20to%20hide%20element%0A%20%20%20%20%20%20%20%20element.style.setProperty('display',%20'none',%20'important');%0A%20%20%20%20%20%20%20%20element.style.setProperty('min-height',%20'0px',%20'important');%0A%20%20%20%20%20%20%20%20element.style.setProperty('height',%20'0px',%20'important');%0A%20%20%20%20%20%20%20%20element.hidden%20=%20true;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Show%20previously%20hidden%20DOM%20element%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20unhideNode%20(element)%20%7B%0A%20%20%20%20%20%20%20%20const%20cachedDisplayProperties%20=%20hiddenElements.get(element);%0A%20%20%20%20%20%20%20%20if%20(!cachedDisplayProperties)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20(const%20prop%20in%20cachedDisplayProperties)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20element.style.setProperty(prop,%20cachedDisplayProperties%5Bprop%5D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20hiddenElements.delete(element);%0A%20%20%20%20%20%20%20%20element.hidden%20=%20false;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Check%20if%20DOM%20element%20contains%20visible%20content%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20node%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isDomNodeEmpty%20(node)%20%7B%0A%20%20%20%20%20%20%20%20//%20no%20sense%20wasting%20cycles%20checking%20if%20the%20page's%20body%20element%20is%20empty%0A%20%20%20%20%20%20%20%20if%20(node.tagName%20===%20'BODY')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20//%20use%20a%20DOMParser%20to%20remove%20all%20metadata%20elements%20before%20checking%20if%0A%20%20%20%20%20%20%20%20//%20the%20node%20is%20empty.%0A%20%20%20%20%20%20%20%20const%20parsedNode%20=%20parser.parseFromString(node.outerHTML,%20'text/html').documentElement;%0A%20%20%20%20%20%20%20%20parsedNode.querySelectorAll('base,link,meta,script,style,template,title,desc').forEach((el)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20el.remove();%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20const%20visibleText%20=%20parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/,%20'');%0A%20%20%20%20%20%20%20%20const%20mediaAndFormContent%20=%20parsedNode.querySelector(mediaAndFormSelectors);%0A%20%20%20%20%20%20%20%20const%20frameElements%20=%20%5B...parsedNode.querySelectorAll('iframe')%5D;%0A%20%20%20%20%20%20%20%20//%20query%20original%20node%20instead%20of%20parsedNode%20for%20img%20elements%20since%20heuristic%20relies%0A%20%20%20%20%20%20%20%20//%20on%20size%20of%20image%20elements%0A%20%20%20%20%20%20%20%20const%20imageElements%20=%20%5B...node.querySelectorAll('img,svg')%5D;%0A%20%20%20%20%20%20%20%20//%20about:blank%20iframes%20don't%20count%20as%20content,%20return%20true%20if:%0A%20%20%20%20%20%20%20%20//%20-%20node%20doesn't%20contain%20any%20iframes%0A%20%20%20%20%20%20%20%20//%20-%20node%20contains%20iframes,%20all%20of%20which%20are%20hidden%20or%20have%20src='about:blank'%0A%20%20%20%20%20%20%20%20const%20noFramesWithContent%20=%20frameElements.every((frame)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(frame.hidden%20%7C%7C%20frame.src%20===%20'about:blank')%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20//%20ad%20containers%20often%20contain%20tracking%20pixels%20and%20other%20small%20images%20(eg%20adchoices%20logo).%0A%20%20%20%20%20%20%20%20//%20these%20should%20be%20treated%20as%20empty%20and%20hidden,%20but%20real%20images%20should%20not.%0A%20%20%20%20%20%20%20%20const%20visibleImages%20=%20imageElements.some((image)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(image.getBoundingClientRect().width%20%3E%2020%20%7C%7C%20image.getBoundingClientRect().height%20%3E%2020)%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20if%20((visibleText%20===%20''%20%7C%7C%20adLabelStrings.includes(visibleText))%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20mediaAndFormContent%20===%20null%20&&%20noFramesWithContent%20&&%20!visibleImages)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Apply%20relevant%20hiding%20rules%20to%20page%20at%20set%20intervals%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20applyRules%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20const%20hideTimeouts%20=%20%5B0,%20100,%20200,%20300,%20400,%20500,%201000,%201500,%202000,%202500,%203000%5D;%0A%20%20%20%20%20%20%20%20const%20unhideTimeouts%20=%20%5B750,%201500,%202250,%203000%5D;%0A%20%20%20%20%20%20%20%20const%20timeoutRules%20=%20extractTimeoutRules(rules);%0A%0A%20%20%20%20%20%20%20%20//%20several%20passes%20are%20made%20to%20hide%20&%20unhide%20elements.%20this%20is%20necessary%20because%20we're%20not%20using%0A%20%20%20%20%20%20%20%20//%20a%20mutation%20observer%20but%20we%20want%20to%20hide/unhide%20elements%20as%20soon%20as%20possible,%20and%20ads%0A%20%20%20%20%20%20%20%20//%20frequently%20take%20from%20several%20hundred%20milliseconds%20to%20several%20seconds%20to%20load%0A%20%20%20%20%20%20%20%20//%20check%20at%200ms,%20100ms,%20200ms,%20300ms,%20400ms,%20500ms,%201000ms,%201500ms,%202000ms,%202500ms,%203000ms%0A%20%20%20%20%20%20%20%20hideTimeouts.forEach((timeout)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hideAdNodes(timeoutRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20timeout);%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20//%20check%20previously%20hidden%20ad%20elements%20for%20contents,%20unhide%20if%20content%20has%20loaded%20after%20hiding.%0A%20%20%20%20%20%20%20%20//%20we%20do%20this%20in%20order%20to%20display%20non-tracking%20ads%20that%20aren't%20blocked%20at%20the%20request%20level%0A%20%20%20%20%20%20%20%20//%20check%20at%20750ms,%201500ms,%202250ms,%203000ms%0A%20%20%20%20%20%20%20%20unhideTimeouts.forEach((timeout)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unhideLoadedAds();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20timeout);%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20//%20clear%20appliedRules%20and%20hiddenElements%20caches%20once%20all%20checks%20have%20run%0A%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20appliedRules%20=%20new%20Set();%0A%20%20%20%20%20%20%20%20%20%20%20%20hiddenElements%20=%20new%20WeakMap();%0A%20%20%20%20%20%20%20%20%7D,%203100);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Separate%20strict%20hide%20rules%20to%20inject%20as%20style%20tag%20if%20enabled%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20extractTimeoutRules%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!shouldInjectStyleTag)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20rules%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20strictHideRules%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20const%20timeoutRules%20=%20%5B%5D;%0A%0A%20%20%20%20%20%20%20%20rules.forEach((rule,%20i)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(rule.type%20===%20'hide')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20strictHideRules.push(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20timeoutRules.push(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20injectStyleTag(strictHideRules);%0A%20%20%20%20%20%20%20%20return%20timeoutRules%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20styletag%20for%20strict%20hide%20rules%20and%20append%20it%20to%20the%20document%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20injectStyleTag%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20let%20styleTagContents%20=%20'';%0A%0A%20%20%20%20%20%20%20%20rules.forEach((rule,%20i)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20!==%20rules.length%20-%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleTagContents%20=%20styleTagContents.concat(rule.selector,%20',');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleTagContents%20=%20styleTagContents.concat(rule.selector);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20styleTagContents%20=%20styleTagContents.concat('%7Bdisplay:none!important;min-height:0!important;height:0!important;%7D');%0A%20%20%20%20%20%20%20%20injectGlobalStyles(styleTagContents);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Apply%20list%20of%20active%20element%20hiding%20rules%20to%20page%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20hideAdNodes%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20const%20document%20=%20globalThis.document;%0A%0A%20%20%20%20%20%20%20%20rules.forEach((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20matchingElementArray%20=%20%5B...document.querySelectorAll(rule.selector)%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20matchingElementArray.forEach((element)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20collapseDomNode(element,%20rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Iterate%20over%20previously%20hidden%20elements,%20unhiding%20if%20content%20has%20loaded%20into%20them%0A%20%20%20%20%20*/%0A%20%20%20%20function%20unhideLoadedAds%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20document%20=%20globalThis.document;%0A%0A%20%20%20%20%20%20%20%20appliedRules.forEach((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20matchingElementArray%20=%20%5B...document.querySelectorAll(rule.selector)%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20matchingElementArray.forEach((element)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20expandNonEmptyDomNode(element,%20rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20ElementHiding%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(isBeingFramed())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureName%20=%20'elementHiding';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20globalRules%20=%20this.getFeatureSetting('rules');%0A%20%20%20%20%20%20%20%20%20%20%20%20adLabelStrings%20=%20this.getFeatureSetting('adLabelStrings');%0A%20%20%20%20%20%20%20%20%20%20%20%20shouldInjectStyleTag%20=%20this.getFeatureSetting('useStrictHideStyleTag');%0A%20%20%20%20%20%20%20%20%20%20%20%20mediaAndFormSelectors%20=%20this.getFeatureSetting('mediaAndFormSelectors')%20%7C%7C%20mediaAndFormSelectors;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20determine%20whether%20strict%20hide%20rules%20should%20be%20injected%20as%20a%20style%20tag%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldInjectStyleTag)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shouldInjectStyleTag%20=%20this.matchDomainFeatureSetting('styleTagExceptions').length%20===%200;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20collect%20all%20matching%20rules%20for%20domain%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20activeDomainRules%20=%20this.matchDomainFeatureSetting('domains').flatMap((item)%20=%3E%20item.rules);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20overrideRules%20=%20activeDomainRules.filter((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20rule.type%20===%20'override'%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20activeRules%20=%20activeDomainRules.concat(globalRules);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20remove%20overrides%20and%20rules%20that%20match%20overrides%20from%20array%20of%20rules%20to%20be%20applied%20to%20page%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideRules.forEach((override)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20activeRules%20=%20activeRules.filter((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20rule.selector%20!==%20override.selector%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20now%20have%20the%20final%20list%20of%20rules%20to%20apply,%20so%20we%20apply%20them%20when%20document%20is%20loaded%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(document.readyState%20===%20'loading')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('DOMContentLoaded',%20(event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20single%20page%20applications%20don't%20have%20a%20DOMContentLoaded%20event%20on%20navigations,%20so%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20we%20use%20proxy/reflect%20on%20history.pushState%20to%20call%20applyRules%20on%20page%20navigations%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20historyMethodProxy%20=%20new%20DDGProxy(featureName,%20History.prototype,%20'pushState',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20historyMethodProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20listen%20for%20popstate%20events%20in%20order%20to%20run%20on%20back/forward%20navigations%0A%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('popstate',%20(event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20ExceptionHandler%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Report%20to%20the%20debugger%20panel%20if%20an%20uncaught%20exception%20occurs%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20handleUncaughtException%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20postDebugMessage('jsException',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20message:%20e.message,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20filename:%20e.filename,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lineno:%20e.lineno,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20colno:%20e.colno,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack:%20e.error?.stack%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20globalThis.addEventListener('error',%20handleUncaughtException);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20logoImg%20=%20'data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAA0aXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarZxpkhw5kqX/4xR1BOzLcQAFIDI36OP392BB5lY9Uy0yyWQyMsLpbgaovkVVYe781/+57l//+lcIPXeXS+t11Or5J4884uSL7r9/xvtv8Pn99/3T88/Pwl+/737/IPKtxJ/p+982f14/+X750xv9ep/11++7/vOT2H/eKPx+4/dP0ifr6/3ni+T78ft++LkQN873RR29/flS188b2a8r7n/8zr8v6/tD/+/+8o3GKu3CB6UYTwrJv//m7wqSfoc0+TPx35Aar/Np8HVJ0b1vxZ83Y0H+cnu//vT+zwv0l0X+9ZX7++r//upvix/nz/fT39ay/qwRX/zbH4Tyt++n3x8T//zB6fcVxb/+IIS4/3E7P7/v3f3e893dzJUVrT8R9RY7/HobXrhY8vT+WuVX43fh6/Z+DX51P72x5dubX/yyMEJkV64LOewwww3n/WnBuMQcT2RPYozGRul7nT0a0dgldlG/wo2NHdups5cWj2Mrc4q/ryW8zx3v8yx0PnkHXhoDb8bu/s+/3P/th/+bX+5ee0vs+++14rqiIovL0M7pv7yKDQn3Z9/KW+Bfv3623/8pfhSqmZdpmTs3OP363mKV8EdspbfPidcV/vxSKLi2f96AJeKzCxcTEjvga0gl1OBbjC0E1rGzQZMrjynHxQ6EUuLmImNOqUbXYo/6bP5OC++1scQa9W2wiY0oqabG3pBTbFbOhfhpuRNDs6SSSym1tNJdGWXWVHMttdZWBXKzpZZbabW11ttosycgsPTaW+999DniSGBgGXW00ccYc0Y3+aDJe01eP/nOiiutvMqqq62+xppG+Fi2YtWadRs2d9xpAxO77rb7Hnue4A5IcfIpp552+hlnXmLtpptvufW22++48/eu/ezqP379L3Yt/OxafDul17Xfu8Z3XWu/3iIITor2jB2LObDjTTtAQEftme8h56id0575EUmKErnIor1xO2jH2MJ8Qiw3/N67P3buP9o3V/p/tG/x/7VzTlv3/2PnHFv3z337N7u2xXP2duzLQq2pT2QfPz99utinSG3++z9H9vER0ogNiCz11FFYzM3HZH6SY2UHQOvr7LCJx9/pYxrz3JXnZbdYl+pjGens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';%0A%20%20%20%20const%20loadingImages%20=%20%7B%0A%20%20%20%20%20%20%20%20darkMode:%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252220%2522%2520height%253D%252220%2522%2520viewBox%253D%25220%25200%252020%252020%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2540keyframes%2520rotate%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520from%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%25280deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520to%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%2528359deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cg%2520style%253D%2522transform-origin%253A%252050%2525%252050%2525%253B%2520animation%253A%2520rotate%25201s%2520infinite%2520reverse%2520linear%253B%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252218.0968%2522%2520y%253D%252216.0861%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%252018.0968%252016.0861%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.1%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.4%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252219.9976%2522%2520y%253D%25228.37451%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%252019.9976%25208.37451%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.2%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252216.1727%2522%2520y%253D%25221.9917%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%252016.1727%25201.9917%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.3%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.91309%2522%2520y%253D%25226.88501%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%25208.91309%25206.88501%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25226.79602%2522%2520y%253D%252210.996%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%25206.79602%252010.996%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.7%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25227%2522%2520y%253D%25228.62549%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%25207%25208.62549%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.8%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520y%253D%252213%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.9%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fg%253E%250A%2520%2520%2520%2520%253C%252Fsvg%253E',%0A%20%20%20%20%20%20%20%20lightMode:%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252220%2522%2520height%253D%252220%2522%2520viewBox%253D%25220%25200%252020%252020%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2540keyframes%2520rotate%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520from%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%25280deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520to%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%2528359deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cg%2520style%253D%2522transform-origin%253A%252050%2525%252050%2525%253B%2520animation%253A%2520rotate%25201s%2520infinite%2520reverse%2520linear%253B%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252218.0968%2522%2520y%253D%252216.0861%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%252018.0968%252016.0861%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.1%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.4%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252219.9976%2522%2520y%253D%25228.37451%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%252019.9976%25208.37451%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.2%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252216.1727%2522%2520y%253D%25221.9917%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%252016.1727%25201.9917%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.3%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.91309%2522%2520y%253D%25226.88501%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%25208.91309%25206.88501%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25226.79602%2522%2520y%253D%252210.996%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%25206.79602%252010.996%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.7%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25227%2522%2520y%253D%25228.62549%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%25207%25208.62549%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.8%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520y%253D%252213%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.9%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fg%253E%250A%2520%2520%2520%2520%253C%252Fsvg%253E'%20//%20'data:application/octet-stream;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxzdHlsZT4KCQlAa2V5ZnJhbWVzIHJvdGF0ZSB7CgkJCWZyb20gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CgkJCX0KCQkJdG8gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMzU5ZGVnKTsKCQkJfQoJCX0KCTwvc3R5bGU+Cgk8ZyBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTAlIDUwJTsgYW5pbWF0aW9uOiByb3RhdGUgMXMgaW5maW5pdGUgcmV2ZXJzZSBsaW5lYXI7Ij4KCQk8cmVjdCB4PSIxOC4wOTY4IiB5PSIxNi4wODYxIiB3aWR0aD0iMyIgaGVpZ2h0PSI3IiByeD0iMS41IiB0cmFuc2Zvcm09InJvdGF0ZSgxMzYuMTYxIDE4LjA5NjggMTYuMDg2MSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+CQoJCTxyZWN0IHg9IjguNDk4NzgiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CgkJPHJlY3QgeD0iMTkuOTk3NiIgeT0iOC4zNzQ1MSIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgdHJhbnNmb3JtPSJyb3RhdGUoOTAgMTkuOTk3NiA4LjM3NDUxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjIiLz4KCQk8cmVjdCB4PSIxNi4xNzI3IiB5PSIxLjk5MTciIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgMTYuMTcyNyAxLjk5MTcpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuMyIvPgoJCTxyZWN0IHg9IjguOTEzMDkiIHk9IjYuODg1MDEiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDEzNi4xNjEgOC45MTMwOSA2Ljg4NTAxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KCQk8cmVjdCB4PSI2Ljc5NjAyIiB5PSIxMC45OTYiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgNi43OTYwMiAxMC45OTYpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuNyIvPgoJCTxyZWN0IHg9IjciIHk9IjguNjI1NDkiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDkwIDcgOC42MjU0OSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC44Ii8+CQkKCQk8cmVjdCB4PSI4LjQ5ODc4IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjkiLz4KCTwvZz4KPC9zdmc+Cg=='%0A%20%20%20%20%7D;%0A%20%20%20%20const%20closeIcon%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252212%2522%2520height%253D%252212%2522%2520viewBox%253D%25220%25200%252012%252012%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%253Cpath%2520fill-rule%253D%2522evenodd%2522%2520clip-rule%253D%2522evenodd%2522%2520d%253D%2522M5.99998%25204.58578L10.2426%25200.34314C10.6331%2520-0.0473839%252011.2663%2520-0.0473839%252011.6568%25200.34314C12.0474%25200.733665%252012.0474%25201.36683%252011.6568%25201.75735L7.41419%25205.99999L11.6568%252010.2426C12.0474%252010.6332%252012.0474%252011.2663%252011.6568%252011.6568C11.2663%252012.0474%252010.6331%252012.0474%252010.2426%252011.6568L5.99998%25207.41421L1.75734%252011.6568C1.36681%252012.0474%25200.733649%252012.0474%25200.343125%252011.6568C-0.0473991%252011.2663%2520-0.0473991%252010.6332%25200.343125%252010.2426L4.58577%25205.99999L0.343125%25201.75735C-0.0473991%25201.36683%2520-0.0473991%25200.733665%25200.343125%25200.34314C0.733649%2520-0.0473839%25201.36681%2520-0.0473839%25201.75734%25200.34314L5.99998%25204.58578Z%2522%2520fill%253D%2522%2523222222%2522%252F%253E%250A%253C%252Fsvg%253E';%0A%0A%20%20%20%20const%20blockedFBLogo%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252280%2522%2520height%253D%252280%2522%2520viewBox%253D%25220%25200%252080%252080%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%253Ccircle%2520cx%253D%252240%2522%2520cy%253D%252240%2522%2520r%253D%252240%2522%2520fill%253D%2522white%2522%252F%253E%250A%253Cg%2520clip-path%253D%2522url%2528%2523clip0%2529%2522%253E%250A%253Cpath%2520d%253D%2522M73.8457%252039.974C73.8457%252021.284%252058.7158%25206.15405%252040.0258%25206.15405C21.3358%25206.15405%25206.15344%252021.284%25206.15344%252039.974C6.15344%252056.884%252018.5611%252070.8622%252034.7381%252073.4275V49.764H26.0999V39.974H34.7381V32.5399C34.7381%252024.0587%252039.764%252019.347%252047.5122%252019.347C51.2293%252019.347%252055.0511%252020.0799%252055.0511%252020.0799V28.3517H50.8105C46.6222%252028.3517%252045.2611%252030.9693%252045.2611%252033.6393V39.974H54.6846L53.1664%252049.764H45.2611V73.4275C61.4381%252070.9146%252073.8457%252056.884%252073.8457%252039.974Z%2522%2520fill%253D%2522%25231877F2%2522%252F%253E%250A%253C%252Fg%253E%250A%253Crect%2520x%253D%25223.01295%2522%2520y%253D%252211.7158%2522%2520width%253D%252212.3077%2522%2520height%253D%252292.3077%2522%2520rx%253D%25226.15385%2522%2520transform%253D%2522rotate%2528-45%25203.01295%252011.7158%2529%2522%2520fill%253D%2522%2523666666%2522%2520stroke%253D%2522white%2522%2520stroke-width%253D%25226.15385%2522%252F%253E%250A%253Cdefs%253E%250A%253CclipPath%2520id%253D%2522clip0%2522%253E%250A%253Crect%2520width%253D%252267.6923%2522%2520height%253D%252267.6923%2522%2520fill%253D%2522white%2522%2520transform%253D%2522translate%25286.15344%25206.15405%2529%2522%252F%253E%250A%253C%252FclipPath%253E%250A%253C%252Fdefs%253E%250A%253C%252Fsvg%253E';%0A%0A%20%20%20%20const%20blockedYTVideo%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252275%2522%2520height%253D%252275%2522%2520viewBox%253D%25220%25200%252075%252075%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%253Crect%2520x%253D%25226.75%2522%2520y%253D%252215.75%2522%2520width%253D%252256.25%2522%2520height%253D%252239%2522%2520rx%253D%252213.5%2522%2520fill%253D%2522%2523DE5833%2522%252F%253E%250A%2520%2520%253Cmask%2520id%253D%2522path-2-outside-1_885_11045%2522%2520maskUnits%253D%2522userSpaceOnUse%2522%2520x%253D%252223.75%2522%2520y%253D%252222.5%2522%2520width%253D%252224%2522%2520height%253D%252226%2522%2520fill%253D%2522black%2522%253E%250A%2520%2520%253Crect%2520fill%253D%2522white%2522%2520x%253D%252223.75%2522%2520y%253D%252222.5%2522%2520width%253D%252224%2522%2520height%253D%252226%2522%252F%253E%250A%2520%2520%253Cpath%2520d%253D%2522M41.9425%252037.5279C43.6677%252036.492%252043.6677%252033.9914%252041.9425%252032.9555L31.0394%252026.4088C29.262%252025.3416%252027%252026.6218%252027%252028.695L27%252041.7884C27%252043.8615%252029.262%252045.1418%252031.0394%252044.0746L41.9425%252037.5279Z%2522%252F%253E%250A%2520%2520%253C%252Fmask%253E%250A%2520%2520%253Cpath%2520d%253D%2522M41.9425%252037.5279C43.6677%252036.492%252043.6677%252033.9914%252041.9425%252032.9555L31.0394%252026.4088C29.262%252025.3416%252027%252026.6218%252027%252028.695L27%252041.7884C27%252043.8615%252029.262%252045.1418%252031.0394%252044.0746L41.9425%252037.5279Z%2522%2520fill%253D%2522white%2522%252F%253E%250A%2520%2520%253Cpath%2520d%253D%2522M30.0296%252044.6809L31.5739%252047.2529L30.0296%252044.6809ZM30.0296%252025.8024L31.5739%252023.2304L30.0296%252025.8024ZM42.8944%252036.9563L44.4387%252039.5283L42.8944%252036.9563ZM41.35%252036.099L28.4852%252028.3744L31.5739%252023.2304L44.4387%252030.955L41.35%252036.099ZM30%252027.5171L30%252042.9663L24%252042.9663L24%252027.5171L30%252027.5171ZM28.4852%252042.1089L41.35%252034.3843L44.4387%252039.5283L31.5739%252047.2529L28.4852%252042.1089ZM30%252042.9663C30%252042.1888%252029.1517%252041.7087%252028.4852%252042.1089L31.5739%252047.2529C28.2413%252049.2539%252024%252046.8535%252024%252042.9663L30%252042.9663ZM28.4852%252028.3744C29.1517%252028.7746%252030%252028.2945%252030%252027.5171L24%252027.5171C24%252023.6299%252028.2413%252021.2294%252031.5739%252023.2304L28.4852%252028.3744ZM44.4387%252030.955C47.6735%252032.8974%252047.6735%252037.586%252044.4387%252039.5283L41.35%252034.3843C40.7031%252034.7728%252040.7031%252035.7105%252041.35%252036.099L44.4387%252030.955Z%2522%2520fill%253D%2522%2523BC4726%2522%2520mask%253D%2522url(%2523path-2-outside-1_885_11045)%2522%252F%253E%250A%2520%2520%253Ccircle%2520cx%253D%252257.75%2522%2520cy%253D%252252.5%2522%2520r%253D%252213.5%2522%2520fill%253D%2522%2523E0E0E0%2522%252F%253E%250A%2520%2520%253Crect%2520x%253D%252248.75%2522%2520y%253D%252250.25%2522%2520width%253D%252218%2522%2520height%253D%25224.5%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523666666%2522%252F%253E%250A%2520%2520%253Cpath%2520fill-rule%253D%2522evenodd%2522%2520clip-rule%253D%2522evenodd%2522%2520d%253D%2522M57.9853%252015.8781C58.2046%252016.1015%252058.5052%252016.2262%252058.8181%252016.2238C59.1311%252016.2262%252059.4316%252016.1015%252059.6509%252015.8781L62.9821%252012.5469C63.2974%252012.2532%252063.4272%252011.8107%252063.3206%252011.3931C63.2139%252010.9756%252062.8879%252010.6495%252062.4703%252010.5429C62.0528%252010.4363%252061.6103%252010.5661%252061.3165%252010.8813L57.9853%252014.2125C57.7627%252014.4325%252057.6374%252014.7324%252057.6374%252015.0453C57.6374%252015.3583%252057.7627%252015.6582%252057.9853%252015.8781ZM61.3598%252018.8363C61.388%252019.4872%252061.9385%252019.9919%252062.5893%252019.9637L62.6915%252019.9559L66.7769%252019.6023C67.4278%252019.5459%252067.9097%252018.9726%252067.8533%252018.3217C67.7968%252017.6708%252067.2235%252017.1889%252066.5726%252017.2453L62.4872%252017.6067C61.8363%252017.6349%252061.3316%252018.1854%252061.3598%252018.8363Z%2522%2520fill%253D%2522%2523AAAAAA%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%2520%2520%253Cpath%2520fill-rule%253D%2522evenodd%2522%2520clip-rule%253D%2522evenodd%2522%2520d%253D%2522M10.6535%252015.8781C10.4342%252016.1015%252010.1336%252016.2262%25209.82067%252016.2238C9.5077%252016.2262%25209.20717%252016.1015%25208.98787%252015.8781L5.65667%252012.5469C5.34138%252012.2532%25205.2116%252011.8107%25205.31823%252011.3931C5.42487%252010.9756%25205.75092%252010.6495%25206.16847%252010.5429C6.58602%252010.4363%25207.02848%252010.5661%25207.32227%252010.8813L10.6535%252014.2125C10.8761%252014.4325%252011.0014%252014.7324%252011.0014%252015.0453C11.0014%252015.3583%252010.8761%252015.6582%252010.6535%252015.8781ZM7.2791%252018.8362C7.25089%252019.4871%25206.7004%252019.9919%25206.04954%252019.9637L5.9474%252019.9558L1.86197%252019.6023C1.44093%252019.5658%25201.07135%252019.3074%25200.892432%252018.9246C0.713515%252018.5417%25200.752449%252018.0924%25200.994567%252017.7461C1.23669%252017.3997%25201.6452%252017.2088%25202.06624%252017.2453L6.15167%252017.6067C6.80254%252017.6349%25207.3073%252018.1854%25207.2791%252018.8362Z%2522%2520fill%253D%2522%2523AAAAAA%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%253C%252Fsvg%253E%250A';%0A%20%20%20%20const%20videoPlayDark%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252222%2522%2520height%253D%252226%2522%2520viewBox%253D%25220%25200%252022%252026%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%253Cpath%2520d%253D%2522M21%252011.2679C22.3333%252012.0377%252022.3333%252013.9622%252021%252014.732L3%252025.1244C1.66667%252025.8942%25202.59376e-06%252024.9319%25202.66105e-06%252023.3923L3.56958e-06%25202.60769C3.63688e-06%25201.06809%25201.66667%25200.105844%25203%25200.875644L21%252011.2679Z%2522%2520fill%253D%2522%2523222222%2522%252F%253E%250A%253C%252Fsvg%253E%250A';%0A%20%20%20%20const%20videoPlayLight%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252222%2522%2520height%253D%252226%2522%2520viewBox%253D%25220%25200%252022%252026%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%253Cpath%2520d%253D%2522M21%252011.2679C22.3333%252012.0377%252022.3333%252013.9622%252021%252014.732L3%252025.1244C1.66667%252025.8942%25202.59376e-06%252024.9319%25202.66105e-06%252023.3923L3.56958e-06%25202.60769C3.63688e-06%25201.06809%25201.66667%25200.105844%25203%25200.875644L21%252011.2679Z%2522%2520fill%253D%2522%2523FFFFFF%2522%252F%253E%250A%253C%252Fsvg%253E';%0A%0A%20%20%20%20const%20ddgFont%20=%20'data:application/octet-stream;base64,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';%0A%20%20%20%20const%20ddgFontBold%20=%20'data:application/octet-stream;base64,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';%0A%0A%20%20%20%20var%20localesJSON%20=%20%60%7B%22bg%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%9F%D1%80%D0%B8%20%D0%B2%D0%BB%D0%B8%D0%B7%D0%B0%D0%BD%D0%B5%20%D1%80%D0%B0%D0%B7%D1%80%D0%B5%D1%88%D0%B0%D0%B2%D0%B0%D1%82%D0%B5%20%D0%BD%D0%B0%20Facebook%20%D0%B4%D0%B0%20%D0%92%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%22,%22informationalModalMessageBody%22:%22%D0%A1%D0%BB%D0%B5%D0%B4%20%D0%BA%D0%B0%D1%82%D0%BE%20%D0%B2%D0%BB%D0%B5%D0%B7%D0%B5%D1%82%D0%B5,%20DuckDuckGo%20%D0%BD%D0%B5%20%D0%BC%D0%BE%D0%B6%D0%B5%20%D0%B4%D0%B0%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BE%D1%82%20Facebook%20%D0%B2%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5%D1%82%D0%BE%20%D0%BD%D0%B0%20%D1%82%D0%BE%D0%B7%D0%B8%20%D1%81%D0%B0%D0%B9%D1%82.%22,%22informationalModalConfirmButtonText%22:%22%D0%92%D1%85%D0%BE%D0%B4%22,%22informationalModalRejectButtonText%22:%22%D0%9D%D0%B0%D0%B7%D0%B0%D0%B4%22,%22loginButtonText%22:%22%D0%92%D1%85%D0%BE%D0%B4%20%D0%B2%D1%8A%D0%B2%20Facebook%22,%22loginBodyText%22:%22Facebook%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%20%D0%92%D0%B0%D1%88%D0%B0%D1%82%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82%20%D0%B2%20%D1%81%D1%8A%D0%BE%D1%82%D0%B2%D0%B5%D1%82%D0%BD%D0%B8%D1%8F%20%D1%81%D0%B0%D0%B9%D1%82,%20%D0%BA%D0%BE%D0%B3%D0%B0%D1%82%D0%BE%20%D0%B3%D0%BE%20%D0%B8%D0%B7%D0%BF%D0%BE%D0%BB%D0%B7%D0%B2%D0%B0%D1%82%D0%B5%20%D0%B7%D0%B0%20%D0%B2%D1%85%D0%BE%D0%B4.%22,%22buttonTextUnblockContent%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5%D1%82%D0%BE%22,%22buttonTextUnblockComment%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B0%22,%22buttonTextUnblockComments%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D1%82%D0%B5%22,%22buttonTextUnblockPost%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F%D1%82%D0%B0%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D1%82%D0%BE%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B2%D0%B0%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B7%D0%B8%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%B5%D0%B7%D0%B8%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%B0%D0%B7%D0%B8%20%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B2%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTextUnblockContent%22:%22%D0%91%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%85%D0%BC%D0%B5%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BE%D1%82%20Facebook%20%D0%BF%D1%80%D0%B8%20%D0%B7%D0%B0%D1%80%D0%B5%D0%B6%D0%B4%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0%D1%82%D0%B0.%20%D0%90%D0%BA%D0%BE%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%82%D0%B5%20%D1%82%D0%BE%D0%B2%D0%B0%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5,%20Facebook%20%D1%89%D0%B5%20%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%20%D0%92%D0%B0%D1%88%D0%B0%D1%82%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22%D0%9D%D0%B0%D1%83%D1%87%D0%B5%D1%82%D0%B5%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%87%D0%B5%22,%22readAbout%22:%22%D0%9F%D1%80%D0%BE%D1%87%D0%B5%D1%82%D0%B5%D1%82%D0%B5%20%D0%B7%D0%B0%20%D1%82%D0%B0%D0%B7%D0%B8%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0%20%D0%BD%D0%B0%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%BE%D1%81%D1%82%D1%82%D0%B0%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%90%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D1%81%D0%B8%D1%87%D0%BA%D0%B8%20%D0%BF%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%20%D0%B2%20YouTube?%22,%22informationalModalMessageBody%22:%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BD%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%20%D0%BF%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D0%B2%D0%B0%20%D0%BD%D0%B0%20Google%20(%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%B8%D0%BA%20%D0%BD%D0%B0%20YouTube)%20%D0%B4%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B8%20%D1%87%D0%B0%D1%81%D1%82%20%D0%BE%D1%82%20%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8F%D1%82%D0%B0%20%D0%B7%D0%B0%20%D0%92%D0%B0%D1%88%D0%B5%D1%82%D0%BE%20%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE,%20%D0%BD%D0%BE%20%D0%B2%D1%81%D0%B5%20%D0%BF%D0%B0%D0%BA%20%D0%BE%D1%81%D0%B8%D0%B3%D1%83%D1%80%D1%8F%D0%B2%D0%B0%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%87%D0%B5%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%BE%D1%81%D1%82%20%D0%BE%D1%82%D0%BA%D0%BE%D0%BB%D0%BA%D0%BE%D1%82%D0%BE%20%D0%BF%D1%80%D0%B8%20%D0%B2%D1%8A%D0%B7%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B6%D0%B4%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D0%BA%D0%BB%D0%B8%D0%BF%D0%B0.%22,%22informationalModalConfirmButtonText%22:%22%D0%90%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D1%81%D0%B8%D1%87%D0%BA%D0%B8%20%D0%BF%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%22,%22informationalModalRejectButtonText%22:%22%D0%9D%D0%B5,%20%D0%B1%D0%BB%D0%B0%D0%B3%D0%BE%D0%B4%D0%B0%D1%80%D1%8F%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D1%82%D0%BE%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B7%D0%B8%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D0%BA%D0%BB%D0%B8%D0%BF%20%D0%B2%20YouTube,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Google%22,%22infoTextUnblockVideo%22:%22%D0%91%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%85%D0%BC%D0%B5%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BE%D1%82%20Google%20(%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%B8%D0%BA%20%D0%BD%D0%B0%20YouTube)%20%D0%BF%D1%80%D0%B8%20%D0%B7%D0%B0%D1%80%D0%B5%D0%B6%D0%B4%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0%D1%82%D0%B0.%20%D0%90%D0%BA%D0%BE%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%82%D0%B5%20%D1%82%D0%BE%D0%B7%D0%B8%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D0%BA%D0%BB%D0%B8%D0%BF,%20Google%20%D1%89%D0%B5%20%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%20%D0%92%D0%B0%D1%88%D0%B0%D1%82%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82.%22,%22infoPreviewToggleText%22:%22%D0%9F%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D0%B5%20%D1%81%D0%B0%20%D0%B4%D0%B5%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B8%20%D0%B7%D0%B0%20%D0%BE%D1%81%D0%B8%D0%B3%D1%83%D1%80%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B4%D0%BE%D0%BF%D1%8A%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%B0%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%BE%D1%81%D1%82%22,%22infoPreviewToggleEnabledText%22:%22%D0%9F%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D0%B5%20%D1%81%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B8%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3E%D0%9D%D0%B0%D1%83%D1%87%D0%B5%D1%82%D0%B5%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%87%D0%B5%3C/a%3E%20%D0%B7%D0%B0%20%D0%B2%D0%B3%D1%80%D0%B0%D0%B4%D0%B5%D0%BD%D0%B0%D1%82%D0%B0%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0%20%D0%BE%D1%82%20%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D0%BB%D0%BD%D0%B8%20%D0%BC%D0%B5%D0%B4%D0%B8%D0%B8%20%D0%BD%D0%B0%20DuckDuckGo%22%7D%7D,%22cs%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Kdy%C5%BE%20se%20p%C5%99ihl%C3%A1s%C3%AD%C5%A1%20p%C5%99es%20Facebook,%20bude%20t%C4%9B%20moct%20sledovat%22,%22informationalModalMessageBody%22:%22Po%20p%C5%99ihl%C3%A1%C5%A1en%C3%AD%20u%C5%BE%20DuckDuckGo%20nem%C5%AF%C5%BEe%20br%C3%A1nit%20Facebooku,%20aby%20t%C4%9B%20na%20t%C3%A9hle%20str%C3%A1nce%20sledoval.%22,%22informationalModalConfirmButtonText%22:%22P%C5%99ihl%C3%A1sit%20se%22,%22informationalModalRejectButtonText%22:%22Zp%C4%9Bt%22,%22loginButtonText%22:%22P%C5%99ihl%C3%A1sit%20se%20pomoc%C3%AD%20Facebooku%22,%22loginBodyText%22:%22Facebook%20sleduje%20tvou%20aktivitu%20na%20webu,%20kdy%C5%BE%20se%20p%C5%99ihl%C3%A1s%C3%AD%C5%A1%20jeho%20prost%C5%99ednictv%C3%ADm.%22,%22buttonTextUnblockContent%22:%22Odblokovat%20obsah%22,%22buttonTextUnblockComment%22:%22Odblokovat%20koment%C3%A1%C5%99%22,%22buttonTextUnblockComments%22:%22Odblokovat%20koment%C3%A1%C5%99e%22,%22buttonTextUnblockPost%22:%22Odblokovat%20p%C5%99%C3%ADsp%C4%9Bvek%22,%22buttonTextUnblockVideo%22:%22Odblokovat%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20zablokoval%20tenhle%20obsah,%20aby%20Facebooku%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTitleUnblockComment%22:%22Slu%C5%BEba%20DuckDuckGo%20zablokovala%20tento%20koment%C3%A1%C5%99,%20aby%20Facebooku%20zabr%C3%A1nila%20ve%20tv%C3%A9m%20sledov%C3%A1n%C3%AD%22,%22infoTitleUnblockComments%22:%22Slu%C5%BEba%20DuckDuckGo%20zablokovala%20tyto%20koment%C3%A1%C5%99e,%20aby%20Facebooku%20zabr%C3%A1nila%20ve%20tv%C3%A9m%20sledov%C3%A1n%C3%AD%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20zablokoval%20tenhle%20p%C5%99%C3%ADsp%C4%9Bvek,%20aby%20Facebooku%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokoval%20tohle%20video,%20aby%20Facebooku%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTextUnblockContent%22:%22P%C5%99i%20na%C4%8D%C3%ADt%C3%A1n%C3%AD%20str%C3%A1nky%20jsme%20Facebooku%20zabr%C3%A1nili,%20aby%20t%C4%9B%20sledoval.%20Kdy%C5%BE%20tenhle%20obsah%20odblokuje%C5%A1,%20Facebook%20bude%20m%C3%ADt%20p%C5%99%C3%ADstup%20ke%20tv%C3%A9%20aktivit%C4%9B.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22V%C3%ADce%20informac%C3%AD%22,%22readAbout%22:%22P%C5%99e%C4%8Dti%20si%20o%C2%A0t%C3%A9hle%20ochran%C4%9B%20soukrom%C3%AD%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Zapnout%20v%C5%A1echny%20n%C3%A1hledy%20YouTube?%22,%22informationalModalMessageBody%22:%22Zobrazov%C3%A1n%C3%AD%20n%C3%A1hled%C5%AF%20umo%C5%BEn%C3%AD%20spole%C4%8Dnosti%20Google%20(kter%C3%A1%20vlastn%C3%AD%20YouTube)%20zobrazit%20n%C4%9Bkter%C3%A9%20informace%20o%C2%A0tv%C3%A9m%20za%C5%99%C3%ADzen%C3%AD,%20ale%20po%C5%99%C3%A1d%20jde%20o%C2%A0diskr%C3%A9tn%C4%9Bj%C5%A1%C3%AD%20volbu,%20ne%C5%BE%20je%20p%C5%99ehr%C3%A1v%C3%A1n%C3%AD%20videa.%22,%22informationalModalConfirmButtonText%22:%22Zapnout%20v%C5%A1echny%20n%C3%A1hledy%22,%22informationalModalRejectButtonText%22:%22Ne,%20d%C4%9Bkuji%22,%22buttonTextUnblockVideo%22:%22Odblokovat%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokoval%20tohle%20video%20z%C2%A0YouTube,%20aby%20Googlu%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTextUnblockVideo%22:%22Zabr%C3%A1nili%20jsme%20spole%C4%8Dnosti%20Google%20(kter%C3%A1%20vlastn%C3%AD%20YouTube),%20aby%20t%C4%9B%20p%C5%99i%20na%C4%8D%C3%ADt%C3%A1n%C3%AD%20str%C3%A1nky%20sledovala.%20Pokud%20toto%20video%20odblokuje%C5%A1,%20Google%20z%C3%ADsk%C3%A1%20p%C5%99%C3%ADstup%20ke%20tv%C3%A9%20aktivit%C4%9B.%22,%22infoPreviewToggleText%22:%22N%C3%A1hledy%20jsou%20pro%20v%C4%9Bt%C5%A1%C3%AD%20soukrom%C3%AD%20vypnut%C3%A9%22,%22infoPreviewToggleEnabledText%22:%22N%C3%A1hledy%20jsou%20zapnut%C3%A9%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EDal%C5%A1%C3%AD%20informace%3C/a%3E%20o%C2%A0ochran%C4%9B%20DuckDuckGo%20p%C5%99ed%20sledov%C3%A1n%C3%ADm%20prost%C5%99ednictv%C3%ADm%20vlo%C5%BEen%C3%A9ho%20obsahu%20ze%20soci%C3%A1ln%C3%ADch%20m%C3%A9di%C3%AD%22%7D%7D,%22da%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22N%C3%A5r%20du%20logger%20ind%20med%20Facebook,%20kan%20de%20spore%20dig%22,%22informationalModalMessageBody%22:%22N%C3%A5r%20du%20er%20logget%20ind,%20kan%20DuckDuckGo%20ikke%20blokere%20for,%20at%20indhold%20fra%20Facebook%20sporer%20dig%20p%C3%A5%20dette%20websted.%22,%22informationalModalConfirmButtonText%22:%22Log%20p%C3%A5%22,%22informationalModalRejectButtonText%22:%22G%C3%A5%20tilbage%22,%22loginButtonText%22:%22Log%20ind%20med%20Facebook%22,%22loginBodyText%22:%22Facebook%20sporer%20din%20aktivitet%20p%C3%A5%20et%20websted,%20n%C3%A5r%20du%20bruger%20dem%20til%20at%20logge%20ind.%22,%22buttonTextUnblockContent%22:%22Fjern%20blokering%20af%20indhold%22,%22buttonTextUnblockComment%22:%22Fjern%20blokering%20af%20kommentar%22,%22buttonTextUnblockComments%22:%22Fjern%20blokering%20af%20kommentarer%22,%22buttonTextUnblockPost%22:%22Fjern%20blokering%20af%20indl%C3%A6g%22,%22buttonTextUnblockVideo%22:%22Fjern%20blokering%20af%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20har%20blokeret%20dette%20indhold%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20har%20blokeret%20denne%20kommentar%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20har%20blokeret%20disse%20kommentarer%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blokerede%20dette%20indl%C3%A6g%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20har%20blokeret%20denne%20video%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTextUnblockContent%22:%22Vi%20blokerede%20for,%20at%20Facebook%20sporede%20dig,%20da%20siden%20blev%20indl%C3%A6st.%20Hvis%20du%20oph%C3%A6ver%20blokeringen%20af%20dette%20indhold,%20vil%20Facebook%20kende%20din%20aktivitet.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Mere%20info%22,%22readAbout%22:%22L%C3%A6s%20om%20denne%20beskyttelse%20af%20privatlivet%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Vil%20du%20aktivere%20alle%20YouTube-forh%C3%A5ndsvisninger?%22,%22informationalModalMessageBody%22:%22Med%20forh%C3%A5ndsvisninger%20kan%20Google%20(som%20ejer%20YouTube)%20se%20nogle%20af%20enhedens%20oplysninger,%20men%20det%20er%20stadig%20mere%20privat%20end%20at%20afspille%20videoen.%22,%22informationalModalConfirmButtonText%22:%22Aktiv%C3%A9r%20alle%20forh%C3%A5ndsvisninger%22,%22informationalModalRejectButtonText%22:%22Nej%20tak.%22,%22buttonTextUnblockVideo%22:%22Fjern%20blokering%20af%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20har%20blokeret%20denne%20YouTube-video%20for%20at%20forhindre%20Google%20i%20at%20spore%20dig%22,%22infoTextUnblockVideo%22:%22Vi%20blokerede%20Google%20(som%20ejer%20YouTube)%20fra%20at%20spore%20dig,%20da%20siden%20blev%20indl%C3%A6st.%20Hvis%20du%20fjerner%20blokeringen%20af%20denne%20video,%20vil%20Google%20f%C3%A5%20kendskab%20til%20din%20aktivitet.%22,%22infoPreviewToggleText%22:%22Forh%C3%A5ndsvisninger%20er%20deaktiveret%20for%20at%20give%20yderligere%20privatliv%22,%22infoPreviewToggleEnabledText%22:%22Forh%C3%A5ndsvisninger%20er%20deaktiveret%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EF%C3%A5%20mere%20at%20vide%20p%C3%A5%3C/a%3E%20om%20DuckDuckGos%20indbyggede%20beskyttelse%20p%C3%A5%20sociale%20medier%22%7D%7D,%22de%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Wenn%20du%20dich%20bei%20Facebook%20anmeldest,%20kann%20Facebook%20dich%20tracken%22,%22informationalModalMessageBody%22:%22Sobald%20du%20angemeldet%20bist,%20kann%20DuckDuckGo%20nicht%20mehr%20verhindern,%20dass%20Facebook-Inhalte%20dich%20auf%20dieser%20Website%20tracken.%22,%22informationalModalConfirmButtonText%22:%22Anmelden%22,%22informationalModalRejectButtonText%22:%22Zur%C3%BCck%22,%22loginButtonText%22:%22Mit%20Facebook%20anmelden%22,%22loginBodyText%22:%22Facebook%20trackt%20deine%20Aktivit%C3%A4t%20auf%20einer%20Website,%20wenn%20du%20dich%20%C3%BCber%20Facebook%20dort%20anmeldest.%22,%22buttonTextUnblockContent%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockComment%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockComments%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockPost%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockVideo%22:%22Blockierung%20aufheben%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20hat%20diesen%20Inhalt%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20hat%20diesen%20Kommentar%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20hat%20diese%20Kommentare%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20hat%20diesen%20Beitrag%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20hat%20dieses%20Video%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTextUnblockContent%22:%22Wir%20haben%20Facebook%20daran%20gehindert,%20dich%20zu%20tracken,%20als%20die%20Seite%20geladen%20wurde.%20Wenn%20du%20die%20Blockierung%20f%C3%BCr%20diesen%20Inhalt%20aufhebst,%20kennt%20Facebook%20deine%20Aktivit%C3%A4ten.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Mehr%20erfahren%22,%22readAbout%22:%22Weitere%20Informationen%20%C3%BCber%20diesen%20Datenschutz%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Alle%20YouTube-Vorschauen%20aktivieren?%22,%22informationalModalMessageBody%22:%22Durch%20das%20Anzeigen%20von%20Vorschauen%20kann%20Google%20(dem%20YouTube%20geh%C3%B6rt)%20einige%20Informationen%20zu%20deinem%20Ger%C3%A4t%20sehen.%20Dies%20ist%20aber%20immer%20noch%20privater%20als%20das%20Abspielen%20des%20Videos.%22,%22informationalModalConfirmButtonText%22:%22Alle%20Vorschauen%20aktivieren%22,%22informationalModalRejectButtonText%22:%22Nein,%20danke%22,%22buttonTextUnblockVideo%22:%22Blockierung%20aufheben%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20hat%20dieses%20YouTube-Video%20blockiert,%20um%20zu%20verhindern,%20dass%20Google%20dich%20trackt.%22,%22infoTextUnblockVideo%22:%22Wir%20haben%20Google%20(dem%20YouTube%20geh%C3%B6rt)%20daran%20gehindert,%20dich%20beim%20Laden%20der%20Seite%20zu%20tracken.%20Wenn%20du%20die%20Blockierung%20f%C3%BCr%20dieses%20Video%20aufhebst,%20kennt%20Google%20deine%20Aktivit%C3%A4ten.%22,%22infoPreviewToggleText%22:%22Vorschau%20f%C3%BCr%20mehr%20Privatsph%C3%A4re%20deaktiviert%22,%22infoPreviewToggleEnabledText%22:%22Vorschau%20aktiviert%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EErfahre%20mehr%3C/a%3E%20%C3%BCber%20den%20DuckDuckGo-Schutz%20vor%20eingebetteten%20Social%20Media-Inhalten%22%7D%7D,%22el%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%CE%97%20%CF%83%CF%8D%CE%BD%CE%B4%CE%B5%CF%83%CE%B7%20%CE%BC%CE%AD%CF%83%CF%89%20Facebook%20%CF%84%CE%BF%CF%85%CF%82%20%CE%B5%CF%80%CE%B9%CF%84%CF%81%CE%AD%CF%80%CE%B5%CE%B9%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%BF%CF%8D%CE%BD%22,%22informationalModalMessageBody%22:%22%CE%9C%CF%8C%CE%BB%CE%B9%CF%82%20%CF%83%CF%85%CE%BD%CE%B4%CE%B5%CE%B8%CE%B5%CE%AF%CF%84%CE%B5,%20%CF%84%CE%BF%20DuckDuckGo%20%CE%B4%CE%B5%CE%BD%20%CE%BC%CF%80%CE%BF%CF%81%CE%B5%CE%AF%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CF%8C%CE%BC%CE%B5%CE%BD%CE%BF%20%CF%84%CE%BF%CF%85%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%83%CE%B5%20%CE%B1%CF%85%CF%84%CF%8C%CE%BD%20%CF%84%CE%BF%CE%BD%20%CE%B9%CF%83%CF%84%CF%8C%CF%84%CE%BF%CF%80%CE%BF.%22,%22informationalModalConfirmButtonText%22:%22%CE%A3%CF%8D%CE%BD%CE%B4%CE%B5%CF%83%CE%B7%22,%22informationalModalRejectButtonText%22:%22%CE%95%CF%80%CE%B9%CF%83%CF%84%CF%81%CE%BF%CF%86%CE%AE%22,%22loginButtonText%22:%22%CE%A3%CF%8D%CE%BD%CE%B4%CE%B5%CF%83%CE%B7%20%CE%BC%CE%AD%CF%83%CF%89%20Facebook%22,%22loginBodyText%22:%22%CE%A4%CE%BF%20Facebook%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%84%CE%B7%20%CE%B4%CF%81%CE%B1%CF%83%CF%84%CE%B7%CF%81%CE%B9%CF%8C%CF%84%CE%B7%CF%84%CE%AC%20%CF%83%CE%B1%CF%82%20%CF%83%CE%B5%20%CE%AD%CE%BD%CE%B1%CE%BD%20%CE%B9%CF%83%CF%84%CF%8C%CF%84%CE%BF%CF%80%CE%BF%20%CF%8C%CF%84%CE%B1%CE%BD%20%CF%84%CE%BF%CE%BD%20%CF%87%CF%81%CE%B7%CF%83%CE%B9%CE%BC%CE%BF%CF%80%CE%BF%CE%B9%CE%B5%CE%AF%CF%84%CE%B5%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CF%83%CF%85%CE%BD%CE%B4%CE%B5%CE%B8%CE%B5%CE%AF%CF%84%CE%B5.%22,%22buttonTextUnblockContent%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CE%BF%CE%BC%CE%AD%CE%BD%CE%BF%CF%85%22,%22buttonTextUnblockComment%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CF%83%CF%87%CE%BF%CE%BB%CE%AF%CE%BF%CF%85%22,%22buttonTextUnblockComments%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CF%83%CF%87%CE%BF%CE%BB%CE%AF%CF%89%CE%BD%22,%22buttonTextUnblockPost%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B1%CE%BD%CE%AC%CF%81%CF%84%CE%B7%CF%83%CE%B7%CF%82%22,%22buttonTextUnblockVideo%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%22,%22infoTitleUnblockContent%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CF%8C%CE%BC%CE%B5%CE%BD%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockComment%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CF%83%CF%87%CF%8C%CE%BB%CE%B9%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockComments%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%B1%20%CF%83%CF%87%CF%8C%CE%BB%CE%B9%CE%B1%20%CE%B1%CF%85%CF%84%CE%AC%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockPost%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%B7%CE%BD%20%CE%B1%CE%BD%CE%AC%CF%81%CF%84%CE%B7%CF%83%CE%B7%20%CE%B1%CF%85%CF%84%CE%AE%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockVideo%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTextUnblockContent%22:%22%CE%91%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%AF%CF%83%CE%B1%CE%BC%CE%B5%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%8C%CF%84%CE%B1%CE%BD%20%CF%86%CE%BF%CF%81%CF%84%CF%8E%CE%B8%CE%B7%CE%BA%CE%B5%20%CE%B7%20%CF%83%CE%B5%CE%BB%CE%AF%CE%B4%CE%B1.%20%CE%95%CE%AC%CE%BD%20%CE%BA%CE%AC%CE%BD%CE%B5%CF%84%CE%B5%20%CE%AC%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B3%CE%B9'%20%CE%B1%CF%85%CF%84%CF%8C%20%CF%84%CE%BF%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CF%8C%CE%BC%CE%B5%CE%BD%CE%BF,%20%CF%84%CE%BF%20Facebook%20%CE%B8%CE%B1%20%CE%B3%CE%BD%CF%89%CF%81%CE%AF%CE%B6%CE%B5%CE%B9%20%CF%84%CE%B7%20%CE%B4%CF%81%CE%B1%CF%83%CF%84%CE%B7%CF%81%CE%B9%CF%8C%CF%84%CE%B7%CF%84%CE%AC%20%CF%83%CE%B1%CF%82.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22%CE%9C%CE%AC%CE%B8%CE%B5%CF%84%CE%B5%20%CF%80%CE%B5%CF%81%CE%B9%CF%83%CF%83%CF%8C%CF%84%CE%B5%CF%81%CE%B1%22,%22readAbout%22:%22%CE%94%CE%B9%CE%B1%CE%B2%CE%AC%CF%83%CF%84%CE%B5%20%CF%83%CF%87%CE%B5%CF%84%CE%B9%CE%BA%CE%AC%20%CE%BC%CE%B5%20%CF%84%CE%B7%CE%BD%20%CF%80%CE%B1%CF%81%CE%BF%CF%8D%CF%83%CE%B1%20%CF%80%CF%81%CE%BF%CF%83%CF%84%CE%B1%CF%83%CE%AF%CE%B1%CF%82%20%CF%80%CF%81%CE%BF%CF%83%CF%89%CF%80%CE%B9%CE%BA%CF%8E%CE%BD%20%CE%B4%CE%B5%CE%B4%CE%BF%CE%BC%CE%AD%CE%BD%CF%89%CE%BD%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%CE%95%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%AF%CE%B7%CF%83%CE%B7%20%CF%8C%CE%BB%CF%89%CE%BD%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CF%89%CE%BD%20%CF%84%CE%BF%CF%85%20YouTube;%22,%22informationalModalMessageBody%22:%22%CE%97%20%CF%80%CF%81%CE%BF%CE%B2%CE%BF%CE%BB%CE%AE%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CF%89%CE%BD%20%CE%B8%CE%B1%20%CE%B5%CF%80%CE%B9%CF%84%CF%81%CE%AD%CF%88%CE%B5%CE%B9%20%CF%83%CF%84%CE%B7%CE%BD%20Google%20(%CF%83%CF%84%CE%B7%CE%BD%20%CE%BF%CF%80%CE%BF%CE%AF%CE%B1%20%CE%B1%CE%BD%CE%AE%CE%BA%CE%B5%CE%B9%20%CF%84%CE%BF%20YouTube)%20%CE%BD%CE%B1%20%CE%B2%CE%BB%CE%AD%CF%80%CE%B5%CE%B9%20%CE%BF%CF%81%CE%B9%CF%83%CE%BC%CE%AD%CE%BD%CE%B5%CF%82%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%B9%CF%82%20%CF%80%CE%BB%CE%B7%CF%81%CE%BF%CF%86%CE%BF%CF%81%CE%AF%CE%B5%CF%82%20%CF%84%CE%B7%CF%82%20%CF%83%CF%85%CF%83%CE%BA%CE%B5%CF%85%CE%AE%CF%82%20%CF%83%CE%B1%CF%82,%20%CF%89%CF%83%CF%84%CF%8C%CF%83%CE%BF%20%CE%B5%CE%BE%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CE%BD%CE%B1%20%CE%B5%CE%AF%CE%BD%CE%B1%CE%B9%20%CF%80%CE%B9%CE%BF%20%CE%B9%CE%B4%CE%B9%CF%89%CF%84%CE%B9%CE%BA%CE%AE%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%B7%CE%BD%20%CE%B1%CE%BD%CE%B1%CF%80%CE%B1%CF%81%CE%B1%CE%B3%CF%89%CE%B3%CE%AE%20%CF%84%CE%BF%CF%85%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF.%22,%22informationalModalConfirmButtonText%22:%22%CE%95%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%AF%CE%B7%CF%83%CE%B7%20%CF%8C%CE%BB%CF%89%CE%BD%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CF%89%CE%BD%22,%22informationalModalRejectButtonText%22:%22%CE%8C%CF%87%CE%B9,%20%CE%B5%CF%85%CF%87%CE%B1%CF%81%CE%B9%CF%83%CF%84%CF%8E%22,%22buttonTextUnblockVideo%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%22,%22infoTitleUnblockVideo%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CF%83%CF%84%CE%BF%20YouTube%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%B7%CE%BD%20Google%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTextUnblockVideo%22:%22%CE%91%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%AF%CF%83%CE%B1%CE%BC%CE%B5%20%CF%84%CE%B7%CE%BD%20Google%20(%CF%83%CF%84%CE%B7%CE%BD%20%CE%BF%CF%80%CE%BF%CE%AF%CE%B1%20%CE%B1%CE%BD%CE%AE%CE%BA%CE%B5%CE%B9%20%CF%84%CE%BF%20YouTube)%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%8C%CF%84%CE%B1%CE%BD%20%CF%86%CE%BF%CF%81%CF%84%CF%8E%CE%B8%CE%B7%CE%BA%CE%B5%20%CE%B7%20%CF%83%CE%B5%CE%BB%CE%AF%CE%B4%CE%B1.%20%CE%95%CE%AC%CE%BD%20%CE%BA%CE%AC%CE%BD%CE%B5%CF%84%CE%B5%20%CE%AC%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B3%CE%B9'%20%CE%B1%CF%85%CF%84%CF%8C%20%CF%84%CE%BF%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF,%20%CE%B7%20Google%20%CE%B8%CE%B1%20%CE%B3%CE%BD%CF%89%CF%81%CE%AF%CE%B6%CE%B5%CE%B9%20%CF%84%CE%B7%20%CE%B4%CF%81%CE%B1%CF%83%CF%84%CE%B7%CF%81%CE%B9%CF%8C%CF%84%CE%B7%CF%84%CE%AC%20%CF%83%CE%B1%CF%82.%22,%22infoPreviewToggleText%22:%22%CE%9F%CE%B9%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CE%B9%CF%82%20%CE%B1%CF%80%CE%B5%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%B9%CE%AE%CE%B8%CE%B7%CE%BA%CE%B1%CE%BD%20%CE%B3%CE%B9%CE%B1%20%CF%80%CF%81%CF%8C%CF%83%CE%B8%CE%B5%CF%84%CE%B7%20%CF%80%CF%81%CE%BF%CF%83%CF%84%CE%B1%CF%83%CE%AF%CE%B1%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CF%83%CF%89%CF%80%CE%B9%CE%BA%CF%8E%CE%BD%20%CE%B4%CE%B5%CE%B4%CE%BF%CE%BC%CE%AD%CE%BD%CF%89%CE%BD%22,%22infoPreviewToggleEnabledText%22:%22%CE%9F%CE%B9%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CE%B9%CF%82%20%CE%B5%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%B9%CE%AE%CE%B8%CE%B7%CE%BA%CE%B1%CE%BD%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3E%CE%9C%CE%AC%CE%B8%CE%B5%CF%84%CE%B5%20%CF%80%CE%B5%CF%81%CE%B9%CF%83%CF%83%CF%8C%CF%84%CE%B5%CF%81%CE%B1%3C/a%3E%20%CE%B3%CE%B9%CE%B1%20%CF%84%CE%B7%CE%BD%20%CE%B5%CE%BD%CF%83%CF%89%CE%BC%CE%B1%CF%84%CF%89%CE%BC%CE%AD%CE%BD%CE%B7%20%CF%80%CF%81%CE%BF%CF%83%CF%84%CE%B1%CF%83%CE%AF%CE%B1%20%CE%BA%CE%BF%CE%B9%CE%BD%CF%89%CE%BD%CE%B9%CE%BA%CF%8E%CE%BD%20%CE%BC%CE%AD%CF%83%CF%89%CE%BD%20DuckDuckGo%22%7D%7D,%22en%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Logging%20in%20with%20Facebook%20lets%20them%20track%20you%22,%22informationalModalMessageBody%22:%22Once%20you're%20logged%20in,%20DuckDuckGo%20can't%20block%20Facebook%20content%20from%20tracking%20you%20on%20this%20site.%22,%22informationalModalConfirmButtonText%22:%22Log%20In%22,%22informationalModalRejectButtonText%22:%22Go%20back%22,%22loginButtonText%22:%22Log%20in%20with%20Facebook%22,%22loginBodyText%22:%22Facebook%20tracks%20your%20activity%20on%20a%20site%20when%20you%20use%20them%20to%20login.%22,%22buttonTextUnblockContent%22:%22Unblock%20Content%22,%22buttonTextUnblockComment%22:%22Unblock%20Comment%22,%22buttonTextUnblockComments%22:%22Unblock%20Comments%22,%22buttonTextUnblockPost%22:%22Unblock%20Post%22,%22buttonTextUnblockVideo%22:%22Unblock%20Video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blocked%20this%20content%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blocked%20this%20comment%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blocked%20these%20comments%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blocked%20this%20post%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blocked%20this%20video%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTextUnblockContent%22:%22We%20blocked%20Facebook%20from%20tracking%20you%20when%20the%20page%20loaded.%20If%20you%20unblock%20this%20content,%20Facebook%20will%20know%20your%20activity.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Learn%20More%22,%22readAbout%22:%22Read%20about%20this%20privacy%20protection%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Enable%20all%20YouTube%20previews?%22,%22informationalModalMessageBody%22:%22Showing%20previews%20will%20allow%20Google%20(which%20owns%20YouTube)%20to%20see%20some%20of%20your%20device%E2%80%99s%20information,%20but%20is%20still%20more%20private%20than%20playing%20the%20video.%22,%22informationalModalConfirmButtonText%22:%22Enable%20All%20Previews%22,%22informationalModalRejectButtonText%22:%22No%20Thanks%22,%22buttonTextUnblockVideo%22:%22Unblock%20Video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blocked%20this%20YouTube%20video%20to%20prevent%20Google%20from%20tracking%20you%22,%22infoTextUnblockVideo%22:%22We%20blocked%20Google%20(which%20owns%20YouTube)%20from%20tracking%20you%20when%20the%20page%20loaded.%20If%20you%20unblock%20this%20video,%20Google%20will%20know%20your%20activity.%22,%22infoPreviewToggleText%22:%22Previews%20disabled%20for%20additional%20privacy%22,%22infoPreviewToggleEnabledText%22:%22Previews%20enabled%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ELearn%20more%3C/a%3E%20about%20DuckDuckGo%20Embedded%20Social%20Media%20Protection%22%7D%7D,%22es%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Al%20iniciar%20sesi%C3%B3n%20en%20Facebook,%20les%20permites%20que%20te%20rastreen%22,%22informationalModalMessageBody%22:%22Una%20vez%20que%20hayas%20iniciado%20sesi%C3%B3n,%20DuckDuckGo%20no%20puede%20bloquear%20el%20contenido%20de%20Facebook%20para%20que%20no%20te%20rastree%20en%20este%20sitio.%22,%22informationalModalConfirmButtonText%22:%22Iniciar%20sesi%C3%B3n%22,%22informationalModalRejectButtonText%22:%22Volver%20atr%C3%A1s%22,%22loginButtonText%22:%22Iniciar%20sesi%C3%B3n%20con%20Facebook%22,%22loginBodyText%22:%22Facebook%20rastrea%20tu%20actividad%20en%20un%20sitio%20web%20cuando%20lo%20usas%20para%20iniciar%20sesi%C3%B3n.%22,%22buttonTextUnblockContent%22:%22Desbloquear%20contenido%22,%22buttonTextUnblockComment%22:%22Desbloquear%20comentario%22,%22buttonTextUnblockComments%22:%22Desbloquear%20comentarios%22,%22buttonTextUnblockPost%22:%22Desbloquear%20publicaci%C3%B3n%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20v%C3%ADdeo%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20ha%20bloqueado%20este%20contenido%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20ha%20bloqueado%20este%20comentario%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20ha%20bloqueado%20estos%20comentarios%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20ha%20bloqueado%20esta%20publicaci%C3%B3n%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloqueado%20este%20v%C3%ADdeo%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTextUnblockContent%22:%22Hemos%20bloqueado%20el%20rastreo%20de%20Facebook%20cuando%20se%20ha%20cargado%20la%20p%C3%A1gina.%20Si%20desbloqueas%20este%20contenido,%20Facebook%20tendr%C3%A1%20conocimiento%20de%20tu%20actividad.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22M%C3%A1s%20informaci%C3%B3n%22,%22readAbout%22:%22Lee%20acerca%20de%20esta%20protecci%C3%B3n%20de%20privacidad%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%C2%BFHabilitar%20todas%20las%20vistas%20previas%20de%20YouTube?%22,%22informationalModalMessageBody%22:%22Mostrar%20vistas%20previas%20permitir%C3%A1%20a%20Google%20(que%20es%20el%20propietario%20de%20YouTube)%20ver%20parte%20de%20la%20informaci%C3%B3n%20de%20tu%20dispositivo,%20pero%20sigue%20siendo%20m%C3%A1s%20privado%20que%20reproducir%20el%20v%C3%ADdeo.%22,%22informationalModalConfirmButtonText%22:%22Habilitar%20todas%20las%20vistas%20previas%22,%22informationalModalRejectButtonText%22:%22No,%20gracias%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20v%C3%ADdeo%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloqueado%20este%20v%C3%ADdeo%20de%20YouTube%20para%20evitar%20que%20Google%20te%20rastree%22,%22infoTextUnblockVideo%22:%22Hemos%20bloqueado%20el%20rastreo%20de%20Google%20(que%20es%20el%20propietario%20de%20YouTube)%20al%20cargarse%20la%20p%C3%A1gina.%20Si%20desbloqueas%20este%20v%C3%ADdeo,%20Goggle%20tendr%C3%A1%20conocimiento%20de%20tu%20actividad.%22,%22infoPreviewToggleText%22:%22Vistas%20previas%20desactivadas%20para%20mayor%20privacidad%22,%22infoPreviewToggleEnabledText%22:%22Vistas%20previas%20activadas%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EM%C3%A1s%20informaci%C3%B3n%3C/a%3E%20sobre%20la%20protecci%C3%B3n%20integrada%20de%20redes%20sociales%20DuckDuckGo%22%7D%7D,%22et%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Kui%20logid%20Facebookiga%20sisse,%20saab%20Facebook%20sind%20j%C3%A4lgida%22,%22informationalModalMessageBody%22:%22Kui%20oled%20sisse%20logitud,%20ei%20saa%20DuckDuckGo%20blokeerida%20Facebooki%20sisu%20sind%20j%C3%A4lgimast.%22,%22informationalModalConfirmButtonText%22:%22Logi%20sisse%22,%22informationalModalRejectButtonText%22:%22Mine%20tagasi%22,%22loginButtonText%22:%22Logi%20sisse%20Facebookiga%22,%22loginBodyText%22:%22Kui%20logid%20sisse%20Facebookiga,%20saab%20Facebook%20sinu%20tegevust%20saidil%20j%C3%A4lgida.%22,%22buttonTextUnblockContent%22:%22Deblokeeri%20sisu%22,%22buttonTextUnblockComment%22:%22Deblokeeri%20kommentaar%22,%22buttonTextUnblockComments%22:%22Deblokeeri%20kommentaarid%22,%22buttonTextUnblockPost%22:%22Deblokeeri%20postitus%22,%22buttonTextUnblockVideo%22:%22Deblokeeri%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blokeeris%20selle%20sisu,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blokeeris%20selle%20kommentaari,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blokeeris%20need%20kommentaarid,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blokeeris%20selle%20postituse,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokeeris%20selle%20video,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTextUnblockContent%22:%22Blokeerisime%20lehe%20laadimise%20ajal%20Facebooki%20jaoks%20sinu%20j%C3%A4lgimise.%20Kui%20sa%20selle%20sisu%20deblokeerid,%20saab%20Facebook%20sinu%20tegevust%20j%C3%A4lgida.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Loe%20edasi%22,%22readAbout%22:%22Loe%20selle%20privaatsuskaitse%20kohta%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Kas%20lubada%20k%C3%B5ik%20YouTube%E2%80%99i%20eelvaated?%22,%22informationalModalMessageBody%22:%22Eelvaate%20n%C3%A4itamine%20v%C3%B5imaldab%20Google%E2%80%99il%20(kellele%20YouTube%20kuulub)%20n%C3%A4ha%20osa%20sinu%20seadme%20teabest,%20kuid%20see%20on%20siiski%20privaatsem%20kui%20video%20esitamine.%22,%22informationalModalConfirmButtonText%22:%22Luba%20k%C3%B5ik%20eelvaated%22,%22informationalModalRejectButtonText%22:%22Ei%20ait%C3%A4h%22,%22buttonTextUnblockVideo%22:%22Deblokeeri%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokeeris%20selle%20YouTube%E2%80%99i%20video,%20et%20takistada%20Google%E2%80%99it%20sind%20j%C3%A4lgimast%22,%22infoTextUnblockVideo%22:%22Me%20blokeerisime%20lehe%20laadimise%20ajal%20Google%E2%80%99i%20(kellele%20YouTube%20kuulub)%20j%C3%A4lgimise.%20Kui%20sa%20selle%20video%20deblokeerid,%20saab%20Google%20sinu%20tegevusest%20teada.%22,%22infoPreviewToggleText%22:%22Eelvaated%20on%20t%C3%A4iendava%20privaatsuse%20tagamiseks%20keelatud%22,%22infoPreviewToggleEnabledText%22:%22Eelvaated%20on%20lubatud%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ELisateave%3C/a%3E%20DuckDuckGo%20sisseehitatud%20sotsiaalmeediakaitse%20kohta%22%7D%7D,%22fi%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Kun%20kirjaudut%20sis%C3%A4%C3%A4n%20Facebook-tunnuksilla,%20Facebook%20voi%20seurata%20sinua%22,%22informationalModalMessageBody%22:%22Kun%20olet%20kirjautunut%20sis%C3%A4%C3%A4n,%20DuckDuckGo%20ei%20voi%20est%C3%A4%C3%A4%20Facebook-sis%C3%A4lt%C3%B6%C3%A4%20seuraamasta%20sinua%20t%C3%A4ll%C3%A4%20sivustolla.%22,%22informationalModalConfirmButtonText%22:%22Kirjaudu%20sis%C3%A4%C3%A4n%22,%22informationalModalRejectButtonText%22:%22Edellinen%22,%22loginButtonText%22:%22Kirjaudu%20sis%C3%A4%C3%A4n%20Facebook-tunnuksilla%22,%22loginBodyText%22:%22Facebook%20seuraa%20toimintaasi%20sivustolla,%20kun%20kirjaudut%20sis%C3%A4%C3%A4n%20sen%20kautta.%22,%22buttonTextUnblockContent%22:%22Poista%20sis%C3%A4ll%C3%B6n%20esto%22,%22buttonTextUnblockComment%22:%22Poista%20kommentin%20esto%22,%22buttonTextUnblockComments%22:%22Poista%20kommenttien%20esto%22,%22buttonTextUnblockPost%22:%22Poista%20julkaisun%20esto%22,%22buttonTextUnblockVideo%22:%22Poista%20videon%20esto%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20sis%C3%A4ll%C3%B6n%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20kommentin%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20esti%20n%C3%A4m%C3%A4%20kommentit%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20julkaisun%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20videon%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTextUnblockContent%22:%22Estimme%20Facebookia%20seuraamasta%20sinua,%20kun%20sivua%20ladattiin.%20Jos%20poistat%20t%C3%A4m%C3%A4n%20sis%C3%A4ll%C3%B6n%20eston,%20Facebook%20saa%20tiet%C3%A4%C3%A4%20toimintasi.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Lue%20lis%C3%A4%C3%A4%22,%22readAbout%22:%22Lue%20t%C3%A4st%C3%A4%20yksityisyydensuojasta%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Otetaanko%20k%C3%A4ytt%C3%B6%C3%B6n%20kaikki%20YouTube-esikatselut?%22,%22informationalModalMessageBody%22:%22Kun%20sallit%20esikatselun,%20Google%20(joka%20omistaa%20YouTuben)%20voi%20n%C3%A4hd%C3%A4%20joitakin%20laitteesi%20tietoja,%20mutta%20se%20on%20silti%20yksityisemp%C3%A4%C3%A4%20kuin%20videon%20toistaminen.%22,%22informationalModalConfirmButtonText%22:%22Ota%20k%C3%A4ytt%C3%B6%C3%B6n%20kaikki%20esikatselut%22,%22informationalModalRejectButtonText%22:%22Ei%20kiitos%22,%22buttonTextUnblockVideo%22:%22Poista%20videon%20esto%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20YouTube-videon,%20jotta%20Google%20ei%20voi%20seurata%20sinua%22,%22infoTextUnblockVideo%22:%22Estimme%20Googlea%20(joka%20omistaa%20YouTuben)%20seuraamasta%20sinua,%20kun%20sivua%20ladattiin.%20Jos%20poistat%20t%C3%A4m%C3%A4n%20videon%20eston,%20Google%20tiet%C3%A4%C3%A4%20toimintasi.%22,%22infoPreviewToggleText%22:%22Esikatselut%20on%20poistettu%20k%C3%A4yt%C3%B6st%C3%A4%20yksityisyyden%20lis%C3%A4%C3%A4miseksi%22,%22infoPreviewToggleEnabledText%22:%22Esikatselut%20k%C3%A4yt%C3%B6ss%C3%A4%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ELue%20lis%C3%A4%C3%A4%3C/a%3E%20DuckDuckGon%20upotetusta%20sosiaalisen%20median%20suojauksesta%22%7D%7D,%22fr%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22L'identification%20via%20Facebook%20leur%20permet%20de%20vous%20pister%22,%22informationalModalMessageBody%22:%22Une%20fois%20que%20vous%20%C3%AAtes%20connect%C3%A9(e),%20DuckDuckGo%20ne%20peut%20pas%20emp%C3%AAcher%20le%20contenu%20Facebook%20de%20vous%20pister%20sur%20ce%20site.%22,%22informationalModalConfirmButtonText%22:%22Connexion%22,%22informationalModalRejectButtonText%22:%22Revenir%20en%20arri%C3%A8re%22,%22loginButtonText%22:%22S'identifier%20avec%20Facebook%22,%22loginBodyText%22:%22Facebook%20piste%20votre%20activit%C3%A9%20sur%20un%20site%20lorsque%20vous%20l'utilisez%20pour%20vous%20identifier.%22,%22buttonTextUnblockContent%22:%22D%C3%A9bloquer%20le%20contenu%22,%22buttonTextUnblockComment%22:%22D%C3%A9bloquer%20le%20commentaire%22,%22buttonTextUnblockComments%22:%22D%C3%A9bloquer%20les%20commentaires%22,%22buttonTextUnblockPost%22:%22D%C3%A9bloquer%20la%20publication%22,%22buttonTextUnblockVideo%22:%22D%C3%A9bloquer%20la%20vid%C3%A9o%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20ce%20contenu%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20suivre%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20ce%20commentaire%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20suivre%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20ces%20commentaires%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20suivre%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20cette%20publication%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20pister%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20cette%20vid%C3%A9o%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20pister%22,%22infoTextUnblockContent%22:%22Nous%20avons%20emp%C3%AAch%C3%A9%20Facebook%20de%20vous%20pister%20lors%20du%20chargement%20de%20la%20page.%20Si%20vous%20d%C3%A9bloquez%20ce%20contenu,%20Facebook%20conna%C3%AEtra%20votre%20activit%C3%A9.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22En%20savoir%20plus%22,%22readAbout%22:%22En%20savoir%20plus%20sur%20cette%20protection%20de%20la%20confidentialit%C3%A9%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Activer%20tous%20les%20aper%C3%A7us%20YouTube%C2%A0?%22,%22informationalModalMessageBody%22:%22L'affichage%20des%20aper%C3%A7us%20permettra%20%C3%A0%20Google%20(propri%C3%A9taire%20de%20YouTube)%20de%20voir%20certaines%20informations%20de%20votre%20appareil,%20mais%20cela%20reste%20davantage%20confidentiel%20qu'en%20lisant%20la%20vid%C3%A9o.%22,%22informationalModalConfirmButtonText%22:%22Activer%20tous%20les%20aper%C3%A7us%22,%22informationalModalRejectButtonText%22:%22Non%20merci%22,%22buttonTextUnblockVideo%22:%22D%C3%A9bloquer%20la%20vid%C3%A9o%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20cette%20vid%C3%A9o%20YouTube%20pour%20emp%C3%AAcher%20Google%20de%20vous%20pister%22,%22infoTextUnblockVideo%22:%22Nous%20avons%20emp%C3%AAch%C3%A9%20Google%20(propri%C3%A9taire%20de%20YouTube)%20de%20vous%20pister%20lors%20du%20chargement%20de%20la%20page.%20Si%20vous%20d%C3%A9bloquez%20cette%20vid%C3%A9o,%20Google%20conna%C3%AEtra%20votre%20activit%C3%A9.%22,%22infoPreviewToggleText%22:%22Aper%C3%A7us%20d%C3%A9sactiv%C3%A9s%20pour%20plus%20de%20confidentialit%C3%A9%22,%22infoPreviewToggleEnabledText%22:%22Aper%C3%A7us%20activ%C3%A9s%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EEn%20savoir%20plus%3C/a%3E%20sur%20la%20protection%20int%C3%A9gr%C3%A9e%20DuckDuckGo%20des%20r%C3%A9seaux%20sociaux%22%7D%7D,%22hr%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Prijava%20putem%20Facebooka%20omogu%C4%87uje%20im%20da%20te%20prate%22,%22informationalModalMessageBody%22:%22Nakon%20%C5%A1to%20se%20prijavi%C5%A1,%20DuckDuckGo%20ne%20mo%C5%BEe%20blokirati%20Facebookov%20sadr%C5%BEaj%20da%20te%20prati%20na%20Facebooku.%22,%22informationalModalConfirmButtonText%22:%22Prijavljivanje%22,%22informationalModalRejectButtonText%22:%22Vrati%20se%22,%22loginButtonText%22:%22Prijavi%20se%20putem%20Facebooka%22,%22loginBodyText%22:%22Facebook%20prati%20tvoju%20aktivnost%20na%20toj%20web%20lokaciji%20kad%20je%20koristi%C5%A1%20za%20prijavu.%22,%22buttonTextUnblockContent%22:%22Deblokiranje%20sadr%C5%BEaja%22,%22buttonTextUnblockComment%22:%22Deblokiranje%20komentara%22,%22buttonTextUnblockComments%22:%22Deblokiranje%20komentara%22,%22buttonTextUnblockPost%22:%22Deblokiranje%20objave%22,%22buttonTextUnblockVideo%22:%22Deblokiranje%20videozapisa%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20sadr%C5%BEaj%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20komentar%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20je%20blokirao%20ove%20komentare%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20je%20blokirao%20ovu%20objavu%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20video%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTextUnblockContent%22:%22Blokirali%20smo%20Facebook%20da%20te%20prati%20kad%20se%20stranica%20u%C4%8Dita.%20Ako%20deblokira%C5%A1%20ovaj%20sadr%C5%BEaj,%20Facebook%20%C4%87e%20znati%20tvoju%20aktivnost.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Saznajte%20vi%C5%A1e%22,%22readAbout%22:%22Pro%C4%8Ditaj%20vi%C5%A1e%20o%20ovoj%20za%C5%A1titi%20privatnosti%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Omogu%C4%87iti%20sve%20YouTube%20pretpreglede?%22,%22informationalModalMessageBody%22:%22Prikazivanje%20pretpregleda%20omogu%C4%87it%20%C4%87e%20Googleu%20(u%20%C4%8Dijem%20je%20vlasni%C5%A1tvu%20YouTube)%20da%20vidi%20neke%20podatke%20o%20tvom%20ure%C4%91aju,%20ali%20je%20i%20dalje%20privatnija%20opcija%20od%20reprodukcije%20videozapisa.%22,%22informationalModalConfirmButtonText%22:%22Omogu%C4%87i%20sve%20pretpreglede%22,%22informationalModalRejectButtonText%22:%22Ne,%20hvala%22,%22buttonTextUnblockVideo%22:%22Deblokiranje%20videozapisa%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20YouTube%20videozapis%20kako%20bi%20sprije%C4%8Dio%20Google%20da%20te%20prati%22,%22infoTextUnblockVideo%22:%22Blokirali%20smo%20Google%20(u%20%C4%8Dijem%20je%20vlasni%C5%A1tvu%20YouTube)%20da%20te%20prati%20kad%20se%20stranica%20u%C4%8Dita.%20Ako%20deblokira%C5%A1%20ovaj%20videozapis,%20Google%20%C4%87e%20znati%20tvoju%20aktivnost.%22,%22infoPreviewToggleText%22:%22Pretpregledi%20su%20onemogu%C4%87eni%20radi%20dodatne%20privatnosti%22,%22infoPreviewToggleEnabledText%22:%22Pretpregledi%20su%20omogu%C4%87eni%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ESaznaj%20vi%C5%A1e%3C/a%3E%20o%20uklju%C4%8Denoj%20DuckDuckGo%20za%C5%A1titi%20od%20dru%C5%A1tvenih%20medija%22%7D%7D,%22hu%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22A%20Facebookkal%20val%C3%B3%20bejelentkez%C3%A9skor%20a%20Facebook%20nyomon%20k%C3%B6vethet%22,%22informationalModalMessageBody%22:%22Miut%C3%A1n%20bejelentkezel,%20a%20DuckDuckGo%20nem%20fogja%20tudni%20blokkolni%20a%20Facebook-tartalmat,%20amely%20nyomon%20k%C3%B6vet%20ezen%20az%20oldalon.%22,%22informationalModalConfirmButtonText%22:%22Bejelentkez%C3%A9s%22,%22informationalModalRejectButtonText%22:%22Visszal%C3%A9p%C3%A9s%22,%22loginButtonText%22:%22Bejelentkez%C3%A9s%20Facebookkal%22,%22loginBodyText%22:%22Ha%20a%20Facebookkal%20jelentkezel%20be,%20nyomon%20k%C3%B6vetik%20a%20webhelyen%20v%C3%A9gzett%20tev%C3%A9kenys%C3%A9gedet.%22,%22buttonTextUnblockContent%22:%22Tartalom%20felold%C3%A1sa%22,%22buttonTextUnblockComment%22:%22Hozz%C3%A1sz%C3%B3l%C3%A1s%20felold%C3%A1sa%22,%22buttonTextUnblockComments%22:%22Hozz%C3%A1sz%C3%B3l%C3%A1sok%20felold%C3%A1sa%22,%22buttonTextUnblockPost%22:%22Bejegyz%C3%A9s%20felold%C3%A1sa%22,%22buttonTextUnblockVideo%22:%22Vide%C3%B3%20felold%C3%A1sa%22,%22infoTitleUnblockContent%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20tartalmat,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockComment%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20hozz%C3%A1sz%C3%B3l%C3%A1st,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockComments%22:%22A%20DuckDuckGo%20blokkolta%20ezeket%20a%20hozz%C3%A1sz%C3%B3l%C3%A1sokat,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockPost%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20bejegyz%C3%A9st,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockVideo%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20vide%C3%B3t,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTextUnblockContent%22:%22Az%20oldal%20bet%C3%B6lt%C3%A9sekor%20blokkoltuk%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben.%20Ha%20feloldod%20ezt%20a%20tartalmat,%20a%20Facebook%20tudni%20fogja,%20hogy%20milyen%20tev%C3%A9kenys%C3%A9get%20v%C3%A9gzel.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Tov%C3%A1bbi%20r%C3%A9szletek%22,%22readAbout%22:%22Tudj%20meg%20t%C3%B6bbet%20err%C5%91l%20az%20adatv%C3%A9delemr%C5%91l%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Enged%C3%A9lyezed%20minden%20YouTube-vide%C3%B3%20el%C5%91n%C3%A9zet%C3%A9t?%22,%22informationalModalMessageBody%22:%22Az%20el%C5%91n%C3%A9zetek%20megjelen%C3%ADt%C3%A9s%C3%A9vel%20a%20Google%20(a%20YouTube%20tulajdonosa)%20l%C3%A1thatja%20a%20k%C3%A9sz%C3%BCl%C3%A9k%20n%C3%A9h%C3%A1ny%20adat%C3%A1t,%20de%20ez%20adatv%C3%A9delmi%20szempontb%C3%B3l%20m%C3%A9g%20mindig%20el%C5%91ny%C3%B6sebb,%20mint%20a%20vide%C3%B3%20lej%C3%A1tsz%C3%A1sa.%22,%22informationalModalConfirmButtonText%22:%22Minden%20el%C5%91n%C3%A9zet%20enged%C3%A9lyez%C3%A9se%22,%22informationalModalRejectButtonText%22:%22Nem,%20k%C3%B6sz%C3%B6n%C3%B6m%22,%22buttonTextUnblockVideo%22:%22Vide%C3%B3%20felold%C3%A1sa%22,%22infoTitleUnblockVideo%22:%22A%20DuckDuckGo%20blokkolta%20a%20YouTube-vide%C3%B3t,%20hogy%20a%20Google%20ne%20k%C3%B6vethessen%20nyomon%22,%22infoTextUnblockVideo%22:%22Blokkoltuk,%20hogy%20a%20Google%20(a%20YouTube%20tulajdonosa)%20nyomon%20k%C3%B6vethessen%20az%20oldal%20bet%C3%B6lt%C3%A9sekor.%20Ha%20feloldod%20a%20vide%C3%B3%20blokkol%C3%A1s%C3%A1t,%20a%20Google%20tudni%20fogja,%20hogy%20milyen%20tev%C3%A9kenys%C3%A9get%20v%C3%A9gzel.%22,%22infoPreviewToggleText%22:%22Az%20el%C5%91n%C3%A9zetek%20a%20fokozott%20adatv%C3%A9delem%20%C3%A9rdek%C3%A9ben%20letiltva%22,%22infoPreviewToggleEnabledText%22:%22Az%20el%C5%91n%C3%A9zetek%20enged%C3%A9lyezve%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ETov%C3%A1bbi%20tudnival%C3%B3k%3C/a%3E%20a%20DuckDuckGo%20be%C3%A1gyazott%20k%C3%B6z%C3%B6ss%C3%A9gi%20m%C3%A9dia%20elleni%20v%C3%A9delm%C3%A9r%C5%91l%22%7D%7D,%22it%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22L'accesso%20con%20Facebook%20consente%20di%20tracciarti%22,%22informationalModalMessageBody%22:%22Dopo%20aver%20effettuato%20l'accesso,%20DuckDuckGo%20non%20pu%C3%B2%20bloccare%20il%20tracciamento%20dei%20contenuti%20di%20Facebook%20su%20questo%20sito.%22,%22informationalModalConfirmButtonText%22:%22Accedi%22,%22informationalModalRejectButtonText%22:%22Torna%20indietro%22,%22loginButtonText%22:%22Accedi%20con%20Facebook%22,%22loginBodyText%22:%22Facebook%20tiene%20traccia%20della%20tua%20attivit%C3%A0%20su%20un%20sito%20quando%20lo%20usi%20per%20accedere.%22,%22buttonTextUnblockContent%22:%22Sblocca%20contenuti%22,%22buttonTextUnblockComment%22:%22Sblocca%20commento%22,%22buttonTextUnblockComments%22:%22Sblocca%20commenti%22,%22buttonTextUnblockPost%22:%22Sblocca%20post%22,%22buttonTextUnblockVideo%22:%22Sblocca%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20ha%20bloccato%20questo%20contenuto%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20ha%20bloccato%20questo%20commento%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20ha%20bloccato%20questi%20commenti%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20ha%20bloccato%20questo%20post%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloccato%20questo%20video%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTextUnblockContent%22:%22Abbiamo%20impedito%20a%20Facebook%20di%20tracciarti%20al%20caricamento%20della%20pagina.%20Se%20sblocchi%20questo%20contenuto,%20Facebook%20conoscer%C3%A0%20la%20tua%20attivit%C3%A0.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Ulteriori%20informazioni%22,%22readAbout%22:%22Leggi%20di%20pi%C3%B9%20su%20questa%20protezione%20della%20privacy%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Abilitare%20tutte%20le%20anteprime%20di%20YouTube?%22,%22informationalModalMessageBody%22:%22La%20visualizzazione%20delle%20anteprime%20consentir%C3%A0%20a%20Google%20(che%20possiede%20YouTube)%20di%20vedere%20alcune%20delle%20informazioni%20del%20tuo%20dispositivo,%20ma%20%C3%A8%20comunque%20pi%C3%B9%20privato%20rispetto%20alla%20riproduzione%20del%20video.%22,%22informationalModalConfirmButtonText%22:%22Abilita%20tutte%20le%20anteprime%22,%22informationalModalRejectButtonText%22:%22No,%20grazie%22,%22buttonTextUnblockVideo%22:%22Sblocca%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloccato%20questo%20video%20di%20YouTube%20per%20impedire%20a%20Google%20di%20tracciarti%22,%22infoTextUnblockVideo%22:%22Abbiamo%20impedito%20a%20Google%20(che%20possiede%20YouTube)%20di%20tracciarti%20quando%20la%20pagina%20%C3%A8%20stata%20caricata.%20Se%20sblocchi%20questo%20video,%20Google%20conoscer%C3%A0%20la%20tua%20attivit%C3%A0.%22,%22infoPreviewToggleText%22:%22Anteprime%20disabilitate%20per%20una%20maggiore%20privacy%22,%22infoPreviewToggleEnabledText%22:%22Anteprime%20abilitate%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EScopri%20di%20pi%C3%B9%3C/a%3E%20sulla%20protezione%20dai%20social%20media%20integrata%20di%20DuckDuckGo%22%7D%7D,%22lt%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Prisijung%C4%99%20prie%20%E2%80%9EFacebook%E2%80%9C%20galite%20b%C5%ABti%20sekami%22,%22informationalModalMessageBody%22:%22Kai%20esate%20prisijung%C4%99,%20%E2%80%9EDuckDuckGo%E2%80%9C%20negali%20u%C5%BEblokuoti%20%E2%80%9EFacebook%E2%80%9C%20turinio,%20tod%C4%97l%20esate%20sekami%20%C5%A1ioje%20svetain%C4%97je.%22,%22informationalModalConfirmButtonText%22:%22Prisijungti%22,%22informationalModalRejectButtonText%22:%22Gr%C4%AF%C5%BEti%20atgal%22,%22loginButtonText%22:%22Prisijunkite%20su%20%E2%80%9EFacebook%E2%80%9C%22,%22loginBodyText%22:%22%E2%80%9EFacebook%E2%80%9C%20seka%20j%C5%ABs%C5%B3%20veikl%C4%85%20svetain%C4%97je,%20kai%20prisijungiate%20su%20%C5%A1ia%20svetaine.%22,%22buttonTextUnblockContent%22:%22Atblokuoti%20turin%C4%AF%22,%22buttonTextUnblockComment%22:%22Atblokuoti%20komentar%C4%85%22,%22buttonTextUnblockComments%22:%22Atblokuoti%20komentarus%22,%22buttonTextUnblockPost%22:%22Atblokuoti%20%C4%AFra%C5%A1%C4%85%22,%22buttonTextUnblockVideo%22:%22Atblokuoti%20vaizdo%20%C4%AFra%C5%A1%C4%85%22,%22infoTitleUnblockContent%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20turin%C4%AF,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockComment%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20komentar%C4%85,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockComments%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1iuos%20komentarus,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockPost%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20%C4%AFra%C5%A1%C4%85,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockVideo%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20vaizdo%20%C4%AFra%C5%A1%C4%85,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTextUnblockContent%22:%22U%C5%BEblokavome%20%E2%80%9EFacebook%E2%80%9C,%20kad%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti,%20kai%20puslapis%20buvo%20%C4%AFkeltas.%20Jei%20atblokuosite%20%C5%A1%C4%AF%20turin%C4%AF,%20%E2%80%9EFacebook%E2%80%9C%20%C5%BEinos%20apie%20j%C5%ABs%C5%B3%20veikl%C4%85.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Su%C5%BEinoti%20daugiau%22,%22readAbout%22:%22Skaitykite%20apie%20%C5%A1i%C4%85%20privatumo%20apsaug%C4%85%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%C4%AEjungti%20visas%20%E2%80%9EYouTube%E2%80%9C%20per%C5%BEi%C5%ABras?%22,%22informationalModalMessageBody%22:%22Per%C5%BEi%C5%ABr%C5%B3%20rodymas%20leis%20%E2%80%9EGoogle%E2%80%9C%20(kuriai%20priklauso%20%E2%80%9EYouTube%E2%80%9C)%20matyti%20tam%20tikr%C4%85%20j%C5%ABs%C5%B3%20%C4%AFrenginio%20informacij%C4%85,%20ta%C4%8Diau%20ji%20vis%20tiek%20bus%20privatesn%C4%97%20nei%20leid%C5%BEiant%20vaizdo%20%C4%AFra%C5%A1%C4%85.%22,%22informationalModalConfirmButtonText%22:%22%C4%AEjungti%20visas%20per%C5%BEi%C5%ABras%22,%22informationalModalRejectButtonText%22:%22Ne,%20d%C4%97koju%22,%22buttonTextUnblockVideo%22:%22Atblokuoti%20vaizdo%20%C4%AFra%C5%A1%C4%85%22,%22infoTitleUnblockVideo%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20%E2%80%9EYouTube%E2%80%9C%20vaizdo%20%C4%AFra%C5%A1%C4%85,%20kad%20%E2%80%9EGoogle%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTextUnblockVideo%22:%22U%C5%BEblokavome%20%E2%80%9EGoogle%E2%80%9C%20(kuriai%20priklauso%20%E2%80%9EYouTube%E2%80%9C)%20galimyb%C4%99%20sekti%20jus,%20kai%20puslapis%20buvo%20%C4%AFkeltas.%20Jei%20atblokuosite%20%C5%A1%C4%AF%20vaizdo%20%C4%AFra%C5%A1%C4%85,%20%E2%80%9EGoogle%E2%80%9C%20su%C5%BEinos%20apie%20j%C5%ABs%C5%B3%20veikl%C4%85.%22,%22infoPreviewToggleText%22:%22Per%C5%BEi%C5%ABros%20i%C5%A1jungtos%20d%C4%97l%20papildomo%20privatumo%22,%22infoPreviewToggleEnabledText%22:%22Per%C5%BEi%C5%ABros%20%C4%AFjungtos%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ESu%C5%BEinokite%20daugiau%3C/a%3E%20apie%20%E2%80%9EDuckDuckGo%E2%80%9C%20%C4%AFd%C4%97t%C4%85j%C4%85%20socialin%C4%97s%20%C5%BEiniasklaidos%20apsaug%C4%85%22%7D%7D,%22lv%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Ja%20pieteiksies%20ar%20Facebook,%20vi%C5%86i%20var%C4%93s%20tevi%20izsekot%22,%22informationalModalMessageBody%22:%22Kad%20tu%20piesakies,%20DuckDuckGo%20nevar%20nov%C4%93rst,%20ka%20Facebook%20saturs%20tevi%20izseko%20%C5%A1aj%C4%81%20vietn%C4%93.%22,%22informationalModalConfirmButtonText%22:%22Pieteikties%22,%22informationalModalRejectButtonText%22:%22Atgriezties%22,%22loginButtonText%22:%22Pieteikties%20ar%20Facebook%22,%22loginBodyText%22:%22Facebook%20izseko%20tavas%20aktivit%C4%81tes%20vietn%C4%93,%20kad%20esi%20pieteicies%20ar%20Facebook.%22,%22buttonTextUnblockContent%22:%22Atblo%C4%B7%C4%93t%20saturu%22,%22buttonTextUnblockComment%22:%22Atblo%C4%B7%C4%93t%20koment%C4%81ru%22,%22buttonTextUnblockComments%22:%22Atblo%C4%B7%C4%93t%20koment%C4%81rus%22,%22buttonTextUnblockPost%22:%22Atblo%C4%B7%C4%93t%20zi%C5%86u%22,%22buttonTextUnblockVideo%22:%22Atblo%C4%B7%C4%93t%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20saturu,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20koment%C4%81ru,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1os%20koment%C4%81rus,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20zi%C5%86u,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20videoklipu,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTextUnblockContent%22:%22M%C4%93s%20blo%C4%B7%C4%93j%C4%81m%20Facebook%20iesp%C4%93ju%20tevi%20izsekot,%20iel%C4%81d%C4%93jot%20lapu.%20Ja%20atblo%C4%B7%C4%93si%20%C5%A1o%20saturu,%20Facebook%20redz%C4%93s,%20ko%20tu%20dari.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Uzzin%C4%81t%20vair%C4%81k%22,%22readAbout%22:%22Lasi%20par%20%C5%A1o%20priv%C4%81tuma%20aizsardz%C4%ABbu%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Vai%20iesp%C4%93jot%20visus%20YouTube%20priek%C5%A1skat%C4%ABjumus?%22,%22informationalModalMessageBody%22:%22Priek%C5%A1skat%C4%ABjumu%20r%C4%81d%C4%AB%C5%A1ana%20%C4%BCaus%20Google%20(kam%20pieder%20YouTube)%20redz%C4%93t%20da%C4%BCu%20tavas%20ier%C4%ABces%20inform%C4%81cijas,%20ta%C4%8Du%20tas%20t%C4%81pat%20ir%20priv%C4%81t%C4%81k%20par%20videoklipa%20atska%C5%86o%C5%A1anu.%22,%22informationalModalConfirmButtonText%22:%22Iesp%C4%93jot%20visus%20priek%C5%A1skat%C4%ABjumus%22,%22informationalModalRejectButtonText%22:%22N%C4%93,%20paldies%22,%22buttonTextUnblockVideo%22:%22Atblo%C4%B7%C4%93t%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20YouTube%20videoklipu,%20lai%20ne%C4%BCautu%20Google%20tevi%20izsekot%22,%22infoTextUnblockVideo%22:%22M%C4%93s%20ne%C4%BC%C4%81v%C4%81m%20Google%20(kam%20pieder%20YouTube)%20tevi%20izsekot,%20kad%20lapa%20tika%20iel%C4%81d%C4%93ta.%20Ja%20atblo%C4%B7%C4%93si%20%C5%A1o%20videoklipu,%20Google%20zin%C4%81s,%20ko%20tu%20dari.%22,%22infoPreviewToggleText%22:%22Priek%C5%A1skat%C4%ABjumi%20ir%20atsp%C4%93joti,%20lai%20nodro%C5%A1in%C4%81tu%20papildu%20konfidencialit%C4%81ti%22,%22infoPreviewToggleEnabledText%22:%22Priek%C5%A1skat%C4%ABjumi%20ir%20iesp%C4%93joti%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EUzzini%20vair%C4%81k%3C/a%3E%20par%20DuckDuckGo%20iegulto%20soci%C4%81lo%20mediju%20aizsardz%C4%ABbu%22%7D%7D,%22nb%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22N%C3%A5r%20du%20logger%20p%C3%A5%20med%20Facebook,%20kan%20de%20spore%20deg%22,%22informationalModalMessageBody%22:%22N%C3%A5r%20du%20er%20logget%20p%C3%A5,%20kan%20ikke%20DuckDuckGo%20hindre%20Facebook-innhold%20i%20%C3%A5%20spore%20deg%20p%C3%A5%20dette%20nettstedet.%22,%22informationalModalConfirmButtonText%22:%22Logg%20inn%22,%22informationalModalRejectButtonText%22:%22G%C3%A5%20tilbake%22,%22loginButtonText%22:%22Logg%20p%C3%A5%20med%20Facebook%22,%22loginBodyText%22:%22N%C3%A5r%20du%20logger%20p%C3%A5%20med%20Facebook,%20sporer%20de%20aktiviteten%20din%20p%C3%A5%20nettstedet.%22,%22buttonTextUnblockContent%22:%22Opphev%20blokkering%20av%20innhold%22,%22buttonTextUnblockComment%22:%22Opphev%20blokkering%20av%20kommentar%22,%22buttonTextUnblockComments%22:%22Opphev%20blokkering%20av%20kommentarer%22,%22buttonTextUnblockPost%22:%22Opphev%20blokkering%20av%20innlegg%22,%22buttonTextUnblockVideo%22:%22Opphev%20blokkering%20av%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blokkerte%20dette%20innholdet%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blokkerte%20denne%20kommentaren%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blokkerte%20disse%20kommentarene%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blokkerte%20dette%20innlegget%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokkerte%20denne%20videoen%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTextUnblockContent%22:%22Vi%20hindret%20Facebook%20i%20%C3%A5%20spore%20deg%20da%20siden%20ble%20lastet.%20Hvis%20du%20opphever%20blokkeringen%20av%20dette%20innholdet,%20f%C3%A5r%20Facebook%20vite%20om%20aktiviteten%20din.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Finn%20ut%20mer%22,%22readAbout%22:%22Les%20om%20denne%20personvernfunksjonen%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Vil%20du%20aktivere%20alle%20YouTube-forh%C3%A5ndsvisninger?%22,%22informationalModalMessageBody%22:%22Forh%C3%A5ndsvisninger%20gj%C3%B8r%20det%20mulig%20for%20Google%20(som%20eier%20YouTube)%20%C3%A5%20se%20enkelte%20opplysninger%20om%20enheten%20din,%20men%20det%20er%20likevel%20mer%20privat%20enn%20%C3%A5%20spille%20av%20videoen.%22,%22informationalModalConfirmButtonText%22:%22Aktiver%20alle%20forh%C3%A5ndsvisninger%22,%22informationalModalRejectButtonText%22:%22Nei%20takk%22,%22buttonTextUnblockVideo%22:%22Opphev%20blokkering%20av%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokkerte%20denne%20YouTube-videoen%20for%20%C3%A5%20hindre%20Google%20i%20%C3%A5%20spore%20deg%22,%22infoTextUnblockVideo%22:%22Vi%20blokkerte%20Google%20(som%20eier%20YouTube)%20mot%20%C3%A5%20spore%20deg%20da%20siden%20ble%20lastet.%20Hvis%20du%20opphever%20blokkeringen%20av%20denne%20videoen,%20f%C3%A5r%20Google%20vite%20om%20aktiviteten%20din.%22,%22infoPreviewToggleText%22:%22Forh%C3%A5ndsvisninger%20er%20deaktivert%20for%20%C3%A5%20gi%20deg%20ekstra%20personvern%22,%22infoPreviewToggleEnabledText%22:%22Forh%C3%A5ndsvisninger%20er%20aktivert%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EFinn%20ut%20mer%3C/a%3E%20om%20DuckDuckGos%20innebygde%20beskyttelse%20for%20sosiale%20medier%22%7D%7D,%22nl%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Als%20je%20inlogt%20met%20Facebook,%20kunnen%20zij%20je%20volgen%22,%22informationalModalMessageBody%22:%22Als%20je%20eenmaal%20bent%20ingelogd,%20kan%20DuckDuckGo%20niet%20voorkomen%20dat%20Facebook%20je%20op%20deze%20site%20volgt.%22,%22informationalModalConfirmButtonText%22:%22Inloggen%22,%22informationalModalRejectButtonText%22:%22Terug%22,%22loginButtonText%22:%22Inloggen%20met%20Facebook%22,%22loginBodyText%22:%22Facebook%20volgt%20je%20activiteit%20op%20een%20site%20als%20je%20Facebook%20gebruikt%20om%20in%20te%20loggen.%22,%22buttonTextUnblockContent%22:%22Inhoud%20deblokkeren%22,%22buttonTextUnblockComment%22:%22Opmerking%20deblokkeren%22,%22buttonTextUnblockComments%22:%22Opmerkingen%20deblokkeren%22,%22buttonTextUnblockPost%22:%22Bericht%20deblokkeren%22,%22buttonTextUnblockVideo%22:%22Video%20deblokkeren%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20heeft%20deze%20inhoud%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20heeft%20deze%20opmerking%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20heeft%20deze%20opmerkingen%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20heeft%20dit%20bericht%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20heeft%20deze%20video%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTextUnblockContent%22:%22We%20hebben%20voorkomen%20dat%20Facebook%20je%20volgde%20toen%20de%20pagina%20werd%20geladen.%20Als%20je%20deze%20inhoud%20deblokkeert,%20kan%20Facebook%20je%20activiteit%20zien.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Meer%20informatie%22,%22readAbout%22:%22Lees%20meer%20over%20deze%20privacybescherming%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Alle%20YouTube-voorbeelden%20inschakelen?%22,%22informationalModalMessageBody%22:%22Bij%20het%20tonen%20van%20voorbeelden%20kan%20Google%20(eigenaar%20van%20YouTube)%20een%20deel%20van%20de%20informatie%20over%20je%20apparaat%20zien,%20maar%20blijft%20je%20privacy%20beter%20beschermd%20dan%20als%20je%20de%20video%20zou%20afspelen.%22,%22informationalModalConfirmButtonText%22:%22Alle%20voorbeelden%20inschakelen%22,%22informationalModalRejectButtonText%22:%22Nee,%20bedankt%22,%22buttonTextUnblockVideo%22:%22Video%20deblokkeren%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20heeft%20deze%20YouTube-video%20geblokkeerd%20om%20te%20voorkomen%20dat%20Google%20je%20kan%20volgen%22,%22infoTextUnblockVideo%22:%22We%20hebben%20voorkomen%20dat%20Google%20(eigenaar%20van%20YouTube)%20je%20volgde%20toen%20de%20pagina%20werd%20geladen.%20Als%20je%20deze%20video%20deblokkeert,%20kan%20Google%20je%20activiteit%20zien.%22,%22infoPreviewToggleText%22:%22Voorbeelden%20uitgeschakeld%20voor%20extra%20privacy%22,%22infoPreviewToggleEnabledText%22:%22Voorbeelden%20ingeschakeld%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EMeer%20informatie%3C/a%3E%20over%20DuckDuckGo's%20bescherming%20tegen%20ingesloten%20social%20media%22%7D%7D,%22pl%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Je%C5%9Bli%20zalogujesz%20si%C4%99%20za%20po%C5%9Brednictwem%20Facebooka,%20b%C4%99dzie%20on%20m%C3%B3g%C5%82%20%C5%9Bledzi%C4%87%20Twoj%C4%85%20aktywno%C5%9B%C4%87%22,%22informationalModalMessageBody%22:%22Po%20zalogowaniu%20si%C4%99%20DuckDuckGo%20nie%20mo%C5%BCe%20zablokowa%C4%87%20mo%C5%BCliwo%C5%9Bci%20%C5%9Bledzenia%20Ci%C4%99%20przez%20Facebooka%20na%20tej%20stronie.%22,%22informationalModalConfirmButtonText%22:%22Zaloguj%20si%C4%99%22,%22informationalModalRejectButtonText%22:%22Wr%C3%B3%C4%87%22,%22loginButtonText%22:%22Zaloguj%20si%C4%99%20za%20po%C5%9Brednictwem%20Facebooka%22,%22loginBodyText%22:%22Facebook%20%C5%9Bledzi%20Twoj%C4%85%20aktywno%C5%9B%C4%87%20na%20stronie,%20gdy%20logujesz%20si%C4%99%20za%20jego%20po%C5%9Brednictwem.%22,%22buttonTextUnblockContent%22:%22Odblokuj%20tre%C5%9B%C4%87%22,%22buttonTextUnblockComment%22:%22Odblokuj%20komentarz%22,%22buttonTextUnblockComments%22:%22Odblokuj%20komentarze%22,%22buttonTextUnblockPost%22:%22Odblokuj%20post%22,%22buttonTextUnblockVideo%22:%22Odblokuj%20wideo%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20zablokowa%C5%82%20t%C4%99%20tre%C5%9B%C4%87,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20zablokowa%C5%82%20ten%20komentarz,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20zablokowa%C5%82%20te%20komentarze,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20zablokowa%C5%82%20ten%20post,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokowa%C5%82%20t%C4%99%20tre%C5%9B%C4%87%20wideo,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87.%22,%22infoTextUnblockContent%22:%22Zablokowali%C5%9Bmy%20Facebookowi%20mo%C5%BCliwo%C5%9B%C4%87%20%C5%9Bledzenia%20Ci%C4%99%20podczas%20%C5%82adowania%20strony.%20Je%C5%9Bli%20odblokujesz%20t%C4%99%20tre%C5%9B%C4%87,%20Facebook%20uzyska%20informacje%20o%20Twojej%20aktywno%C5%9Bci.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Dowiedz%20si%C4%99%20wi%C4%99cej%22,%22readAbout%22:%22Dowiedz%20si%C4%99%20wi%C4%99cej%20o%20tej%20ochronie%20prywatno%C5%9Bci%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22W%C5%82%C4%85czy%C4%87%20wszystkie%20podgl%C4%85dy%20w%20YouTube?%22,%22informationalModalMessageBody%22:%22Wy%C5%9Bwietlanie%20podgl%C4%85du%20pozwala%20Google%20(kt%C3%B3ry%20jest%20w%C5%82a%C5%9Bcicielem%20YouTube)%20zobaczy%C4%87%20niekt%C3%B3re%20informacje%20o%20Twoim%20urz%C4%85dzeniu,%20ale%20nadal%20jest%20to%20bardziej%20prywatne%20ni%C5%BC%20odtwarzanie%20filmu.%22,%22informationalModalConfirmButtonText%22:%22W%C5%82%C4%85cz%20wszystkie%20podgl%C4%85dy%22,%22informationalModalRejectButtonText%22:%22Nie,%20dzi%C4%99kuj%C4%99%22,%22buttonTextUnblockVideo%22:%22Odblokuj%20wideo%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokowa%C5%82%20ten%20film%20w%20YouTube,%20aby%20uniemo%C5%BCliwi%C4%87%20Google%20%C5%9Bledzenie%20Twojej%20aktywno%C5%9Bci%22,%22infoTextUnblockVideo%22:%22Zablokowali%C5%9Bmy%20mo%C5%BCliwo%C5%9B%C4%87%20%C5%9Bledzenia%20Ci%C4%99%20przez%20Google%20(w%C5%82a%C5%9Bciciela%20YouTube)%20podczas%20%C5%82adowania%20strony.%20Je%C5%9Bli%20odblokujesz%20ten%20film,%20Google%20zobaczy%20Twoj%C4%85%20aktywno%C5%9B%C4%87.%22,%22infoPreviewToggleText%22:%22Podgl%C4%85dy%20zosta%C5%82y%20wy%C5%82%C4%85czone,%20aby%20zapewni%C4%87%20wi%C4%99ksz%C4%85%20ptywatno%C5%9B%C4%87%22,%22infoPreviewToggleEnabledText%22:%22Podgl%C4%85dy%20w%C5%82%C4%85czone%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EDowiedz%20si%C4%99%20wi%C4%99cej%3C/a%3E%20o%20zabezpieczeniu%20osadzonych%20tre%C5%9Bci%20spo%C5%82eczno%C5%9Bciowych%20DuckDuckGo%22%7D%7D,%22pt%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Iniciar%20sess%C3%A3o%20no%20Facebook%20permite%20que%20este%20te%20rastreie%22,%22informationalModalMessageBody%22:%22Depois%20de%20iniciares%20sess%C3%A3o,%20o%20DuckDuckGo%20n%C3%A3o%20poder%C3%A1%20bloquear%20o%20rastreio%20por%20parte%20do%20conte%C3%BAdo%20do%20Facebook%20neste%20site.%22,%22informationalModalConfirmButtonText%22:%22Iniciar%20sess%C3%A3o%22,%22informationalModalRejectButtonText%22:%22Retroceder%22,%22loginButtonText%22:%22Iniciar%20sess%C3%A3o%20com%20o%20Facebook%22,%22loginBodyText%22:%22O%20Facebook%20rastreia%20a%20tua%20atividade%20num%20site%20quando%20o%20usas%20para%20iniciares%20sess%C3%A3o.%22,%22buttonTextUnblockContent%22:%22Desbloquear%20Conte%C3%BAdo%22,%22buttonTextUnblockComment%22:%22Desbloquear%20Coment%C3%A1rio%22,%22buttonTextUnblockComments%22:%22Desbloquear%20Coment%C3%A1rios%22,%22buttonTextUnblockPost%22:%22Desbloquear%20Publica%C3%A7%C3%A3o%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20V%C3%ADdeo%22,%22infoTitleUnblockContent%22:%22O%20DuckDuckGo%20bloqueou%20este%20conte%C3%BAdo%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockComment%22:%22O%20DuckDuckGo%20bloqueou%20este%20coment%C3%A1rio%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockComments%22:%22O%20DuckDuckGo%20bloqueou%20estes%20coment%C3%A1rios%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockPost%22:%22O%20DuckDuckGo%20bloqueou%20esta%20publica%C3%A7%C3%A3o%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockVideo%22:%22O%20DuckDuckGo%20bloqueou%20este%20v%C3%ADdeo%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTextUnblockContent%22:%22Bloque%C3%A1mos%20o%20rastreio%20por%20parte%20do%20Facebook%20quando%20a%20p%C3%A1gina%20foi%20carregada.%20Se%20desbloqueares%20este%20conte%C3%BAdo,%20o%20Facebook%20fica%20a%20saber%20a%20tua%20atividade.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Saiba%20mais%22,%22readAbout%22:%22Ler%20mais%20sobre%20esta%20prote%C3%A7%C3%A3o%20de%20privacidade%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Ativar%20todas%20as%20pr%C3%A9-visualiza%C3%A7%C3%B5es%20do%20YouTube?%22,%22informationalModalMessageBody%22:%22Mostrar%20visualiza%C3%A7%C3%B5es%20permite%20%C3%A0%20Google%20(que%20det%C3%A9m%20o%20YouTube)%20ver%20algumas%20das%20informa%C3%A7%C3%B5es%20do%20teu%20dispositivo,%20mas%20ainda%20%C3%A9%20mais%20privado%20do%20que%20reproduzir%20o%20v%C3%ADdeo.%22,%22informationalModalConfirmButtonText%22:%22Ativar%20todas%20as%20pr%C3%A9-visualiza%C3%A7%C3%B5es%22,%22informationalModalRejectButtonText%22:%22N%C3%A3o,%20obrigado%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20V%C3%ADdeo%22,%22infoTitleUnblockVideo%22:%22O%20DuckDuckGo%20bloqueou%20este%20v%C3%ADdeo%20do%20YouTube%20para%20impedir%20que%20a%20Google%20te%20rastreie%22,%22infoTextUnblockVideo%22:%22Bloque%C3%A1mos%20o%20rastreio%20por%20parte%20da%20Google%20(que%20det%C3%A9m%20o%20YouTube)%20quando%20a%20p%C3%A1gina%20foi%20carregada.%20Se%20desbloqueares%20este%20v%C3%ADdeo,%20a%20Google%20fica%20a%20saber%20a%20tua%20atividade.%22,%22infoPreviewToggleText%22:%22Pr%C3%A9-visualiza%C3%A7%C3%B5es%20desativadas%20para%20privacidade%20adicional%22,%22infoPreviewToggleEnabledText%22:%22Pr%C3%A9-visualiza%C3%A7%C3%B5es%20ativadas%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ESaiba%20mais%3C/a%3E%20sobre%20a%20Prote%C3%A7%C3%A3o%20contra%20conte%C3%BAdos%20de%20redes%20sociais%20incorporados%20do%20DuckDuckGo%22%7D%7D,%22ro%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Conectarea%20cu%20Facebook%20%C3%AEi%20permite%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22informationalModalMessageBody%22:%22Odat%C4%83%20ce%20te-ai%20conectat,%20DuckDuckGo%20nu%20poate%20%C3%AEmpiedica%20con%C8%9Binutul%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%20pe%20acest%20site.%22,%22informationalModalConfirmButtonText%22:%22Autentificare%22,%22informationalModalRejectButtonText%22:%22%C3%8Enapoi%22,%22loginButtonText%22:%22Conecteaz%C4%83-te%20cu%20Facebook%22,%22loginBodyText%22:%22Facebook%20urm%C4%83re%C8%99te%20activitatea%20ta%20pe%20un%20site%20atunci%20c%C3%A2nd%20%C3%AEl%20utilizezi%20pentru%20a%20te%20conecta.%22,%22buttonTextUnblockContent%22:%22Deblocheaz%C4%83%20con%C8%9Binutul%22,%22buttonTextUnblockComment%22:%22Deblocheaz%C4%83%20comentariul%22,%22buttonTextUnblockComments%22:%22Deblocheaz%C4%83%20comentariile%22,%22buttonTextUnblockPost%22:%22Deblocheaz%C4%83%20postarea%22,%22buttonTextUnblockVideo%22:%22Deblocheaz%C4%83%20videoclipul%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20a%20blocat%20acest%20con%C8%9Binut%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20a%20blocat%20acest%20comentariu%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20a%20blocat%20aceste%20comentarii%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20a%20blocat%20aceast%C4%83%20postare%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20blocat%20acest%20videoclip%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTextUnblockContent%22:%22Am%20%C3%AEmpiedicat%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%20atunci%20c%C3%A2nd%20pagina%20a%20fost%20%C3%AEnc%C4%83rcat%C4%83.%20Dac%C4%83%20deblochezi%20acest%20con%C8%9Binut,%20Facebook%20%C3%AE%C8%9Bi%20va%20cunoa%C8%99te%20activitatea.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Afl%C4%83%20mai%20multe%22,%22readAbout%22:%22Cite%C8%99te%20despre%20aceast%C4%83%20protec%C8%9Bie%20a%20confiden%C8%9Bialit%C4%83%C8%9Bii%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Activezi%20toate%20previzualiz%C4%83rile%20YouTube?%22,%22informationalModalMessageBody%22:%22Afi%C8%99area%20previzualiz%C4%83rilor%20va%20permite%20ca%20Google%20(care%20de%C8%9Bine%20YouTube)%20s%C4%83%20vad%C4%83%20unele%20dintre%20informa%C8%9Biile%20despre%20dispozitivul%20t%C4%83u,%20dar%20este%20totu%C8%99i%20mai%20privat%C4%83%20dec%C3%A2t%20redarea%20videoclipului.%22,%22informationalModalConfirmButtonText%22:%22Activeaz%C4%83%20toate%20previzualiz%C4%83rile%22,%22informationalModalRejectButtonText%22:%22Nu,%20mul%C8%9Bumesc%22,%22buttonTextUnblockVideo%22:%22Deblocheaz%C4%83%20videoclipul%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20blocat%20acest%20videoclip%20de%20pe%20YouTube%20pentru%20a%20%C3%AEmpiedica%20Google%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTextUnblockVideo%22:%22Am%20%C3%AEmpiedicat%20Google%20(care%20de%C8%9Bine%20YouTube)%20s%C4%83%20te%20urm%C4%83reasc%C4%83%20atunci%20c%C3%A2nd%20s-a%20%C3%AEnc%C4%83rcat%20pagina.%20Dac%C4%83%20deblochezi%20acest%20videoclip,%20Google%20va%20cunoa%C8%99te%20activitatea%20ta.%22,%22infoPreviewToggleText%22:%22Previzualiz%C4%83rile%20au%20fost%20dezactivate%20pentru%20o%20confiden%C8%9Bialitate%20suplimentar%C4%83%22,%22infoPreviewToggleEnabledText%22:%22Previzualiz%C4%83ri%20activate%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EAfl%C4%83%20mai%20multe%3C/a%3E%20despre%20Protec%C8%9Bia%20integrat%C4%83%20DuckDuckGo%20pentru%20re%C8%9Belele%20sociale%22%7D%7D,%22ru%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%92%D1%85%D0%BE%D0%B4%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20Facebook%20%D0%BF%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D0%B5%D1%82%20%D1%8D%D1%82%D0%BE%D0%B9%20%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9%20%D1%81%D0%B5%D1%82%D0%B8%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B0%D1%81%22,%22informationalModalMessageBody%22:%22%D0%9F%D0%BE%D1%81%D0%BB%D0%B5%20%D0%B2%D1%85%D0%BE%D0%B4%D0%B0%20DuckDuckGo%20%D0%BD%D0%B5%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D1%88%D0%B8%D1%85%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D0%B9%20%D1%81%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82%D0%BE%D0%BC%20%D0%BD%D0%B0%20Facebook.%22,%22informationalModalConfirmButtonText%22:%22%D0%92%D0%BE%D0%B9%D1%82%D0%B8%22,%22informationalModalRejectButtonText%22:%22%D0%92%D0%B5%D1%80%D0%BD%D1%83%D1%82%D1%8C%D1%81%D1%8F%22,%22loginButtonText%22:%22%D0%92%D0%BE%D0%B9%D1%82%D0%B8%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20Facebook%22,%22loginBodyText%22:%22%D0%9F%D1%80%D0%B8%20%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B8%20%D1%83%D1%87%D0%B5%D1%82%D0%BD%D0%BE%D0%B9%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8%20Facebook%20%D0%B4%D0%BB%D1%8F%20%D0%B2%D1%85%D0%BE%D0%B4%D0%B0%20%D0%BD%D0%B0%20%D1%81%D0%B0%D0%B9%D1%82%D1%8B%20%D1%8D%D1%82%D0%B0%20%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F%20%D1%81%D0%B5%D1%82%D1%8C%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D1%82%D1%8C%20%D0%BD%D0%B0%20%D0%BD%D0%B8%D1%85%20%D0%B2%D0%B0%D1%88%D0%B8%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F.%22,%22buttonTextUnblockContent%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockComment%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockComments%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockPost%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%D1%82%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%D1%82%20%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D0%B9,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%B8%20%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D0%B8,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D1%83%20%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8E,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTextUnblockContent%22:%22%D0%92%D0%BE%20%D0%B2%D1%80%D0%B5%D0%BC%D1%8F%20%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B%20%D0%BC%D1%8B%20%D0%BF%D0%BE%D0%BC%D0%B5%D1%88%D0%B0%D0%BB%D0%B8%20Facebook%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D0%B8%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F.%20%D0%95%D1%81%D0%BB%D0%B8%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%8D%D1%82%D0%BE%D1%82%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82,%20Facebook%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D1%84%D0%B8%D0%BA%D1%81%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D1%83%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82%D1%8C.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22%D0%A3%D0%B7%D0%BD%D0%B0%D1%82%D1%8C%20%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5%22,%22readAbout%22:%22%D0%9F%D0%BE%D0%B4%D1%80%D0%BE%D0%B1%D0%BD%D0%B5%D0%B5%20%D0%BE%D0%B1%20%D1%8D%D1%82%D0%BE%D0%BC%20%D0%B2%D0%B8%D0%B4%D0%B5%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D1%8B%20%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B4%D0%B5%D0%BD%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%92%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D0%B8%D0%B7%20YouTube?%22,%22informationalModalMessageBody%22:%22%D0%90%D0%BA%D1%82%D0%B8%D0%B2%D0%B0%D1%86%D0%B8%D1%8F%20%D0%BF%D1%80%D0%B5%D0%B4%D0%B2%D0%B0%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B0%20%D0%BF%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D0%B8%D1%82%20Google%20(%D0%B2%D0%BB%D0%B0%D0%B4%D0%B5%D0%BB%D1%8C%D1%86%D1%83%20YouTube)%20%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C%20%D0%BD%D0%B5%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B5%20%D1%81%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BE%20%D0%B2%D0%B0%D1%88%D0%B5%D0%BC%20%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5,%20%D0%BE%D0%B4%D0%BD%D0%B0%D0%BA%D0%BE%20%D1%8D%D1%82%D0%BE%20%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5%20%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D1%8B%D0%B9%20%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82,%20%D1%87%D0%B5%D0%BC%20%D0%B2%D0%BE%D1%81%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D1%86%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%BC.%22,%22informationalModalConfirmButtonText%22:%22%D0%92%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%22,%22informationalModalRejectButtonText%22:%22%D0%9D%D0%B5%D1%82,%20%D1%81%D0%BF%D0%B0%D1%81%D0%B8%D0%B1%D0%BE%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D0%B8%D0%B7%20YouTube,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Google%22,%22infoTextUnblockVideo%22:%22%D0%92%D0%BE%20%D0%B2%D1%80%D0%B5%D0%BC%D1%8F%20%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B%20%D0%BC%D1%8B%20%D0%BF%D0%BE%D0%BC%D0%B5%D1%88%D0%B0%D0%BB%D0%B8%20Google%20(%D0%B2%D0%BB%D0%B0%D0%B4%D0%B5%D0%BB%D1%8C%D1%86%D1%83%20YouTube)%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D0%B8%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F.%20%D0%95%D1%81%D0%BB%D0%B8%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE,%20Google%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D1%84%D0%B8%D0%BA%D1%81%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D1%83%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82%D1%8C.%22,%22infoPreviewToggleText%22:%22%D0%9F%D1%80%D0%B5%D0%B4%D0%B2%D0%B0%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%20%D0%BE%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%20%D0%B4%D0%BB%D1%8F%20%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D1%8B%20%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B4%D0%B5%D0%BD%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8%22,%22infoPreviewToggleEnabledText%22:%22%D0%9F%D1%80%D0%B5%D0%B4%D0%B2%D0%B0%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%20%D0%B2%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3E%D0%9F%D0%BE%D0%B4%D1%80%D0%BE%D0%B1%D0%BD%D0%B5%D0%B5%3C/a%3E%20%D0%BE%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B5%20DuckDuckGo%20%D0%BE%D1%82%20%D0%B2%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82%D0%B0%20%D1%81%D0%BE%D1%86%D1%81%D0%B5%D1%82%D0%B5%D0%B9%22%7D%7D,%22sk%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Prihl%C3%A1senie%20cez%20Facebook%20mu%20umo%C5%BEn%C3%AD%20sledova%C5%A5%20v%C3%A1s%22,%22informationalModalMessageBody%22:%22DuckDuckGo%20po%20prihl%C3%A1sen%C3%AD%20nem%C3%B4%C5%BEe%20na%20tejto%20lokalite%20zablokova%C5%A5%20sledovanie%20va%C5%A1ej%20osoby%20obsahom%20Facebooku.%22,%22informationalModalConfirmButtonText%22:%22Prihl%C3%A1si%C5%A5%20sa%22,%22informationalModalRejectButtonText%22:%22Prejs%C5%A5%20sp%C3%A4%C5%A5%22,%22loginButtonText%22:%22Prihl%C3%A1ste%20sa%20pomocou%20slu%C5%BEby%20Facebook%22,%22loginBodyText%22:%22Ke%C4%8F%20pou%C5%BEijete%20prihlasovanie%20cez%20Facebook,%20Facebook%20bude%20na%20lokalite%20sledova%C5%A5%20va%C5%A1u%20aktivitu.%22,%22buttonTextUnblockContent%22:%22Odblokova%C5%A5%20obsah%22,%22buttonTextUnblockComment%22:%22Odblokova%C5%A5%20koment%C3%A1r%22,%22buttonTextUnblockComments%22:%22Odblokova%C5%A5%20koment%C3%A1re%22,%22buttonTextUnblockPost%22:%22Odblokova%C5%A5%20pr%C3%ADspevok%22,%22buttonTextUnblockVideo%22:%22Odblokova%C5%A5%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20zablokoval%20tento%20obsah,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20zablokoval%20tento%20koment%C3%A1r,%20aby%20zabr%C3%A1nil%20sledovaniu%20zo%20strany%20Facebooku%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20zablokoval%20tieto%20koment%C3%A1re,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20zablokoval%20tento%20pr%C3%ADspevok,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokoval%20toto%20video,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTextUnblockContent%22:%22Pri%20na%C4%8D%C3%ADtan%C3%AD%20str%C3%A1nky%20sme%20zablokovali%20Facebook,%20aby%20v%C3%A1s%20nesledoval.%20Ak%20tento%20obsah%20odblokujete,%20Facebook%20bude%20vedie%C5%A5%20o%20va%C5%A1ej%20aktivite.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Zistite%20viac%22,%22readAbout%22:%22Pre%C4%8D%C3%ADtajte%20si%20o%20tejto%20ochrane%20s%C3%BAkromia%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Chcete%20povoli%C5%A5%20v%C5%A1etky%20uk%C3%A1%C5%BEky%20zo%20slu%C5%BEby%20YouTube?%22,%22informationalModalMessageBody%22:%22Zobrazenie%20uk%C3%A1%C5%BEok%20umo%C5%BEn%C3%AD%20spolo%C4%8Dnosti%20Google%20(ktor%C3%A1%20vlastn%C3%AD%20YouTube)%20vidie%C5%A5%20niektor%C3%A9%20inform%C3%A1cie%20o%20va%C5%A1om%20zariaden%C3%AD,%20ale%20st%C3%A1le%20je%20to%20s%C3%BAkromnej%C5%A1ie%20ako%20prehr%C3%A1vanie%20videa.%22,%22informationalModalConfirmButtonText%22:%22Povoli%C5%A5%20v%C5%A1etky%20uk%C3%A1%C5%BEky%22,%22informationalModalRejectButtonText%22:%22Nie,%20%C4%8Fakujem%22,%22buttonTextUnblockVideo%22:%22Odblokova%C5%A5%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20toto%20video%20v%20slu%C5%BEbe%20YouTube%20zablokoval%20s%20cie%C4%BEom%20pred%C3%ADs%C5%A5%20tomu,%20aby%20v%C3%A1s%20spolo%C4%8Dnos%C5%A5%20Google%20mohla%20sledova%C5%A5%22,%22infoTextUnblockVideo%22:%22Zablokovali%20sme%20pre%20spolo%C4%8Dnos%C5%A5%20Google%20(ktor%C3%A1%20vlastn%C3%AD%20YouTube),%20aby%20v%C3%A1s%20nemohla%20sledova%C5%A5,%20ke%C4%8F%20sa%20str%C3%A1nka%20na%C4%8D%C3%ADta.%20Ak%20toto%20video%20odblokujete,%20Google%20bude%20pozna%C5%A5%20va%C5%A1u%20aktivitu.%22,%22infoPreviewToggleText%22:%22Uk%C3%A1%C5%BEky%20s%C3%BA%20zak%C3%A1zan%C3%A9%20s%20cie%C4%BEom%20zv%C3%BD%C5%A1i%C5%A5%20ochranu%20s%C3%BAkromia%22,%22infoPreviewToggleEnabledText%22:%22Uk%C3%A1%C5%BEky%20s%C3%BA%20povolen%C3%A9%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EZ%C3%ADskajte%20viac%20inform%C3%A1ci%C3%AD%3C/a%3E%20o%20DuckDuckGo,%20vlo%C5%BEenej%20ochrane%20soci%C3%A1lnych%20m%C3%A9di%C3%AD%22%7D%7D,%22sl%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%C4%8Ce%20se%20prijavite%20s%20Facebookom,%20vam%20Facebook%20lahko%20sledi%22,%22informationalModalMessageBody%22:%22Ko%20ste%20enkrat%20prijavljeni,%20DuckDuckGo%20ne%20more%20blokirati%20Facebookove%20vsebine,%20da%20bi%20vam%20sledila%20na%20tem%20spletnem%20mestu.%22,%22informationalModalConfirmButtonText%22:%22Prijava%22,%22informationalModalRejectButtonText%22:%22Pojdi%20nazaj%22,%22loginButtonText%22:%22Prijavite%20se%20s%20Facebookom%22,%22loginBodyText%22:%22%C4%8Ce%20se%20prijavite%20s%20Facebookom,%20bo%20nato%20spremljal%20va%C5%A1a%20dejanja%20na%20spletnem%20mestu.%22,%22buttonTextUnblockContent%22:%22Odblokiraj%20vsebino%22,%22buttonTextUnblockComment%22:%22Odblokiraj%20komentar%22,%22buttonTextUnblockComments%22:%22Odblokiraj%20komentarje%22,%22buttonTextUnblockPost%22:%22Odblokiraj%20objavo%22,%22buttonTextUnblockVideo%22:%22Odblokiraj%20videoposnetek%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20je%20blokiral%20to%20vsebino,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20je%20blokiral%20ta%20komentar,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20je%20blokiral%20te%20komentarje,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20je%20blokiral%20to%20objavo,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokiral%20ta%20videoposnetek,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTextUnblockContent%22:%22Ko%20se%20je%20stran%20nalo%C5%BEila,%20smo%20Facebooku%20prepre%C4%8Dili,%20da%20bi%20vam%20sledil.%20%C4%8Ce%20to%20vsebino%20odblokirate,%20bo%20Facebook%20izvedel%20za%20va%C5%A1a%20dejanja.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Ve%C4%8D%22,%22readAbout%22:%22Preberite%20ve%C4%8D%20o%20tej%20za%C5%A1%C4%8Diti%20zasebnosti%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%C5%BDelite%20omogo%C4%8Diti%20vse%20YouTubove%20predoglede?%22,%22informationalModalMessageBody%22:%22Prikaz%20predogledov%20omogo%C4%8Da%20Googlu%20(ki%20je%20lastnik%20YouTuba)%20vpogled%20v%20nekatere%20podatke%20o%20napravi,%20vendar%20je%20%C5%A1e%20vedno%20bolj%20zasebno%20kot%20predvajanje%20videoposnetka.%22,%22informationalModalConfirmButtonText%22:%22Omogo%C4%8Di%20vse%20predoglede%22,%22informationalModalRejectButtonText%22:%22Ne,%20hvala%22,%22buttonTextUnblockVideo%22:%22Odblokiraj%20videoposnetek%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokiral%20ta%20videoposnetek%20v%20YouTubu,%20da%20bi%20Googlu%20prepre%C4%8Dil%20sledenje%22,%22infoTextUnblockVideo%22:%22Googlu%20(ki%20je%20lastnik%20YouTuba)%20smo%20prepre%C4%8Dili,%20da%20bi%20vam%20sledil,%20ko%20se%20je%20stran%20nalo%C5%BEila.%20%C4%8Ce%20odblokirate%20ta%20videoposnetek,%20bo%20Google%20izvedel%20za%20va%C5%A1o%20dejavnost.%22,%22infoPreviewToggleText%22:%22Predogledi%20so%20zaradi%20dodatne%20zasebnosti%20onemogo%C4%8Deni%22,%22infoPreviewToggleEnabledText%22:%22Predogledi%20so%20omogo%C4%8Deni%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EVe%C4%8D%3C/a%3E%20o%20vgrajeni%20za%C5%A1%C4%8Diti%20dru%C5%BEbenih%20medijev%20DuckDuckGo%22%7D%7D,%22sv%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Om%20du%20loggar%20in%20med%20Facebook%20kan%20de%20sp%C3%A5ra%20dig%22,%22informationalModalMessageBody%22:%22N%C3%A4r%20du%20v%C3%A4l%20%C3%A4r%20inloggad%20kan%20DuckDuckGo%20inte%20hindra%20Facebooks%20inneh%C3%A5ll%20fr%C3%A5n%20att%20sp%C3%A5ra%20dig%20p%C3%A5%20den%20h%C3%A4r%20webbplatsen.%22,%22informationalModalConfirmButtonText%22:%22Logga%20in%22,%22informationalModalRejectButtonText%22:%22G%C3%A5%20tillbaka%22,%22loginButtonText%22:%22Logga%20in%20med%20Facebook%22,%22loginBodyText%22:%22Facebook%20sp%C3%A5rar%20din%20aktivitet%20p%C3%A5%20en%20webbplats%20om%20du%20anv%C3%A4nder%20det%20f%C3%B6r%20att%20logga%20in.%22,%22buttonTextUnblockContent%22:%22Avblockera%20inneh%C3%A5ll%22,%22buttonTextUnblockComment%22:%22Avblockera%20kommentar%22,%22buttonTextUnblockComments%22:%22Avblockera%20kommentarer%22,%22buttonTextUnblockPost%22:%22Avblockera%20inl%C3%A4gg%22,%22buttonTextUnblockVideo%22:%22Avblockera%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blockerade%20det%20h%C3%A4r%20inneh%C3%A5llet%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blockerade%20den%20h%C3%A4r%20kommentaren%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blockerade%20de%20h%C3%A4r%20kommentarerna%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blockerade%20det%20h%C3%A4r%20inl%C3%A4gget%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blockerade%20den%20h%C3%A4r%20videon%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTextUnblockContent%22:%22Vi%20hindrade%20Facebook%20fr%C3%A5n%20att%20sp%C3%A5ra%20dig%20n%C3%A4r%20sidan%20l%C3%A4stes%20in.%20Om%20du%20avblockerar%20det%20h%C3%A4r%20inneh%C3%A5llet%20kommer%20Facebook%20att%20k%C3%A4nna%20till%20din%20aktivitet.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22L%C3%A4s%20mer%22,%22readAbout%22:%22L%C3%A4s%20mer%20om%20detta%20integritetsskydd%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Aktivera%20alla%20f%C3%B6rhandsvisningar%20f%C3%B6r%20YouTube?%22,%22informationalModalMessageBody%22:%22Genom%20att%20visa%20f%C3%B6rhandsvisningar%20kan%20Google%20(som%20%C3%A4ger%20YouTube)%20se%20en%20del%20av%20enhetens%20information,%20men%20det%20%C3%A4r%20%C3%A4nd%C3%A5%20mer%20privat%20%C3%A4n%20att%20spela%20upp%20videon.%22,%22informationalModalConfirmButtonText%22:%22Aktivera%20alla%20f%C3%B6rhandsvisningar%22,%22informationalModalRejectButtonText%22:%22Nej%20tack%22,%22buttonTextUnblockVideo%22:%22Avblockera%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blockerade%20den%20h%C3%A4r%20YouTube-videon%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Google%20sp%C3%A5rar%20dig%22,%22infoTextUnblockVideo%22:%22Vi%20hindrade%20Google%20(som%20%C3%A4ger%20YouTube)%20fr%C3%A5n%20att%20sp%C3%A5ra%20dig%20n%C3%A4r%20sidan%20laddades.%20Om%20du%20tar%20bort%20blockeringen%20av%20videon%20kommer%20Google%20att%20k%C3%A4nna%20till%20din%20aktivitet.%22,%22infoPreviewToggleText%22:%22F%C3%B6rhandsvisningar%20har%20inaktiverats%20f%C3%B6r%20ytterligare%20integritet%22,%22infoPreviewToggleEnabledText%22:%22F%C3%B6rhandsvisningar%20aktiverade%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EL%C3%A4s%20mer%3C/a%3E%20om%20DuckDuckGos%20skydd%20mot%20inb%C3%A4ddade%20sociala%20medier%22%7D%7D,%22tr%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Facebook%20ile%20giri%C5%9F%20yapmak,%20sizi%20takip%20etmelerini%20sa%C4%9Flar%22,%22informationalModalMessageBody%22:%22Giri%C5%9F%20yapt%C4%B1ktan%20sonra,%20DuckDuckGo%20Facebook%20i%C3%A7eri%C4%9Finin%20sizi%20bu%20sitede%20izlemesini%20engelleyemez.%22,%22informationalModalConfirmButtonText%22:%22Oturum%20A%C3%A7%22,%22informationalModalRejectButtonText%22:%22Geri%20d%C3%B6n%22,%22loginButtonText%22:%22Facebook%20ile%20giri%C5%9F%20yap%C4%B1n%22,%22loginBodyText%22:%22Facebook,%20giri%C5%9F%20yapmak%20i%C3%A7in%20kulland%C4%B1%C4%9F%C4%B1n%C4%B1zda%20bir%20sitedeki%20etkinli%C4%9Finizi%20izler.%22,%22buttonTextUnblockContent%22:%22%C4%B0%C3%A7eri%C4%9Fin%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockComment%22:%22Yorumun%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockComments%22:%22Yorumlar%C4%B1n%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockPost%22:%22G%C3%B6nderinin%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockVideo%22:%22Videonun%20Engelini%20Kald%C4%B1r%22,%22infoTitleUnblockContent%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20i%C3%A7eri%C4%9Fi%20engelledi%22,%22infoTitleUnblockComment%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20yorumu%20engelledi%22,%22infoTitleUnblockComments%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20yorumlar%C4%B1%20engelledi%22,%22infoTitleUnblockPost%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20g%C3%B6nderiyi%20engelledi%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20videoyu%20engelledi%22,%22infoTextUnblockContent%22:%22Sayfa%20y%C3%BCklendi%C4%9Finde%20Facebook'un%20sizi%20izlemesini%20engelledik.%20Bu%20i%C3%A7eri%C4%9Fin%20engelini%20kald%C4%B1r%C4%B1rsan%C4%B1z%20Facebook%20etkinli%C4%9Finizi%20%C3%B6%C4%9Frenecektir.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Daha%20Fazla%20Bilgi%22,%22readAbout%22:%22Bu%20gizlilik%20korumas%C4%B1%20hakk%C4%B1nda%20bilgi%20edinin%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22T%C3%BCm%20YouTube%20%C3%B6nizlemeleri%20etkinle%C5%9Ftirilsin%20mi?%22,%22informationalModalMessageBody%22:%22%C3%96nizlemelerin%20g%C3%B6sterilmesi%20Google'%C4%B1n%20(YouTube'un%20sahibi)%20cihaz%C4%B1n%C4%B1z%C4%B1n%20baz%C4%B1%20bilgilerini%20g%C3%B6rmesine%20izin%20verir,%20ancak%20yine%20de%20videoyu%20oynatmaktan%20daha%20%C3%B6zeldir.%22,%22informationalModalConfirmButtonText%22:%22T%C3%BCm%20%C3%96nizlemeleri%20Etkinle%C5%9Ftir%22,%22informationalModalRejectButtonText%22:%22Hay%C4%B1r%20Te%C5%9Fekk%C3%BCrler%22,%22buttonTextUnblockVideo%22:%22Videonun%20Engelini%20Kald%C4%B1r%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo,%20Google'%C4%B1n%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20YouTube%20videosunu%20engelledi%22,%22infoTextUnblockVideo%22:%22Sayfa%20y%C3%BCklendi%C4%9Finde%20Google'%C4%B1n%20(YouTube'un%20sahibi)%20sizi%20izlemesini%20engelledik.%20Bu%20videonun%20engelini%20kald%C4%B1r%C4%B1rsan%C4%B1z,%20Google%20etkinli%C4%9Finizi%20%C3%B6%C4%9Frenecektir.%22,%22infoPreviewToggleText%22:%22Ek%20gizlilik%20i%C3%A7in%20%C3%B6nizlemeler%20devre%20d%C4%B1%C5%9F%C4%B1%20b%C4%B1rak%C4%B1ld%C4%B1%22,%22infoPreviewToggleEnabledText%22:%22%C3%96nizlemeler%20etkinle%C5%9Ftirildi%22,%22infoPreviewInfoText%22:%22DuckDuckGo%20Yerle%C5%9Fik%20Sosyal%20Medya%20Korumas%C4%B1%20hakk%C4%B1nda%20%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3Edaha%20fazla%20bilgi%20edinin%3C/a%3E%22%7D%7D%7D%60;%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Style%20Definitions%0A%20%20%20%20%20*********************************************************/%0A%20%20%20%20const%20styles%20=%20%7B%0A%20%20%20%20%20%20%20%20fontStyle:%20%60%0A%20%20%20%20%20%20%20%20@font-face%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20%20%20%20%20src:%20url($%7BddgFont%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20@font-face%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20%20%20%20%20src:%20url($%7BddgFontBold%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20darkMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#111111;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20textFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20rgba(255,%20255,%20255,%200.9);%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#111111;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20linkFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#7295F6;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#5784FF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundHover:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#557FF3;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundPress:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#3969EF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonText:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#EEEEEE;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonBgState:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20active:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background:%20#5784FF;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20inactive:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background-color:%20#666666;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20lightMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20textFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#222222;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20linkFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#3969EF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#3969EF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundHover:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#2B55CA;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundPress:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#1E42A4;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonText:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#666666;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonBgState:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20active:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background:%20#3969EF;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20inactive:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background-color:%20#666666;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20loginMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#666666;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20cancelMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20rgba(34,%2034,%2034,%200.1);%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#222222;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundHover:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20rgba(0,%200,%200,%200.12);%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundPress:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20rgba(0,%200,%200,%200.18);%0A%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20button:%20%60%0A%20%20%20%20%20%20%20%20border-radius:%208px;%0A%0A%20%20%20%20%20%20%20%20padding:%2011px%2022px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20margin:%200px%20auto;%0A%20%20%20%20%20%20%20%20border-color:%20#3969EF;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20box-shadow:%20none;%0A%20%20%20%20%20%20%20%20z-index:%202147483646;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20circle:%20%60%0A%20%20%20%20%20%20%20%20border-radius:%2050%25;%0A%20%20%20%20%20%20%20%20width:%2018px;%0A%20%20%20%20%20%20%20%20height:%2018px;%0A%20%20%20%20%20%20%20%20background:%20#E0E0E0;%0A%20%20%20%20%20%20%20%20border:%201px%20solid%20#E0E0E0;%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20top:%20-8px;%0A%20%20%20%20%20%20%20%20right:%20-8px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20loginIcon:%20%60%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20top:%20-13px;%0A%20%20%20%20%20%20%20%20right:%20-10px;%0A%20%20%20%20%20%20%20%20height:%2028px;%0A%20%20%20%20%20%20%20%20width:%2028px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20rectangle:%20%60%0A%20%20%20%20%20%20%20%20width:%2012px;%0A%20%20%20%20%20%20%20%20height:%203px;%0A%20%20%20%20%20%20%20%20background:%20#666666;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20top:%2042.5%25;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20textBubble:%20%60%0A%20%20%20%20%20%20%20%20background:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20border:%201px%20solid%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%20%20%20%20border-radius:%2016px;%0A%20%20%20%20%20%20%20%20box-shadow:%200px%202px%206px%20rgba(0,%200,%200,%200.12),%200px%208px%2016px%20rgba(0,%200,%200,%200.08);%0A%20%20%20%20%20%20%20%20width:%20360px;%0A%20%20%20%20%20%20%20%20margin-top:%2010px;%0A%20%20%20%20%20%20%20%20z-index:%202147483647;%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20line-height:%20normal;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20textBubbleWidth:%20360,%20//%20Should%20match%20the%20width%20rule%20in%20textBubble%0A%20%20%20%20%20%20%20%20textBubbleLeftShift:%20100,%20//%20Should%20match%20the%20CSS%20left:%20rule%20in%20textBubble%0A%20%20%20%20%20%20%20%20textArrow:%20%60%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20background:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20border:%20solid%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%20%20%20%20border-width:%200%201px%201px%200;%0A%20%20%20%20%20%20%20%20padding:%205px;%0A%20%20%20%20%20%20%20%20transform:%20rotate(-135deg);%0A%20%20%20%20%20%20%20%20-webkit-transform:%20rotate(-135deg);%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20top:%20-9px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20arrowDefaultLocationPercent:%2050,%0A%20%20%20%20%20%20%20%20hoverTextTitle:%20%60%0A%20%20%20%20%20%20%20%20padding:%200px%2012px%2012px;%0A%20%20%20%20%20%20%20%20margin-top:%20-5px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20hoverTextBody:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20padding:%2017px;%0A%20%20%20%20%20%20%20%20text-align:%20left;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20hoverContainer:%20%60%0A%20%20%20%20%20%20%20%20padding-bottom:%2010px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20buttonTextContainer:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20row;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20headerRow:%20%60%0A%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20block:%20%60%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%20%20%20%20border:%201px%20solid%20rgba(0,0,0,0.1);%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20max-width:%20600px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20line-height:%201;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubeDialogBlock:%20%60%0A%20%20%20%20%20%20%20%20height:%20calc(100%25%20-%2030px);%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-height:%20initial;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20imgRow:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20margin:%2020px%200px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20content:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20padding:%2016px%200;%0A%20%20%20%20%20%20%20%20flex:%201%201%201px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20feedbackLink:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20font-style:%20normal;%0A%20%20%20%20%20%20%20%20font-weight:%20400;%0A%20%20%20%20%20%20%20%20font-size:%2012px;%0A%20%20%20%20%20%20%20%20line-height:%2012px;%0A%20%20%20%20%20%20%20%20color:%20#ABABAB;%0A%20%20%20%20%20%20%20%20text-decoration:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20feedbackRow:%20%60%0A%20%20%20%20%20%20%20%20height:%2030px;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20titleBox:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20padding:%2012px;%0A%20%20%20%20%20%20%20%20max-height:%2044px;%0A%20%20%20%20%20%20%20%20border-bottom:%201px%20solid;%0A%20%20%20%20%20%20%20%20border-color:%20rgba(196,%20196,%20196,%200.3);%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20margin-bottom:%204px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20title:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20line-height:%201.4;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20margin:%20auto%2010px;%0A%20%20%20%20%20%20%20%20flex-basis:%20100%25;%0A%20%20%20%20%20%20%20%20height:%201.4em;%0A%20%20%20%20%20%20%20%20flex-wrap:%20wrap;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20text-align:%20left;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20buttonRow:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20height:%20100%25%0A%20%20%20%20%20%20%20%20flex-direction:%20row;%0A%20%20%20%20%20%20%20%20margin:%2020px%20auto%200px;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%20%20%20%20align-items:%20flex-start;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modalContentTitle:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20font-size:%2017px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20margin:%2010px%20auto;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200px%2032px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modalContentText:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20margin:%200px%20auto%2014px;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modalButtonRow:%20%60%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modalButton:%20%60%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modalIcon:%20%60%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20contentTitle:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20font-size:%2017px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20margin:%2020px%20auto%2010px;%0A%20%20%20%20%20%20%20%20padding:%200px%2030px;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20margin-top:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20contentText:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20padding:%200px%2040px;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20margin:%200%20auto%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20icon:%20%60%0A%20%20%20%20%20%20%20%20height:%2080px;%0A%20%20%20%20%20%20%20%20width:%2080px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20closeIcon:%20%60%0A%20%20%20%20%20%20%20%20height:%2012px;%0A%20%20%20%20%20%20%20%20width:%2012px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20closeButton:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20min-width:%2020px;%0A%20%20%20%20%20%20%20%20height:%2021px;%0A%20%20%20%20%20%20%20%20border:%200;%0A%20%20%20%20%20%20%20%20background:%20transparent;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20logo:%20%60%0A%20%20%20%20%20%20%20%20flex-basis:%200%25;%0A%20%20%20%20%20%20%20%20min-width:%2020px;%0A%20%20%20%20%20%20%20%20height:%2021px;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20logoImg:%20%60%0A%20%20%20%20%20%20%20%20height:%2021px;%0A%20%20%20%20%20%20%20%20width:%2021px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20loadingImg:%20%60%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20margin:%200px%208px%200px%200px;%0A%20%20%20%20%20%20%20%20height:%2014px;%0A%20%20%20%20%20%20%20%20width:%2014px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modal:%20%60%0A%20%20%20%20%20%20%20%20width:%20340px;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20background-color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20top:%2050%25;%0A%20%20%20%20%20%20%20%20left:%2050%25;%0A%20%20%20%20%20%20%20%20transform:%20translate(-50%25,%20-50%25);%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20box-shadow:%200px%201px%203px%20rgba(0,%200,%200,%200.08),%200px%202px%204px%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modalContent:%20%60%0A%20%20%20%20%20%20%20%20padding:%2024px;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20overlay:%20%60%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20background-color:%20#666666;%0A%20%20%20%20%20%20%20%20opacity:%20.5;%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20position:%20fixed;%0A%20%20%20%20%20%20%20%20top:%200;%0A%20%20%20%20%20%20%20%20right:%200;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20modalContainer:%20%60%0A%20%20%20%20%20%20%20%20height:%20100vh;%0A%20%20%20%20%20%20%20%20width:%20100vw;%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%20%20%20%20z-index:%202147483647;%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20position:%20fixed;%0A%20%20%20%20%20%20%20%20border:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20headerLinkContainer:%20%60%0A%20%20%20%20%20%20%20%20flex-basis:%20100%25;%0A%20%20%20%20%20%20%20%20display:%20grid;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20headerLink:%20%60%0A%20%20%20%20%20%20%20%20line-height:%201.4;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20text-decoration:%20none;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20min-width:%20100px;%0A%20%20%20%20%20%20%20%20text-align:%20end;%0A%20%20%20%20%20%20%20%20float:%20right;%0A%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20generalLink:%20%60%0A%20%20%20%20%20%20%20%20line-height:%201.4;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20text-decoration:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20wrapperDiv:%20%60%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20border:%200;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20max-width:%20600px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20toggleButtonWrapper:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20toggleButton:%20%60%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20width:%2030px;%0A%20%20%20%20%20%20%20%20height:%2016px;%0A%20%20%20%20%20%20%20%20margin-top:%20-3px;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20background-color:%20transparent;%0A%20%20%20%20%20%20%20%20text-align:%20left;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20toggleButtonBg:%20%60%0A%20%20%20%20%20%20%20%20right:%200;%0A%20%20%20%20%20%20%20%20width:%2030px;%0A%20%20%20%20%20%20%20%20height:%2016px;%0A%20%20%20%20%20%20%20%20overflow:%20visible;%0A%20%20%20%20%20%20%20%20border-radius:%2010px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20toggleButtonText:%20%60%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20margin:%200%200%200%207px;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20toggleButtonKnob:%20%60%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20width:%2014px;%0A%20%20%20%20%20%20%20%20height:%2014px;%0A%20%20%20%20%20%20%20%20border-radius:%2010px;%0A%20%20%20%20%20%20%20%20background-color:%20#ffffff;%0A%20%20%20%20%20%20%20%20margin-top:%201px;%0A%20%20%20%20%20%20%20%20top:%20calc(50%25%20-%2014px/2%20-%201px);%0A%20%20%20%20%20%20%20%20box-shadow:%200px%200px%201px%20rgba(0,%200,%200,%200.05),%200px%201px%201px%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20toggleButtonKnobState:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20active:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20right:%201px;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20inactive:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20left:%201px;%0A%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20placeholderWrapperDiv:%20%60%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-width:%20380px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubeWrapperDiv:%20%60%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-width:%20380px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubeDialogDiv:%20%60%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-height:%20initial;%0A%20%20%20%20%20%20%20%20height:%20calc(100%25%20-%2030px);%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubeDialogBottomRow:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%20%20%20%20margin-top:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePlaceholder:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-start;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%20%20%20%20background:%20rgba(45,%2045,%2045,%200.8);%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePreviewWrapperImg:%20%60%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePreviewImg:%20%60%0A%20%20%20%20%20%20%20%20min-width:%20100%25;%0A%20%20%20%20%20%20%20%20min-height:%20100%25;%0A%20%20%20%20%20%20%20%20height:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubeTopSection:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20flex:%201;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20space-between;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20padding:%2018px%2012px%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubeTitle:%20%60%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20line-height:%2014px;%0A%20%20%20%20%20%20%20%20color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20white-space:%20nowrap;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20text-overflow:%20ellipsis;%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePlayButtonRow:%20%60%0A%20%20%20%20%20%20%20%20flex:%202;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePlayButton:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20height:%2048px;%0A%20%20%20%20%20%20%20%20width:%2080px;%0A%20%20%20%20%20%20%20%20padding:%200px%2024px;%0A%20%20%20%20%20%20%20%20border-radius:%208px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePreviewToggleRow:%20%60%0A%20%20%20%20%20%20%20%20flex:%201;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20padding:%200%2012px%2018px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePreviewToggleText:%20%60%0A%20%20%20%20%20%20%20%20color:%20#EEEEEE;%0A%20%20%20%20%20%20%20%20font-weight:%20400;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20youTubePreviewInfoText:%20%60%0A%20%20%20%20%20%20%20%20color:%20#ABABAB;%0A%20%20%20%20%60%0A%20%20%20%20%7D;%0A%0A%20%20%20%20function%20getConfig%20(locale)%20%7B%0A%20%20%20%20%20%20%20%20const%20locales%20=%20JSON.parse(localesJSON);%0A%20%20%20%20%20%20%20%20const%20fbStrings%20=%20locales%5Blocale%5D%5B'facebook.json'%5D;%0A%20%20%20%20%20%20%20%20const%20ytStrings%20=%20locales%5Blocale%5D%5B'youtube.json'%5D;%0A%0A%20%20%20%20%20%20%20%20const%20sharedStrings%20=%20locales%5Blocale%5D%5B'shared.json'%5D;%0A%20%20%20%20%20%20%20%20const%20config%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20'Facebook,%20Inc.':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20informationalModal:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20icon:%20blockedFBLogo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageTitle:%20fbStrings.informationalModalMessageTitle,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageBody:%20fbStrings.informationalModalMessageBody,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20confirmButtonText:%20fbStrings.informationalModalConfirmButtonText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rejectButtonText:%20fbStrings.informationalModalRejectButtonText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elementData:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Like%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-like'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Button%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/like.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/like.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/share_button.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/share_button.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Save%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-save'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Share%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-share-button'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Page%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/page.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/page.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Page%20Div':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-page'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/plugins/page.php?href=data-href&tabs=data-tabs&width=data-width&height=data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-tabs':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'timeline'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-height':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Comment%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/comment_embed.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/comment_embed.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Comments':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-comments',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fb%5C%5C:comments'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockComments,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockComments,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'allowFull',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/comments.php?href=data-href&numposts=data-numposts&sdk=joey&version=v9.0&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-numposts':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%2010%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Embedded%20Comment%20Div':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-comment-embed'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/comment_embed.php?href=data-href&sdk=joey&width=data-width&include_parent=data-include-parent',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-include-parent':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'false'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Post%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/post.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/post.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Posts%20Div':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-post'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'allowFull',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/post.php?href=data-href&sdk=joey&show_text=true&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fallbackAttribute:%20'data-width'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Video%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/video.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/video.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Video':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-video'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/plugins/video.php?href=data-href&show_text=true&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fallbackAttribute:%20'data-width'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Group%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/group.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/group.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Group':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-group'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/plugins/group.php?href=data-href&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Login%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-login-button'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'loginButton',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20icon:%20blockedFBLogo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.loginButtonText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20popupBodyText:%20fbStrings.loginBodyText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'allowFull',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/login_button.php?app_id=app_id_replace&auto_logout_link=false&button_type=continue_with&sdk=joey&size=large&use_continue_as=false&width=',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20app_id_replace:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'null'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20Youtube:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20informationalModal:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20icon:%20blockedYTVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageTitle:%20ytStrings.informationalModalMessageTitle,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageBody:%20ytStrings.informationalModalMessageBody,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20confirmButtonText:%20ytStrings.informationalModalConfirmButtonText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rejectButtonText:%20ytStrings.informationalModalRejectButtonText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elementData:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'YouTube%20embedded%20video':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube-nocookie.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube-nocookie.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube-nocookie.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube-nocookie.com/embed'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'youtube-video',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20ytStrings.buttonTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20ytStrings.infoTitleUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20ytStrings.infoTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewToggleText:%20ytStrings.infoPreviewToggleText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20placeholder:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewToggleEnabledText:%20ytStrings.infoPreviewToggleEnabledText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewInfoText:%20ytStrings.infoPreviewInfoText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20videoPlayIcon:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lightMode:%20videoPlayLight,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20darkMode:%20videoPlayDark%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'youtube-video'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'YouTube%20embedded%20subscription%20button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube-nocookie.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube-nocookie.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube-nocookie.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube-nocookie.com/subscribe_embed'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20config,%20sharedStrings%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20%7B'darkMode'%20%7C%20'lightMode'%20%7C%20'loginMode'%20%7C%20'cancelMode'%7D%20displayMode%0A%20%20%20%20%20*%20%20%20Key%20for%20theme%20value%20to%20determine%20the%20styling%20of%20buttons/placeholders.%0A%20%20%20%20%20*%20%20%20Matches%20%60styles%5Bmode%5D%60%20keys:%0A%20%20%20%20%20*%20%20%20%20%20-%20%60'lightMode'%60:%20Primary%20colors%20styling%20for%20light%20theme%0A%20%20%20%20%20*%20%20%20%20%20-%20%60'darkMode'%60:%20Primary%20colors%20styling%20for%20dark%20theme%0A%20%20%20%20%20*%20%20%20%20%20-%20%60'cancelMode'%60:%20Secondary%20colors%20styling%20for%20all%20themes%0A%20%20%20%20%20*/%0A%0A%20%20%20%20let%20devMode%20=%20false;%0A%20%20%20%20let%20isYoutubePreviewsEnabled%20=%20false;%0A%20%20%20%20let%20appID;%0A%0A%20%20%20%20const%20titleID%20=%20'DuckDuckGoPrivacyEssentialsCTLElementTitle';%0A%0A%20%20%20%20//%20Configuration%20for%20how%20the%20placeholder%20elements%20should%20look%20and%20behave.%0A%20%20%20%20//%20@see%20%7BgetConfig%7D%0A%20%20%20%20let%20config%20=%20null;%0A%20%20%20%20let%20sharedStrings%20=%20null;%0A%0A%20%20%20%20//%20TODO:%20Remove%20these%20redundant%20data%20structures%20and%20refactor%20the%20related%20code.%0A%20%20%20%20//%20%20%20%20%20%20%20There%20should%20be%20no%20need%20to%20have%20the%20entity%20configuration%20stored%20in%20two%0A%20%20%20%20//%20%20%20%20%20%20%20places.%0A%20%20%20%20const%20entities%20=%20%5B%5D;%0A%20%20%20%20const%20entityData%20=%20%7B%7D;%0A%0A%20%20%20%20//%20Used%20to%20avoid%20displaying%20placeholders%20for%20the%20same%20tracking%20element%20twice.%0A%20%20%20%20const%20knownTrackingElements%20=%20new%20WeakSet();%0A%0A%20%20%20%20//%20Promise%20that%20is%20resolved%20when%20the%20Click%20to%20Load%20feature%20init()%20function%20has%0A%20%20%20%20//%20finished%20its%20work,%20enough%20that%20it's%20now%20safe%20to%20replace%20elements%20with%0A%20%20%20%20//%20placeholders.%0A%20%20%20%20let%20readyToDisplayPlaceholdersResolver;%0A%20%20%20%20const%20readyToDisplayPlaceholders%20=%20new%20Promise(resolve%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20readyToDisplayPlaceholdersResolver%20=%20resolve;%0A%20%20%20%20%7D);%0A%0A%20%20%20%20//%20Promise%20that%20is%20resolved%20when%20the%20page%20has%20finished%20loading%20(and%0A%20%20%20%20//%20readyToDisplayPlaceholders%20has%20resolved).%20Wait%20for%20this%20before%20sending%0A%20%20%20%20//%20essential%20messages%20to%20surrogate%20scripts.%0A%20%20%20%20let%20afterPageLoadResolver;%0A%20%20%20%20const%20afterPageLoad%20=%20new%20Promise(resolve%20=%3E%20%7B%20afterPageLoadResolver%20=%20resolve;%20%7D);%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Widget%20Replacement%20logic%0A%20%20%20%20%20*********************************************************/%0A%20%20%20%20class%20DuckWidget%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BObject%7D%20widgetData%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20configuration%20for%20this%20%22widget%22%20as%20determined%20in%20ctl-config.js.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20originalElement%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20original%20tracking%20element%20to%20replace%20with%20a%20placeholder.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20entity%20behind%20the%20tracking%20element%20(e.g.%20%22Facebook,%20Inc.%22).%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20constructor%20(widgetData,%20originalElement,%20entity)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction%20=%20%7B%20...widgetData.clickAction%20%7D;%20//%20shallow%20copy%0A%20%20%20%20%20%20%20%20%20%20%20%20this.replaceSettings%20=%20widgetData.replaceSettings;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.originalElement%20=%20originalElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.placeholderElement%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.dataElements%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.gatherDataElements();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.entity%20=%20entity;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.widgetID%20=%20Math.random();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.autoplay%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Boolean%20if%20widget%20is%20unblocked%20and%20content%20should%20not%20be%20blocked%0A%20%20%20%20%20%20%20%20%20%20%20%20this.isUnblocked%20=%20false;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Dispatch%20an%20event%20on%20the%20target%20element,%20including%20the%20widget's%20ID%20and%0A%20%20%20%20%20%20%20%20%20*%20other%20details.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BEventTarget%7D%20eventTarget%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20eventName%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20dispatchEvent%20(eventTarget,%20eventName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20eventTarget.dispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20eventName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entity:%20this.entity,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20this.replaceSettings,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widgetID:%20this.widgetID%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Take%20note%20of%20some%20of%20the%20tracking%20element's%20attributes%20(as%20determined%20by%0A%20%20%20%20%20%20%20%20%20*%20clickAction.urlDataAttributesToPreserve)%20and%20store%20those%20in%0A%20%20%20%20%20%20%20%20%20*%20this.dataElement.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20gatherDataElements%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this.clickAction.urlDataAttributesToPreserve)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5BattrName,%20attrSettings%5D%20of%20Object.entries(this.clickAction.urlDataAttributesToPreserve))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20value%20=%20this.originalElement.getAttribute(attrName);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(attrSettings.required)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Missing%20a%20required%20attribute%20means%20we%20won't%20be%20able%20to%20replace%20it%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20with%20a%20light%20version,%20replace%20with%20full%20version.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.type%20=%20'allowFull';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%20=%20attrSettings.default;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.dataElements%5BattrName%5D%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Return%20the%20URL%20of%20the%20Facebook%20content,%20for%20use%20when%20a%20Facebook%20Click%20to%0A%20%20%20%20%20%20%20%20%20*%20Load%20placeholder%20has%20been%20clicked%20by%20the%20user.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getTargetURL%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Copying%20over%20data%20fields%20should%20be%20done%20lazily,%20since%20some%20required%20data%20may%20not%20be%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20captured%20until%20after%20page%20scripts%20run.%0A%20%20%20%20%20%20%20%20%20%20%20%20this.copySocialDataFields();%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.clickAction.targetURL%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Determines%20which%20display%20mode%20the%20placeholder%20element%20should%20render%20in.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BdisplayMode%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getMode%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Login%20buttons%20are%20always%20the%20login%20style%20types%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.replaceSettings.type%20===%20'loginButton')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20'loginMode'%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(window?.matchMedia('(prefers-color-scheme:%20dark)')?.matches)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20'darkMode'%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20'lightMode'%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Take%20note%20of%20some%20of%20the%20tracking%20element's%20style%20attributes%20(as%0A%20%20%20%20%20%20%20%20%20*%20determined%20by%20clickAction.styleDataAttributes)%20as%20a%20CSS%20string.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getStyle%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20styleString%20=%20'border:%20none;';%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.clickAction.styleDataAttributes)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Copy%20elements%20from%20the%20original%20div%20into%20style%20attributes%20as%20directed%20by%20config%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5Battr,%20valAttr%5D%20of%20Object.entries(this.clickAction.styleDataAttributes))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20valueFound%20=%20this.dataElements%5BvalAttr.name%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!valueFound)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20valueFound%20=%20this.dataElements%5BvalAttr.fallbackAttribute%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20partialStyleString%20=%20'';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(valueFound)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20partialStyleString%20+=%20%60$%7Battr%7D:%20$%7BvalueFound%7D%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!partialStyleString.includes(valAttr.unit))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20partialStyleString%20+=%20valAttr.unit;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20partialStyleString%20+=%20';';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleString%20+=%20partialStyleString;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20styleString%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Store%20some%20attributes%20from%20the%20original%20tracking%20element,%20used%20for%20both%0A%20%20%20%20%20%20%20%20%20*%20placeholder%20element%20styling,%20and%20when%20restoring%20the%20original%20tracking%0A%20%20%20%20%20%20%20%20%20*%20element.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20copySocialDataFields%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this.clickAction.urlDataAttributesToPreserve)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20App%20ID%20may%20be%20set%20by%20client%20scripts,%20and%20is%20required%20for%20some%20elements.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.dataElements.app_id_replace%20&&%20appID%20!=%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.targetURL%20=%20this.clickAction.targetURL.replace('app_id_replace',%20appID);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20key%20of%20Object.keys(this.dataElements))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20attrValue%20=%20this.dataElements%5Bkey%5D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!attrValue)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20URL%20for%20Facebook%20videos%20are%20specified%20as%20the%20data-href%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20attribute%20on%20a%20div,%20that%20is%20then%20used%20to%20create%20the%20iframe.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Some%20websites%20omit%20the%20protocol%20part%20of%20the%20URL%20when%20doing%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20that,%20which%20then%20prevents%20the%20iframe%20from%20loading%20correctly.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(key%20===%20'data-href'%20&&%20attrValue.startsWith('//'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20attrValue%20=%20window.location.protocol%20+%20attrValue;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.targetURL%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.targetURL.replace(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20key,%20encodeURIComponent(attrValue)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Creates%20an%20iFrame%20for%20this%20facebook%20content.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BHTMLIFrameElement%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20createFBIFrame%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20frame%20=%20document.createElement('iframe');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20frame.setAttribute('src',%20this.getTargetURL());%0A%20%20%20%20%20%20%20%20%20%20%20%20frame.setAttribute('style',%20this.getStyle());%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20frame%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Tweaks%20an%20embedded%20YouTube%20video%20element%20ready%20for%20when%20it's%0A%20%20%20%20%20%20%20%20%20*%20reloaded.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20videoElement%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BEventListener?%7D%20onError%0A%20%20%20%20%20%20%20%20%20*%20%20%20Function%20to%20be%20called%20if%20the%20video%20fails%20to%20load.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20adjustYouTubeVideoElement%20(videoElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20onError%20=%20null;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!videoElement.src)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20onError%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20url%20=%20new%20URL(videoElement.src);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20hostname:%20originalHostname%20%7D%20=%20url;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Upgrade%20video%20to%20YouTube's%20%22privacy%20enhanced%22%20mode,%20but%20fall%20back%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20to%20standard%20mode%20if%20the%20video%20fails%20to%20load.%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Note:%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%201.%20Changing%20the%20iframe's%20host%20like%20this%20won't%20cause%20a%20CSP%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20violation%20on%20Chrome,%20see%20https://crbug.com/1271196.%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%202.%20The%20onError%20event%20doesn't%20fire%20for%20blocked%20iframes%20on%20Chrome.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(originalHostname%20!==%20'www.youtube-nocookie.com')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.hostname%20=%20'www.youtube-nocookie.com';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onError%20=%20(event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.hostname%20=%20originalHostname;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20videoElement.src%20=%20url.href;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20event.stopImmediatePropagation();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Configure%20auto-play%20correctly%20depending%20on%20if%20the%20video's%20preview%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20loaded,%20otherwise%20it%20doesn't%20allow%20autoplay.%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20allowString%20=%20videoElement.getAttribute('allow')%20%7C%7C%20'';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20allowed%20=%20new%20Set(allowString.split(';').map(s%20=%3E%20s.trim()));%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.autoplay)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20allowed.add('autoplay');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.searchParams.set('autoplay',%20'1');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20allowed.delete('autoplay');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.searchParams.delete('autoplay');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20allowString%20=%20Array.from(allowed).join(';%20');%0A%20%20%20%20%20%20%20%20%20%20%20%20videoElement.setAttribute('allow',%20allowString);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20videoElement.src%20=%20url.href;%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20onError%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Fades%20the%20given%20element%20in/out.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20element%20to%20fade%20in%20or%20out.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bnumber%7D%20interval%0A%20%20%20%20%20%20%20%20%20*%20%20%20Frequency%20of%20opacity%20updates%20(ms).%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bboolean%7D%20fadeIn%0A%20%20%20%20%20%20%20%20%20*%20%20%20True%20if%20the%20element%20should%20fade%20in%20instead%20of%20out.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPromise%3Cvoid%3E%7D%0A%20%20%20%20%20%20%20%20%20*%20%20%20%20Promise%20that%20resolves%20when%20the%20fade%20in/out%20is%20complete.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20fadeElement%20(element,%20interval,%20fadeIn)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20Promise(resolve%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20opacity%20=%20fadeIn%20?%200%20:%201;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20originStyle%20=%20element.style.cssText;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20fadeOut%20=%20setInterval(function%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20opacity%20+=%20fadeIn%20?%200.03%20:%20-0.03;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20element.style.cssText%20=%20originStyle%20+%20%60opacity:%20$%7Bopacity%7D;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(opacity%20%3C=%200%20%7C%7C%20opacity%20%3E=%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearInterval(fadeOut);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20resolve();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20interval);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Fades%20the%20given%20element%20out.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20element%20to%20fade%20out.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPromise%3Cvoid%3E%7D%0A%20%20%20%20%20%20%20%20%20*%20%20%20%20Promise%20that%20resolves%20when%20the%20fade%20out%20is%20complete.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20fadeOutElement%20(element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.fadeElement(element,%2010,%20false)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Fades%20the%20given%20element%20in.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20element%20to%20fade%20in.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPromise%3Cvoid%3E%7D%0A%20%20%20%20%20%20%20%20%20*%20%20%20%20Promise%20that%20resolves%20when%20the%20fade%20in%20is%20complete.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20fadeInElement%20(element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.fadeElement(element,%2010,%20true)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20The%20function%20that's%20called%20when%20the%20user%20clicks%20to%20load%20some%20content.%0A%20%20%20%20%20%20%20%20%20*%20Unblocks%20the%20content,%20puts%20it%20back%20in%20the%20page,%20and%20removes%20the%0A%20%20%20%20%20%20%20%20%20*%20placeholder.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20originalElement%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20original%20tracking%20element.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20replacementElement%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20placeholder%20element.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20clickFunction%20(originalElement,%20replacementElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20clicked%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20handleClick%20=%20e%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Ensure%20that%20the%20click%20is%20created%20by%20a%20user%20event%20&%20prevent%20double%20clicks%20from%20adding%20more%20animations%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(e.isTrusted%20&&%20!clicked)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.isUnblocked%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clicked%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20isLogin%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20clickElement%20=%20e.srcElement;%20//%20Object.assign(%7B%7D,%20e)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.replaceSettings.type%20===%20'loginButton')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isLogin%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('ddg-ctp-unblockClickToLoadContent-complete',%20()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20parent%20=%20replacementElement.parentNode;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20placeholder%20was%20removed%20from%20the%20DOM%20while%20we%20loaded%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20the%20original%20content,%20give%20up.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!parent)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20we%20allow%20everything%20when%20this%20element%20is%20clicked,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20notify%20surrogate%20to%20enable%20SDK%20and%20replace%20original%20element.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.clickAction.type%20===%20'allowFull')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20parent.replaceChild(originalElement,%20replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.dispatchEvent(window,%20'ddg-ctp-load-sdk');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Create%20a%20container%20for%20the%20new%20FB%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20fbContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.style.cssText%20=%20styles.wrapperDiv;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20fadeIn%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fadeIn.style.cssText%20=%20'display:%20none;%20opacity:%200;';%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Loading%20animation%20(FB%20can%20take%20some%20time%20to%20load)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20loadingImg%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadingImg.setAttribute('src',%20loadingImages%5Bthis.getMode()%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadingImg.setAttribute('height',%20'14px');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadingImg.style.cssText%20=%20styles.loadingImg;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Always%20add%20the%20animation%20to%20the%20button,%20regardless%20of%20click%20source%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(clickElement.nodeName%20===%20'BUTTON')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickElement.firstElementChild.insertBefore(loadingImg,%20clickElement.firstElementChild.firstChild);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20try%20to%20find%20the%20button%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20el%20=%20clickElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20button%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20while%20(button%20===%20null%20&&%20el%20!==%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20button%20=%20el.querySelector('button');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%20=%20el.parentElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(button)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20button.firstElementChild.insertBefore(loadingImg,%20button.firstElementChild.firstChild);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.appendChild(fadeIn);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20fbElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20onError%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch%20(this.clickAction.type)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20'iFrame':%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement%20=%20this.createFBIFrame();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20'youtube-video':%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onError%20=%20this.adjustYouTubeVideoElement(originalElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement%20=%20originalElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement%20=%20originalElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Modify%20the%20overlay%20to%20include%20a%20Facebook%20iFrame,%20which%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20starts%20invisible.%20Once%20loaded,%20fade%20out%20and%20remove%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20overlay%20then%20fade%20in%20the%20Facebook%20content.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20parent.replaceChild(fbContainer,%20replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.appendChild(replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fadeIn.appendChild(fbElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement.addEventListener('load',%20async%20()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20this.fadeOutElement(replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.replaceWith(fbElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.dispatchEvent(fbElement,%20'ddg-ctp-placeholder-clicked');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20this.fadeInElement(fadeIn);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Focus%20on%20new%20element%20for%20screen%20readers.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement.focus();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Note:%20This%20event%20only%20fires%20on%20Firefox,%20on%20Chrome%20the%20frame's%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20load%20event%20will%20always%20fire.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(onError)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement.addEventListener('error',%20onError,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20action%20=%20this.entity%20===%20'Youtube'%20?%20'block-ctl-yt'%20:%20'block-ctl-fb';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unblockClickToLoadContent(%7B%20entity:%20this.entity,%20action,%20isLogin%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20this%20is%20a%20login%20button,%20show%20modal%20if%20needed%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.replaceSettings.type%20===%20'loginButton'%20&&%20entityData%5Bthis.entity%5D.shouldShowLoginModal)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20e%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20makeModal(this.entity,%20handleClick,%20e);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20handleClick%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Replace%20the%20given%20tracking%20element%20with%20the%20given%20placeholder.%0A%20%20%20%20%20*%20Notes:%0A%20%20%20%20%20*%20%201.%20This%20function%20also%20dispatches%20events%20targetting%20the%20original%20and%0A%20%20%20%20%20*%20%20%20%20%20placeholder%20elements.%20That%20way,%20the%20surrogate%20scripts%20can%20use%20the%20event%0A%20%20%20%20%20*%20%20%20%20%20targets%20to%20keep%20track%20of%20which%20placeholder%20corresponds%20to%20which%20tracking%0A%20%20%20%20%20*%20%20%20%20%20element.%0A%20%20%20%20%20*%20%202.%20To%20achieve%20that,%20the%20original%20and%20placeholder%20elements%20must%20be%20in%20the%20DOM%0A%20%20%20%20%20*%20%20%20%20%20at%20the%20time%20the%20events%20are%20dispatched.%20Otherwise,%20the%20events%20will%20not%0A%20%20%20%20%20*%20%20%20%20%20bubble%20up%20and%20the%20surrogate%20script%20will%20miss%20them.%0A%20%20%20%20%20*%20%203.%20Placeholder%20must%20be%20shown%20immediately%20(to%20avoid%20a%20flicker%20for%20the%20user),%0A%20%20%20%20%20*%20%20%20%20%20but%20the%20events%20must%20only%20be%20sent%20once%20the%20document%20(and%20therefore%0A%20%20%20%20%20*%20%20%20%20%20surrogate%20scripts)%20have%20loaded.%0A%20%20%20%20%20*%20%204.%20Therefore,%20we%20hide%20the%20element%20until%20the%20page%20has%20loaded,%20then%20dispatch%0A%20%20%20%20%20*%20%20%20%20%20the%20events%20after%20page%20load,%20and%20then%20remove%20the%20element%20from%20the%20DOM.%0A%20%20%20%20%20*%20%205.%20The%20%22ddg-ctp-ready%22%20event%20needs%20to%20be%20dispatched%20_after_%20the%20element%0A%20%20%20%20%20*%20%20%20%20%20replacement%20events%20have%20fired.%20That%20is%20why%20a%20setTimeout%20is%20required%0A%20%20%20%20%20*%20%20%20%20%20before%20dispatching%20%22ddg-ctp-ready%22.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%20Also%20note,%20this%20all%20assumes%20that%20the%20surrogate%20script%20that%20needs%20these%0A%20%20%20%20%20*%20%20events%20will%20not%20be%20loaded%20asynchronously%20after%20the%20page%20has%20finished%0A%20%20%20%20%20*%20%20loading.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20DuckWidget%20associated%20with%20the%20tracking%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20trackingElement%0A%20%20%20%20%20*%20%20%20The%20tracking%20element%20on%20the%20page%20to%20replace.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20placeholderElement%0A%20%20%20%20%20*%20%20%20The%20placeholder%20element%20that%20should%20be%20shown%20instead.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20replaceTrackingElement%20(widget,%20trackingElement,%20placeholderElement)%20%7B%0A%20%20%20%20%20%20%20%20//%20In%20some%20situations%20(e.g.%20YouTube%20Click%20to%20Load%20previews%20are%0A%20%20%20%20%20%20%20%20//%20enabled/disabled),%20a%20second%20placeholder%20will%20be%20shown%20for%20a%20tracking%0A%20%20%20%20%20%20%20%20//%20element.%0A%20%20%20%20%20%20%20%20const%20elementToReplace%20=%20widget.placeholderElement%20%7C%7C%20trackingElement;%0A%0A%20%20%20%20%20%20%20%20//%20Note%20the%20placeholder%20element,%20so%20that%20it%20can%20also%20be%20replaced%20later%20if%0A%20%20%20%20%20%20%20%20//%20necessary.%0A%20%20%20%20%20%20%20%20widget.placeholderElement%20=%20placeholderElement;%0A%0A%20%20%20%20%20%20%20%20//%20First%20hide%20the%20element,%20since%20we%20need%20to%20keep%20it%20in%20the%20DOM%20until%20the%0A%20%20%20%20%20%20%20%20//%20events%20have%20been%20dispatched.%0A%20%20%20%20%20%20%20%20const%20originalDisplay%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.style.getPropertyValue('display'),%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.style.getPropertyPriority('display')%0A%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20elementToReplace.style.setProperty('display',%20'none',%20'important');%0A%0A%20%20%20%20%20%20%20%20//%20Add%20the%20placeholder%20element%20to%20the%20page.%0A%20%20%20%20%20%20%20%20elementToReplace.parentElement.insertBefore(%0A%20%20%20%20%20%20%20%20%20%20%20%20placeholderElement,%20elementToReplace%0A%20%20%20%20%20%20%20%20);%0A%0A%20%20%20%20%20%20%20%20//%20While%20the%20placeholder%20is%20shown%20(and%20original%20element%20hidden)%0A%20%20%20%20%20%20%20%20//%20synchronously,%20the%20events%20are%20dispatched%20(and%20original%20element%20removed%0A%20%20%20%20%20%20%20%20//%20from%20the%20DOM)%20asynchronously%20after%20the%20page%20has%20finished%20loading.%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20promise/prefer-await-to-then%0A%20%20%20%20%20%20%20%20afterPageLoad.then(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20With%20page%20load%20complete,%20and%20both%20elements%20in%20the%20DOM,%20the%20events%20can%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20be%20dispatched.%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.dispatchEvent(trackingElement,%20'ddg-ctp-tracking-element');%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.dispatchEvent(placeholderElement,%20'ddg-ctp-placeholder-element');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Once%20the%20events%20are%20sent,%20the%20tracking%20element%20(or%20previous%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20placeholder)%20can%20finally%20be%20removed%20from%20the%20DOM.%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.remove();%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.style.setProperty('display',%20...originalDisplay);%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20placeholder%20element%20for%20the%20given%20tracking%20element%20and%20replaces%0A%20%20%20%20%20*%20it%20on%20the%20page.%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20CTL%20'widget'%20associated%20with%20the%20tracking%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20trackingElement%0A%20%20%20%20%20*%20%20%20The%20tracking%20element%20on%20the%20page%20that%20should%20be%20replaced%20with%20a%20placeholder.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createPlaceholderElementAndReplace%20(widget,%20trackingElement)%20%7B%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'blank')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20document.createElement('div'));%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'loginButton')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20icon%20=%20widget.replaceSettings.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Create%20a%20button%20to%20replace%20old%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20button,%20container%20%7D%20=%20makeLoginButton(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.buttonText,%20widget.getMode(),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.popupBodyText,%20icon,%20trackingElement%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20button.addEventListener('click',%20widget.clickFunction(trackingElement,%20container));%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20container);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Facebook%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'dialog')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20icon%20=%20widget.replaceSettings.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20button%20=%20makeButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20textButton%20=%20makeTextButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20contentBlock,%20shadowRoot%20%7D%20=%20createContentBlock(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget,%20button,%20textButton,%20icon%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20button.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%20%20%20%20%20%20%20%20%20%20%20%20textButton.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20contentBlock);%0A%20%20%20%20%20%20%20%20%20%20%20%20showExtraUnblockIfShortPlaceholder(shadowRoot,%20contentBlock);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20YouTube%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'youtube-video')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sendMessage('updateYouTubeCTLAddedFlag',%20true);%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceYouTubeCTL(trackingElement,%20widget);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Subscribe%20to%20changes%20to%20youtubePreviewsEnabled%20setting%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20and%20update%20the%20CTL%20state%0A%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'ddg-settings-youtubePreviewsEnabled',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(/**%20@type%20CustomEvent%20*/%20%7B%20detail:%20value%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isYoutubePreviewsEnabled%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceYouTubeCTL(trackingElement,%20widget);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20trackingElement%0A%20%20%20%20%20*%20%20%20The%20original%20tracking%20element%20(YouTube%20video%20iframe)%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20CTL%20'widget'%20associated%20with%20the%20tracking%20element.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20replaceYouTubeCTL%20(trackingElement,%20widget)%20%7B%0A%20%20%20%20%20%20%20%20//%20Skip%20replacing%20tracking%20element%20if%20it%20has%20already%20been%20unblocked%0A%20%20%20%20%20%20%20%20if%20(widget.isUnblocked)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20(isYoutubePreviewsEnabled%20===%20true)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Show%20YouTube%20Preview%20for%20embedded%20video%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20oldPlaceholder%20=%20widget.placeholderElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20youTubePreview,%20shadowRoot%20%7D%20=%20createYouTubePreview(trackingElement,%20widget);%0A%20%20%20%20%20%20%20%20%20%20%20%20resizeElementToMatch(oldPlaceholder%20%7C%7C%20trackingElement,%20youTubePreview);%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20youTubePreview);%0A%20%20%20%20%20%20%20%20%20%20%20%20showExtraUnblockIfShortPlaceholder(shadowRoot,%20youTubePreview);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Block%20YouTube%20embedded%20video%20and%20display%20blocking%20dialog%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.autoplay%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20oldPlaceholder%20=%20widget.placeholderElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20blockingDialog,%20shadowRoot%20%7D%20=%20createYouTubeBlockingDialog(trackingElement,%20widget);%0A%20%20%20%20%20%20%20%20%20%20%20%20resizeElementToMatch(oldPlaceholder%20%7C%7C%20trackingElement,%20blockingDialog);%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20blockingDialog);%0A%20%20%20%20%20%20%20%20%20%20%20%20showExtraUnblockIfShortPlaceholder(shadowRoot,%20blockingDialog);%0A%20%20%20%20%20%20%20%20%20%20%20%20hideInfoTextIfNarrowPlaceholder(shadowRoot,%20blockingDialog,%20460);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Show%20the%20extra%20unblock%20link%20in%20the%20header%20if%20the%20placeholder%20or%0A%20%20%20%20%20*%20its%20parent%20is%20too%20short%20for%20the%20normal%20unblock%20button%20to%20be%20visible.%0A%20%20%20%20%20*%20Note:%20This%20does%20not%20take%20into%20account%20the%20placeholder's%20vertical%0A%20%20%20%20%20*%20%20%20%20%20%20%20position%20in%20the%20parent%20element.%0A%20%20%20%20%20*%20@param%20%7BShadowRoot%7D%20shadowRoot%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20placeholder%20Placeholder%20for%20tracking%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20showExtraUnblockIfShortPlaceholder%20(shadowRoot,%20placeholder)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!placeholder.parentElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20%7B%20height:%20placeholderHeight%20%7D%20=%20placeholder.getBoundingClientRect();%0A%20%20%20%20%20%20%20%20const%20%7B%20height:%20parentHeight%20%7D%20=%20placeholder.parentElement.getBoundingClientRect();%0A%0A%20%20%20%20%20%20%20%20if%20((placeholderHeight%20%3E%200%20&&%20placeholderHeight%20%3C=%20200)%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20(parentHeight%20%3E%200%20&&%20parentHeight%20%3C=%20230))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%20@type%20%7BHTMLElement?%7D%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20titleRowTextButton%20=%20shadowRoot.querySelector(%60#$%7BtitleID%20+%20'TextButton'%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(titleRowTextButton)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20titleRowTextButton.style.display%20=%20'block';%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Avoid%20the%20placeholder%20being%20taller%20than%20the%20containing%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20and%20overflowing.%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%20@type%20%7BHTMLElement?%7D%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20innerDiv%20=%20shadowRoot.querySelector('.DuckDuckGoSocialContainer');%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(innerDiv)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20innerDiv.style.minHeight%20=%20'';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20innerDiv.style.maxHeight%20=%20parentHeight%20+%20'px';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20innerDiv.style.overflow%20=%20'hidden';%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hide%20the%20info%20text%20(and%20move%20the%20%22Learn%20More%22%20link)%20if%20the%20placeholder%20is%20too%0A%20%20%20%20%20*%20narrow.%0A%20%20%20%20%20*%20@param%20%7BShadowRoot%7D%20shadowRoot%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20placeholder%20Placeholder%20for%20tracking%20element%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20narrowWidth%0A%20%20%20%20%20*%20%20%20%20Maximum%20placeholder%20width%20(in%20pixels)%20for%20the%20placeholder%20to%20be%20considered%0A%20%20%20%20%20*%20%20%20%20narrow.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20hideInfoTextIfNarrowPlaceholder%20(shadowRoot,%20placeholder,%20narrowWidth)%20%7B%0A%20%20%20%20%20%20%20%20const%20%7B%20width:%20placeholderWidth%20%7D%20=%20placeholder.getBoundingClientRect();%0A%20%20%20%20%20%20%20%20if%20(placeholderWidth%20%3E%200%20&&%20placeholderWidth%20%3C=%20narrowWidth)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20buttonContainer%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shadowRoot.querySelector('.DuckDuckGoButton.primary')?.parentElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20contentTitle%20=%20shadowRoot.getElementById('contentTitle');%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20infoText%20=%20shadowRoot.getElementById('infoText');%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%20@type%20%7BHTMLElement?%7D%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20learnMoreLink%20=%20shadowRoot.getElementById('learnMoreLink');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20These%20elements%20will%20exist,%20but%20this%20check%20keeps%20TypeScript%20happy.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!buttonContainer%20%7C%7C%20!contentTitle%20%7C%7C%20!infoText%20%7C%7C%20!learnMoreLink)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Remove%20the%20information%20text.%0A%20%20%20%20%20%20%20%20%20%20%20%20infoText.remove();%0A%20%20%20%20%20%20%20%20%20%20%20%20learnMoreLink.remove();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Append%20the%20%22Learn%20More%22%20link%20to%20the%20title.%0A%20%20%20%20%20%20%20%20%20%20%20%20contentTitle.innerText%20+=%20'.%20';%0A%20%20%20%20%20%20%20%20%20%20%20%20learnMoreLink.style.removeProperty('font-size');%0A%20%20%20%20%20%20%20%20%20%20%20%20contentTitle.appendChild(learnMoreLink);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Improve%20margin/padding,%20to%20ensure%20as%20much%20is%20displayed%20as%20possible.%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonContainer.style.removeProperty('margin');%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Replace%20the%20blocked%20CTL%20elements%20on%20the%20page%20with%20placeholders.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20%5BtargetElement%5D%0A%20%20%20%20%20*%20%20%20If%20specified,%20only%20this%20element%20will%20be%20replaced%20(assuming%20it%20matches%0A%20%20%20%20%20*%20%20%20one%20of%20the%20expected%20CSS%20selectors).%20If%20omitted,%20all%20matching%20elements%0A%20%20%20%20%20*%20%20%20in%20the%20document%20will%20be%20replaced%20instead.%0A%20%20%20%20%20*/%0A%20%20%20%20async%20function%20replaceClickToLoadElements%20(targetElement)%20%7B%0A%20%20%20%20%20%20%20%20await%20readyToDisplayPlaceholders;%0A%0A%20%20%20%20%20%20%20%20for%20(const%20entity%20of%20Object.keys(config))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20widgetData%20of%20Object.values(config%5Bentity%5D.elementData))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20selector%20=%20widgetData.selectors.join();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20trackingElements%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(targetElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(targetElement.matches(selector))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trackingElements.push(targetElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trackingElements%20=%20Array.from(document.querySelectorAll(selector));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20Promise.all(trackingElements.map(trackingElement%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(knownTrackingElements.has(trackingElement))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Promise.resolve()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20knownTrackingElements.add(trackingElement);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20widget%20=%20new%20DuckWidget(widgetData,%20trackingElement,%20entity);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20createPlaceholderElementAndReplace(widget,%20trackingElement)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Messaging%20to%20surrogates%20&%20extension%0A%20%20%20%20%20*********************************************************/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20unblockClickToLoadContentRequest%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20entity%0A%20%20%20%20%20*%20%20%20The%20entity%20to%20unblock%20requests%20for%20(e.g.%20%22Facebook,%20Inc.%22).%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20%5BisLogin=false%5D%0A%20%20%20%20%20*%20%20%20True%20if%20we%20should%20%22allow%20social%20login%22,%20defaults%20to%20false.%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20action%0A%20%20%20%20%20*%20%20%20The%20Click%20to%20Load%20blocklist%20rule%20action%20(e.g.%20%22block-ctl-fb%22)%20that%20should%0A%20%20%20%20%20*%20%20%20be%20allowed.%20Important%20since%20in%20the%20future%20there%20might%20be%20multiple%20types%20of%0A%20%20%20%20%20*%20%20%20embedded%20content%20from%20the%20same%20entity%20that%20the%20user%20can%20allow%0A%20%20%20%20%20*%20%20%20independently.%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Send%20a%20message%20to%20the%20background%20to%20unblock%20requests%20for%20the%20given%20entity%20for%0A%20%20%20%20%20*%20the%20page.%0A%20%20%20%20%20*%20@param%20%7BunblockClickToLoadContentRequest%7D%20message%0A%20%20%20%20%20*%20@see%20%7B@link%20ddg-ctp-unblockClickToLoadContent-complete%7D%20for%20the%20response%20handler.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20unblockClickToLoadContent%20(message)%20%7B%0A%20%20%20%20%20%20%20%20sendMessage('unblockClickToLoadContent',%20message);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Unblock%20the%20entity,%20close%20the%20login%20dialog%20and%20continue%20the%20Facebook%20login%0A%20%20%20%20%20*%20flow.%20Called%20after%20the%20user%20clicks%20to%20proceed%20after%20the%20warning%20dialog%20is%0A%20%20%20%20%20*%20shown.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20*/%0A%20%20%20%20function%20runLogin%20(entity)%20%7B%0A%20%20%20%20%20%20%20%20const%20action%20=%20entity%20===%20'Youtube'%20?%20'block-ctl-yt'%20:%20'block-ctl-fb';%0A%20%20%20%20%20%20%20%20unblockClickToLoadContent(%7B%20entity,%20action,%20isLogin:%20true%20%7D);%0A%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent('ddg-ctp-run-login',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entity%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Close%20the%20login%20dialog%20and%20abort.%20Called%20after%20the%20user%20clicks%20to%20cancel%0A%20%20%20%20%20*%20after%20the%20warning%20dialog%20is%20shown.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20*/%0A%20%20%20%20function%20cancelModal%20(entity)%20%7B%0A%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent('ddg-ctp-cancel-modal',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entity%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20openShareFeedbackPage%20()%20%7B%0A%20%20%20%20%20%20%20%20sendMessage('openShareFeedbackPage',%20'');%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20getYouTubeVideoDetails%20(videoURL)%20%7B%0A%20%20%20%20%20%20%20%20sendMessage('getYouTubeVideoDetails',%20videoURL);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Widget%20building%20blocks%0A%20%20%20%20%20*********************************************************/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20%22Learn%20more%22%20link%20element.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20%5Bmode='lightMode'%5D%0A%20%20%20%20%20*%20@returns%20%7BHTMLAnchorElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getLearnMoreLink%20(mode%20=%20'lightMode')%20%7B%0A%20%20%20%20%20%20%20%20const%20linkElement%20=%20document.createElement('a');%0A%20%20%20%20%20%20%20%20linkElement.style.cssText%20=%20styles.generalLink%20+%20styles%5Bmode%5D.linkFont;%0A%20%20%20%20%20%20%20%20linkElement.ariaLabel%20=%20sharedStrings.readAbout;%0A%20%20%20%20%20%20%20%20linkElement.href%20=%20'https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/';%0A%20%20%20%20%20%20%20%20linkElement.target%20=%20'_blank';%0A%20%20%20%20%20%20%20%20linkElement.textContent%20=%20sharedStrings.learnMore;%0A%20%20%20%20%20%20%20%20linkElement.id%20=%20'learnMoreLink';%0A%20%20%20%20%20%20%20%20return%20linkElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Resizes%20and%20positions%20the%20target%20element%20to%20match%20the%20source%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20sourceElement%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20targetElement%0A%20%20%20%20%20*/%0A%20%20%20%20function%20resizeElementToMatch%20(sourceElement,%20targetElement)%20%7B%0A%20%20%20%20%20%20%20%20const%20computedStyle%20=%20window.getComputedStyle(sourceElement);%0A%20%20%20%20%20%20%20%20const%20stylesToCopy%20=%20%5B'position',%20'top',%20'bottom',%20'left',%20'right',%0A%20%20%20%20%20%20%20%20%20%20%20%20'transform',%20'margin'%5D;%0A%0A%20%20%20%20%20%20%20%20//%20It's%20apparently%20preferable%20to%20use%20the%20source%20element's%20size%20relative%20to%0A%20%20%20%20%20%20%20%20//%20the%20current%20viewport,%20when%20resizing%20the%20target%20element.%20However,%20the%0A%20%20%20%20%20%20%20%20//%20declarativeNetRequest%20API%20%22collapses%22%20(hides)%20blocked%20elements.%20When%0A%20%20%20%20%20%20%20%20//%20that%20happens,%20getBoundingClientRect%20will%20return%20all%20zeros.%0A%20%20%20%20%20%20%20%20//%20TODO:%20Remove%20this%20entirely,%20and%20always%20use%20the%20computed%20height/width%20of%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20the%20source%20element%20instead?%0A%20%20%20%20%20%20%20%20const%20%7B%20height,%20width%20%7D%20=%20sourceElement.getBoundingClientRect();%0A%20%20%20%20%20%20%20%20if%20(height%20%3E%200%20&&%20width%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20targetElement.style.height%20=%20height%20+%20'px';%0A%20%20%20%20%20%20%20%20%20%20%20%20targetElement.style.width%20=%20width%20+%20'px';%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20stylesToCopy.push('height',%20'width');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20(const%20key%20of%20stylesToCopy)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20targetElement.style%5Bkey%5D%20=%20computedStyle%5Bkey%5D;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20%60%3Cstyle/%3E%60%20element%20with%20DDG%20font-face%20styles/CSS%0A%20%20%20%20%20*%20to%20be%20attached%20to%20DDG%20wrapper%20elements%0A%20%20%20%20%20*%20@returns%20HTMLStyleElement%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeFontFaceStyleElement%20()%20%7B%0A%20%20%20%20%20%20%20%20//%20Put%20our%20custom%20font-faces%20inside%20the%20wrapper%20element,%20since%0A%20%20%20%20%20%20%20%20//%20@font-face%20does%20not%20work%20inside%20a%20shadowRoot.%0A%20%20%20%20%20%20%20%20//%20See%20https://github.com/mdn/interactive-examples/issues/887.%0A%20%20%20%20%20%20%20%20const%20fontFaceStyleElement%20=%20document.createElement('style');%0A%20%20%20%20%20%20%20%20fontFaceStyleElement.textContent%20=%20styles.fontStyle;%0A%20%20%20%20%20%20%20%20return%20fontFaceStyleElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20%60%3Cstyle/%3E%60%20element%20with%20base%20styles%20for%20DDG%20social%20container%20and%0A%20%20%20%20%20*%20button%20to%20be%20attached%20to%20DDG%20wrapper%20elements/shadowRoot,%20also%20returns%20a%20wrapper%0A%20%20%20%20%20*%20class%20name%20for%20Social%20Container%20link%20styles%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20%5Bmode='lightMode'%5D%0A%20%20%20%20%20*%20@returns%20%7B%7BwrapperClass:%20string,%20styleElement:%20HTMLStyleElement;%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeBaseStyleElement%20(mode%20=%20'lightMode')%20%7B%0A%20%20%20%20%20%20%20%20//%20Style%20element%20includes%20our%20font%20&%20overwrites%20page%20styles%0A%20%20%20%20%20%20%20%20const%20styleElement%20=%20document.createElement('style');%0A%20%20%20%20%20%20%20%20const%20wrapperClass%20=%20'DuckDuckGoSocialContainer';%0A%20%20%20%20%20%20%20%20styleElement.textContent%20=%20%60%0A%20%20%20%20%20%20%20%20.$%7BwrapperClass%7D%20a%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.linkFont%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.$%7BwrapperClass%7D%20a:hover%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.linkFont%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.button%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton%20%3E%20div%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.buttonTextContainer%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonBackground%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary%20%3E%20div%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonFont%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary:hover%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonBackgroundHover%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary:active%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonBackgroundPress%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonBackground%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary%20%3E%20div%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonFont%7D%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary:hover%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonBackgroundHover%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary:active%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonBackgroundPress%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20return%20%7B%20wrapperClass,%20styleElement%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20an%20anchor%20element%20with%20no%20destination.%20It%20is%20expected%20that%20a%20click%0A%20%20%20%20%20*%20handler%20is%20added%20to%20the%20element%20later.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20linkText%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20%5Bmode='lightMode'%5D%0A%20%20%20%20%20*%20@returns%20%7BHTMLAnchorElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeTextButton%20(linkText,%20mode)%20%7B%0A%20%20%20%20%20%20%20%20const%20linkElement%20=%20document.createElement('a');%0A%20%20%20%20%20%20%20%20linkElement.style.cssText%20=%20styles.headerLink%20+%20styles%5Bmode%5D.linkFont;%0A%20%20%20%20%20%20%20%20linkElement.textContent%20=%20linkText;%0A%20%20%20%20%20%20%20%20return%20linkElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20button%20element.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20buttonText%0A%20%20%20%20%20*%20%20%20Text%20to%20be%20displayed%20inside%20the%20button.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20%5Bmode='lightMode'%5D%0A%20%20%20%20%20*%20%20%20The%20button%20is%20usually%20styled%20as%20the%20primary%20call%20to%20action,%20but%20if%0A%20%20%20%20%20*%20%20%20'cancelMode'%20is%20specified%20the%20button%20is%20styled%20as%20a%20secondary%20call%20to%0A%20%20%20%20%20*%20%20%20action.%0A%20%20%20%20%20*%20@returns%20%7BHTMLButtonElement%7D%20Button%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeButton%20(buttonText,%20mode%20=%20'lightMode')%20%7B%0A%20%20%20%20%20%20%20%20const%20button%20=%20document.createElement('button');%0A%20%20%20%20%20%20%20%20button.classList.add('DuckDuckGoButton');%0A%20%20%20%20%20%20%20%20button.classList.add(mode%20===%20'cancelMode'%20?%20'secondary'%20:%20'primary');%0A%20%20%20%20%20%20%20%20if%20(buttonText)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20textContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20textContainer.textContent%20=%20buttonText;%0A%20%20%20%20%20%20%20%20%20%20%20%20button.appendChild(textContainer);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20button%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20toggle%20button.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20mode%0A%20%20%20%20%20*%20@param%20%7Bboolean%7D%20%5BisActive=false%5D%0A%20%20%20%20%20*%20%20%20True%20if%20the%20button%20should%20be%20toggled%20by%20default.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BclassNames=''%5D%0A%20%20%20%20%20*%20%20%20Class%20names%20to%20assign%20to%20the%20button%20(space%20delimited).%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BdataKey=''%5D%0A%20%20%20%20%20*%20%20%20Value%20to%20assign%20to%20the%20button's%20'data-key'%20attribute.%0A%20%20%20%20%20*%20@returns%20%7BHTMLButtonElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeToggleButton%20(mode,%20isActive%20=%20false,%20classNames%20=%20'',%20dataKey%20=%20'')%20%7B%0A%20%20%20%20%20%20%20%20const%20toggleButton%20=%20document.createElement('button');%0A%20%20%20%20%20%20%20%20toggleButton.className%20=%20classNames;%0A%20%20%20%20%20%20%20%20toggleButton.style.cssText%20=%20styles.toggleButton;%0A%20%20%20%20%20%20%20%20toggleButton.type%20=%20'button';%0A%20%20%20%20%20%20%20%20toggleButton.setAttribute('aria-pressed',%20isActive%20?%20'true'%20:%20'false');%0A%20%20%20%20%20%20%20%20toggleButton.setAttribute('data-key',%20dataKey);%0A%0A%20%20%20%20%20%20%20%20const%20activeKey%20=%20isActive%20?%20'active'%20:%20'inactive';%0A%0A%20%20%20%20%20%20%20%20const%20toggleBg%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20toggleBg.style.cssText%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20styles.toggleButtonBg%20+%20styles%5Bmode%5D.toggleButtonBgState%5BactiveKey%5D;%0A%0A%20%20%20%20%20%20%20%20const%20toggleKnob%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20toggleKnob.style.cssText%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20styles.toggleButtonKnob%20+%20styles.toggleButtonKnobState%5BactiveKey%5D;%0A%0A%20%20%20%20%20%20%20%20toggleButton.appendChild(toggleBg);%0A%20%20%20%20%20%20%20%20toggleButton.appendChild(toggleKnob);%0A%0A%20%20%20%20%20%20%20%20return%20toggleButton%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20toggle%20button%20that's%20wrapped%20in%20a%20div%20with%20some%20text.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20text%0A%20%20%20%20%20*%20%20%20Text%20to%20display%20by%20the%20button.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20mode%0A%20%20%20%20%20*%20@param%20%7Bboolean%7D%20%5BisActive=false%5D%0A%20%20%20%20%20*%20%20%20True%20if%20the%20button%20should%20be%20toggled%20by%20default.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BtoggleClassNames=''%5D%0A%20%20%20%20%20*%20%20%20Class%20names%20to%20assign%20to%20the%20toggle%20button.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BtextCssStyles=''%5D%0A%20%20%20%20%20*%20%20%20Styles%20to%20apply%20to%20the%20wrapping%20div%20(on%20top%20of%20ones%20determined%20by%20the%0A%20%20%20%20%20*%20%20%20display%20mode.)%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BdataKey=''%5D%0A%20%20%20%20%20*%20%20%20Value%20to%20assign%20to%20the%20button's%20'data-key'%20attribute.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeToggleButtonWithText%20(text,%20mode,%20isActive%20=%20false,%20toggleClassNames%20=%20'',%20textCssStyles%20=%20'',%20dataKey%20=%20'')%20%7B%0A%20%20%20%20%20%20%20%20const%20wrapper%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20wrapper.style.cssText%20=%20styles.toggleButtonWrapper;%0A%0A%20%20%20%20%20%20%20%20const%20toggleButton%20=%20makeToggleButton(mode,%20isActive,%20toggleClassNames,%20dataKey);%0A%0A%20%20%20%20%20%20%20%20const%20textDiv%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20textDiv.style.cssText%20=%20styles.contentText%20+%20styles.toggleButtonText%20+%20styles%5Bmode%5D.toggleButtonText%20+%20textCssStyles;%0A%20%20%20%20%20%20%20%20textDiv.textContent%20=%20text;%0A%0A%20%20%20%20%20%20%20%20wrapper.appendChild(toggleButton);%0A%20%20%20%20%20%20%20%20wrapper.appendChild(textDiv);%0A%20%20%20%20%20%20%20%20return%20wrapper%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20the%20default%20block%20symbol,%20for%20when%20the%20image%20isn't%20available.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeDefaultBlockIcon%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20blockedIcon%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20const%20dash%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20blockedIcon.appendChild(dash);%0A%20%20%20%20%20%20%20%20blockedIcon.style.cssText%20=%20styles.circle;%0A%20%20%20%20%20%20%20%20dash.style.cssText%20=%20styles.rectangle;%0A%20%20%20%20%20%20%20%20return%20blockedIcon%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20share%20feedback%20link%20element.%0A%20%20%20%20%20*%20@returns%20%7BHTMLAnchorElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeShareFeedbackLink%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20feedbackLink%20=%20document.createElement('a');%0A%20%20%20%20%20%20%20%20feedbackLink.style.cssText%20=%20styles.feedbackLink;%0A%20%20%20%20%20%20%20%20feedbackLink.target%20=%20'_blank';%0A%20%20%20%20%20%20%20%20feedbackLink.href%20=%20'#';%0A%20%20%20%20%20%20%20%20feedbackLink.text%20=%20'Share%20Feedback';%0A%20%20%20%20%20%20%20%20//%20Open%20Feedback%20Form%20page%20through%20background%20event%20to%20avoid%20browser%20blocking%20extension%20link%0A%20%20%20%20%20%20%20%20feedbackLink.addEventListener('click',%20function%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.preventDefault();%0A%20%20%20%20%20%20%20%20%20%20%20%20openShareFeedbackPage();%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20return%20feedbackLink%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20share%20feedback%20link%20element,%20wrapped%20in%20a%20styled%20div.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeShareFeedbackRow%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20feedbackRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20feedbackRow.style.cssText%20=%20styles.feedbackRow;%0A%0A%20%20%20%20%20%20%20%20const%20feedbackLink%20=%20makeShareFeedbackLink();%0A%20%20%20%20%20%20%20%20feedbackRow.appendChild(feedbackLink);%0A%0A%20%20%20%20%20%20%20%20return%20feedbackRow%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20placeholder%20Facebook%20login%20button.%20When%20clicked,%20a%20warning%20dialog%0A%20%20%20%20%20*%20is%20displayed%20to%20the%20user.%20The%20login%20flow%20only%20continues%20if%20the%20user%20clicks%20to%0A%20%20%20%20%20*%20proceed.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20buttonText%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20mode%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20hoverTextBody%0A%20%20%20%20%20*%20%20%20The%20hover%20text%20to%20display%20for%20the%20button.%0A%20%20%20%20%20*%20@param%20%7Bstring?%7D%20icon%0A%20%20%20%20%20*%20%20%20The%20source%20of%20the%20icon%20to%20display%20in%20the%20button,%20if%20null%20the%20default%20block%0A%20%20%20%20%20*%20%20%20icon%20is%20used%20instead.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20originalElement%0A%20%20%20%20%20*%20%20%20The%20original%20Facebook%20login%20button%20that%20this%20placeholder%20is%20replacing.%0A%20%20%20%20%20*%20%20%20Note:%20This%20function%20does%20not%20actually%20replace%20the%20button,%20the%20caller%20is%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20expected%20to%20do%20that.%0A%20%20%20%20%20*%20@returns%20%7B%7B%20container:%20HTMLDivElement,%20button:%20HTMLButtonElement%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeLoginButton%20(buttonText,%20mode,%20hoverTextBody,%20icon,%20originalElement)%20%7B%0A%20%20%20%20%20%20%20%20const%20container%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20container.style.cssText%20=%20'position:%20relative;';%0A%20%20%20%20%20%20%20%20container.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20container.attachShadow(%7B%20mode:%20devMode%20?%20'open'%20:%20'closed'%20%7D);%0A%20%20%20%20%20%20%20%20//%20inherit%20any%20class%20styles%20on%20the%20button%0A%20%20%20%20%20%20%20%20container.className%20=%20'fb-login-button%20FacebookLogin__button';%0A%20%20%20%20%20%20%20%20const%20%7B%20styleElement%20%7D%20=%20makeBaseStyleElement(mode);%0A%20%20%20%20%20%20%20%20styleElement.textContent%20+=%20%60%0A%20%20%20%20%20%20%20%20#DuckDuckGoPrivacyEssentialsHoverableText%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20#DuckDuckGoPrivacyEssentialsHoverable:hover%20#DuckDuckGoPrivacyEssentialsHoverableText%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20const%20hoverContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20hoverContainer.id%20=%20'DuckDuckGoPrivacyEssentialsHoverable';%0A%20%20%20%20%20%20%20%20hoverContainer.style.cssText%20=%20styles.hoverContainer;%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(hoverContainer);%0A%0A%20%20%20%20%20%20%20%20//%20Make%20the%20button%0A%20%20%20%20%20%20%20%20const%20button%20=%20makeButton(buttonText,%20mode);%0A%20%20%20%20%20%20%20%20//%20Add%20blocked%20icon%0A%20%20%20%20%20%20%20%20if%20(!icon)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20button.appendChild(makeDefaultBlockIcon());%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20imgElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.style.cssText%20=%20styles.loginIcon;%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('src',%20icon);%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('height',%20'28px');%0A%20%20%20%20%20%20%20%20%20%20%20%20button.appendChild(imgElement);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20hoverContainer.appendChild(button);%0A%0A%20%20%20%20%20%20%20%20//%20hover%20action%0A%20%20%20%20%20%20%20%20const%20hoverBox%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20hoverBox.id%20=%20'DuckDuckGoPrivacyEssentialsHoverableText';%0A%20%20%20%20%20%20%20%20hoverBox.style.cssText%20=%20styles.textBubble;%0A%20%20%20%20%20%20%20%20const%20arrow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20arrow.style.cssText%20=%20styles.textArrow;%0A%20%20%20%20%20%20%20%20hoverBox.appendChild(arrow);%0A%20%20%20%20%20%20%20%20const%20branding%20=%20createTitleRow('DuckDuckGo');%0A%20%20%20%20%20%20%20%20branding.style.cssText%20+=%20styles.hoverTextTitle;%0A%20%20%20%20%20%20%20%20hoverBox.appendChild(branding);%0A%20%20%20%20%20%20%20%20const%20hoverText%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20hoverText.style.cssText%20=%20styles.hoverTextBody;%0A%20%20%20%20%20%20%20%20hoverText.textContent%20=%20hoverTextBody%20+%20'%20';%0A%20%20%20%20%20%20%20%20hoverText.appendChild(getLearnMoreLink(mode));%0A%20%20%20%20%20%20%20%20hoverBox.appendChild(hoverText);%0A%0A%20%20%20%20%20%20%20%20hoverContainer.appendChild(hoverBox);%0A%20%20%20%20%20%20%20%20const%20rect%20=%20originalElement.getBoundingClientRect();%0A%0A%20%20%20%20%20%20%20%20//%20The%20left%20side%20of%20the%20hover%20popup%20may%20go%20offscreen%20if%20the%0A%20%20%20%20%20%20%20%20//%20login%20button%20is%20all%20the%20way%20on%20the%20left%20side%20of%20the%20page.%20This%0A%20%20%20%20%20%20%20%20//%20If%20that%20is%20the%20case,%20dynamically%20shift%20the%20box%20right%20so%20it%20shows%0A%20%20%20%20%20%20%20%20//%20properly.%0A%20%20%20%20%20%20%20%20if%20(rect.left%20%3C%20styles.textBubbleLeftShift)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20leftShift%20=%20-rect.left%20+%2010;%20//%2010px%20away%20from%20edge%20of%20the%20screen%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverBox.style.cssText%20+=%20%60left:%20$%7BleftShift%7Dpx;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20change%20=%20(1%20-%20(rect.left%20/%20styles.textBubbleLeftShift))%20*%20(100%20-%20styles.arrowDefaultLocationPercent);%0A%20%20%20%20%20%20%20%20%20%20%20%20arrow.style.cssText%20+=%20%60left:%20$%7BMath.max(10,%20styles.arrowDefaultLocationPercent%20-%20change)%7D%25;%60;%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(rect.left%20+%20styles.textBubbleWidth%20-%20styles.textBubbleLeftShift%20%3E%20window.innerWidth)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20rightShift%20=%20rect.left%20+%20styles.textBubbleWidth%20-%20styles.textBubbleLeftShift;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diff%20=%20Math.min(rightShift%20-%20window.innerWidth,%20styles.textBubbleLeftShift);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20rightMargin%20=%2020;%20//%20Add%20some%20margin%20to%20the%20page,%20so%20scrollbar%20doesn't%20overlap.%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverBox.style.cssText%20+=%20%60left:%20-$%7Bstyles.textBubbleLeftShift%20+%20diff%20+%20rightMargin%7Dpx;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20change%20=%20((diff%20/%20styles.textBubbleLeftShift))%20*%20(100%20-%20styles.arrowDefaultLocationPercent);%0A%20%20%20%20%20%20%20%20%20%20%20%20arrow.style.cssText%20+=%20%60left:%20$%7BMath.max(10,%20styles.arrowDefaultLocationPercent%20+%20change)%7D%25;%60;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverBox.style.cssText%20+=%20%60left:%20-$%7Bstyles.textBubbleLeftShift%7Dpx;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20arrow.style.cssText%20+=%20%60left:%20$%7Bstyles.arrowDefaultLocationPercent%7D%25;%60;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20button,%0A%20%20%20%20%20%20%20%20%20%20%20%20container%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20privacy%20warning%20dialog%20for%20the%20user,%20so%20that%20the%20user%20can%20choose%20to%0A%20%20%20%20%20*%20proceed/abort.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20*%20%20%20The%20entity%20to%20unblock%20requests%20for%20(e.g.%20%22Facebook,%20Inc.%22)%20if%20the%20user%0A%20%20%20%20%20*%20%20%20clicks%20to%20proceed.%0A%20%20%20%20%20*%20@param%20%7Bfunction%7D%20acceptFunction%0A%20%20%20%20%20*%20%20%20The%20function%20to%20call%20if%20the%20user%20has%20clicked%20to%20proceed.%0A%20%20%20%20%20*%20@param%20%7B...any%7D%20acceptFunctionParams%0A%20%20%20%20%20*%20%20%20The%20parameters%20passed%20to%20acceptFunction%20when%20it%20is%20called.%0A%20%20%20%20%20*%20%20%20TODO:%20Have%20the%20caller%20bind%20these%20arguments%20to%20the%20function%20instead.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeModal%20(entity,%20acceptFunction,%20...acceptFunctionParams)%20%7B%0A%20%20%20%20%20%20%20%20const%20icon%20=%20entityData%5Bentity%5D.modalIcon;%0A%0A%20%20%20%20%20%20%20%20const%20modalContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20modalContainer.setAttribute('data-key',%20'modal');%0A%20%20%20%20%20%20%20%20modalContainer.style.cssText%20=%20styles.modalContainer;%0A%0A%20%20%20%20%20%20%20%20modalContainer.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20const%20closeModal%20=%20()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20document.body.removeChild(modalContainer);%0A%20%20%20%20%20%20%20%20%20%20%20%20cancelModal(entity);%0A%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20//%20Protect%20the%20contents%20of%20our%20modal%20inside%20a%20shadowRoot,%20to%20avoid%0A%20%20%20%20%20%20%20%20//%20it%20being%20styled%20by%20the%20website's%20stylesheets.%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20modalContainer.attachShadow(%7B%20mode:%20devMode%20?%20'open'%20:%20'closed'%20%7D);%0A%20%20%20%20%20%20%20%20const%20%7B%20styleElement%20%7D%20=%20makeBaseStyleElement('lightMode');%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20const%20pageOverlay%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20pageOverlay.style.cssText%20=%20styles.overlay;%0A%0A%20%20%20%20%20%20%20%20const%20modal%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20modal.style.cssText%20=%20styles.modal;%0A%0A%20%20%20%20%20%20%20%20//%20Title%0A%20%20%20%20%20%20%20%20const%20modalTitle%20=%20createTitleRow('DuckDuckGo',%20null,%20closeModal);%0A%20%20%20%20%20%20%20%20modal.appendChild(modalTitle);%0A%0A%20%20%20%20%20%20%20%20const%20iconElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20iconElement.style.cssText%20=%20styles.icon%20+%20styles.modalIcon;%0A%20%20%20%20%20%20%20%20iconElement.setAttribute('src',%20icon);%0A%20%20%20%20%20%20%20%20iconElement.setAttribute('height',%20'70px');%0A%0A%20%20%20%20%20%20%20%20const%20title%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20title.style.cssText%20=%20styles.modalContentTitle;%0A%20%20%20%20%20%20%20%20title.textContent%20=%20entityData%5Bentity%5D.modalTitle;%0A%0A%20%20%20%20%20%20%20%20//%20Content%0A%20%20%20%20%20%20%20%20const%20modalContent%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20modalContent.style.cssText%20=%20styles.modalContent;%0A%0A%20%20%20%20%20%20%20%20const%20message%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20message.style.cssText%20=%20styles.modalContentText;%0A%20%20%20%20%20%20%20%20message.textContent%20=%20entityData%5Bentity%5D.modalText%20+%20'%20';%0A%20%20%20%20%20%20%20%20message.appendChild(getLearnMoreLink());%0A%0A%20%20%20%20%20%20%20%20modalContent.appendChild(iconElement);%0A%20%20%20%20%20%20%20%20modalContent.appendChild(title);%0A%20%20%20%20%20%20%20%20modalContent.appendChild(message);%0A%0A%20%20%20%20%20%20%20%20//%20Buttons%0A%20%20%20%20%20%20%20%20const%20buttonRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20buttonRow.style.cssText%20=%20styles.modalButtonRow;%0A%20%20%20%20%20%20%20%20const%20allowButton%20=%20makeButton(entityData%5Bentity%5D.modalAcceptText,%20'lightMode');%0A%20%20%20%20%20%20%20%20allowButton.style.cssText%20+=%20styles.modalButton%20+%20'margin-bottom:%208px;';%0A%20%20%20%20%20%20%20%20allowButton.setAttribute('data-key',%20'allow');%0A%20%20%20%20%20%20%20%20allowButton.addEventListener('click',%20function%20doLogin%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20acceptFunction(...acceptFunctionParams);%0A%20%20%20%20%20%20%20%20%20%20%20%20document.body.removeChild(modalContainer);%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20const%20rejectButton%20=%20makeButton(entityData%5Bentity%5D.modalRejectText,%20'cancelMode');%0A%20%20%20%20%20%20%20%20rejectButton.setAttribute('data-key',%20'reject');%0A%20%20%20%20%20%20%20%20rejectButton.style.cssText%20+=%20styles.modalButton;%0A%20%20%20%20%20%20%20%20rejectButton.addEventListener('click',%20closeModal);%0A%0A%20%20%20%20%20%20%20%20buttonRow.appendChild(allowButton);%0A%20%20%20%20%20%20%20%20buttonRow.appendChild(rejectButton);%0A%20%20%20%20%20%20%20%20modalContent.appendChild(buttonRow);%0A%0A%20%20%20%20%20%20%20%20modal.appendChild(modalContent);%0A%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(pageOverlay);%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(modal);%0A%0A%20%20%20%20%20%20%20%20document.body.insertBefore(modalContainer,%20document.body.childNodes%5B0%5D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20the%20%22title%20row%22%20div%20that%20contains%20a%20placeholder's%20heading.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20message%0A%20%20%20%20%20*%20%20%20The%20title%20text%20to%20display.%0A%20%20%20%20%20*%20@param%20%7BHTMLAnchorElement?%7D%20%5BtextButton%5D%0A%20%20%20%20%20*%20%20%20The%20link%20to%20display%20with%20the%20title,%20if%20any.%0A%20%20%20%20%20*%20@param%20%7BEventListener%7D%20%5BcloseBtnFn%5D%0A%20%20%20%20%20*%20%20%20If%20provided,%20a%20close%20button%20is%20added%20that%20calls%20this%20function%20when%20clicked.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createTitleRow%20(message,%20textButton,%20closeBtnFn)%20%7B%0A%20%20%20%20%20%20%20%20//%20Create%20row%20container%0A%20%20%20%20%20%20%20%20const%20row%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20row.style.cssText%20=%20styles.titleBox;%0A%0A%20%20%20%20%20%20%20%20//%20Logo%0A%20%20%20%20%20%20%20%20const%20logoContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20logoContainer.style.cssText%20=%20styles.logo;%0A%20%20%20%20%20%20%20%20const%20logoElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20logoElement.setAttribute('src',%20logoImg);%0A%20%20%20%20%20%20%20%20logoElement.setAttribute('height',%20'21px');%0A%20%20%20%20%20%20%20%20logoElement.style.cssText%20=%20styles.logoImg;%0A%20%20%20%20%20%20%20%20logoContainer.appendChild(logoElement);%0A%20%20%20%20%20%20%20%20row.appendChild(logoContainer);%0A%0A%20%20%20%20%20%20%20%20//%20Content%20box%20title%0A%20%20%20%20%20%20%20%20const%20msgElement%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20msgElement.id%20=%20titleID;%20//%20Ensure%20we%20can%20find%20this%20to%20potentially%20hide%20it%20later.%0A%20%20%20%20%20%20%20%20msgElement.textContent%20=%20message;%0A%20%20%20%20%20%20%20%20msgElement.style.cssText%20=%20styles.title;%0A%20%20%20%20%20%20%20%20row.appendChild(msgElement);%0A%0A%20%20%20%20%20%20%20%20//%20Close%20Button%0A%20%20%20%20%20%20%20%20if%20(typeof%20closeBtnFn%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20closeButton%20=%20document.createElement('button');%0A%20%20%20%20%20%20%20%20%20%20%20%20closeButton.style.cssText%20=%20styles.closeButton;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20closeIconImg%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20closeIconImg.setAttribute('src',%20closeIcon);%0A%20%20%20%20%20%20%20%20%20%20%20%20closeIconImg.setAttribute('height',%20'12px');%0A%20%20%20%20%20%20%20%20%20%20%20%20closeIconImg.style.cssText%20=%20styles.closeIcon;%0A%20%20%20%20%20%20%20%20%20%20%20%20closeButton.appendChild(closeIconImg);%0A%20%20%20%20%20%20%20%20%20%20%20%20closeButton.addEventListener('click',%20closeBtnFn);%0A%20%20%20%20%20%20%20%20%20%20%20%20row.appendChild(closeButton);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Text%20button%20for%20very%20small%20boxes%0A%20%20%20%20%20%20%20%20if%20(textButton)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20textButton.id%20=%20titleID%20+%20'TextButton';%0A%20%20%20%20%20%20%20%20%20%20%20%20row.appendChild(textButton);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20row%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20placeholder%20element%20(wrapped%20in%20a%20div%20and%20shadowRoot),%20to%20replace%20a%0A%20%20%20%20%20*%20tracking%20element%20with.%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20Widget%20corresponding%20to%20the%20tracking%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLButtonElement%7D%20button%0A%20%20%20%20%20*%20%20%20Primary%20button%20that%20loads%20the%20original%20tracking%20element%20(and%20removed%20this%0A%20%20%20%20%20*%20%20%20placeholder)%20when%20clicked.%0A%20%20%20%20%20*%20@param%20%7BHTMLAnchorElement?%7D%20textButton%0A%20%20%20%20%20*%20%20%20Link%20to%20display%20next%20to%20the%20title,%20if%20any.%0A%20%20%20%20%20*%20@param%20%7Bstring?%7D%20img%0A%20%20%20%20%20*%20%20%20Source%20of%20image%20to%20display%20in%20the%20placeholder%20(if%20any).%0A%20%20%20%20%20*%20@param%20%7BHTMLDivElement%7D%20%5BbottomRow%5D%0A%20%20%20%20%20*%20%20%20Bottom%20row%20to%20append%20to%20the%20placeholder,%20if%20any.%0A%20%20%20%20%20*%20@returns%20%7B%7B%20contentBlock:%20HTMLDivElement,%20shadowRoot:%20ShadowRoot%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createContentBlock%20(widget,%20button,%20textButton,%20img,%20bottomRow)%20%7B%0A%20%20%20%20%20%20%20%20const%20contentBlock%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentBlock.style.cssText%20=%20styles.wrapperDiv;%0A%0A%20%20%20%20%20%20%20%20contentBlock.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20//%20Put%20everything%20else%20inside%20the%20shadowRoot%20of%20the%20wrapper%20element%20to%0A%20%20%20%20%20%20%20%20//%20reduce%20the%20chances%20of%20the%20website's%20stylesheets%20messing%20up%20the%0A%20%20%20%20%20%20%20%20//%20placeholder's%20appearance.%0A%20%20%20%20%20%20%20%20const%20shadowRootMode%20=%20devMode%20?%20'open'%20:%20'closed';%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20contentBlock.attachShadow(%7B%20mode:%20shadowRootMode%20%7D);%0A%0A%20%20%20%20%20%20%20%20//%20Style%20element%20includes%20our%20font%20&%20overwrites%20page%20styles%0A%20%20%20%20%20%20%20%20const%20%7B%20wrapperClass,%20styleElement%20%7D%20=%20makeBaseStyleElement(widget.getMode());%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20//%20Create%20overall%20grid%20structure%0A%20%20%20%20%20%20%20%20const%20element%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20element.style.cssText%20=%20styles.block%20+%20styles%5Bwidget.getMode()%5D.background%20+%20styles%5Bwidget.getMode()%5D.textFont;%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'youtube-video')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20element.style.cssText%20+=%20styles.youTubeDialogBlock;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20element.className%20=%20wrapperClass;%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(element);%0A%0A%20%20%20%20%20%20%20%20//%20grid%20of%20three%20rows%0A%20%20%20%20%20%20%20%20const%20titleRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20titleRow.style.cssText%20=%20styles.headerRow;%0A%20%20%20%20%20%20%20%20element.appendChild(titleRow);%0A%20%20%20%20%20%20%20%20titleRow.appendChild(createTitleRow('DuckDuckGo',%20textButton));%0A%0A%20%20%20%20%20%20%20%20const%20contentRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentRow.style.cssText%20=%20styles.content;%0A%0A%20%20%20%20%20%20%20%20if%20(img)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20imageRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20imageRow.style.cssText%20=%20styles.imgRow;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20imgElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.style.cssText%20=%20styles.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('src',%20img);%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('height',%20'70px');%0A%20%20%20%20%20%20%20%20%20%20%20%20imageRow.appendChild(imgElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20element.appendChild(imageRow);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20contentTitle%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentTitle.style.cssText%20=%20styles.contentTitle;%0A%20%20%20%20%20%20%20%20contentTitle.textContent%20=%20widget.replaceSettings.infoTitle;%0A%20%20%20%20%20%20%20%20contentTitle.id%20=%20'contentTitle';%0A%20%20%20%20%20%20%20%20contentRow.appendChild(contentTitle);%0A%20%20%20%20%20%20%20%20const%20contentText%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentText.style.cssText%20=%20styles.contentText;%0A%20%20%20%20%20%20%20%20const%20contentTextSpan%20=%20document.createElement('span');%0A%20%20%20%20%20%20%20%20contentTextSpan.id%20=%20'infoText';%0A%20%20%20%20%20%20%20%20contentTextSpan.textContent%20=%20widget.replaceSettings.infoText%20+%20'%20';%0A%20%20%20%20%20%20%20%20contentText.appendChild(contentTextSpan);%0A%20%20%20%20%20%20%20%20contentText.appendChild(getLearnMoreLink());%0A%20%20%20%20%20%20%20%20contentRow.appendChild(contentText);%0A%20%20%20%20%20%20%20%20element.appendChild(contentRow);%0A%0A%20%20%20%20%20%20%20%20const%20buttonRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20buttonRow.style.cssText%20=%20styles.buttonRow;%0A%20%20%20%20%20%20%20%20buttonRow.appendChild(button);%0A%20%20%20%20%20%20%20%20contentText.appendChild(buttonRow);%0A%0A%20%20%20%20%20%20%20%20if%20(bottomRow)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20contentRow.appendChild(bottomRow);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%20Share%20Feedback%20Link%20*/%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'youtube-video')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20feedbackRow%20=%20makeShareFeedbackRow();%0A%20%20%20%20%20%20%20%20%20%20%20%20shadowRoot.appendChild(feedbackRow);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20contentBlock,%20shadowRoot%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20the%20content%20block%20to%20replace%20embedded%20YouTube%20videos/iframes%20with.%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20trackingElement%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20@returns%20%7B%7B%20blockingDialog:%20HTMLElement,%20shadowRoot:%20ShadowRoot%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createYouTubeBlockingDialog%20(trackingElement,%20widget)%20%7B%0A%20%20%20%20%20%20%20%20const%20button%20=%20makeButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%20%20%20%20%20%20%20%20const%20textButton%20=%20makeTextButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%0A%20%20%20%20%20%20%20%20const%20bottomRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20bottomRow.style.cssText%20=%20styles.youTubeDialogBottomRow;%0A%20%20%20%20%20%20%20%20const%20previewToggle%20=%20makeToggleButtonWithText(%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.previewToggleText,%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.getMode(),%0A%20%20%20%20%20%20%20%20%20%20%20%20false,%0A%20%20%20%20%20%20%20%20%20%20%20%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20'yt-preview-toggle'%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20previewToggle.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20()%20=%3E%20makeModal(widget.entity,%20()%20=%3E%20sendMessage('setYoutubePreviewsEnabled',%20true),%20widget.entity)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20bottomRow.appendChild(previewToggle);%0A%0A%20%20%20%20%20%20%20%20const%20%7B%20contentBlock,%20shadowRoot%20%7D%20=%20createContentBlock(%0A%20%20%20%20%20%20%20%20%20%20%20%20widget,%20button,%20textButton,%20null,%20bottomRow%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20contentBlock.id%20=%20trackingElement.id;%0A%20%20%20%20%20%20%20%20contentBlock.style.cssText%20+=%20styles.wrapperDiv%20+%20styles.youTubeWrapperDiv;%0A%0A%20%20%20%20%20%20%20%20button.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%20%20%20%20%20%20%20%20textButton.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20blockingDialog:%20contentBlock,%0A%20%20%20%20%20%20%20%20%20%20%20%20shadowRoot%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20the%20placeholder%20element%20to%20replace%20a%20YouTube%20video%20iframe%20element%0A%20%20%20%20%20*%20with%20a%20preview%20image.%20Mutates%20widget%20Object%20to%20set%20the%20autoplay%20property%0A%20%20%20%20%20*%20as%20the%20preview%20details%20load.%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20originalElement%0A%20%20%20%20%20*%20%20%20The%20YouTube%20video%20iframe%20element.%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20widget%20Object.%20We%20mutate%20this%20to%20set%20the%20autoplay%20property.%0A%20%20%20%20%20*%20@returns%20%7B%7B%20youTubePreview:%20HTMLElement,%20shadowRoot:%20ShadowRoot%20%7D%7D%0A%20%20%20%20%20*%20%20%20Object%20containing%20the%20YouTube%20Preview%20element%20and%20its%20shadowRoot.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createYouTubePreview%20(originalElement,%20widget)%20%7B%0A%20%20%20%20%20%20%20%20const%20youTubePreview%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20youTubePreview.id%20=%20originalElement.id;%0A%20%20%20%20%20%20%20%20youTubePreview.style.cssText%20=%20styles.wrapperDiv%20+%20styles.placeholderWrapperDiv;%0A%0A%20%20%20%20%20%20%20%20youTubePreview.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20//%20Protect%20the%20contents%20of%20our%20placeholder%20inside%20a%20shadowRoot,%20to%20avoid%0A%20%20%20%20%20%20%20%20//%20it%20being%20styled%20by%20the%20website's%20stylesheets.%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20youTubePreview.attachShadow(%7B%20mode:%20devMode%20?%20'open'%20:%20'closed'%20%7D);%0A%20%20%20%20%20%20%20%20const%20%7B%20wrapperClass,%20styleElement%20%7D%20=%20makeBaseStyleElement(widget.getMode());%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20const%20youTubePreviewDiv%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.style.cssText%20=%20styles.youTubeDialogDiv;%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.classList.add(wrapperClass);%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(youTubePreviewDiv);%0A%0A%20%20%20%20%20%20%20%20/**%20Preview%20Image%20*/%0A%20%20%20%20%20%20%20%20const%20previewImageWrapper%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20previewImageWrapper.style.cssText%20=%20styles.youTubePreviewWrapperImg;%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.appendChild(previewImageWrapper);%0A%20%20%20%20%20%20%20%20//%20We%20use%20an%20image%20element%20for%20the%20preview%20image%20so%20that%20we%20can%20ensure%0A%20%20%20%20%20%20%20%20//%20the%20referrer%20isn't%20passed.%0A%20%20%20%20%20%20%20%20const%20previewImageElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20previewImageElement.setAttribute('referrerPolicy',%20'no-referrer');%0A%20%20%20%20%20%20%20%20previewImageElement.style.cssText%20=%20styles.youTubePreviewImg;%0A%20%20%20%20%20%20%20%20previewImageWrapper.appendChild(previewImageElement);%0A%0A%20%20%20%20%20%20%20%20const%20innerDiv%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20innerDiv.style.cssText%20=%20styles.youTubePlaceholder;%0A%0A%20%20%20%20%20%20%20%20/**%20Top%20section%20*/%0A%20%20%20%20%20%20%20%20const%20topSection%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20topSection.style.cssText%20=%20styles.youTubeTopSection;%0A%20%20%20%20%20%20%20%20innerDiv.appendChild(topSection);%0A%0A%20%20%20%20%20%20%20%20/**%20Video%20Title%20*/%0A%20%20%20%20%20%20%20%20const%20titleElement%20=%20document.createElement('p');%0A%20%20%20%20%20%20%20%20titleElement.style.cssText%20=%20styles.youTubeTitle;%0A%20%20%20%20%20%20%20%20topSection.appendChild(titleElement);%0A%0A%20%20%20%20%20%20%20%20/**%20Text%20Button%20on%20top%20section%20*/%0A%20%20%20%20%20%20%20%20//%20Use%20darkMode%20styles%20because%20the%20preview%20background%20is%20dark%20and%20causes%20poor%20contrast%0A%20%20%20%20%20%20%20%20//%20with%20lightMode%20button,%20making%20it%20hard%20to%20read.%0A%20%20%20%20%20%20%20%20const%20textButton%20=%20makeTextButton(widget.replaceSettings.buttonText,%20'darkMode');%0A%20%20%20%20%20%20%20%20textButton.id%20=%20titleID%20+%20'TextButton';%0A%0A%20%20%20%20%20%20%20%20textButton.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.clickFunction(originalElement,%20youTubePreview)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20topSection.appendChild(textButton);%0A%0A%20%20%20%20%20%20%20%20/**%20Play%20Button%20*/%0A%20%20%20%20%20%20%20%20const%20playButtonRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20playButtonRow.style.cssText%20=%20styles.youTubePlayButtonRow;%0A%0A%20%20%20%20%20%20%20%20const%20playButton%20=%20makeButton('',%20widget.getMode());%0A%20%20%20%20%20%20%20%20playButton.style.cssText%20+=%20styles.youTubePlayButton;%0A%0A%20%20%20%20%20%20%20%20const%20videoPlayImg%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20const%20videoPlayIcon%20=%20widget.replaceSettings.placeholder.videoPlayIcon%5Bwidget.getMode()%5D;%0A%20%20%20%20%20%20%20%20videoPlayImg.setAttribute('src',%20videoPlayIcon);%0A%20%20%20%20%20%20%20%20playButton.appendChild(videoPlayImg);%0A%0A%20%20%20%20%20%20%20%20playButton.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.clickFunction(originalElement,%20youTubePreview)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20playButtonRow.appendChild(playButton);%0A%20%20%20%20%20%20%20%20innerDiv.appendChild(playButtonRow);%0A%0A%20%20%20%20%20%20%20%20/**%20Preview%20Toggle%20*/%0A%20%20%20%20%20%20%20%20const%20previewToggleRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20previewToggleRow.style.cssText%20=%20styles.youTubePreviewToggleRow;%0A%0A%20%20%20%20%20%20%20%20const%20previewToggle%20=%20makeToggleButtonWithText(%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.placeholder.previewToggleEnabledText,%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.getMode(),%0A%20%20%20%20%20%20%20%20%20%20%20%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20styles.youTubePreviewToggleText,%0A%20%20%20%20%20%20%20%20%20%20%20%20'yt-preview-toggle'%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20previewToggle.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20()%20=%3E%20sendMessage('setYoutubePreviewsEnabled',%20false)%0A%20%20%20%20%20%20%20%20);%0A%0A%20%20%20%20%20%20%20%20/**%20Preview%20Info%20Text%20*/%0A%20%20%20%20%20%20%20%20const%20previewText%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20previewText.style.cssText%20=%20styles.contentText%20+%20styles.toggleButtonText%20+%20styles.youTubePreviewInfoText;%0A%20%20%20%20%20%20%20%20//%20Since%20this%20string%20contains%20an%20anchor%20element,%20setting%20innerText%20won't%0A%20%20%20%20%20%20%20%20//%20work.%0A%20%20%20%20%20%20%20%20//%20Warning:%20This%20is%20not%20ideal!%20The%20translated%20(and%20original)%20strings%20must%20be%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20checked%20very%20carefully!%20Any%20HTML%20they%20contain%20will%20be%20inserted.%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20Ideally,%20the%20translation%20system%20would%20allow%20only%20certain%20element%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20types%20to%20be%20included,%20and%20would%20avoid%20the%20URLs%20for%20links%20being%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20included%20in%20the%20translations.%0A%20%20%20%20%20%20%20%20previewText.insertAdjacentHTML(%0A%20%20%20%20%20%20%20%20%20%20%20%20'beforeend',%20widget.replaceSettings.placeholder.previewInfoText%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20const%20previewTextLink%20=%20previewText.querySelector('a');%0A%20%20%20%20%20%20%20%20if%20(previewTextLink)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20newPreviewTextLink%20=%20getLearnMoreLink(widget.getMode());%0A%20%20%20%20%20%20%20%20%20%20%20%20newPreviewTextLink.innerText%20=%20previewTextLink.innerText;%0A%20%20%20%20%20%20%20%20%20%20%20%20previewTextLink.replaceWith(newPreviewTextLink);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20previewToggleRow.appendChild(previewToggle);%0A%20%20%20%20%20%20%20%20previewToggleRow.appendChild(previewText);%0A%20%20%20%20%20%20%20%20innerDiv.appendChild(previewToggleRow);%0A%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.appendChild(innerDiv);%0A%0A%20%20%20%20%20%20%20%20//%20We%20use%20.then()%20instead%20of%20await%20here%20to%20show%20the%20placeholder%20right%20away%0A%20%20%20%20%20%20%20%20//%20while%20the%20YouTube%20endpoint%20takes%20it%20time%20to%20respond.%0A%20%20%20%20%20%20%20%20const%20videoURL%20=%20originalElement.src%20%7C%7C%20originalElement.getAttribute('data-src');%0A%20%20%20%20%20%20%20%20getYouTubeVideoDetails(videoURL);%0A%20%20%20%20%20%20%20%20window.addEventListener('ddg-ctp-youTubeVideoDetails',%0A%20%20%20%20%20%20%20%20%20%20%20%20(/**%20@type%20%7BCustomEvent%7D%20*/%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%20videoURL:%20videoURLResp,%20status,%20title,%20previewImage%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(videoURLResp%20!==%20videoURL)%20%7B%20return%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(status%20===%20'success')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20titleElement.innerText%20=%20title;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20titleElement.title%20=%20title;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(previewImage)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewImageElement.setAttribute('src',%20previewImage);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget.autoplay%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20);%0A%0A%20%20%20%20%20%20%20%20/**%20Share%20Feedback%20Link%20*/%0A%20%20%20%20%20%20%20%20const%20feedbackRow%20=%20makeShareFeedbackRow();%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(feedbackRow);%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20youTubePreview,%20shadowRoot%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Convention%20is%20that%20each%20function%20should%20be%20named%20the%20same%20as%20the%20sendMessage%0A%20%20%20%20//%20method%20we%20are%20calling%20into%20eg.%20calling%20%60sendMessage('getClickToLoadState')%60%0A%20%20%20%20//%20will%20result%20in%20a%20response%20routed%20to%20%60updateHandlers.getClickToLoadState()%60.%0A%20%20%20%20const%20messageResponseHandlers%20=%20%7B%0A%20%20%20%20%20%20%20%20getClickToLoadState%20(response)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20devMode%20=%20response.devMode;%0A%20%20%20%20%20%20%20%20%20%20%20%20isYoutubePreviewsEnabled%20=%20response.youtubePreviewsEnabled;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Mark%20the%20feature%20as%20ready,%20to%20allow%20placeholder%20replacements%20to%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20start.%0A%20%20%20%20%20%20%20%20%20%20%20%20readyToDisplayPlaceholdersResolver();%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20setYoutubePreviewsEnabled%20(response)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(response?.messageType%20&&%20typeof%20response?.value%20===%20'boolean')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20response.messageType,%20%7B%20detail:%20response.value%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20getYouTubeVideoDetails%20(response)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(response?.status%20&&%20typeof%20response.videoURL%20===%20'string')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'ddg-ctp-youTubeVideoDetails',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20detail:%20response%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20unblockClickToLoadContent%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent('ddg-ctp-unblockClickToLoadContent-complete')%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20const%20knownMessageResponseType%20=%20Object.prototype.hasOwnProperty.bind(messageResponseHandlers);%0A%0A%20%20%20%20class%20ClickToLoad%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20async%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20websiteOwner%20=%20args?.site?.parentEntity;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20settings%20=%20args?.featureSettings?.clickToLoad%20%7C%7C%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20locale%20=%20args?.locale%20%7C%7C%20'en';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20localizedConfig%20=%20getConfig(locale);%0A%20%20%20%20%20%20%20%20%20%20%20%20config%20=%20localizedConfig.config;%0A%20%20%20%20%20%20%20%20%20%20%20%20sharedStrings%20=%20localizedConfig.sharedStrings;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20entity%20of%20Object.keys(config))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Strip%20config%20entities%20that%20are%20first-party,%20or%20aren't%20enabled%20in%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20extension's%20clickToLoad%20settings.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20((websiteOwner%20&&%20entity%20===%20websiteOwner)%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20!settings%5Bentity%5D%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20settings%5Bentity%5D.state%20!==%20'enabled')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20config%5Bentity%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Populate%20the%20entities%20and%20entityData%20data%20structures.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20Remove%20them%20and%20this%20logic,%20they%20seem%20unnecessary.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entities.push(entity);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20shouldShowLoginModal%20=%20!!config%5Bentity%5D.informationalModal;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20currentEntityData%20=%20%7B%20shouldShowLoginModal%20%7D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldShowLoginModal)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20informationalModal%20%7D%20=%20config%5Bentity%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalIcon%20=%20informationalModal.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalTitle%20=%20informationalModal.messageTitle;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalText%20=%20informationalModal.messageBody;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalAcceptText%20=%20informationalModal.confirmButtonText;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalRejectText%20=%20informationalModal.rejectButtonText;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entityData%5Bentity%5D%20=%20currentEntityData;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Listen%20for%20events%20from%20%22surrogate%22%20scripts.%0A%20%20%20%20%20%20%20%20%20%20%20%20addEventListener('ddg-ctp',%20(/**%20@type%20%7BCustomEvent%7D%20*/%20event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!('detail'%20in%20event))%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20entity%20=%20event.detail?.entity;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!entities.includes(entity))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Unknown%20entity,%20reject%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(event.detail?.appID)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20appID%20=%20JSON.stringify(event.detail.appID).replace(/%22/g,%20'');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Handle%20login%20call%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(event.detail?.action%20===%20'login')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(entityData%5Bentity%5D.shouldShowLoginModal)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20makeModal(entity,%20runLogin,%20entity);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20runLogin(entity);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Request%20the%20current%20state%20of%20Click%20to%20Load%20from%20the%20platform.%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Note:%20When%20the%20response%20is%20received,%20the%20response%20handler%20resolves%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20the%20readyToDisplayPlaceholders%20Promise.%0A%20%20%20%20%20%20%20%20%20%20%20%20sendMessage('getClickToLoadState');%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20readyToDisplayPlaceholders;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Then%20wait%20for%20the%20page%20to%20finish%20loading,%20and%20resolve%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20afterPageLoad%20Promise.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(document.readyState%20===%20'complete')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20afterPageLoadResolver();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('load',%20afterPageLoadResolver,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20afterPageLoad;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Then%20wait%20for%20any%20in-progress%20element%20replacements,%20before%20letting%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20the%20surrogate%20scripts%20know%20to%20start.%0A%20%20%20%20%20%20%20%20%20%20%20%20window.setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready'));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%200);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20update%20(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20Once%20all%20Click%20to%20Load%20messages%20include%20the%20feature%20property,%20drop%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20messages%20that%20don't%20include%20the%20feature%20property%20too.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(message?.feature%20&&%20message?.feature%20!==%20'clickToLoad')%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20messageType%20=%20message?.messageType;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!messageType)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Message%20responses.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(messageType%20===%20'response')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20messageResponseType%20=%20message?.responseMessageType;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(messageResponseType%20&&%20knownMessageResponseType(messageResponseType))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20messageResponseHandlers%5BmessageResponseType%5D(message.response)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Other%20known%20update%20messages.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(messageType%20===%20'displayClickToLoadPlaceholders')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20Pass%20%60message.options.ruleAction%60%20through,%20that%20way%20only%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20content%20corresponding%20to%20the%20entity%20for%20that%20ruleAction%20need%20to%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20be%20replaced%20with%20a%20placeholder.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20replaceClickToLoadElements()%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20var%20platformFeatures%20=%20%7B%0A%20%20%20%20%20%20%20%20ddg_feature_runtimeChecks:%20RuntimeChecks,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingAudio:%20FingerprintingAudio,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingBattery:%20FingerprintingBattery,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingCanvas:%20FingerprintingCanvas,%0A%20%20%20%20%20%20%20%20ddg_feature_cookie:%20CookieFeature,%0A%20%20%20%20%20%20%20%20ddg_feature_googleRejected:%20GoogleRejected,%0A%20%20%20%20%20%20%20%20ddg_feature_gpc:%20GlobalPrivacyControl,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingHardware:%20FingerprintingHardware,%0A%20%20%20%20%20%20%20%20ddg_feature_referrer:%20Referrer,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingScreenSize:%20FingerprintingScreenSize,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingTemporaryStorage:%20FingerprintingTemporaryStorage,%0A%20%20%20%20%20%20%20%20ddg_feature_navigatorInterface:%20NavigatorInterface,%0A%20%20%20%20%20%20%20%20ddg_feature_elementHiding:%20ElementHiding,%0A%20%20%20%20%20%20%20%20ddg_feature_exceptionHandler:%20ExceptionHandler,%0A%20%20%20%20%20%20%20%20ddg_feature_clickToLoad:%20ClickToLoad%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/*%20global%20false%20*/%0A%0A%20%20%20%20function%20shouldRun%20()%20%7B%0A%20%20%20%20%20%20%20%20//%20don't%20inject%20into%20non-HTML%20documents%20(such%20as%20XML%20documents)%0A%20%20%20%20%20%20%20%20//%20but%20do%20inject%20into%20XHTML%20documents%0A%20%20%20%20%20%20%20%20if%20(document%20instanceof%20Document%20===%20false%20&&%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20document%20instanceof%20XMLDocument%20===%20false%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20document.createElement('div')%20instanceof%20HTMLDivElement%20===%20false%0A%20%20%20%20%20%20%20%20))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20initArgs%20=%20null;%0A%20%20%20%20const%20updates%20=%20%5B%5D;%0A%20%20%20%20const%20features%20=%20%5B%5D;%0A%20%20%20%20const%20alwaysInitFeatures%20=%20new%20Set(%5B'cookie'%5D);%0A%20%20%20%20const%20performanceMonitor%20=%20new%20PerformanceMonitor();%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20%7Bobject%7D%20LoadArgs%0A%20%20%20%20%20*%20@property%20%7Bobject%7D%20platform%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20platform.name%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20%5Bplatform.version%5D%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20%5BdocumentOriginIsTracker%5D%0A%20%20%20%20%20*%20@property%20%7Bobject%7D%20%5BbundledConfig%5D%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20%5BinjectName%5D%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BLoadArgs%7D%20args%0A%20%20%20%20%20*/%0A%20%20%20%20function%20load%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20mark%20=%20performanceMonitor.mark('load');%0A%20%20%20%20%20%20%20%20if%20(!shouldRun())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20featureNames%20=%20platformSupport%5B%22chrome%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20;%0A%0A%20%20%20%20%20%20%20%20for%20(const%20featureName%20of%20featureNames)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20ContentFeature%20=%20platformFeatures%5B'ddg_feature_'%20+%20featureName%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureInstance%20=%20new%20ContentFeature(featureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20featureInstance.callLoad(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20features.push(%7B%20featureName,%20featureInstance%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%7D%0A%0A%20%20%20%20async%20function%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20mark%20=%20performanceMonitor.mark('init');%0A%20%20%20%20%20%20%20%20initArgs%20=%20args;%0A%20%20%20%20%20%20%20%20if%20(!shouldRun())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20registerMessageSecret(args.messageSecret);%0A%20%20%20%20%20%20%20%20initStringExemptionLists(args);%0A%20%20%20%20%20%20%20%20const%20resolvedFeatures%20=%20await%20Promise.all(features);%0A%20%20%20%20%20%20%20%20resolvedFeatures.forEach((%7B%20featureInstance,%20featureName%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!isFeatureBroken(args,%20featureName)%20%7C%7C%20alwaysInitExtensionFeatures(args,%20featureName))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20featureInstance.callInit(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20//%20Fire%20off%20updates%20that%20came%20in%20faster%20than%20the%20init%0A%20%20%20%20%20%20%20%20while%20(updates.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20update%20=%20updates.pop();%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20updateFeaturesInner(update);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%20%20%20%20if%20(args.debug)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20performanceMonitor.measureAll();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20update%20(args)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!shouldRun())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(initArgs%20===%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20updates.push(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20updateFeaturesInner(args);%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20alwaysInitExtensionFeatures%20(args,%20featureName)%20%7B%0A%20%20%20%20%20%20%20%20return%20args.platform.name%20===%20'extension'%20&&%20alwaysInitFeatures.has(featureName)%0A%20%20%20%20%7D%0A%0A%20%20%20%20async%20function%20updateFeaturesInner%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20resolvedFeatures%20=%20await%20Promise.all(features);%0A%20%20%20%20%20%20%20%20resolvedFeatures.forEach((%7B%20featureInstance,%20featureName%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!isFeatureBroken(initArgs,%20featureName)%20&&%20featureInstance.update)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20featureInstance.update(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20exports.init%20=%20init;%0A%20%20%20%20exports.load%20=%20load;%0A%20%20%20%20exports.update%20=%20update;%0A%0A%20%20%20%20return%20exports;%0A%0A%7D)(%7B%7D);%0A")} + ${decodeURI("/*!%20%C2%A9%20DuckDuckGo%20ContentScopeScripts%20protections%20https://github.com/duckduckgo/content-scope-scripts/%20*/%0Avar%20contentScopeFeatures%20=%20(function%20(exports)%20%7B%0A%20%20%20%20'use%20strict';%0A%0A%20%20%20%20/*%20global%20cloneInto,%20exportFunction,%20false%20*/%0A%0A%20%20%20%20//%20Only%20use%20globalThis%20for%20testing%20this%20breaks%20window.wrappedJSObject%20code%20in%20Firefox%0A%20%20%20%20//%20eslint-disable-next-line%20no-global-assign%0A%20%20%20%20let%20globalObj%20=%20typeof%20window%20===%20'undefined'%20?%20globalThis%20:%20window;%0A%20%20%20%20let%20Error$1%20=%20globalObj.Error;%0A%20%20%20%20let%20messageSecret;%0A%20%20%20%20const%20CapturedSet%20=%20globalObj.Set;%0A%20%20%20%20//%20Capture%20prototype%20to%20prevent%20overloading%0A%20%20%20%20const%20createSet%20=%20()%20=%3E%20new%20CapturedSet();%0A%0A%20%20%20%20//%20save%20a%20reference%20to%20original%20CustomEvent%20amd%20dispatchEvent%20so%20they%20can't%20be%20overriden%20to%20forge%20messages%0A%20%20%20%20const%20OriginalCustomEvent%20=%20typeof%20CustomEvent%20===%20'undefined'%20?%20null%20:%20CustomEvent;%0A%20%20%20%20const%20originalWindowDispatchEvent%20=%20typeof%20window%20===%20'undefined'%20?%20null%20:%20window.dispatchEvent.bind(window);%0A%20%20%20%20function%20registerMessageSecret%20(secret)%20%7B%0A%20%20%20%20%20%20%20%20messageSecret%20=%20secret;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@returns%20%7BHTMLElement%7D%20the%20element%20to%20inject%20the%20script%20into%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getInjectionElement%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20document.head%20%7C%7C%20document.documentElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20script%20element%20with%20the%20given%20code%20to%20avoid%20Firefox%20CSP%20restrictions.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20css%0A%20%20%20%20%20*%20@returns%20%7BHTMLLinkElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createStyleElement%20(css)%20%7B%0A%20%20%20%20%20%20%20%20const%20style%20=%20document.createElement('link');%0A%20%20%20%20%20%20%20%20style.href%20=%20'data:text/css,'%20+%20encodeURIComponent(css);%0A%20%20%20%20%20%20%20%20style.setAttribute('rel',%20'stylesheet');%0A%20%20%20%20%20%20%20%20style.setAttribute('type',%20'text/css');%0A%20%20%20%20%20%20%20%20return%20style%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Injects%20a%20script%20into%20the%20page,%20avoiding%20CSP%20restrictions%20if%20possible.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20injectGlobalStyles%20(css)%20%7B%0A%20%20%20%20%20%20%20%20const%20style%20=%20createStyleElement(css);%0A%20%20%20%20%20%20%20%20getInjectionElement().appendChild(style);%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20linear%20feedback%20shift%20register%20to%20find%20a%20random%20approximation%0A%20%20%20%20function%20nextRandom%20(v)%20%7B%0A%20%20%20%20%20%20%20%20return%20Math.abs((v%20%3E%3E%201)%20%7C%20(((v%20%3C%3C%2062)%20%5E%20(v%20%3C%3C%2061))%20&%20(~(~0%20%3C%3C%2063)%20%3C%3C%2062)))%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20exemptionLists%20=%20%7B%7D;%0A%20%20%20%20function%20shouldExemptUrl%20(type,%20url)%20%7B%0A%20%20%20%20%20%20%20%20for%20(const%20regex%20of%20exemptionLists%5Btype%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(regex.test(url))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20debug%20=%20false;%0A%0A%20%20%20%20function%20initStringExemptionLists%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20%7B%20stringExemptionLists%20%7D%20=%20args;%0A%20%20%20%20%20%20%20%20debug%20=%20args.debug;%0A%20%20%20%20%20%20%20%20for%20(const%20type%20in%20stringExemptionLists)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20exemptionLists%5Btype%5D%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20stringExemption%20of%20stringExemptionLists%5Btype%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exemptionLists%5Btype%5D.push(new%20RegExp(stringExemption));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Best%20guess%20effort%20if%20the%20document%20is%20being%20framed%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%20if%20we%20infer%20the%20document%20is%20framed%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isBeingFramed%20()%20%7B%0A%20%20%20%20%20%20%20%20if%20('ancestorOrigins'%20in%20globalThis.location)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20globalThis.location.ancestorOrigins.length%20%3E%200%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20globalThis.top%20!==%20globalThis.window%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Best%20guess%20effort%20if%20the%20document%20is%20third%20party%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%20if%20we%20infer%20the%20document%20is%20third%20party%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isThirdPartyFrame%20()%20%7B%0A%20%20%20%20%20%20%20%20if%20(!isBeingFramed())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20getTabHostname()%20is%20string%7Cnull%20here%0A%20%20%20%20%20%20%20%20return%20!matchHostname(globalThis.location.hostname,%20getTabHostname())%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Best%20guess%20effort%20of%20the%20tabs%20hostname;%20where%20possible%20always%20prefer%20the%20args.site.domain%0A%20%20%20%20%20*%20@returns%20%7Bstring%7Cnull%7D%20inferred%20tab%20hostname%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getTabHostname%20()%20%7B%0A%20%20%20%20%20%20%20%20let%20framingOrigin%20=%20null;%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20globalThis.top%20is%20possibly%20'null'%20here%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20globalThis.top.location.href;%0A%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20globalThis.document.referrer;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Not%20supported%20in%20Firefox%0A%20%20%20%20%20%20%20%20if%20('ancestorOrigins'%20in%20globalThis.location%20&&%20globalThis.location.ancestorOrigins.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20ancestorOrigins%20is%20reverse%20order,%20with%20the%20last%20item%20being%20the%20top%20frame%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20globalThis.location.ancestorOrigins.item(globalThis.location.ancestorOrigins.length%20-%201);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20framingOrigin%20is%20possibly%20'null'%20here%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20new%20URL(framingOrigin).hostname;%0A%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20framingOrigin%20=%20null;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20framingOrigin%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Returns%20true%20if%20hostname%20is%20a%20subset%20of%20exceptionDomain%20or%20an%20exact%20match.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20hostname%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20exceptionDomain%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20matchHostname%20(hostname,%20exceptionDomain)%20%7B%0A%20%20%20%20%20%20%20%20return%20hostname%20===%20exceptionDomain%20%7C%7C%20hostname.endsWith(%60.$%7BexceptionDomain%7D%60)%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20lineTest%20=%20/(%5C()?(https?:%5B%5E)%5D+):%5B0-9%5D+:%5B0-9%5D+(%5C))?/;%0A%20%20%20%20function%20getStackTraceUrls%20(stack)%20%7B%0A%20%20%20%20%20%20%20%20const%20urls%20=%20createSet();%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20errorLines%20=%20stack.split('%5Cn');%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Should%20cater%20for%20Chrome%20and%20Firefox%20stacks,%20we%20only%20care%20about%20https?%20resources.%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20line%20of%20errorLines)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20res%20=%20line.match(lineTest);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(res)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urls.add(new%20URL(res%5B2%5D,%20location.href));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Fall%20through%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20urls%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20getStackTraceOrigins%20(stack)%20%7B%0A%20%20%20%20%20%20%20%20const%20urls%20=%20getStackTraceUrls(stack);%0A%20%20%20%20%20%20%20%20const%20origins%20=%20createSet();%0A%20%20%20%20%20%20%20%20for%20(const%20url%20of%20urls)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20origins.add(url.hostname);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20origins%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Checks%20the%20stack%20trace%20if%20there%20are%20known%20libraries%20that%20are%20broken.%0A%20%20%20%20function%20shouldExemptMethod%20(type)%20%7B%0A%20%20%20%20%20%20%20%20//%20Short%20circuit%20stack%20tracing%20if%20we%20don't%20have%20checks%0A%20%20%20%20%20%20%20%20if%20(!(type%20in%20exemptionLists)%20%7C%7C%20exemptionLists%5Btype%5D.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20const%20errorFiles%20=%20getStackTraceUrls(stack);%0A%20%20%20%20%20%20%20%20for%20(const%20path%20of%20errorFiles)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldExemptUrl(type,%20path.href))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Iterate%20through%20the%20key,%20passing%20an%20item%20index%20and%20a%20byte%20to%20be%20modified%0A%20%20%20%20function%20iterateDataKey%20(key,%20callback)%20%7B%0A%20%20%20%20%20%20%20%20let%20item%20=%20key.charCodeAt(0);%0A%20%20%20%20%20%20%20%20for%20(const%20i%20in%20key)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20byte%20=%20key.charCodeAt(i);%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(let%20j%20=%208;%20j%20%3E=%200;%20j--)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20res%20=%20callback(item,%20byte);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Exit%20early%20if%20callback%20returns%20null%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(res%20===%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20find%20next%20item%20to%20perturb%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20item%20=%20nextRandom(item);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Right%20shift%20as%20we%20use%20the%20least%20significant%20bit%20of%20it%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20byte%20=%20byte%20%3E%3E%201;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isFeatureBroken%20(args,%20feature)%20%7B%0A%20%20%20%20%20%20%20%20return%20isWindowsSpecificFeature(feature)%0A%20%20%20%20%20%20%20%20%20%20%20%20?%20!args.site.enabledFeatures.includes(feature)%0A%20%20%20%20%20%20%20%20%20%20%20%20:%20args.site.isBroken%20%7C%7C%20args.site.allowlisted%20%7C%7C%20!args.site.enabledFeatures.includes(feature)%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20For%20each%20property%20defined%20on%20the%20object,%20update%20it%20with%20the%20target%20value.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20overrideProperty%20(name,%20prop)%20%7B%0A%20%20%20%20%20%20%20%20//%20Don't%20update%20if%20existing%20value%20is%20undefined%20or%20null%0A%20%20%20%20%20%20%20%20if%20(!(prop.origValue%20===%20undefined))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20When%20re-defining%20properties,%20we%20bind%20the%20overwritten%20functions%20to%20null.%20This%20prevents%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20sites%20from%20using%20toString%20to%20see%20if%20the%20function%20has%20been%20overwritten%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20without%20this%20bind%20call,%20a%20site%20could%20run%20something%20like%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20%60Object.getOwnPropertyDescriptor(Screen.prototype,%20%22availTop%22).get.toString()%60%20and%20see%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20the%20contents%20of%20the%20function.%20Appending%20.bind(null)%20to%20the%20function%20definition%20will%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20have%20the%20same%20toString%20call%20return%20the%20default%20%5Bnative%20code%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(prop.object,%20name,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20no-extra-bind%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20(()%20=%3E%20prop.targetValue).bind(null)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20prop.origValue%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20defineProperty%20(object,%20propertyName,%20descriptor)%20%7B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(object,%20propertyName,%20descriptor);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20camelcase%20(dashCaseText)%20%7B%0A%20%20%20%20%20%20%20%20return%20dashCaseText.replace(/-(.)/g,%20(match,%20letter)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20letter.toUpperCase()%0A%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20We%20use%20this%20method%20to%20detect%20M1%20macs%20and%20set%20appropriate%20API%20values%20to%20prevent%20sites%20from%20detecting%20fingerprinting%20protections%0A%20%20%20%20function%20isAppleSilicon%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20canvas%20=%20document.createElement('canvas');%0A%20%20%20%20%20%20%20%20const%20gl%20=%20canvas.getContext('webgl');%0A%0A%20%20%20%20%20%20%20%20//%20Best%20guess%20if%20the%20device%20is%20an%20Apple%20Silicon%0A%20%20%20%20%20%20%20%20//%20https://stackoverflow.com/a/65412357%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'null'%0A%20%20%20%20%20%20%20%20return%20gl.getSupportedExtensions().indexOf('WEBGL_compressed_texture_etc')%20!==%20-1%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Take%20configSeting%20which%20should%20be%20an%20array%20of%20possible%20values.%0A%20%20%20%20%20*%20If%20a%20value%20contains%20a%20criteria%20that%20is%20a%20match%20for%20this%20environment%20then%20return%20that%20value.%0A%20%20%20%20%20*%20Otherwise%20return%20the%20first%20value%20that%20doesn't%20have%20a%20criteria.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7B*%5B%5D%7D%20configSetting%20-%20Config%20setting%20which%20should%20contain%20a%20list%20of%20possible%20values%0A%20%20%20%20%20*%20@returns%20%7B*%7Cundefined%7D%20-%20The%20value%20from%20the%20list%20that%20best%20matches%20the%20criteria%20in%20the%20config%0A%20%20%20%20%20*/%0A%20%20%20%20function%20processAttrByCriteria%20(configSetting)%20%7B%0A%20%20%20%20%20%20%20%20let%20bestOption;%0A%20%20%20%20%20%20%20%20for%20(const%20item%20of%20configSetting)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(item.criteria)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(item.criteria.arch%20===%20'AppleSilicon'%20&&%20isAppleSilicon())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bestOption%20=%20item;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bestOption%20=%20item;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20bestOption%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20functionMap%20=%20%7B%0A%20%20%20%20%20%20%20%20/**%20Useful%20for%20debugging%20APIs%20in%20the%20wild,%20shouldn't%20be%20used%20*/%0A%20%20%20%20%20%20%20%20debug:%20(...args)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20console.log('debugger',%20...args);%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20no-debugger%0A%20%20%20%20%20%20%20%20%20%20%20%20debugger%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20noop:%20()%20=%3E%20%7B%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Handles%20the%20processing%20of%20a%20config%20setting.%0A%20%20%20%20%20*%20@param%20%7B*%7D%20configSetting%0A%20%20%20%20%20*%20@param%20%7B*%7D%20%5BdefaultValue%5D%0A%20%20%20%20%20*%20@returns%0A%20%20%20%20%20*/%0A%20%20%20%20function%20processAttr%20(configSetting,%20defaultValue)%20%7B%0A%20%20%20%20%20%20%20%20if%20(configSetting%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20configSettingType%20=%20typeof%20configSetting;%0A%20%20%20%20%20%20%20%20switch%20(configSettingType)%20%7B%0A%20%20%20%20%20%20%20%20case%20'object':%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(Array.isArray(configSetting))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configSetting%20=%20processAttrByCriteria(configSetting);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!configSetting.type)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting.type%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting.functionName%20&&%20functionMap%5BconfigSetting.functionName%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20functionMap%5BconfigSetting.functionName%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(configSetting.type%20===%20'undefined')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20undefined%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20configSetting.value%0A%20%20%20%20%20%20%20%20default:%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultValue%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20getStack%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20new%20Error$1().stack%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@template%20%7Bobject%7D%20P%0A%20%20%20%20%20*%20@typedef%20%7Bobject%7D%20ProxyObject%3CP%3E%0A%20%20%20%20%20*%20@property%20%7B(target?:%20object,%20thisArg?:%20P,%20args?:%20object)%20=%3E%20void%7D%20apply%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@template%20%5BP=object%5D%0A%20%20%20%20%20*/%0A%20%20%20%20class%20DDGProxy%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureName%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BP%7D%20objectScope%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20property%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BProxyObject%3CP%3E%7D%20proxyObject%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20constructor%20(featureName,%20objectScope,%20property,%20proxyObject)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.objectScope%20=%20objectScope;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.property%20=%20property;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.featureName%20=%20featureName;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.camelFeatureName%20=%20camelcase(this.featureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20outputHandler%20=%20(...args)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20isExempt%20=%20shouldExemptMethod(this.camelFeatureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(debug)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20postDebugMessage(this.camelFeatureName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isProxy:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20action:%20isExempt%20?%20'ignore'%20:%20'restrict',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kind:%20this.property,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack:%20getStack(),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args:%20JSON.stringify(args%5B2%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20normal%20return%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(isExempt)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20proxyObject.apply(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20getMethod%20=%20(target,%20prop,%20receiver)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(prop%20===%20'toString')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20method%20=%20Reflect.get(target,%20prop,%20receiver).bind(target);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(method,%20'toString',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20String.toString.bind(String.toString),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20method%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.get(target,%20prop,%20receiver)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this._native%20=%20objectScope%5Bproperty%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20handler%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20handler.apply%20=%20outputHandler;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20handler.get%20=%20getMethod;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.internal%20=%20new%20globalObj.Proxy(objectScope%5Bproperty%5D,%20handler);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Actually%20apply%20the%20proxy%20to%20the%20native%20property%0A%20%20%20%20%20%20%20%20overload%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.objectScope%5Bthis.property%5D%20=%20this.internal;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20postDebugMessage%20(feature,%20message)%20%7B%0A%20%20%20%20%20%20%20%20if%20(message.stack)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20%5B...getStackTraceOrigins(message.stack)%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20message.scriptOrigins%20=%20scriptOrigins;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20globalObj.postMessage(%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20action:%20feature,%0A%20%20%20%20%20%20%20%20%20%20%20%20message%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20DDGReflect;%0A%20%20%20%20let%20DDGPromise;%0A%0A%20%20%20%20//%20Exports%20for%20usage%20where%20we%20have%20to%20cross%20the%20xray%20boundary:%20https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20DDGPromise%20=%20globalObj.Promise;%0A%20%20%20%20%20%20%20%20DDGReflect%20=%20globalObj.Reflect;%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isUnprotectedDomain%20(topLevelHostname,%20featureList)%20%7B%0A%20%20%20%20%20%20%20%20let%20unprotectedDomain%20=%20false;%0A%20%20%20%20%20%20%20%20const%20domainParts%20=%20topLevelHostname.split('.');%0A%0A%20%20%20%20%20%20%20%20//%20walk%20up%20the%20domain%20to%20see%20if%20it's%20unprotected%0A%20%20%20%20%20%20%20%20while%20(domainParts.length%20%3E%201%20&&%20!unprotectedDomain)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20partialDomain%20=%20domainParts.join('.');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20unprotectedDomain%20=%20featureList.filter(domain%20=%3E%20domain.domain%20===%20partialDomain).length%20%3E%200;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20domainParts.shift();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20unprotectedDomain%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20parseVersionString%20(versionString)%20%7B%0A%20%20%20%20%20%20%20%20const%20%5Bmajor%20=%200,%20minor%20=%200,%20patch%20=%200%5D%20=%20versionString.split('.').map(Number);%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20major,%0A%20%20%20%20%20%20%20%20%20%20%20%20minor,%0A%20%20%20%20%20%20%20%20%20%20%20%20patch%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20minVersionString%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20applicationVersionString%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20satisfiesMinVersion%20(minVersionString,%20applicationVersionString)%20%7B%0A%20%20%20%20%20%20%20%20const%20%7B%20major:%20minMajor,%20minor:%20minMinor,%20patch:%20minPatch%20%7D%20=%20parseVersionString(minVersionString);%0A%20%20%20%20%20%20%20%20const%20%7B%20major,%20minor,%20patch%20%7D%20=%20parseVersionString(applicationVersionString);%0A%0A%20%20%20%20%20%20%20%20return%20(major%20%3E%20minMajor%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(major%20%3E=%20minMajor%20&&%20minor%20%3E%20minMinor)%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(major%20%3E=%20minMajor%20&&%20minor%20%3E=%20minMinor%20&&%20patch%20%3E=%20minPatch))%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7Bstring%20%7C%20number%20%7C%20undefined%7D%20minSupportedVersion%0A%20%20%20%20%20*%20@param%20%7Bstring%20%7C%20number%20%7C%20undefined%7D%20currentVersion%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isSupportedVersion%20(minSupportedVersion,%20currentVersion)%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20currentVersion%20===%20'string'%20&&%20typeof%20minSupportedVersion%20===%20'string')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(satisfiesMinVersion(minSupportedVersion,%20currentVersion))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(typeof%20currentVersion%20===%20'number'%20&&%20typeof%20minSupportedVersion%20===%20'number')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(minSupportedVersion%20%3C=%20currentVersion)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Retutns%20a%20list%20of%20enabled%20features%0A%20%20%20%20%20*%20@param%20%7BRemoteConfig%7D%20data%0A%20%20%20%20%20*%20@param%20%7Bstring%20%7C%20null%7D%20topLevelHostname%0A%20%20%20%20%20*%20@param%20%7BPlatform%5B'version'%5D%7D%20platformVersion%0A%20%20%20%20%20*%20@param%20%7Bstring%5B%5D%7D%20platformSpecificFeatures%0A%20%20%20%20%20*%20@returns%20%7Bstring%5B%5D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20computeEnabledFeatures%20(data,%20topLevelHostname,%20platformVersion,%20platformSpecificFeatures%20=%20%5B%5D)%20%7B%0A%20%20%20%20%20%20%20%20const%20remoteFeatureNames%20=%20Object.keys(data.features);%0A%20%20%20%20%20%20%20%20const%20platformSpecificFeaturesNotInRemoteConfig%20=%20platformSpecificFeatures.filter((featureName)%20=%3E%20!remoteFeatureNames.includes(featureName));%0A%20%20%20%20%20%20%20%20const%20enabledFeatures%20=%20remoteFeatureNames.filter((featureName)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20feature%20=%20data.features%5BfeatureName%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Check%20that%20the%20platform%20supports%20minSupportedVersion%20checks%20and%20that%20the%20feature%20has%20a%20minSupportedVersion%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(feature.minSupportedVersion%20&&%20platformVersion)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!isSupportedVersion(feature.minSupportedVersion,%20platformVersion))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20feature.state%20===%20'enabled'%20&&%20!isUnprotectedDomain(topLevelHostname,%20feature.exceptions)%0A%20%20%20%20%20%20%20%20%7D).concat(platformSpecificFeaturesNotInRemoteConfig);%20//%20only%20disable%20platform%20specific%20features%20if%20it's%20explicitly%20disabled%20in%20remote%20config%0A%20%20%20%20%20%20%20%20return%20enabledFeatures%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Returns%20the%20relevant%20feature%20settings%20for%20the%20enabled%20features%0A%20%20%20%20%20*%20@param%20%7BRemoteConfig%7D%20data%0A%20%20%20%20%20*%20@param%20%7Bstring%5B%5D%7D%20enabledFeatures%0A%20%20%20%20%20*%20@returns%20%7BRecord%3Cstring,%20unknown%3E%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20parseFeatureSettings%20(data,%20enabledFeatures)%20%7B%0A%20%20%20%20%20%20%20%20/**%20@type%20%7BRecord%3Cstring,%20unknown%3E%7D%20*/%0A%20%20%20%20%20%20%20%20const%20featureSettings%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20const%20remoteFeatureNames%20=%20Object.keys(data.features);%0A%20%20%20%20%20%20%20%20remoteFeatureNames.forEach((featureName)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!enabledFeatures.includes(featureName))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20featureSettings%5BfeatureName%5D%20=%20data.features%5BfeatureName%5D.settings;%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20return%20featureSettings%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20windowsSpecificFeatures%20=%20%5B'windowsPermissionUsage'%5D;%0A%0A%20%20%20%20function%20isWindowsSpecificFeature%20(featureName)%20%7B%0A%20%20%20%20%20%20%20%20return%20windowsSpecificFeatures.includes(featureName)%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20createCustomEvent%20(eventName,%20eventDetail)%20%7B%0A%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20possibly%20null%0A%20%20%20%20%20%20%20%20return%20new%20OriginalCustomEvent(eventName,%20eventDetail)%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20sendMessage%20(messageType,%20options)%20%7B%0A%20%20%20%20%20%20%20%20//%20FF%20&%20Chrome%0A%20%20%20%20%20%20%20%20return%20originalWindowDispatchEvent(createCustomEvent('sendMessageProxy'%20+%20messageSecret,%20%7B%20detail:%20%7B%20messageType,%20options%20%7D%20%7D))%0A%20%20%20%20%20%20%20%20//%20TBD%20other%20platforms%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20baseFeatures%20=%20/**%20@type%20%7Bconst%7D%20*/(%5B%0A%20%20%20%20%20%20%20%20'runtimeChecks',%0A%20%20%20%20%20%20%20%20'fingerprintingAudio',%0A%20%20%20%20%20%20%20%20'fingerprintingBattery',%0A%20%20%20%20%20%20%20%20'fingerprintingCanvas',%0A%20%20%20%20%20%20%20%20'cookie',%0A%20%20%20%20%20%20%20%20'googleRejected',%0A%20%20%20%20%20%20%20%20'gpc',%0A%20%20%20%20%20%20%20%20'fingerprintingHardware',%0A%20%20%20%20%20%20%20%20'referrer',%0A%20%20%20%20%20%20%20%20'fingerprintingScreenSize',%0A%20%20%20%20%20%20%20%20'fingerprintingTemporaryStorage',%0A%20%20%20%20%20%20%20%20'navigatorInterface',%0A%20%20%20%20%20%20%20%20'elementHiding',%0A%20%20%20%20%20%20%20%20'exceptionHandler'%0A%20%20%20%20%5D);%0A%0A%20%20%20%20const%20otherFeatures%20=%20/**%20@type%20%7Bconst%7D%20*/(%5B%0A%20%20%20%20%20%20%20%20'clickToLoad',%0A%20%20%20%20%20%20%20%20'windowsPermissionUsage',%0A%20%20%20%20%20%20%20%20'webCompat',%0A%20%20%20%20%20%20%20%20'duckPlayer'%0A%20%20%20%20%5D);%0A%0A%20%20%20%20/**%20@typedef%20%7BbaseFeatures%5Bnumber%5D%7CotherFeatures%5Bnumber%5D%7D%20FeatureName%20*/%0A%20%20%20%20/**%20@type%20%7BRecord%3Cstring,%20FeatureName%5B%5D%3E%7D%20*/%0A%20%20%20%20const%20platformSupport%20=%20%7B%0A%20%20%20%20%20%20%20%20apple:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'webCompat'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20android:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20windows:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'windowsPermissionUsage',%0A%20%20%20%20%20%20%20%20%20%20%20%20'duckPlayer'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20firefox:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'clickToLoad'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20chrome:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'clickToLoad'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20'chrome-mv3':%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20'clickToLoad'%0A%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20integration:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20...baseFeatures,%0A%20%20%20%20%20%20%20%20%20%20%20%20...otherFeatures%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Performance%20monitor,%20holds%20reference%20to%20PerformanceMark%20instances.%0A%20%20%20%20%20*/%0A%20%20%20%20class%20PerformanceMonitor%20%7B%0A%20%20%20%20%20%20%20%20constructor%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.marks%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Create%20performance%20marker%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20name%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPerformanceMark%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20mark%20(name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20mark%20=%20new%20PerformanceMark(name);%0A%20%20%20%20%20%20%20%20%20%20%20%20this.marks.push(mark);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20mark%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Measure%20all%20performance%20markers%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20measureAll%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.marks.forEach((mark)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mark.measure();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Tiny%20wrapper%20around%20performance.mark%20and%20performance.measure%0A%20%20%20%20%20*/%0A%20%20%20%20class%20PerformanceMark%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20name%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20constructor%20(name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.name%20=%20name;%0A%20%20%20%20%20%20%20%20%20%20%20%20performance.mark(this.name%20+%20'Start');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20end%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20performance.mark(this.name%20+%20'End');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20measure%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20performance.measure(this.name,%20this.name%20+%20'Start',%20this.name%20+%20'End');%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20_typeof$2(obj)%20%7B%20%22@babel/helpers%20-%20typeof%22;%20return%20_typeof$2%20=%20%22function%22%20==%20typeof%20Symbol%20&&%20%22symbol%22%20==%20typeof%20Symbol.iterator%20?%20function%20(obj)%20%7B%20return%20typeof%20obj;%20%7D%20:%20function%20(obj)%20%7B%20return%20obj%20&&%20%22function%22%20==%20typeof%20Symbol%20&&%20obj.constructor%20===%20Symbol%20&&%20obj%20!==%20Symbol.prototype%20?%20%22symbol%22%20:%20typeof%20obj;%20%7D,%20_typeof$2(obj);%20%7D%0A%20%20%20%20function%20isJSONArray(value)%20%7B%0A%20%20%20%20%20%20return%20Array.isArray(value);%0A%20%20%20%20%7D%0A%20%20%20%20function%20isJSONObject(value)%20%7B%0A%20%20%20%20%20%20return%20value%20!==%20null%20&&%20_typeof$2(value)%20===%20'object'%20&&%20value.constructor%20===%20Object%20//%20do%20not%20match%20on%20classes%20or%20Array%0A%20%20%20%20%20%20;%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20_typeof$1(obj)%20%7B%20%22@babel/helpers%20-%20typeof%22;%20return%20_typeof$1%20=%20%22function%22%20==%20typeof%20Symbol%20&&%20%22symbol%22%20==%20typeof%20Symbol.iterator%20?%20function%20(obj)%20%7B%20return%20typeof%20obj;%20%7D%20:%20function%20(obj)%20%7B%20return%20obj%20&&%20%22function%22%20==%20typeof%20Symbol%20&&%20obj.constructor%20===%20Symbol%20&&%20obj%20!==%20Symbol.prototype%20?%20%22symbol%22%20:%20typeof%20obj;%20%7D,%20_typeof$1(obj);%20%7D%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20deep%20equality%20of%20two%20JSON%20values,%20objects,%20or%20arrays%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20isEqual(a,%20b)%20%7B%0A%20%20%20%20%20%20//%20FIXME:%20this%20function%20will%20return%20false%20for%20two%20objects%20with%20the%20same%20keys%0A%20%20%20%20%20%20//%20%20but%20different%20order%20of%20keys%0A%20%20%20%20%20%20return%20JSON.stringify(a)%20===%20JSON.stringify(b);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Get%20all%20but%20the%20last%20items%20from%20an%20array%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20initial(array)%20%7B%0A%20%20%20%20%20%20return%20array.slice(0,%20array.length%20-%201);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Get%20the%20last%20item%20from%20an%20array%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20last(array)%20%7B%0A%20%20%20%20%20%20return%20array%5Barray.length%20-%201%5D;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20whether%20a%20value%20is%20an%20Object%20or%20an%20Array%20(and%20not%20a%20primitive%20JSON%20value)%0A%20%20%20%20%20*/%0A%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20function%20isObjectOrArray(value)%20%7B%0A%20%20%20%20%20%20return%20_typeof$1(value)%20===%20'object'%20&&%20value%20!==%20null;%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20_typeof(obj)%20%7B%20%22@babel/helpers%20-%20typeof%22;%20return%20_typeof%20=%20%22function%22%20==%20typeof%20Symbol%20&&%20%22symbol%22%20==%20typeof%20Symbol.iterator%20?%20function%20(obj)%20%7B%20return%20typeof%20obj;%20%7D%20:%20function%20(obj)%20%7B%20return%20obj%20&&%20%22function%22%20==%20typeof%20Symbol%20&&%20obj.constructor%20===%20Symbol%20&&%20obj%20!==%20Symbol.prototype%20?%20%22symbol%22%20:%20typeof%20obj;%20%7D,%20_typeof(obj);%20%7D%0A%20%20%20%20function%20ownKeys(object,%20enumerableOnly)%20%7B%20var%20keys%20=%20Object.keys(object);%20if%20(Object.getOwnPropertySymbols)%20%7B%20var%20symbols%20=%20Object.getOwnPropertySymbols(object);%20enumerableOnly%20&&%20(symbols%20=%20symbols.filter(function%20(sym)%20%7B%20return%20Object.getOwnPropertyDescriptor(object,%20sym).enumerable;%20%7D)),%20keys.push.apply(keys,%20symbols);%20%7D%20return%20keys;%20%7D%0A%20%20%20%20function%20_objectSpread(target)%20%7B%20for%20(var%20i%20=%201;%20i%20%3C%20arguments.length;%20i++)%20%7B%20var%20source%20=%20null%20!=%20arguments%5Bi%5D%20?%20arguments%5Bi%5D%20:%20%7B%7D;%20i%20%25%202%20?%20ownKeys(Object(source),%20!0).forEach(function%20(key)%20%7B%20_defineProperty(target,%20key,%20source%5Bkey%5D);%20%7D)%20:%20Object.getOwnPropertyDescriptors%20?%20Object.defineProperties(target,%20Object.getOwnPropertyDescriptors(source))%20:%20ownKeys(Object(source)).forEach(function%20(key)%20%7B%20Object.defineProperty(target,%20key,%20Object.getOwnPropertyDescriptor(source,%20key));%20%7D);%20%7D%20return%20target;%20%7D%0A%20%20%20%20function%20_defineProperty(obj,%20key,%20value)%20%7B%20key%20=%20_toPropertyKey(key);%20if%20(key%20in%20obj)%20%7B%20Object.defineProperty(obj,%20key,%20%7B%20value:%20value,%20enumerable:%20true,%20configurable:%20true,%20writable:%20true%20%7D);%20%7D%20else%20%7B%20obj%5Bkey%5D%20=%20value;%20%7D%20return%20obj;%20%7D%0A%20%20%20%20function%20_toPropertyKey(arg)%20%7B%20var%20key%20=%20_toPrimitive(arg,%20%22string%22);%20return%20_typeof(key)%20===%20%22symbol%22%20?%20key%20:%20String(key);%20%7D%0A%20%20%20%20function%20_toPrimitive(input,%20hint)%20%7B%20if%20(_typeof(input)%20!==%20%22object%22%20%7C%7C%20input%20===%20null)%20return%20input;%20var%20prim%20=%20input%5BSymbol.toPrimitive%5D;%20if%20(prim%20!==%20undefined)%20%7B%20var%20res%20=%20prim.call(input,%20hint%20%7C%7C%20%22default%22);%20if%20(_typeof(res)%20!==%20%22object%22)%20return%20res;%20throw%20new%20TypeError(%22@@toPrimitive%20must%20return%20a%20primitive%20value.%22);%20%7D%20return%20(hint%20===%20%22string%22%20?%20String%20:%20Number)(input);%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Shallow%20clone%20of%20an%20Object,%20Array,%20or%20value%0A%20%20%20%20%20*%20Symbols%20are%20cloned%20too.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shallowClone(value)%20%7B%0A%20%20%20%20%20%20if%20(isJSONArray(value))%20%7B%0A%20%20%20%20%20%20%20%20//%20copy%20array%20items%0A%20%20%20%20%20%20%20%20var%20copy%20=%20value.slice();%0A%0A%20%20%20%20%20%20%20%20//%20copy%20all%20symbols%0A%20%20%20%20%20%20%20%20Object.getOwnPropertySymbols(value).forEach(function%20(symbol)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20copy%5Bsymbol%5D%20=%20value%5Bsymbol%5D;%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20return%20copy;%0A%20%20%20%20%20%20%7D%20else%20if%20(isJSONObject(value))%20%7B%0A%20%20%20%20%20%20%20%20//%20copy%20object%20properties%0A%20%20%20%20%20%20%20%20var%20_copy%20=%20_objectSpread(%7B%7D,%20value);%0A%0A%20%20%20%20%20%20%20%20//%20copy%20all%20symbols%0A%20%20%20%20%20%20%20%20Object.getOwnPropertySymbols(value).forEach(function%20(symbol)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20_copy%5Bsymbol%5D%20=%20value%5Bsymbol%5D;%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20return%20_copy;%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20return%20value;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Update%20a%20value%20in%20an%20object%20in%20an%20immutable%20way.%0A%20%20%20%20%20*%20If%20the%20value%20is%20unchanged,%20the%20original%20object%20will%20be%20returned%0A%20%20%20%20%20*/%0A%20%20%20%20function%20applyProp(object,%20key,%20value)%20%7B%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20if%20(object%5Bkey%5D%20===%20value)%20%7B%0A%20%20%20%20%20%20%20%20//%20return%20original%20object%20unchanged%20when%20the%20new%20value%20is%20identical%20to%20the%20old%20one%0A%20%20%20%20%20%20%20%20return%20object;%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20var%20updatedObject%20=%20shallowClone(object);%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20updatedObject%5Bkey%5D%20=%20value;%0A%20%20%20%20%20%20%20%20return%20updatedObject;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20get%20a%20nested%20property%20in%20an%20object%20or%20array%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@return%20Returns%20the%20field%20when%20found,%20or%20undefined%20when%20the%20path%20doesn't%20exist%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getIn(object,%20path)%20%7B%0A%20%20%20%20%20%20var%20value%20=%20object;%0A%20%20%20%20%20%20var%20i%20=%200;%0A%20%20%20%20%20%20while%20(i%20%3C%20path.length)%20%7B%0A%20%20%20%20%20%20%20%20if%20(isJSONObject(value))%20%7B%0A%20%20%20%20%20%20%20%20%20%20value%20=%20value%5Bpath%5Bi%5D%5D;%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(isJSONArray(value))%20%7B%0A%20%20%20%20%20%20%20%20%20%20value%20=%20value%5BparseInt(path%5Bi%5D)%5D;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20value%20=%20undefined;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20i++;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20return%20value;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20replace%20a%20nested%20property%20in%20an%20object%20with%20a%20new%20value%0A%20%20%20%20%20*%20without%20mutating%20the%20object%20itself.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20object%0A%20%20%20%20%20*%20@param%20path%0A%20%20%20%20%20*%20@param%20value%0A%20%20%20%20%20*%20@param%20%5BcreatePath=false%5D%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20If%20true,%20%60path%60%20will%20be%20created%20when%20(partly)%20missing%20in%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20the%20object.%20For%20correctly%20creating%20nested%20Arrays%20or%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Objects,%20the%20function%20relies%20on%20%60path%60%20containing%20number%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20in%20case%20of%20array%20indexes.%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20If%20false%20(default),%20an%20error%20will%20be%20thrown%20when%20the%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20path%20doesn't%20exist.%0A%20%20%20%20%20*%20@return%20Returns%20a%20new,%20updated%20object%20or%20array%0A%20%20%20%20%20*/%0A%20%20%20%20function%20setIn(object,%20path,%20value)%20%7B%0A%20%20%20%20%20%20var%20createPath%20=%20arguments.length%20%3E%203%20&&%20arguments%5B3%5D%20!==%20undefined%20?%20arguments%5B3%5D%20:%20false;%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20value;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20updatedValue%20=%20setIn(object%20?%20object%5Bkey%5D%20:%20undefined,%20path.slice(1),%20value,%20createPath);%0A%20%20%20%20%20%20if%20(isJSONObject(object)%20%7C%7C%20isJSONArray(object))%20%7B%0A%20%20%20%20%20%20%20%20return%20applyProp(object,%20key,%20updatedValue);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20if%20(createPath)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20newObject%20=%20IS_INTEGER_REGEX.test(key)%20?%20%5B%5D%20:%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20newObject%5Bkey%5D%20=%20updatedValue;%0A%20%20%20%20%20%20%20%20%20%20return%20newObject;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Path%20does%20not%20exist');%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20var%20IS_INTEGER_REGEX%20=%20/%5E%5Cd+$/;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20replace%20a%20nested%20property%20in%20an%20object%20with%20a%20new%20value%0A%20%20%20%20%20*%20without%20mutating%20the%20object%20itself.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@return%20%20Returns%20a%20new,%20updated%20object%20or%20array%0A%20%20%20%20%20*/%0A%20%20%20%20function%20updateIn(object,%20path,%20callback)%20%7B%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20callback(object);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(!isObjectOrArray(object))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Path%20doesn%5C't%20exist');%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20updatedValue%20=%20updateIn(object%5Bkey%5D,%20path.slice(1),%20callback);%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20applyProp(object,%20key,%20updatedValue);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20helper%20function%20to%20delete%20a%20nested%20property%20in%20an%20object%0A%20%20%20%20%20*%20without%20mutating%20the%20object%20itself.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@return%20Returns%20a%20new,%20updated%20object%20or%20array%0A%20%20%20%20%20*/%0A%20%20%20%20function%20deleteIn(object,%20path)%20%7B%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20object;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(!isObjectOrArray(object))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Path%20does%20not%20exist');%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(path.length%20===%201)%20%7B%0A%20%20%20%20%20%20%20%20var%20_key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20%20%20if%20(!(_key%20in%20object))%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20key%20doesn't%20exist.%20return%20object%20unchanged%0A%20%20%20%20%20%20%20%20%20%20return%20object;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20updatedObject%20=%20shallowClone(object);%0A%20%20%20%20%20%20%20%20%20%20if%20(isJSONArray(updatedObject))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20updatedObject.splice(parseInt(_key),%201);%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20if%20(isJSONObject(updatedObject))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20delete%20updatedObject%5B_key%5D;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20return%20updatedObject;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20key%20=%20path%5B0%5D;%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20updatedValue%20=%20deleteIn(object%5Bkey%5D,%20path.slice(1));%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20applyProp(object,%20key,%20updatedValue);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Insert%20a%20new%20item%20in%20an%20array%20at%20a%20specific%20index.%0A%20%20%20%20%20*%20Example%20usage:%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%20%20%20%20insertAt(%7Barr:%20%5B1,2,3%5D%7D,%20%5B'arr',%20'2'%5D,%20'inserted')%20%20//%20%5B1,2,'inserted',3%5D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20insertAt(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20var%20parentPath%20=%20path.slice(0,%20path.length%20-%201);%0A%20%20%20%20%20%20var%20index%20=%20path%5Bpath.length%20-%201%5D;%0A%20%20%20%20%20%20return%20updateIn(document,%20parentPath,%20function%20(items)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!Array.isArray(items))%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20TypeError('Array%20expected%20at%20path%20'%20+%20JSON.stringify(parentPath));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20updatedItems%20=%20shallowClone(items);%0A%20%20%20%20%20%20%20%20updatedItems.splice(parseInt(index),%200,%20value);%0A%20%20%20%20%20%20%20%20return%20updatedItems;%0A%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20whether%20a%20path%20exists%20in%20a%20JSON%20object%0A%20%20%20%20%20*%20@return%20Returns%20true%20if%20the%20path%20exists,%20else%20returns%20false%0A%20%20%20%20%20*/%0A%20%20%20%20function%20existsIn(document,%20path)%20%7B%0A%20%20%20%20%20%20if%20(document%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20true;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(document%20===%20null)%20%7B%0A%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20existsIn(document%5Bpath%5B0%5D%5D,%20path.slice(1));%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Parse%20a%20JSON%20Pointer%0A%20%20%20%20%20*/%0A%20%20%20%20function%20parseJSONPointer(pointer)%20%7B%0A%20%20%20%20%20%20var%20path%20=%20pointer.split('/');%0A%20%20%20%20%20%20path.shift();%20//%20remove%20the%20first%20empty%20entry%0A%0A%20%20%20%20%20%20return%20path.map(function%20(p)%20%7B%0A%20%20%20%20%20%20%20%20return%20p.replace(/~1/g,%20'/').replace(/~0/g,%20'~');%0A%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Compile%20a%20JSON%20Pointer%0A%20%20%20%20%20*/%0A%20%20%20%20function%20compileJSONPointer(path)%20%7B%0A%20%20%20%20%20%20return%20path.map(compileJSONPointerProp).join('');%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Compile%20a%20single%20path%20property%20from%20a%20JSONPath%0A%20%20%20%20%20*/%0A%20%20%20%20function%20compileJSONPointerProp(pathProp)%20%7B%0A%20%20%20%20%20%20return%20'/'%20+%20String(pathProp).replace(/~/g,%20'~0').replace(/%5C//g,%20'~1');%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Apply%20a%20patch%20to%20a%20JSON%20object%0A%20%20%20%20%20*%20The%20original%20JSON%20object%20will%20not%20be%20changed,%0A%20%20%20%20%20*%20instead,%20the%20patch%20is%20applied%20in%20an%20immutable%20way%0A%20%20%20%20%20*/%0A%20%20%20%20function%20immutableJSONPatch(document,%20operations,%20options)%20%7B%0A%20%20%20%20%20%20var%20updatedDocument%20=%20document;%0A%20%20%20%20%20%20for%20(var%20i%20=%200;%20i%20%3C%20operations.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20validateJSONPatchOperation(operations%5Bi%5D);%0A%20%20%20%20%20%20%20%20var%20operation%20=%20operations%5Bi%5D;%0A%0A%20%20%20%20%20%20%20%20//%20TODO:%20test%20before%0A%20%20%20%20%20%20%20%20if%20(options%20&&%20options.before)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20result%20=%20options.before(updatedDocument,%20operation);%0A%20%20%20%20%20%20%20%20%20%20if%20(result%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(result.document%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20result.document;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(result.json%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20deprecated%20since%20v5.0.0.%20Cleanup%20this%20warning%20some%20day%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Deprecation%20warning:%20returned%20object%20property%20%22.json%22%20has%20been%20renamed%20to%20%22.document%22');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(result.operation%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20operation%20=%20result.operation;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20previousDocument%20=%20updatedDocument;%0A%20%20%20%20%20%20%20%20var%20path%20=%20parsePath(updatedDocument,%20operation.path);%0A%20%20%20%20%20%20%20%20if%20(operation.op%20===%20'add')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20add(updatedDocument,%20path,%20operation.value);%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'remove')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20remove(updatedDocument,%20path);%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'replace')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20replace(updatedDocument,%20path,%20operation.value);%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'copy')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20copy(updatedDocument,%20path,%20parseFrom(operation.from));%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'move')%20%7B%0A%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20move(updatedDocument,%20path,%20parseFrom(operation.from));%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(operation.op%20===%20'test')%20%7B%0A%20%20%20%20%20%20%20%20%20%20test(updatedDocument,%20path,%20operation.value);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Unknown%20JSONPatch%20operation%20'%20+%20JSON.stringify(operation));%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20TODO:%20test%20after%0A%20%20%20%20%20%20%20%20if%20(options%20&&%20options.after)%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20_result%20=%20options.after(updatedDocument,%20operation,%20previousDocument);%0A%20%20%20%20%20%20%20%20%20%20if%20(_result%20!==%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20updatedDocument%20=%20_result;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20return%20updatedDocument;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Replace%20an%20existing%20item%0A%20%20%20%20%20*/%0A%20%20%20%20function%20replace(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20return%20setIn(document,%20path,%20value);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Remove%20an%20item%20or%20property%0A%20%20%20%20%20*/%0A%20%20%20%20function%20remove(document,%20path)%20%7B%0A%20%20%20%20%20%20return%20deleteIn(document,%20path);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Add%20an%20item%20or%20property%0A%20%20%20%20%20*/%0A%20%20%20%20function%20add(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20if%20(isArrayItem(document,%20path))%20%7B%0A%20%20%20%20%20%20%20%20return%20insertAt(document,%20path,%20value);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20return%20setIn(document,%20path,%20value);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Copy%20a%20value%0A%20%20%20%20%20*/%0A%20%20%20%20function%20copy(document,%20path,%20from)%20%7B%0A%20%20%20%20%20%20var%20value%20=%20getIn(document,%20from);%0A%20%20%20%20%20%20if%20(isArrayItem(document,%20path))%20%7B%0A%20%20%20%20%20%20%20%20return%20insertAt(document,%20path,%20value);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20var%20_value%20=%20getIn(document,%20from);%0A%20%20%20%20%20%20%20%20return%20setIn(document,%20path,%20_value);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Move%20a%20value%0A%20%20%20%20%20*/%0A%20%20%20%20function%20move(document,%20path,%20from)%20%7B%0A%20%20%20%20%20%20var%20value%20=%20getIn(document,%20from);%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20var%20removedJson%20=%20deleteIn(document,%20from);%0A%20%20%20%20%20%20return%20isArrayItem(removedJson,%20path)%20?%20insertAt(removedJson,%20path,%20value)%20:%20setIn(removedJson,%20path,%20value);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Test%20whether%20the%20data%20contains%20the%20provided%20value%20at%20the%20specified%20path.%0A%20%20%20%20%20*%20Throws%20an%20error%20when%20the%20test%20fails%0A%20%20%20%20%20*/%0A%20%20%20%20function%20test(document,%20path,%20value)%20%7B%0A%20%20%20%20%20%20if%20(value%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error(%22Test%20failed:%20no%20value%20provided%20(path:%20%5C%22%22.concat(compileJSONPointer(path),%20%22%5C%22)%22));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(!existsIn(document,%20path))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error(%22Test%20failed:%20path%20not%20found%20(path:%20%5C%22%22.concat(compileJSONPointer(path),%20%22%5C%22)%22));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20actualValue%20=%20getIn(document,%20path);%0A%20%20%20%20%20%20if%20(!isEqual(actualValue,%20value))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error(%22Test%20failed,%20value%20differs%20(path:%20%5C%22%22.concat(compileJSONPointer(path),%20%22%5C%22)%22));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20function%20isArrayItem(document,%20path)%20%7B%0A%20%20%20%20%20%20if%20(path.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20parent%20=%20getIn(document,%20initial(path));%0A%20%20%20%20%20%20return%20Array.isArray(parent);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Resolve%20the%20path%20index%20of%20an%20array,%20resolves%20indexes%20'-'%0A%20%20%20%20%20*%20@returns%20Returns%20the%20resolved%20path%0A%20%20%20%20%20*/%0A%20%20%20%20function%20resolvePathIndex(document,%20path)%20%7B%0A%20%20%20%20%20%20if%20(last(path)%20!==%20'-')%20%7B%0A%20%20%20%20%20%20%20%20return%20path;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20var%20parentPath%20=%20initial(path);%0A%20%20%20%20%20%20var%20parent%20=%20getIn(document,%20parentPath);%0A%0A%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/ban-ts-comment%0A%20%20%20%20%20%20//%20@ts-ignore%0A%20%20%20%20%20%20return%20parentPath.concat(parent.length);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Validate%20a%20JSONPatch%20operation.%0A%20%20%20%20%20*%20Throws%20an%20error%20when%20there%20is%20an%20issue%0A%20%20%20%20%20*/%0A%20%20%20%20function%20validateJSONPatchOperation(operation)%20%7B%0A%20%20%20%20%20%20//%20TODO:%20write%20unit%20tests%0A%20%20%20%20%20%20var%20ops%20=%20%5B'add',%20'remove',%20'replace',%20'copy',%20'move',%20'test'%5D;%0A%20%20%20%20%20%20if%20(!ops.includes(operation.op))%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Unknown%20JSONPatch%20op%20'%20+%20JSON.stringify(operation.op));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(typeof%20operation.path%20!==%20'string')%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20Error('Required%20property%20%22path%22%20missing%20or%20not%20a%20string%20in%20operation%20'%20+%20JSON.stringify(operation));%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(operation.op%20===%20'copy'%20%7C%7C%20operation.op%20===%20'move')%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20operation.from%20!==%20'string')%20%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Required%20property%20%22from%22%20missing%20or%20not%20a%20string%20in%20operation%20'%20+%20JSON.stringify(operation));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20function%20parsePath(document,%20pointer)%20%7B%0A%20%20%20%20%20%20return%20resolvePathIndex(document,%20parseJSONPointer(pointer));%0A%20%20%20%20%7D%0A%20%20%20%20function%20parseFrom(fromPointer)%20%7B%0A%20%20%20%20%20%20return%20parseJSONPointer(fromPointer);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20%7Bobject%7D%20AssetConfig%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20regularFontUrl%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20boldFontUrl%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20%7Bobject%7D%20Site%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20domain%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20isBroken%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20allowlisted%0A%20%20%20%20%20*%20@property%20%7Bstring%5B%5D%7D%20enabledFeatures%0A%20%20%20%20%20*/%0A%0A%20%20%20%20class%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20/**%20@type%20%7Bimport('./utils.js').RemoteConfig%20%7C%20undefined%7D%20*/%0A%20%20%20%20%20%20%20%20#bundledConfig%0A%20%20%20%20%20%20%20%20/**%20@type%20%7Bobject%20%7C%20undefined%7D%20*/%0A%20%20%20%20%20%20%20%20#trackerLookup%0A%20%20%20%20%20%20%20%20/**%20@type%20%7Bboolean%20%7C%20undefined%7D%20*/%0A%20%20%20%20%20%20%20%20#documentOriginIsTracker%0A%20%20%20%20%20%20%20%20/**%20@type%20%7BRecord%3Cstring,%20unknown%3E%20%7C%20undefined%7D%20*/%0A%20%20%20%20%20%20%20%20#bundledfeatureSettings%0A%0A%20%20%20%20%20%20%20%20/**%20@type%20%7B%7B%20debug:%20boolean,%20featureSettings:%20Record%3Cstring,%20unknown%3E,%20assets:%20AssetConfig%20%7C%20undefined,%20site:%20Site%20%20%7D%20%7C%20null%7D%20*/%0A%20%20%20%20%20%20%20%20#args%0A%0A%20%20%20%20%20%20%20%20constructor%20(featureName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.name%20=%20featureName;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#args%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.monitor%20=%20new%20PerformanceMonitor();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20isDebug%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#args?.debug%20%7C%7C%20false%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bimport('./utils').Platform%7D%20platform%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20set%20platform%20(platform)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this._platform%20=%20platform;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20platform%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'Platform%20%7C%20undefined'%20is%20not%20assignable%20to%20type%20'Platform'%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._platform%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@type%20%7BAssetConfig%20%7C%20undefined%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20get%20assetConfig%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#args?.assets%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20get%20documentOriginIsTracker%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20!!this.#documentOriginIsTracker%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bobject%7D%0A%20%20%20%20%20%20%20%20%20**/%0A%20%20%20%20%20%20%20%20get%20trackerLookup%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#trackerLookup%20%7C%7C%20%7B%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bimport('./utils.js').RemoteConfig%20%7C%20undefined%7D%0A%20%20%20%20%20%20%20%20%20**/%0A%20%20%20%20%20%20%20%20get%20bundledConfig%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#bundledConfig%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Get%20the%20value%20of%20a%20config%20setting.%0A%20%20%20%20%20%20%20%20%20*%20If%20the%20value%20is%20not%20set,%20return%20the%20default%20value.%0A%20%20%20%20%20%20%20%20%20*%20If%20the%20value%20is%20not%20an%20object,%20return%20the%20value.%0A%20%20%20%20%20%20%20%20%20*%20If%20the%20value%20is%20an%20object,%20check%20its%20type%20property.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20attrName%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bany%7D%20defaultValue%20-%20The%20default%20value%20to%20use%20if%20the%20config%20setting%20is%20not%20set%0A%20%20%20%20%20%20%20%20%20*%20@returns%20The%20value%20of%20the%20config%20setting%20or%20the%20default%20value%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getFeatureAttr%20(attrName,%20defaultValue)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20configSetting%20=%20this.getFeatureSetting(attrName);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20processAttr(configSetting,%20defaultValue)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureKeyName%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BfeatureName%5D%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bany%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getFeatureSetting%20(featureKeyName,%20featureName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20result%20=%20this._getFeatureSetting(featureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(featureKeyName%20===%20'domains')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('domains%20is%20a%20reserved%20feature%20setting%20key%20name')%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domainMatch%20=%20%5B...this.matchDomainFeatureSetting('domains')%5D.sort((a,%20b)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20a.domain.length%20-%20b.domain.length%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20match%20of%20domainMatch)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(match.patchSettings%20===%20undefined)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20=%20immutableJSONPatch(result,%20match.patchSettings);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.error('Error%20applying%20patch%20settings',%20e);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20result?.%5BfeatureKeyName%5D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BfeatureName%5D%20-%20The%20name%20of%20the%20feature%20to%20get%20the%20settings%20for;%20defaults%20to%20the%20name%20of%20the%20feature%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bany%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20_getFeatureSetting%20(featureName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20camelFeatureName%20=%20featureName%20%7C%7C%20camelcase(this.name);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#args?.featureSettings?.%5BcamelFeatureName%5D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureKeyName%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BfeatureName%5D%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getFeatureSettingEnabled%20(featureKeyName,%20featureName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20result%20=%20this.getFeatureSetting(featureKeyName,%20featureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20result%20===%20'enabled'%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20featureKeyName%0A%20%20%20%20%20%20%20%20%20*%20@return%20%7Bany%5B%5D%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20matchDomainFeatureSetting%20(featureKeyName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domain%20=%20this.#args?.site.domain;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!domain)%20return%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domains%20=%20this._getFeatureSetting()?.%5BfeatureKeyName%5D%20%7C%7C%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20domains.filter((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20matchHostname(domain,%20rule.domain)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20callInit%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20mark%20=%20this.monitor.mark(this.name%20+%20'CallInit');%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#args%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.platform%20=%20args.platform;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.init(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.measure();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20load%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20callLoad%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20mark%20=%20this.monitor.mark(this.name%20+%20'CallLoad');%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#args%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.platform%20=%20args.platform;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#bundledConfig%20=%20args.bundledConfig;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20we%20have%20a%20bundled%20config,%20treat%20it%20as%20a%20regular%20config%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20This%20will%20be%20overriden%20by%20the%20remote%20config%20if%20it%20is%20available%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#bundledConfig%20&&%20this.#args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20enabledFeatures%20=%20computeEnabledFeatures(args.bundledConfig,%20getTabHostname(),%20this.platform.version);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.#args.featureSettings%20=%20parseFeatureSettings(args.bundledConfig,%20enabledFeatures);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#trackerLookup%20=%20args.trackerLookup;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#documentOriginIsTracker%20=%20args.documentOriginIsTracker;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.load(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20measure%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#args?.debug)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.monitor.measureAll();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20update%20()%20%7B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Indent%20a%20code%20block%20using%20braces%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20string%0A%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20removeIndent%20(string)%20%7B%0A%20%20%20%20%20%20%20%20const%20lines%20=%20string.split('%5Cn');%0A%20%20%20%20%20%20%20%20const%20indentSize%20=%202;%0A%20%20%20%20%20%20%20%20let%20currentIndent%20=%200;%0A%20%20%20%20%20%20%20%20const%20indentedLines%20=%20lines.map((line)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(line.trim().startsWith('%7D'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentIndent%20-=%20indentSize;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20indentedLine%20=%20'%20'.repeat(currentIndent)%20+%20line.trim();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(line.trim().endsWith('%7B'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentIndent%20+=%20indentSize;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20indentedLine%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20return%20indentedLines.filter(a%20=%3E%20a.trim()).join('%5Cn')%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20lookup%20=%20%7B%7D;%0A%20%20%20%20function%20getOrGenerateIdentifier%20(path)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!(path%20in%20lookup))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20lookup%5Bpath%5D%20=%20generateAlphaIdentifier(Object.keys(lookup).length%20+%201);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20lookup%5Bpath%5D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20generateAlphaIdentifier%20(num)%20%7B%0A%20%20%20%20%20%20%20%20if%20(num%20%3C%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20Error('Input%20must%20be%20a%20positive%20integer')%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20charCodeOffset%20=%2097;%0A%20%20%20%20%20%20%20%20let%20identifier%20=%20'';%0A%20%20%20%20%20%20%20%20while%20(num%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20num--;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20remainder%20=%20num%20%25%2026;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20charCode%20=%20remainder%20+%20charCodeOffset;%0A%20%20%20%20%20%20%20%20%20%20%20%20identifier%20=%20String.fromCharCode(charCode)%20+%20identifier;%0A%20%20%20%20%20%20%20%20%20%20%20%20num%20=%20Math.floor(num%20/%2026);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20'_ddg_'%20+%20identifier%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7B*%7D%20scope%0A%20%20%20%20%20*%20@param%20%7BRecord%3Cstring,%20any%3E%7D%20outputs%0A%20%20%20%20%20*%20@returns%20%7BProxy%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20constructProxy%20(scope,%20outputs)%20%7B%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Expected%202%20arguments,%20but%20got%201%0A%20%20%20%20%20%20%20%20if%20(Object.is(scope))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Should%20not%20happen,%20but%20just%20in%20case%20fail%20safely%0A%20%20%20%20%20%20%20%20%20%20%20%20console.error('Runtime%20checks:%20Scope%20must%20be%20an%20object',%20scope,%20outputs);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20scope%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20new%20Proxy(scope,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20get%20(target,%20property,%20receiver)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20targetObj%20=%20target%5Bproperty%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20targetOut%20=%20target;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20property%20===%20'string'%20&&%20property%20in%20outputs)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetOut%20=%20outputs;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflects%20functions%20with%20the%20correct%20'this'%20scope%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20targetObj%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20(...args)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(targetOut%5Bproperty%5D,%20target,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.get(targetOut,%20property,%20receiver)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20valToString%20(val)%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20val%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20val.toString()%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20JSON.stringify(val)%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Output%20scope%20variable%20definitions%20to%20arbitrary%20depth%0A%20%20%20%20%20*/%0A%20%20%20%20function%20stringifyScope%20(scope,%20scopePath)%20%7B%0A%20%20%20%20%20%20%20%20let%20output%20=%20'';%0A%20%20%20%20%20%20%20%20for%20(const%20%5Bkey,%20value%5D%20of%20scope)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20varOutName%20=%20getOrGenerateIdentifier(%5B...scopePath,%20key%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(value%20instanceof%20Map)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxyName%20=%20getOrGenerateIdentifier(%5B'_proxyFor_',%20varOutName%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7BproxyName%7D%20=%20$%7BscopePath.join('?.')%7D?.$%7Bkey%7D%20?%20$%7BscopePath.join('.')%7D.$%7Bkey%7D%20:%20Object.bind(null);%0A%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20keys%20=%20Array.from(value.keys());%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20stringifyScope(value,%20%5B...scopePath,%20key%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxyOut%20=%20keys.map((keyName)%20=%3E%20%60$%7BkeyName%7D:%20$%7BgetOrGenerateIdentifier(%5B...scopePath,%20key,%20keyName%5D)%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7BvarOutName%7D%20=%20constructProxy($%7BproxyName%7D,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20$%7BproxyOut.join(',%5Cn')%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20we're%20at%20the%20top%20level,%20we%20need%20to%20add%20the%20window%20and%20globalThis%20variables%20(Eg:%20let%20navigator%20=%20parentScope_navigator)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(scopePath.length%20===%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7Bkey%7D%20=%20$%7BvarOutName%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20output%20+=%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20$%7BvarOutName%7D%20=%20$%7BvalToString(value)%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20output%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Code%20generates%20wrapping%20variables%20for%20code%20that%20is%20injected%20into%20the%20page%0A%20%20%20%20%20*%20@param%20%7B*%7D%20code%0A%20%20%20%20%20*%20@param%20%7B*%7D%20config%0A%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20wrapScriptCodeOverload%20(code,%20config)%20%7B%0A%20%20%20%20%20%20%20%20const%20processedConfig%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20for%20(const%20%5Bkey,%20value%5D%20of%20Object.entries(config))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20processedConfig%5Bkey%5D%20=%20processAttr(value);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20//%20Don't%20do%20anything%20if%20the%20config%20is%20empty%0A%20%20%20%20%20%20%20%20if%20(Object.keys(processedConfig).length%20===%200)%20return%20code%0A%0A%20%20%20%20%20%20%20%20let%20prepend%20=%20'';%0A%20%20%20%20%20%20%20%20const%20aggregatedLookup%20=%20new%20Map();%0A%20%20%20%20%20%20%20%20let%20currentScope%20=%20null;%0A%20%20%20%20%20%20%20%20/*%20Convert%20the%20config%20into%20a%20map%20of%20scopePath%20-%3E%20%7B%20key:%20value%20%7D%20*/%0A%20%20%20%20%20%20%20%20for%20(const%20%5Bkey,%20value%5D%20of%20Object.entries(processedConfig))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20path%20=%20key.split('.');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20currentScope%20=%20aggregatedLookup;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20pathOut%20=%20path%5Bpath.length%20-%201%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Traverse%20the%20path%20and%20create%20the%20nested%20objects%0A%20%20%20%20%20%20%20%20%20%20%20%20path.slice(0,%20-1).forEach((pathPart,%20index)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!currentScope.has(pathPart))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentScope.set(pathPart,%20new%20Map());%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentScope%20=%20currentScope.get(pathPart);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20currentScope.set(pathOut,%20value);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20prepend%20+=%20stringifyScope(aggregatedLookup,%20%5B'parentScope'%5D);%0A%20%20%20%20%20%20%20%20//%20Stringify%20top%20level%20keys%0A%20%20%20%20%20%20%20%20const%20keysOut%20=%20%5B...aggregatedLookup.keys()%5D.map((keyName)%20=%3E%20%60$%7BkeyName%7D:%20$%7BgetOrGenerateIdentifier(%5B'parentScope',%20keyName%5D)%7D%60).join(',%5Cn');%0A%20%20%20%20%20%20%20%20prepend%20+=%20%60%0A%20%20%20%20const%20window%20=%20constructProxy(parentScope,%20%7B%0A%20%20%20%20%20%20%20%20$%7BkeysOut%7D%0A%20%20%20%20%7D);%0A%20%20%20%20const%20globalThis%20=%20constructProxy(parentScope,%20%7B%0A%20%20%20%20%20%20%20%20$%7BkeysOut%7D%0A%20%20%20%20%7D);%0A%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20return%20removeIndent(%60(function%20(parentScope)%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20DuckDuckGo%20Runtime%20Checks%20injected%20code.%0A%20%20%20%20%20%20%20%20%20*%20If%20you're%20reading%20this,%20you're%20probably%20trying%20to%20debug%20a%20site%20that%20is%20breaking%20due%20to%20our%20runtime%20checks.%0A%20%20%20%20%20%20%20%20%20*%20Please%20raise%20an%20issues%20on%20our%20GitHub%20repo:%20https://github.com/duckduckgo/content-scope-scripts/%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20$%7BconstructProxy.toString()%7D%0A%20%20%20%20%20%20%20%20$%7Bprepend%7D%0A%20%20%20%20%20%20%20%20$%7Bcode%7D%0A%20%20%20%20%7D)(globalThis)%0A%20%20%20%20%60)%0A%20%20%20%20%7D%0A%0A%20%20%20%20/*%20global%20TrustedScriptURL,%20TrustedScript%20*/%0A%0A%20%20%20%20let%20stackDomains%20=%20%5B%5D;%0A%20%20%20%20let%20matchAllStackDomains%20=%20false;%0A%20%20%20%20let%20taintCheck%20=%20false;%0A%20%20%20%20let%20initialCreateElement;%0A%20%20%20%20let%20tagModifiers%20=%20%7B%7D;%0A%20%20%20%20let%20shadowDomEnabled%20=%20false;%0A%20%20%20%20let%20scriptOverload%20=%20%7B%7D;%0A%20%20%20%20//%20Ignore%20monitoring%20properties%20that%20are%20only%20relevant%20once%20and%20already%20handled%0A%20%20%20%20const%20defaultIgnoreMonitorList%20=%20%5B'onerror',%20'onload'%5D;%0A%20%20%20%20let%20ignoreMonitorList%20=%20defaultIgnoreMonitorList;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20tagName%0A%20%20%20%20%20*%20@param%20%7B'property'%20%7C%20'attribute'%20%7C%20'handler'%20%7C%20'listener'%7D%20filterName%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20key%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shouldFilterKey%20(tagName,%20filterName,%20key)%20%7B%0A%20%20%20%20%20%20%20%20if%20(filterName%20===%20'attribute')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20key%20=%20key.toLowerCase();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20tagModifiers?.%5BtagName%5D?.filters?.%5BfilterName%5D?.includes(key)%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20elementRemovalTimeout;%0A%20%20%20%20const%20featureName%20=%20'runtimeChecks';%0A%20%20%20%20const%20taintSymbol%20=%20Symbol(featureName);%0A%20%20%20%20const%20supportedSinks%20=%20%5B'src'%5D;%0A%20%20%20%20//%20Store%20the%20original%20methods%20so%20we%20can%20call%20them%20without%20any%20side%20effects%0A%20%20%20%20const%20defaultElementMethods%20=%20%7B%0A%20%20%20%20%20%20%20%20setAttribute:%20HTMLElement.prototype.setAttribute,%0A%20%20%20%20%20%20%20%20setAttributeNS:%20HTMLElement.prototype.setAttributeNS,%0A%20%20%20%20%20%20%20%20getAttribute:%20HTMLElement.prototype.getAttribute,%0A%20%20%20%20%20%20%20%20getAttributeNS:%20HTMLElement.prototype.getAttributeNS,%0A%20%20%20%20%20%20%20%20removeAttribute:%20HTMLElement.prototype.removeAttribute,%0A%20%20%20%20%20%20%20%20remove:%20HTMLElement.prototype.remove,%0A%20%20%20%20%20%20%20%20removeChild:%20HTMLElement.prototype.removeChild%0A%20%20%20%20%7D;%0A%20%20%20%20const%20supportedTrustedTypes%20=%20'TrustedScriptURL'%20in%20window;%0A%0A%20%20%20%20class%20DDGRuntimeChecks%20extends%20HTMLElement%20%7B%0A%20%20%20%20%20%20%20%20#tagName%0A%20%20%20%20%20%20%20%20#el%0A%20%20%20%20%20%20%20%20#listeners%0A%20%20%20%20%20%20%20%20#connected%0A%20%20%20%20%20%20%20%20#sinks%0A%0A%20%20%20%20%20%20%20%20constructor%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20super();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#tagName%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#el%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#connected%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#sinks%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shadowDomEnabled)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20shadow%20=%20this.attachShadow(%7B%20mode:%20'open'%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20style%20=%20createStyleElement(%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20:host%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shadow.appendChild(style);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20This%20method%20is%20called%20once%20and%20externally%20so%20has%20to%20remain%20public.%0A%20%20%20%20%20%20%20%20%20**/%0A%20%20%20%20%20%20%20%20setTagName%20(tagName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#tagName%20=%20tagName;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Clear%20the%20method%20so%20it%20can't%20be%20called%20again%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS2790:%20The%20operand%20of%20a%20'delete'%20operator%20must%20be%20optional.%0A%20%20%20%20%20%20%20%20%20%20%20%20delete%20this.setTagName;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20connectedCallback%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Solves%20re-entrancy%20issues%20from%20React%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#connected)%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#connected%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this._transplantElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Restore%20the%20'this'%20object%20with%20the%20DDGRuntimeChecks%20prototype%20as%20sometimes%20pages%20will%20overwrite%20it.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.setPrototypeOf(this,%20DDGRuntimeChecks.prototype);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this._transplantElement();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20_monitorProperties%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Mutation%20oberver%20and%20observedAttributes%20don't%20work%20on%20property%20accessors%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20So%20instead%20we%20need%20to%20monitor%20all%20properties%20on%20the%20prototypes%20and%20forward%20them%20to%20the%20real%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20propertyNames%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20proto%20=%20Object.getPrototypeOf(el);%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20(proto%20&&%20proto%20!==%20Object.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20propertyNames.push(...Object.getOwnPropertyNames(proto));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proto%20=%20Object.getPrototypeOf(proto);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20classMethods%20=%20Object.getOwnPropertyNames(Object.getPrototypeOf(this));%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Filter%20away%20the%20methods%20we%20don't%20want%20to%20monitor%20from%20our%20own%20class%0A%20%20%20%20%20%20%20%20%20%20%20%20propertyNames%20=%20propertyNames.filter(prop%20=%3E%20!classMethods.includes(prop));%0A%20%20%20%20%20%20%20%20%20%20%20%20propertyNames.forEach(prop%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(prop%20===%20'constructor')%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20May%20throw,%20but%20this%20is%20best%20effort%20monitoring.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(this,%20prop,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el%5Bprop%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20set%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'property',%20prop))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(ignoreMonitorList.includes(prop))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5Bprop%5D%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20computeScriptOverload%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Short%20circuit%20if%20we%20don't%20have%20any%20script%20text%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el.textContent%20===%20'')%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Short%20circuit%20if%20we're%20in%20a%20trusted%20script%20environment%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TrustedScript%20is%20not%20defined%20in%20the%20TS%20lib%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedTrustedTypes%20&&%20el.textContent%20instanceof%20TrustedScript)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20el.textContent%20=%20wrapScriptCodeOverload(el.textContent,%20scriptOverload);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20The%20element%20has%20been%20moved%20to%20the%20DOM,%20so%20we%20can%20now%20reflect%20all%20changes%20to%20a%20real%20element.%0A%20%20%20%20%20%20%20%20%20*%20This%20is%20to%20allow%20us%20to%20interrogate%20the%20real%20element%20before%20it%20is%20moved%20to%20the%20DOM.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20_transplantElement%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Creeate%20the%20real%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20initialCreateElement.call(document,%20this.#tagName);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(taintCheck)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Add%20a%20symbol%20to%20the%20element%20so%20we%20can%20identify%20it%20as%20a%20runtime%20checked%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(el,%20taintSymbol,%20%7B%20value:%20true,%20configurable:%20false,%20enumerable:%20false,%20writable:%20false%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20attrs%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20attribute%20of%20this.getAttributeNames())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20attribute))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defaultElementMethods.setAttribute.call(el,%20attribute,%20this.getAttribute(attribute));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20props%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20props%20=%20Object.keys(this);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Nonce%20isn't%20enumerable%20so%20we%20need%20to%20add%20it%20manually%0A%20%20%20%20%20%20%20%20%20%20%20%20props.push('nonce');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20prop%20of%20props)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'property',%20prop))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5Bprop%5D%20=%20this%5Bprop%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20sink%20of%20supportedSinks)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#sinks%5Bsink%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5Bsink%5D%20=%20this.#sinks%5Bsink%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20listeners%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5B...args%5D%20of%20this.#listeners)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'listener',%20args%5B0%5D))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.addEventListener(...args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners%20=%20%5B%5D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Reflect%20all%20'on'%20event%20handlers%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20propName%20in%20this)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(propName.startsWith('on'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'handler',%20propName))%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20prop%20=%20this%5BpropName%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20prop%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%5BpropName%5D%20=%20prop;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Move%20all%20children%20to%20the%20new%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20(this.firstChild)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.appendChild(this.firstChild);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.#tagName%20===%20'script')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.computeScriptOverload(el);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Move%20the%20new%20element%20to%20the%20DOM%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.insertAdjacentElement('afterend',%20el);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%20console.warn(e);%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20this._monitorProperties(el);%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO%20pollyfill%20WeakRef%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#el%20=%20new%20WeakRef(el);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Delay%20removal%20of%20the%20custom%20element%20so%20if%20the%20script%20calls%20removeChild%20it%20will%20still%20be%20in%20the%20DOM%20and%20not%20throw.%0A%20%20%20%20%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.remove();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20elementRemovalTimeout);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20_getElement%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#el?.deref()%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Calls%20a%20method%20on%20the%20real%20element%20if%20it%20exists,%20otherwise%20calls%20the%20method%20on%20the%20DDGRuntimeChecks%20element.%0A%20%20%20%20%20%20%20%20%20*%20@template%20%7Bkeyof%20defaultElementMethods%7D%20E%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BE%7D%20method%0A%20%20%20%20%20%20%20%20%20*%20@param%20%20%7B...Parameters%3CdefaultElementMethods%5BE%5D%3E%7D%20args%0A%20%20%20%20%20%20%20%20%20*%20@return%20%7BReturnType%3CdefaultElementMethods%5BE%5D%3E%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20_callMethod%20(method,%20...args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20defaultElementMethods%5Bmethod%5D.call(el,%20...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TS%20doesn't%20like%20the%20spread%20operator%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20super%5Bmethod%5D(...args)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/*%20Native%20DOM%20element%20methods%20we're%20capturing%20to%20supplant%20values%20into%20the%20constructed%20node%20or%20store%20data%20for.%20*/%0A%0A%20%20%20%20%20%20%20%20set%20src%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.src%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#sinks.src%20=%20value;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20src%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el.src%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TrustedScriptURL%20is%20not%20defined%20in%20the%20TS%20lib%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedTrustedTypes%20&&%20this.#sinks.src%20instanceof%20TrustedScriptURL)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#sinks.src.toString()%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#sinks.src%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20getAttribute%20(name,%20value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20name))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedSinks.includes(name))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Use%20Reflect%20to%20avoid%20infinite%20recursion%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.get(DDGRuntimeChecks.prototype,%20name,%20this)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('getAttribute',%20name,%20value)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20getAttributeNS%20(namespace,%20name,%20value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(namespace)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('getAttributeNS',%20namespace,%20name,%20value)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(DDGRuntimeChecks.prototype.getAttribute,%20this,%20%5Bname,%20value%5D)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20setAttribute%20(name,%20value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20name))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedSinks.includes(name))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Use%20Reflect%20to%20avoid%20infinite%20recursion%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.set(DDGRuntimeChecks.prototype,%20name,%20value,%20this)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('setAttribute',%20name,%20value)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20setAttributeNS%20(namespace,%20name,%20value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(namespace)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('setAttributeNS',%20namespace,%20name,%20value)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(DDGRuntimeChecks.prototype.setAttribute,%20this,%20%5Bname,%20value%5D)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20removeAttribute%20(name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'attribute',%20name))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportedSinks.includes(name))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20this%5Bname%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('removeAttribute',%20name)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20addEventListener%20(...args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'listener',%20args%5B0%5D))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el.addEventListener(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners.push(%5B...args%5D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20removeEventListener%20(...args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldFilterKey(this.#tagName,%20'listener',%20args%5B0%5D))%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20this._getElement();%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(el)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el.removeEventListener(...args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.#listeners%20=%20this.#listeners.filter((listener)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20listener%5B0%5D%20!==%20args%5B0%5D%20%7C%7C%20listener%5B1%5D%20!==%20args%5B1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20toString%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20interfaceName%20=%20this.#tagName.charAt(0).toUpperCase()%20+%20this.#tagName.slice(1);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%60%5Bobject%20HTML$%7BinterfaceName%7DElement%5D%60%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20tagName%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.#tagName.toUpperCase()%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20nodeName%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.tagName%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20remove%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('remove')%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TS%20node%20return%20here%0A%20%20%20%20%20%20%20%20removeChild%20(child)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this._callMethod('removeChild',%20child)%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Overrides%20the%20instanceof%20checks%20to%20make%20the%20custom%20element%20interface%20pass%20an%20instanceof%20check%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20elementInterface%0A%20%20%20%20%20*/%0A%20%20%20%20function%20overloadInstanceOfChecks%20(elementInterface)%20%7B%0A%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20Proxy(elementInterface%5BSymbol.hasInstance%5D,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20apply%20(fn,%20scope,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(args%5B0%5D%20instanceof%20DDGRuntimeChecks)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(fn,%20scope,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20//%20May%20throw,%20but%20we%20can%20ignore%20it%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20Object.defineProperty(elementInterface,%20Symbol.hasInstance,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20proxy%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%20catch%20%7B%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Returns%20true%20if%20the%20tag%20should%20be%20intercepted%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20tagName%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shouldInterrogate%20(tagName)%20%7B%0A%20%20%20%20%20%20%20%20const%20interestingTags%20=%20%5B'script'%5D;%0A%20%20%20%20%20%20%20%20if%20(!interestingTags.includes(tagName))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(matchAllStackDomains)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20isInterrogatingDebugMessage('matchedAllStackDomain');%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(taintCheck%20&&%20document.currentScript?.%5BtaintSymbol%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20isInterrogatingDebugMessage('taintCheck');%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20%5B...getStackTraceOrigins(stack)%5D;%0A%20%20%20%20%20%20%20%20const%20interestingHost%20=%20scriptOrigins.find(origin%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20stackDomains.some(rule%20=%3E%20matchHostname(origin,%20rule.domain))%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20const%20isInterestingHost%20=%20!!interestingHost;%0A%20%20%20%20%20%20%20%20if%20(isInterestingHost)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20isInterrogatingDebugMessage('matchedStackDomain',%20interestingHost,%20stack,%20scriptOrigins);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20isInterestingHost%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isInterrogatingDebugMessage%20(matchType,%20matchedStackDomain,%20stack,%20scriptOrigins)%20%7B%0A%20%20%20%20%20%20%20%20postDebugMessage('runtimeChecks',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20matchedStackDomain,%0A%20%20%20%20%20%20%20%20%20%20%20%20matchType,%0A%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins,%0A%20%20%20%20%20%20%20%20%20%20%20%20stack%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20overrideCreateElement%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20Document.prototype,%20'createElement',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20apply%20(fn,%20scope,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.length%20%3E=%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20String()%20is%20used%20to%20coerce%20the%20value%20to%20a%20string%20(For:%20ProseMirror/prosemirror-model/src/to_dom.ts)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20initialTagName%20=%20String(args%5B0%5D).toLowerCase();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldInterrogate(initialTagName))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args%5B0%5D%20=%20'ddg-runtime-checks';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20el%20=%20Reflect.apply(fn,%20scope,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el.setTagName(initialTagName);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20el%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Reflect.apply(fn,%20scope,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20proxy.overload();%0A%20%20%20%20%20%20%20%20initialCreateElement%20=%20proxy._native;%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20RuntimeChecks%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20load%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20This%20shouldn't%20happen,%20but%20if%20it%20does%20we%20don't%20want%20to%20break%20the%20page%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20TS%20node%20return%20here%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20customElements.define('ddg-runtime-checks',%20DDGRuntimeChecks);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20enabled%20=%20this.getFeatureSettingEnabled('matchAllDomains');%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!enabled)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enabled%20=%20this.matchDomainFeatureSetting('domains').length%20%3E%200;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!enabled)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20taintCheck%20=%20this.getFeatureSettingEnabled('taintCheck');%0A%20%20%20%20%20%20%20%20%20%20%20%20matchAllStackDomains%20=%20this.getFeatureSettingEnabled('matchAllStackDomains');%0A%20%20%20%20%20%20%20%20%20%20%20%20stackDomains%20=%20this.getFeatureSetting('stackDomains')%20%7C%7C%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20elementRemovalTimeout%20=%20this.getFeatureSetting('elementRemovalTimeout')%20%7C%7C%201000;%0A%20%20%20%20%20%20%20%20%20%20%20%20tagModifiers%20=%20this.getFeatureSetting('tagModifiers')%20%7C%7C%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20shadowDomEnabled%20=%20this.getFeatureSettingEnabled('shadowDom')%20%7C%7C%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20scriptOverload%20=%20this.getFeatureSetting('scriptOverload')%20%7C%7C%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20ignoreMonitorList%20=%20this.getFeatureSetting('ignoreMonitorList')%20%7C%7C%20defaultIgnoreMonitorList;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideCreateElement();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.getFeatureSettingEnabled('overloadInstanceOf'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20overloadInstanceOfChecks(HTMLScriptElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.getFeatureSettingEnabled('injectGlobalStyles'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20injectGlobalStyles(%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ddg-runtime-checks%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20@ts-nocheck%0A%20%20%20%20%20%20%20%20const%20sjcl%20=%20(()%20=%3E%20%7B%0A%20%20%20%20/*jslint%20indent:%202,%20bitwise:%20false,%20nomen:%20false,%20plusplus:%20false,%20white:%20false,%20regexp:%20false%20*/%0A%20%20%20%20/*global%20document,%20window,%20escape,%20unescape,%20module,%20require,%20Uint32Array%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20The%20Stanford%20Javascript%20Crypto%20Library,%20top-level%20namespace.%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*/%0A%20%20%20%20var%20sjcl%20=%20%7B%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Symmetric%20ciphers.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20cipher:%20%7B%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Hash%20functions.%20%20Right%20now%20only%20SHA256%20is%20implemented.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20hash:%20%7B%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Key%20exchange%20functions.%20%20Right%20now%20only%20SRP%20is%20implemented.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20keyexchange:%20%7B%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Cipher%20modes%20of%20operation.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20mode:%20%7B%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Miscellaneous.%20%20HMAC%20and%20PBKDF2.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20misc:%20%7B%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Bit%20array%20encoders%20and%20decoders.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20*%20@description%0A%20%20%20%20%20%20%20*%20The%20members%20of%20this%20namespace%20are%20functions%20which%20translate%20between%0A%20%20%20%20%20%20%20*%20SJCL's%20bitArrays%20and%20other%20objects%20(usually%20strings).%20%20Because%20it%0A%20%20%20%20%20%20%20*%20isn't%20always%20clear%20which%20direction%20is%20encoding%20and%20which%20is%20decoding,%0A%20%20%20%20%20%20%20*%20the%20method%20names%20are%20%22fromBits%22%20and%20%22toBits%22.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20codec:%20%7B%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Exceptions.%0A%20%20%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20exception:%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Ciphertext%20is%20corrupt.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20corrupt:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22CORRUPT:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Invalid%20parameter.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20invalid:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22INVALID:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Bug%20or%20missing%20feature%20in%20SJCL.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20bug:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22BUG:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Something%20isn't%20ready.%0A%20%20%20%20%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20notReady:%20function(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this.toString%20=%20function()%20%7B%20return%20%22NOT%20READY:%20%22+this.message;%20%7D;%0A%20%20%20%20%20%20%20%20%20%20this.message%20=%20message;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%20%20%20%20/**%20@fileOverview%20Arrays%20of%20bits,%20encoded%20as%20arrays%20of%20Numbers.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Arrays%20of%20bits,%20encoded%20as%20arrays%20of%20Numbers.%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*%20@description%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20These%20objects%20are%20the%20currency%20accepted%20by%20SJCL's%20crypto%20functions.%0A%20%20%20%20%20*%20%3C/p%3E%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20Most%20of%20our%20crypto%20primitives%20operate%20on%20arrays%20of%204-byte%20words%20internally,%0A%20%20%20%20%20*%20but%20many%20of%20them%20can%20take%20arguments%20that%20are%20not%20a%20multiple%20of%204%20bytes.%0A%20%20%20%20%20*%20This%20library%20encodes%20arrays%20of%20bits%20(whose%20size%20need%20not%20be%20a%20multiple%20of%208%0A%20%20%20%20%20*%20bits)%20as%20arrays%20of%2032-bit%20words.%20%20The%20bits%20are%20packed,%20big-endian,%20into%20an%0A%20%20%20%20%20*%20array%20of%20words,%2032%20bits%20at%20a%20time.%20%20Since%20the%20words%20are%20double-precision%0A%20%20%20%20%20*%20floating%20point%20numbers,%20they%20fit%20some%20extra%20data.%20%20We%20use%20this%20(in%20a%20private,%0A%20%20%20%20%20*%20possibly-changing%20manner)%20to%20encode%20the%20number%20of%20bits%20actually%20%20present%0A%20%20%20%20%20*%20in%20the%20last%20word%20of%20the%20array.%0A%20%20%20%20%20*%20%3C/p%3E%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%3Cp%3E%0A%20%20%20%20%20*%20Because%20bitwise%20ops%20clear%20this%20out-of-band%20data,%20these%20arrays%20can%20be%20passed%0A%20%20%20%20%20*%20to%20ciphers%20like%20AES%20which%20want%20arrays%20of%20words.%0A%20%20%20%20%20*%20%3C/p%3E%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.bitArray%20=%20%7B%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Array%20slices%20in%20units%20of%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array%20to%20slice.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20bstart%20The%20offset%20to%20the%20start%20of%20the%20slice,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20bend%20The%20offset%20to%20the%20end%20of%20the%20slice,%20in%20bits.%20%20If%20this%20is%20undefined,%0A%20%20%20%20%20%20%20*%20slice%20until%20the%20end%20of%20the%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20requested%20slice.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20bitSlice:%20function%20(a,%20bstart,%20bend)%20%7B%0A%20%20%20%20%20%20%20%20a%20=%20sjcl.bitArray._shiftRight(a.slice(bstart/32),%2032%20-%20(bstart%20&%2031)).slice(1);%0A%20%20%20%20%20%20%20%20return%20(bend%20===%20undefined)%20?%20a%20:%20sjcl.bitArray.clamp(a,%20bend-bstart);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Extract%20a%20number%20packed%20into%20a%20bit%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array%20to%20slice.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20bstart%20The%20offset%20to%20the%20start%20of%20the%20slice,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20blength%20The%20length%20of%20the%20number%20to%20extract.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20requested%20slice.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20extract:%20function(a,%20bstart,%20blength)%20%7B%0A%20%20%20%20%20%20%20%20//%20FIXME:%20this%20Math.floor%20is%20not%20necessary%20at%20all,%20but%20for%20some%20reason%0A%20%20%20%20%20%20%20%20//%20seems%20to%20suppress%20a%20bug%20in%20the%20Chromium%20JIT.%0A%20%20%20%20%20%20%20%20var%20x,%20sh%20=%20Math.floor((-bstart-blength)%20&%2031);%0A%20%20%20%20%20%20%20%20if%20((bstart%20+%20blength%20-%201%20%5E%20bstart)%20&%20-32)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20it%20crosses%20a%20boundary%0A%20%20%20%20%20%20%20%20%20%20x%20=%20(a%5Bbstart/32%7C0%5D%20%3C%3C%20(32%20-%20sh))%20%5E%20(a%5Bbstart/32+1%7C0%5D%20%3E%3E%3E%20sh);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20within%20a%20single%20word%0A%20%20%20%20%20%20%20%20%20%20x%20=%20a%5Bbstart/32%7C0%5D%20%3E%3E%3E%20sh;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20x%20&%20((1%3C%3Cblength)%20-%201);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Concatenate%20two%20bit%20arrays.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a1%20The%20first%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a2%20The%20second%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20concatenation%20of%20a1%20and%20a2.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20concat:%20function%20(a1,%20a2)%20%7B%0A%20%20%20%20%20%20%20%20if%20(a1.length%20===%200%20%7C%7C%20a2.length%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20a1.concat(a2);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20var%20last%20=%20a1%5Ba1.length-1%5D,%20shift%20=%20sjcl.bitArray.getPartial(last);%0A%20%20%20%20%20%20%20%20if%20(shift%20===%2032)%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20a1.concat(a2);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20sjcl.bitArray._shiftRight(a2,%20shift,%20last%7C0,%20a1.slice(0,a1.length-1));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Find%20the%20length%20of%20an%20array%20of%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20length%20of%20a,%20in%20bits.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20bitLength:%20function%20(a)%20%7B%0A%20%20%20%20%20%20%20%20var%20l%20=%20a.length,%20x;%0A%20%20%20%20%20%20%20%20if%20(l%20===%200)%20%7B%20return%200;%20%7D%0A%20%20%20%20%20%20%20%20x%20=%20a%5Bl%20-%201%5D;%0A%20%20%20%20%20%20%20%20return%20(l-1)%20*%2032%20+%20sjcl.bitArray.getPartial(x);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Truncate%20an%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20len%20The%20length%20to%20truncate%20to,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20A%20new%20array,%20truncated%20to%20len%20bits.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20clamp:%20function%20(a,%20len)%20%7B%0A%20%20%20%20%20%20%20%20if%20(a.length%20*%2032%20%3C%20len)%20%7B%20return%20a;%20%7D%0A%20%20%20%20%20%20%20%20a%20=%20a.slice(0,%20Math.ceil(len%20/%2032));%0A%20%20%20%20%20%20%20%20var%20l%20=%20a.length;%0A%20%20%20%20%20%20%20%20len%20=%20len%20&%2031;%0A%20%20%20%20%20%20%20%20if%20(l%20%3E%200%20&&%20len)%20%7B%0A%20%20%20%20%20%20%20%20%20%20a%5Bl-1%5D%20=%20sjcl.bitArray.partial(len,%20a%5Bl-1%5D%20&%200x80000000%20%3E%3E%20(len-1),%201);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20a;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Make%20a%20partial%20word%20for%20a%20bit%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20len%20The%20number%20of%20bits%20in%20the%20word.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20x%20The%20bits.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20%5B_end=0%5D%20Pass%201%20if%20x%20has%20already%20been%20shifted%20to%20the%20high%20side.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20partial%20word.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20partial:%20function%20(len,%20x,%20_end)%20%7B%0A%20%20%20%20%20%20%20%20if%20(len%20===%2032)%20%7B%20return%20x;%20%7D%0A%20%20%20%20%20%20%20%20return%20(_end%20?%20x%7C0%20:%20x%20%3C%3C%20(32-len))%20+%20len%20*%200x10000000000;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Get%20the%20number%20of%20bits%20used%20by%20a%20partial%20word.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20x%20The%20partial%20word.%0A%20%20%20%20%20%20%20*%20@return%20%7BNumber%7D%20The%20number%20of%20bits%20used%20by%20the%20partial%20word.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20getPartial:%20function%20(x)%20%7B%0A%20%20%20%20%20%20%20%20return%20Math.round(x/0x10000000000)%20%7C%7C%2032;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Compare%20two%20arrays%20for%20equality%20in%20a%20predictable%20amount%20of%20time.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20first%20array.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20b%20The%20second%20array.%0A%20%20%20%20%20%20%20*%20@return%20%7Bboolean%7D%20true%20if%20a%20==%20b;%20false%20otherwise.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20equal:%20function%20(a,%20b)%20%7B%0A%20%20%20%20%20%20%20%20if%20(sjcl.bitArray.bitLength(a)%20!==%20sjcl.bitArray.bitLength(b))%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20false;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20x%20=%200,%20i;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Ca.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20x%20%7C=%20a%5Bi%5D%5Eb%5Bi%5D;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20(x%20===%200);%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%20Shift%20an%20array%20right.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20a%20The%20array%20to%20shift.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20shift%20The%20number%20of%20bits%20to%20shift.%0A%20%20%20%20%20%20%20*%20@param%20%7BNumber%7D%20%5Bcarry=0%5D%20A%20byte%20to%20carry%20in%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7D%20%5Bout=%5B%5D%5D%20An%20array%20to%20prepend%20to%20the%20output.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_shiftRight:%20function%20(a,%20shift,%20carry,%20out)%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20last2=0,%20shift2;%0A%20%20%20%20%20%20%20%20if%20(out%20===%20undefined)%20%7B%20out%20=%20%5B%5D;%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20for%20(;%20shift%20%3E=%2032;%20shift%20-=%2032)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(carry);%0A%20%20%20%20%20%20%20%20%20%20carry%20=%200;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(shift%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20return%20out.concat(a);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Ca.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(carry%20%7C%20a%5Bi%5D%3E%3E%3Eshift);%0A%20%20%20%20%20%20%20%20%20%20carry%20=%20a%5Bi%5D%20%3C%3C%20(32-shift);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20last2%20=%20a.length%20?%20a%5Ba.length-1%5D%20:%200;%0A%20%20%20%20%20%20%20%20shift2%20=%20sjcl.bitArray.getPartial(last2);%0A%20%20%20%20%20%20%20%20out.push(sjcl.bitArray.partial(shift+shift2%20&%2031,%20(shift%20+%20shift2%20%3E%2032)%20?%20carry%20:%20out.pop(),1));%0A%20%20%20%20%20%20%20%20return%20out;%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%20xor%20a%20block%20of%204%20words%20together.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_xor4:%20function(x,y)%20%7B%0A%20%20%20%20%20%20%20%20return%20%5Bx%5B0%5D%5Ey%5B0%5D,x%5B1%5D%5Ey%5B1%5D,x%5B2%5D%5Ey%5B2%5D,x%5B3%5D%5Ey%5B3%5D%5D;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%20byteswap%20a%20word%20array%20inplace.%0A%20%20%20%20%20%20%20*%20(does%20not%20handle%20partial%20words)%0A%20%20%20%20%20%20%20*%20@param%20%7Bsjcl.bitArray%7D%20a%20word%20array%0A%20%20%20%20%20%20%20*%20@return%20%7Bsjcl.bitArray%7D%20byteswapped%20array%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20byteswapM:%20function(a)%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20v,%20m%20=%200xff00;%0A%20%20%20%20%20%20%20%20for%20(i%20=%200;%20i%20%3C%20a.length;%20++i)%20%7B%0A%20%20%20%20%20%20%20%20%20%20v%20=%20a%5Bi%5D;%0A%20%20%20%20%20%20%20%20%20%20a%5Bi%5D%20=%20(v%20%3E%3E%3E%2024)%20%7C%20((v%20%3E%3E%3E%208)%20&%20m)%20%7C%20((v%20&%20m)%20%3C%3C%208)%20%7C%20(v%20%3C%3C%2024);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20a;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%20%20%20%20/**%20@fileOverview%20Bit%20array%20codec%20implementations.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20UTF-8%20strings%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.codec.utf8String%20=%20%7B%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20bitArray%20to%20a%20UTF-8%20string.%20*/%0A%20%20%20%20%20%20fromBits:%20function%20(arr)%20%7B%0A%20%20%20%20%20%20%20%20var%20out%20=%20%22%22,%20bl%20=%20sjcl.bitArray.bitLength(arr),%20i,%20tmp;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Cbl/8;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20if%20((i&3)%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%20arr%5Bi/4%5D;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20out%20+=%20String.fromCharCode(tmp%20%3E%3E%3E%208%20%3E%3E%3E%208%20%3E%3E%3E%208);%0A%20%20%20%20%20%20%20%20%20%20tmp%20%3C%3C=%208;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20decodeURIComponent(escape(out));%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20UTF-8%20string%20to%20a%20bitArray.%20*/%0A%20%20%20%20%20%20toBits:%20function%20(str)%20%7B%0A%20%20%20%20%20%20%20%20str%20=%20unescape(encodeURIComponent(str));%0A%20%20%20%20%20%20%20%20var%20out%20=%20%5B%5D,%20i,%20tmp=0;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Cstr.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20tmp%20=%20tmp%20%3C%3C%208%20%7C%20str.charCodeAt(i);%0A%20%20%20%20%20%20%20%20%20%20if%20((i&3)%20===%203)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20out.push(tmp);%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%200;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(i&3)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(sjcl.bitArray.partial(8*(i&3),%20tmp));%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20out;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%20%20%20%20/**%20@fileOverview%20Bit%20array%20codec%20implementations.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hexadecimal%0A%20%20%20%20%20*%20@namespace%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.codec.hex%20=%20%7B%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20bitArray%20to%20a%20hex%20string.%20*/%0A%20%20%20%20%20%20fromBits:%20function%20(arr)%20%7B%0A%20%20%20%20%20%20%20%20var%20out%20=%20%22%22,%20i;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Carr.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out%20+=%20((arr%5Bi%5D%7C0)+0xF00000000000).toString(16).substr(4);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20out.substr(0,%20sjcl.bitArray.bitLength(arr)/4);//.replace(/(.%7B8%7D)/g,%20%22$1%20%22);%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20/**%20Convert%20from%20a%20hex%20string%20to%20a%20bitArray.%20*/%0A%20%20%20%20%20%20toBits:%20function%20(str)%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20out=%5B%5D,%20len;%0A%20%20%20%20%20%20%20%20str%20=%20str.replace(/%5Cs%7C0x/g,%20%22%22);%0A%20%20%20%20%20%20%20%20len%20=%20str.length;%0A%20%20%20%20%20%20%20%20str%20=%20str%20+%20%2200000000%22;%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3Cstr.length;%20i+=8)%20%7B%0A%20%20%20%20%20%20%20%20%20%20out.push(parseInt(str.substr(i,8),16)%5E0);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20sjcl.bitArray.clamp(out,%20len*4);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%20@fileOverview%20Javascript%20SHA-256%20implementation.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20An%20older%20version%20of%20this%20implementation%20is%20available%20in%20the%20public%0A%20%20%20%20%20*%20domain,%20but%20this%20one%20is%20(c)%20Emily%20Stark,%20Mike%20Hamburg,%20Dan%20Boneh,%0A%20%20%20%20%20*%20Stanford%20University%202008-2010%20and%20BSD-licensed%20for%20liability%0A%20%20%20%20%20*%20reasons.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20Special%20thanks%20to%20Aldo%20Cortesi%20for%20pointing%20out%20several%20bugs%20in%0A%20%20%20%20%20*%20this%20code.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Context%20for%20a%20SHA-256%20operation%20in%20progress.%0A%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.hash.sha256%20=%20function%20(hash)%20%7B%0A%20%20%20%20%20%20if%20(!this._key%5B0%5D)%20%7B%20this._precompute();%20%7D%0A%20%20%20%20%20%20if%20(hash)%20%7B%0A%20%20%20%20%20%20%20%20this._h%20=%20hash._h.slice(0);%0A%20%20%20%20%20%20%20%20this._buffer%20=%20hash._buffer.slice(0);%0A%20%20%20%20%20%20%20%20this._length%20=%20hash._length;%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20this.reset();%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hash%20a%20string%20or%20an%20array%20of%20words.%0A%20%20%20%20%20*%20@static%0A%20%20%20%20%20*%20@param%20%7BbitArray%7CString%7D%20data%20the%20data%20to%20hash.%0A%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20hash%20value,%20an%20array%20of%2016%20big-endian%20words.%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.hash.sha256.hash%20=%20function%20(data)%20%7B%0A%20%20%20%20%20%20return%20(new%20sjcl.hash.sha256()).update(data).finalize();%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.hash.sha256.prototype%20=%20%7B%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20The%20hash's%20block%20size,%20in%20bits.%0A%20%20%20%20%20%20%20*%20@constant%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20blockSize:%20512,%0A%20%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Reset%20the%20hash%20state.%0A%20%20%20%20%20%20%20*%20@return%20this%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20reset:function%20()%20%7B%0A%20%20%20%20%20%20%20%20this._h%20=%20this._init.slice(0);%0A%20%20%20%20%20%20%20%20this._buffer%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20this._length%20=%200;%0A%20%20%20%20%20%20%20%20return%20this;%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Input%20several%20words%20to%20the%20hash.%0A%20%20%20%20%20%20%20*%20@param%20%7BbitArray%7CString%7D%20data%20the%20data%20to%20hash.%0A%20%20%20%20%20%20%20*%20@return%20this%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20update:%20function%20(data)%20%7B%0A%20%20%20%20%20%20%20%20if%20(typeof%20data%20===%20%22string%22)%20%7B%0A%20%20%20%20%20%20%20%20%20%20data%20=%20sjcl.codec.utf8String.toBits(data);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20var%20i,%20b%20=%20this._buffer%20=%20sjcl.bitArray.concat(this._buffer,%20data),%0A%20%20%20%20%20%20%20%20%20%20%20%20ol%20=%20this._length,%0A%20%20%20%20%20%20%20%20%20%20%20%20nl%20=%20this._length%20=%20ol%20+%20sjcl.bitArray.bitLength(data);%0A%20%20%20%20%20%20%20%20if%20(nl%20%3E%209007199254740991)%7B%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20sjcl.exception.invalid(%22Cannot%20hash%20more%20than%202%5E53%20-%201%20bits%22);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20(typeof%20Uint32Array%20!==%20'undefined')%20%7B%0A%20%20%20%20%09var%20c%20=%20new%20Uint32Array(b);%0A%20%20%20%20%20%20%20%20%09var%20j%20=%200;%0A%20%20%20%20%20%20%20%20%09for%20(i%20=%20512+ol%20-%20((512+ol)%20&%20511);%20i%20%3C=%20nl;%20i+=%20512)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%09%20%20%20%20this._block(c.subarray(16%20*%20j,%2016%20*%20(j+1)));%0A%20%20%20%20%20%20%20%20%20%20%09%20%20%20%20j%20+=%201;%0A%20%20%20%20%20%20%20%20%09%7D%0A%20%20%20%20%20%20%20%20%09b.splice(0,%2016%20*%20j);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09for%20(i%20=%20512+ol%20-%20((512+ol)%20&%20511);%20i%20%3C=%20nl;%20i+=%20512)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%09%20%20%20%20this._block(b.splice(0,16));%0A%20%20%20%20%20%20%20%20%20%20%09%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20this;%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Complete%20hashing%20and%20output%20the%20hash%20value.%0A%20%20%20%20%20%20%20*%20@return%20%7BbitArray%7D%20The%20hash%20value,%20an%20array%20of%208%20big-endian%20words.%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20finalize:function%20()%20%7B%0A%20%20%20%20%20%20%20%20var%20i,%20b%20=%20this._buffer,%20h%20=%20this._h;%0A%0A%20%20%20%20%20%20%20%20//%20Round%20out%20and%20push%20the%20buffer%0A%20%20%20%20%20%20%20%20b%20=%20sjcl.bitArray.concat(b,%20%5Bsjcl.bitArray.partial(1,1)%5D);%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20//%20Round%20out%20the%20buffer%20to%20a%20multiple%20of%2016%20words,%20less%20the%202%20length%20words.%0A%20%20%20%20%20%20%20%20for%20(i%20=%20b.length%20+%202;%20i%20&%2015;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20b.push(0);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20//%20append%20the%20length%0A%20%20%20%20%20%20%20%20b.push(Math.floor(this._length%20/%200x100000000));%0A%20%20%20%20%20%20%20%20b.push(this._length%20%7C%200);%0A%0A%20%20%20%20%20%20%20%20while%20(b.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20this._block(b.splice(0,16));%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20this.reset();%0A%20%20%20%20%20%20%20%20return%20h;%0A%20%20%20%20%20%20%7D,%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20The%20SHA-256%20initialization%20vector,%20to%20be%20precomputed.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_init:%5B%5D,%0A%20%20%20%20%20%20/*%0A%20%20%20%20%20%20_init:%5B0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19%5D,%0A%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20The%20SHA-256%20hash%20key,%20to%20be%20precomputed.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_key:%5B%5D,%0A%20%20%20%20%20%20/*%0A%20%20%20%20%20%20_key:%0A%20%20%20%20%20%20%20%20%5B0x428a2f98,%200x71374491,%200xb5c0fbcf,%200xe9b5dba5,%200x3956c25b,%200x59f111f1,%200x923f82a4,%200xab1c5ed5,%0A%20%20%20%20%20%20%20%20%200xd807aa98,%200x12835b01,%200x243185be,%200x550c7dc3,%200x72be5d74,%200x80deb1fe,%200x9bdc06a7,%200xc19bf174,%0A%20%20%20%20%20%20%20%20%200xe49b69c1,%200xefbe4786,%200x0fc19dc6,%200x240ca1cc,%200x2de92c6f,%200x4a7484aa,%200x5cb0a9dc,%200x76f988da,%0A%20%20%20%20%20%20%20%20%200x983e5152,%200xa831c66d,%200xb00327c8,%200xbf597fc7,%200xc6e00bf3,%200xd5a79147,%200x06ca6351,%200x14292967,%0A%20%20%20%20%20%20%20%20%200x27b70a85,%200x2e1b2138,%200x4d2c6dfc,%200x53380d13,%200x650a7354,%200x766a0abb,%200x81c2c92e,%200x92722c85,%0A%20%20%20%20%20%20%20%20%200xa2bfe8a1,%200xa81a664b,%200xc24b8b70,%200xc76c51a3,%200xd192e819,%200xd6990624,%200xf40e3585,%200x106aa070,%0A%20%20%20%20%20%20%20%20%200x19a4c116,%200x1e376c08,%200x2748774c,%200x34b0bcb5,%200x391c0cb3,%200x4ed8aa4a,%200x5b9cca4f,%200x682e6ff3,%0A%20%20%20%20%20%20%20%20%200x748f82ee,%200x78a5636f,%200x84c87814,%200x8cc70208,%200x90befffa,%200xa4506ceb,%200xbef9a3f7,%200xc67178f2%5D,%0A%20%20%20%20%20%20*/%0A%0A%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Function%20to%20precompute%20_init%20and%20_key.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_precompute:%20function%20()%20%7B%0A%20%20%20%20%20%20%20%20var%20i%20=%200,%20prime%20=%202,%20factor,%20isPrime;%0A%0A%20%20%20%20%20%20%20%20function%20frac(x)%20%7B%20return%20(x-Math.floor(x))%20*%200x100000000%20%7C%200;%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20(;%20i%3C64;%20prime++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20isPrime%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20for%20(factor=2;%20factor*factor%20%3C=%20prime;%20factor++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(prime%20%25%20factor%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20isPrime%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20break;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20if%20(isPrime)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%3C8)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20this._init%5Bi%5D%20=%20frac(Math.pow(prime,%201/2));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this._key%5Bi%5D%20=%20frac(Math.pow(prime,%201/3));%0A%20%20%20%20%20%20%20%20%20%20%20%20i++;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20*%20Perform%20one%20cycle%20of%20SHA-256.%0A%20%20%20%20%20%20%20*%20@param%20%7BUint32Array%7CbitArray%7D%20w%20one%20block%20of%20words.%0A%20%20%20%20%20%20%20*%20@private%0A%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20_block:function%20(w)%20%7B%20%20%0A%20%20%20%20%20%20%20%20var%20i,%20tmp,%20a,%20b,%0A%20%20%20%20%20%20%20%20%20%20h%20=%20this._h,%0A%20%20%20%20%20%20%20%20%20%20k%20=%20this._key,%0A%20%20%20%20%20%20%20%20%20%20h0%20=%20h%5B0%5D,%20h1%20=%20h%5B1%5D,%20h2%20=%20h%5B2%5D,%20h3%20=%20h%5B3%5D,%0A%20%20%20%20%20%20%20%20%20%20h4%20=%20h%5B4%5D,%20h5%20=%20h%5B5%5D,%20h6%20=%20h%5B6%5D,%20h7%20=%20h%5B7%5D;%0A%0A%20%20%20%20%20%20%20%20/*%20Rationale%20for%20placement%20of%20%7C0%20:%0A%20%20%20%20%20%20%20%20%20*%20If%20a%20value%20can%20overflow%20is%20original%2032%20bits%20by%20a%20factor%20of%20more%20than%20a%20few%0A%20%20%20%20%20%20%20%20%20*%20million%20(2%5E23%20ish),%20there%20is%20a%20possibility%20that%20it%20might%20overflow%20the%0A%20%20%20%20%20%20%20%20%20*%2053-bit%20mantissa%20and%20lose%20precision.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20To%20avoid%20this,%20we%20clamp%20back%20to%2032%20bits%20by%20%7C'ing%20with%200%20on%20any%20value%20that%0A%20%20%20%20%20%20%20%20%20*%20propagates%20around%20the%20loop,%20and%20on%20the%20hash%20state%20h%5B%5D.%20%20I%20don't%20believe%0A%20%20%20%20%20%20%20%20%20*%20that%20the%20clamps%20on%20h4%20and%20on%20h0%20are%20strictly%20necessary,%20but%20it's%20close%0A%20%20%20%20%20%20%20%20%20*%20(for%20h4%20anyway),%20and%20better%20safe%20than%20sorry.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20The%20clamps%20on%20h%5B%5D%20are%20necessary%20for%20the%20output%20to%20be%20correct%20even%20in%20the%0A%20%20%20%20%20%20%20%20%20*%20common%20case%20and%20for%20short%20inputs.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20for%20(i=0;%20i%3C64;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20//%20load%20up%20the%20input%20word%20for%20this%20round%0A%20%20%20%20%20%20%20%20%20%20if%20(i%3C16)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%20w%5Bi%5D;%0A%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%20%20=%20w%5B(i+1%20)%20&%2015%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20b%20%20%20=%20w%5B(i+14)%20&%2015%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20tmp%20=%20w%5Bi&15%5D%20=%20((a%3E%3E%3E7%20%20%5E%20a%3E%3E%3E18%20%5E%20a%3E%3E%3E3%20%20%5E%20a%3C%3C25%20%5E%20a%3C%3C14)%20+%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(b%3E%3E%3E17%20%5E%20b%3E%3E%3E19%20%5E%20b%3E%3E%3E10%20%5E%20b%3C%3C15%20%5E%20b%3C%3C13)%20+%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w%5Bi&15%5D%20+%20w%5B(i+9)%20&%2015%5D)%20%7C%200;%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20tmp%20=%20(tmp%20+%20h7%20+%20(h4%3E%3E%3E6%20%5E%20h4%3E%3E%3E11%20%5E%20h4%3E%3E%3E25%20%5E%20h4%3C%3C26%20%5E%20h4%3C%3C21%20%5E%20h4%3C%3C7)%20+%20%20(h6%20%5E%20h4&(h5%5Eh6))%20+%20k%5Bi%5D);%20//%20%7C%200;%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20//%20shift%20register%0A%20%20%20%20%20%20%20%20%20%20h7%20=%20h6;%20h6%20=%20h5;%20h5%20=%20h4;%0A%20%20%20%20%20%20%20%20%20%20h4%20=%20h3%20+%20tmp%20%7C%200;%0A%20%20%20%20%20%20%20%20%20%20h3%20=%20h2;%20h2%20=%20h1;%20h1%20=%20h0;%0A%0A%20%20%20%20%20%20%20%20%20%20h0%20=%20(tmp%20+%20%20((h1&h2)%20%5E%20(h3&(h1%5Eh2)))%20+%20(h1%3E%3E%3E2%20%5E%20h1%3E%3E%3E13%20%5E%20h1%3E%3E%3E22%20%5E%20h1%3C%3C30%20%5E%20h1%3C%3C19%20%5E%20h1%3C%3C10))%20%7C%200;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20h%5B0%5D%20=%20h%5B0%5D+h0%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B1%5D%20=%20h%5B1%5D+h1%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B2%5D%20=%20h%5B2%5D+h2%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B3%5D%20=%20h%5B3%5D+h3%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B4%5D%20=%20h%5B4%5D+h4%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B5%5D%20=%20h%5B5%5D+h5%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B6%5D%20=%20h%5B6%5D+h6%20%7C%200;%0A%20%20%20%20%20%20%20%20h%5B7%5D%20=%20h%5B7%5D+h7%20%7C%200;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%0A%20%20%20%20/**%20@fileOverview%20HMAC%20implementation.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@author%20Emily%20Stark%0A%20%20%20%20%20*%20@author%20Mike%20Hamburg%0A%20%20%20%20%20*%20@author%20Dan%20Boneh%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%20HMAC%20with%20the%20specified%20hash%20function.%0A%20%20%20%20%20*%20@constructor%0A%20%20%20%20%20*%20@param%20%7BbitArray%7D%20key%20the%20key%20for%20HMAC.%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20%5BHash=sjcl.hash.sha256%5D%20The%20hash%20function%20to%20use.%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.misc.hmac%20=%20function%20(key,%20Hash)%20%7B%0A%20%20%20%20%20%20this._hash%20=%20Hash%20=%20Hash%20%7C%7C%20sjcl.hash.sha256;%0A%20%20%20%20%20%20var%20exKey%20=%20%5B%5B%5D,%5B%5D%5D,%20i,%0A%20%20%20%20%20%20%20%20%20%20bs%20=%20Hash.prototype.blockSize%20/%2032;%0A%20%20%20%20%20%20this._baseHash%20=%20%5Bnew%20Hash(),%20new%20Hash()%5D;%0A%0A%20%20%20%20%20%20if%20(key.length%20%3E%20bs)%20%7B%0A%20%20%20%20%20%20%20%20key%20=%20Hash.hash(key);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20for%20(i=0;%20i%3Cbs;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20exKey%5B0%5D%5Bi%5D%20=%20key%5Bi%5D%5E0x36363636;%0A%20%20%20%20%20%20%20%20exKey%5B1%5D%5Bi%5D%20=%20key%5Bi%5D%5E0x5C5C5C5C;%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20this._baseHash%5B0%5D.update(exKey%5B0%5D);%0A%20%20%20%20%20%20this._baseHash%5B1%5D.update(exKey%5B1%5D);%0A%20%20%20%20%20%20this._resultHash%20=%20new%20Hash(this._baseHash%5B0%5D);%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/**%20HMAC%20with%20the%20specified%20hash%20function.%20%20Also%20called%20encrypt%20since%20it's%20a%20prf.%0A%20%20%20%20%20*%20@param%20%7BbitArray%7CString%7D%20data%20The%20data%20to%20mac.%0A%20%20%20%20%20*/%0A%20%20%20%20sjcl.misc.hmac.prototype.encrypt%20=%20sjcl.misc.hmac.prototype.mac%20=%20function%20(data)%20%7B%0A%20%20%20%20%20%20if%20(!this._updated)%20%7B%0A%20%20%20%20%20%20%20%20this.update(data);%0A%20%20%20%20%20%20%20%20return%20this.digest(data);%0A%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20throw%20new%20sjcl.exception.invalid(%22encrypt%20on%20already%20updated%20hmac%20called!%22);%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.misc.hmac.prototype.reset%20=%20function%20()%20%7B%0A%20%20%20%20%20%20this._resultHash%20=%20new%20this._hash(this._baseHash%5B0%5D);%0A%20%20%20%20%20%20this._updated%20=%20false;%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.misc.hmac.prototype.update%20=%20function%20(data)%20%7B%0A%20%20%20%20%20%20this._updated%20=%20true;%0A%20%20%20%20%20%20this._resultHash.update(data);%0A%20%20%20%20%7D;%0A%0A%20%20%20%20sjcl.misc.hmac.prototype.digest%20=%20function%20()%20%7B%0A%20%20%20%20%20%20var%20w%20=%20this._resultHash.finalize(),%20result%20=%20new%20(this._hash)(this._baseHash%5B1%5D).update(w).finalize();%0A%0A%20%20%20%20%20%20this.reset();%0A%0A%20%20%20%20%20%20return%20result;%0A%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20return%20sjcl;%0A%20%20%20%20%20%20%7D)();%0A%0A%20%20%20%20function%20getDataKeySync%20(sessionKey,%20domainKey,%20inputData)%20%7B%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20new-cap%0A%20%20%20%20%20%20%20%20const%20hmac%20=%20new%20sjcl.misc.hmac(sjcl.codec.utf8String.toBits(sessionKey%20+%20domainKey),%20sjcl.hash.sha256);%0A%20%20%20%20%20%20%20%20return%20sjcl.codec.hex.fromBits(hmac.encrypt(inputData))%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingAudio%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20sessionKey,%20site%20%7D%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domainKey%20=%20site.domain;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureName%20=%20'fingerprinting-audio';%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20In%20place%20modify%20array%20data%20to%20remove%20fingerprinting%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20transformArrayData%20(channelData,%20domainKey,%20sessionKey,%20thisArg)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20%7B%20audioKey%20%7D%20=%20getCachedResponse(thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!audioKey)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20cdSum%20=%200;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20k%20in%20channelData)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cdSum%20+=%20channelData%5Bk%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20the%20buffer%20is%20blank,%20skip%20adding%20data%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cdSum%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20audioKey%20=%20getDataKeySync(sessionKey,%20domainKey,%20cdSum);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setCache(thisArg,%20args,%20audioKey);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20iterateDataKey(audioKey,%20(item,%20byte)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20itemAudioIndex%20=%20item%20%25%20channelData.length;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20factor%20=%20byte%20*%200.0000001;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(byte%20%5E%200x1)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20factor%20=%200%20-%20factor;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20channelData%5BitemAudioIndex%5D%20=%20channelData%5BitemAudioIndex%5D%20+%20factor;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20copyFromChannelProxy%20=%20new%20DDGProxy(featureName,%20AudioBuffer.prototype,%20'copyFromChannel',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%5Bsource,%20channelNumber,%20startInChannel%5D%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20This%20is%20implemented%20in%20a%20different%20way%20to%20canvas%20purely%20because%20calling%20the%20function%20copied%20the%20original%20value,%20which%20is%20not%20ideal%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(//%20If%20channelNumber%20is%20longer%20than%20arrayBuffer%20number%20of%20channels%20then%20call%20the%20default%20method%20to%20throw%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20channelNumber%20%3E%20thisArg.numberOfChannels%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20startInChannel%20is%20longer%20than%20the%20arrayBuffer%20length%20then%20call%20the%20default%20method%20to%20throw%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20startInChannel%20%3E%20thisArg.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20normal%20return%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Call%20the%20protected%20getChannelData%20we%20implement,%20slice%20from%20the%20startInChannel%20value%20and%20assign%20to%20the%20source%20array%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20thisArg.getChannelData(channelNumber).slice(startInChannel).forEach((val,%20index)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20source%5Bindex%5D%20=%20val;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20copyFromChannelProxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cacheExpiry%20=%2060;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cacheData%20=%20new%20WeakMap();%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20getCachedResponse%20(thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20data%20=%20cacheData.get(thisArg);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20timeNow%20=%20Date.now();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(data%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.args%20===%20JSON.stringify(args)%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.expires%20%3E%20timeNow)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.expires%20=%20timeNow%20+%20cacheExpiry;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cacheData.set(thisArg,%20data);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20data%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%7B%20audioKey:%20null%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20setCache%20(thisArg,%20args,%20audioKey)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cacheData.set(thisArg,%20%7B%20args:%20JSON.stringify(args),%20expires:%20Date.now()%20+%20cacheExpiry,%20audioKey%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20getChannelDataProxy%20=%20new%20DDGProxy(featureName,%20AudioBuffer.prototype,%20'getChannelData',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20normal%20return%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20channelData%20=%20DDGReflect.apply(target,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Anything%20we%20do%20here%20should%20be%20caught%20and%20ignored%20silently%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transformArrayData(channelData,%20domainKey,%20sessionKey,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20channelData%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20getChannelDataProxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20audioMethods%20=%20%5B'getByteTimeDomainData',%20'getFloatTimeDomainData',%20'getByteFrequencyData',%20'getFloatFrequencyData'%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20audioMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20AnalyserNode.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DDGReflect.apply(target,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Anything%20we%20do%20here%20should%20be%20caught%20and%20ignored%20silently%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transformArrayData(args%5B0%5D,%20domainKey,%20sessionKey,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Overwrites%20the%20Battery%20API%20if%20present%20in%20the%20browser.%0A%20%20%20%20%20*%20It%20will%20return%20the%20values%20defined%20in%20the%20getBattery%20function%20to%20the%20client,%0A%20%20%20%20%20*%20as%20well%20as%20prevent%20any%20script%20from%20listening%20to%20events.%0A%20%20%20%20%20*/%0A%20%20%20%20class%20FingerprintingBattery%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(globalThis.navigator.getBattery)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20BatteryManager%20=%20globalThis.BatteryManager;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20spoofedValues%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20charging:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20chargingTime:%200,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20dischargingTime:%20Infinity,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20level:%201%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20eventProperties%20=%20%5B'onchargingchange',%20'onchargingtimechange',%20'ondischargingtimechange',%20'onlevelchange'%5D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5Bprop,%20val%5D%20of%20Object.entries(spoofedValues))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(BatteryManager.prototype,%20prop,%20%7B%20get:%20()%20=%3E%20val%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20eventProp%20of%20eventProperties)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(BatteryManager.prototype,%20eventProp,%20%7B%20get:%20()%20=%3E%20null%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20var%20commonjsGlobal%20=%20typeof%20globalThis%20!==%20'undefined'%20?%20globalThis%20:%20typeof%20window%20!==%20'undefined'%20?%20window%20:%20typeof%20global%20!==%20'undefined'%20?%20global%20:%20typeof%20self%20!==%20'undefined'%20?%20self%20:%20%7B%7D;%0A%0A%20%20%20%20function%20getDefaultExportFromCjs%20(x)%20%7B%0A%20%20%20%20%09return%20x%20&&%20x.__esModule%20&&%20Object.prototype.hasOwnProperty.call(x,%20'default')%20?%20x%5B'default'%5D%20:%20x;%0A%20%20%20%20%7D%0A%0A%20%20%20%20var%20alea$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20alea$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20port%20of%20an%20algorithm%20by%20Johannes%20Baag%C3%B8e%20%3Cbaagoe@baagoe.com%3E,%202010%0A%20%20%20%20%09//%20http://baagoe.com/en/RandomMusings/javascript/%0A%20%20%20%20%09//%20https://github.com/nquinlan/better-random-numbers-for-javascript-mirror%0A%20%20%20%20%09//%20Original%20work%20is%20under%20MIT%20license%20-%0A%0A%20%20%20%20%09//%20Copyright%20(C)%202010%20by%20Johannes%20Baag%C3%B8e%20%3Cbaagoe@baagoe.org%3E%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20Permission%20is%20hereby%20granted,%20free%20of%20charge,%20to%20any%20person%20obtaining%20a%20copy%0A%20%20%20%20%09//%20of%20this%20software%20and%20associated%20documentation%20files%20(the%20%22Software%22),%20to%20deal%0A%20%20%20%20%09//%20in%20the%20Software%20without%20restriction,%20including%20without%20limitation%20the%20rights%0A%20%20%20%20%09//%20to%20use,%20copy,%20modify,%20merge,%20publish,%20distribute,%20sublicense,%20and/or%20sell%0A%20%20%20%20%09//%20copies%20of%20the%20Software,%20and%20to%20permit%20persons%20to%20whom%20the%20Software%20is%0A%20%20%20%20%09//%20furnished%20to%20do%20so,%20subject%20to%20the%20following%20conditions:%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20The%20above%20copyright%20notice%20and%20this%20permission%20notice%20shall%20be%20included%20in%0A%20%20%20%20%09//%20all%20copies%20or%20substantial%20portions%20of%20the%20Software.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20THE%20SOFTWARE%20IS%20PROVIDED%20%22AS%20IS%22,%20WITHOUT%20WARRANTY%20OF%20ANY%20KIND,%20EXPRESS%20OR%0A%20%20%20%20%09//%20IMPLIED,%20INCLUDING%20BUT%20NOT%20LIMITED%20TO%20THE%20WARRANTIES%20OF%20MERCHANTABILITY,%0A%20%20%20%20%09//%20FITNESS%20FOR%20A%20PARTICULAR%20PURPOSE%20AND%20NONINFRINGEMENT.%20IN%20NO%20EVENT%20SHALL%20THE%0A%20%20%20%20%09//%20AUTHORS%20OR%20COPYRIGHT%20HOLDERS%20BE%20LIABLE%20FOR%20ANY%20CLAIM,%20DAMAGES%20OR%20OTHER%0A%20%20%20%20%09//%20LIABILITY,%20WHETHER%20IN%20AN%20ACTION%20OF%20CONTRACT,%20TORT%20OR%20OTHERWISE,%20ARISING%20FROM,%0A%20%20%20%20%09//%20OUT%20OF%20OR%20IN%20CONNECTION%20WITH%20THE%20SOFTWARE%20OR%20THE%20USE%20OR%20OTHER%20DEALINGS%20IN%0A%20%20%20%20%09//%20THE%20SOFTWARE.%0A%0A%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20Alea(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20mash%20=%20Mash();%0A%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t%20=%202091639%20*%20me.s0%20+%20me.c%20*%202.3283064365386963e-10;%20//%202%5E-32%0A%20%20%20%20%09%20%20%20%20me.s0%20=%20me.s1;%0A%20%20%20%20%09%20%20%20%20me.s1%20=%20me.s2;%0A%20%20%20%20%09%20%20%20%20return%20me.s2%20=%20t%20-%20(me.c%20=%20t%20%7C%200);%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20//%20Apply%20the%20seeding%20algorithm%20from%20Baagoe.%0A%20%20%20%20%09%20%20me.c%20=%201;%0A%20%20%20%20%09%20%20me.s0%20=%20mash('%20');%0A%20%20%20%20%09%20%20me.s1%20=%20mash('%20');%0A%20%20%20%20%09%20%20me.s2%20=%20mash('%20');%0A%20%20%20%20%09%20%20me.s0%20-=%20mash(seed);%0A%20%20%20%20%09%20%20if%20(me.s0%20%3C%200)%20%7B%20me.s0%20+=%201;%20%7D%0A%20%20%20%20%09%20%20me.s1%20-=%20mash(seed);%0A%20%20%20%20%09%20%20if%20(me.s1%20%3C%200)%20%7B%20me.s1%20+=%201;%20%7D%0A%20%20%20%20%09%20%20me.s2%20-=%20mash(seed);%0A%20%20%20%20%09%20%20if%20(me.s2%20%3C%200)%20%7B%20me.s2%20+=%201;%20%7D%0A%20%20%20%20%09%20%20mash%20=%20null;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.c%20=%20f.c;%0A%20%20%20%20%09%20%20t.s0%20=%20f.s0;%0A%20%20%20%20%09%20%20t.s1%20=%20f.s1;%0A%20%20%20%20%09%20%20t.s2%20=%20f.s2;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20Alea(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.int32%20=%20function()%20%7B%20return%20(xg.next()%20*%200x100000000)%20%7C%200;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20return%20prng()%20+%20(prng()%20*%200x200000%20%7C%200)%20*%201.1102230246251565e-16;%20//%202%5E-53%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20Mash()%20%7B%0A%20%20%20%20%09%20%20var%20n%20=%200xefc8249d;%0A%0A%20%20%20%20%09%20%20var%20mash%20=%20function(data)%20%7B%0A%20%20%20%20%09%20%20%20%20data%20=%20String(data);%0A%20%20%20%20%09%20%20%20%20for%20(var%20i%20=%200;%20i%20%3C%20data.length;%20i++)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20n%20+=%20data.charCodeAt(i);%0A%20%20%20%20%09%20%20%20%20%20%20var%20h%20=%200.02519603282416938%20*%20n;%0A%20%20%20%20%09%20%20%20%20%20%20n%20=%20h%20%3E%3E%3E%200;%0A%20%20%20%20%09%20%20%20%20%20%20h%20-=%20n;%0A%20%20%20%20%09%20%20%20%20%20%20h%20*=%20n;%0A%20%20%20%20%09%20%20%20%20%20%20n%20=%20h%20%3E%3E%3E%200;%0A%20%20%20%20%09%20%20%20%20%20%20h%20-=%20n;%0A%20%20%20%20%09%20%20%20%20%20%20n%20+=%20h%20*%200x100000000;%20//%202%5E32%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20return%20(n%20%3E%3E%3E%200)%20*%202.3283064365386963e-10;%20//%202%5E-32%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20return%20mash;%0A%20%20%20%20%09%7D%0A%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.alea%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(alea$1));%0A%0A%20%20%20%20var%20aleaExports%20=%20alea$1.exports;%0A%0A%20%20%20%20var%20xor128$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xor128$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22xor128%22%20prng%20algorithm%20by%0A%20%20%20%20%09//%20George%20Marsaglia.%20%20See%20http://www.jstatsoft.org/v08/i14/paper%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20strseed%20=%20'';%0A%0A%20%20%20%20%09%20%20me.x%20=%200;%0A%20%20%20%20%09%20%20me.y%20=%200;%0A%20%20%20%20%09%20%20me.z%20=%200;%0A%20%20%20%20%09%20%20me.w%20=%200;%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t%20=%20me.x%20%5E%20(me.x%20%3C%3C%2011);%0A%20%20%20%20%09%20%20%20%20me.x%20=%20me.y;%0A%20%20%20%20%09%20%20%20%20me.y%20=%20me.z;%0A%20%20%20%20%09%20%20%20%20me.z%20=%20me.w;%0A%20%20%20%20%09%20%20%20%20return%20me.w%20%5E=%20(me.w%20%3E%3E%3E%2019)%20%5E%20t%20%5E%20(t%20%3E%3E%3E%208);%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Integer%20seed.%0A%20%20%20%20%09%20%20%20%20me.x%20=%20seed;%0A%20%20%20%20%09%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20//%20String%20seed.%0A%20%20%20%20%09%20%20%20%20strseed%20+=%20seed;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20Mix%20in%20string%20seed,%20then%20discard%20an%20initial%20batch%20of%2064%20values.%0A%20%20%20%20%09%20%20for%20(var%20k%20=%200;%20k%20%3C%20strseed.length%20+%2064;%20k++)%20%7B%0A%20%20%20%20%09%20%20%20%20me.x%20%5E=%20strseed.charCodeAt(k)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.x%20=%20f.x;%0A%20%20%20%20%09%20%20t.y%20=%20f.y;%0A%20%20%20%20%09%20%20t.z%20=%20f.z;%0A%20%20%20%20%09%20%20t.w%20=%20f.w;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xor128%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xor128$1));%0A%0A%20%20%20%20var%20xor128Exports%20=%20xor128$1.exports;%0A%0A%20%20%20%20var%20xorwow$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xorwow$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22xorwow%22%20prng%20algorithm%20by%0A%20%20%20%20%09//%20George%20Marsaglia.%20%20See%20http://www.jstatsoft.org/v08/i14/paper%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20strseed%20=%20'';%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t%20=%20(me.x%20%5E%20(me.x%20%3E%3E%3E%202));%0A%20%20%20%20%09%20%20%20%20me.x%20=%20me.y;%20me.y%20=%20me.z;%20me.z%20=%20me.w;%20me.w%20=%20me.v;%0A%20%20%20%20%09%20%20%20%20return%20(me.d%20=%20(me.d%20+%20362437%20%7C%200))%20+%0A%20%20%20%20%09%20%20%20%20%20%20%20(me.v%20=%20(me.v%20%5E%20(me.v%20%3C%3C%204))%20%5E%20(t%20%5E%20(t%20%3C%3C%201)))%20%7C%200;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20me.x%20=%200;%0A%20%20%20%20%09%20%20me.y%20=%200;%0A%20%20%20%20%09%20%20me.z%20=%200;%0A%20%20%20%20%09%20%20me.w%20=%200;%0A%20%20%20%20%09%20%20me.v%20=%200;%0A%0A%20%20%20%20%09%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Integer%20seed.%0A%20%20%20%20%09%20%20%20%20me.x%20=%20seed;%0A%20%20%20%20%09%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20//%20String%20seed.%0A%20%20%20%20%09%20%20%20%20strseed%20+=%20seed;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20Mix%20in%20string%20seed,%20then%20discard%20an%20initial%20batch%20of%2064%20values.%0A%20%20%20%20%09%20%20for%20(var%20k%20=%200;%20k%20%3C%20strseed.length%20+%2064;%20k++)%20%7B%0A%20%20%20%20%09%20%20%20%20me.x%20%5E=%20strseed.charCodeAt(k)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20if%20(k%20==%20strseed.length)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20me.d%20=%20me.x%20%3C%3C%2010%20%5E%20me.x%20%3E%3E%3E%204;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.x%20=%20f.x;%0A%20%20%20%20%09%20%20t.y%20=%20f.y;%0A%20%20%20%20%09%20%20t.z%20=%20f.z;%0A%20%20%20%20%09%20%20t.w%20=%20f.w;%0A%20%20%20%20%09%20%20t.v%20=%20f.v;%0A%20%20%20%20%09%20%20t.d%20=%20f.d;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xorwow%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xorwow$1));%0A%0A%20%20%20%20var%20xorwowExports%20=%20xorwow$1.exports;%0A%0A%20%20%20%20var%20xorshift7$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xorshift7$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22xorshift7%22%20algorithm%20by%0A%20%20%20%20%09//%20Fran%C3%A7ois%20Panneton%20and%20Pierre%20L'ecuyer:%0A%20%20%20%20%09//%20%22On%20the%20Xorgshift%20Random%20Number%20Generators%22%0A%20%20%20%20%09//%20http://saluc.engr.uconn.edu/refs/crypto/rng/panneton05onthexorshift.pdf%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this;%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Update%20xor%20generator.%0A%20%20%20%20%09%20%20%20%20var%20X%20=%20me.x,%20i%20=%20me.i,%20t,%20v;%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5Bi%5D;%20t%20%5E=%20(t%20%3E%3E%3E%207);%20v%20=%20t%20%5E%20(t%20%3C%3C%2024);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%201)%20&%207%5D;%20v%20%5E=%20t%20%5E%20(t%20%3E%3E%3E%2010);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%203)%20&%207%5D;%20v%20%5E=%20t%20%5E%20(t%20%3E%3E%3E%203);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%204)%20&%207%5D;%20v%20%5E=%20t%20%5E%20(t%20%3C%3C%207);%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5B(i%20+%207)%20&%207%5D;%20t%20=%20t%20%5E%20(t%20%3C%3C%2013);%20v%20%5E=%20t%20%5E%20(t%20%3C%3C%209);%0A%20%20%20%20%09%20%20%20%20X%5Bi%5D%20=%20v;%0A%20%20%20%20%09%20%20%20%20me.i%20=%20(i%20+%201)%20&%207;%0A%20%20%20%20%09%20%20%20%20return%20v;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20function%20init(me,%20seed)%20%7B%0A%20%20%20%20%09%20%20%20%20var%20j,%20X%20=%20%5B%5D;%0A%0A%20%20%20%20%09%20%20%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Seed%20state%20array%20using%20a%2032-bit%20integer.%0A%20%20%20%20%09%20%20%20%20%20%20X%5B0%5D%20=%20seed;%0A%20%20%20%20%09%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Seed%20state%20using%20a%20string.%0A%20%20%20%20%09%20%20%20%20%20%20seed%20=%20''%20+%20seed;%0A%20%20%20%20%09%20%20%20%20%20%20for%20(j%20=%200;%20j%20%3C%20seed.length;%20++j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20X%5Bj%20&%207%5D%20=%20(X%5Bj%20&%207%5D%20%3C%3C%2015)%20%5E%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20%20%20(seed.charCodeAt(j)%20+%20X%5B(j%20+%201)%20&%207%5D%20%3C%3C%2013);%0A%20%20%20%20%09%20%20%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Enforce%20an%20array%20length%20of%208,%20not%20all%20zeroes.%0A%20%20%20%20%09%20%20%20%20while%20(X.length%20%3C%208)%20X.push(0);%0A%20%20%20%20%09%20%20%20%20for%20(j%20=%200;%20j%20%3C%208%20&&%20X%5Bj%5D%20===%200;%20++j);%0A%20%20%20%20%09%20%20%20%20if%20(j%20==%208)%20X%5B7%5D%20=%20-1;%20else%20X%5Bj%5D;%0A%0A%20%20%20%20%09%20%20%20%20me.x%20=%20X;%0A%20%20%20%20%09%20%20%20%20me.i%20=%200;%0A%0A%20%20%20%20%09%20%20%20%20//%20Discard%20an%20initial%20256%20values.%0A%20%20%20%20%09%20%20%20%20for%20(j%20=%20256;%20j%20%3E%200;%20--j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20init(me,%20seed);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.x%20=%20f.x.slice();%0A%20%20%20%20%09%20%20t.i%20=%20f.i;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20if%20(seed%20==%20null)%20seed%20=%20+(new%20Date);%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(state.x)%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xorshift7%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xorshift7$1));%0A%0A%20%20%20%20var%20xorshift7Exports%20=%20xorshift7$1.exports;%0A%0A%20%20%20%20var%20xor4096$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20xor4096$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20Richard%20Brent's%20Xorgens%20xor4096%20algorithm.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20This%20fast%20non-cryptographic%20random%20number%20generator%20is%20designed%20for%0A%20%20%20%20%09//%20use%20in%20Monte-Carlo%20algorithms.%20It%20combines%20a%20long-period%20xorshift%0A%20%20%20%20%09//%20generator%20with%20a%20Weyl%20generator,%20and%20it%20passes%20all%20common%20batteries%0A%20%20%20%20%09//%20of%20stasticial%20tests%20for%20randomness%20while%20consuming%20only%20a%20few%20nanoseconds%0A%20%20%20%20%09//%20for%20each%20prng%20generated.%20%20For%20background%20on%20the%20generator,%20see%20Brent's%0A%20%20%20%20%09//%20paper:%20%22Some%20long-period%20random%20number%20generators%20using%20shifts%20and%20xors.%22%0A%20%20%20%20%09//%20http://arxiv.org/pdf/1004.3115v1.pdf%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20Usage:%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20var%20xor4096%20=%20require('xor4096');%0A%20%20%20%20%09//%20random%20=%20xor4096(1);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Seed%20with%20int32%20or%20string.%0A%20%20%20%20%09//%20assert.equal(random(),%200.1520436450538547);%20//%20(0,%201)%20range,%2053%20bits.%0A%20%20%20%20%09//%20assert.equal(random.int32(),%201806534897);%20%20%20//%20signed%20int32,%2032%20bits.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20For%20nonzero%20numeric%20keys,%20this%20impelementation%20provides%20a%20sequence%0A%20%20%20%20%09//%20identical%20to%20that%20by%20Brent's%20xorgens%203%20implementaion%20in%20C.%20%20This%0A%20%20%20%20%09//%20implementation%20also%20provides%20for%20initalizing%20the%20generator%20with%0A%20%20%20%20%09//%20string%20seeds,%20or%20for%20saving%20and%20restoring%20the%20state%20of%20the%20generator.%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20On%20Chrome,%20this%20prng%20benchmarks%20about%202.1%20times%20slower%20than%0A%20%20%20%20%09//%20Javascript's%20built-in%20Math.random().%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this;%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20w%20=%20me.w,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20X%20=%20me.X,%20i%20=%20me.i,%20t,%20v;%0A%20%20%20%20%09%20%20%20%20//%20Update%20Weyl%20generator.%0A%20%20%20%20%09%20%20%20%20me.w%20=%20w%20=%20(w%20+%200x61c88647)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20//%20Update%20xor%20generator.%0A%20%20%20%20%09%20%20%20%20v%20=%20X%5B(i%20+%2034)%20&%20127%5D;%0A%20%20%20%20%09%20%20%20%20t%20=%20X%5Bi%20=%20((i%20+%201)%20&%20127)%5D;%0A%20%20%20%20%09%20%20%20%20v%20%5E=%20v%20%3C%3C%2013;%0A%20%20%20%20%09%20%20%20%20t%20%5E=%20t%20%3C%3C%2017;%0A%20%20%20%20%09%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2015;%0A%20%20%20%20%09%20%20%20%20t%20%5E=%20t%20%3E%3E%3E%2012;%0A%20%20%20%20%09%20%20%20%20//%20Update%20Xor%20generator%20array%20state.%0A%20%20%20%20%09%20%20%20%20v%20=%20X%5Bi%5D%20=%20v%20%5E%20t;%0A%20%20%20%20%09%20%20%20%20me.i%20=%20i;%0A%20%20%20%20%09%20%20%20%20//%20Result%20is%20the%20combination.%0A%20%20%20%20%09%20%20%20%20return%20(v%20+%20(w%20%5E%20(w%20%3E%3E%3E%2016)))%20%7C%200;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20function%20init(me,%20seed)%20%7B%0A%20%20%20%20%09%20%20%20%20var%20t,%20v,%20i,%20j,%20w,%20X%20=%20%5B%5D,%20limit%20=%20128;%0A%20%20%20%20%09%20%20%20%20if%20(seed%20===%20(seed%20%7C%200))%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Numeric%20seeds%20initialize%20v,%20which%20is%20used%20to%20generates%20X.%0A%20%20%20%20%09%20%20%20%20%20%20v%20=%20seed;%0A%20%20%20%20%09%20%20%20%20%20%20seed%20=%20null;%0A%20%20%20%20%09%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20String%20seeds%20are%20mixed%20into%20v%20and%20X%20one%20character%20at%20a%20time.%0A%20%20%20%20%09%20%20%20%20%20%20seed%20=%20seed%20+%20'%5C0';%0A%20%20%20%20%09%20%20%20%20%20%20v%20=%200;%0A%20%20%20%20%09%20%20%20%20%20%20limit%20=%20Math.max(limit,%20seed.length);%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Initialize%20circular%20array%20and%20weyl%20value.%0A%20%20%20%20%09%20%20%20%20for%20(i%20=%200,%20j%20=%20-32;%20j%20%3C%20limit;%20++j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20Put%20the%20unicode%20characters%20into%20the%20array,%20and%20shuffle%20them.%0A%20%20%20%20%09%20%20%20%20%20%20if%20(seed)%20v%20%5E=%20seed.charCodeAt((j%20+%2032)%20%25%20seed.length);%0A%20%20%20%20%09%20%20%20%20%20%20//%20After%2032%20shuffles,%20take%20v%20as%20the%20starting%20w%20value.%0A%20%20%20%20%09%20%20%20%20%20%20if%20(j%20===%200)%20w%20=%20v;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3C%3C%2010;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2015;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3C%3C%204;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2013;%0A%20%20%20%20%09%20%20%20%20%20%20if%20(j%20%3E=%200)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20w%20=%20(w%20+%200x61c88647)%20%7C%200;%20%20%20%20%20//%20Weyl.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20t%20=%20(X%5Bj%20&%20127%5D%20%5E=%20(v%20+%20w));%20%20//%20Combine%20xor%20and%20weyl%20to%20init%20array.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20i%20=%20(0%20==%20t)%20?%20i%20+%201%20:%200;%20%20%20%20%20//%20Count%20zeroes.%0A%20%20%20%20%09%20%20%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20We%20have%20detected%20all%20zeroes;%20make%20the%20key%20nonzero.%0A%20%20%20%20%09%20%20%20%20if%20(i%20%3E=%20128)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20X%5B(seed%20&&%20seed.length%20%7C%7C%200)%20&%20127%5D%20=%20-1;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Run%20the%20generator%20512%20times%20to%20further%20mix%20the%20state%20before%20using%20it.%0A%20%20%20%20%09%20%20%20%20//%20Factoring%20this%20as%20a%20function%20slows%20the%20main%20generator,%20so%20it%20is%20just%0A%20%20%20%20%09%20%20%20%20//%20unrolled%20here.%20%20The%20weyl%20generator%20is%20not%20advanced%20while%20warming%20up.%0A%20%20%20%20%09%20%20%20%20i%20=%20127;%0A%20%20%20%20%09%20%20%20%20for%20(j%20=%204%20*%20128;%20j%20%3E%200;%20--j)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20v%20=%20X%5B(i%20+%2034)%20&%20127%5D;%0A%20%20%20%20%09%20%20%20%20%20%20t%20=%20X%5Bi%20=%20((i%20+%201)%20&%20127)%5D;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3C%3C%2013;%0A%20%20%20%20%09%20%20%20%20%20%20t%20%5E=%20t%20%3C%3C%2017;%0A%20%20%20%20%09%20%20%20%20%20%20v%20%5E=%20v%20%3E%3E%3E%2015;%0A%20%20%20%20%09%20%20%20%20%20%20t%20%5E=%20t%20%3E%3E%3E%2012;%0A%20%20%20%20%09%20%20%20%20%20%20X%5Bi%5D%20=%20v%20%5E%20t;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20//%20Storing%20state%20as%20object%20members%20is%20faster%20than%20using%20closure%20variables.%0A%20%20%20%20%09%20%20%20%20me.w%20=%20w;%0A%20%20%20%20%09%20%20%20%20me.X%20=%20X;%0A%20%20%20%20%09%20%20%20%20me.i%20=%20i;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20init(me,%20seed);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.i%20=%20f.i;%0A%20%20%20%20%09%20%20t.w%20=%20f.w;%0A%20%20%20%20%09%20%20t.X%20=%20f.X.slice();%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20if%20(seed%20==%20null)%20seed%20=%20+(new%20Date);%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(state.X)%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.xor4096%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20window%20object%20or%20global%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(xor4096$1));%0A%0A%20%20%20%20var%20xor4096Exports%20=%20xor4096$1.exports;%0A%0A%20%20%20%20var%20tychei$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20tychei$1.exports;%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09//%20A%20Javascript%20implementaion%20of%20the%20%22Tyche-i%22%20prng%20algorithm%20by%0A%20%20%20%20%09//%20Samuel%20Neves%20and%20Filipe%20Araujo.%0A%20%20%20%20%09//%20See%20https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf%0A%0A%20%20%20%20%09(function(global,%20module,%20define)%20%7B%0A%0A%20%20%20%20%09function%20XorGen(seed)%20%7B%0A%20%20%20%20%09%20%20var%20me%20=%20this,%20strseed%20=%20'';%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20generator%20function.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20b%20=%20me.b,%20c%20=%20me.c,%20d%20=%20me.d,%20a%20=%20me.a;%0A%20%20%20%20%09%20%20%20%20b%20=%20(b%20%3C%3C%2025)%20%5E%20(b%20%3E%3E%3E%207)%20%5E%20c;%0A%20%20%20%20%09%20%20%20%20c%20=%20(c%20-%20d)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20d%20=%20(d%20%3C%3C%2024)%20%5E%20(d%20%3E%3E%3E%208)%20%5E%20a;%0A%20%20%20%20%09%20%20%20%20a%20=%20(a%20-%20b)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.b%20=%20b%20=%20(b%20%3C%3C%2020)%20%5E%20(b%20%3E%3E%3E%2012)%20%5E%20c;%0A%20%20%20%20%09%20%20%20%20me.c%20=%20c%20=%20(c%20-%20d)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.d%20=%20(d%20%3C%3C%2016)%20%5E%20(c%20%3E%3E%3E%2016)%20%5E%20a;%0A%20%20%20%20%09%20%20%20%20return%20me.a%20=%20(a%20-%20b)%20%7C%200;%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20/*%20The%20following%20is%20non-inverted%20tyche,%20which%20has%20better%20internal%0A%20%20%20%20%09%20%20%20*%20bit%20diffusion,%20but%20which%20is%20about%2025%25%20slower%20than%20tyche-i%20in%20JS.%0A%20%20%20%20%09%20%20me.next%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20a%20=%20me.a,%20b%20=%20me.b,%20c%20=%20me.c,%20d%20=%20me.d;%0A%20%20%20%20%09%20%20%20%20a%20=%20(me.a%20+%20me.b%20%7C%200)%20%3E%3E%3E%200;%0A%20%20%20%20%09%20%20%20%20d%20=%20me.d%20%5E%20a;%20d%20=%20d%20%3C%3C%2016%20%5E%20d%20%3E%3E%3E%2016;%0A%20%20%20%20%09%20%20%20%20c%20=%20me.c%20+%20d%20%7C%200;%0A%20%20%20%20%09%20%20%20%20b%20=%20me.b%20%5E%20c;%20b%20=%20b%20%3C%3C%2012%20%5E%20d%20%3E%3E%3E%2020;%0A%20%20%20%20%09%20%20%20%20me.a%20=%20a%20=%20a%20+%20b%20%7C%200;%0A%20%20%20%20%09%20%20%20%20d%20=%20d%20%5E%20a;%20me.d%20=%20d%20=%20d%20%3C%3C%208%20%5E%20d%20%3E%3E%3E%2024;%0A%20%20%20%20%09%20%20%20%20me.c%20=%20c%20=%20c%20+%20d%20%7C%200;%0A%20%20%20%20%09%20%20%20%20b%20=%20b%20%5E%20c;%0A%20%20%20%20%09%20%20%20%20return%20me.b%20=%20(b%20%3C%3C%207%20%5E%20b%20%3E%3E%3E%2025);%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20*/%0A%0A%20%20%20%20%09%20%20me.a%20=%200;%0A%20%20%20%20%09%20%20me.b%20=%200;%0A%20%20%20%20%09%20%20me.c%20=%202654435769%20%7C%200;%0A%20%20%20%20%09%20%20me.d%20=%201367130551;%0A%0A%20%20%20%20%09%20%20if%20(seed%20===%20Math.floor(seed))%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Integer%20seed.%0A%20%20%20%20%09%20%20%20%20me.a%20=%20(seed%20/%200x100000000)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.b%20=%20seed%20%7C%200;%0A%20%20%20%20%09%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20//%20String%20seed.%0A%20%20%20%20%09%20%20%20%20strseed%20+=%20seed;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20Mix%20in%20string%20seed,%20then%20discard%20an%20initial%20batch%20of%2064%20values.%0A%20%20%20%20%09%20%20for%20(var%20k%20=%200;%20k%20%3C%20strseed.length%20+%2020;%20k++)%20%7B%0A%20%20%20%20%09%20%20%20%20me.b%20%5E=%20strseed.charCodeAt(k)%20%7C%200;%0A%20%20%20%20%09%20%20%20%20me.next();%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.a%20=%20f.a;%0A%20%20%20%20%09%20%20t.b%20=%20f.b;%0A%20%20%20%20%09%20%20t.c%20=%20f.c;%0A%20%20%20%20%09%20%20t.d%20=%20f.d;%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%20%20%20%20%09function%20impl(seed,%20opts)%20%7B%0A%20%20%20%20%09%20%20var%20xg%20=%20new%20XorGen(seed),%0A%20%20%20%20%09%20%20%20%20%20%20state%20=%20opts%20&&%20opts.state,%0A%20%20%20%20%09%20%20%20%20%20%20prng%20=%20function()%20%7B%20return%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20do%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20var%20top%20=%20xg.next()%20%3E%3E%3E%2011,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20bot%20=%20(xg.next()%20%3E%3E%3E%200)%20/%200x100000000,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20result%20=%20(top%20+%20bot)%20/%20(1%20%3C%3C%2021);%0A%20%20%20%20%09%20%20%20%20%7D%20while%20(result%20===%200);%0A%20%20%20%20%09%20%20%20%20return%20result;%0A%20%20%20%20%09%20%20%7D;%0A%20%20%20%20%09%20%20prng.int32%20=%20xg.next;%0A%20%20%20%20%09%20%20prng.quick%20=%20prng;%0A%20%20%20%20%09%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20if%20(typeof(state)%20==%20'object')%20copy(state,%20xg);%0A%20%20%20%20%09%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(xg,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20prng;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09if%20(module%20&&%20module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20impl;%0A%20%20%20%20%09%7D%20else%20if%20(define%20&&%20define.amd)%20%7B%0A%20%20%20%20%09%20%20define(function()%20%7B%20return%20impl;%20%7D);%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20this.tychei%20=%20impl;%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20commonjsGlobal,%0A%20%20%20%20%09%20%20module,%20%20%20%20//%20present%20in%20node.js%0A%20%20%20%20%09%20%20(typeof%20undefined)%20==%20'function'%20%20%20%20//%20present%20with%20an%20AMD%20loader%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(tychei$1));%0A%0A%20%20%20%20var%20tycheiExports%20=%20tychei$1.exports;%0A%0A%20%20%20%20var%20seedrandom$1%20=%20%7Bexports:%20%7B%7D%7D;%0A%0A%20%20%20%20/*%0A%20%20%20%20Copyright%202019%20David%20Bau.%0A%0A%20%20%20%20Permission%20is%20hereby%20granted,%20free%20of%20charge,%20to%20any%20person%20obtaining%0A%20%20%20%20a%20copy%20of%20this%20software%20and%20associated%20documentation%20files%20(the%0A%20%20%20%20%22Software%22),%20to%20deal%20in%20the%20Software%20without%20restriction,%20including%0A%20%20%20%20without%20limitation%20the%20rights%20to%20use,%20copy,%20modify,%20merge,%20publish,%0A%20%20%20%20distribute,%20sublicense,%20and/or%20sell%20copies%20of%20the%20Software,%20and%20to%0A%20%20%20%20permit%20persons%20to%20whom%20the%20Software%20is%20furnished%20to%20do%20so,%20subject%20to%0A%20%20%20%20the%20following%20conditions:%0A%0A%20%20%20%20The%20above%20copyright%20notice%20and%20this%20permission%20notice%20shall%20be%0A%20%20%20%20included%20in%20all%20copies%20or%20substantial%20portions%20of%20the%20Software.%0A%0A%20%20%20%20THE%20SOFTWARE%20IS%20PROVIDED%20%22AS%20IS%22,%20WITHOUT%20WARRANTY%20OF%20ANY%20KIND,%0A%20%20%20%20EXPRESS%20OR%20IMPLIED,%20INCLUDING%20BUT%20NOT%20LIMITED%20TO%20THE%20WARRANTIES%20OF%0A%20%20%20%20MERCHANTABILITY,%20FITNESS%20FOR%20A%20PARTICULAR%20PURPOSE%20AND%20NONINFRINGEMENT.%0A%20%20%20%20IN%20NO%20EVENT%20SHALL%20THE%20AUTHORS%20OR%20COPYRIGHT%20HOLDERS%20BE%20LIABLE%20FOR%20ANY%0A%20%20%20%20CLAIM,%20DAMAGES%20OR%20OTHER%20LIABILITY,%20WHETHER%20IN%20AN%20ACTION%20OF%20CONTRACT,%0A%20%20%20%20TORT%20OR%20OTHERWISE,%20ARISING%20FROM,%20OUT%20OF%20OR%20IN%20CONNECTION%20WITH%20THE%0A%20%20%20%20SOFTWARE%20OR%20THE%20USE%20OR%20OTHER%20DEALINGS%20IN%20THE%20SOFTWARE.%0A%0A%20%20%20%20*/%0A%0A%20%20%20%20(function%20(module)%20%7B%0A%20%20%20%20%09(function%20(global,%20pool,%20math)%20%7B%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20The%20following%20constants%20are%20related%20to%20IEEE%20754%20limits.%0A%20%20%20%20%09//%0A%0A%20%20%20%20%09var%20width%20=%20256,%20%20%20%20%20%20%20%20//%20each%20RC4%20output%20is%200%20%3C=%20x%20%3C%20256%0A%20%20%20%20%09%20%20%20%20chunks%20=%206,%20%20%20%20%20%20%20%20%20//%20at%20least%20six%20RC4%20outputs%20for%20each%20double%0A%20%20%20%20%09%20%20%20%20digits%20=%2052,%20%20%20%20%20%20%20%20//%20there%20are%2052%20significant%20digits%20in%20a%20double%0A%20%20%20%20%09%20%20%20%20rngname%20=%20'random',%20//%20rngname:%20name%20for%20Math.random%20and%20Math.seedrandom%0A%20%20%20%20%09%20%20%20%20startdenom%20=%20math.pow(width,%20chunks),%0A%20%20%20%20%09%20%20%20%20significance%20=%20math.pow(2,%20digits),%0A%20%20%20%20%09%20%20%20%20overflow%20=%20significance%20*%202,%0A%20%20%20%20%09%20%20%20%20mask%20=%20width%20-%201,%0A%20%20%20%20%09%20%20%20%20nodecrypto;%20%20%20%20%20%20%20%20%20//%20node.js%20crypto%20module,%20initialized%20at%20the%20bottom.%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20seedrandom()%0A%20%20%20%20%09//%20This%20is%20the%20seedrandom%20function%20described%20above.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20seedrandom(seed,%20options,%20callback)%20%7B%0A%20%20%20%20%09%20%20var%20key%20=%20%5B%5D;%0A%20%20%20%20%09%20%20options%20=%20(options%20==%20true)%20?%20%7B%20entropy:%20true%20%7D%20:%20(options%20%7C%7C%20%7B%7D);%0A%0A%20%20%20%20%09%20%20//%20Flatten%20the%20seed%20string%20or%20build%20one%20from%20local%20entropy%20if%20needed.%0A%20%20%20%20%09%20%20var%20shortseed%20=%20mixkey(flatten(%0A%20%20%20%20%09%20%20%20%20options.entropy%20?%20%5Bseed,%20tostring(pool)%5D%20:%0A%20%20%20%20%09%20%20%20%20(seed%20==%20null)%20?%20autoseed()%20:%20seed,%203),%20key);%0A%0A%20%20%20%20%09%20%20//%20Use%20the%20seed%20to%20initialize%20an%20ARC4%20generator.%0A%20%20%20%20%09%20%20var%20arc4%20=%20new%20ARC4(key);%0A%0A%20%20%20%20%09%20%20//%20This%20function%20returns%20a%20random%20double%20in%20%5B0,%201)%20that%20contains%0A%20%20%20%20%09%20%20//%20randomness%20in%20every%20bit%20of%20the%20mantissa%20of%20the%20IEEE%20754%20value.%0A%20%20%20%20%09%20%20var%20prng%20=%20function()%20%7B%0A%20%20%20%20%09%20%20%20%20var%20n%20=%20arc4.g(chunks),%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Start%20with%20a%20numerator%20n%20%3C%202%20%5E%2048%0A%20%20%20%20%09%20%20%20%20%20%20%20%20d%20=%20startdenom,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20and%20denominator%20d%20=%202%20%5E%2048.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20x%20=%200;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20and%20no%20'extra%20last%20byte'.%0A%20%20%20%20%09%20%20%20%20while%20(n%20%3C%20significance)%20%7B%20%20%20%20%20%20%20%20%20%20//%20Fill%20up%20all%20significant%20digits%20by%0A%20%20%20%20%09%20%20%20%20%20%20n%20=%20(n%20+%20x)%20*%20width;%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20shifting%20numerator%20and%0A%20%20%20%20%09%20%20%20%20%20%20d%20*=%20width;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20denominator%20and%20generating%20a%0A%20%20%20%20%09%20%20%20%20%20%20x%20=%20arc4.g(1);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20new%20least-significant-byte.%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20while%20(n%20%3E=%20overflow)%20%7B%20%20%20%20%20%20%20%20%20%20%20%20%20//%20To%20avoid%20rounding%20up,%20before%20adding%0A%20%20%20%20%09%20%20%20%20%20%20n%20/=%202;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20last%20byte,%20shift%20everything%0A%20%20%20%20%09%20%20%20%20%20%20d%20/=%202;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20right%20using%20integer%20math%20until%0A%20%20%20%20%09%20%20%20%20%20%20x%20%3E%3E%3E=%201;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20we%20have%20exactly%20the%20desired%20bits.%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20return%20(n%20+%20x)%20/%20d;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Form%20the%20number%20within%20%5B0,%201).%0A%20%20%20%20%09%20%20%7D;%0A%0A%20%20%20%20%09%20%20prng.int32%20=%20function()%20%7B%20return%20arc4.g(4)%20%7C%200;%20%7D;%0A%20%20%20%20%09%20%20prng.quick%20=%20function()%20%7B%20return%20arc4.g(4)%20/%200x100000000;%20%7D;%0A%20%20%20%20%09%20%20prng.double%20=%20prng;%0A%0A%20%20%20%20%09%20%20//%20Mix%20the%20randomness%20into%20accumulated%20entropy.%0A%20%20%20%20%09%20%20mixkey(tostring(arc4.S),%20pool);%0A%0A%20%20%20%20%09%20%20//%20Calling%20convention:%20what%20to%20return%20as%20a%20function%20of%20prng,%20seed,%20is_math.%0A%20%20%20%20%09%20%20return%20(options.pass%20%7C%7C%20callback%20%7C%7C%0A%20%20%20%20%09%20%20%20%20%20%20function(prng,%20seed,%20is_math_call,%20state)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20if%20(state)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20//%20Load%20the%20arc4%20state%20from%20the%20given%20state%20if%20it%20has%20an%20S%20array.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20if%20(state.S)%20%7B%20copy(state,%20arc4);%20%7D%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20//%20Only%20provide%20the%20.state%20method%20if%20requested%20via%20options.state.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%20%20prng.state%20=%20function()%20%7B%20return%20copy(arc4,%20%7B%7D);%20%7D;%0A%20%20%20%20%09%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20If%20called%20as%20a%20method%20of%20Math%20(Math.seedrandom()),%20mutate%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20Math.random%20because%20that%20is%20how%20seedrandom.js%20has%20worked%20since%20v1.0.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20if%20(is_math_call)%20%7B%20math%5Brngname%5D%20=%20prng;%20return%20seed;%20%7D%0A%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20Otherwise,%20it%20is%20a%20newer%20calling%20convention,%20so%20return%20the%0A%20%20%20%20%09%20%20%20%20%20%20%20%20//%20prng%20directly.%0A%20%20%20%20%09%20%20%20%20%20%20%20%20else%20return%20prng;%0A%20%20%20%20%09%20%20%20%20%20%20%7D)(%0A%20%20%20%20%09%20%20prng,%0A%20%20%20%20%09%20%20shortseed,%0A%20%20%20%20%09%20%20'global'%20in%20options%20?%20options.global%20:%20(this%20==%20math),%0A%20%20%20%20%09%20%20options.state);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20ARC4%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20An%20ARC4%20implementation.%20%20The%20constructor%20takes%20a%20key%20in%20the%20form%20of%0A%20%20%20%20%09//%20an%20array%20of%20at%20most%20(width)%20integers%20that%20should%20be%200%20%3C=%20x%20%3C%20(width).%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20The%20g(count)%20method%20returns%20a%20pseudorandom%20integer%20that%20concatenates%0A%20%20%20%20%09//%20the%20next%20(count)%20outputs%20from%20ARC4.%20%20Its%20return%20value%20is%20a%20number%20x%0A%20%20%20%20%09//%20that%20is%20in%20the%20range%200%20%3C=%20x%20%3C%20(width%20%5E%20count).%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20ARC4(key)%20%7B%0A%20%20%20%20%09%20%20var%20t,%20keylen%20=%20key.length,%0A%20%20%20%20%09%20%20%20%20%20%20me%20=%20this,%20i%20=%200,%20j%20=%20me.i%20=%20me.j%20=%200,%20s%20=%20me.S%20=%20%5B%5D;%0A%0A%20%20%20%20%09%20%20//%20The%20empty%20key%20%5B%5D%20is%20treated%20as%20%5B0%5D.%0A%20%20%20%20%09%20%20if%20(!keylen)%20%7B%20key%20=%20%5Bkeylen++%5D;%20%7D%0A%0A%20%20%20%20%09%20%20//%20Set%20up%20S%20using%20the%20standard%20key%20scheduling%20algorithm.%0A%20%20%20%20%09%20%20while%20(i%20%3C%20width)%20%7B%0A%20%20%20%20%09%20%20%20%20s%5Bi%5D%20=%20i++;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20for%20(i%20=%200;%20i%20%3C%20width;%20i++)%20%7B%0A%20%20%20%20%09%20%20%20%20s%5Bi%5D%20=%20s%5Bj%20=%20mask%20&%20(j%20+%20key%5Bi%20%25%20keylen%5D%20+%20(t%20=%20s%5Bi%5D))%5D;%0A%20%20%20%20%09%20%20%20%20s%5Bj%5D%20=%20t;%0A%20%20%20%20%09%20%20%7D%0A%0A%20%20%20%20%09%20%20//%20The%20%22g%22%20method%20returns%20the%20next%20(count)%20outputs%20as%20one%20number.%0A%20%20%20%20%09%20%20(me.g%20=%20function(count)%20%7B%0A%20%20%20%20%09%20%20%20%20//%20Using%20instance%20members%20instead%20of%20closure%20state%20nearly%20doubles%20speed.%0A%20%20%20%20%09%20%20%20%20var%20t,%20r%20=%200,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20i%20=%20me.i,%20j%20=%20me.j,%20s%20=%20me.S;%0A%20%20%20%20%09%20%20%20%20while%20(count--)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20t%20=%20s%5Bi%20=%20mask%20&%20(i%20+%201)%5D;%0A%20%20%20%20%09%20%20%20%20%20%20r%20=%20r%20*%20width%20+%20s%5Bmask%20&%20((s%5Bi%5D%20=%20s%5Bj%20=%20mask%20&%20(j%20+%20t)%5D)%20+%20(s%5Bj%5D%20=%20t))%5D;%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20me.i%20=%20i;%20me.j%20=%20j;%0A%20%20%20%20%09%20%20%20%20return%20r;%0A%20%20%20%20%09%20%20%20%20//%20For%20robust%20unpredictability,%20the%20function%20call%20below%20automatically%0A%20%20%20%20%09%20%20%20%20//%20discards%20an%20initial%20batch%20of%20values.%20%20This%20is%20called%20RC4-drop%5B256%5D.%0A%20%20%20%20%09%20%20%20%20//%20See%20http://google.com/search?q=rsa+fluhrer+response&btnI%0A%20%20%20%20%09%20%20%7D)(width);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20copy()%0A%20%20%20%20%09//%20Copies%20internal%20state%20of%20ARC4%20to%20or%20from%20a%20plain%20object.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20copy(f,%20t)%20%7B%0A%20%20%20%20%09%20%20t.i%20=%20f.i;%0A%20%20%20%20%09%20%20t.j%20=%20f.j;%0A%20%20%20%20%09%20%20t.S%20=%20f.S.slice();%0A%20%20%20%20%09%20%20return%20t;%0A%20%20%20%20%09%7D%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20flatten()%0A%20%20%20%20%09//%20Converts%20an%20object%20tree%20to%20nested%20arrays%20of%20strings.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20flatten(obj,%20depth)%20%7B%0A%20%20%20%20%09%20%20var%20result%20=%20%5B%5D,%20typ%20=%20(typeof%20obj),%20prop;%0A%20%20%20%20%09%20%20if%20(depth%20&&%20typ%20==%20'object')%20%7B%0A%20%20%20%20%09%20%20%20%20for%20(prop%20in%20obj)%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20try%20%7B%20result.push(flatten(obj%5Bprop%5D,%20depth%20-%201));%20%7D%20catch%20(e)%20%7B%7D%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20(result.length%20?%20result%20:%20typ%20==%20'string'%20?%20obj%20:%20obj%20+%20'%5C0');%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20mixkey()%0A%20%20%20%20%09//%20Mixes%20a%20string%20seed%20into%20a%20key%20that%20is%20an%20array%20of%20integers,%20and%0A%20%20%20%20%09//%20returns%20a%20shortened%20string%20seed%20that%20is%20equivalent%20to%20the%20result%20key.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20mixkey(seed,%20key)%20%7B%0A%20%20%20%20%09%20%20var%20stringseed%20=%20seed%20+%20'',%20smear,%20j%20=%200;%0A%20%20%20%20%09%20%20while%20(j%20%3C%20stringseed.length)%20%7B%0A%20%20%20%20%09%20%20%20%20key%5Bmask%20&%20j%5D%20=%0A%20%20%20%20%09%20%20%20%20%20%20mask%20&%20((smear%20%5E=%20key%5Bmask%20&%20j%5D%20*%2019)%20+%20stringseed.charCodeAt(j++));%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%20%20return%20tostring(key);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20autoseed()%0A%20%20%20%20%09//%20Returns%20an%20object%20for%20autoseeding,%20using%20window.crypto%20and%20Node%20crypto%0A%20%20%20%20%09//%20module%20if%20available.%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20autoseed()%20%7B%0A%20%20%20%20%09%20%20try%20%7B%0A%20%20%20%20%09%20%20%20%20var%20out;%0A%20%20%20%20%09%20%20%20%20if%20(nodecrypto%20&&%20(out%20=%20nodecrypto.randomBytes))%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20//%20The%20use%20of%20'out'%20to%20remember%20randomBytes%20makes%20tight%20minified%20code.%0A%20%20%20%20%09%20%20%20%20%20%20out%20=%20out(width);%0A%20%20%20%20%09%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%09%20%20%20%20%20%20out%20=%20new%20Uint8Array(width);%0A%20%20%20%20%09%20%20%20%20%20%20(global.crypto%20%7C%7C%20global.msCrypto).getRandomValues(out);%0A%20%20%20%20%09%20%20%20%20%7D%0A%20%20%20%20%09%20%20%20%20return%20tostring(out);%0A%20%20%20%20%09%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%09%20%20%20%20var%20browser%20=%20global.navigator,%0A%20%20%20%20%09%20%20%20%20%20%20%20%20plugins%20=%20browser%20&&%20browser.plugins;%0A%20%20%20%20%09%20%20%20%20return%20%5B+new%20Date,%20global,%20plugins,%20global.screen,%20tostring(pool)%5D;%0A%20%20%20%20%09%20%20%7D%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20tostring()%0A%20%20%20%20%09//%20Converts%20an%20array%20of%20charcodes%20to%20a%20string%0A%20%20%20%20%09//%0A%20%20%20%20%09function%20tostring(a)%20%7B%0A%20%20%20%20%09%20%20return%20String.fromCharCode.apply(0,%20a);%0A%20%20%20%20%09%7D%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20When%20seedrandom.js%20is%20loaded,%20we%20immediately%20mix%20a%20few%20bits%0A%20%20%20%20%09//%20from%20the%20built-in%20RNG%20into%20the%20entropy%20pool.%20%20Because%20we%20do%0A%20%20%20%20%09//%20not%20want%20to%20interfere%20with%20deterministic%20PRNG%20state%20later,%0A%20%20%20%20%09//%20seedrandom%20will%20not%20call%20math.random%20on%20its%20own%20again%20after%0A%20%20%20%20%09//%20initialization.%0A%20%20%20%20%09//%0A%20%20%20%20%09mixkey(math.random(),%20pool);%0A%0A%20%20%20%20%09//%0A%20%20%20%20%09//%20Nodejs%20and%20AMD%20support:%20export%20the%20implementation%20as%20a%20module%20using%0A%20%20%20%20%09//%20either%20convention.%0A%20%20%20%20%09//%0A%20%20%20%20%09if%20(module.exports)%20%7B%0A%20%20%20%20%09%20%20module.exports%20=%20seedrandom;%0A%20%20%20%20%09%20%20//%20When%20in%20node.js,%20try%20using%20crypto%20package%20for%20autoseeding.%0A%20%20%20%20%09%20%20try%20%7B%0A%20%20%20%20%09%20%20%20%20nodecrypto%20=%20require('crypto');%0A%20%20%20%20%09%20%20%7D%20catch%20(ex)%20%7B%7D%0A%20%20%20%20%09%7D%20else%20%7B%0A%20%20%20%20%09%20%20//%20When%20included%20as%20a%20plain%20script,%20set%20up%20Math.seedrandom%20global.%0A%20%20%20%20%09%20%20math%5B'seed'%20+%20rngname%5D%20=%20seedrandom;%0A%20%20%20%20%09%7D%0A%0A%0A%20%20%20%20%09//%20End%20anonymous%20scope,%20and%20pass%20initial%20values.%0A%20%20%20%20%09%7D)(%0A%20%20%20%20%09%20%20//%20global:%20%60self%60%20in%20browsers%20(including%20strict%20mode%20and%20web%20workers),%0A%20%20%20%20%09%20%20//%20otherwise%20%60this%60%20in%20Node%20and%20other%20environments%0A%20%20%20%20%09%20%20(typeof%20self%20!==%20'undefined')%20?%20self%20:%20commonjsGlobal,%0A%20%20%20%20%09%20%20%5B%5D,%20%20%20%20%20//%20pool:%20entropy%20pool%20starts%20empty%0A%20%20%20%20%09%20%20Math%20%20%20%20//%20math:%20package%20containing%20random,%20pow,%20and%20seedrandom%0A%20%20%20%20%09);%20%0A%20%20%20%20%7D%20(seedrandom$1));%0A%0A%20%20%20%20var%20seedrandomExports%20=%20seedrandom$1.exports;%0A%0A%20%20%20%20//%20A%20library%20of%20seedable%20RNGs%20implemented%20in%20Javascript.%0A%20%20%20%20//%0A%20%20%20%20//%20Usage:%0A%20%20%20%20//%0A%20%20%20%20//%20var%20seedrandom%20=%20require('seedrandom');%0A%20%20%20%20//%20var%20random%20=%20seedrandom(1);%20//%20or%20any%20seed.%0A%20%20%20%20//%20var%20x%20=%20random();%20%20%20%20%20%20%20//%200%20%3C=%20x%20%3C%201.%20%20Every%20bit%20is%20random.%0A%20%20%20%20//%20var%20x%20=%20random.quick();%20//%200%20%3C=%20x%20%3C%201.%20%2032%20bits%20of%20randomness.%0A%0A%20%20%20%20//%20alea,%20a%2053-bit%20multiply-with-carry%20generator%20by%20Johannes%20Baag%C3%B8e.%0A%20%20%20%20//%20Period:%20~2%5E116%0A%20%20%20%20//%20Reported%20to%20pass%20all%20BigCrush%20tests.%0A%20%20%20%20var%20alea%20=%20aleaExports;%0A%0A%20%20%20%20//%20xor128,%20a%20pure%20xor-shift%20generator%20by%20George%20Marsaglia.%0A%20%20%20%20//%20Period:%202%5E128-1.%0A%20%20%20%20//%20Reported%20to%20fail:%20MatrixRank%20and%20LinearComp.%0A%20%20%20%20var%20xor128%20=%20xor128Exports;%0A%0A%20%20%20%20//%20xorwow,%20George%20Marsaglia's%20160-bit%20xor-shift%20combined%20plus%20weyl.%0A%20%20%20%20//%20Period:%202%5E192-2%5E32%0A%20%20%20%20//%20Reported%20to%20fail:%20CollisionOver,%20SimpPoker,%20and%20LinearComp.%0A%20%20%20%20var%20xorwow%20=%20xorwowExports;%0A%0A%20%20%20%20//%20xorshift7,%20by%20Fran%C3%A7ois%20Panneton%20and%20Pierre%20L'ecuyer,%20takes%0A%20%20%20%20//%20a%20different%20approach:%20it%20adds%20robustness%20by%20allowing%20more%20shifts%0A%20%20%20%20//%20than%20Marsaglia's%20original%20three.%20%20It%20is%20a%207-shift%20generator%0A%20%20%20%20//%20with%20256%20bits,%20that%20passes%20BigCrush%20with%20no%20systmatic%20failures.%0A%20%20%20%20//%20Period%202%5E256-1.%0A%20%20%20%20//%20No%20systematic%20BigCrush%20failures%20reported.%0A%20%20%20%20var%20xorshift7%20=%20xorshift7Exports;%0A%0A%20%20%20%20//%20xor4096,%20by%20Richard%20Brent,%20is%20a%204096-bit%20xor-shift%20with%20a%0A%20%20%20%20//%20very%20long%20period%20that%20also%20adds%20a%20Weyl%20generator.%20It%20also%20passes%0A%20%20%20%20//%20BigCrush%20with%20no%20systematic%20failures.%20%20Its%20long%20period%20may%0A%20%20%20%20//%20be%20useful%20if%20you%20have%20many%20generators%20and%20need%20to%20avoid%0A%20%20%20%20//%20collisions.%0A%20%20%20%20//%20Period:%202%5E4128-2%5E32.%0A%20%20%20%20//%20No%20systematic%20BigCrush%20failures%20reported.%0A%20%20%20%20var%20xor4096%20=%20xor4096Exports;%0A%0A%20%20%20%20//%20Tyche-i,%20by%20Samuel%20Neves%20and%20Filipe%20Araujo,%20is%20a%20bit-shifting%20random%0A%20%20%20%20//%20number%20generator%20derived%20from%20ChaCha,%20a%20modern%20stream%20cipher.%0A%20%20%20%20//%20https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf%0A%20%20%20%20//%20Period:%20~2%5E127%0A%20%20%20%20//%20No%20systematic%20BigCrush%20failures%20reported.%0A%20%20%20%20var%20tychei%20=%20tycheiExports;%0A%0A%20%20%20%20//%20The%20original%20ARC4-based%20prng%20included%20in%20this%20library.%0A%20%20%20%20//%20Period:%20~2%5E1600%0A%20%20%20%20var%20sr%20=%20seedrandomExports;%0A%0A%20%20%20%20sr.alea%20=%20alea;%0A%20%20%20%20sr.xor128%20=%20xor128;%0A%20%20%20%20sr.xorwow%20=%20xorwow;%0A%20%20%20%20sr.xorshift7%20=%20xorshift7;%0A%20%20%20%20sr.xor4096%20=%20xor4096;%0A%20%20%20%20sr.tychei%20=%20tychei;%0A%0A%20%20%20%20var%20seedrandom%20=%20sr;%0A%0A%20%20%20%20var%20Seedrandom%20=%20/*@__PURE__*/getDefaultExportFromCjs(seedrandom);%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BHTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20domainKey%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20sessionKey%0A%20%20%20%20%20*%20@param%20%7Bany%7D%20getImageDataProxy%0A%20%20%20%20%20*%20@param%20%7BCanvasRenderingContext2D%20%7C%20WebGL2RenderingContext%20%7C%20WebGLRenderingContext%7D%20ctx?%0A%20%20%20%20%20*/%0A%20%20%20%20function%20computeOffScreenCanvas%20(canvas,%20domainKey,%20sessionKey,%20getImageDataProxy,%20ctx)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!ctx)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'null'%20is%20not%20assignable%20to%20type%20'CanvasRenderingContext2D%20%7C%20WebGL2RenderingContext%20%7C%20WebGLRenderingContext'.%0A%20%20%20%20%20%20%20%20%20%20%20%20ctx%20=%20canvas.getContext('2d');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Make%20a%20off-screen%20canvas%20and%20put%20the%20data%20there%0A%20%20%20%20%20%20%20%20const%20offScreenCanvas%20=%20document.createElement('canvas');%0A%20%20%20%20%20%20%20%20offScreenCanvas.width%20=%20canvas.width;%0A%20%20%20%20%20%20%20%20offScreenCanvas.height%20=%20canvas.height;%0A%20%20%20%20%20%20%20%20const%20offScreenCtx%20=%20offScreenCanvas.getContext('2d');%0A%0A%20%20%20%20%20%20%20%20let%20rasterizedCtx%20=%20ctx;%0A%20%20%20%20%20%20%20%20//%20If%20we're%20not%20a%202d%20canvas%20we%20need%20to%20rasterise%20first%20into%202d%0A%20%20%20%20%20%20%20%20const%20rasterizeToCanvas%20=%20!(ctx%20instanceof%20CanvasRenderingContext2D);%0A%20%20%20%20%20%20%20%20if%20(rasterizeToCanvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'CanvasRenderingContext2D%20%7C%20null'%20is%20not%20assignable%20to%20type%20'CanvasRenderingContext2D%20%7C%20WebGL2RenderingContext%20%7C%20WebGLRenderingContext'.%0A%20%20%20%20%20%20%20%20%20%20%20%20rasterizedCtx%20=%20offScreenCtx;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20'offScreenCtx'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20offScreenCtx.drawImage(canvas,%200,%200);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20We%20*always*%20compute%20the%20random%20pixels%20on%20the%20complete%20pixel%20set,%20then%20pass%20back%20the%20subset%20later%0A%20%20%20%20%20%20%20%20let%20imageData%20=%20getImageDataProxy._native.apply(rasterizedCtx,%20%5B0,%200,%20canvas.width,%20canvas.height%5D);%0A%20%20%20%20%20%20%20%20imageData%20=%20modifyPixelData(imageData,%20sessionKey,%20domainKey,%20canvas.width);%0A%0A%20%20%20%20%20%20%20%20if%20(rasterizeToCanvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Type%20'null'%20is%20not%20assignable%20to%20type%20'CanvasRenderingContext2D'.%0A%20%20%20%20%20%20%20%20%20%20%20%20clearCanvas(offScreenCtx);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20'offScreenCtx'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20offScreenCtx.putImageData(imageData,%200,%200);%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20offScreenCanvas,%20offScreenCtx%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Clears%20the%20pixels%20from%20the%20canvas%20context%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7BCanvasRenderingContext2D%7D%20canvasContext%0A%20%20%20%20%20*/%0A%20%20%20%20function%20clearCanvas%20(canvasContext)%20%7B%0A%20%20%20%20%20%20%20%20//%20Save%20state%20and%20clean%20the%20pixels%20from%20the%20canvas%0A%20%20%20%20%20%20%20%20canvasContext.save();%0A%20%20%20%20%20%20%20%20canvasContext.globalCompositeOperation%20=%20'destination-out';%0A%20%20%20%20%20%20%20%20canvasContext.fillStyle%20=%20'rgb(255,255,255)';%0A%20%20%20%20%20%20%20%20canvasContext.fillRect(0,%200,%20canvasContext.canvas.width,%20canvasContext.canvas.height);%0A%20%20%20%20%20%20%20%20canvasContext.restore();%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BImageData%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20sessionKey%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20domainKey%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20width%0A%20%20%20%20%20*/%0A%20%20%20%20function%20modifyPixelData%20(imageData,%20domainKey,%20sessionKey,%20width)%20%7B%0A%20%20%20%20%20%20%20%20const%20d%20=%20imageData.data;%0A%20%20%20%20%20%20%20%20const%20length%20=%20d.length%20/%204;%0A%20%20%20%20%20%20%20%20let%20checkSum%20=%200;%0A%20%20%20%20%20%20%20%20const%20mappingArray%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20for%20(let%20i%20=%200;%20i%20%3C%20length;%20i%20+=%204)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!shouldIgnorePixel(d,%20i)%20&&%20!adjacentSame(d,%20i,%20width))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mappingArray.push(i);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20checkSum%20+=%20d%5Bi%5D%20+%20d%5Bi%20+%201%5D%20+%20d%5Bi%20+%202%5D%20+%20d%5Bi%20+%203%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20windowHash%20=%20getDataKeySync(sessionKey,%20domainKey,%20checkSum);%0A%20%20%20%20%20%20%20%20const%20rng%20=%20new%20Seedrandom(windowHash);%0A%20%20%20%20%20%20%20%20for%20(let%20i%20=%200;%20i%20%3C%20mappingArray.length;%20i++)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20rand%20=%20rng();%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20byte%20=%20Math.floor(rand%20*%2010);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20channel%20=%20byte%20%25%203;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20pixelCanvasIndex%20=%20mappingArray%5Bi%5D%20+%20channel;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20d%5BpixelCanvasIndex%5D%20=%20d%5BpixelCanvasIndex%5D%20%5E%20(byte%20&%200x1);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20imageData%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Ignore%20pixels%20that%20have%20neighbours%20that%20are%20the%20same%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7BUint8ClampedArray%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20width%0A%20%20%20%20%20*/%0A%20%20%20%20function%20adjacentSame%20(imageData,%20index,%20width)%20%7B%0A%20%20%20%20%20%20%20%20const%20widthPixel%20=%20width%20*%204;%0A%20%20%20%20%20%20%20%20const%20x%20=%20index%20%25%20widthPixel;%0A%20%20%20%20%20%20%20%20const%20maxLength%20=%20imageData.length;%0A%0A%20%20%20%20%20%20%20%20//%20Pixels%20not%20on%20the%20right%20border%20of%20the%20canvas%0A%20%20%20%20%20%20%20%20if%20(x%20%3C%20widthPixel)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20right%20=%20index%20+%204;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!pixelsSame(imageData,%20index,%20right))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalRightUp%20=%20right%20-%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalRightUp%20%3E%200%20&&%20!pixelsSame(imageData,%20index,%20diagonalRightUp))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalRightDown%20=%20right%20+%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalRightDown%20%3C%20maxLength%20&&%20!pixelsSame(imageData,%20index,%20diagonalRightDown))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Pixels%20not%20on%20the%20left%20border%20of%20the%20canvas%0A%20%20%20%20%20%20%20%20if%20(x%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20left%20=%20index%20-%204;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!pixelsSame(imageData,%20index,%20left))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalLeftUp%20=%20left%20-%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalLeftUp%20%3E%200%20&&%20!pixelsSame(imageData,%20index,%20diagonalLeftUp))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diagonalLeftDown%20=%20left%20+%20widthPixel;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(diagonalLeftDown%20%3C%20maxLength%20&&%20!pixelsSame(imageData,%20index,%20diagonalLeftDown))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20up%20=%20index%20-%20widthPixel;%0A%20%20%20%20%20%20%20%20if%20(up%20%3E%200%20&&%20!pixelsSame(imageData,%20index,%20up))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20down%20=%20index%20+%20widthPixel;%0A%20%20%20%20%20%20%20%20if%20(down%20%3C%20maxLength%20&&%20!pixelsSame(imageData,%20index,%20down))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Check%20that%20a%20pixel%20at%20index%20and%20index2%20match%20all%20channels%0A%20%20%20%20%20*%20@param%20%7BUint8ClampedArray%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index2%0A%20%20%20%20%20*/%0A%20%20%20%20function%20pixelsSame%20(imageData,%20index,%20index2)%20%7B%0A%20%20%20%20%20%20%20%20return%20imageData%5Bindex%5D%20===%20imageData%5Bindex2%5D%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20imageData%5Bindex%20+%201%5D%20===%20imageData%5Bindex2%20+%201%5D%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20imageData%5Bindex%20+%202%5D%20===%20imageData%5Bindex2%20+%202%5D%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20imageData%5Bindex%20+%203%5D%20===%20imageData%5Bindex2%20+%203%5D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Returns%20true%20if%20pixel%20should%20be%20ignored%0A%20%20%20%20%20*%20@param%20%7BUint8ClampedArray%7D%20imageData%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20index%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shouldIgnorePixel%20(imageData,%20index)%20%7B%0A%20%20%20%20%20%20%20%20//%20Transparent%20pixels%0A%20%20%20%20%20%20%20%20if%20(imageData%5Bindex%20+%203%5D%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingCanvas%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20sessionKey,%20site%20%7D%20=%20args;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20domainKey%20=%20site.domain;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureName%20=%20'fingerprinting-canvas';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20supportsWebGl%20=%20this.getFeatureSettingEnabled('webGl');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeCanvases%20=%20new%20WeakSet();%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20canvasContexts%20=%20new%20WeakMap();%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20canvasCache%20=%20new%20WeakMap();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20Clear%20cache%20as%20canvas%20has%20changed%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7BOffscreenCanvas%20%7C%20HTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20clearCache%20(canvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvasCache.delete(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7BOffscreenCanvas%20%7C%20HTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20treatAsUnsafe%20(canvas)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unsafeCanvases.add(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearCache(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20HTMLCanvasElement.prototype,%20'getContext',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20context%20=%20DDGReflect.apply(target,%20thisArg,%20args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvasContexts.set(thisArg,%20context);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20context%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20proxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Known%20data%20methods%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20safeMethods%20=%20%5B'putImageData',%20'drawImage'%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20safeMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20safeMethodProxy%20=%20new%20DDGProxy(featureName,%20CanvasRenderingContext2D.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Don't%20apply%20escape%20hatch%20for%20canvases%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(methodName%20===%20'drawImage'%20&&%20args%5B0%5D%20&&%20args%5B0%5D%20instanceof%20HTMLCanvasElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20treatAsUnsafe(args%5B0%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearCache(thisArg.canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20safeMethodProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeMethods%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'strokeRect',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'bezierCurveTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'quadraticCurveTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'arcTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'ellipse',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'rect',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fill',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'stroke',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'lineTo',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'beginPath',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'closePath',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'arc',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fillText',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fillRect',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'strokeText',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createConicGradient',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createLinearGradient',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createRadialGradient',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createPattern'%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20unsafeMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Some%20methods%20are%20browser%20specific%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(methodName%20in%20CanvasRenderingContext2D.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeProxy%20=%20new%20DDGProxy(featureName,%20CanvasRenderingContext2D.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20treatAsUnsafe(thisArg.canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unsafeProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(supportsWebGl)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeGlMethods%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'commit',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'compileShader',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'shaderSource',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'attachShader',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'createProgram',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'linkProgram',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'drawElements',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'drawArrays'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20glContexts%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WebGLRenderingContext%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('WebGL2RenderingContext'%20in%20globalThis)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20glContexts.push(WebGL2RenderingContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20context%20of%20glContexts)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20unsafeGlMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Some%20methods%20are%20browser%20specific%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(methodName%20in%20context.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20unsafeProxy%20=%20new%20DDGProxy(featureName,%20context.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20treatAsUnsafe(thisArg.canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unsafeProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Using%20proxies%20here%20to%20swallow%20calls%20to%20toString%20etc%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20getImageDataProxy%20=%20new%20DDGProxy(featureName,%20CanvasRenderingContext2D.prototype,%20'getImageData',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!unsafeCanvases.has(thisArg.canvas))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Anything%20we%20do%20here%20should%20be%20caught%20and%20ignored%20silently%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20offScreenCtx%20%7D%20=%20getCachedOffScreenCanvasOrCompute(thisArg.canvas,%20domainKey,%20sessionKey);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Call%20the%20original%20method%20on%20the%20modified%20off-screen%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20offScreenCtx,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20getImageDataProxy.overload();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20Get%20cached%20offscreen%20if%20one%20exists,%20otherwise%20compute%20one%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLCanvasElement%7D%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20domainKey%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20sessionKey%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20getCachedOffScreenCanvasOrCompute%20(canvas,%20domainKey,%20sessionKey)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20result;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(canvasCache.has(canvas))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20=%20canvasCache.get(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20ctx%20=%20canvasContexts.get(canvas);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20result%20=%20computeOffScreenCanvas(canvas,%20domainKey,%20sessionKey,%20getImageDataProxy,%20ctx);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20canvasCache.set(canvas,%20result);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20result%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20canvasMethods%20=%20%5B'toDataURL',%20'toBlob'%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20methodName%20of%20canvasMethods)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20proxy%20=%20new%20DDGProxy(featureName,%20HTMLCanvasElement.prototype,%20methodName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Short%20circuit%20for%20low%20risk%20canvas%20calls%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!unsafeCanvases.has(thisArg))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'thisArg'%20is%20possibly%20'undefined'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20offScreenCanvas%20%7D%20=%20getCachedOffScreenCanvasOrCompute(thisArg,%20domainKey,%20sessionKey);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Call%20the%20original%20method%20on%20the%20modified%20off-screen%20canvas%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20offScreenCanvas,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Something%20we%20did%20caused%20an%20exception,%20fall%20back%20to%20the%20native%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20proxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Cookie%20%7B%0A%20%20%20%20%20%20%20%20constructor%20(cookieString)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parts%20=%20cookieString.split(';');%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parse();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20parse%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20EXTRACT_ATTRIBUTES%20=%20new%20Set(%5B'max-age',%20'expires',%20'domain'%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20this.attrIdx%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parts.forEach((part,%20index)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20kv%20=%20part.split('=',%201);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20attribute%20=%20kv%5B0%5D.trim();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20value%20=%20part.slice(kv%5B0%5D.length%20+%201);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(index%20===%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.name%20=%20attribute;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.value%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(EXTRACT_ATTRIBUTES.has(attribute.toLowerCase()))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this%5Battribute.toLowerCase()%5D%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.attrIdx%5Battribute.toLowerCase()%5D%20=%20index;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20getExpiry%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20expires%20is%20not%20defined%20in%20the%20type%20definition%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this.maxAge%20&&%20!this.expires)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20NaN%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20expiry%20=%20this.maxAge%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20?%20parseInt(this.maxAge)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20expires%20is%20not%20defined%20in%20the%20type%20definition%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20:%20(new%20Date(this.expires)%20-%20new%20Date())%20/%201000;%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20expiry%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20get%20maxAge%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this%5B'max-age'%5D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20set%20maxAge%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.attrIdx%5B'max-age'%5D%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.parts.splice(this.attrIdx%5B'max-age'%5D,%201,%20%60max-age=$%7Bvalue%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.parts.push(%60max-age=$%7Bvalue%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20this.parse();%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20toString%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.parts.join(';')%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Check%20if%20the%20current%20document%20origin%20is%20on%20the%20tracker%20list,%20using%20the%20provided%20lookup%20trie.%0A%20%20%20%20%20*%20@param%20%7Bobject%7D%20trackerLookup%20Trie%20lookup%20of%20tracker%20domains%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%20True%20iff%20the%20origin%20is%20a%20tracker.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isTrackerOrigin%20(trackerLookup,%20originHostname%20=%20document.location.hostname)%20%7B%0A%20%20%20%20%20%20%20%20const%20parts%20=%20originHostname.split('.').reverse();%0A%20%20%20%20%20%20%20%20let%20node%20=%20trackerLookup;%0A%20%20%20%20%20%20%20%20for%20(const%20sub%20of%20parts)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(node%5Bsub%5D%20===%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(node%5Bsub%5D)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20node%20=%20node%5Bsub%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20ExtensionCookiePolicy%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20isFrame%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20isTracker%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20shouldBlock%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20isThirdPartyFrame%0A%20%20%20%20%20*/%0A%0A%20%20%20%20//%20Initial%20cookie%20policy%20pre%20init%0A%20%20%20%20let%20cookiePolicy%20=%20%7B%0A%20%20%20%20%20%20%20%20debug:%20false,%0A%20%20%20%20%20%20%20%20isFrame:%20isBeingFramed(),%0A%20%20%20%20%20%20%20%20isTracker:%20false,%0A%20%20%20%20%20%20%20%20shouldBlock:%20true,%0A%20%20%20%20%20%20%20%20shouldBlockTrackerCookie:%20true,%0A%20%20%20%20%20%20%20%20shouldBlockNonTrackerCookie:%20false,%0A%20%20%20%20%20%20%20%20isThirdPartyFrame:%20isThirdPartyFrame(),%0A%20%20%20%20%20%20%20%20policy:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20threshold:%20604800,%20//%207%20days%0A%20%20%20%20%20%20%20%20%20%20%20%20maxAge:%20604800%20//%207%20days%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20trackerPolicy:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20threshold:%2086400,%20//%201%20day%0A%20%20%20%20%20%20%20%20%20%20%20%20maxAge:%2086400%20//%201%20day%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20allowlist:%20/**%20@type%20%7B%7B%20host:%20string%20%7D%5B%5D%7D%20*/(%5B%5D)%0A%20%20%20%20%7D;%0A%20%20%20%20let%20trackerLookup%20=%20%7B%7D;%0A%0A%20%20%20%20let%20loadedPolicyResolve;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7B'ignore'%20%7C%20'block'%20%7C%20'restrict'%7D%20action%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20reason%0A%20%20%20%20%20*%20@param%20%7Bany%7D%20ctx%0A%20%20%20%20%20*/%0A%20%20%20%20function%20debugHelper%20(action,%20reason,%20ctx)%20%7B%0A%20%20%20%20%20%20%20%20cookiePolicy.debug%20&&%20postDebugMessage('jscookie',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20action,%0A%20%20%20%20%20%20%20%20%20%20%20%20reason,%0A%20%20%20%20%20%20%20%20%20%20%20%20stack:%20ctx.stack,%0A%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20globalThis.document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins:%20%5B...ctx.scriptOrigins%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20value:%20ctx.value%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20shouldBlockTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.shouldBlock%20&&%20cookiePolicy.shouldBlockTrackerCookie%20&&%20isTrackingCookie()%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20shouldBlockNonTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.shouldBlock%20&&%20cookiePolicy.shouldBlockNonTrackerCookie%20&&%20isNonTrackingCookie()%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BSet%3Cstring%3E%7D%20scriptOrigins%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isFirstPartyTrackerScript%20(scriptOrigins)%20%7B%0A%20%20%20%20%20%20%20%20let%20matched%20=%20false;%0A%20%20%20%20%20%20%20%20for%20(const%20scriptOrigin%20of%20scriptOrigins)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(cookiePolicy.allowlist.find((allowlistOrigin)%20=%3E%20matchHostname(allowlistOrigin.host,%20scriptOrigin)))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(isTrackerOrigin(trackerLookup,%20scriptOrigin))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20matched%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20matched%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@returns%20%7Bboolean%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.isFrame%20&&%20cookiePolicy.isTracker%20&&%20cookiePolicy.isThirdPartyFrame%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20isNonTrackingCookie%20()%20%7B%0A%20%20%20%20%20%20%20%20return%20cookiePolicy.isFrame%20&&%20!cookiePolicy.isTracker%20&&%20cookiePolicy.isThirdPartyFrame%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20CookieFeature%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20load%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.documentOriginIsTracker)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.isTracker%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.trackerLookup)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trackerLookup%20=%20this.trackerLookup;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.bundledConfig)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20use%20the%20bundled%20config%20to%20get%20a%20best-effort%20at%20the%20policy,%20before%20the%20background%20sends%20the%20real%20one%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20exceptions,%20settings%20%7D%20=%20this.bundledConfig.features.cookie;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20tabHostname%20=%20getTabHostname();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20tabExempted%20=%20true;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(tabHostname%20!=%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tabExempted%20=%20exceptions.some((exception)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20matchHostname(tabHostname,%20exception.domain)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20frameExempted%20=%20settings.excludedCookieDomains.some((exception)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20matchHostname(globalThis.location.hostname,%20exception.domain)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.shouldBlock%20=%20!frameExempted%20&&%20!tabExempted;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.policy%20=%20settings.firstPartyCookiePolicy;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.trackerPolicy%20=%20settings.firstPartyTrackerCookiePolicy;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Allows%20for%20ad%20click%20conversion%20detection%20as%20described%20by%20https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20This%20only%20applies%20when%20the%20resources%20that%20would%20set%20these%20cookies%20are%20unblocked.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy.allowlist%20=%20this.getFeatureSetting('allowlist',%20'adClickAttribution')%20%7C%7C%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20cookie%20policy%20is%20injected%20into%20every%20frame%20immediately%20so%20that%20no%20cookie%20will%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20be%20missed.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20document%20=%20globalThis.document;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cookieSetter%20=%20Object.getOwnPropertyDescriptor(globalThis.Document.prototype,%20'cookie').set;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20Object%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20cookieGetter%20=%20Object.getOwnPropertyDescriptor(globalThis.Document.prototype,%20'cookie').get;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20loadPolicy%20=%20new%20Promise((resolve)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadedPolicyResolve%20=%20resolve;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Create%20the%20then%20callback%20now%20-%20this%20ensures%20that%20Promise.prototype.then%20changes%20won't%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20this%20call.%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20loadPolicyThen%20=%20loadPolicy.then.bind(loadPolicy);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20getCookiePolicy%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20getStackTraceOrigins(stack);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20getCookieContext%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20'getter'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldBlockTrackingCookie()%20%7C%7C%20shouldBlockNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('block',%20'3p%20frame',%20getCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20''%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(isTrackingCookie()%20%7C%7C%20isNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'3p%20frame',%20getCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'cookieSetter'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20cookieGetter.call(document)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20setCookiePolicy%20(value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20stack%20=%20getStack();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20scriptOrigins%20=%20getStackTraceOrigins(stack);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20setCookieContext%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20scriptOrigins,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldBlockTrackingCookie()%20%7C%7C%20shouldBlockNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('block',%20'3p%20frame',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(isTrackingCookie()%20%7C%7C%20isNonTrackingCookie())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'3p%20frame',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20call%20the%20native%20document.cookie%20implementation.%20This%20will%20set%20the%20cookie%20immediately%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20if%20the%20value%20is%20valid.%20We%20will%20override%20this%20set%20later%20if%20the%20policy%20dictates%20that%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20the%20expiry%20should%20be%20changed.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'cookieSetter'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookieSetter.call(document,%20value);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20wait%20for%20config%20before%20doing%20same-site%20tests%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadPolicyThen(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20shouldBlock,%20policy,%20trackerPolicy%20%7D%20=%20cookiePolicy;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20chosenPolicy%20=%20isFirstPartyTrackerScript(scriptOrigins)%20?%20trackerPolicy%20:%20policy;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!shouldBlock)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'disabled',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20extract%20cookie%20expiry%20from%20cookie%20string%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20cookie%20=%20new%20Cookie(value);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20apply%20cookie%20policy%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(cookie.getExpiry()%20%3E%20chosenPolicy.threshold)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20check%20if%20the%20cookie%20still%20exists%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(document.cookie.split(';').findIndex(kv%20=%3E%20kv.trim().startsWith(cookie.parts%5B0%5D.trim()))%20!==%20-1)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookie.maxAge%20=%20chosenPolicy.maxAge;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('restrict',%20'expiry',%20setCookieContext);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS18048:%20'cookieSetter'%20is%20possibly%20'undefined'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookieSetter.apply(document,%20%5Bcookie.toString()%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'dissappeared',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'expiry',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debugHelper('ignore',%20'error',%20setCookieContext);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20suppress%20error%20in%20cookie%20override%20to%20avoid%20breakage%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.warn('Error%20in%20cookie%20override',%20e);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(document,%20'cookie',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20set:%20setCookiePolicy,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20getCookiePolicy%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20restOfPolicy%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20debug:%20this.isDebug,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shouldBlockTrackerCookie:%20this.getFeatureSettingEnabled('trackerCookie'),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shouldBlockNonTrackerCookie:%20this.getFeatureSettingEnabled('nonTrackerCookie'),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20allowlist:%20this.getFeatureSetting('allowlist',%20'adClickAttribution')%20%7C%7C%20%5B%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20policy:%20this.getFeatureSetting('firstPartyCookiePolicy'),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trackerPolicy:%20this.getFeatureSetting('firstPartyTrackerCookiePolicy')%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20extension%20provides%20some%20additional%20info%20about%20the%20cookie%20policy,%20let's%20use%20that%20over%20our%20guesses%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.cookie)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20extensionCookiePolicy%20=%20/**%20@type%20%7BExtensionCookiePolicy%7D%20*/(args.cookie);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20...extensionCookiePolicy,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20...restOfPolicy%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cookiePolicy%20=%20Object.assign(cookiePolicy,%20restOfPolicy);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20loadedPolicyResolve();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20GoogleRejected%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('browsingTopics'%20in%20Document.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Document.prototype.browsingTopics;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('joinAdInterestGroup'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.joinAdInterestGroup;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('leaveAdInterestGroup'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.leaveAdInterestGroup;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('updateAdInterestGroups'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.updateAdInterestGroups;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('runAdAuction'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.runAdAuction;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20('adAuctionComponents'%20in%20Navigator.prototype)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20Navigator.prototype.adAuctionComponents;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Throw%20away%20this%20exception,%20it's%20likely%20a%20confict%20with%20another%20extension%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Set%20Global%20Privacy%20Control%20property%20on%20DOM%0A%20%20%20%20class%20GlobalPrivacyControl%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20GPC%20on,%20set%20DOM%20property%20prototype%20to%20true%20if%20not%20already%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.globalPrivacyControlValue)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(navigator.globalPrivacyControl)%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'globalPrivacyControl',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20()%20=%3E%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20GPC%20off%20&%20unsupported%20by%20browser,%20set%20DOM%20property%20prototype%20to%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20this%20may%20be%20overwritten%20by%20the%20user%20agent%20or%20other%20extensions%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20navigator.globalPrivacyControl%20!==%20'undefined')%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'globalPrivacyControl',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20()%20=%3E%20false,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Ignore%20exceptions%20that%20could%20be%20caused%20by%20conflicting%20with%20other%20extensions%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingHardware%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20Navigator%20=%20globalThis.Navigator;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20navigator%20=%20globalThis.navigator;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('keyboard',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Navigator.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20navigator.keyboard,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20error%20TS2554:%20Expected%202%20arguments,%20but%20got%201.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('keyboard')%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('hardwareConcurrency',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Navigator.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20navigator.hardwareConcurrency,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('hardwareConcurrency',%202)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('deviceMemory',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Navigator.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20navigator.deviceMemory,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('deviceMemory',%208)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Referrer%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Unfortunately,%20we%20only%20have%20limited%20information%20about%20the%20referrer%20and%20current%20frame.%20A%20single%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20page%20may%20load%20many%20requests%20and%20sub%20frames,%20all%20with%20different%20referrers.%20Since%20we%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(args.referrer%20&&%20//%20make%20sure%20the%20referrer%20was%20set%20correctly%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20args.referrer.referrer%20!==%20undefined%20&&%20//%20referrer%20value%20will%20be%20undefined%20when%20it%20should%20be%20unchanged.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document.referrer%20&&%20//%20don't%20change%20the%20value%20if%20it%20isn't%20set%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20document.referrer%20!==%20''%20&&%20//%20don't%20add%20referrer%20information%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20new%20URL(document.URL).hostname%20!==%20new%20URL(document.referrer).hostname)%20%7B%20//%20don't%20replace%20the%20referrer%20for%20the%20current%20host.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20trimmedReferer%20=%20document.referrer;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(new%20URL(document.referrer).hostname%20===%20args.referrer.referrerHost)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20make%20sure%20the%20real%20referrer%20&%20replacement%20referrer%20match%20if%20we're%20going%20to%20replace%20it%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trimmedReferer%20=%20args.referrer.referrer;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20if%20we%20don't%20have%20a%20matching%20referrer,%20just%20trim%20it%20to%20origin.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trimmedReferer%20=%20new%20URL(document.referrer).origin%20+%20'/';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('referrer',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Document.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20document.referrer,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20trimmedReferer%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20normalize%20window%20dimensions,%20if%20more%20than%20one%20monitor%20is%20in%20play.%0A%20%20%20%20%20*%20%20X/Y%20values%20are%20set%20in%20the%20browser%20based%20on%20distance%20to%20the%20main%20monitor%20top%20or%20left,%20which%0A%20%20%20%20%20*%20can%20mean%20second%20or%20more%20monitors%20have%20very%20large%20or%20negative%20values.%20This%20function%20maps%20a%20given%0A%20%20%20%20%20*%20given%20coordinate%20value%20to%20the%20proper%20place%20on%20the%20main%20screen.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20normalizeWindowDimension%20(value,%20targetDimension)%20%7B%0A%20%20%20%20%20%20%20%20if%20(value%20%3E%20targetDimension)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20value%20%25%20targetDimension%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(value%20%3C%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20targetDimension%20+%20value%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20value%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20setWindowPropertyValue%20(property,%20value)%20%7B%0A%20%20%20%20%20%20%20%20//%20Here%20we%20don't%20update%20the%20prototype%20getter%20because%20the%20values%20are%20updated%20dynamically%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(globalThis,%20property,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20get:%20()%20=%3E%20value,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20@typescript-eslint/no-empty-function%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20set:%20()%20=%3E%20%7B%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20origPropertyValues%20=%20%7B%7D;%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Fix%20window%20dimensions.%20The%20extension%20runs%20in%20a%20different%20JS%20context%20than%20the%0A%20%20%20%20%20*%20page,%20so%20we%20can%20inject%20the%20correct%20screen%20values%20as%20the%20window%20is%20resized,%0A%20%20%20%20%20*%20ensuring%20that%20no%20information%20is%20leaked%20as%20the%20dimensions%20change,%20but%20also%20that%20the%0A%20%20%20%20%20*%20values%20change%20correctly%20for%20valid%20use%20cases.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20setWindowDimensions%20()%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20window%20=%20globalThis;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20top%20=%20globalThis.top;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20normalizedY%20=%20normalizeWindowDimension(window.screenY,%20window.screen.height);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20normalizedX%20=%20normalizeWindowDimension(window.screenX,%20window.screen.width);%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(normalizedY%20%3C=%20origPropertyValues.availTop)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenY',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenTop',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenY',%20normalizedY);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenTop',%20normalizedY);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(top.window.outerHeight%20%3E=%20origPropertyValues.availHeight%20-%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerHeight',%20top.window.screen.height);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerHeight',%20top.window.outerHeight);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20top%20not%20accessible%20to%20certain%20iFrames,%20so%20ignore.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(normalizedX%20%3C=%20origPropertyValues.availLeft)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenX',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenLeft',%200);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenX',%20normalizedX);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('screenLeft',%20normalizedX);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(top.window.outerWidth%20%3E=%20origPropertyValues.availWidth%20-%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerWidth',%20top.window.screen.width);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20-%20%20error%20TS18047:%20'top'%20is%20possibly%20'null'.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowPropertyValue('outerWidth',%20top.window.outerWidth);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20top%20not%20accessible%20to%20certain%20iFrames,%20so%20ignore.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20in%20a%20cross%20domain%20iFrame,%20top.window%20is%20not%20accessible.%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingScreenSize%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20Screen%20=%20globalThis.Screen;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20screen%20=%20globalThis.screen;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availTop%20=%20overrideProperty('availTop',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availTop,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('availTop',%200)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availLeft%20=%20overrideProperty('availLeft',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availLeft,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('availLeft',%200)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availWidth%20=%20overrideProperty('availWidth',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availWidth,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20screen.width%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20origPropertyValues.availHeight%20=%20overrideProperty('availHeight',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.availHeight,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20screen.height%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('colorDepth',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.colorDepth,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('colorDepth',%2024)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideProperty('pixelDepth',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20object:%20Screen.prototype,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20origValue:%20screen.pixelDepth,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetValue:%20this.getFeatureAttr('pixelDepth',%2024)%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('resize',%20function%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20setWindowDimensions();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20setWindowDimensions();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20FingerprintingTemporaryStorage%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20navigator%20=%20globalThis.navigator;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20Navigator%20=%20globalThis.Navigator;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20Temporary%20storage%20can%20be%20used%20to%20determine%20hard%20disk%20usage%20and%20size.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20This%20will%20limit%20the%20max%20storage%20to%204GB%20without%20completely%20disabling%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*%20feature.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(navigator.webkitTemporaryStorage)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20org%20=%20navigator.webkitTemporaryStorage.queryUsageAndQuota;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20tStorage%20=%20navigator.webkitTemporaryStorage;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tStorage.queryUsageAndQuota%20=%20function%20queryUsageAndQuota%20(callback,%20err)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20modifiedCallback%20=%20function%20(usedBytes,%20grantedBytes)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20maxBytesGranted%20=%204%20*%201024%20*%201024%20*%201024;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20spoofedGrantedBytes%20=%20Math.min(grantedBytes,%20maxBytesGranted);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20callback(usedBytes,%20spoofedGrantedBytes);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20org.call(navigator.webkitTemporaryStorage,%20modifiedCallback,%20err);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'webkitTemporaryStorage',%20%7B%20get:%20()%20=%3E%20tStorage%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20catch%20(e)%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20injectNavigatorInterface%20(args)%20%7B%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(navigator.duckduckgo)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!args.platform%20%7C%7C%20!args.platform.name)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20defineProperty(Navigator.prototype,%20'duckduckgo',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20platform:%20args.platform.name,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isDuckDuckGo%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGPromise.resolve(true)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20enumerable:%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20configurable:%20false,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20writable:%20false%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%20catch%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20todo:%20Just%20ignore%20this%20exception?%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20NavigatorInterface%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20load%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.matchDomainFeatureSetting('privilegedDomains').length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20injectNavigatorInterface(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20injectNavigatorInterface(args);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20adLabelStrings%20=%20%5B%5D;%0A%20%20%20%20const%20parser%20=%20new%20DOMParser();%0A%20%20%20%20let%20hiddenElements%20=%20new%20WeakMap();%0A%20%20%20%20let%20appliedRules%20=%20new%20Set();%0A%20%20%20%20let%20shouldInjectStyleTag%20=%20false;%0A%20%20%20%20let%20mediaAndFormSelectors%20=%20'video,canvas,embed,object,audio,map,form,input,textarea,select,option,button';%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hide%20DOM%20element%20if%20rule%20conditions%20met%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20rule%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20%5BpreviousElement%5D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20collapseDomNode%20(element,%20rule,%20previousElement)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20type%20=%20rule.type;%0A%20%20%20%20%20%20%20%20const%20alreadyHidden%20=%20hiddenElements.has(element);%0A%0A%20%20%20%20%20%20%20%20if%20(alreadyHidden)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20switch%20(type)%20%7B%0A%20%20%20%20%20%20%20%20case%20'hide':%0A%20%20%20%20%20%20%20%20%20%20%20%20hideNode(element);%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20case%20'hide-empty':%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(isDomNodeEmpty(element))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hideNode(element);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20appliedRules.add(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20case%20'closest-empty':%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20hide%20the%20outermost%20empty%20node%20so%20that%20we%20may%20unhide%20if%20ad%20loads%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(isDomNodeEmpty(element))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20collapseDomNode(element.parentNode,%20rule,%20element);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(previousElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hideNode(previousElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20appliedRules.add(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Unhide%20previously%20hidden%20DOM%20element%20if%20content%20loaded%20into%20it%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*%20@param%20%7BObject%7D%20rule%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20%5BpreviousElement%5D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20expandNonEmptyDomNode%20(element,%20rule,%20previousElement)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20const%20type%20=%20rule.type;%0A%0A%20%20%20%20%20%20%20%20const%20alreadyHidden%20=%20hiddenElements.has(element);%0A%0A%20%20%20%20%20%20%20%20switch%20(type)%20%7B%0A%20%20%20%20%20%20%20%20case%20'hide':%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20only%20care%20about%20rule%20types%20that%20specifically%20apply%20to%20empty%20elements%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20case%20'hide-empty':%0A%20%20%20%20%20%20%20%20case%20'closest-empty':%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(alreadyHidden%20&&%20!isDomNodeEmpty(element))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unhideNode(element);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if%20(type%20===%20'closest-empty')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20iterate%20upwards%20from%20matching%20DOM%20elements%20until%20we%20arrive%20at%20previously%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20hidden%20element.%20Unhide%20element%20if%20it%20contains%20visible%20content.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20expandNonEmptyDomNode(element.parentNode,%20rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hide%20DOM%20element%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20hideNode%20(element)%20%7B%0A%20%20%20%20%20%20%20%20//%20maintain%20a%20reference%20to%20each%20hidden%20element%20along%20with%20the%20properties%0A%20%20%20%20%20%20%20%20//%20that%20are%20being%20overwritten%0A%20%20%20%20%20%20%20%20const%20cachedDisplayProperties%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20display:%20element.style.display,%0A%20%20%20%20%20%20%20%20%20%20%20%20'min-height':%20element.style.minHeight,%0A%20%20%20%20%20%20%20%20%20%20%20%20height:%20element.style.height%0A%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20hiddenElements.set(element,%20cachedDisplayProperties);%0A%0A%20%20%20%20%20%20%20%20//%20apply%20styles%20to%20hide%20element%0A%20%20%20%20%20%20%20%20element.style.setProperty('display',%20'none',%20'important');%0A%20%20%20%20%20%20%20%20element.style.setProperty('min-height',%20'0px',%20'important');%0A%20%20%20%20%20%20%20%20element.style.setProperty('height',%20'0px',%20'important');%0A%20%20%20%20%20%20%20%20element.hidden%20=%20true;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Show%20previously%20hidden%20DOM%20element%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20unhideNode%20(element)%20%7B%0A%20%20%20%20%20%20%20%20const%20cachedDisplayProperties%20=%20hiddenElements.get(element);%0A%20%20%20%20%20%20%20%20if%20(!cachedDisplayProperties)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20(const%20prop%20in%20cachedDisplayProperties)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20element.style.setProperty(prop,%20cachedDisplayProperties%5Bprop%5D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20hiddenElements.delete(element);%0A%20%20%20%20%20%20%20%20element.hidden%20=%20false;%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Check%20if%20DOM%20element%20contains%20visible%20content%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20node%0A%20%20%20%20%20*/%0A%20%20%20%20function%20isDomNodeEmpty%20(node)%20%7B%0A%20%20%20%20%20%20%20%20//%20no%20sense%20wasting%20cycles%20checking%20if%20the%20page's%20body%20element%20is%20empty%0A%20%20%20%20%20%20%20%20if%20(node.tagName%20===%20'BODY')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20//%20use%20a%20DOMParser%20to%20remove%20all%20metadata%20elements%20before%20checking%20if%0A%20%20%20%20%20%20%20%20//%20the%20node%20is%20empty.%0A%20%20%20%20%20%20%20%20const%20parsedNode%20=%20parser.parseFromString(node.outerHTML,%20'text/html').documentElement;%0A%20%20%20%20%20%20%20%20parsedNode.querySelectorAll('base,link,meta,script,style,template,title,desc').forEach((el)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20el.remove();%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20const%20visibleText%20=%20parsedNode.innerText.trim().toLocaleLowerCase().replace(/:$/,%20'');%0A%20%20%20%20%20%20%20%20const%20mediaAndFormContent%20=%20parsedNode.querySelector(mediaAndFormSelectors);%0A%20%20%20%20%20%20%20%20const%20frameElements%20=%20%5B...parsedNode.querySelectorAll('iframe')%5D;%0A%20%20%20%20%20%20%20%20//%20query%20original%20node%20instead%20of%20parsedNode%20for%20img%20elements%20since%20heuristic%20relies%0A%20%20%20%20%20%20%20%20//%20on%20size%20of%20image%20elements%0A%20%20%20%20%20%20%20%20const%20imageElements%20=%20%5B...node.querySelectorAll('img,svg')%5D;%0A%20%20%20%20%20%20%20%20//%20about:blank%20iframes%20don't%20count%20as%20content,%20return%20true%20if:%0A%20%20%20%20%20%20%20%20//%20-%20node%20doesn't%20contain%20any%20iframes%0A%20%20%20%20%20%20%20%20//%20-%20node%20contains%20iframes,%20all%20of%20which%20are%20hidden%20or%20have%20src='about:blank'%0A%20%20%20%20%20%20%20%20const%20noFramesWithContent%20=%20frameElements.every((frame)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(frame.hidden%20%7C%7C%20frame.src%20===%20'about:blank')%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20//%20ad%20containers%20often%20contain%20tracking%20pixels%20and%20other%20small%20images%20(eg%20adchoices%20logo).%0A%20%20%20%20%20%20%20%20//%20these%20should%20be%20treated%20as%20empty%20and%20hidden,%20but%20real%20images%20should%20not.%0A%20%20%20%20%20%20%20%20const%20visibleImages%20=%20imageElements.some((image)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20(image.getBoundingClientRect().width%20%3E%2020%20%7C%7C%20image.getBoundingClientRect().height%20%3E%2020)%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20if%20((visibleText%20===%20''%20%7C%7C%20adLabelStrings.includes(visibleText))%20&&%0A%20%20%20%20%20%20%20%20%20%20%20%20mediaAndFormContent%20===%20null%20&&%20noFramesWithContent%20&&%20!visibleImages)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Apply%20relevant%20hiding%20rules%20to%20page%20at%20set%20intervals%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20applyRules%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20const%20hideTimeouts%20=%20%5B0,%20100,%20200,%20300,%20400,%20500,%201000,%201500,%202000,%202500,%203000%5D;%0A%20%20%20%20%20%20%20%20const%20unhideTimeouts%20=%20%5B750,%201500,%202250,%203000%5D;%0A%20%20%20%20%20%20%20%20const%20timeoutRules%20=%20extractTimeoutRules(rules);%0A%0A%20%20%20%20%20%20%20%20//%20several%20passes%20are%20made%20to%20hide%20&%20unhide%20elements.%20this%20is%20necessary%20because%20we're%20not%20using%0A%20%20%20%20%20%20%20%20//%20a%20mutation%20observer%20but%20we%20want%20to%20hide/unhide%20elements%20as%20soon%20as%20possible,%20and%20ads%0A%20%20%20%20%20%20%20%20//%20frequently%20take%20from%20several%20hundred%20milliseconds%20to%20several%20seconds%20to%20load%0A%20%20%20%20%20%20%20%20//%20check%20at%200ms,%20100ms,%20200ms,%20300ms,%20400ms,%20500ms,%201000ms,%201500ms,%202000ms,%202500ms,%203000ms%0A%20%20%20%20%20%20%20%20hideTimeouts.forEach((timeout)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20hideAdNodes(timeoutRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20timeout);%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20//%20check%20previously%20hidden%20ad%20elements%20for%20contents,%20unhide%20if%20content%20has%20loaded%20after%20hiding.%0A%20%20%20%20%20%20%20%20//%20we%20do%20this%20in%20order%20to%20display%20non-tracking%20ads%20that%20aren't%20blocked%20at%20the%20request%20level%0A%20%20%20%20%20%20%20%20//%20check%20at%20750ms,%201500ms,%202250ms,%203000ms%0A%20%20%20%20%20%20%20%20unhideTimeouts.forEach((timeout)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unhideLoadedAds();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20timeout);%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20//%20clear%20appliedRules%20and%20hiddenElements%20caches%20once%20all%20checks%20have%20run%0A%20%20%20%20%20%20%20%20setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20appliedRules%20=%20new%20Set();%0A%20%20%20%20%20%20%20%20%20%20%20%20hiddenElements%20=%20new%20WeakMap();%0A%20%20%20%20%20%20%20%20%7D,%203100);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Separate%20strict%20hide%20rules%20to%20inject%20as%20style%20tag%20if%20enabled%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20extractTimeoutRules%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!shouldInjectStyleTag)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20rules%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20strictHideRules%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20const%20timeoutRules%20=%20%5B%5D;%0A%0A%20%20%20%20%20%20%20%20rules.forEach((rule,%20i)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(rule.type%20===%20'hide')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20strictHideRules.push(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20timeoutRules.push(rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20injectStyleTag(strictHideRules);%0A%20%20%20%20%20%20%20%20return%20timeoutRules%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20styletag%20for%20strict%20hide%20rules%20and%20append%20it%20to%20the%20document%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20injectStyleTag%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20let%20styleTagContents%20=%20'';%0A%0A%20%20%20%20%20%20%20%20rules.forEach((rule,%20i)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(i%20!==%20rules.length%20-%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleTagContents%20=%20styleTagContents.concat(rule.selector,%20',');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleTagContents%20=%20styleTagContents.concat(rule.selector);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20styleTagContents%20=%20styleTagContents.concat('%7Bdisplay:none!important;min-height:0!important;height:0!important;%7D');%0A%20%20%20%20%20%20%20%20injectGlobalStyles(styleTagContents);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Apply%20list%20of%20active%20element%20hiding%20rules%20to%20page%0A%20%20%20%20%20*%20@param%20%7BObject%5B%5D%7D%20rules%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.selector%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20rules%5B%5D.type%0A%20%20%20%20%20*/%0A%20%20%20%20function%20hideAdNodes%20(rules)%20%7B%0A%20%20%20%20%20%20%20%20const%20document%20=%20globalThis.document;%0A%0A%20%20%20%20%20%20%20%20rules.forEach((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20matchingElementArray%20=%20%5B...document.querySelectorAll(rule.selector)%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20matchingElementArray.forEach((element)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20@ts-expect-error%20https://app.asana.com/0/1201614831475344/1203979574128023/f%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20collapseDomNode(element,%20rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Iterate%20over%20previously%20hidden%20elements,%20unhiding%20if%20content%20has%20loaded%20into%20them%0A%20%20%20%20%20*/%0A%20%20%20%20function%20unhideLoadedAds%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20document%20=%20globalThis.document;%0A%0A%20%20%20%20%20%20%20%20appliedRules.forEach((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20matchingElementArray%20=%20%5B...document.querySelectorAll(rule.selector)%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20matchingElementArray.forEach((element)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20expandNonEmptyDomNode(element,%20rule);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20ElementHiding%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(isBeingFramed())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureName%20=%20'elementHiding';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20globalRules%20=%20this.getFeatureSetting('rules');%0A%20%20%20%20%20%20%20%20%20%20%20%20adLabelStrings%20=%20this.getFeatureSetting('adLabelStrings');%0A%20%20%20%20%20%20%20%20%20%20%20%20shouldInjectStyleTag%20=%20this.getFeatureSetting('useStrictHideStyleTag');%0A%20%20%20%20%20%20%20%20%20%20%20%20mediaAndFormSelectors%20=%20this.getFeatureSetting('mediaAndFormSelectors')%20%7C%7C%20mediaAndFormSelectors;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20determine%20whether%20strict%20hide%20rules%20should%20be%20injected%20as%20a%20style%20tag%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldInjectStyleTag)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shouldInjectStyleTag%20=%20this.matchDomainFeatureSetting('styleTagExceptions').length%20===%200;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20collect%20all%20matching%20rules%20for%20domain%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20activeDomainRules%20=%20this.matchDomainFeatureSetting('domains').flatMap((item)%20=%3E%20item.rules);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20overrideRules%20=%20activeDomainRules.filter((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20rule.type%20===%20'override'%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20activeRules%20=%20activeDomainRules.concat(globalRules);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20remove%20overrides%20and%20rules%20that%20match%20overrides%20from%20array%20of%20rules%20to%20be%20applied%20to%20page%0A%20%20%20%20%20%20%20%20%20%20%20%20overrideRules.forEach((override)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20activeRules%20=%20activeRules.filter((rule)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20rule.selector%20!==%20override.selector%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20now%20have%20the%20final%20list%20of%20rules%20to%20apply,%20so%20we%20apply%20them%20when%20document%20is%20loaded%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(document.readyState%20===%20'loading')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('DOMContentLoaded',%20(event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20single%20page%20applications%20don't%20have%20a%20DOMContentLoaded%20event%20on%20navigations,%20so%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20we%20use%20proxy/reflect%20on%20history.pushState%20to%20call%20applyRules%20on%20page%20navigations%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20historyMethodProxy%20=%20new%20DDGProxy(featureName,%20History.prototype,%20'pushState',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20apply%20(target,%20thisArg,%20args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20DDGReflect.apply(target,%20thisArg,%20args)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20historyMethodProxy.overload();%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20listen%20for%20popstate%20events%20in%20order%20to%20run%20on%20back/forward%20navigations%0A%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('popstate',%20(event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20applyRules(activeRules);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20ExceptionHandler%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20init%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Report%20to%20the%20debugger%20panel%20if%20an%20uncaught%20exception%20occurs%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20handleUncaughtException%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20postDebugMessage('jsException',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20documentUrl:%20document.location.href,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20message:%20e.message,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20filename:%20e.filename,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lineno:%20e.lineno,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20colno:%20e.colno,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20stack:%20e.error?.stack%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20globalThis.addEventListener('error',%20handleUncaughtException);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20const%20logoImg%20=%20'data:image/png;base64,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';%0A%20%20%20%20const%20loadingImages%20=%20%7B%0A%20%20%20%20%20%20%20%20darkMode:%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252220%2522%2520height%253D%252220%2522%2520viewBox%253D%25220%25200%252020%252020%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2540keyframes%2520rotate%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520from%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%25280deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520to%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%2528359deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cg%2520style%253D%2522transform-origin%253A%252050%2525%252050%2525%253B%2520animation%253A%2520rotate%25201s%2520infinite%2520reverse%2520linear%253B%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252218.0968%2522%2520y%253D%252216.0861%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%252018.0968%252016.0861%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.1%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.4%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252219.9976%2522%2520y%253D%25228.37451%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%252019.9976%25208.37451%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.2%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252216.1727%2522%2520y%253D%25221.9917%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%252016.1727%25201.9917%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.3%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.91309%2522%2520y%253D%25226.88501%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%25208.91309%25206.88501%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25226.79602%2522%2520y%253D%252210.996%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%25206.79602%252010.996%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.7%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25227%2522%2520y%253D%25228.62549%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%25207%25208.62549%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.8%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520y%253D%252213%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.9%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fg%253E%250A%2520%2520%2520%2520%253C%252Fsvg%253E',%0A%20%20%20%20%20%20%20%20lightMode:%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252220%2522%2520height%253D%252220%2522%2520viewBox%253D%25220%25200%252020%252020%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2540keyframes%2520rotate%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520from%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%25280deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520to%2520%257B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520transform%253A%2520rotate%2528359deg%2529%253B%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%257D%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fstyle%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253Cg%2520style%253D%2522transform-origin%253A%252050%2525%252050%2525%253B%2520animation%253A%2520rotate%25201s%2520infinite%2520reverse%2520linear%253B%2522%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252218.0968%2522%2520y%253D%252216.0861%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%252018.0968%252016.0861%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.1%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.4%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252219.9976%2522%2520y%253D%25228.37451%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%252019.9976%25208.37451%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.2%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%252216.1727%2522%2520y%253D%25221.9917%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%252016.1727%25201.9917%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.3%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.91309%2522%2520y%253D%25226.88501%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%2528136.161%25208.91309%25206.88501%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25226.79602%2522%2520y%253D%252210.996%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252846.1607%25206.79602%252010.996%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.7%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25227%2522%2520y%253D%25228.62549%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520transform%253D%2522rotate%252890%25207%25208.62549%2529%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.8%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%2520%253Crect%2520x%253D%25228.49878%2522%2520y%253D%252213%2522%2520width%253D%25223%2522%2520height%253D%25227%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523111111%2522%2520fill-opacity%253D%25220.9%2522%252F%253E%250A%2520%2520%2520%2520%2520%2520%2520%2520%253C%252Fg%253E%250A%2520%2520%2520%2520%253C%252Fsvg%253E'%20//%20'data:application/octet-stream;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxzdHlsZT4KCQlAa2V5ZnJhbWVzIHJvdGF0ZSB7CgkJCWZyb20gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CgkJCX0KCQkJdG8gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMzU5ZGVnKTsKCQkJfQoJCX0KCTwvc3R5bGU+Cgk8ZyBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTAlIDUwJTsgYW5pbWF0aW9uOiByb3RhdGUgMXMgaW5maW5pdGUgcmV2ZXJzZSBsaW5lYXI7Ij4KCQk8cmVjdCB4PSIxOC4wOTY4IiB5PSIxNi4wODYxIiB3aWR0aD0iMyIgaGVpZ2h0PSI3IiByeD0iMS41IiB0cmFuc2Zvcm09InJvdGF0ZSgxMzYuMTYxIDE4LjA5NjggMTYuMDg2MSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+CQoJCTxyZWN0IHg9IjguNDk4NzgiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CgkJPHJlY3QgeD0iMTkuOTk3NiIgeT0iOC4zNzQ1MSIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgdHJhbnNmb3JtPSJyb3RhdGUoOTAgMTkuOTk3NiA4LjM3NDUxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjIiLz4KCQk8cmVjdCB4PSIxNi4xNzI3IiB5PSIxLjk5MTciIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgMTYuMTcyNyAxLjk5MTcpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuMyIvPgoJCTxyZWN0IHg9IjguOTEzMDkiIHk9IjYuODg1MDEiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDEzNi4xNjEgOC45MTMwOSA2Ljg4NTAxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KCQk8cmVjdCB4PSI2Ljc5NjAyIiB5PSIxMC45OTYiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgNi43OTYwMiAxMC45OTYpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuNyIvPgoJCTxyZWN0IHg9IjciIHk9IjguNjI1NDkiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDkwIDcgOC42MjU0OSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC44Ii8+CQkKCQk8cmVjdCB4PSI4LjQ5ODc4IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjkiLz4KCTwvZz4KPC9zdmc+Cg=='%0A%20%20%20%20%7D;%0A%20%20%20%20const%20closeIcon%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252212%2522%2520height%253D%252212%2522%2520viewBox%253D%25220%25200%252012%252012%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%253Cpath%2520fill-rule%253D%2522evenodd%2522%2520clip-rule%253D%2522evenodd%2522%2520d%253D%2522M5.99998%25204.58578L10.2426%25200.34314C10.6331%2520-0.0473839%252011.2663%2520-0.0473839%252011.6568%25200.34314C12.0474%25200.733665%252012.0474%25201.36683%252011.6568%25201.75735L7.41419%25205.99999L11.6568%252010.2426C12.0474%252010.6332%252012.0474%252011.2663%252011.6568%252011.6568C11.2663%252012.0474%252010.6331%252012.0474%252010.2426%252011.6568L5.99998%25207.41421L1.75734%252011.6568C1.36681%252012.0474%25200.733649%252012.0474%25200.343125%252011.6568C-0.0473991%252011.2663%2520-0.0473991%252010.6332%25200.343125%252010.2426L4.58577%25205.99999L0.343125%25201.75735C-0.0473991%25201.36683%2520-0.0473991%25200.733665%25200.343125%25200.34314C0.733649%2520-0.0473839%25201.36681%2520-0.0473839%25201.75734%25200.34314L5.99998%25204.58578Z%2522%2520fill%253D%2522%2523222222%2522%252F%253E%250A%253C%252Fsvg%253E';%0A%0A%20%20%20%20const%20blockedFBLogo%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252280%2522%2520height%253D%252280%2522%2520viewBox%253D%25220%25200%252080%252080%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%253Ccircle%2520cx%253D%252240%2522%2520cy%253D%252240%2522%2520r%253D%252240%2522%2520fill%253D%2522white%2522%252F%253E%250A%253Cg%2520clip-path%253D%2522url%2528%2523clip0%2529%2522%253E%250A%253Cpath%2520d%253D%2522M73.8457%252039.974C73.8457%252021.284%252058.7158%25206.15405%252040.0258%25206.15405C21.3358%25206.15405%25206.15344%252021.284%25206.15344%252039.974C6.15344%252056.884%252018.5611%252070.8622%252034.7381%252073.4275V49.764H26.0999V39.974H34.7381V32.5399C34.7381%252024.0587%252039.764%252019.347%252047.5122%252019.347C51.2293%252019.347%252055.0511%252020.0799%252055.0511%252020.0799V28.3517H50.8105C46.6222%252028.3517%252045.2611%252030.9693%252045.2611%252033.6393V39.974H54.6846L53.1664%252049.764H45.2611V73.4275C61.4381%252070.9146%252073.8457%252056.884%252073.8457%252039.974Z%2522%2520fill%253D%2522%25231877F2%2522%252F%253E%250A%253C%252Fg%253E%250A%253Crect%2520x%253D%25223.01295%2522%2520y%253D%252211.7158%2522%2520width%253D%252212.3077%2522%2520height%253D%252292.3077%2522%2520rx%253D%25226.15385%2522%2520transform%253D%2522rotate%2528-45%25203.01295%252011.7158%2529%2522%2520fill%253D%2522%2523666666%2522%2520stroke%253D%2522white%2522%2520stroke-width%253D%25226.15385%2522%252F%253E%250A%253Cdefs%253E%250A%253CclipPath%2520id%253D%2522clip0%2522%253E%250A%253Crect%2520width%253D%252267.6923%2522%2520height%253D%252267.6923%2522%2520fill%253D%2522white%2522%2520transform%253D%2522translate%25286.15344%25206.15405%2529%2522%252F%253E%250A%253C%252FclipPath%253E%250A%253C%252Fdefs%253E%250A%253C%252Fsvg%253E';%0A%0A%20%20%20%20const%20blockedYTVideo%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252275%2522%2520height%253D%252275%2522%2520viewBox%253D%25220%25200%252075%252075%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%253Crect%2520x%253D%25226.75%2522%2520y%253D%252215.75%2522%2520width%253D%252256.25%2522%2520height%253D%252239%2522%2520rx%253D%252213.5%2522%2520fill%253D%2522%2523DE5833%2522%252F%253E%250A%2520%2520%253Cmask%2520id%253D%2522path-2-outside-1_885_11045%2522%2520maskUnits%253D%2522userSpaceOnUse%2522%2520x%253D%252223.75%2522%2520y%253D%252222.5%2522%2520width%253D%252224%2522%2520height%253D%252226%2522%2520fill%253D%2522black%2522%253E%250A%2520%2520%253Crect%2520fill%253D%2522white%2522%2520x%253D%252223.75%2522%2520y%253D%252222.5%2522%2520width%253D%252224%2522%2520height%253D%252226%2522%252F%253E%250A%2520%2520%253Cpath%2520d%253D%2522M41.9425%252037.5279C43.6677%252036.492%252043.6677%252033.9914%252041.9425%252032.9555L31.0394%252026.4088C29.262%252025.3416%252027%252026.6218%252027%252028.695L27%252041.7884C27%252043.8615%252029.262%252045.1418%252031.0394%252044.0746L41.9425%252037.5279Z%2522%252F%253E%250A%2520%2520%253C%252Fmask%253E%250A%2520%2520%253Cpath%2520d%253D%2522M41.9425%252037.5279C43.6677%252036.492%252043.6677%252033.9914%252041.9425%252032.9555L31.0394%252026.4088C29.262%252025.3416%252027%252026.6218%252027%252028.695L27%252041.7884C27%252043.8615%252029.262%252045.1418%252031.0394%252044.0746L41.9425%252037.5279Z%2522%2520fill%253D%2522white%2522%252F%253E%250A%2520%2520%253Cpath%2520d%253D%2522M30.0296%252044.6809L31.5739%252047.2529L30.0296%252044.6809ZM30.0296%252025.8024L31.5739%252023.2304L30.0296%252025.8024ZM42.8944%252036.9563L44.4387%252039.5283L42.8944%252036.9563ZM41.35%252036.099L28.4852%252028.3744L31.5739%252023.2304L44.4387%252030.955L41.35%252036.099ZM30%252027.5171L30%252042.9663L24%252042.9663L24%252027.5171L30%252027.5171ZM28.4852%252042.1089L41.35%252034.3843L44.4387%252039.5283L31.5739%252047.2529L28.4852%252042.1089ZM30%252042.9663C30%252042.1888%252029.1517%252041.7087%252028.4852%252042.1089L31.5739%252047.2529C28.2413%252049.2539%252024%252046.8535%252024%252042.9663L30%252042.9663ZM28.4852%252028.3744C29.1517%252028.7746%252030%252028.2945%252030%252027.5171L24%252027.5171C24%252023.6299%252028.2413%252021.2294%252031.5739%252023.2304L28.4852%252028.3744ZM44.4387%252030.955C47.6735%252032.8974%252047.6735%252037.586%252044.4387%252039.5283L41.35%252034.3843C40.7031%252034.7728%252040.7031%252035.7105%252041.35%252036.099L44.4387%252030.955Z%2522%2520fill%253D%2522%2523BC4726%2522%2520mask%253D%2522url(%2523path-2-outside-1_885_11045)%2522%252F%253E%250A%2520%2520%253Ccircle%2520cx%253D%252257.75%2522%2520cy%253D%252252.5%2522%2520r%253D%252213.5%2522%2520fill%253D%2522%2523E0E0E0%2522%252F%253E%250A%2520%2520%253Crect%2520x%253D%252248.75%2522%2520y%253D%252250.25%2522%2520width%253D%252218%2522%2520height%253D%25224.5%2522%2520rx%253D%25221.5%2522%2520fill%253D%2522%2523666666%2522%252F%253E%250A%2520%2520%253Cpath%2520fill-rule%253D%2522evenodd%2522%2520clip-rule%253D%2522evenodd%2522%2520d%253D%2522M57.9853%252015.8781C58.2046%252016.1015%252058.5052%252016.2262%252058.8181%252016.2238C59.1311%252016.2262%252059.4316%252016.1015%252059.6509%252015.8781L62.9821%252012.5469C63.2974%252012.2532%252063.4272%252011.8107%252063.3206%252011.3931C63.2139%252010.9756%252062.8879%252010.6495%252062.4703%252010.5429C62.0528%252010.4363%252061.6103%252010.5661%252061.3165%252010.8813L57.9853%252014.2125C57.7627%252014.4325%252057.6374%252014.7324%252057.6374%252015.0453C57.6374%252015.3583%252057.7627%252015.6582%252057.9853%252015.8781ZM61.3598%252018.8363C61.388%252019.4872%252061.9385%252019.9919%252062.5893%252019.9637L62.6915%252019.9559L66.7769%252019.6023C67.4278%252019.5459%252067.9097%252018.9726%252067.8533%252018.3217C67.7968%252017.6708%252067.2235%252017.1889%252066.5726%252017.2453L62.4872%252017.6067C61.8363%252017.6349%252061.3316%252018.1854%252061.3598%252018.8363Z%2522%2520fill%253D%2522%2523AAAAAA%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%2520%2520%253Cpath%2520fill-rule%253D%2522evenodd%2522%2520clip-rule%253D%2522evenodd%2522%2520d%253D%2522M10.6535%252015.8781C10.4342%252016.1015%252010.1336%252016.2262%25209.82067%252016.2238C9.5077%252016.2262%25209.20717%252016.1015%25208.98787%252015.8781L5.65667%252012.5469C5.34138%252012.2532%25205.2116%252011.8107%25205.31823%252011.3931C5.42487%252010.9756%25205.75092%252010.6495%25206.16847%252010.5429C6.58602%252010.4363%25207.02848%252010.5661%25207.32227%252010.8813L10.6535%252014.2125C10.8761%252014.4325%252011.0014%252014.7324%252011.0014%252015.0453C11.0014%252015.3583%252010.8761%252015.6582%252010.6535%252015.8781ZM7.2791%252018.8362C7.25089%252019.4871%25206.7004%252019.9919%25206.04954%252019.9637L5.9474%252019.9558L1.86197%252019.6023C1.44093%252019.5658%25201.07135%252019.3074%25200.892432%252018.9246C0.713515%252018.5417%25200.752449%252018.0924%25200.994567%252017.7461C1.23669%252017.3997%25201.6452%252017.2088%25202.06624%252017.2453L6.15167%252017.6067C6.80254%252017.6349%25207.3073%252018.1854%25207.2791%252018.8362Z%2522%2520fill%253D%2522%2523AAAAAA%2522%2520fill-opacity%253D%25220.6%2522%252F%253E%250A%253C%252Fsvg%253E%250A';%0A%20%20%20%20const%20videoPlayDark%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252222%2522%2520height%253D%252226%2522%2520viewBox%253D%25220%25200%252022%252026%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%253Cpath%2520d%253D%2522M21%252011.2679C22.3333%252012.0377%252022.3333%252013.9622%252021%252014.732L3%252025.1244C1.66667%252025.8942%25202.59376e-06%252024.9319%25202.66105e-06%252023.3923L3.56958e-06%25202.60769C3.63688e-06%25201.06809%25201.66667%25200.105844%25203%25200.875644L21%252011.2679Z%2522%2520fill%253D%2522%2523222222%2522%252F%253E%250A%253C%252Fsvg%253E%250A';%0A%20%20%20%20const%20videoPlayLight%20=%20'data:image/svg+xml;utf8,%253Csvg%2520width%253D%252222%2522%2520height%253D%252226%2522%2520viewBox%253D%25220%25200%252022%252026%2522%2520fill%253D%2522none%2522%2520xmlns%253D%2522http%253A%252F%252Fwww.w3.org%252F2000%252Fsvg%2522%253E%250A%2520%2520%253Cpath%2520d%253D%2522M21%252011.2679C22.3333%252012.0377%252022.3333%252013.9622%252021%252014.732L3%252025.1244C1.66667%252025.8942%25202.59376e-06%252024.9319%25202.66105e-06%252023.3923L3.56958e-06%25202.60769C3.63688e-06%25201.06809%25201.66667%25200.105844%25203%25200.875644L21%252011.2679Z%2522%2520fill%253D%2522%2523FFFFFF%2522%252F%253E%250A%253C%252Fsvg%253E';%0A%0A%20%20%20%20var%20localesJSON%20=%20%60%7B%22bg%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%9F%D1%80%D0%B8%20%D0%B2%D0%BB%D0%B8%D0%B7%D0%B0%D0%BD%D0%B5%20%D1%80%D0%B0%D0%B7%D1%80%D0%B5%D1%88%D0%B0%D0%B2%D0%B0%D1%82%D0%B5%20%D0%BD%D0%B0%20Facebook%20%D0%B4%D0%B0%20%D0%92%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%22,%22informationalModalMessageBody%22:%22%D0%A1%D0%BB%D0%B5%D0%B4%20%D0%BA%D0%B0%D1%82%D0%BE%20%D0%B2%D0%BB%D0%B5%D0%B7%D0%B5%D1%82%D0%B5,%20DuckDuckGo%20%D0%BD%D0%B5%20%D0%BC%D0%BE%D0%B6%D0%B5%20%D0%B4%D0%B0%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BE%D1%82%20Facebook%20%D0%B2%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5%D1%82%D0%BE%20%D0%BD%D0%B0%20%D1%82%D0%BE%D0%B7%D0%B8%20%D1%81%D0%B0%D0%B9%D1%82.%22,%22informationalModalConfirmButtonText%22:%22%D0%92%D1%85%D0%BE%D0%B4%22,%22informationalModalRejectButtonText%22:%22%D0%9D%D0%B0%D0%B7%D0%B0%D0%B4%22,%22loginButtonText%22:%22%D0%92%D1%85%D0%BE%D0%B4%20%D0%B2%D1%8A%D0%B2%20Facebook%22,%22loginBodyText%22:%22Facebook%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%20%D0%92%D0%B0%D1%88%D0%B0%D1%82%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82%20%D0%B2%20%D1%81%D1%8A%D0%BE%D1%82%D0%B2%D0%B5%D1%82%D0%BD%D0%B8%D1%8F%20%D1%81%D0%B0%D0%B9%D1%82,%20%D0%BA%D0%BE%D0%B3%D0%B0%D1%82%D0%BE%20%D0%B3%D0%BE%20%D0%B8%D0%B7%D0%BF%D0%BE%D0%BB%D0%B7%D0%B2%D0%B0%D1%82%D0%B5%20%D0%B7%D0%B0%20%D0%B2%D1%85%D0%BE%D0%B4.%22,%22buttonTextUnblockContent%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5%D1%82%D0%BE%22,%22buttonTextUnblockComment%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B0%22,%22buttonTextUnblockComments%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D1%82%D0%B5%22,%22buttonTextUnblockPost%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F%D1%82%D0%B0%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D1%82%D0%BE%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B2%D0%B0%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B7%D0%B8%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%B5%D0%B7%D0%B8%20%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%B0%D0%B7%D0%B8%20%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B2%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Facebook%22,%22infoTextUnblockContent%22:%22%D0%91%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%85%D0%BC%D0%B5%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BE%D1%82%20Facebook%20%D0%BF%D1%80%D0%B8%20%D0%B7%D0%B0%D1%80%D0%B5%D0%B6%D0%B4%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0%D1%82%D0%B0.%20%D0%90%D0%BA%D0%BE%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%82%D0%B5%20%D1%82%D0%BE%D0%B2%D0%B0%20%D1%81%D1%8A%D0%B4%D1%8A%D1%80%D0%B6%D0%B0%D0%BD%D0%B8%D0%B5,%20Facebook%20%D1%89%D0%B5%20%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%20%D0%92%D0%B0%D1%88%D0%B0%D1%82%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22%D0%9D%D0%B0%D1%83%D1%87%D0%B5%D1%82%D0%B5%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%87%D0%B5%22,%22readAbout%22:%22%D0%9F%D1%80%D0%BE%D1%87%D0%B5%D1%82%D0%B5%D1%82%D0%B5%20%D0%B7%D0%B0%20%D1%82%D0%B0%D0%B7%D0%B8%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0%20%D0%BD%D0%B0%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%BE%D1%81%D1%82%D1%82%D0%B0%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%90%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D1%81%D0%B8%D1%87%D0%BA%D0%B8%20%D0%BF%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%20%D0%B2%20YouTube?%22,%22informationalModalMessageBody%22:%22%D0%9F%D0%BE%D0%BA%D0%B0%D0%B7%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BD%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%20%D0%BF%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D0%B2%D0%B0%20%D0%BD%D0%B0%20Google%20(%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%B8%D0%BA%20%D0%BD%D0%B0%20YouTube)%20%D0%B4%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B8%20%D1%87%D0%B0%D1%81%D1%82%20%D0%BE%D1%82%20%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8F%D1%82%D0%B0%20%D0%B7%D0%B0%20%D0%92%D0%B0%D1%88%D0%B5%D1%82%D0%BE%20%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%BE,%20%D0%BD%D0%BE%20%D0%B2%D1%81%D0%B5%20%D0%BF%D0%B0%D0%BA%20%D0%BE%D1%81%D0%B8%D0%B3%D1%83%D1%80%D1%8F%D0%B2%D0%B0%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%87%D0%B5%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%BE%D1%81%D1%82%20%D0%BE%D1%82%D0%BA%D0%BE%D0%BB%D0%BA%D0%BE%D1%82%D0%BE%20%D0%BF%D1%80%D0%B8%20%D0%B2%D1%8A%D0%B7%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B6%D0%B4%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D0%BA%D0%BB%D0%B8%D0%BF%D0%B0.%22,%22informationalModalConfirmButtonText%22:%22%D0%90%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D1%81%D0%B8%D1%87%D0%BA%D0%B8%20%D0%BF%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%22,%22informationalModalRejectButtonText%22:%22%D0%9D%D0%B5,%20%D0%B1%D0%BB%D0%B0%D0%B3%D0%BE%D0%B4%D0%B0%D1%80%D1%8F%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D1%82%D0%BE%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%20%D1%82%D0%BE%D0%B7%D0%B8%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D0%BA%D0%BB%D0%B8%D0%BF%20%D0%B2%20YouTube,%20%D0%B7%D0%B0%20%D0%B4%D0%B0%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BE%D1%82%D0%B2%D1%80%D0%B0%D1%82%D0%B8%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BE%D1%82%20Google%22,%22infoTextUnblockVideo%22:%22%D0%91%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%85%D0%BC%D0%B5%20%D0%BF%D1%80%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%D1%82%D0%BE%20%D0%BE%D1%82%20Google%20(%D1%81%D0%BE%D0%B1%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%B8%D0%BA%20%D0%BD%D0%B0%20YouTube)%20%D0%BF%D1%80%D0%B8%20%D0%B7%D0%B0%D1%80%D0%B5%D0%B6%D0%B4%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0%D1%82%D0%B0.%20%D0%90%D0%BA%D0%BE%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%B0%D1%82%D0%B5%20%D1%82%D0%BE%D0%B7%D0%B8%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%D0%BA%D0%BB%D0%B8%D0%BF,%20Google%20%D1%89%D0%B5%20%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%20%D0%92%D0%B0%D1%88%D0%B0%D1%82%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82.%22,%22infoPreviewToggleText%22:%22%D0%9F%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D0%B5%20%D1%81%D0%B0%20%D0%B4%D0%B5%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B8%20%D0%B7%D0%B0%20%D0%BE%D1%81%D0%B8%D0%B3%D1%83%D1%80%D1%8F%D0%B2%D0%B0%D0%BD%D0%B5%20%D0%BD%D0%B0%20%D0%B4%D0%BE%D0%BF%D1%8A%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%B0%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D0%BD%D0%BE%D1%81%D1%82%22,%22infoPreviewToggleEnabledText%22:%22%D0%9F%D1%80%D0%B5%D0%B3%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D0%B5%20%D1%81%D0%B0%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%B8%D1%80%D0%B0%D0%BD%D0%B8%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3E%D0%9D%D0%B0%D1%83%D1%87%D0%B5%D1%82%D0%B5%20%D0%BF%D0%BE%D0%B2%D0%B5%D1%87%D0%B5%3C/a%3E%20%D0%B7%D0%B0%20%D0%B2%D0%B3%D1%80%D0%B0%D0%B4%D0%B5%D0%BD%D0%B0%D1%82%D0%B0%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B0%20%D0%BE%D1%82%20%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D0%BB%D0%BD%D0%B8%20%D0%BC%D0%B5%D0%B4%D0%B8%D0%B8%20%D0%BD%D0%B0%20DuckDuckGo%22%7D%7D,%22cs%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Kdy%C5%BE%20se%20p%C5%99ihl%C3%A1s%C3%AD%C5%A1%20p%C5%99es%20Facebook,%20bude%20t%C4%9B%20moct%20sledovat%22,%22informationalModalMessageBody%22:%22Po%20p%C5%99ihl%C3%A1%C5%A1en%C3%AD%20u%C5%BE%20DuckDuckGo%20nem%C5%AF%C5%BEe%20br%C3%A1nit%20Facebooku,%20aby%20t%C4%9B%20na%20t%C3%A9hle%20str%C3%A1nce%20sledoval.%22,%22informationalModalConfirmButtonText%22:%22P%C5%99ihl%C3%A1sit%20se%22,%22informationalModalRejectButtonText%22:%22Zp%C4%9Bt%22,%22loginButtonText%22:%22P%C5%99ihl%C3%A1sit%20se%20pomoc%C3%AD%20Facebooku%22,%22loginBodyText%22:%22Facebook%20sleduje%20tvou%20aktivitu%20na%20webu,%20kdy%C5%BE%20se%20p%C5%99ihl%C3%A1s%C3%AD%C5%A1%20jeho%20prost%C5%99ednictv%C3%ADm.%22,%22buttonTextUnblockContent%22:%22Odblokovat%20obsah%22,%22buttonTextUnblockComment%22:%22Odblokovat%20koment%C3%A1%C5%99%22,%22buttonTextUnblockComments%22:%22Odblokovat%20koment%C3%A1%C5%99e%22,%22buttonTextUnblockPost%22:%22Odblokovat%20p%C5%99%C3%ADsp%C4%9Bvek%22,%22buttonTextUnblockVideo%22:%22Odblokovat%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20zablokoval%20tenhle%20obsah,%20aby%20Facebooku%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTitleUnblockComment%22:%22Slu%C5%BEba%20DuckDuckGo%20zablokovala%20tento%20koment%C3%A1%C5%99,%20aby%20Facebooku%20zabr%C3%A1nila%20ve%20tv%C3%A9m%20sledov%C3%A1n%C3%AD%22,%22infoTitleUnblockComments%22:%22Slu%C5%BEba%20DuckDuckGo%20zablokovala%20tyto%20koment%C3%A1%C5%99e,%20aby%20Facebooku%20zabr%C3%A1nila%20ve%20tv%C3%A9m%20sledov%C3%A1n%C3%AD%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20zablokoval%20tenhle%20p%C5%99%C3%ADsp%C4%9Bvek,%20aby%20Facebooku%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokoval%20tohle%20video,%20aby%20Facebooku%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTextUnblockContent%22:%22P%C5%99i%20na%C4%8D%C3%ADt%C3%A1n%C3%AD%20str%C3%A1nky%20jsme%20Facebooku%20zabr%C3%A1nili,%20aby%20t%C4%9B%20sledoval.%20Kdy%C5%BE%20tenhle%20obsah%20odblokuje%C5%A1,%20Facebook%20bude%20m%C3%ADt%20p%C5%99%C3%ADstup%20ke%20tv%C3%A9%20aktivit%C4%9B.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22V%C3%ADce%20informac%C3%AD%22,%22readAbout%22:%22P%C5%99e%C4%8Dti%20si%20o%C2%A0t%C3%A9hle%20ochran%C4%9B%20soukrom%C3%AD%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Zapnout%20v%C5%A1echny%20n%C3%A1hledy%20YouTube?%22,%22informationalModalMessageBody%22:%22Zobrazov%C3%A1n%C3%AD%20n%C3%A1hled%C5%AF%20umo%C5%BEn%C3%AD%20spole%C4%8Dnosti%20Google%20(kter%C3%A1%20vlastn%C3%AD%20YouTube)%20zobrazit%20n%C4%9Bkter%C3%A9%20informace%20o%C2%A0tv%C3%A9m%20za%C5%99%C3%ADzen%C3%AD,%20ale%20po%C5%99%C3%A1d%20jde%20o%C2%A0diskr%C3%A9tn%C4%9Bj%C5%A1%C3%AD%20volbu,%20ne%C5%BE%20je%20p%C5%99ehr%C3%A1v%C3%A1n%C3%AD%20videa.%22,%22informationalModalConfirmButtonText%22:%22Zapnout%20v%C5%A1echny%20n%C3%A1hledy%22,%22informationalModalRejectButtonText%22:%22Ne,%20d%C4%9Bkuji%22,%22buttonTextUnblockVideo%22:%22Odblokovat%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokoval%20tohle%20video%20z%C2%A0YouTube,%20aby%20Googlu%20zabr%C3%A1nil%20t%C4%9B%20sledovat%22,%22infoTextUnblockVideo%22:%22Zabr%C3%A1nili%20jsme%20spole%C4%8Dnosti%20Google%20(kter%C3%A1%20vlastn%C3%AD%20YouTube),%20aby%20t%C4%9B%20p%C5%99i%20na%C4%8D%C3%ADt%C3%A1n%C3%AD%20str%C3%A1nky%20sledovala.%20Pokud%20toto%20video%20odblokuje%C5%A1,%20Google%20z%C3%ADsk%C3%A1%20p%C5%99%C3%ADstup%20ke%20tv%C3%A9%20aktivit%C4%9B.%22,%22infoPreviewToggleText%22:%22N%C3%A1hledy%20jsou%20pro%20v%C4%9Bt%C5%A1%C3%AD%20soukrom%C3%AD%20vypnut%C3%A9%22,%22infoPreviewToggleEnabledText%22:%22N%C3%A1hledy%20jsou%20zapnut%C3%A9%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EDal%C5%A1%C3%AD%20informace%3C/a%3E%20o%C2%A0ochran%C4%9B%20DuckDuckGo%20p%C5%99ed%20sledov%C3%A1n%C3%ADm%20prost%C5%99ednictv%C3%ADm%20vlo%C5%BEen%C3%A9ho%20obsahu%20ze%20soci%C3%A1ln%C3%ADch%20m%C3%A9di%C3%AD%22%7D%7D,%22da%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22N%C3%A5r%20du%20logger%20ind%20med%20Facebook,%20kan%20de%20spore%20dig%22,%22informationalModalMessageBody%22:%22N%C3%A5r%20du%20er%20logget%20ind,%20kan%20DuckDuckGo%20ikke%20blokere%20for,%20at%20indhold%20fra%20Facebook%20sporer%20dig%20p%C3%A5%20dette%20websted.%22,%22informationalModalConfirmButtonText%22:%22Log%20p%C3%A5%22,%22informationalModalRejectButtonText%22:%22G%C3%A5%20tilbage%22,%22loginButtonText%22:%22Log%20ind%20med%20Facebook%22,%22loginBodyText%22:%22Facebook%20sporer%20din%20aktivitet%20p%C3%A5%20et%20websted,%20n%C3%A5r%20du%20bruger%20dem%20til%20at%20logge%20ind.%22,%22buttonTextUnblockContent%22:%22Fjern%20blokering%20af%20indhold%22,%22buttonTextUnblockComment%22:%22Fjern%20blokering%20af%20kommentar%22,%22buttonTextUnblockComments%22:%22Fjern%20blokering%20af%20kommentarer%22,%22buttonTextUnblockPost%22:%22Fjern%20blokering%20af%20indl%C3%A6g%22,%22buttonTextUnblockVideo%22:%22Fjern%20blokering%20af%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20har%20blokeret%20dette%20indhold%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20har%20blokeret%20denne%20kommentar%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20har%20blokeret%20disse%20kommentarer%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blokerede%20dette%20indl%C3%A6g%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20har%20blokeret%20denne%20video%20for%20at%20forhindre%20Facebook%20i%20at%20spore%20dig%22,%22infoTextUnblockContent%22:%22Vi%20blokerede%20for,%20at%20Facebook%20sporede%20dig,%20da%20siden%20blev%20indl%C3%A6st.%20Hvis%20du%20oph%C3%A6ver%20blokeringen%20af%20dette%20indhold,%20vil%20Facebook%20kende%20din%20aktivitet.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Mere%20info%22,%22readAbout%22:%22L%C3%A6s%20om%20denne%20beskyttelse%20af%20privatlivet%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Vil%20du%20aktivere%20alle%20YouTube-forh%C3%A5ndsvisninger?%22,%22informationalModalMessageBody%22:%22Med%20forh%C3%A5ndsvisninger%20kan%20Google%20(som%20ejer%20YouTube)%20se%20nogle%20af%20enhedens%20oplysninger,%20men%20det%20er%20stadig%20mere%20privat%20end%20at%20afspille%20videoen.%22,%22informationalModalConfirmButtonText%22:%22Aktiv%C3%A9r%20alle%20forh%C3%A5ndsvisninger%22,%22informationalModalRejectButtonText%22:%22Nej%20tak.%22,%22buttonTextUnblockVideo%22:%22Fjern%20blokering%20af%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20har%20blokeret%20denne%20YouTube-video%20for%20at%20forhindre%20Google%20i%20at%20spore%20dig%22,%22infoTextUnblockVideo%22:%22Vi%20blokerede%20Google%20(som%20ejer%20YouTube)%20fra%20at%20spore%20dig,%20da%20siden%20blev%20indl%C3%A6st.%20Hvis%20du%20fjerner%20blokeringen%20af%20denne%20video,%20vil%20Google%20f%C3%A5%20kendskab%20til%20din%20aktivitet.%22,%22infoPreviewToggleText%22:%22Forh%C3%A5ndsvisninger%20er%20deaktiveret%20for%20at%20give%20yderligere%20privatliv%22,%22infoPreviewToggleEnabledText%22:%22Forh%C3%A5ndsvisninger%20er%20deaktiveret%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EF%C3%A5%20mere%20at%20vide%20p%C3%A5%3C/a%3E%20om%20DuckDuckGos%20indbyggede%20beskyttelse%20p%C3%A5%20sociale%20medier%22%7D%7D,%22de%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Wenn%20du%20dich%20bei%20Facebook%20anmeldest,%20kann%20Facebook%20dich%20tracken%22,%22informationalModalMessageBody%22:%22Sobald%20du%20angemeldet%20bist,%20kann%20DuckDuckGo%20nicht%20mehr%20verhindern,%20dass%20Facebook-Inhalte%20dich%20auf%20dieser%20Website%20tracken.%22,%22informationalModalConfirmButtonText%22:%22Anmelden%22,%22informationalModalRejectButtonText%22:%22Zur%C3%BCck%22,%22loginButtonText%22:%22Mit%20Facebook%20anmelden%22,%22loginBodyText%22:%22Facebook%20trackt%20deine%20Aktivit%C3%A4t%20auf%20einer%20Website,%20wenn%20du%20dich%20%C3%BCber%20Facebook%20dort%20anmeldest.%22,%22buttonTextUnblockContent%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockComment%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockComments%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockPost%22:%22Blockierung%20aufheben%22,%22buttonTextUnblockVideo%22:%22Blockierung%20aufheben%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20hat%20diesen%20Inhalt%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20hat%20diesen%20Kommentar%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20hat%20diese%20Kommentare%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20hat%20diesen%20Beitrag%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20hat%20dieses%20Video%20blockiert,%20um%20zu%20verhindern,%20dass%20Facebook%20dich%20trackt%22,%22infoTextUnblockContent%22:%22Wir%20haben%20Facebook%20daran%20gehindert,%20dich%20zu%20tracken,%20als%20die%20Seite%20geladen%20wurde.%20Wenn%20du%20die%20Blockierung%20f%C3%BCr%20diesen%20Inhalt%20aufhebst,%20kennt%20Facebook%20deine%20Aktivit%C3%A4ten.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Mehr%20erfahren%22,%22readAbout%22:%22Weitere%20Informationen%20%C3%BCber%20diesen%20Datenschutz%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Alle%20YouTube-Vorschauen%20aktivieren?%22,%22informationalModalMessageBody%22:%22Durch%20das%20Anzeigen%20von%20Vorschauen%20kann%20Google%20(dem%20YouTube%20geh%C3%B6rt)%20einige%20Informationen%20zu%20deinem%20Ger%C3%A4t%20sehen.%20Dies%20ist%20aber%20immer%20noch%20privater%20als%20das%20Abspielen%20des%20Videos.%22,%22informationalModalConfirmButtonText%22:%22Alle%20Vorschauen%20aktivieren%22,%22informationalModalRejectButtonText%22:%22Nein,%20danke%22,%22buttonTextUnblockVideo%22:%22Blockierung%20aufheben%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20hat%20dieses%20YouTube-Video%20blockiert,%20um%20zu%20verhindern,%20dass%20Google%20dich%20trackt.%22,%22infoTextUnblockVideo%22:%22Wir%20haben%20Google%20(dem%20YouTube%20geh%C3%B6rt)%20daran%20gehindert,%20dich%20beim%20Laden%20der%20Seite%20zu%20tracken.%20Wenn%20du%20die%20Blockierung%20f%C3%BCr%20dieses%20Video%20aufhebst,%20kennt%20Google%20deine%20Aktivit%C3%A4ten.%22,%22infoPreviewToggleText%22:%22Vorschau%20f%C3%BCr%20mehr%20Privatsph%C3%A4re%20deaktiviert%22,%22infoPreviewToggleEnabledText%22:%22Vorschau%20aktiviert%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EErfahre%20mehr%3C/a%3E%20%C3%BCber%20den%20DuckDuckGo-Schutz%20vor%20eingebetteten%20Social%20Media-Inhalten%22%7D%7D,%22el%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%CE%97%20%CF%83%CF%8D%CE%BD%CE%B4%CE%B5%CF%83%CE%B7%20%CE%BC%CE%AD%CF%83%CF%89%20Facebook%20%CF%84%CE%BF%CF%85%CF%82%20%CE%B5%CF%80%CE%B9%CF%84%CF%81%CE%AD%CF%80%CE%B5%CE%B9%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%BF%CF%8D%CE%BD%22,%22informationalModalMessageBody%22:%22%CE%9C%CF%8C%CE%BB%CE%B9%CF%82%20%CF%83%CF%85%CE%BD%CE%B4%CE%B5%CE%B8%CE%B5%CE%AF%CF%84%CE%B5,%20%CF%84%CE%BF%20DuckDuckGo%20%CE%B4%CE%B5%CE%BD%20%CE%BC%CF%80%CE%BF%CF%81%CE%B5%CE%AF%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CF%8C%CE%BC%CE%B5%CE%BD%CE%BF%20%CF%84%CE%BF%CF%85%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%83%CE%B5%20%CE%B1%CF%85%CF%84%CF%8C%CE%BD%20%CF%84%CE%BF%CE%BD%20%CE%B9%CF%83%CF%84%CF%8C%CF%84%CE%BF%CF%80%CE%BF.%22,%22informationalModalConfirmButtonText%22:%22%CE%A3%CF%8D%CE%BD%CE%B4%CE%B5%CF%83%CE%B7%22,%22informationalModalRejectButtonText%22:%22%CE%95%CF%80%CE%B9%CF%83%CF%84%CF%81%CE%BF%CF%86%CE%AE%22,%22loginButtonText%22:%22%CE%A3%CF%8D%CE%BD%CE%B4%CE%B5%CF%83%CE%B7%20%CE%BC%CE%AD%CF%83%CF%89%20Facebook%22,%22loginBodyText%22:%22%CE%A4%CE%BF%20Facebook%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%84%CE%B7%20%CE%B4%CF%81%CE%B1%CF%83%CF%84%CE%B7%CF%81%CE%B9%CF%8C%CF%84%CE%B7%CF%84%CE%AC%20%CF%83%CE%B1%CF%82%20%CF%83%CE%B5%20%CE%AD%CE%BD%CE%B1%CE%BD%20%CE%B9%CF%83%CF%84%CF%8C%CF%84%CE%BF%CF%80%CE%BF%20%CF%8C%CF%84%CE%B1%CE%BD%20%CF%84%CE%BF%CE%BD%20%CF%87%CF%81%CE%B7%CF%83%CE%B9%CE%BC%CE%BF%CF%80%CE%BF%CE%B9%CE%B5%CE%AF%CF%84%CE%B5%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CF%83%CF%85%CE%BD%CE%B4%CE%B5%CE%B8%CE%B5%CE%AF%CF%84%CE%B5.%22,%22buttonTextUnblockContent%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CE%BF%CE%BC%CE%AD%CE%BD%CE%BF%CF%85%22,%22buttonTextUnblockComment%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CF%83%CF%87%CE%BF%CE%BB%CE%AF%CE%BF%CF%85%22,%22buttonTextUnblockComments%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CF%83%CF%87%CE%BF%CE%BB%CE%AF%CF%89%CE%BD%22,%22buttonTextUnblockPost%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B1%CE%BD%CE%AC%CF%81%CF%84%CE%B7%CF%83%CE%B7%CF%82%22,%22buttonTextUnblockVideo%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%22,%22infoTitleUnblockContent%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CF%8C%CE%BC%CE%B5%CE%BD%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockComment%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CF%83%CF%87%CF%8C%CE%BB%CE%B9%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockComments%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%B1%20%CF%83%CF%87%CF%8C%CE%BB%CE%B9%CE%B1%20%CE%B1%CF%85%CF%84%CE%AC%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockPost%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%B7%CE%BD%20%CE%B1%CE%BD%CE%AC%CF%81%CF%84%CE%B7%CF%83%CE%B7%20%CE%B1%CF%85%CF%84%CE%AE%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTitleUnblockVideo%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTextUnblockContent%22:%22%CE%91%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%AF%CF%83%CE%B1%CE%BC%CE%B5%20%CF%84%CE%BF%20Facebook%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%8C%CF%84%CE%B1%CE%BD%20%CF%86%CE%BF%CF%81%CF%84%CF%8E%CE%B8%CE%B7%CE%BA%CE%B5%20%CE%B7%20%CF%83%CE%B5%CE%BB%CE%AF%CE%B4%CE%B1.%20%CE%95%CE%AC%CE%BD%20%CE%BA%CE%AC%CE%BD%CE%B5%CF%84%CE%B5%20%CE%AC%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B3%CE%B9'%20%CE%B1%CF%85%CF%84%CF%8C%20%CF%84%CE%BF%20%CF%80%CE%B5%CF%81%CE%B9%CE%B5%CF%87%CF%8C%CE%BC%CE%B5%CE%BD%CE%BF,%20%CF%84%CE%BF%20Facebook%20%CE%B8%CE%B1%20%CE%B3%CE%BD%CF%89%CF%81%CE%AF%CE%B6%CE%B5%CE%B9%20%CF%84%CE%B7%20%CE%B4%CF%81%CE%B1%CF%83%CF%84%CE%B7%CF%81%CE%B9%CF%8C%CF%84%CE%B7%CF%84%CE%AC%20%CF%83%CE%B1%CF%82.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22%CE%9C%CE%AC%CE%B8%CE%B5%CF%84%CE%B5%20%CF%80%CE%B5%CF%81%CE%B9%CF%83%CF%83%CF%8C%CF%84%CE%B5%CF%81%CE%B1%22,%22readAbout%22:%22%CE%94%CE%B9%CE%B1%CE%B2%CE%AC%CF%83%CF%84%CE%B5%20%CF%83%CF%87%CE%B5%CF%84%CE%B9%CE%BA%CE%AC%20%CE%BC%CE%B5%20%CF%84%CE%B7%CE%BD%20%CF%80%CE%B1%CF%81%CE%BF%CF%8D%CF%83%CE%B1%20%CF%80%CF%81%CE%BF%CF%83%CF%84%CE%B1%CF%83%CE%AF%CE%B1%CF%82%20%CF%80%CF%81%CE%BF%CF%83%CF%89%CF%80%CE%B9%CE%BA%CF%8E%CE%BD%20%CE%B4%CE%B5%CE%B4%CE%BF%CE%BC%CE%AD%CE%BD%CF%89%CE%BD%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%CE%95%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%AF%CE%B7%CF%83%CE%B7%20%CF%8C%CE%BB%CF%89%CE%BD%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CF%89%CE%BD%20%CF%84%CE%BF%CF%85%20YouTube;%22,%22informationalModalMessageBody%22:%22%CE%97%20%CF%80%CF%81%CE%BF%CE%B2%CE%BF%CE%BB%CE%AE%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CF%89%CE%BD%20%CE%B8%CE%B1%20%CE%B5%CF%80%CE%B9%CF%84%CF%81%CE%AD%CF%88%CE%B5%CE%B9%20%CF%83%CF%84%CE%B7%CE%BD%20Google%20(%CF%83%CF%84%CE%B7%CE%BD%20%CE%BF%CF%80%CE%BF%CE%AF%CE%B1%20%CE%B1%CE%BD%CE%AE%CE%BA%CE%B5%CE%B9%20%CF%84%CE%BF%20YouTube)%20%CE%BD%CE%B1%20%CE%B2%CE%BB%CE%AD%CF%80%CE%B5%CE%B9%20%CE%BF%CF%81%CE%B9%CF%83%CE%BC%CE%AD%CE%BD%CE%B5%CF%82%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%B9%CF%82%20%CF%80%CE%BB%CE%B7%CF%81%CE%BF%CF%86%CE%BF%CF%81%CE%AF%CE%B5%CF%82%20%CF%84%CE%B7%CF%82%20%CF%83%CF%85%CF%83%CE%BA%CE%B5%CF%85%CE%AE%CF%82%20%CF%83%CE%B1%CF%82,%20%CF%89%CF%83%CF%84%CF%8C%CF%83%CE%BF%20%CE%B5%CE%BE%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CE%BD%CE%B1%20%CE%B5%CE%AF%CE%BD%CE%B1%CE%B9%20%CF%80%CE%B9%CE%BF%20%CE%B9%CE%B4%CE%B9%CF%89%CF%84%CE%B9%CE%BA%CE%AE%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%B7%CE%BD%20%CE%B1%CE%BD%CE%B1%CF%80%CE%B1%CF%81%CE%B1%CE%B3%CF%89%CE%B3%CE%AE%20%CF%84%CE%BF%CF%85%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF.%22,%22informationalModalConfirmButtonText%22:%22%CE%95%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%AF%CE%B7%CF%83%CE%B7%20%CF%8C%CE%BB%CF%89%CE%BD%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CF%89%CE%BD%22,%22informationalModalRejectButtonText%22:%22%CE%8C%CF%87%CE%B9,%20%CE%B5%CF%85%CF%87%CE%B1%CF%81%CE%B9%CF%83%CF%84%CF%8E%22,%22buttonTextUnblockVideo%22:%22%CE%86%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%22,%22infoTitleUnblockVideo%22:%22%CE%A4%CE%BF%20DuckDuckGo%20%CE%B1%CF%80%CE%AD%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%B5%20%CF%84%CE%BF%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF%20%CE%B1%CF%85%CF%84%CF%8C%20%CF%83%CF%84%CE%BF%20YouTube%20%CE%B3%CE%B9%CE%B1%20%CE%BD%CE%B1%20%CE%B5%CE%BC%CF%80%CE%BF%CE%B4%CE%AF%CF%83%CE%B5%CE%B9%20%CF%84%CE%B7%CE%BD%20Google%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%22,%22infoTextUnblockVideo%22:%22%CE%91%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%AF%CF%83%CE%B1%CE%BC%CE%B5%20%CF%84%CE%B7%CE%BD%20Google%20(%CF%83%CF%84%CE%B7%CE%BD%20%CE%BF%CF%80%CE%BF%CE%AF%CE%B1%20%CE%B1%CE%BD%CE%AE%CE%BA%CE%B5%CE%B9%20%CF%84%CE%BF%20YouTube)%20%CE%B1%CF%80%CF%8C%20%CF%84%CE%BF%20%CE%BD%CE%B1%20%CF%83%CE%B1%CF%82%20%CF%80%CE%B1%CF%81%CE%B1%CE%BA%CE%BF%CE%BB%CE%BF%CF%85%CE%B8%CE%B5%CE%AF%20%CF%8C%CF%84%CE%B1%CE%BD%20%CF%86%CE%BF%CF%81%CF%84%CF%8E%CE%B8%CE%B7%CE%BA%CE%B5%20%CE%B7%20%CF%83%CE%B5%CE%BB%CE%AF%CE%B4%CE%B1.%20%CE%95%CE%AC%CE%BD%20%CE%BA%CE%AC%CE%BD%CE%B5%CF%84%CE%B5%20%CE%AC%CF%81%CF%83%CE%B7%20%CE%B1%CF%80%CE%BF%CE%BA%CE%BB%CE%B5%CE%B9%CF%83%CE%BC%CE%BF%CF%8D%20%CE%B3%CE%B9'%20%CE%B1%CF%85%CF%84%CF%8C%20%CF%84%CE%BF%20%CE%B2%CE%AF%CE%BD%CF%84%CE%B5%CE%BF,%20%CE%B7%20Google%20%CE%B8%CE%B1%20%CE%B3%CE%BD%CF%89%CF%81%CE%AF%CE%B6%CE%B5%CE%B9%20%CF%84%CE%B7%20%CE%B4%CF%81%CE%B1%CF%83%CF%84%CE%B7%CF%81%CE%B9%CF%8C%CF%84%CE%B7%CF%84%CE%AC%20%CF%83%CE%B1%CF%82.%22,%22infoPreviewToggleText%22:%22%CE%9F%CE%B9%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CE%B9%CF%82%20%CE%B1%CF%80%CE%B5%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%B9%CE%AE%CE%B8%CE%B7%CE%BA%CE%B1%CE%BD%20%CE%B3%CE%B9%CE%B1%20%CF%80%CF%81%CF%8C%CF%83%CE%B8%CE%B5%CF%84%CE%B7%20%CF%80%CF%81%CE%BF%CF%83%CF%84%CE%B1%CF%83%CE%AF%CE%B1%20%CF%84%CF%89%CE%BD%20%CF%80%CF%81%CE%BF%CF%83%CF%89%CF%80%CE%B9%CE%BA%CF%8E%CE%BD%20%CE%B4%CE%B5%CE%B4%CE%BF%CE%BC%CE%AD%CE%BD%CF%89%CE%BD%22,%22infoPreviewToggleEnabledText%22:%22%CE%9F%CE%B9%20%CF%80%CF%81%CE%BF%CE%B5%CF%80%CE%B9%CF%83%CE%BA%CE%BF%CF%80%CE%AE%CF%83%CE%B5%CE%B9%CF%82%20%CE%B5%CE%BD%CE%B5%CF%81%CE%B3%CE%BF%CF%80%CE%BF%CE%B9%CE%AE%CE%B8%CE%B7%CE%BA%CE%B1%CE%BD%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3E%CE%9C%CE%AC%CE%B8%CE%B5%CF%84%CE%B5%20%CF%80%CE%B5%CF%81%CE%B9%CF%83%CF%83%CF%8C%CF%84%CE%B5%CF%81%CE%B1%3C/a%3E%20%CE%B3%CE%B9%CE%B1%20%CF%84%CE%B7%CE%BD%20%CE%B5%CE%BD%CF%83%CF%89%CE%BC%CE%B1%CF%84%CF%89%CE%BC%CE%AD%CE%BD%CE%B7%20%CF%80%CF%81%CE%BF%CF%83%CF%84%CE%B1%CF%83%CE%AF%CE%B1%20%CE%BA%CE%BF%CE%B9%CE%BD%CF%89%CE%BD%CE%B9%CE%BA%CF%8E%CE%BD%20%CE%BC%CE%AD%CF%83%CF%89%CE%BD%20DuckDuckGo%22%7D%7D,%22en%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Logging%20in%20with%20Facebook%20lets%20them%20track%20you%22,%22informationalModalMessageBody%22:%22Once%20you're%20logged%20in,%20DuckDuckGo%20can't%20block%20Facebook%20content%20from%20tracking%20you%20on%20this%20site.%22,%22informationalModalConfirmButtonText%22:%22Log%20In%22,%22informationalModalRejectButtonText%22:%22Go%20back%22,%22loginButtonText%22:%22Log%20in%20with%20Facebook%22,%22loginBodyText%22:%22Facebook%20tracks%20your%20activity%20on%20a%20site%20when%20you%20use%20them%20to%20login.%22,%22buttonTextUnblockContent%22:%22Unblock%20Content%22,%22buttonTextUnblockComment%22:%22Unblock%20Comment%22,%22buttonTextUnblockComments%22:%22Unblock%20Comments%22,%22buttonTextUnblockPost%22:%22Unblock%20Post%22,%22buttonTextUnblockVideo%22:%22Unblock%20Video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blocked%20this%20content%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blocked%20this%20comment%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blocked%20these%20comments%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blocked%20this%20post%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blocked%20this%20video%20to%20prevent%20Facebook%20from%20tracking%20you%22,%22infoTextUnblockContent%22:%22We%20blocked%20Facebook%20from%20tracking%20you%20when%20the%20page%20loaded.%20If%20you%20unblock%20this%20content,%20Facebook%20will%20know%20your%20activity.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Learn%20More%22,%22readAbout%22:%22Read%20about%20this%20privacy%20protection%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Enable%20all%20YouTube%20previews?%22,%22informationalModalMessageBody%22:%22Showing%20previews%20will%20allow%20Google%20(which%20owns%20YouTube)%20to%20see%20some%20of%20your%20device%E2%80%99s%20information,%20but%20is%20still%20more%20private%20than%20playing%20the%20video.%22,%22informationalModalConfirmButtonText%22:%22Enable%20All%20Previews%22,%22informationalModalRejectButtonText%22:%22No%20Thanks%22,%22buttonTextUnblockVideo%22:%22Unblock%20Video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blocked%20this%20YouTube%20video%20to%20prevent%20Google%20from%20tracking%20you%22,%22infoTextUnblockVideo%22:%22We%20blocked%20Google%20(which%20owns%20YouTube)%20from%20tracking%20you%20when%20the%20page%20loaded.%20If%20you%20unblock%20this%20video,%20Google%20will%20know%20your%20activity.%22,%22infoPreviewToggleText%22:%22Previews%20disabled%20for%20additional%20privacy%22,%22infoPreviewToggleEnabledText%22:%22Previews%20enabled%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ELearn%20more%3C/a%3E%20about%20DuckDuckGo%20Embedded%20Social%20Media%20Protection%22%7D%7D,%22es%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Al%20iniciar%20sesi%C3%B3n%20en%20Facebook,%20les%20permites%20que%20te%20rastreen%22,%22informationalModalMessageBody%22:%22Una%20vez%20que%20hayas%20iniciado%20sesi%C3%B3n,%20DuckDuckGo%20no%20puede%20bloquear%20el%20contenido%20de%20Facebook%20para%20que%20no%20te%20rastree%20en%20este%20sitio.%22,%22informationalModalConfirmButtonText%22:%22Iniciar%20sesi%C3%B3n%22,%22informationalModalRejectButtonText%22:%22Volver%20atr%C3%A1s%22,%22loginButtonText%22:%22Iniciar%20sesi%C3%B3n%20con%20Facebook%22,%22loginBodyText%22:%22Facebook%20rastrea%20tu%20actividad%20en%20un%20sitio%20web%20cuando%20lo%20usas%20para%20iniciar%20sesi%C3%B3n.%22,%22buttonTextUnblockContent%22:%22Desbloquear%20contenido%22,%22buttonTextUnblockComment%22:%22Desbloquear%20comentario%22,%22buttonTextUnblockComments%22:%22Desbloquear%20comentarios%22,%22buttonTextUnblockPost%22:%22Desbloquear%20publicaci%C3%B3n%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20v%C3%ADdeo%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20ha%20bloqueado%20este%20contenido%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20ha%20bloqueado%20este%20comentario%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20ha%20bloqueado%20estos%20comentarios%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20ha%20bloqueado%20esta%20publicaci%C3%B3n%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloqueado%20este%20v%C3%ADdeo%20para%20evitar%20que%20Facebook%20te%20rastree%22,%22infoTextUnblockContent%22:%22Hemos%20bloqueado%20el%20rastreo%20de%20Facebook%20cuando%20se%20ha%20cargado%20la%20p%C3%A1gina.%20Si%20desbloqueas%20este%20contenido,%20Facebook%20tendr%C3%A1%20conocimiento%20de%20tu%20actividad.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22M%C3%A1s%20informaci%C3%B3n%22,%22readAbout%22:%22Lee%20acerca%20de%20esta%20protecci%C3%B3n%20de%20privacidad%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%C2%BFHabilitar%20todas%20las%20vistas%20previas%20de%20YouTube?%22,%22informationalModalMessageBody%22:%22Mostrar%20vistas%20previas%20permitir%C3%A1%20a%20Google%20(que%20es%20el%20propietario%20de%20YouTube)%20ver%20parte%20de%20la%20informaci%C3%B3n%20de%20tu%20dispositivo,%20pero%20sigue%20siendo%20m%C3%A1s%20privado%20que%20reproducir%20el%20v%C3%ADdeo.%22,%22informationalModalConfirmButtonText%22:%22Habilitar%20todas%20las%20vistas%20previas%22,%22informationalModalRejectButtonText%22:%22No,%20gracias%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20v%C3%ADdeo%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloqueado%20este%20v%C3%ADdeo%20de%20YouTube%20para%20evitar%20que%20Google%20te%20rastree%22,%22infoTextUnblockVideo%22:%22Hemos%20bloqueado%20el%20rastreo%20de%20Google%20(que%20es%20el%20propietario%20de%20YouTube)%20al%20cargarse%20la%20p%C3%A1gina.%20Si%20desbloqueas%20este%20v%C3%ADdeo,%20Goggle%20tendr%C3%A1%20conocimiento%20de%20tu%20actividad.%22,%22infoPreviewToggleText%22:%22Vistas%20previas%20desactivadas%20para%20mayor%20privacidad%22,%22infoPreviewToggleEnabledText%22:%22Vistas%20previas%20activadas%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EM%C3%A1s%20informaci%C3%B3n%3C/a%3E%20sobre%20la%20protecci%C3%B3n%20integrada%20de%20redes%20sociales%20DuckDuckGo%22%7D%7D,%22et%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Kui%20logid%20Facebookiga%20sisse,%20saab%20Facebook%20sind%20j%C3%A4lgida%22,%22informationalModalMessageBody%22:%22Kui%20oled%20sisse%20logitud,%20ei%20saa%20DuckDuckGo%20blokeerida%20Facebooki%20sisu%20sind%20j%C3%A4lgimast.%22,%22informationalModalConfirmButtonText%22:%22Logi%20sisse%22,%22informationalModalRejectButtonText%22:%22Mine%20tagasi%22,%22loginButtonText%22:%22Logi%20sisse%20Facebookiga%22,%22loginBodyText%22:%22Kui%20logid%20sisse%20Facebookiga,%20saab%20Facebook%20sinu%20tegevust%20saidil%20j%C3%A4lgida.%22,%22buttonTextUnblockContent%22:%22Deblokeeri%20sisu%22,%22buttonTextUnblockComment%22:%22Deblokeeri%20kommentaar%22,%22buttonTextUnblockComments%22:%22Deblokeeri%20kommentaarid%22,%22buttonTextUnblockPost%22:%22Deblokeeri%20postitus%22,%22buttonTextUnblockVideo%22:%22Deblokeeri%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blokeeris%20selle%20sisu,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blokeeris%20selle%20kommentaari,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blokeeris%20need%20kommentaarid,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blokeeris%20selle%20postituse,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokeeris%20selle%20video,%20et%20Facebook%20ei%20saaks%20sind%20j%C3%A4lgida%22,%22infoTextUnblockContent%22:%22Blokeerisime%20lehe%20laadimise%20ajal%20Facebooki%20jaoks%20sinu%20j%C3%A4lgimise.%20Kui%20sa%20selle%20sisu%20deblokeerid,%20saab%20Facebook%20sinu%20tegevust%20j%C3%A4lgida.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Loe%20edasi%22,%22readAbout%22:%22Loe%20selle%20privaatsuskaitse%20kohta%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Kas%20lubada%20k%C3%B5ik%20YouTube%E2%80%99i%20eelvaated?%22,%22informationalModalMessageBody%22:%22Eelvaate%20n%C3%A4itamine%20v%C3%B5imaldab%20Google%E2%80%99il%20(kellele%20YouTube%20kuulub)%20n%C3%A4ha%20osa%20sinu%20seadme%20teabest,%20kuid%20see%20on%20siiski%20privaatsem%20kui%20video%20esitamine.%22,%22informationalModalConfirmButtonText%22:%22Luba%20k%C3%B5ik%20eelvaated%22,%22informationalModalRejectButtonText%22:%22Ei%20ait%C3%A4h%22,%22buttonTextUnblockVideo%22:%22Deblokeeri%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokeeris%20selle%20YouTube%E2%80%99i%20video,%20et%20takistada%20Google%E2%80%99it%20sind%20j%C3%A4lgimast%22,%22infoTextUnblockVideo%22:%22Me%20blokeerisime%20lehe%20laadimise%20ajal%20Google%E2%80%99i%20(kellele%20YouTube%20kuulub)%20j%C3%A4lgimise.%20Kui%20sa%20selle%20video%20deblokeerid,%20saab%20Google%20sinu%20tegevusest%20teada.%22,%22infoPreviewToggleText%22:%22Eelvaated%20on%20t%C3%A4iendava%20privaatsuse%20tagamiseks%20keelatud%22,%22infoPreviewToggleEnabledText%22:%22Eelvaated%20on%20lubatud%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ELisateave%3C/a%3E%20DuckDuckGo%20sisseehitatud%20sotsiaalmeediakaitse%20kohta%22%7D%7D,%22fi%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Kun%20kirjaudut%20sis%C3%A4%C3%A4n%20Facebook-tunnuksilla,%20Facebook%20voi%20seurata%20sinua%22,%22informationalModalMessageBody%22:%22Kun%20olet%20kirjautunut%20sis%C3%A4%C3%A4n,%20DuckDuckGo%20ei%20voi%20est%C3%A4%C3%A4%20Facebook-sis%C3%A4lt%C3%B6%C3%A4%20seuraamasta%20sinua%20t%C3%A4ll%C3%A4%20sivustolla.%22,%22informationalModalConfirmButtonText%22:%22Kirjaudu%20sis%C3%A4%C3%A4n%22,%22informationalModalRejectButtonText%22:%22Edellinen%22,%22loginButtonText%22:%22Kirjaudu%20sis%C3%A4%C3%A4n%20Facebook-tunnuksilla%22,%22loginBodyText%22:%22Facebook%20seuraa%20toimintaasi%20sivustolla,%20kun%20kirjaudut%20sis%C3%A4%C3%A4n%20sen%20kautta.%22,%22buttonTextUnblockContent%22:%22Poista%20sis%C3%A4ll%C3%B6n%20esto%22,%22buttonTextUnblockComment%22:%22Poista%20kommentin%20esto%22,%22buttonTextUnblockComments%22:%22Poista%20kommenttien%20esto%22,%22buttonTextUnblockPost%22:%22Poista%20julkaisun%20esto%22,%22buttonTextUnblockVideo%22:%22Poista%20videon%20esto%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20sis%C3%A4ll%C3%B6n%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20kommentin%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20esti%20n%C3%A4m%C3%A4%20kommentit%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20julkaisun%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20videon%20est%C3%A4%C3%A4kseen%20Facebookia%20seuraamasta%20sinua%22,%22infoTextUnblockContent%22:%22Estimme%20Facebookia%20seuraamasta%20sinua,%20kun%20sivua%20ladattiin.%20Jos%20poistat%20t%C3%A4m%C3%A4n%20sis%C3%A4ll%C3%B6n%20eston,%20Facebook%20saa%20tiet%C3%A4%C3%A4%20toimintasi.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Lue%20lis%C3%A4%C3%A4%22,%22readAbout%22:%22Lue%20t%C3%A4st%C3%A4%20yksityisyydensuojasta%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Otetaanko%20k%C3%A4ytt%C3%B6%C3%B6n%20kaikki%20YouTube-esikatselut?%22,%22informationalModalMessageBody%22:%22Kun%20sallit%20esikatselun,%20Google%20(joka%20omistaa%20YouTuben)%20voi%20n%C3%A4hd%C3%A4%20joitakin%20laitteesi%20tietoja,%20mutta%20se%20on%20silti%20yksityisemp%C3%A4%C3%A4%20kuin%20videon%20toistaminen.%22,%22informationalModalConfirmButtonText%22:%22Ota%20k%C3%A4ytt%C3%B6%C3%B6n%20kaikki%20esikatselut%22,%22informationalModalRejectButtonText%22:%22Ei%20kiitos%22,%22buttonTextUnblockVideo%22:%22Poista%20videon%20esto%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20esti%20t%C3%A4m%C3%A4n%20YouTube-videon,%20jotta%20Google%20ei%20voi%20seurata%20sinua%22,%22infoTextUnblockVideo%22:%22Estimme%20Googlea%20(joka%20omistaa%20YouTuben)%20seuraamasta%20sinua,%20kun%20sivua%20ladattiin.%20Jos%20poistat%20t%C3%A4m%C3%A4n%20videon%20eston,%20Google%20tiet%C3%A4%C3%A4%20toimintasi.%22,%22infoPreviewToggleText%22:%22Esikatselut%20on%20poistettu%20k%C3%A4yt%C3%B6st%C3%A4%20yksityisyyden%20lis%C3%A4%C3%A4miseksi%22,%22infoPreviewToggleEnabledText%22:%22Esikatselut%20k%C3%A4yt%C3%B6ss%C3%A4%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ELue%20lis%C3%A4%C3%A4%3C/a%3E%20DuckDuckGon%20upotetusta%20sosiaalisen%20median%20suojauksesta%22%7D%7D,%22fr%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22L'identification%20via%20Facebook%20leur%20permet%20de%20vous%20pister%22,%22informationalModalMessageBody%22:%22Une%20fois%20que%20vous%20%C3%AAtes%20connect%C3%A9(e),%20DuckDuckGo%20ne%20peut%20pas%20emp%C3%AAcher%20le%20contenu%20Facebook%20de%20vous%20pister%20sur%20ce%20site.%22,%22informationalModalConfirmButtonText%22:%22Connexion%22,%22informationalModalRejectButtonText%22:%22Revenir%20en%20arri%C3%A8re%22,%22loginButtonText%22:%22S'identifier%20avec%20Facebook%22,%22loginBodyText%22:%22Facebook%20piste%20votre%20activit%C3%A9%20sur%20un%20site%20lorsque%20vous%20l'utilisez%20pour%20vous%20identifier.%22,%22buttonTextUnblockContent%22:%22D%C3%A9bloquer%20le%20contenu%22,%22buttonTextUnblockComment%22:%22D%C3%A9bloquer%20le%20commentaire%22,%22buttonTextUnblockComments%22:%22D%C3%A9bloquer%20les%20commentaires%22,%22buttonTextUnblockPost%22:%22D%C3%A9bloquer%20la%20publication%22,%22buttonTextUnblockVideo%22:%22D%C3%A9bloquer%20la%20vid%C3%A9o%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20ce%20contenu%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20suivre%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20ce%20commentaire%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20suivre%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20ces%20commentaires%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20suivre%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20cette%20publication%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20pister%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20cette%20vid%C3%A9o%20pour%20emp%C3%AAcher%20Facebook%20de%20vous%20pister%22,%22infoTextUnblockContent%22:%22Nous%20avons%20emp%C3%AAch%C3%A9%20Facebook%20de%20vous%20pister%20lors%20du%20chargement%20de%20la%20page.%20Si%20vous%20d%C3%A9bloquez%20ce%20contenu,%20Facebook%20conna%C3%AEtra%20votre%20activit%C3%A9.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22En%20savoir%20plus%22,%22readAbout%22:%22En%20savoir%20plus%20sur%20cette%20protection%20de%20la%20confidentialit%C3%A9%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Activer%20tous%20les%20aper%C3%A7us%20YouTube%C2%A0?%22,%22informationalModalMessageBody%22:%22L'affichage%20des%20aper%C3%A7us%20permettra%20%C3%A0%20Google%20(propri%C3%A9taire%20de%20YouTube)%20de%20voir%20certaines%20informations%20de%20votre%20appareil,%20mais%20cela%20reste%20davantage%20confidentiel%20qu'en%20lisant%20la%20vid%C3%A9o.%22,%22informationalModalConfirmButtonText%22:%22Activer%20tous%20les%20aper%C3%A7us%22,%22informationalModalRejectButtonText%22:%22Non%20merci%22,%22buttonTextUnblockVideo%22:%22D%C3%A9bloquer%20la%20vid%C3%A9o%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20bloqu%C3%A9%20cette%20vid%C3%A9o%20YouTube%20pour%20emp%C3%AAcher%20Google%20de%20vous%20pister%22,%22infoTextUnblockVideo%22:%22Nous%20avons%20emp%C3%AAch%C3%A9%20Google%20(propri%C3%A9taire%20de%20YouTube)%20de%20vous%20pister%20lors%20du%20chargement%20de%20la%20page.%20Si%20vous%20d%C3%A9bloquez%20cette%20vid%C3%A9o,%20Google%20conna%C3%AEtra%20votre%20activit%C3%A9.%22,%22infoPreviewToggleText%22:%22Aper%C3%A7us%20d%C3%A9sactiv%C3%A9s%20pour%20plus%20de%20confidentialit%C3%A9%22,%22infoPreviewToggleEnabledText%22:%22Aper%C3%A7us%20activ%C3%A9s%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EEn%20savoir%20plus%3C/a%3E%20sur%20la%20protection%20int%C3%A9gr%C3%A9e%20DuckDuckGo%20des%20r%C3%A9seaux%20sociaux%22%7D%7D,%22hr%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Prijava%20putem%20Facebooka%20omogu%C4%87uje%20im%20da%20te%20prate%22,%22informationalModalMessageBody%22:%22Nakon%20%C5%A1to%20se%20prijavi%C5%A1,%20DuckDuckGo%20ne%20mo%C5%BEe%20blokirati%20Facebookov%20sadr%C5%BEaj%20da%20te%20prati%20na%20Facebooku.%22,%22informationalModalConfirmButtonText%22:%22Prijavljivanje%22,%22informationalModalRejectButtonText%22:%22Vrati%20se%22,%22loginButtonText%22:%22Prijavi%20se%20putem%20Facebooka%22,%22loginBodyText%22:%22Facebook%20prati%20tvoju%20aktivnost%20na%20toj%20web%20lokaciji%20kad%20je%20koristi%C5%A1%20za%20prijavu.%22,%22buttonTextUnblockContent%22:%22Deblokiranje%20sadr%C5%BEaja%22,%22buttonTextUnblockComment%22:%22Deblokiranje%20komentara%22,%22buttonTextUnblockComments%22:%22Deblokiranje%20komentara%22,%22buttonTextUnblockPost%22:%22Deblokiranje%20objave%22,%22buttonTextUnblockVideo%22:%22Deblokiranje%20videozapisa%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20sadr%C5%BEaj%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20komentar%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20je%20blokirao%20ove%20komentare%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20je%20blokirao%20ovu%20objavu%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20video%20kako%20bi%20sprije%C4%8Dio%20Facebook%20da%20te%20prati%22,%22infoTextUnblockContent%22:%22Blokirali%20smo%20Facebook%20da%20te%20prati%20kad%20se%20stranica%20u%C4%8Dita.%20Ako%20deblokira%C5%A1%20ovaj%20sadr%C5%BEaj,%20Facebook%20%C4%87e%20znati%20tvoju%20aktivnost.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Saznajte%20vi%C5%A1e%22,%22readAbout%22:%22Pro%C4%8Ditaj%20vi%C5%A1e%20o%20ovoj%20za%C5%A1titi%20privatnosti%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Omogu%C4%87iti%20sve%20YouTube%20pretpreglede?%22,%22informationalModalMessageBody%22:%22Prikazivanje%20pretpregleda%20omogu%C4%87it%20%C4%87e%20Googleu%20(u%20%C4%8Dijem%20je%20vlasni%C5%A1tvu%20YouTube)%20da%20vidi%20neke%20podatke%20o%20tvom%20ure%C4%91aju,%20ali%20je%20i%20dalje%20privatnija%20opcija%20od%20reprodukcije%20videozapisa.%22,%22informationalModalConfirmButtonText%22:%22Omogu%C4%87i%20sve%20pretpreglede%22,%22informationalModalRejectButtonText%22:%22Ne,%20hvala%22,%22buttonTextUnblockVideo%22:%22Deblokiranje%20videozapisa%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokirao%20ovaj%20YouTube%20videozapis%20kako%20bi%20sprije%C4%8Dio%20Google%20da%20te%20prati%22,%22infoTextUnblockVideo%22:%22Blokirali%20smo%20Google%20(u%20%C4%8Dijem%20je%20vlasni%C5%A1tvu%20YouTube)%20da%20te%20prati%20kad%20se%20stranica%20u%C4%8Dita.%20Ako%20deblokira%C5%A1%20ovaj%20videozapis,%20Google%20%C4%87e%20znati%20tvoju%20aktivnost.%22,%22infoPreviewToggleText%22:%22Pretpregledi%20su%20onemogu%C4%87eni%20radi%20dodatne%20privatnosti%22,%22infoPreviewToggleEnabledText%22:%22Pretpregledi%20su%20omogu%C4%87eni%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ESaznaj%20vi%C5%A1e%3C/a%3E%20o%20uklju%C4%8Denoj%20DuckDuckGo%20za%C5%A1titi%20od%20dru%C5%A1tvenih%20medija%22%7D%7D,%22hu%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22A%20Facebookkal%20val%C3%B3%20bejelentkez%C3%A9skor%20a%20Facebook%20nyomon%20k%C3%B6vethet%22,%22informationalModalMessageBody%22:%22Miut%C3%A1n%20bejelentkezel,%20a%20DuckDuckGo%20nem%20fogja%20tudni%20blokkolni%20a%20Facebook-tartalmat,%20amely%20nyomon%20k%C3%B6vet%20ezen%20az%20oldalon.%22,%22informationalModalConfirmButtonText%22:%22Bejelentkez%C3%A9s%22,%22informationalModalRejectButtonText%22:%22Visszal%C3%A9p%C3%A9s%22,%22loginButtonText%22:%22Bejelentkez%C3%A9s%20Facebookkal%22,%22loginBodyText%22:%22Ha%20a%20Facebookkal%20jelentkezel%20be,%20nyomon%20k%C3%B6vetik%20a%20webhelyen%20v%C3%A9gzett%20tev%C3%A9kenys%C3%A9gedet.%22,%22buttonTextUnblockContent%22:%22Tartalom%20felold%C3%A1sa%22,%22buttonTextUnblockComment%22:%22Hozz%C3%A1sz%C3%B3l%C3%A1s%20felold%C3%A1sa%22,%22buttonTextUnblockComments%22:%22Hozz%C3%A1sz%C3%B3l%C3%A1sok%20felold%C3%A1sa%22,%22buttonTextUnblockPost%22:%22Bejegyz%C3%A9s%20felold%C3%A1sa%22,%22buttonTextUnblockVideo%22:%22Vide%C3%B3%20felold%C3%A1sa%22,%22infoTitleUnblockContent%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20tartalmat,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockComment%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20hozz%C3%A1sz%C3%B3l%C3%A1st,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockComments%22:%22A%20DuckDuckGo%20blokkolta%20ezeket%20a%20hozz%C3%A1sz%C3%B3l%C3%A1sokat,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockPost%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20bejegyz%C3%A9st,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTitleUnblockVideo%22:%22A%20DuckDuckGo%20blokkolta%20ezt%20a%20vide%C3%B3t,%20hogy%20megakad%C3%A1lyozza%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben%22,%22infoTextUnblockContent%22:%22Az%20oldal%20bet%C3%B6lt%C3%A9sekor%20blokkoltuk%20a%20Facebookot%20a%20nyomon%20k%C3%B6vet%C3%A9sedben.%20Ha%20feloldod%20ezt%20a%20tartalmat,%20a%20Facebook%20tudni%20fogja,%20hogy%20milyen%20tev%C3%A9kenys%C3%A9get%20v%C3%A9gzel.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Tov%C3%A1bbi%20r%C3%A9szletek%22,%22readAbout%22:%22Tudj%20meg%20t%C3%B6bbet%20err%C5%91l%20az%20adatv%C3%A9delemr%C5%91l%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Enged%C3%A9lyezed%20minden%20YouTube-vide%C3%B3%20el%C5%91n%C3%A9zet%C3%A9t?%22,%22informationalModalMessageBody%22:%22Az%20el%C5%91n%C3%A9zetek%20megjelen%C3%ADt%C3%A9s%C3%A9vel%20a%20Google%20(a%20YouTube%20tulajdonosa)%20l%C3%A1thatja%20a%20k%C3%A9sz%C3%BCl%C3%A9k%20n%C3%A9h%C3%A1ny%20adat%C3%A1t,%20de%20ez%20adatv%C3%A9delmi%20szempontb%C3%B3l%20m%C3%A9g%20mindig%20el%C5%91ny%C3%B6sebb,%20mint%20a%20vide%C3%B3%20lej%C3%A1tsz%C3%A1sa.%22,%22informationalModalConfirmButtonText%22:%22Minden%20el%C5%91n%C3%A9zet%20enged%C3%A9lyez%C3%A9se%22,%22informationalModalRejectButtonText%22:%22Nem,%20k%C3%B6sz%C3%B6n%C3%B6m%22,%22buttonTextUnblockVideo%22:%22Vide%C3%B3%20felold%C3%A1sa%22,%22infoTitleUnblockVideo%22:%22A%20DuckDuckGo%20blokkolta%20a%20YouTube-vide%C3%B3t,%20hogy%20a%20Google%20ne%20k%C3%B6vethessen%20nyomon%22,%22infoTextUnblockVideo%22:%22Blokkoltuk,%20hogy%20a%20Google%20(a%20YouTube%20tulajdonosa)%20nyomon%20k%C3%B6vethessen%20az%20oldal%20bet%C3%B6lt%C3%A9sekor.%20Ha%20feloldod%20a%20vide%C3%B3%20blokkol%C3%A1s%C3%A1t,%20a%20Google%20tudni%20fogja,%20hogy%20milyen%20tev%C3%A9kenys%C3%A9get%20v%C3%A9gzel.%22,%22infoPreviewToggleText%22:%22Az%20el%C5%91n%C3%A9zetek%20a%20fokozott%20adatv%C3%A9delem%20%C3%A9rdek%C3%A9ben%20letiltva%22,%22infoPreviewToggleEnabledText%22:%22Az%20el%C5%91n%C3%A9zetek%20enged%C3%A9lyezve%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ETov%C3%A1bbi%20tudnival%C3%B3k%3C/a%3E%20a%20DuckDuckGo%20be%C3%A1gyazott%20k%C3%B6z%C3%B6ss%C3%A9gi%20m%C3%A9dia%20elleni%20v%C3%A9delm%C3%A9r%C5%91l%22%7D%7D,%22it%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22L'accesso%20con%20Facebook%20consente%20di%20tracciarti%22,%22informationalModalMessageBody%22:%22Dopo%20aver%20effettuato%20l'accesso,%20DuckDuckGo%20non%20pu%C3%B2%20bloccare%20il%20tracciamento%20dei%20contenuti%20di%20Facebook%20su%20questo%20sito.%22,%22informationalModalConfirmButtonText%22:%22Accedi%22,%22informationalModalRejectButtonText%22:%22Torna%20indietro%22,%22loginButtonText%22:%22Accedi%20con%20Facebook%22,%22loginBodyText%22:%22Facebook%20tiene%20traccia%20della%20tua%20attivit%C3%A0%20su%20un%20sito%20quando%20lo%20usi%20per%20accedere.%22,%22buttonTextUnblockContent%22:%22Sblocca%20contenuti%22,%22buttonTextUnblockComment%22:%22Sblocca%20commento%22,%22buttonTextUnblockComments%22:%22Sblocca%20commenti%22,%22buttonTextUnblockPost%22:%22Sblocca%20post%22,%22buttonTextUnblockVideo%22:%22Sblocca%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20ha%20bloccato%20questo%20contenuto%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20ha%20bloccato%20questo%20commento%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20ha%20bloccato%20questi%20commenti%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20ha%20bloccato%20questo%20post%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloccato%20questo%20video%20per%20impedire%20a%20Facebook%20di%20tracciarti%22,%22infoTextUnblockContent%22:%22Abbiamo%20impedito%20a%20Facebook%20di%20tracciarti%20al%20caricamento%20della%20pagina.%20Se%20sblocchi%20questo%20contenuto,%20Facebook%20conoscer%C3%A0%20la%20tua%20attivit%C3%A0.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Ulteriori%20informazioni%22,%22readAbout%22:%22Leggi%20di%20pi%C3%B9%20su%20questa%20protezione%20della%20privacy%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Abilitare%20tutte%20le%20anteprime%20di%20YouTube?%22,%22informationalModalMessageBody%22:%22La%20visualizzazione%20delle%20anteprime%20consentir%C3%A0%20a%20Google%20(che%20possiede%20YouTube)%20di%20vedere%20alcune%20delle%20informazioni%20del%20tuo%20dispositivo,%20ma%20%C3%A8%20comunque%20pi%C3%B9%20privato%20rispetto%20alla%20riproduzione%20del%20video.%22,%22informationalModalConfirmButtonText%22:%22Abilita%20tutte%20le%20anteprime%22,%22informationalModalRejectButtonText%22:%22No,%20grazie%22,%22buttonTextUnblockVideo%22:%22Sblocca%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20ha%20bloccato%20questo%20video%20di%20YouTube%20per%20impedire%20a%20Google%20di%20tracciarti%22,%22infoTextUnblockVideo%22:%22Abbiamo%20impedito%20a%20Google%20(che%20possiede%20YouTube)%20di%20tracciarti%20quando%20la%20pagina%20%C3%A8%20stata%20caricata.%20Se%20sblocchi%20questo%20video,%20Google%20conoscer%C3%A0%20la%20tua%20attivit%C3%A0.%22,%22infoPreviewToggleText%22:%22Anteprime%20disabilitate%20per%20una%20maggiore%20privacy%22,%22infoPreviewToggleEnabledText%22:%22Anteprime%20abilitate%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EScopri%20di%20pi%C3%B9%3C/a%3E%20sulla%20protezione%20dai%20social%20media%20integrata%20di%20DuckDuckGo%22%7D%7D,%22lt%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Prisijung%C4%99%20prie%20%E2%80%9EFacebook%E2%80%9C%20galite%20b%C5%ABti%20sekami%22,%22informationalModalMessageBody%22:%22Kai%20esate%20prisijung%C4%99,%20%E2%80%9EDuckDuckGo%E2%80%9C%20negali%20u%C5%BEblokuoti%20%E2%80%9EFacebook%E2%80%9C%20turinio,%20tod%C4%97l%20esate%20sekami%20%C5%A1ioje%20svetain%C4%97je.%22,%22informationalModalConfirmButtonText%22:%22Prisijungti%22,%22informationalModalRejectButtonText%22:%22Gr%C4%AF%C5%BEti%20atgal%22,%22loginButtonText%22:%22Prisijunkite%20su%20%E2%80%9EFacebook%E2%80%9C%22,%22loginBodyText%22:%22%E2%80%9EFacebook%E2%80%9C%20seka%20j%C5%ABs%C5%B3%20veikl%C4%85%20svetain%C4%97je,%20kai%20prisijungiate%20su%20%C5%A1ia%20svetaine.%22,%22buttonTextUnblockContent%22:%22Atblokuoti%20turin%C4%AF%22,%22buttonTextUnblockComment%22:%22Atblokuoti%20komentar%C4%85%22,%22buttonTextUnblockComments%22:%22Atblokuoti%20komentarus%22,%22buttonTextUnblockPost%22:%22Atblokuoti%20%C4%AFra%C5%A1%C4%85%22,%22buttonTextUnblockVideo%22:%22Atblokuoti%20vaizdo%20%C4%AFra%C5%A1%C4%85%22,%22infoTitleUnblockContent%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20turin%C4%AF,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockComment%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20komentar%C4%85,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockComments%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1iuos%20komentarus,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockPost%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20%C4%AFra%C5%A1%C4%85,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTitleUnblockVideo%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20vaizdo%20%C4%AFra%C5%A1%C4%85,%20kad%20%E2%80%9EFacebook%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTextUnblockContent%22:%22U%C5%BEblokavome%20%E2%80%9EFacebook%E2%80%9C,%20kad%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti,%20kai%20puslapis%20buvo%20%C4%AFkeltas.%20Jei%20atblokuosite%20%C5%A1%C4%AF%20turin%C4%AF,%20%E2%80%9EFacebook%E2%80%9C%20%C5%BEinos%20apie%20j%C5%ABs%C5%B3%20veikl%C4%85.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Su%C5%BEinoti%20daugiau%22,%22readAbout%22:%22Skaitykite%20apie%20%C5%A1i%C4%85%20privatumo%20apsaug%C4%85%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%C4%AEjungti%20visas%20%E2%80%9EYouTube%E2%80%9C%20per%C5%BEi%C5%ABras?%22,%22informationalModalMessageBody%22:%22Per%C5%BEi%C5%ABr%C5%B3%20rodymas%20leis%20%E2%80%9EGoogle%E2%80%9C%20(kuriai%20priklauso%20%E2%80%9EYouTube%E2%80%9C)%20matyti%20tam%20tikr%C4%85%20j%C5%ABs%C5%B3%20%C4%AFrenginio%20informacij%C4%85,%20ta%C4%8Diau%20ji%20vis%20tiek%20bus%20privatesn%C4%97%20nei%20leid%C5%BEiant%20vaizdo%20%C4%AFra%C5%A1%C4%85.%22,%22informationalModalConfirmButtonText%22:%22%C4%AEjungti%20visas%20per%C5%BEi%C5%ABras%22,%22informationalModalRejectButtonText%22:%22Ne,%20d%C4%97koju%22,%22buttonTextUnblockVideo%22:%22Atblokuoti%20vaizdo%20%C4%AFra%C5%A1%C4%85%22,%22infoTitleUnblockVideo%22:%22%E2%80%9EDuckDuckGo%E2%80%9C%20u%C5%BEblokavo%20%C5%A1%C4%AF%20%E2%80%9EYouTube%E2%80%9C%20vaizdo%20%C4%AFra%C5%A1%C4%85,%20kad%20%E2%80%9EGoogle%E2%80%9C%20negal%C4%97t%C5%B3%20j%C5%ABs%C5%B3%20sekti%22,%22infoTextUnblockVideo%22:%22U%C5%BEblokavome%20%E2%80%9EGoogle%E2%80%9C%20(kuriai%20priklauso%20%E2%80%9EYouTube%E2%80%9C)%20galimyb%C4%99%20sekti%20jus,%20kai%20puslapis%20buvo%20%C4%AFkeltas.%20Jei%20atblokuosite%20%C5%A1%C4%AF%20vaizdo%20%C4%AFra%C5%A1%C4%85,%20%E2%80%9EGoogle%E2%80%9C%20su%C5%BEinos%20apie%20j%C5%ABs%C5%B3%20veikl%C4%85.%22,%22infoPreviewToggleText%22:%22Per%C5%BEi%C5%ABros%20i%C5%A1jungtos%20d%C4%97l%20papildomo%20privatumo%22,%22infoPreviewToggleEnabledText%22:%22Per%C5%BEi%C5%ABros%20%C4%AFjungtos%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ESu%C5%BEinokite%20daugiau%3C/a%3E%20apie%20%E2%80%9EDuckDuckGo%E2%80%9C%20%C4%AFd%C4%97t%C4%85j%C4%85%20socialin%C4%97s%20%C5%BEiniasklaidos%20apsaug%C4%85%22%7D%7D,%22lv%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Ja%20pieteiksies%20ar%20Facebook,%20vi%C5%86i%20var%C4%93s%20tevi%20izsekot%22,%22informationalModalMessageBody%22:%22Kad%20tu%20piesakies,%20DuckDuckGo%20nevar%20nov%C4%93rst,%20ka%20Facebook%20saturs%20tevi%20izseko%20%C5%A1aj%C4%81%20vietn%C4%93.%22,%22informationalModalConfirmButtonText%22:%22Pieteikties%22,%22informationalModalRejectButtonText%22:%22Atgriezties%22,%22loginButtonText%22:%22Pieteikties%20ar%20Facebook%22,%22loginBodyText%22:%22Facebook%20izseko%20tavas%20aktivit%C4%81tes%20vietn%C4%93,%20kad%20esi%20pieteicies%20ar%20Facebook.%22,%22buttonTextUnblockContent%22:%22Atblo%C4%B7%C4%93t%20saturu%22,%22buttonTextUnblockComment%22:%22Atblo%C4%B7%C4%93t%20koment%C4%81ru%22,%22buttonTextUnblockComments%22:%22Atblo%C4%B7%C4%93t%20koment%C4%81rus%22,%22buttonTextUnblockPost%22:%22Atblo%C4%B7%C4%93t%20zi%C5%86u%22,%22buttonTextUnblockVideo%22:%22Atblo%C4%B7%C4%93t%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20saturu,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20koment%C4%81ru,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1os%20koment%C4%81rus,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20zi%C5%86u,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20videoklipu,%20lai%20ne%C4%BCautu%20Facebook%20tevi%20izsekot%22,%22infoTextUnblockContent%22:%22M%C4%93s%20blo%C4%B7%C4%93j%C4%81m%20Facebook%20iesp%C4%93ju%20tevi%20izsekot,%20iel%C4%81d%C4%93jot%20lapu.%20Ja%20atblo%C4%B7%C4%93si%20%C5%A1o%20saturu,%20Facebook%20redz%C4%93s,%20ko%20tu%20dari.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Uzzin%C4%81t%20vair%C4%81k%22,%22readAbout%22:%22Lasi%20par%20%C5%A1o%20priv%C4%81tuma%20aizsardz%C4%ABbu%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Vai%20iesp%C4%93jot%20visus%20YouTube%20priek%C5%A1skat%C4%ABjumus?%22,%22informationalModalMessageBody%22:%22Priek%C5%A1skat%C4%ABjumu%20r%C4%81d%C4%AB%C5%A1ana%20%C4%BCaus%20Google%20(kam%20pieder%20YouTube)%20redz%C4%93t%20da%C4%BCu%20tavas%20ier%C4%ABces%20inform%C4%81cijas,%20ta%C4%8Du%20tas%20t%C4%81pat%20ir%20priv%C4%81t%C4%81k%20par%20videoklipa%20atska%C5%86o%C5%A1anu.%22,%22informationalModalConfirmButtonText%22:%22Iesp%C4%93jot%20visus%20priek%C5%A1skat%C4%ABjumus%22,%22informationalModalRejectButtonText%22:%22N%C4%93,%20paldies%22,%22buttonTextUnblockVideo%22:%22Atblo%C4%B7%C4%93t%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blo%C4%B7%C4%93ja%20%C5%A1o%20YouTube%20videoklipu,%20lai%20ne%C4%BCautu%20Google%20tevi%20izsekot%22,%22infoTextUnblockVideo%22:%22M%C4%93s%20ne%C4%BC%C4%81v%C4%81m%20Google%20(kam%20pieder%20YouTube)%20tevi%20izsekot,%20kad%20lapa%20tika%20iel%C4%81d%C4%93ta.%20Ja%20atblo%C4%B7%C4%93si%20%C5%A1o%20videoklipu,%20Google%20zin%C4%81s,%20ko%20tu%20dari.%22,%22infoPreviewToggleText%22:%22Priek%C5%A1skat%C4%ABjumi%20ir%20atsp%C4%93joti,%20lai%20nodro%C5%A1in%C4%81tu%20papildu%20konfidencialit%C4%81ti%22,%22infoPreviewToggleEnabledText%22:%22Priek%C5%A1skat%C4%ABjumi%20ir%20iesp%C4%93joti%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EUzzini%20vair%C4%81k%3C/a%3E%20par%20DuckDuckGo%20iegulto%20soci%C4%81lo%20mediju%20aizsardz%C4%ABbu%22%7D%7D,%22nb%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22N%C3%A5r%20du%20logger%20p%C3%A5%20med%20Facebook,%20kan%20de%20spore%20deg%22,%22informationalModalMessageBody%22:%22N%C3%A5r%20du%20er%20logget%20p%C3%A5,%20kan%20ikke%20DuckDuckGo%20hindre%20Facebook-innhold%20i%20%C3%A5%20spore%20deg%20p%C3%A5%20dette%20nettstedet.%22,%22informationalModalConfirmButtonText%22:%22Logg%20inn%22,%22informationalModalRejectButtonText%22:%22G%C3%A5%20tilbake%22,%22loginButtonText%22:%22Logg%20p%C3%A5%20med%20Facebook%22,%22loginBodyText%22:%22N%C3%A5r%20du%20logger%20p%C3%A5%20med%20Facebook,%20sporer%20de%20aktiviteten%20din%20p%C3%A5%20nettstedet.%22,%22buttonTextUnblockContent%22:%22Opphev%20blokkering%20av%20innhold%22,%22buttonTextUnblockComment%22:%22Opphev%20blokkering%20av%20kommentar%22,%22buttonTextUnblockComments%22:%22Opphev%20blokkering%20av%20kommentarer%22,%22buttonTextUnblockPost%22:%22Opphev%20blokkering%20av%20innlegg%22,%22buttonTextUnblockVideo%22:%22Opphev%20blokkering%20av%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blokkerte%20dette%20innholdet%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blokkerte%20denne%20kommentaren%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blokkerte%20disse%20kommentarene%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blokkerte%20dette%20innlegget%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokkerte%20denne%20videoen%20for%20%C3%A5%20hindre%20Facebook%20i%20%C3%A5%20spore%20deg%22,%22infoTextUnblockContent%22:%22Vi%20hindret%20Facebook%20i%20%C3%A5%20spore%20deg%20da%20siden%20ble%20lastet.%20Hvis%20du%20opphever%20blokkeringen%20av%20dette%20innholdet,%20f%C3%A5r%20Facebook%20vite%20om%20aktiviteten%20din.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Finn%20ut%20mer%22,%22readAbout%22:%22Les%20om%20denne%20personvernfunksjonen%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Vil%20du%20aktivere%20alle%20YouTube-forh%C3%A5ndsvisninger?%22,%22informationalModalMessageBody%22:%22Forh%C3%A5ndsvisninger%20gj%C3%B8r%20det%20mulig%20for%20Google%20(som%20eier%20YouTube)%20%C3%A5%20se%20enkelte%20opplysninger%20om%20enheten%20din,%20men%20det%20er%20likevel%20mer%20privat%20enn%20%C3%A5%20spille%20av%20videoen.%22,%22informationalModalConfirmButtonText%22:%22Aktiver%20alle%20forh%C3%A5ndsvisninger%22,%22informationalModalRejectButtonText%22:%22Nei%20takk%22,%22buttonTextUnblockVideo%22:%22Opphev%20blokkering%20av%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blokkerte%20denne%20YouTube-videoen%20for%20%C3%A5%20hindre%20Google%20i%20%C3%A5%20spore%20deg%22,%22infoTextUnblockVideo%22:%22Vi%20blokkerte%20Google%20(som%20eier%20YouTube)%20mot%20%C3%A5%20spore%20deg%20da%20siden%20ble%20lastet.%20Hvis%20du%20opphever%20blokkeringen%20av%20denne%20videoen,%20f%C3%A5r%20Google%20vite%20om%20aktiviteten%20din.%22,%22infoPreviewToggleText%22:%22Forh%C3%A5ndsvisninger%20er%20deaktivert%20for%20%C3%A5%20gi%20deg%20ekstra%20personvern%22,%22infoPreviewToggleEnabledText%22:%22Forh%C3%A5ndsvisninger%20er%20aktivert%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EFinn%20ut%20mer%3C/a%3E%20om%20DuckDuckGos%20innebygde%20beskyttelse%20for%20sosiale%20medier%22%7D%7D,%22nl%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Als%20je%20inlogt%20met%20Facebook,%20kunnen%20zij%20je%20volgen%22,%22informationalModalMessageBody%22:%22Als%20je%20eenmaal%20bent%20ingelogd,%20kan%20DuckDuckGo%20niet%20voorkomen%20dat%20Facebook%20je%20op%20deze%20site%20volgt.%22,%22informationalModalConfirmButtonText%22:%22Inloggen%22,%22informationalModalRejectButtonText%22:%22Terug%22,%22loginButtonText%22:%22Inloggen%20met%20Facebook%22,%22loginBodyText%22:%22Facebook%20volgt%20je%20activiteit%20op%20een%20site%20als%20je%20Facebook%20gebruikt%20om%20in%20te%20loggen.%22,%22buttonTextUnblockContent%22:%22Inhoud%20deblokkeren%22,%22buttonTextUnblockComment%22:%22Opmerking%20deblokkeren%22,%22buttonTextUnblockComments%22:%22Opmerkingen%20deblokkeren%22,%22buttonTextUnblockPost%22:%22Bericht%20deblokkeren%22,%22buttonTextUnblockVideo%22:%22Video%20deblokkeren%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20heeft%20deze%20inhoud%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20heeft%20deze%20opmerking%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20heeft%20deze%20opmerkingen%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20heeft%20dit%20bericht%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20heeft%20deze%20video%20geblokkeerd%20om%20te%20voorkomen%20dat%20Facebook%20je%20kan%20volgen%22,%22infoTextUnblockContent%22:%22We%20hebben%20voorkomen%20dat%20Facebook%20je%20volgde%20toen%20de%20pagina%20werd%20geladen.%20Als%20je%20deze%20inhoud%20deblokkeert,%20kan%20Facebook%20je%20activiteit%20zien.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Meer%20informatie%22,%22readAbout%22:%22Lees%20meer%20over%20deze%20privacybescherming%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Alle%20YouTube-voorbeelden%20inschakelen?%22,%22informationalModalMessageBody%22:%22Bij%20het%20tonen%20van%20voorbeelden%20kan%20Google%20(eigenaar%20van%20YouTube)%20een%20deel%20van%20de%20informatie%20over%20je%20apparaat%20zien,%20maar%20blijft%20je%20privacy%20beter%20beschermd%20dan%20als%20je%20de%20video%20zou%20afspelen.%22,%22informationalModalConfirmButtonText%22:%22Alle%20voorbeelden%20inschakelen%22,%22informationalModalRejectButtonText%22:%22Nee,%20bedankt%22,%22buttonTextUnblockVideo%22:%22Video%20deblokkeren%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20heeft%20deze%20YouTube-video%20geblokkeerd%20om%20te%20voorkomen%20dat%20Google%20je%20kan%20volgen%22,%22infoTextUnblockVideo%22:%22We%20hebben%20voorkomen%20dat%20Google%20(eigenaar%20van%20YouTube)%20je%20volgde%20toen%20de%20pagina%20werd%20geladen.%20Als%20je%20deze%20video%20deblokkeert,%20kan%20Google%20je%20activiteit%20zien.%22,%22infoPreviewToggleText%22:%22Voorbeelden%20uitgeschakeld%20voor%20extra%20privacy%22,%22infoPreviewToggleEnabledText%22:%22Voorbeelden%20ingeschakeld%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EMeer%20informatie%3C/a%3E%20over%20DuckDuckGo's%20bescherming%20tegen%20ingesloten%20social%20media%22%7D%7D,%22pl%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Je%C5%9Bli%20zalogujesz%20si%C4%99%20za%20po%C5%9Brednictwem%20Facebooka,%20b%C4%99dzie%20on%20m%C3%B3g%C5%82%20%C5%9Bledzi%C4%87%20Twoj%C4%85%20aktywno%C5%9B%C4%87%22,%22informationalModalMessageBody%22:%22Po%20zalogowaniu%20si%C4%99%20DuckDuckGo%20nie%20mo%C5%BCe%20zablokowa%C4%87%20mo%C5%BCliwo%C5%9Bci%20%C5%9Bledzenia%20Ci%C4%99%20przez%20Facebooka%20na%20tej%20stronie.%22,%22informationalModalConfirmButtonText%22:%22Zaloguj%20si%C4%99%22,%22informationalModalRejectButtonText%22:%22Wr%C3%B3%C4%87%22,%22loginButtonText%22:%22Zaloguj%20si%C4%99%20za%20po%C5%9Brednictwem%20Facebooka%22,%22loginBodyText%22:%22Facebook%20%C5%9Bledzi%20Twoj%C4%85%20aktywno%C5%9B%C4%87%20na%20stronie,%20gdy%20logujesz%20si%C4%99%20za%20jego%20po%C5%9Brednictwem.%22,%22buttonTextUnblockContent%22:%22Odblokuj%20tre%C5%9B%C4%87%22,%22buttonTextUnblockComment%22:%22Odblokuj%20komentarz%22,%22buttonTextUnblockComments%22:%22Odblokuj%20komentarze%22,%22buttonTextUnblockPost%22:%22Odblokuj%20post%22,%22buttonTextUnblockVideo%22:%22Odblokuj%20wideo%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20zablokowa%C5%82%20t%C4%99%20tre%C5%9B%C4%87,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20zablokowa%C5%82%20ten%20komentarz,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20zablokowa%C5%82%20te%20komentarze,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20zablokowa%C5%82%20ten%20post,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokowa%C5%82%20t%C4%99%20tre%C5%9B%C4%87%20wideo,%20aby%20Facebook%20nie%20m%C3%B3g%C5%82%20Ci%C4%99%20%C5%9Bledzi%C4%87.%22,%22infoTextUnblockContent%22:%22Zablokowali%C5%9Bmy%20Facebookowi%20mo%C5%BCliwo%C5%9B%C4%87%20%C5%9Bledzenia%20Ci%C4%99%20podczas%20%C5%82adowania%20strony.%20Je%C5%9Bli%20odblokujesz%20t%C4%99%20tre%C5%9B%C4%87,%20Facebook%20uzyska%20informacje%20o%20Twojej%20aktywno%C5%9Bci.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Dowiedz%20si%C4%99%20wi%C4%99cej%22,%22readAbout%22:%22Dowiedz%20si%C4%99%20wi%C4%99cej%20o%20tej%20ochronie%20prywatno%C5%9Bci%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22W%C5%82%C4%85czy%C4%87%20wszystkie%20podgl%C4%85dy%20w%20YouTube?%22,%22informationalModalMessageBody%22:%22Wy%C5%9Bwietlanie%20podgl%C4%85du%20pozwala%20Google%20(kt%C3%B3ry%20jest%20w%C5%82a%C5%9Bcicielem%20YouTube)%20zobaczy%C4%87%20niekt%C3%B3re%20informacje%20o%20Twoim%20urz%C4%85dzeniu,%20ale%20nadal%20jest%20to%20bardziej%20prywatne%20ni%C5%BC%20odtwarzanie%20filmu.%22,%22informationalModalConfirmButtonText%22:%22W%C5%82%C4%85cz%20wszystkie%20podgl%C4%85dy%22,%22informationalModalRejectButtonText%22:%22Nie,%20dzi%C4%99kuj%C4%99%22,%22buttonTextUnblockVideo%22:%22Odblokuj%20wideo%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokowa%C5%82%20ten%20film%20w%20YouTube,%20aby%20uniemo%C5%BCliwi%C4%87%20Google%20%C5%9Bledzenie%20Twojej%20aktywno%C5%9Bci%22,%22infoTextUnblockVideo%22:%22Zablokowali%C5%9Bmy%20mo%C5%BCliwo%C5%9B%C4%87%20%C5%9Bledzenia%20Ci%C4%99%20przez%20Google%20(w%C5%82a%C5%9Bciciela%20YouTube)%20podczas%20%C5%82adowania%20strony.%20Je%C5%9Bli%20odblokujesz%20ten%20film,%20Google%20zobaczy%20Twoj%C4%85%20aktywno%C5%9B%C4%87.%22,%22infoPreviewToggleText%22:%22Podgl%C4%85dy%20zosta%C5%82y%20wy%C5%82%C4%85czone,%20aby%20zapewni%C4%87%20wi%C4%99ksz%C4%85%20ptywatno%C5%9B%C4%87%22,%22infoPreviewToggleEnabledText%22:%22Podgl%C4%85dy%20w%C5%82%C4%85czone%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EDowiedz%20si%C4%99%20wi%C4%99cej%3C/a%3E%20o%20zabezpieczeniu%20osadzonych%20tre%C5%9Bci%20spo%C5%82eczno%C5%9Bciowych%20DuckDuckGo%22%7D%7D,%22pt%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Iniciar%20sess%C3%A3o%20no%20Facebook%20permite%20que%20este%20te%20rastreie%22,%22informationalModalMessageBody%22:%22Depois%20de%20iniciares%20sess%C3%A3o,%20o%20DuckDuckGo%20n%C3%A3o%20poder%C3%A1%20bloquear%20o%20rastreio%20por%20parte%20do%20conte%C3%BAdo%20do%20Facebook%20neste%20site.%22,%22informationalModalConfirmButtonText%22:%22Iniciar%20sess%C3%A3o%22,%22informationalModalRejectButtonText%22:%22Retroceder%22,%22loginButtonText%22:%22Iniciar%20sess%C3%A3o%20com%20o%20Facebook%22,%22loginBodyText%22:%22O%20Facebook%20rastreia%20a%20tua%20atividade%20num%20site%20quando%20o%20usas%20para%20iniciares%20sess%C3%A3o.%22,%22buttonTextUnblockContent%22:%22Desbloquear%20Conte%C3%BAdo%22,%22buttonTextUnblockComment%22:%22Desbloquear%20Coment%C3%A1rio%22,%22buttonTextUnblockComments%22:%22Desbloquear%20Coment%C3%A1rios%22,%22buttonTextUnblockPost%22:%22Desbloquear%20Publica%C3%A7%C3%A3o%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20V%C3%ADdeo%22,%22infoTitleUnblockContent%22:%22O%20DuckDuckGo%20bloqueou%20este%20conte%C3%BAdo%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockComment%22:%22O%20DuckDuckGo%20bloqueou%20este%20coment%C3%A1rio%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockComments%22:%22O%20DuckDuckGo%20bloqueou%20estes%20coment%C3%A1rios%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockPost%22:%22O%20DuckDuckGo%20bloqueou%20esta%20publica%C3%A7%C3%A3o%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTitleUnblockVideo%22:%22O%20DuckDuckGo%20bloqueou%20este%20v%C3%ADdeo%20para%20evitar%20que%20o%20Facebook%20te%20rastreie%22,%22infoTextUnblockContent%22:%22Bloque%C3%A1mos%20o%20rastreio%20por%20parte%20do%20Facebook%20quando%20a%20p%C3%A1gina%20foi%20carregada.%20Se%20desbloqueares%20este%20conte%C3%BAdo,%20o%20Facebook%20fica%20a%20saber%20a%20tua%20atividade.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Saiba%20mais%22,%22readAbout%22:%22Ler%20mais%20sobre%20esta%20prote%C3%A7%C3%A3o%20de%20privacidade%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Ativar%20todas%20as%20pr%C3%A9-visualiza%C3%A7%C3%B5es%20do%20YouTube?%22,%22informationalModalMessageBody%22:%22Mostrar%20visualiza%C3%A7%C3%B5es%20permite%20%C3%A0%20Google%20(que%20det%C3%A9m%20o%20YouTube)%20ver%20algumas%20das%20informa%C3%A7%C3%B5es%20do%20teu%20dispositivo,%20mas%20ainda%20%C3%A9%20mais%20privado%20do%20que%20reproduzir%20o%20v%C3%ADdeo.%22,%22informationalModalConfirmButtonText%22:%22Ativar%20todas%20as%20pr%C3%A9-visualiza%C3%A7%C3%B5es%22,%22informationalModalRejectButtonText%22:%22N%C3%A3o,%20obrigado%22,%22buttonTextUnblockVideo%22:%22Desbloquear%20V%C3%ADdeo%22,%22infoTitleUnblockVideo%22:%22O%20DuckDuckGo%20bloqueou%20este%20v%C3%ADdeo%20do%20YouTube%20para%20impedir%20que%20a%20Google%20te%20rastreie%22,%22infoTextUnblockVideo%22:%22Bloque%C3%A1mos%20o%20rastreio%20por%20parte%20da%20Google%20(que%20det%C3%A9m%20o%20YouTube)%20quando%20a%20p%C3%A1gina%20foi%20carregada.%20Se%20desbloqueares%20este%20v%C3%ADdeo,%20a%20Google%20fica%20a%20saber%20a%20tua%20atividade.%22,%22infoPreviewToggleText%22:%22Pr%C3%A9-visualiza%C3%A7%C3%B5es%20desativadas%20para%20privacidade%20adicional%22,%22infoPreviewToggleEnabledText%22:%22Pr%C3%A9-visualiza%C3%A7%C3%B5es%20ativadas%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3ESaiba%20mais%3C/a%3E%20sobre%20a%20Prote%C3%A7%C3%A3o%20contra%20conte%C3%BAdos%20de%20redes%20sociais%20incorporados%20do%20DuckDuckGo%22%7D%7D,%22ro%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Conectarea%20cu%20Facebook%20%C3%AEi%20permite%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22informationalModalMessageBody%22:%22Odat%C4%83%20ce%20te-ai%20conectat,%20DuckDuckGo%20nu%20poate%20%C3%AEmpiedica%20con%C8%9Binutul%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%20pe%20acest%20site.%22,%22informationalModalConfirmButtonText%22:%22Autentificare%22,%22informationalModalRejectButtonText%22:%22%C3%8Enapoi%22,%22loginButtonText%22:%22Conecteaz%C4%83-te%20cu%20Facebook%22,%22loginBodyText%22:%22Facebook%20urm%C4%83re%C8%99te%20activitatea%20ta%20pe%20un%20site%20atunci%20c%C3%A2nd%20%C3%AEl%20utilizezi%20pentru%20a%20te%20conecta.%22,%22buttonTextUnblockContent%22:%22Deblocheaz%C4%83%20con%C8%9Binutul%22,%22buttonTextUnblockComment%22:%22Deblocheaz%C4%83%20comentariul%22,%22buttonTextUnblockComments%22:%22Deblocheaz%C4%83%20comentariile%22,%22buttonTextUnblockPost%22:%22Deblocheaz%C4%83%20postarea%22,%22buttonTextUnblockVideo%22:%22Deblocheaz%C4%83%20videoclipul%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20a%20blocat%20acest%20con%C8%9Binut%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20a%20blocat%20acest%20comentariu%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20a%20blocat%20aceste%20comentarii%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20a%20blocat%20aceast%C4%83%20postare%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20blocat%20acest%20videoclip%20pentru%20a%20%C3%AEmpiedica%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTextUnblockContent%22:%22Am%20%C3%AEmpiedicat%20Facebook%20s%C4%83%20te%20urm%C4%83reasc%C4%83%20atunci%20c%C3%A2nd%20pagina%20a%20fost%20%C3%AEnc%C4%83rcat%C4%83.%20Dac%C4%83%20deblochezi%20acest%20con%C8%9Binut,%20Facebook%20%C3%AE%C8%9Bi%20va%20cunoa%C8%99te%20activitatea.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Afl%C4%83%20mai%20multe%22,%22readAbout%22:%22Cite%C8%99te%20despre%20aceast%C4%83%20protec%C8%9Bie%20a%20confiden%C8%9Bialit%C4%83%C8%9Bii%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Activezi%20toate%20previzualiz%C4%83rile%20YouTube?%22,%22informationalModalMessageBody%22:%22Afi%C8%99area%20previzualiz%C4%83rilor%20va%20permite%20ca%20Google%20(care%20de%C8%9Bine%20YouTube)%20s%C4%83%20vad%C4%83%20unele%20dintre%20informa%C8%9Biile%20despre%20dispozitivul%20t%C4%83u,%20dar%20este%20totu%C8%99i%20mai%20privat%C4%83%20dec%C3%A2t%20redarea%20videoclipului.%22,%22informationalModalConfirmButtonText%22:%22Activeaz%C4%83%20toate%20previzualiz%C4%83rile%22,%22informationalModalRejectButtonText%22:%22Nu,%20mul%C8%9Bumesc%22,%22buttonTextUnblockVideo%22:%22Deblocheaz%C4%83%20videoclipul%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20a%20blocat%20acest%20videoclip%20de%20pe%20YouTube%20pentru%20a%20%C3%AEmpiedica%20Google%20s%C4%83%20te%20urm%C4%83reasc%C4%83%22,%22infoTextUnblockVideo%22:%22Am%20%C3%AEmpiedicat%20Google%20(care%20de%C8%9Bine%20YouTube)%20s%C4%83%20te%20urm%C4%83reasc%C4%83%20atunci%20c%C3%A2nd%20s-a%20%C3%AEnc%C4%83rcat%20pagina.%20Dac%C4%83%20deblochezi%20acest%20videoclip,%20Google%20va%20cunoa%C8%99te%20activitatea%20ta.%22,%22infoPreviewToggleText%22:%22Previzualiz%C4%83rile%20au%20fost%20dezactivate%20pentru%20o%20confiden%C8%9Bialitate%20suplimentar%C4%83%22,%22infoPreviewToggleEnabledText%22:%22Previzualiz%C4%83ri%20activate%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EAfl%C4%83%20mai%20multe%3C/a%3E%20despre%20Protec%C8%9Bia%20integrat%C4%83%20DuckDuckGo%20pentru%20re%C8%9Belele%20sociale%22%7D%7D,%22ru%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%92%D1%85%D0%BE%D0%B4%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20Facebook%20%D0%BF%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D1%8F%D0%B5%D1%82%20%D1%8D%D1%82%D0%BE%D0%B9%20%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9%20%D1%81%D0%B5%D1%82%D0%B8%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B0%D1%81%22,%22informationalModalMessageBody%22:%22%D0%9F%D0%BE%D1%81%D0%BB%D0%B5%20%D0%B2%D1%85%D0%BE%D0%B4%D0%B0%20DuckDuckGo%20%D0%BD%D0%B5%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B0%D1%88%D0%B8%D1%85%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D0%B9%20%D1%81%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82%D0%BE%D0%BC%20%D0%BD%D0%B0%20Facebook.%22,%22informationalModalConfirmButtonText%22:%22%D0%92%D0%BE%D0%B9%D1%82%D0%B8%22,%22informationalModalRejectButtonText%22:%22%D0%92%D0%B5%D1%80%D0%BD%D1%83%D1%82%D1%8C%D1%81%D1%8F%22,%22loginButtonText%22:%22%D0%92%D0%BE%D0%B9%D1%82%D0%B8%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20Facebook%22,%22loginBodyText%22:%22%D0%9F%D1%80%D0%B8%20%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B8%20%D1%83%D1%87%D0%B5%D1%82%D0%BD%D0%BE%D0%B9%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D0%B8%20Facebook%20%D0%B4%D0%BB%D1%8F%20%D0%B2%D1%85%D0%BE%D0%B4%D0%B0%20%D0%BD%D0%B0%20%D1%81%D0%B0%D0%B9%D1%82%D1%8B%20%D1%8D%D1%82%D0%B0%20%D1%81%D0%BE%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F%20%D1%81%D0%B5%D1%82%D1%8C%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D1%82%D1%8C%20%D0%BD%D0%B0%20%D0%BD%D0%B8%D1%85%20%D0%B2%D0%B0%D1%88%D0%B8%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F.%22,%22buttonTextUnblockContent%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockComment%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockComments%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockPost%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%D1%82%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%D1%82%20%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D0%B9,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%B8%20%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D0%B8,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D1%83%20%D0%BF%D1%83%D0%B1%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8E,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Facebook%22,%22infoTextUnblockContent%22:%22%D0%92%D0%BE%20%D0%B2%D1%80%D0%B5%D0%BC%D1%8F%20%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B%20%D0%BC%D1%8B%20%D0%BF%D0%BE%D0%BC%D0%B5%D1%88%D0%B0%D0%BB%D0%B8%20Facebook%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D0%B8%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F.%20%D0%95%D1%81%D0%BB%D0%B8%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D1%8D%D1%82%D0%BE%D1%82%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82,%20Facebook%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D1%84%D0%B8%D0%BA%D1%81%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D1%83%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82%D1%8C.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22%D0%A3%D0%B7%D0%BD%D0%B0%D1%82%D1%8C%20%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5%22,%22readAbout%22:%22%D0%9F%D0%BE%D0%B4%D1%80%D0%BE%D0%B1%D0%BD%D0%B5%D0%B5%20%D0%BE%D0%B1%20%D1%8D%D1%82%D0%BE%D0%BC%20%D0%B2%D0%B8%D0%B4%D0%B5%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D1%8B%20%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B4%D0%B5%D0%BD%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%D0%92%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D0%B8%D0%B7%20YouTube?%22,%22informationalModalMessageBody%22:%22%D0%90%D0%BA%D1%82%D0%B8%D0%B2%D0%B0%D1%86%D0%B8%D1%8F%20%D0%BF%D1%80%D0%B5%D0%B4%D0%B2%D0%B0%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B0%20%D0%BF%D0%BE%D0%B7%D0%B2%D0%BE%D0%BB%D0%B8%D1%82%20Google%20(%D0%B2%D0%BB%D0%B0%D0%B4%D0%B5%D0%BB%D1%8C%D1%86%D1%83%20YouTube)%20%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B8%D1%82%D1%8C%20%D0%BD%D0%B5%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D1%8B%D0%B5%20%D1%81%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F%20%D0%BE%20%D0%B2%D0%B0%D1%88%D0%B5%D0%BC%20%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B5,%20%D0%BE%D0%B4%D0%BD%D0%B0%D0%BA%D0%BE%20%D1%8D%D1%82%D0%BE%20%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5%20%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D1%8B%D0%B9%20%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82,%20%D1%87%D0%B5%D0%BC%20%D0%B2%D0%BE%D1%81%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D1%86%D0%B5%D0%BB%D0%B8%D0%BA%D0%BE%D0%BC.%22,%22informationalModalConfirmButtonText%22:%22%D0%92%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C%20%D0%BF%D1%80%D0%B5%D0%B4%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%22,%22informationalModalRejectButtonText%22:%22%D0%9D%D0%B5%D1%82,%20%D1%81%D0%BF%D0%B0%D1%81%D0%B8%D0%B1%D0%BE%22,%22buttonTextUnblockVideo%22:%22%D0%A0%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20%D0%B7%D0%B0%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BB%20%D1%8D%D1%82%D0%BE%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE%20%D0%B8%D0%B7%20YouTube,%20%D1%87%D1%82%D0%BE%D0%B1%D1%8B%20%D0%B2%D0%B0%D1%81%20%D0%BD%D0%B5%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B6%D0%B8%D0%B2%D0%B0%D0%BB%20Google%22,%22infoTextUnblockVideo%22:%22%D0%92%D0%BE%20%D0%B2%D1%80%D0%B5%D0%BC%D1%8F%20%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8%20%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B%20%D0%BC%D1%8B%20%D0%BF%D0%BE%D0%BC%D0%B5%D1%88%D0%B0%D0%BB%D0%B8%20Google%20(%D0%B2%D0%BB%D0%B0%D0%B4%D0%B5%D0%BB%D1%8C%D1%86%D1%83%20YouTube)%20%D0%BE%D1%82%D1%81%D0%BB%D0%B5%D0%B4%D0%B8%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D0%B8%20%D0%B4%D0%B5%D0%B9%D1%81%D1%82%D0%B2%D0%B8%D1%8F.%20%D0%95%D1%81%D0%BB%D0%B8%20%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE,%20Google%20%D1%81%D0%BC%D0%BE%D0%B6%D0%B5%D1%82%20%D1%84%D0%B8%D0%BA%D1%81%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B2%D0%B0%D1%88%D1%83%20%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D1%81%D1%82%D1%8C.%22,%22infoPreviewToggleText%22:%22%D0%9F%D1%80%D0%B5%D0%B4%D0%B2%D0%B0%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%20%D0%BE%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%20%D0%B4%D0%BB%D1%8F%20%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D1%8B%20%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B4%D0%B5%D0%BD%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8%22,%22infoPreviewToggleEnabledText%22:%22%D0%9F%D1%80%D0%B5%D0%B4%D0%B2%D0%B0%D1%80%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9%20%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%20%D0%B2%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3E%D0%9F%D0%BE%D0%B4%D1%80%D0%BE%D0%B1%D0%BD%D0%B5%D0%B5%3C/a%3E%20%D0%BE%20%D0%B7%D0%B0%D1%89%D0%B8%D1%82%D0%B5%20DuckDuckGo%20%D0%BE%D1%82%20%D0%B2%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%BD%D0%BE%D0%B3%D0%BE%20%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82%D0%B0%20%D1%81%D0%BE%D1%86%D1%81%D0%B5%D1%82%D0%B5%D0%B9%22%7D%7D,%22sk%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Prihl%C3%A1senie%20cez%20Facebook%20mu%20umo%C5%BEn%C3%AD%20sledova%C5%A5%20v%C3%A1s%22,%22informationalModalMessageBody%22:%22DuckDuckGo%20po%20prihl%C3%A1sen%C3%AD%20nem%C3%B4%C5%BEe%20na%20tejto%20lokalite%20zablokova%C5%A5%20sledovanie%20va%C5%A1ej%20osoby%20obsahom%20Facebooku.%22,%22informationalModalConfirmButtonText%22:%22Prihl%C3%A1si%C5%A5%20sa%22,%22informationalModalRejectButtonText%22:%22Prejs%C5%A5%20sp%C3%A4%C5%A5%22,%22loginButtonText%22:%22Prihl%C3%A1ste%20sa%20pomocou%20slu%C5%BEby%20Facebook%22,%22loginBodyText%22:%22Ke%C4%8F%20pou%C5%BEijete%20prihlasovanie%20cez%20Facebook,%20Facebook%20bude%20na%20lokalite%20sledova%C5%A5%20va%C5%A1u%20aktivitu.%22,%22buttonTextUnblockContent%22:%22Odblokova%C5%A5%20obsah%22,%22buttonTextUnblockComment%22:%22Odblokova%C5%A5%20koment%C3%A1r%22,%22buttonTextUnblockComments%22:%22Odblokova%C5%A5%20koment%C3%A1re%22,%22buttonTextUnblockPost%22:%22Odblokova%C5%A5%20pr%C3%ADspevok%22,%22buttonTextUnblockVideo%22:%22Odblokova%C5%A5%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20zablokoval%20tento%20obsah,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20zablokoval%20tento%20koment%C3%A1r,%20aby%20zabr%C3%A1nil%20sledovaniu%20zo%20strany%20Facebooku%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20zablokoval%20tieto%20koment%C3%A1re,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20zablokoval%20tento%20pr%C3%ADspevok,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20zablokoval%20toto%20video,%20aby%20v%C3%A1s%20Facebook%20nesledoval%22,%22infoTextUnblockContent%22:%22Pri%20na%C4%8D%C3%ADtan%C3%AD%20str%C3%A1nky%20sme%20zablokovali%20Facebook,%20aby%20v%C3%A1s%20nesledoval.%20Ak%20tento%20obsah%20odblokujete,%20Facebook%20bude%20vedie%C5%A5%20o%20va%C5%A1ej%20aktivite.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Zistite%20viac%22,%22readAbout%22:%22Pre%C4%8D%C3%ADtajte%20si%20o%20tejto%20ochrane%20s%C3%BAkromia%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Chcete%20povoli%C5%A5%20v%C5%A1etky%20uk%C3%A1%C5%BEky%20zo%20slu%C5%BEby%20YouTube?%22,%22informationalModalMessageBody%22:%22Zobrazenie%20uk%C3%A1%C5%BEok%20umo%C5%BEn%C3%AD%20spolo%C4%8Dnosti%20Google%20(ktor%C3%A1%20vlastn%C3%AD%20YouTube)%20vidie%C5%A5%20niektor%C3%A9%20inform%C3%A1cie%20o%20va%C5%A1om%20zariaden%C3%AD,%20ale%20st%C3%A1le%20je%20to%20s%C3%BAkromnej%C5%A1ie%20ako%20prehr%C3%A1vanie%20videa.%22,%22informationalModalConfirmButtonText%22:%22Povoli%C5%A5%20v%C5%A1etky%20uk%C3%A1%C5%BEky%22,%22informationalModalRejectButtonText%22:%22Nie,%20%C4%8Fakujem%22,%22buttonTextUnblockVideo%22:%22Odblokova%C5%A5%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20toto%20video%20v%20slu%C5%BEbe%20YouTube%20zablokoval%20s%20cie%C4%BEom%20pred%C3%ADs%C5%A5%20tomu,%20aby%20v%C3%A1s%20spolo%C4%8Dnos%C5%A5%20Google%20mohla%20sledova%C5%A5%22,%22infoTextUnblockVideo%22:%22Zablokovali%20sme%20pre%20spolo%C4%8Dnos%C5%A5%20Google%20(ktor%C3%A1%20vlastn%C3%AD%20YouTube),%20aby%20v%C3%A1s%20nemohla%20sledova%C5%A5,%20ke%C4%8F%20sa%20str%C3%A1nka%20na%C4%8D%C3%ADta.%20Ak%20toto%20video%20odblokujete,%20Google%20bude%20pozna%C5%A5%20va%C5%A1u%20aktivitu.%22,%22infoPreviewToggleText%22:%22Uk%C3%A1%C5%BEky%20s%C3%BA%20zak%C3%A1zan%C3%A9%20s%20cie%C4%BEom%20zv%C3%BD%C5%A1i%C5%A5%20ochranu%20s%C3%BAkromia%22,%22infoPreviewToggleEnabledText%22:%22Uk%C3%A1%C5%BEky%20s%C3%BA%20povolen%C3%A9%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EZ%C3%ADskajte%20viac%20inform%C3%A1ci%C3%AD%3C/a%3E%20o%20DuckDuckGo,%20vlo%C5%BEenej%20ochrane%20soci%C3%A1lnych%20m%C3%A9di%C3%AD%22%7D%7D,%22sl%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22%C4%8Ce%20se%20prijavite%20s%20Facebookom,%20vam%20Facebook%20lahko%20sledi%22,%22informationalModalMessageBody%22:%22Ko%20ste%20enkrat%20prijavljeni,%20DuckDuckGo%20ne%20more%20blokirati%20Facebookove%20vsebine,%20da%20bi%20vam%20sledila%20na%20tem%20spletnem%20mestu.%22,%22informationalModalConfirmButtonText%22:%22Prijava%22,%22informationalModalRejectButtonText%22:%22Pojdi%20nazaj%22,%22loginButtonText%22:%22Prijavite%20se%20s%20Facebookom%22,%22loginBodyText%22:%22%C4%8Ce%20se%20prijavite%20s%20Facebookom,%20bo%20nato%20spremljal%20va%C5%A1a%20dejanja%20na%20spletnem%20mestu.%22,%22buttonTextUnblockContent%22:%22Odblokiraj%20vsebino%22,%22buttonTextUnblockComment%22:%22Odblokiraj%20komentar%22,%22buttonTextUnblockComments%22:%22Odblokiraj%20komentarje%22,%22buttonTextUnblockPost%22:%22Odblokiraj%20objavo%22,%22buttonTextUnblockVideo%22:%22Odblokiraj%20videoposnetek%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20je%20blokiral%20to%20vsebino,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20je%20blokiral%20ta%20komentar,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20je%20blokiral%20te%20komentarje,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20je%20blokiral%20to%20objavo,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokiral%20ta%20videoposnetek,%20da%20bi%20Facebooku%20prepre%C4%8Dil%20sledenje%22,%22infoTextUnblockContent%22:%22Ko%20se%20je%20stran%20nalo%C5%BEila,%20smo%20Facebooku%20prepre%C4%8Dili,%20da%20bi%20vam%20sledil.%20%C4%8Ce%20to%20vsebino%20odblokirate,%20bo%20Facebook%20izvedel%20za%20va%C5%A1a%20dejanja.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Ve%C4%8D%22,%22readAbout%22:%22Preberite%20ve%C4%8D%20o%20tej%20za%C5%A1%C4%8Diti%20zasebnosti%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22%C5%BDelite%20omogo%C4%8Diti%20vse%20YouTubove%20predoglede?%22,%22informationalModalMessageBody%22:%22Prikaz%20predogledov%20omogo%C4%8Da%20Googlu%20(ki%20je%20lastnik%20YouTuba)%20vpogled%20v%20nekatere%20podatke%20o%20napravi,%20vendar%20je%20%C5%A1e%20vedno%20bolj%20zasebno%20kot%20predvajanje%20videoposnetka.%22,%22informationalModalConfirmButtonText%22:%22Omogo%C4%8Di%20vse%20predoglede%22,%22informationalModalRejectButtonText%22:%22Ne,%20hvala%22,%22buttonTextUnblockVideo%22:%22Odblokiraj%20videoposnetek%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20je%20blokiral%20ta%20videoposnetek%20v%20YouTubu,%20da%20bi%20Googlu%20prepre%C4%8Dil%20sledenje%22,%22infoTextUnblockVideo%22:%22Googlu%20(ki%20je%20lastnik%20YouTuba)%20smo%20prepre%C4%8Dili,%20da%20bi%20vam%20sledil,%20ko%20se%20je%20stran%20nalo%C5%BEila.%20%C4%8Ce%20odblokirate%20ta%20videoposnetek,%20bo%20Google%20izvedel%20za%20va%C5%A1o%20dejavnost.%22,%22infoPreviewToggleText%22:%22Predogledi%20so%20zaradi%20dodatne%20zasebnosti%20onemogo%C4%8Deni%22,%22infoPreviewToggleEnabledText%22:%22Predogledi%20so%20omogo%C4%8Deni%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EVe%C4%8D%3C/a%3E%20o%20vgrajeni%20za%C5%A1%C4%8Diti%20dru%C5%BEbenih%20medijev%20DuckDuckGo%22%7D%7D,%22sv%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Om%20du%20loggar%20in%20med%20Facebook%20kan%20de%20sp%C3%A5ra%20dig%22,%22informationalModalMessageBody%22:%22N%C3%A4r%20du%20v%C3%A4l%20%C3%A4r%20inloggad%20kan%20DuckDuckGo%20inte%20hindra%20Facebooks%20inneh%C3%A5ll%20fr%C3%A5n%20att%20sp%C3%A5ra%20dig%20p%C3%A5%20den%20h%C3%A4r%20webbplatsen.%22,%22informationalModalConfirmButtonText%22:%22Logga%20in%22,%22informationalModalRejectButtonText%22:%22G%C3%A5%20tillbaka%22,%22loginButtonText%22:%22Logga%20in%20med%20Facebook%22,%22loginBodyText%22:%22Facebook%20sp%C3%A5rar%20din%20aktivitet%20p%C3%A5%20en%20webbplats%20om%20du%20anv%C3%A4nder%20det%20f%C3%B6r%20att%20logga%20in.%22,%22buttonTextUnblockContent%22:%22Avblockera%20inneh%C3%A5ll%22,%22buttonTextUnblockComment%22:%22Avblockera%20kommentar%22,%22buttonTextUnblockComments%22:%22Avblockera%20kommentarer%22,%22buttonTextUnblockPost%22:%22Avblockera%20inl%C3%A4gg%22,%22buttonTextUnblockVideo%22:%22Avblockera%20video%22,%22infoTitleUnblockContent%22:%22DuckDuckGo%20blockerade%20det%20h%C3%A4r%20inneh%C3%A5llet%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockComment%22:%22DuckDuckGo%20blockerade%20den%20h%C3%A4r%20kommentaren%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockComments%22:%22DuckDuckGo%20blockerade%20de%20h%C3%A4r%20kommentarerna%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockPost%22:%22DuckDuckGo%20blockerade%20det%20h%C3%A4r%20inl%C3%A4gget%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blockerade%20den%20h%C3%A4r%20videon%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Facebook%20sp%C3%A5rar%20dig%22,%22infoTextUnblockContent%22:%22Vi%20hindrade%20Facebook%20fr%C3%A5n%20att%20sp%C3%A5ra%20dig%20n%C3%A4r%20sidan%20l%C3%A4stes%20in.%20Om%20du%20avblockerar%20det%20h%C3%A4r%20inneh%C3%A5llet%20kommer%20Facebook%20att%20k%C3%A4nna%20till%20din%20aktivitet.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22L%C3%A4s%20mer%22,%22readAbout%22:%22L%C3%A4s%20mer%20om%20detta%20integritetsskydd%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22Aktivera%20alla%20f%C3%B6rhandsvisningar%20f%C3%B6r%20YouTube?%22,%22informationalModalMessageBody%22:%22Genom%20att%20visa%20f%C3%B6rhandsvisningar%20kan%20Google%20(som%20%C3%A4ger%20YouTube)%20se%20en%20del%20av%20enhetens%20information,%20men%20det%20%C3%A4r%20%C3%A4nd%C3%A5%20mer%20privat%20%C3%A4n%20att%20spela%20upp%20videon.%22,%22informationalModalConfirmButtonText%22:%22Aktivera%20alla%20f%C3%B6rhandsvisningar%22,%22informationalModalRejectButtonText%22:%22Nej%20tack%22,%22buttonTextUnblockVideo%22:%22Avblockera%20video%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo%20blockerade%20den%20h%C3%A4r%20YouTube-videon%20f%C3%B6r%20att%20f%C3%B6rhindra%20att%20Google%20sp%C3%A5rar%20dig%22,%22infoTextUnblockVideo%22:%22Vi%20hindrade%20Google%20(som%20%C3%A4ger%20YouTube)%20fr%C3%A5n%20att%20sp%C3%A5ra%20dig%20n%C3%A4r%20sidan%20laddades.%20Om%20du%20tar%20bort%20blockeringen%20av%20videon%20kommer%20Google%20att%20k%C3%A4nna%20till%20din%20aktivitet.%22,%22infoPreviewToggleText%22:%22F%C3%B6rhandsvisningar%20har%20inaktiverats%20f%C3%B6r%20ytterligare%20integritet%22,%22infoPreviewToggleEnabledText%22:%22F%C3%B6rhandsvisningar%20aktiverade%22,%22infoPreviewInfoText%22:%22%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3EL%C3%A4s%20mer%3C/a%3E%20om%20DuckDuckGos%20skydd%20mot%20inb%C3%A4ddade%20sociala%20medier%22%7D%7D,%22tr%22:%7B%22facebook.json%22:%7B%22informationalModalMessageTitle%22:%22Facebook%20ile%20giri%C5%9F%20yapmak,%20sizi%20takip%20etmelerini%20sa%C4%9Flar%22,%22informationalModalMessageBody%22:%22Giri%C5%9F%20yapt%C4%B1ktan%20sonra,%20DuckDuckGo%20Facebook%20i%C3%A7eri%C4%9Finin%20sizi%20bu%20sitede%20izlemesini%20engelleyemez.%22,%22informationalModalConfirmButtonText%22:%22Oturum%20A%C3%A7%22,%22informationalModalRejectButtonText%22:%22Geri%20d%C3%B6n%22,%22loginButtonText%22:%22Facebook%20ile%20giri%C5%9F%20yap%C4%B1n%22,%22loginBodyText%22:%22Facebook,%20giri%C5%9F%20yapmak%20i%C3%A7in%20kulland%C4%B1%C4%9F%C4%B1n%C4%B1zda%20bir%20sitedeki%20etkinli%C4%9Finizi%20izler.%22,%22buttonTextUnblockContent%22:%22%C4%B0%C3%A7eri%C4%9Fin%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockComment%22:%22Yorumun%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockComments%22:%22Yorumlar%C4%B1n%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockPost%22:%22G%C3%B6nderinin%20Engelini%20Kald%C4%B1r%22,%22buttonTextUnblockVideo%22:%22Videonun%20Engelini%20Kald%C4%B1r%22,%22infoTitleUnblockContent%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20i%C3%A7eri%C4%9Fi%20engelledi%22,%22infoTitleUnblockComment%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20yorumu%20engelledi%22,%22infoTitleUnblockComments%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20yorumlar%C4%B1%20engelledi%22,%22infoTitleUnblockPost%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20g%C3%B6nderiyi%20engelledi%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo,%20Facebook'un%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20videoyu%20engelledi%22,%22infoTextUnblockContent%22:%22Sayfa%20y%C3%BCklendi%C4%9Finde%20Facebook'un%20sizi%20izlemesini%20engelledik.%20Bu%20i%C3%A7eri%C4%9Fin%20engelini%20kald%C4%B1r%C4%B1rsan%C4%B1z%20Facebook%20etkinli%C4%9Finizi%20%C3%B6%C4%9Frenecektir.%22%7D,%22shared.json%22:%7B%22learnMore%22:%22Daha%20Fazla%20Bilgi%22,%22readAbout%22:%22Bu%20gizlilik%20korumas%C4%B1%20hakk%C4%B1nda%20bilgi%20edinin%22%7D,%22youtube.json%22:%7B%22informationalModalMessageTitle%22:%22T%C3%BCm%20YouTube%20%C3%B6nizlemeleri%20etkinle%C5%9Ftirilsin%20mi?%22,%22informationalModalMessageBody%22:%22%C3%96nizlemelerin%20g%C3%B6sterilmesi%20Google'%C4%B1n%20(YouTube'un%20sahibi)%20cihaz%C4%B1n%C4%B1z%C4%B1n%20baz%C4%B1%20bilgilerini%20g%C3%B6rmesine%20izin%20verir,%20ancak%20yine%20de%20videoyu%20oynatmaktan%20daha%20%C3%B6zeldir.%22,%22informationalModalConfirmButtonText%22:%22T%C3%BCm%20%C3%96nizlemeleri%20Etkinle%C5%9Ftir%22,%22informationalModalRejectButtonText%22:%22Hay%C4%B1r%20Te%C5%9Fekk%C3%BCrler%22,%22buttonTextUnblockVideo%22:%22Videonun%20Engelini%20Kald%C4%B1r%22,%22infoTitleUnblockVideo%22:%22DuckDuckGo,%20Google'%C4%B1n%20sizi%20izlemesini%20%C3%B6nlemek%20i%C3%A7in%20bu%20YouTube%20videosunu%20engelledi%22,%22infoTextUnblockVideo%22:%22Sayfa%20y%C3%BCklendi%C4%9Finde%20Google'%C4%B1n%20(YouTube'un%20sahibi)%20sizi%20izlemesini%20engelledik.%20Bu%20videonun%20engelini%20kald%C4%B1r%C4%B1rsan%C4%B1z,%20Google%20etkinli%C4%9Finizi%20%C3%B6%C4%9Frenecektir.%22,%22infoPreviewToggleText%22:%22Ek%20gizlilik%20i%C3%A7in%20%C3%B6nizlemeler%20devre%20d%C4%B1%C5%9F%C4%B1%20b%C4%B1rak%C4%B1ld%C4%B1%22,%22infoPreviewToggleEnabledText%22:%22%C3%96nizlemeler%20etkinle%C5%9Ftirildi%22,%22infoPreviewInfoText%22:%22DuckDuckGo%20Yerle%C5%9Fik%20Sosyal%20Medya%20Korumas%C4%B1%20hakk%C4%B1nda%20%3Ca%20href=%5C%5C%5C%22https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/%5C%5C%5C%22%3Edaha%20fazla%20bilgi%20edinin%3C/a%3E%22%7D%7D%7D%60;%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Style%20Definitions%0A%20%20%20%20%20*********************************************************/%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Get%20CSS%20style%20defintions%20for%20CTL,%20using%20the%20provided%20AssetConfig%20for%20any%20non-embedded%20assets%0A%20%20%20%20%20*%20(e.g.%20fonts.)%0A%20%20%20%20%20*%20@param%20%7Bimport('../../content-feature.js').AssetConfig%7D%20%5Bassets%5D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getStyles%20(assets)%20%7B%0A%20%20%20%20%20%20%20%20let%20fontStyle%20=%20'';%0A%20%20%20%20%20%20%20%20let%20regularFontFamily%20=%20%22system,%20-apple-system,%20system-ui,%20BlinkMacSystemFont,%20'Segoe%20UI',%20Roboto,%20Helvetica,%20Arial,%20sans-serif,%20'Apple%20Color%20Emoji',%20'Segoe%20UI%20Emoji',%20'Segoe%20UI%20Symbol'%22;%0A%20%20%20%20%20%20%20%20let%20boldFontFamily%20=%20regularFontFamily;%0A%20%20%20%20%20%20%20%20if%20(assets?.regularFontUrl%20&&%20assets?.boldFontUrl)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20fontStyle%20=%20%60%0A%20%20%20%20%20%20%20%20@font-face%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentials;%0A%20%20%20%20%20%20%20%20%20%20%20%20src:%20url($%7Bassets.regularFontUrl%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20@font-face%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20font-family:%20DuckDuckGoPrivacyEssentialsBold;%0A%20%20%20%20%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20%20%20%20%20src:%20url($%7Bassets.boldFontUrl%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20regularFontFamily%20=%20'DuckDuckGoPrivacyEssentials';%0A%20%20%20%20%20%20%20%20%20%20%20%20boldFontFamily%20=%20'DuckDuckGoPrivacyEssentialsBold';%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20fontStyle,%0A%20%20%20%20%20%20%20%20%20%20%20%20darkMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#111111;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20textFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20rgba(255,%20255,%20255,%200.9);%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#111111;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linkFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#7295F6;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#5784FF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundHover:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#557FF3;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundPress:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#3969EF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonText:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#EEEEEE;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonBgState:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20active:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background:%20#5784FF;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20inactive:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background-color:%20#666666;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20lightMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20textFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#222222;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linkFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#3969EF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#3969EF;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundHover:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#2B55CA;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundPress:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#1E42A4;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonText:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#666666;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonBgState:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20active:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background:%20#3969EF;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20inactive:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20background-color:%20#666666;%0A%20%20%20%20%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20loginMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20#666666;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20cancelMode:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackground:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20rgba(34,%2034,%2034,%200.1);%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonFont:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20color:%20#222222;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundHover:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20rgba(0,%200,%200,%200.12);%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonBackgroundPress:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20background:%20rgba(0,%200,%200,%200.18);%0A%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20button:%20%60%0A%20%20%20%20%20%20%20%20border-radius:%208px;%0A%0A%20%20%20%20%20%20%20%20padding:%2011px%2022px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20margin:%200px%20auto;%0A%20%20%20%20%20%20%20%20border-color:%20#3969EF;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%0A%20%20%20%20%20%20%20%20font-family:%20$%7BboldFontFamily%7D;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20box-shadow:%20none;%0A%20%20%20%20%20%20%20%20z-index:%202147483646;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20circle:%20%60%0A%20%20%20%20%20%20%20%20border-radius:%2050%25;%0A%20%20%20%20%20%20%20%20width:%2018px;%0A%20%20%20%20%20%20%20%20height:%2018px;%0A%20%20%20%20%20%20%20%20background:%20#E0E0E0;%0A%20%20%20%20%20%20%20%20border:%201px%20solid%20#E0E0E0;%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20top:%20-8px;%0A%20%20%20%20%20%20%20%20right:%20-8px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20loginIcon:%20%60%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20top:%20-13px;%0A%20%20%20%20%20%20%20%20right:%20-10px;%0A%20%20%20%20%20%20%20%20height:%2028px;%0A%20%20%20%20%20%20%20%20width:%2028px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20rectangle:%20%60%0A%20%20%20%20%20%20%20%20width:%2012px;%0A%20%20%20%20%20%20%20%20height:%203px;%0A%20%20%20%20%20%20%20%20background:%20#666666;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20top:%2042.5%25;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20textBubble:%20%60%0A%20%20%20%20%20%20%20%20background:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20border:%201px%20solid%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%20%20%20%20border-radius:%2016px;%0A%20%20%20%20%20%20%20%20box-shadow:%200px%202px%206px%20rgba(0,%200,%200,%200.12),%200px%208px%2016px%20rgba(0,%200,%200,%200.08);%0A%20%20%20%20%20%20%20%20width:%20360px;%0A%20%20%20%20%20%20%20%20margin-top:%2010px;%0A%20%20%20%20%20%20%20%20z-index:%202147483647;%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20line-height:%20normal;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20textBubbleWidth:%20360,%20//%20Should%20match%20the%20width%20rule%20in%20textBubble%0A%20%20%20%20%20%20%20%20%20%20%20%20textBubbleLeftShift:%20100,%20//%20Should%20match%20the%20CSS%20left:%20rule%20in%20textBubble%0A%20%20%20%20%20%20%20%20%20%20%20%20textArrow:%20%60%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20background:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20border:%20solid%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%20%20%20%20border-width:%200%201px%201px%200;%0A%20%20%20%20%20%20%20%20padding:%205px;%0A%20%20%20%20%20%20%20%20transform:%20rotate(-135deg);%0A%20%20%20%20%20%20%20%20-webkit-transform:%20rotate(-135deg);%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20top:%20-9px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20arrowDefaultLocationPercent:%2050,%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverTextTitle:%20%60%0A%20%20%20%20%20%20%20%20padding:%200px%2012px%2012px;%0A%20%20%20%20%20%20%20%20margin-top:%20-5px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverTextBody:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BregularFontFamily%7D;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20padding:%2017px;%0A%20%20%20%20%20%20%20%20text-align:%20left;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverContainer:%20%60%0A%20%20%20%20%20%20%20%20padding-bottom:%2010px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonTextContainer:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20row;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20headerRow:%20%60%0A%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20block:%20%60%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%20%20%20%20border:%201px%20solid%20rgba(0,0,0,0.1);%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20max-width:%20600px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%0A%20%20%20%20%20%20%20%20font-family:%20$%7BregularFontFamily%7D;%0A%20%20%20%20%20%20%20%20line-height:%201;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubeDialogBlock:%20%60%0A%20%20%20%20%20%20%20%20height:%20calc(100%25%20-%2030px);%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-height:%20initial;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20imgRow:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20margin:%2020px%200px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20content:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20padding:%2016px%200;%0A%20%20%20%20%20%20%20%20flex:%201%201%201px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20feedbackLink:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BregularFontFamily%7D;%0A%20%20%20%20%20%20%20%20font-style:%20normal;%0A%20%20%20%20%20%20%20%20font-weight:%20400;%0A%20%20%20%20%20%20%20%20font-size:%2012px;%0A%20%20%20%20%20%20%20%20line-height:%2012px;%0A%20%20%20%20%20%20%20%20color:%20#ABABAB;%0A%20%20%20%20%20%20%20%20text-decoration:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20feedbackRow:%20%60%0A%20%20%20%20%20%20%20%20height:%2030px;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20titleBox:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20padding:%2012px;%0A%20%20%20%20%20%20%20%20max-height:%2044px;%0A%20%20%20%20%20%20%20%20border-bottom:%201px%20solid;%0A%20%20%20%20%20%20%20%20border-color:%20rgba(196,%20196,%20196,%200.3);%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20margin-bottom:%204px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20title:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BregularFontFamily%7D;%0A%20%20%20%20%20%20%20%20line-height:%201.4;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20margin:%20auto%2010px;%0A%20%20%20%20%20%20%20%20flex-basis:%20100%25;%0A%20%20%20%20%20%20%20%20height:%201.4em;%0A%20%20%20%20%20%20%20%20flex-wrap:%20wrap;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20text-align:%20left;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonRow:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20height:%20100%25%0A%20%20%20%20%20%20%20%20flex-direction:%20row;%0A%20%20%20%20%20%20%20%20margin:%2020px%20auto%200px;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%20%20%20%20align-items:%20flex-start;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modalContentTitle:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BboldFontFamily%7D;%0A%20%20%20%20%20%20%20%20font-size:%2017px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20margin:%2010px%20auto;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200px%2032px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modalContentText:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BregularFontFamily%7D;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20margin:%200px%20auto%2014px;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modalButtonRow:%20%60%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modalButton:%20%60%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modalIcon:%20%60%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20contentTitle:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BboldFontFamily%7D;%0A%20%20%20%20%20%20%20%20font-size:%2017px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20margin:%2020px%20auto%2010px;%0A%20%20%20%20%20%20%20%20padding:%200px%2030px;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20margin-top:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20contentText:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BregularFontFamily%7D;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20line-height:%2021px;%0A%20%20%20%20%20%20%20%20padding:%200px%2040px;%0A%20%20%20%20%20%20%20%20text-align:%20center;%0A%20%20%20%20%20%20%20%20margin:%200%20auto%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20icon:%20%60%0A%20%20%20%20%20%20%20%20height:%2080px;%0A%20%20%20%20%20%20%20%20width:%2080px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20closeIcon:%20%60%0A%20%20%20%20%20%20%20%20height:%2012px;%0A%20%20%20%20%20%20%20%20width:%2012px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20closeButton:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20min-width:%2020px;%0A%20%20%20%20%20%20%20%20height:%2021px;%0A%20%20%20%20%20%20%20%20border:%200;%0A%20%20%20%20%20%20%20%20background:%20transparent;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20logo:%20%60%0A%20%20%20%20%20%20%20%20flex-basis:%200%25;%0A%20%20%20%20%20%20%20%20min-width:%2020px;%0A%20%20%20%20%20%20%20%20height:%2021px;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20logoImg:%20%60%0A%20%20%20%20%20%20%20%20height:%2021px;%0A%20%20%20%20%20%20%20%20width:%2021px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20loadingImg:%20%60%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20margin:%200px%208px%200px%200px;%0A%20%20%20%20%20%20%20%20height:%2014px;%0A%20%20%20%20%20%20%20%20width:%2014px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modal:%20%60%0A%20%20%20%20%20%20%20%20width:%20340px;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%20%20%20%20background-color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20top:%2050%25;%0A%20%20%20%20%20%20%20%20left:%2050%25;%0A%20%20%20%20%20%20%20%20transform:%20translate(-50%25,%20-50%25);%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20box-shadow:%200px%201px%203px%20rgba(0,%200,%200,%200.08),%200px%202px%204px%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modalContent:%20%60%0A%20%20%20%20%20%20%20%20padding:%2024px;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20overlay:%20%60%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20background-color:%20#666666;%0A%20%20%20%20%20%20%20%20opacity:%20.5;%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20position:%20fixed;%0A%20%20%20%20%20%20%20%20top:%200;%0A%20%20%20%20%20%20%20%20right:%200;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20modalContainer:%20%60%0A%20%20%20%20%20%20%20%20height:%20100vh;%0A%20%20%20%20%20%20%20%20width:%20100vw;%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%20%20%20%20z-index:%202147483647;%0A%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20position:%20fixed;%0A%20%20%20%20%20%20%20%20border:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20headerLinkContainer:%20%60%0A%20%20%20%20%20%20%20%20flex-basis:%20100%25;%0A%20%20%20%20%20%20%20%20display:%20grid;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20headerLink:%20%60%0A%20%20%20%20%20%20%20%20line-height:%201.4;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20font-family:%20$%7BboldFontFamily%7D;%0A%20%20%20%20%20%20%20%20text-decoration:%20none;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20min-width:%20100px;%0A%20%20%20%20%20%20%20%20text-align:%20end;%0A%20%20%20%20%20%20%20%20float:%20right;%0A%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20generalLink:%20%60%0A%20%20%20%20%20%20%20%20line-height:%201.4;%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20font-family:%20$%7BboldFontFamily%7D;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20text-decoration:%20none;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20wrapperDiv:%20%60%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20border:%200;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20max-width:%20600px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonWrapper:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButton:%20%60%0A%20%20%20%20%20%20%20%20cursor:%20pointer;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20width:%2030px;%0A%20%20%20%20%20%20%20%20height:%2016px;%0A%20%20%20%20%20%20%20%20margin-top:%20-3px;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%20%20%20%20border:%20none;%0A%20%20%20%20%20%20%20%20background-color:%20transparent;%0A%20%20%20%20%20%20%20%20text-align:%20left;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonBg:%20%60%0A%20%20%20%20%20%20%20%20right:%200;%0A%20%20%20%20%20%20%20%20width:%2030px;%0A%20%20%20%20%20%20%20%20height:%2016px;%0A%20%20%20%20%20%20%20%20overflow:%20visible;%0A%20%20%20%20%20%20%20%20border-radius:%2010px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonText:%20%60%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20margin:%200%200%200%207px;%0A%20%20%20%20%20%20%20%20padding:%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonKnob:%20%60%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20display:%20inline-block;%0A%20%20%20%20%20%20%20%20width:%2014px;%0A%20%20%20%20%20%20%20%20height:%2014px;%0A%20%20%20%20%20%20%20%20border-radius:%2010px;%0A%20%20%20%20%20%20%20%20background-color:%20#ffffff;%0A%20%20%20%20%20%20%20%20margin-top:%201px;%0A%20%20%20%20%20%20%20%20top:%20calc(50%25%20-%2014px/2%20-%201px);%0A%20%20%20%20%20%20%20%20box-shadow:%200px%200px%201px%20rgba(0,%200,%200,%200.05),%200px%201px%201px%20rgba(0,%200,%200,%200.1);%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20toggleButtonKnobState:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20active:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20right:%201px;%0A%20%20%20%20%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20inactive:%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20left:%201px;%0A%20%20%20%20%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20placeholderWrapperDiv:%20%60%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-width:%20380px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%20%20%20%20margin:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubeWrapperDiv:%20%60%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-width:%20380px;%0A%20%20%20%20%20%20%20%20min-height:%20300px;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubeDialogDiv:%20%60%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20border-radius:%2012px;%0A%20%20%20%20%20%20%20%20max-width:%20initial;%0A%20%20%20%20%20%20%20%20min-height:%20initial;%0A%20%20%20%20%20%20%20%20height:%20calc(100%25%20-%2030px);%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubeDialogBottomRow:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%20%20%20%20margin-top:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePlaceholder:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-start;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%20%20%20%20background:%20rgba(45,%2045,%2045,%200.8);%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePreviewWrapperImg:%20%60%0A%20%20%20%20%20%20%20%20position:%20absolute;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20height:%20100%25;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePreviewImg:%20%60%0A%20%20%20%20%20%20%20%20min-width:%20100%25;%0A%20%20%20%20%20%20%20%20min-height:%20100%25;%0A%20%20%20%20%20%20%20%20height:%20auto;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubeTopSection:%20%60%0A%20%20%20%20%20%20%20%20font-family:%20$%7BboldFontFamily%7D;%0A%20%20%20%20%20%20%20%20flex:%201;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20space-between;%0A%20%20%20%20%20%20%20%20position:%20relative;%0A%20%20%20%20%20%20%20%20padding:%2018px%2012px%200;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubeTitle:%20%60%0A%20%20%20%20%20%20%20%20font-size:%2014px;%0A%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20line-height:%2014px;%0A%20%20%20%20%20%20%20%20color:%20#FFFFFF;%0A%20%20%20%20%20%20%20%20margin:%200;%0A%20%20%20%20%20%20%20%20width:%20100%25;%0A%20%20%20%20%20%20%20%20white-space:%20nowrap;%0A%20%20%20%20%20%20%20%20overflow:%20hidden;%0A%20%20%20%20%20%20%20%20text-overflow:%20ellipsis;%0A%20%20%20%20%20%20%20%20box-sizing:%20border-box;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePlayButtonRow:%20%60%0A%20%20%20%20%20%20%20%20flex:%202;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePlayButton:%20%60%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20justify-content:%20center;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20height:%2048px;%0A%20%20%20%20%20%20%20%20width:%2080px;%0A%20%20%20%20%20%20%20%20padding:%200px%2024px;%0A%20%20%20%20%20%20%20%20border-radius:%208px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePreviewToggleRow:%20%60%0A%20%20%20%20%20%20%20%20flex:%201;%0A%20%20%20%20%20%20%20%20display:%20flex;%0A%20%20%20%20%20%20%20%20flex-direction:%20column;%0A%20%20%20%20%20%20%20%20justify-content:%20flex-end;%0A%20%20%20%20%20%20%20%20align-items:%20center;%0A%20%20%20%20%20%20%20%20padding:%200%2012px%2018px;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePreviewToggleText:%20%60%0A%20%20%20%20%20%20%20%20color:%20#EEEEEE;%0A%20%20%20%20%20%20%20%20font-weight:%20400;%0A%20%20%20%20%60,%0A%20%20%20%20%20%20%20%20%20%20%20%20youTubePreviewInfoText:%20%60%0A%20%20%20%20%20%20%20%20color:%20#ABABAB;%0A%20%20%20%20%60%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20locale%20UI%20locale%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getConfig%20(locale)%20%7B%0A%20%20%20%20%20%20%20%20const%20locales%20=%20JSON.parse(localesJSON);%0A%20%20%20%20%20%20%20%20const%20fbStrings%20=%20locales%5Blocale%5D%5B'facebook.json'%5D;%0A%20%20%20%20%20%20%20%20const%20ytStrings%20=%20locales%5Blocale%5D%5B'youtube.json'%5D;%0A%0A%20%20%20%20%20%20%20%20const%20sharedStrings%20=%20locales%5Blocale%5D%5B'shared.json'%5D;%0A%20%20%20%20%20%20%20%20const%20config%20=%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20'Facebook,%20Inc.':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20informationalModal:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20icon:%20blockedFBLogo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageTitle:%20fbStrings.informationalModalMessageTitle,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageBody:%20fbStrings.informationalModalMessageBody,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20confirmButtonText:%20fbStrings.informationalModalConfirmButtonText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rejectButtonText:%20fbStrings.informationalModalRejectButtonText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elementData:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Like%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-like'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Button%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/like.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/like.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/share_button.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/share_button.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Save%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-save'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Share%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-share-button'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Page%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/page.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/page.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Page%20Div':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-page'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/plugins/page.php?href=data-href&tabs=data-tabs&width=data-width&height=data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-tabs':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'timeline'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-height':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Comment%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/comment_embed.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/comment_embed.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Comments':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-comments',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'fb%5C%5C:comments'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockComments,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockComments,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'allowFull',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/comments.php?href=data-href&numposts=data-numposts&sdk=joey&version=v9.0&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-numposts':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%2010%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Embedded%20Comment%20Div':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-comment-embed'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockComment,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/comment_embed.php?href=data-href&sdk=joey&width=data-width&include_parent=data-include-parent',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-include-parent':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'false'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Post%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/post.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/post.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Posts%20Div':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-post'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockPost,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'allowFull',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/post.php?href=data-href&sdk=joey&show_text=true&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fallbackAttribute:%20'data-width'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Video%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/video.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/video.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Video':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-video'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/plugins/video.php?href=data-href&show_text=true&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20height:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-height',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fallbackAttribute:%20'data-width'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Group%20iFrames':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/plugins/group.php'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.facebook.com/v2.0/plugins/group.php'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'originalElement'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Group':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-group'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'dialog',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.buttonTextUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20fbStrings.infoTitleUnblockContent,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20fbStrings.infoTextUnblockContent%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'iFrame',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/plugins/group.php?href=data-href&width=data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleDataAttributes:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20width:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20name:%20'data-width',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit:%20'px'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'FB%20Login%20Button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'.fb-login-button'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'loginButton',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20icon:%20blockedFBLogo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20fbStrings.loginButtonText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20popupBodyText:%20fbStrings.loginBodyText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'allowFull',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20targetURL:%20'https://www.facebook.com/v9.0/plugins/login_button.php?app_id=app_id_replace&auto_logout_link=false&button_type=continue_with&sdk=joey&size=large&use_continue_as=false&width=',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20urlDataAttributesToPreserve:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-href':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20required:%20true%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'data-width':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'500'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20app_id_replace:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%20'null'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20Youtube:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20informationalModal:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20icon:%20blockedYTVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageTitle:%20ytStrings.informationalModalMessageTitle,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20messageBody:%20ytStrings.informationalModalMessageBody,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20confirmButtonText:%20ytStrings.informationalModalConfirmButtonText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rejectButtonText:%20ytStrings.informationalModalRejectButtonText%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elementData:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'YouTube%20embedded%20video':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube-nocookie.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube-nocookie.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube-nocookie.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube.com/embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube-nocookie.com/embed'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'youtube-video',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20buttonText:%20ytStrings.buttonTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoTitle:%20ytStrings.infoTitleUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20infoText:%20ytStrings.infoTextUnblockVideo,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewToggleText:%20ytStrings.infoPreviewToggleText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20placeholder:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewToggleEnabledText:%20ytStrings.infoPreviewToggleEnabledText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewInfoText:%20ytStrings.infoPreviewInfoText,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20videoPlayIcon:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lightMode:%20videoPlayLight,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20darkMode:%20videoPlayDark%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickAction:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'youtube-video'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'YouTube%20embedded%20subscription%20button':%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20selectors:%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//youtube-nocookie.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bsrc*='//www.youtube-nocookie.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//youtube-nocookie.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube.com/subscribe_embed'%5D%22,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22iframe%5Bdata-src*='//www.youtube-nocookie.com/subscribe_embed'%5D%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5D,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20type:%20'blank'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20config,%20sharedStrings%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20%7B'darkMode'%20%7C%20'lightMode'%20%7C%20'loginMode'%20%7C%20'cancelMode'%7D%20displayMode%0A%20%20%20%20%20*%20%20%20Key%20for%20theme%20value%20to%20determine%20the%20styling%20of%20buttons/placeholders.%0A%20%20%20%20%20*%20%20%20Matches%20%60styles%5Bmode%5D%60%20keys:%0A%20%20%20%20%20*%20%20%20%20%20-%20%60'lightMode'%60:%20Primary%20colors%20styling%20for%20light%20theme%0A%20%20%20%20%20*%20%20%20%20%20-%20%60'darkMode'%60:%20Primary%20colors%20styling%20for%20dark%20theme%0A%20%20%20%20%20*%20%20%20%20%20-%20%60'cancelMode'%60:%20Secondary%20colors%20styling%20for%20all%20themes%0A%20%20%20%20%20*/%0A%0A%20%20%20%20let%20devMode%20=%20false;%0A%20%20%20%20let%20isYoutubePreviewsEnabled%20=%20false;%0A%20%20%20%20let%20appID;%0A%0A%20%20%20%20const%20titleID%20=%20'DuckDuckGoPrivacyEssentialsCTLElementTitle';%0A%0A%20%20%20%20//%20Configuration%20for%20how%20the%20placeholder%20elements%20should%20look%20and%20behave.%0A%20%20%20%20//%20@see%20%7BgetConfig%7D%0A%20%20%20%20let%20config%20=%20null;%0A%20%20%20%20let%20sharedStrings%20=%20null;%0A%20%20%20%20let%20styles%20=%20null;%0A%0A%20%20%20%20//%20TODO:%20Remove%20these%20redundant%20data%20structures%20and%20refactor%20the%20related%20code.%0A%20%20%20%20//%20%20%20%20%20%20%20There%20should%20be%20no%20need%20to%20have%20the%20entity%20configuration%20stored%20in%20two%0A%20%20%20%20//%20%20%20%20%20%20%20places.%0A%20%20%20%20const%20entities%20=%20%5B%5D;%0A%20%20%20%20const%20entityData%20=%20%7B%7D;%0A%0A%20%20%20%20//%20Used%20to%20avoid%20displaying%20placeholders%20for%20the%20same%20tracking%20element%20twice.%0A%20%20%20%20const%20knownTrackingElements%20=%20new%20WeakSet();%0A%0A%20%20%20%20//%20Promise%20that%20is%20resolved%20when%20the%20Click%20to%20Load%20feature%20init()%20function%20has%0A%20%20%20%20//%20finished%20its%20work,%20enough%20that%20it's%20now%20safe%20to%20replace%20elements%20with%0A%20%20%20%20//%20placeholders.%0A%20%20%20%20let%20readyToDisplayPlaceholdersResolver;%0A%20%20%20%20const%20readyToDisplayPlaceholders%20=%20new%20Promise(resolve%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20readyToDisplayPlaceholdersResolver%20=%20resolve;%0A%20%20%20%20%7D);%0A%0A%20%20%20%20//%20Promise%20that%20is%20resolved%20when%20the%20page%20has%20finished%20loading%20(and%0A%20%20%20%20//%20readyToDisplayPlaceholders%20has%20resolved).%20Wait%20for%20this%20before%20sending%0A%20%20%20%20//%20essential%20messages%20to%20surrogate%20scripts.%0A%20%20%20%20let%20afterPageLoadResolver;%0A%20%20%20%20const%20afterPageLoad%20=%20new%20Promise(resolve%20=%3E%20%7B%20afterPageLoadResolver%20=%20resolve;%20%7D);%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Widget%20Replacement%20logic%0A%20%20%20%20%20*********************************************************/%0A%20%20%20%20class%20DuckWidget%20%7B%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BObject%7D%20widgetData%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20configuration%20for%20this%20%22widget%22%20as%20determined%20in%20ctl-config.js.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20originalElement%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20original%20tracking%20element%20to%20replace%20with%20a%20placeholder.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20entity%20behind%20the%20tracking%20element%20(e.g.%20%22Facebook,%20Inc.%22).%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20constructor%20(widgetData,%20originalElement,%20entity)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction%20=%20%7B%20...widgetData.clickAction%20%7D;%20//%20shallow%20copy%0A%20%20%20%20%20%20%20%20%20%20%20%20this.replaceSettings%20=%20widgetData.replaceSettings;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.originalElement%20=%20originalElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.placeholderElement%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.dataElements%20=%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.gatherDataElements();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.entity%20=%20entity;%0A%20%20%20%20%20%20%20%20%20%20%20%20this.widgetID%20=%20Math.random();%0A%20%20%20%20%20%20%20%20%20%20%20%20this.autoplay%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Boolean%20if%20widget%20is%20unblocked%20and%20content%20should%20not%20be%20blocked%0A%20%20%20%20%20%20%20%20%20%20%20%20this.isUnblocked%20=%20false;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Dispatch%20an%20event%20on%20the%20target%20element,%20including%20the%20widget's%20ID%20and%0A%20%20%20%20%20%20%20%20%20*%20other%20details.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BEventTarget%7D%20eventTarget%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bstring%7D%20eventName%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20dispatchEvent%20(eventTarget,%20eventName)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20eventTarget.dispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20eventName,%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entity:%20this.entity,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceSettings:%20this.replaceSettings,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widgetID:%20this.widgetID%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Take%20note%20of%20some%20of%20the%20tracking%20element's%20attributes%20(as%20determined%20by%0A%20%20%20%20%20%20%20%20%20*%20clickAction.urlDataAttributesToPreserve)%20and%20store%20those%20in%0A%20%20%20%20%20%20%20%20%20*%20this.dataElement.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20gatherDataElements%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this.clickAction.urlDataAttributesToPreserve)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5BattrName,%20attrSettings%5D%20of%20Object.entries(this.clickAction.urlDataAttributesToPreserve))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20value%20=%20this.originalElement.getAttribute(attrName);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!value)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(attrSettings.required)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Missing%20a%20required%20attribute%20means%20we%20won't%20be%20able%20to%20replace%20it%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20with%20a%20light%20version,%20replace%20with%20full%20version.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.type%20=%20'allowFull';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%20=%20attrSettings.default;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.dataElements%5BattrName%5D%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Return%20the%20URL%20of%20the%20Facebook%20content,%20for%20use%20when%20a%20Facebook%20Click%20to%0A%20%20%20%20%20%20%20%20%20*%20Load%20placeholder%20has%20been%20clicked%20by%20the%20user.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getTargetURL%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Copying%20over%20data%20fields%20should%20be%20done%20lazily,%20since%20some%20required%20data%20may%20not%20be%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20captured%20until%20after%20page%20scripts%20run.%0A%20%20%20%20%20%20%20%20%20%20%20%20this.copySocialDataFields();%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.clickAction.targetURL%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Determines%20which%20display%20mode%20the%20placeholder%20element%20should%20render%20in.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BdisplayMode%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getMode%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Login%20buttons%20are%20always%20the%20login%20style%20types%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.replaceSettings.type%20===%20'loginButton')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20'loginMode'%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(window?.matchMedia('(prefers-color-scheme:%20dark)')?.matches)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20'darkMode'%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20'lightMode'%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Take%20note%20of%20some%20of%20the%20tracking%20element's%20style%20attributes%20(as%0A%20%20%20%20%20%20%20%20%20*%20determined%20by%20clickAction.styleDataAttributes)%20as%20a%20CSS%20string.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7Bstring%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20getStyle%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20styleString%20=%20'border:%20none;';%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.clickAction.styleDataAttributes)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Copy%20elements%20from%20the%20original%20div%20into%20style%20attributes%20as%20directed%20by%20config%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20%5Battr,%20valAttr%5D%20of%20Object.entries(this.clickAction.styleDataAttributes))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20valueFound%20=%20this.dataElements%5BvalAttr.name%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!valueFound)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20valueFound%20=%20this.dataElements%5BvalAttr.fallbackAttribute%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20partialStyleString%20=%20'';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(valueFound)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20partialStyleString%20+=%20%60$%7Battr%7D:%20$%7BvalueFound%7D%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!partialStyleString.includes(valAttr.unit))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20partialStyleString%20+=%20valAttr.unit;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20partialStyleString%20+=%20';';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20styleString%20+=%20partialStyleString;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20styleString%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Store%20some%20attributes%20from%20the%20original%20tracking%20element,%20used%20for%20both%0A%20%20%20%20%20%20%20%20%20*%20placeholder%20element%20styling,%20and%20when%20restoring%20the%20original%20tracking%0A%20%20%20%20%20%20%20%20%20*%20element.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20copySocialDataFields%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!this.clickAction.urlDataAttributesToPreserve)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20App%20ID%20may%20be%20set%20by%20client%20scripts,%20and%20is%20required%20for%20some%20elements.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.dataElements.app_id_replace%20&&%20appID%20!=%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.targetURL%20=%20this.clickAction.targetURL.replace('app_id_replace',%20appID);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20key%20of%20Object.keys(this.dataElements))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20attrValue%20=%20this.dataElements%5Bkey%5D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!attrValue)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20URL%20for%20Facebook%20videos%20are%20specified%20as%20the%20data-href%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20attribute%20on%20a%20div,%20that%20is%20then%20used%20to%20create%20the%20iframe.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Some%20websites%20omit%20the%20protocol%20part%20of%20the%20URL%20when%20doing%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20that,%20which%20then%20prevents%20the%20iframe%20from%20loading%20correctly.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(key%20===%20'data-href'%20&&%20attrValue.startsWith('//'))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20attrValue%20=%20window.location.protocol%20+%20attrValue;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.targetURL%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.clickAction.targetURL.replace(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20key,%20encodeURIComponent(attrValue)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Creates%20an%20iFrame%20for%20this%20facebook%20content.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BHTMLIFrameElement%7D%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20createFBIFrame%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20frame%20=%20document.createElement('iframe');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20frame.setAttribute('src',%20this.getTargetURL());%0A%20%20%20%20%20%20%20%20%20%20%20%20frame.setAttribute('style',%20this.getStyle());%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20frame%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Tweaks%20an%20embedded%20YouTube%20video%20element%20ready%20for%20when%20it's%0A%20%20%20%20%20%20%20%20%20*%20reloaded.%0A%20%20%20%20%20%20%20%20%20*%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20videoElement%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BEventListener?%7D%20onError%0A%20%20%20%20%20%20%20%20%20*%20%20%20Function%20to%20be%20called%20if%20the%20video%20fails%20to%20load.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20adjustYouTubeVideoElement%20(videoElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20onError%20=%20null;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!videoElement.src)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20onError%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20url%20=%20new%20URL(videoElement.src);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20hostname:%20originalHostname%20%7D%20=%20url;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Upgrade%20video%20to%20YouTube's%20%22privacy%20enhanced%22%20mode,%20but%20fall%20back%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20to%20standard%20mode%20if%20the%20video%20fails%20to%20load.%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Note:%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%201.%20Changing%20the%20iframe's%20host%20like%20this%20won't%20cause%20a%20CSP%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20violation%20on%20Chrome,%20see%20https://crbug.com/1271196.%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%202.%20The%20onError%20event%20doesn't%20fire%20for%20blocked%20iframes%20on%20Chrome.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(originalHostname%20!==%20'www.youtube-nocookie.com')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.hostname%20=%20'www.youtube-nocookie.com';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onError%20=%20(event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.hostname%20=%20originalHostname;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20videoElement.src%20=%20url.href;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20event.stopImmediatePropagation();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Configure%20auto-play%20correctly%20depending%20on%20if%20the%20video's%20preview%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20loaded,%20otherwise%20it%20doesn't%20allow%20autoplay.%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20allowString%20=%20videoElement.getAttribute('allow')%20%7C%7C%20'';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20allowed%20=%20new%20Set(allowString.split(';').map(s%20=%3E%20s.trim()));%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.autoplay)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20allowed.add('autoplay');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.searchParams.set('autoplay',%20'1');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20allowed.delete('autoplay');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20url.searchParams.delete('autoplay');%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20allowString%20=%20Array.from(allowed).join(';%20');%0A%20%20%20%20%20%20%20%20%20%20%20%20videoElement.setAttribute('allow',%20allowString);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20videoElement.src%20=%20url.href;%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20onError%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Fades%20the%20given%20element%20in/out.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20element%20to%20fade%20in%20or%20out.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bnumber%7D%20interval%0A%20%20%20%20%20%20%20%20%20*%20%20%20Frequency%20of%20opacity%20updates%20(ms).%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7Bboolean%7D%20fadeIn%0A%20%20%20%20%20%20%20%20%20*%20%20%20True%20if%20the%20element%20should%20fade%20in%20instead%20of%20out.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPromise%3Cvoid%3E%7D%0A%20%20%20%20%20%20%20%20%20*%20%20%20%20Promise%20that%20resolves%20when%20the%20fade%20in/out%20is%20complete.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20fadeElement%20(element,%20interval,%20fadeIn)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20new%20Promise(resolve%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20opacity%20=%20fadeIn%20?%200%20:%201;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20originStyle%20=%20element.style.cssText;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20fadeOut%20=%20setInterval(function%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20opacity%20+=%20fadeIn%20?%200.03%20:%20-0.03;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20element.style.cssText%20=%20originStyle%20+%20%60opacity:%20$%7Bopacity%7D;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(opacity%20%3C=%200%20%7C%7C%20opacity%20%3E=%201)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clearInterval(fadeOut);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20resolve();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20interval);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Fades%20the%20given%20element%20out.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20element%20to%20fade%20out.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPromise%3Cvoid%3E%7D%0A%20%20%20%20%20%20%20%20%20*%20%20%20%20Promise%20that%20resolves%20when%20the%20fade%20out%20is%20complete.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20fadeOutElement%20(element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.fadeElement(element,%2010,%20false)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20Fades%20the%20given%20element%20in.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20element%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20element%20to%20fade%20in.%0A%20%20%20%20%20%20%20%20%20*%20@returns%20%7BPromise%3Cvoid%3E%7D%0A%20%20%20%20%20%20%20%20%20*%20%20%20%20Promise%20that%20resolves%20when%20the%20fade%20in%20is%20complete.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20fadeInElement%20(element)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20this.fadeElement(element,%2010,%20true)%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20The%20function%20that's%20called%20when%20the%20user%20clicks%20to%20load%20some%20content.%0A%20%20%20%20%20%20%20%20%20*%20Unblocks%20the%20content,%20puts%20it%20back%20in%20the%20page,%20and%20removes%20the%0A%20%20%20%20%20%20%20%20%20*%20placeholder.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20originalElement%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20original%20tracking%20element.%0A%20%20%20%20%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20replacementElement%0A%20%20%20%20%20%20%20%20%20*%20%20%20The%20placeholder%20element.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20clickFunction%20(originalElement,%20replacementElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20let%20clicked%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20handleClick%20=%20e%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Ensure%20that%20the%20click%20is%20created%20by%20a%20user%20event%20&%20prevent%20double%20clicks%20from%20adding%20more%20animations%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(e.isTrusted%20&&%20!clicked)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.isUnblocked%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clicked%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20isLogin%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20clickElement%20=%20e.srcElement;%20//%20Object.assign(%7B%7D,%20e)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.replaceSettings.type%20===%20'loginButton')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isLogin%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('ddg-ctp-unblockClickToLoadContent-complete',%20()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20parent%20=%20replacementElement.parentNode;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20The%20placeholder%20was%20removed%20from%20the%20DOM%20while%20we%20loaded%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20the%20original%20content,%20give%20up.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!parent)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20we%20allow%20everything%20when%20this%20element%20is%20clicked,%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20notify%20surrogate%20to%20enable%20SDK%20and%20replace%20original%20element.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.clickAction.type%20===%20'allowFull')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20parent.replaceChild(originalElement,%20replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.dispatchEvent(window,%20'ddg-ctp-load-sdk');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Create%20a%20container%20for%20the%20new%20FB%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20fbContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.style.cssText%20=%20styles.wrapperDiv;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20fadeIn%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fadeIn.style.cssText%20=%20'display:%20none;%20opacity:%200;';%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Loading%20animation%20(FB%20can%20take%20some%20time%20to%20load)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20loadingImg%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadingImg.setAttribute('src',%20loadingImages%5Bthis.getMode()%5D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadingImg.setAttribute('height',%20'14px');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20loadingImg.style.cssText%20=%20styles.loadingImg;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Always%20add%20the%20animation%20to%20the%20button,%20regardless%20of%20click%20source%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(clickElement.nodeName%20===%20'BUTTON')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20clickElement.firstElementChild.insertBefore(loadingImg,%20clickElement.firstElementChild.firstChild);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20try%20to%20find%20the%20button%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20el%20=%20clickElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20button%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20while%20(button%20===%20null%20&&%20el%20!==%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20button%20=%20el.querySelector('button');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20el%20=%20el.parentElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(button)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20button.firstElementChild.insertBefore(loadingImg,%20button.firstElementChild.firstChild);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.appendChild(fadeIn);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20fbElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20onError%20=%20null;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch%20(this.clickAction.type)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20'iFrame':%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement%20=%20this.createFBIFrame();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20'youtube-video':%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20onError%20=%20this.adjustYouTubeVideoElement(originalElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement%20=%20originalElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20default:%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement%20=%20originalElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Modify%20the%20overlay%20to%20include%20a%20Facebook%20iFrame,%20which%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20starts%20invisible.%20Once%20loaded,%20fade%20out%20and%20remove%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20overlay%20then%20fade%20in%20the%20Facebook%20content.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20parent.replaceChild(fbContainer,%20replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.appendChild(replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fadeIn.appendChild(fbElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement.addEventListener('load',%20async%20()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20this.fadeOutElement(replacementElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbContainer.replaceWith(fbElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20this.dispatchEvent(fbElement,%20'ddg-ctp-placeholder-clicked');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20this.fadeInElement(fadeIn);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Focus%20on%20new%20element%20for%20screen%20readers.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement.focus();%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Note:%20This%20event%20only%20fires%20on%20Firefox,%20on%20Chrome%20the%20frame's%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20load%20event%20will%20always%20fire.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(onError)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fbElement.addEventListener('error',%20onError,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20action%20=%20this.entity%20===%20'Youtube'%20?%20'block-ctl-yt'%20:%20'block-ctl-fb';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unblockClickToLoadContent(%7B%20entity:%20this.entity,%20action,%20isLogin%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20If%20this%20is%20a%20login%20button,%20show%20modal%20if%20needed%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(this.replaceSettings.type%20===%20'loginButton'%20&&%20entityData%5Bthis.entity%5D.shouldShowLoginModal)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20e%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20makeModal(this.entity,%20handleClick,%20e);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20handleClick%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Replace%20the%20given%20tracking%20element%20with%20the%20given%20placeholder.%0A%20%20%20%20%20*%20Notes:%0A%20%20%20%20%20*%20%201.%20This%20function%20also%20dispatches%20events%20targetting%20the%20original%20and%0A%20%20%20%20%20*%20%20%20%20%20placeholder%20elements.%20That%20way,%20the%20surrogate%20scripts%20can%20use%20the%20event%0A%20%20%20%20%20*%20%20%20%20%20targets%20to%20keep%20track%20of%20which%20placeholder%20corresponds%20to%20which%20tracking%0A%20%20%20%20%20*%20%20%20%20%20element.%0A%20%20%20%20%20*%20%202.%20To%20achieve%20that,%20the%20original%20and%20placeholder%20elements%20must%20be%20in%20the%20DOM%0A%20%20%20%20%20*%20%20%20%20%20at%20the%20time%20the%20events%20are%20dispatched.%20Otherwise,%20the%20events%20will%20not%0A%20%20%20%20%20*%20%20%20%20%20bubble%20up%20and%20the%20surrogate%20script%20will%20miss%20them.%0A%20%20%20%20%20*%20%203.%20Placeholder%20must%20be%20shown%20immediately%20(to%20avoid%20a%20flicker%20for%20the%20user),%0A%20%20%20%20%20*%20%20%20%20%20but%20the%20events%20must%20only%20be%20sent%20once%20the%20document%20(and%20therefore%0A%20%20%20%20%20*%20%20%20%20%20surrogate%20scripts)%20have%20loaded.%0A%20%20%20%20%20*%20%204.%20Therefore,%20we%20hide%20the%20element%20until%20the%20page%20has%20loaded,%20then%20dispatch%0A%20%20%20%20%20*%20%20%20%20%20the%20events%20after%20page%20load,%20and%20then%20remove%20the%20element%20from%20the%20DOM.%0A%20%20%20%20%20*%20%205.%20The%20%22ddg-ctp-ready%22%20event%20needs%20to%20be%20dispatched%20_after_%20the%20element%0A%20%20%20%20%20*%20%20%20%20%20replacement%20events%20have%20fired.%20That%20is%20why%20a%20setTimeout%20is%20required%0A%20%20%20%20%20*%20%20%20%20%20before%20dispatching%20%22ddg-ctp-ready%22.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20%20Also%20note,%20this%20all%20assumes%20that%20the%20surrogate%20script%20that%20needs%20these%0A%20%20%20%20%20*%20%20events%20will%20not%20be%20loaded%20asynchronously%20after%20the%20page%20has%20finished%0A%20%20%20%20%20*%20%20loading.%0A%20%20%20%20%20*%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20DuckWidget%20associated%20with%20the%20tracking%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20trackingElement%0A%20%20%20%20%20*%20%20%20The%20tracking%20element%20on%20the%20page%20to%20replace.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20placeholderElement%0A%20%20%20%20%20*%20%20%20The%20placeholder%20element%20that%20should%20be%20shown%20instead.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20replaceTrackingElement%20(widget,%20trackingElement,%20placeholderElement)%20%7B%0A%20%20%20%20%20%20%20%20//%20In%20some%20situations%20(e.g.%20YouTube%20Click%20to%20Load%20previews%20are%0A%20%20%20%20%20%20%20%20//%20enabled/disabled),%20a%20second%20placeholder%20will%20be%20shown%20for%20a%20tracking%0A%20%20%20%20%20%20%20%20//%20element.%0A%20%20%20%20%20%20%20%20const%20elementToReplace%20=%20widget.placeholderElement%20%7C%7C%20trackingElement;%0A%0A%20%20%20%20%20%20%20%20//%20Note%20the%20placeholder%20element,%20so%20that%20it%20can%20also%20be%20replaced%20later%20if%0A%20%20%20%20%20%20%20%20//%20necessary.%0A%20%20%20%20%20%20%20%20widget.placeholderElement%20=%20placeholderElement;%0A%0A%20%20%20%20%20%20%20%20//%20First%20hide%20the%20element,%20since%20we%20need%20to%20keep%20it%20in%20the%20DOM%20until%20the%0A%20%20%20%20%20%20%20%20//%20events%20have%20been%20dispatched.%0A%20%20%20%20%20%20%20%20const%20originalDisplay%20=%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.style.getPropertyValue('display'),%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.style.getPropertyPriority('display')%0A%20%20%20%20%20%20%20%20%5D;%0A%20%20%20%20%20%20%20%20elementToReplace.style.setProperty('display',%20'none',%20'important');%0A%0A%20%20%20%20%20%20%20%20//%20When%20iframes%20are%20blocked%20by%20the%20declarativeNetRequest%20API,%20they%20are%0A%20%20%20%20%20%20%20%20//%20collapsed%20(hidden)%20automatically.%20Unfortunately%20however,%20there's%20a%20bug%0A%20%20%20%20%20%20%20%20//%20that%20stops%20them%20from%20being%20uncollapsed%20(shown%20again)%20if%20they%20are%20removed%0A%20%20%20%20%20%20%20%20//%20from%20the%20DOM%20after%20they%20are%20collapsed.%20As%20a%20workaround,%20have%20the%20iframe%0A%20%20%20%20%20%20%20%20//%20load%20a%20benign%20data%20URI,%20so%20that%20it's%20uncollapsed,%20before%20removing%20it%20from%0A%20%20%20%20%20%20%20%20//%20the%20DOM.%20See%20https://crbug.com/1428971%0A%20%20%20%20%20%20%20%20const%20originalSrc%20=%20elementToReplace.src;%0A%20%20%20%20%20%20%20%20elementToReplace.src%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20'data:text/plain;charset=utf-8;base64,'%20+%20btoa('https://crbug.com/1428971');%0A%0A%20%20%20%20%20%20%20%20//%20Add%20the%20placeholder%20element%20to%20the%20page.%0A%20%20%20%20%20%20%20%20elementToReplace.parentElement.insertBefore(%0A%20%20%20%20%20%20%20%20%20%20%20%20placeholderElement,%20elementToReplace%0A%20%20%20%20%20%20%20%20);%0A%0A%20%20%20%20%20%20%20%20//%20While%20the%20placeholder%20is%20shown%20(and%20original%20element%20hidden)%0A%20%20%20%20%20%20%20%20//%20synchronously,%20the%20events%20are%20dispatched%20(and%20original%20element%20removed%0A%20%20%20%20%20%20%20%20//%20from%20the%20DOM)%20asynchronously%20after%20the%20page%20has%20finished%20loading.%0A%20%20%20%20%20%20%20%20//%20eslint-disable-next-line%20promise/prefer-await-to-then%0A%20%20%20%20%20%20%20%20afterPageLoad.then(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20With%20page%20load%20complete,%20and%20both%20elements%20in%20the%20DOM,%20the%20events%20can%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20be%20dispatched.%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.dispatchEvent(trackingElement,%20'ddg-ctp-tracking-element');%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.dispatchEvent(placeholderElement,%20'ddg-ctp-placeholder-element');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Once%20the%20events%20are%20sent,%20the%20tracking%20element%20(or%20previous%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20placeholder)%20can%20finally%20be%20removed%20from%20the%20DOM.%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.remove();%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.style.setProperty('display',%20...originalDisplay);%0A%20%20%20%20%20%20%20%20%20%20%20%20elementToReplace.src%20=%20originalSrc;%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20placeholder%20element%20for%20the%20given%20tracking%20element%20and%20replaces%0A%20%20%20%20%20*%20it%20on%20the%20page.%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20CTL%20'widget'%20associated%20with%20the%20tracking%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20trackingElement%0A%20%20%20%20%20*%20%20%20The%20tracking%20element%20on%20the%20page%20that%20should%20be%20replaced%20with%20a%20placeholder.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createPlaceholderElementAndReplace%20(widget,%20trackingElement)%20%7B%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'blank')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20document.createElement('div'));%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'loginButton')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20icon%20=%20widget.replaceSettings.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Create%20a%20button%20to%20replace%20old%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20button,%20container%20%7D%20=%20makeLoginButton(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.buttonText,%20widget.getMode(),%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.popupBodyText,%20icon,%20trackingElement%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20button.addEventListener('click',%20widget.clickFunction(trackingElement,%20container));%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20container);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Facebook%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'dialog')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20icon%20=%20widget.replaceSettings.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20button%20=%20makeButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20textButton%20=%20makeTextButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20contentBlock,%20shadowRoot%20%7D%20=%20createContentBlock(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget,%20button,%20textButton,%20icon%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20button.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%20%20%20%20%20%20%20%20%20%20%20%20textButton.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20contentBlock);%0A%20%20%20%20%20%20%20%20%20%20%20%20showExtraUnblockIfShortPlaceholder(shadowRoot,%20contentBlock);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20YouTube%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'youtube-video')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20sendMessage('updateYouTubeCTLAddedFlag',%20true);%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceYouTubeCTL(trackingElement,%20widget);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Subscribe%20to%20changes%20to%20youtubePreviewsEnabled%20setting%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20and%20update%20the%20CTL%20state%0A%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'ddg-settings-youtubePreviewsEnabled',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(/**%20@type%20CustomEvent%20*/%20%7B%20detail:%20value%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isYoutubePreviewsEnabled%20=%20value;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20replaceYouTubeCTL(trackingElement,%20widget);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20trackingElement%0A%20%20%20%20%20*%20%20%20The%20original%20tracking%20element%20(YouTube%20video%20iframe)%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20CTL%20'widget'%20associated%20with%20the%20tracking%20element.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20replaceYouTubeCTL%20(trackingElement,%20widget)%20%7B%0A%20%20%20%20%20%20%20%20//%20Skip%20replacing%20tracking%20element%20if%20it%20has%20already%20been%20unblocked%0A%20%20%20%20%20%20%20%20if%20(widget.isUnblocked)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20(isYoutubePreviewsEnabled%20===%20true)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Show%20YouTube%20Preview%20for%20embedded%20video%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20oldPlaceholder%20=%20widget.placeholderElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20youTubePreview,%20shadowRoot%20%7D%20=%20createYouTubePreview(trackingElement,%20widget);%0A%20%20%20%20%20%20%20%20%20%20%20%20resizeElementToMatch(oldPlaceholder%20%7C%7C%20trackingElement,%20youTubePreview);%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20youTubePreview);%0A%20%20%20%20%20%20%20%20%20%20%20%20showExtraUnblockIfShortPlaceholder(shadowRoot,%20youTubePreview);%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Block%20YouTube%20embedded%20video%20and%20display%20blocking%20dialog%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.autoplay%20=%20false;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20oldPlaceholder%20=%20widget.placeholderElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20blockingDialog,%20shadowRoot%20%7D%20=%20createYouTubeBlockingDialog(trackingElement,%20widget);%0A%20%20%20%20%20%20%20%20%20%20%20%20resizeElementToMatch(oldPlaceholder%20%7C%7C%20trackingElement,%20blockingDialog);%0A%20%20%20%20%20%20%20%20%20%20%20%20replaceTrackingElement(widget,%20trackingElement,%20blockingDialog);%0A%20%20%20%20%20%20%20%20%20%20%20%20showExtraUnblockIfShortPlaceholder(shadowRoot,%20blockingDialog);%0A%20%20%20%20%20%20%20%20%20%20%20%20hideInfoTextIfNarrowPlaceholder(shadowRoot,%20blockingDialog,%20460);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Show%20the%20extra%20unblock%20link%20in%20the%20header%20if%20the%20placeholder%20or%0A%20%20%20%20%20*%20its%20parent%20is%20too%20short%20for%20the%20normal%20unblock%20button%20to%20be%20visible.%0A%20%20%20%20%20*%20Note:%20This%20does%20not%20take%20into%20account%20the%20placeholder's%20vertical%0A%20%20%20%20%20*%20%20%20%20%20%20%20position%20in%20the%20parent%20element.%0A%20%20%20%20%20*%20@param%20%7BShadowRoot%7D%20shadowRoot%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20placeholder%20Placeholder%20for%20tracking%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20showExtraUnblockIfShortPlaceholder%20(shadowRoot,%20placeholder)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!placeholder.parentElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20%7B%20height:%20placeholderHeight%20%7D%20=%20placeholder.getBoundingClientRect();%0A%20%20%20%20%20%20%20%20const%20%7B%20height:%20parentHeight%20%7D%20=%20placeholder.parentElement.getBoundingClientRect();%0A%0A%20%20%20%20%20%20%20%20if%20((placeholderHeight%20%3E%200%20&&%20placeholderHeight%20%3C=%20200)%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20(parentHeight%20%3E%200%20&&%20parentHeight%20%3C=%20230))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%20@type%20%7BHTMLElement?%7D%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20titleRowTextButton%20=%20shadowRoot.querySelector(%60#$%7BtitleID%20+%20'TextButton'%7D%60);%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(titleRowTextButton)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20titleRowTextButton.style.display%20=%20'block';%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Avoid%20the%20placeholder%20being%20taller%20than%20the%20containing%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20and%20overflowing.%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%20@type%20%7BHTMLElement?%7D%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20innerDiv%20=%20shadowRoot.querySelector('.DuckDuckGoSocialContainer');%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(innerDiv)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20innerDiv.style.minHeight%20=%20'';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20innerDiv.style.maxHeight%20=%20parentHeight%20+%20'px';%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20innerDiv.style.overflow%20=%20'hidden';%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Hide%20the%20info%20text%20(and%20move%20the%20%22Learn%20More%22%20link)%20if%20the%20placeholder%20is%20too%0A%20%20%20%20%20*%20narrow.%0A%20%20%20%20%20*%20@param%20%7BShadowRoot%7D%20shadowRoot%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20placeholder%20Placeholder%20for%20tracking%20element%0A%20%20%20%20%20*%20@param%20%7Bnumber%7D%20narrowWidth%0A%20%20%20%20%20*%20%20%20%20Maximum%20placeholder%20width%20(in%20pixels)%20for%20the%20placeholder%20to%20be%20considered%0A%20%20%20%20%20*%20%20%20%20narrow.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20hideInfoTextIfNarrowPlaceholder%20(shadowRoot,%20placeholder,%20narrowWidth)%20%7B%0A%20%20%20%20%20%20%20%20const%20%7B%20width:%20placeholderWidth%20%7D%20=%20placeholder.getBoundingClientRect();%0A%20%20%20%20%20%20%20%20if%20(placeholderWidth%20%3E%200%20&&%20placeholderWidth%20%3C=%20narrowWidth)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20buttonContainer%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shadowRoot.querySelector('.DuckDuckGoButton.primary')?.parentElement;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20contentTitle%20=%20shadowRoot.getElementById('contentTitle');%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20infoText%20=%20shadowRoot.getElementById('infoText');%0A%20%20%20%20%20%20%20%20%20%20%20%20/**%20@type%20%7BHTMLElement?%7D%20*/%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20learnMoreLink%20=%20shadowRoot.getElementById('learnMoreLink');%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20These%20elements%20will%20exist,%20but%20this%20check%20keeps%20TypeScript%20happy.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!buttonContainer%20%7C%7C%20!contentTitle%20%7C%7C%20!infoText%20%7C%7C%20!learnMoreLink)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Remove%20the%20information%20text.%0A%20%20%20%20%20%20%20%20%20%20%20%20infoText.remove();%0A%20%20%20%20%20%20%20%20%20%20%20%20learnMoreLink.remove();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Append%20the%20%22Learn%20More%22%20link%20to%20the%20title.%0A%20%20%20%20%20%20%20%20%20%20%20%20contentTitle.innerText%20+=%20'.%20';%0A%20%20%20%20%20%20%20%20%20%20%20%20learnMoreLink.style.removeProperty('font-size');%0A%20%20%20%20%20%20%20%20%20%20%20%20contentTitle.appendChild(learnMoreLink);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Improve%20margin/padding,%20to%20ensure%20as%20much%20is%20displayed%20as%20possible.%0A%20%20%20%20%20%20%20%20%20%20%20%20buttonContainer.style.removeProperty('margin');%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Replace%20the%20blocked%20CTL%20elements%20on%20the%20page%20with%20placeholders.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20%5BtargetElement%5D%0A%20%20%20%20%20*%20%20%20If%20specified,%20only%20this%20element%20will%20be%20replaced%20(assuming%20it%20matches%0A%20%20%20%20%20*%20%20%20one%20of%20the%20expected%20CSS%20selectors).%20If%20omitted,%20all%20matching%20elements%0A%20%20%20%20%20*%20%20%20in%20the%20document%20will%20be%20replaced%20instead.%0A%20%20%20%20%20*/%0A%20%20%20%20async%20function%20replaceClickToLoadElements%20(targetElement)%20%7B%0A%20%20%20%20%20%20%20%20await%20readyToDisplayPlaceholders;%0A%0A%20%20%20%20%20%20%20%20for%20(const%20entity%20of%20Object.keys(config))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20widgetData%20of%20Object.values(config%5Bentity%5D.elementData))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20selector%20=%20widgetData.selectors.join();%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20let%20trackingElements%20=%20%5B%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(targetElement)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(targetElement.matches(selector))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trackingElements.push(targetElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20trackingElements%20=%20Array.from(document.querySelectorAll(selector));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20Promise.all(trackingElements.map(trackingElement%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(knownTrackingElements.has(trackingElement))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20Promise.resolve()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20knownTrackingElements.add(trackingElement);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20widget%20=%20new%20DuckWidget(widgetData,%20trackingElement,%20entity);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20createPlaceholderElementAndReplace(widget,%20trackingElement)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Messaging%20to%20surrogates%20&%20extension%0A%20%20%20%20%20*********************************************************/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20unblockClickToLoadContentRequest%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20entity%0A%20%20%20%20%20*%20%20%20The%20entity%20to%20unblock%20requests%20for%20(e.g.%20%22Facebook,%20Inc.%22).%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20%5BisLogin=false%5D%0A%20%20%20%20%20*%20%20%20True%20if%20we%20should%20%22allow%20social%20login%22,%20defaults%20to%20false.%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20action%0A%20%20%20%20%20*%20%20%20The%20Click%20to%20Load%20blocklist%20rule%20action%20(e.g.%20%22block-ctl-fb%22)%20that%20should%0A%20%20%20%20%20*%20%20%20be%20allowed.%20Important%20since%20in%20the%20future%20there%20might%20be%20multiple%20types%20of%0A%20%20%20%20%20*%20%20%20embedded%20content%20from%20the%20same%20entity%20that%20the%20user%20can%20allow%0A%20%20%20%20%20*%20%20%20independently.%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Send%20a%20message%20to%20the%20background%20to%20unblock%20requests%20for%20the%20given%20entity%20for%0A%20%20%20%20%20*%20the%20page.%0A%20%20%20%20%20*%20@param%20%7BunblockClickToLoadContentRequest%7D%20message%0A%20%20%20%20%20*%20@see%20%7B@link%20ddg-ctp-unblockClickToLoadContent-complete%7D%20for%20the%20response%20handler.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20unblockClickToLoadContent%20(message)%20%7B%0A%20%20%20%20%20%20%20%20sendMessage('unblockClickToLoadContent',%20message);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Unblock%20the%20entity,%20close%20the%20login%20dialog%20and%20continue%20the%20Facebook%20login%0A%20%20%20%20%20*%20flow.%20Called%20after%20the%20user%20clicks%20to%20proceed%20after%20the%20warning%20dialog%20is%0A%20%20%20%20%20*%20shown.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20*/%0A%20%20%20%20function%20runLogin%20(entity)%20%7B%0A%20%20%20%20%20%20%20%20const%20action%20=%20entity%20===%20'Youtube'%20?%20'block-ctl-yt'%20:%20'block-ctl-fb';%0A%20%20%20%20%20%20%20%20unblockClickToLoadContent(%7B%20entity,%20action,%20isLogin:%20true%20%7D);%0A%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent('ddg-ctp-run-login',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entity%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Close%20the%20login%20dialog%20and%20abort.%20Called%20after%20the%20user%20clicks%20to%20cancel%0A%20%20%20%20%20*%20after%20the%20warning%20dialog%20is%20shown.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20*/%0A%20%20%20%20function%20cancelModal%20(entity)%20%7B%0A%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent('ddg-ctp-cancel-modal',%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entity%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20openShareFeedbackPage%20()%20%7B%0A%20%20%20%20%20%20%20%20sendMessage('openShareFeedbackPage',%20'');%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20getYouTubeVideoDetails%20(videoURL)%20%7B%0A%20%20%20%20%20%20%20%20sendMessage('getYouTubeVideoDetails',%20videoURL);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/*********************************************************%0A%20%20%20%20%20*%20%20Widget%20building%20blocks%0A%20%20%20%20%20*********************************************************/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20%22Learn%20more%22%20link%20element.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20%5Bmode='lightMode'%5D%0A%20%20%20%20%20*%20@returns%20%7BHTMLAnchorElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20getLearnMoreLink%20(mode%20=%20'lightMode')%20%7B%0A%20%20%20%20%20%20%20%20const%20linkElement%20=%20document.createElement('a');%0A%20%20%20%20%20%20%20%20linkElement.style.cssText%20=%20styles.generalLink%20+%20styles%5Bmode%5D.linkFont;%0A%20%20%20%20%20%20%20%20linkElement.ariaLabel%20=%20sharedStrings.readAbout;%0A%20%20%20%20%20%20%20%20linkElement.href%20=%20'https://help.duckduckgo.com/duckduckgo-help-pages/privacy/embedded-content-protection/';%0A%20%20%20%20%20%20%20%20linkElement.target%20=%20'_blank';%0A%20%20%20%20%20%20%20%20linkElement.textContent%20=%20sharedStrings.learnMore;%0A%20%20%20%20%20%20%20%20linkElement.id%20=%20'learnMoreLink';%0A%20%20%20%20%20%20%20%20return%20linkElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Resizes%20and%20positions%20the%20target%20element%20to%20match%20the%20source%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20sourceElement%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20targetElement%0A%20%20%20%20%20*/%0A%20%20%20%20function%20resizeElementToMatch%20(sourceElement,%20targetElement)%20%7B%0A%20%20%20%20%20%20%20%20const%20computedStyle%20=%20window.getComputedStyle(sourceElement);%0A%20%20%20%20%20%20%20%20const%20stylesToCopy%20=%20%5B'position',%20'top',%20'bottom',%20'left',%20'right',%0A%20%20%20%20%20%20%20%20%20%20%20%20'transform',%20'margin'%5D;%0A%0A%20%20%20%20%20%20%20%20//%20It's%20apparently%20preferable%20to%20use%20the%20source%20element's%20size%20relative%20to%0A%20%20%20%20%20%20%20%20//%20the%20current%20viewport,%20when%20resizing%20the%20target%20element.%20However,%20the%0A%20%20%20%20%20%20%20%20//%20declarativeNetRequest%20API%20%22collapses%22%20(hides)%20blocked%20elements.%20When%0A%20%20%20%20%20%20%20%20//%20that%20happens,%20getBoundingClientRect%20will%20return%20all%20zeros.%0A%20%20%20%20%20%20%20%20//%20TODO:%20Remove%20this%20entirely,%20and%20always%20use%20the%20computed%20height/width%20of%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20the%20source%20element%20instead?%0A%20%20%20%20%20%20%20%20const%20%7B%20height,%20width%20%7D%20=%20sourceElement.getBoundingClientRect();%0A%20%20%20%20%20%20%20%20if%20(height%20%3E%200%20&&%20width%20%3E%200)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20targetElement.style.height%20=%20height%20+%20'px';%0A%20%20%20%20%20%20%20%20%20%20%20%20targetElement.style.width%20=%20width%20+%20'px';%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20stylesToCopy.push('height',%20'width');%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20for%20(const%20key%20of%20stylesToCopy)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20targetElement.style%5Bkey%5D%20=%20computedStyle%5Bkey%5D;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20%60%3Cstyle/%3E%60%20element%20with%20DDG%20font-face%20styles/CSS%0A%20%20%20%20%20*%20to%20be%20attached%20to%20DDG%20wrapper%20elements%0A%20%20%20%20%20*%20@returns%20HTMLStyleElement%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeFontFaceStyleElement%20()%20%7B%0A%20%20%20%20%20%20%20%20//%20Put%20our%20custom%20font-faces%20inside%20the%20wrapper%20element,%20since%0A%20%20%20%20%20%20%20%20//%20@font-face%20does%20not%20work%20inside%20a%20shadowRoot.%0A%20%20%20%20%20%20%20%20//%20See%20https://github.com/mdn/interactive-examples/issues/887.%0A%20%20%20%20%20%20%20%20const%20fontFaceStyleElement%20=%20document.createElement('style');%0A%20%20%20%20%20%20%20%20fontFaceStyleElement.textContent%20=%20styles.fontStyle;%0A%20%20%20%20%20%20%20%20return%20fontFaceStyleElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20%60%3Cstyle/%3E%60%20element%20with%20base%20styles%20for%20DDG%20social%20container%20and%0A%20%20%20%20%20*%20button%20to%20be%20attached%20to%20DDG%20wrapper%20elements/shadowRoot,%20also%20returns%20a%20wrapper%0A%20%20%20%20%20*%20class%20name%20for%20Social%20Container%20link%20styles%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20%5Bmode='lightMode'%5D%0A%20%20%20%20%20*%20@returns%20%7B%7BwrapperClass:%20string,%20styleElement:%20HTMLStyleElement;%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeBaseStyleElement%20(mode%20=%20'lightMode')%20%7B%0A%20%20%20%20%20%20%20%20//%20Style%20element%20includes%20our%20font%20&%20overwrites%20page%20styles%0A%20%20%20%20%20%20%20%20const%20styleElement%20=%20document.createElement('style');%0A%20%20%20%20%20%20%20%20const%20wrapperClass%20=%20'DuckDuckGoSocialContainer';%0A%20%20%20%20%20%20%20%20styleElement.textContent%20=%20%60%0A%20%20%20%20%20%20%20%20.$%7BwrapperClass%7D%20a%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.linkFont%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.$%7BwrapperClass%7D%20a:hover%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.linkFont%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20font-weight:%20bold;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.button%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton%20%3E%20div%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.buttonTextContainer%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonBackground%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary%20%3E%20div%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonFont%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary:hover%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonBackgroundHover%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.primary:active%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles%5Bmode%5D.buttonBackgroundPress%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonBackground%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary%20%3E%20div%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonFont%7D%0A%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary:hover%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonBackgroundHover%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20.DuckDuckGoButton.secondary:active%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20$%7Bstyles.cancelMode.buttonBackgroundPress%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20return%20%7B%20wrapperClass,%20styleElement%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20an%20anchor%20element%20with%20no%20destination.%20It%20is%20expected%20that%20a%20click%0A%20%20%20%20%20*%20handler%20is%20added%20to%20the%20element%20later.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20linkText%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20mode%0A%20%20%20%20%20*%20@returns%20%7BHTMLAnchorElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeTextButton%20(linkText,%20mode%20=%20'lightMode')%20%7B%0A%20%20%20%20%20%20%20%20const%20linkElement%20=%20document.createElement('a');%0A%20%20%20%20%20%20%20%20linkElement.style.cssText%20=%20styles.headerLink%20+%20styles%5Bmode%5D.linkFont;%0A%20%20%20%20%20%20%20%20linkElement.textContent%20=%20linkText;%0A%20%20%20%20%20%20%20%20return%20linkElement%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20button%20element.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20buttonText%0A%20%20%20%20%20*%20%20%20Text%20to%20be%20displayed%20inside%20the%20button.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20%5Bmode='lightMode'%5D%0A%20%20%20%20%20*%20%20%20The%20button%20is%20usually%20styled%20as%20the%20primary%20call%20to%20action,%20but%20if%0A%20%20%20%20%20*%20%20%20'cancelMode'%20is%20specified%20the%20button%20is%20styled%20as%20a%20secondary%20call%20to%0A%20%20%20%20%20*%20%20%20action.%0A%20%20%20%20%20*%20@returns%20%7BHTMLButtonElement%7D%20Button%20element%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeButton%20(buttonText,%20mode%20=%20'lightMode')%20%7B%0A%20%20%20%20%20%20%20%20const%20button%20=%20document.createElement('button');%0A%20%20%20%20%20%20%20%20button.classList.add('DuckDuckGoButton');%0A%20%20%20%20%20%20%20%20button.classList.add(mode%20===%20'cancelMode'%20?%20'secondary'%20:%20'primary');%0A%20%20%20%20%20%20%20%20if%20(buttonText)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20textContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20textContainer.textContent%20=%20buttonText;%0A%20%20%20%20%20%20%20%20%20%20%20%20button.appendChild(textContainer);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20button%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20toggle%20button.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20mode%0A%20%20%20%20%20*%20@param%20%7Bboolean%7D%20%5BisActive=false%5D%0A%20%20%20%20%20*%20%20%20True%20if%20the%20button%20should%20be%20toggled%20by%20default.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BclassNames=''%5D%0A%20%20%20%20%20*%20%20%20Class%20names%20to%20assign%20to%20the%20button%20(space%20delimited).%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BdataKey=''%5D%0A%20%20%20%20%20*%20%20%20Value%20to%20assign%20to%20the%20button's%20'data-key'%20attribute.%0A%20%20%20%20%20*%20@returns%20%7BHTMLButtonElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeToggleButton%20(mode,%20isActive%20=%20false,%20classNames%20=%20'',%20dataKey%20=%20'')%20%7B%0A%20%20%20%20%20%20%20%20const%20toggleButton%20=%20document.createElement('button');%0A%20%20%20%20%20%20%20%20toggleButton.className%20=%20classNames;%0A%20%20%20%20%20%20%20%20toggleButton.style.cssText%20=%20styles.toggleButton;%0A%20%20%20%20%20%20%20%20toggleButton.type%20=%20'button';%0A%20%20%20%20%20%20%20%20toggleButton.setAttribute('aria-pressed',%20isActive%20?%20'true'%20:%20'false');%0A%20%20%20%20%20%20%20%20toggleButton.setAttribute('data-key',%20dataKey);%0A%0A%20%20%20%20%20%20%20%20const%20activeKey%20=%20isActive%20?%20'active'%20:%20'inactive';%0A%0A%20%20%20%20%20%20%20%20const%20toggleBg%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20toggleBg.style.cssText%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20styles.toggleButtonBg%20+%20styles%5Bmode%5D.toggleButtonBgState%5BactiveKey%5D;%0A%0A%20%20%20%20%20%20%20%20const%20toggleKnob%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20toggleKnob.style.cssText%20=%0A%20%20%20%20%20%20%20%20%20%20%20%20styles.toggleButtonKnob%20+%20styles.toggleButtonKnobState%5BactiveKey%5D;%0A%0A%20%20%20%20%20%20%20%20toggleButton.appendChild(toggleBg);%0A%20%20%20%20%20%20%20%20toggleButton.appendChild(toggleKnob);%0A%0A%20%20%20%20%20%20%20%20return%20toggleButton%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20toggle%20button%20that's%20wrapped%20in%20a%20div%20with%20some%20text.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20text%0A%20%20%20%20%20*%20%20%20Text%20to%20display%20by%20the%20button.%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20mode%0A%20%20%20%20%20*%20@param%20%7Bboolean%7D%20%5BisActive=false%5D%0A%20%20%20%20%20*%20%20%20True%20if%20the%20button%20should%20be%20toggled%20by%20default.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BtoggleClassNames=''%5D%0A%20%20%20%20%20*%20%20%20Class%20names%20to%20assign%20to%20the%20toggle%20button.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BtextCssStyles=''%5D%0A%20%20%20%20%20*%20%20%20Styles%20to%20apply%20to%20the%20wrapping%20div%20(on%20top%20of%20ones%20determined%20by%20the%0A%20%20%20%20%20*%20%20%20display%20mode.)%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20%5BdataKey=''%5D%0A%20%20%20%20%20*%20%20%20Value%20to%20assign%20to%20the%20button's%20'data-key'%20attribute.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeToggleButtonWithText%20(text,%20mode,%20isActive%20=%20false,%20toggleClassNames%20=%20'',%20textCssStyles%20=%20'',%20dataKey%20=%20'')%20%7B%0A%20%20%20%20%20%20%20%20const%20wrapper%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20wrapper.style.cssText%20=%20styles.toggleButtonWrapper;%0A%0A%20%20%20%20%20%20%20%20const%20toggleButton%20=%20makeToggleButton(mode,%20isActive,%20toggleClassNames,%20dataKey);%0A%0A%20%20%20%20%20%20%20%20const%20textDiv%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20textDiv.style.cssText%20=%20styles.contentText%20+%20styles.toggleButtonText%20+%20styles%5Bmode%5D.toggleButtonText%20+%20textCssStyles;%0A%20%20%20%20%20%20%20%20textDiv.textContent%20=%20text;%0A%0A%20%20%20%20%20%20%20%20wrapper.appendChild(toggleButton);%0A%20%20%20%20%20%20%20%20wrapper.appendChild(textDiv);%0A%20%20%20%20%20%20%20%20return%20wrapper%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20the%20default%20block%20symbol,%20for%20when%20the%20image%20isn't%20available.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeDefaultBlockIcon%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20blockedIcon%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20const%20dash%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20blockedIcon.appendChild(dash);%0A%20%20%20%20%20%20%20%20blockedIcon.style.cssText%20=%20styles.circle;%0A%20%20%20%20%20%20%20%20dash.style.cssText%20=%20styles.rectangle;%0A%20%20%20%20%20%20%20%20return%20blockedIcon%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20share%20feedback%20link%20element.%0A%20%20%20%20%20*%20@returns%20%7BHTMLAnchorElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeShareFeedbackLink%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20feedbackLink%20=%20document.createElement('a');%0A%20%20%20%20%20%20%20%20feedbackLink.style.cssText%20=%20styles.feedbackLink;%0A%20%20%20%20%20%20%20%20feedbackLink.target%20=%20'_blank';%0A%20%20%20%20%20%20%20%20feedbackLink.href%20=%20'#';%0A%20%20%20%20%20%20%20%20feedbackLink.text%20=%20'Share%20Feedback';%0A%20%20%20%20%20%20%20%20//%20Open%20Feedback%20Form%20page%20through%20background%20event%20to%20avoid%20browser%20blocking%20extension%20link%0A%20%20%20%20%20%20%20%20feedbackLink.addEventListener('click',%20function%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20e.preventDefault();%0A%20%20%20%20%20%20%20%20%20%20%20%20openShareFeedbackPage();%0A%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20return%20feedbackLink%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20share%20feedback%20link%20element,%20wrapped%20in%20a%20styled%20div.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeShareFeedbackRow%20()%20%7B%0A%20%20%20%20%20%20%20%20const%20feedbackRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20feedbackRow.style.cssText%20=%20styles.feedbackRow;%0A%0A%20%20%20%20%20%20%20%20const%20feedbackLink%20=%20makeShareFeedbackLink();%0A%20%20%20%20%20%20%20%20feedbackRow.appendChild(feedbackLink);%0A%0A%20%20%20%20%20%20%20%20return%20feedbackRow%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20placeholder%20Facebook%20login%20button.%20When%20clicked,%20a%20warning%20dialog%0A%20%20%20%20%20*%20is%20displayed%20to%20the%20user.%20The%20login%20flow%20only%20continues%20if%20the%20user%20clicks%20to%0A%20%20%20%20%20*%20proceed.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20buttonText%0A%20%20%20%20%20*%20@param%20%7BdisplayMode%7D%20mode%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20hoverTextBody%0A%20%20%20%20%20*%20%20%20The%20hover%20text%20to%20display%20for%20the%20button.%0A%20%20%20%20%20*%20@param%20%7Bstring?%7D%20icon%0A%20%20%20%20%20*%20%20%20The%20source%20of%20the%20icon%20to%20display%20in%20the%20button,%20if%20null%20the%20default%20block%0A%20%20%20%20%20*%20%20%20icon%20is%20used%20instead.%0A%20%20%20%20%20*%20@param%20%7BHTMLElement%7D%20originalElement%0A%20%20%20%20%20*%20%20%20The%20original%20Facebook%20login%20button%20that%20this%20placeholder%20is%20replacing.%0A%20%20%20%20%20*%20%20%20Note:%20This%20function%20does%20not%20actually%20replace%20the%20button,%20the%20caller%20is%0A%20%20%20%20%20*%20%20%20%20%20%20%20%20%20expected%20to%20do%20that.%0A%20%20%20%20%20*%20@returns%20%7B%7B%20container:%20HTMLDivElement,%20button:%20HTMLButtonElement%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeLoginButton%20(buttonText,%20mode,%20hoverTextBody,%20icon,%20originalElement)%20%7B%0A%20%20%20%20%20%20%20%20const%20container%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20container.style.cssText%20=%20'position:%20relative;';%0A%20%20%20%20%20%20%20%20container.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20container.attachShadow(%7B%20mode:%20devMode%20?%20'open'%20:%20'closed'%20%7D);%0A%20%20%20%20%20%20%20%20//%20inherit%20any%20class%20styles%20on%20the%20button%0A%20%20%20%20%20%20%20%20container.className%20=%20'fb-login-button%20FacebookLogin__button';%0A%20%20%20%20%20%20%20%20const%20%7B%20styleElement%20%7D%20=%20makeBaseStyleElement(mode);%0A%20%20%20%20%20%20%20%20styleElement.textContent%20+=%20%60%0A%20%20%20%20%20%20%20%20#DuckDuckGoPrivacyEssentialsHoverableText%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20display:%20none;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20#DuckDuckGoPrivacyEssentialsHoverable:hover%20#DuckDuckGoPrivacyEssentialsHoverableText%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20display:%20block;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%60;%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20const%20hoverContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20hoverContainer.id%20=%20'DuckDuckGoPrivacyEssentialsHoverable';%0A%20%20%20%20%20%20%20%20hoverContainer.style.cssText%20=%20styles.hoverContainer;%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(hoverContainer);%0A%0A%20%20%20%20%20%20%20%20//%20Make%20the%20button%0A%20%20%20%20%20%20%20%20const%20button%20=%20makeButton(buttonText,%20mode);%0A%20%20%20%20%20%20%20%20//%20Add%20blocked%20icon%0A%20%20%20%20%20%20%20%20if%20(!icon)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20button.appendChild(makeDefaultBlockIcon());%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20imgElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.style.cssText%20=%20styles.loginIcon;%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('src',%20icon);%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('height',%20'28px');%0A%20%20%20%20%20%20%20%20%20%20%20%20button.appendChild(imgElement);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20hoverContainer.appendChild(button);%0A%0A%20%20%20%20%20%20%20%20//%20hover%20action%0A%20%20%20%20%20%20%20%20const%20hoverBox%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20hoverBox.id%20=%20'DuckDuckGoPrivacyEssentialsHoverableText';%0A%20%20%20%20%20%20%20%20hoverBox.style.cssText%20=%20styles.textBubble;%0A%20%20%20%20%20%20%20%20const%20arrow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20arrow.style.cssText%20=%20styles.textArrow;%0A%20%20%20%20%20%20%20%20hoverBox.appendChild(arrow);%0A%20%20%20%20%20%20%20%20const%20branding%20=%20createTitleRow('DuckDuckGo');%0A%20%20%20%20%20%20%20%20branding.style.cssText%20+=%20styles.hoverTextTitle;%0A%20%20%20%20%20%20%20%20hoverBox.appendChild(branding);%0A%20%20%20%20%20%20%20%20const%20hoverText%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20hoverText.style.cssText%20=%20styles.hoverTextBody;%0A%20%20%20%20%20%20%20%20hoverText.textContent%20=%20hoverTextBody%20+%20'%20';%0A%20%20%20%20%20%20%20%20hoverText.appendChild(getLearnMoreLink(mode));%0A%20%20%20%20%20%20%20%20hoverBox.appendChild(hoverText);%0A%0A%20%20%20%20%20%20%20%20hoverContainer.appendChild(hoverBox);%0A%20%20%20%20%20%20%20%20const%20rect%20=%20originalElement.getBoundingClientRect();%0A%0A%20%20%20%20%20%20%20%20//%20The%20left%20side%20of%20the%20hover%20popup%20may%20go%20offscreen%20if%20the%0A%20%20%20%20%20%20%20%20//%20login%20button%20is%20all%20the%20way%20on%20the%20left%20side%20of%20the%20page.%20This%0A%20%20%20%20%20%20%20%20//%20If%20that%20is%20the%20case,%20dynamically%20shift%20the%20box%20right%20so%20it%20shows%0A%20%20%20%20%20%20%20%20//%20properly.%0A%20%20%20%20%20%20%20%20if%20(rect.left%20%3C%20styles.textBubbleLeftShift)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20leftShift%20=%20-rect.left%20+%2010;%20//%2010px%20away%20from%20edge%20of%20the%20screen%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverBox.style.cssText%20+=%20%60left:%20$%7BleftShift%7Dpx;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20change%20=%20(1%20-%20(rect.left%20/%20styles.textBubbleLeftShift))%20*%20(100%20-%20styles.arrowDefaultLocationPercent);%0A%20%20%20%20%20%20%20%20%20%20%20%20arrow.style.cssText%20+=%20%60left:%20$%7BMath.max(10,%20styles.arrowDefaultLocationPercent%20-%20change)%7D%25;%60;%0A%20%20%20%20%20%20%20%20%7D%20else%20if%20(rect.left%20+%20styles.textBubbleWidth%20-%20styles.textBubbleLeftShift%20%3E%20window.innerWidth)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20rightShift%20=%20rect.left%20+%20styles.textBubbleWidth%20-%20styles.textBubbleLeftShift;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20diff%20=%20Math.min(rightShift%20-%20window.innerWidth,%20styles.textBubbleLeftShift);%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20rightMargin%20=%2020;%20//%20Add%20some%20margin%20to%20the%20page,%20so%20scrollbar%20doesn't%20overlap.%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverBox.style.cssText%20+=%20%60left:%20-$%7Bstyles.textBubbleLeftShift%20+%20diff%20+%20rightMargin%7Dpx;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20change%20=%20((diff%20/%20styles.textBubbleLeftShift))%20*%20(100%20-%20styles.arrowDefaultLocationPercent);%0A%20%20%20%20%20%20%20%20%20%20%20%20arrow.style.cssText%20+=%20%60left:%20$%7BMath.max(10,%20styles.arrowDefaultLocationPercent%20+%20change)%7D%25;%60;%0A%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20hoverBox.style.cssText%20+=%20%60left:%20-$%7Bstyles.textBubbleLeftShift%7Dpx;%60;%0A%20%20%20%20%20%20%20%20%20%20%20%20arrow.style.cssText%20+=%20%60left:%20$%7Bstyles.arrowDefaultLocationPercent%7D%25;%60;%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20button,%0A%20%20%20%20%20%20%20%20%20%20%20%20container%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20a%20privacy%20warning%20dialog%20for%20the%20user,%20so%20that%20the%20user%20can%20choose%20to%0A%20%20%20%20%20*%20proceed/abort.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20entity%0A%20%20%20%20%20*%20%20%20The%20entity%20to%20unblock%20requests%20for%20(e.g.%20%22Facebook,%20Inc.%22)%20if%20the%20user%0A%20%20%20%20%20*%20%20%20clicks%20to%20proceed.%0A%20%20%20%20%20*%20@param%20%7Bfunction%7D%20acceptFunction%0A%20%20%20%20%20*%20%20%20The%20function%20to%20call%20if%20the%20user%20has%20clicked%20to%20proceed.%0A%20%20%20%20%20*%20@param%20%7B...any%7D%20acceptFunctionParams%0A%20%20%20%20%20*%20%20%20The%20parameters%20passed%20to%20acceptFunction%20when%20it%20is%20called.%0A%20%20%20%20%20*%20%20%20TODO:%20Have%20the%20caller%20bind%20these%20arguments%20to%20the%20function%20instead.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20makeModal%20(entity,%20acceptFunction,%20...acceptFunctionParams)%20%7B%0A%20%20%20%20%20%20%20%20const%20icon%20=%20entityData%5Bentity%5D.modalIcon;%0A%0A%20%20%20%20%20%20%20%20const%20modalContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20modalContainer.setAttribute('data-key',%20'modal');%0A%20%20%20%20%20%20%20%20modalContainer.style.cssText%20=%20styles.modalContainer;%0A%0A%20%20%20%20%20%20%20%20modalContainer.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20const%20closeModal%20=%20()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20document.body.removeChild(modalContainer);%0A%20%20%20%20%20%20%20%20%20%20%20%20cancelModal(entity);%0A%20%20%20%20%20%20%20%20%7D;%0A%0A%20%20%20%20%20%20%20%20//%20Protect%20the%20contents%20of%20our%20modal%20inside%20a%20shadowRoot,%20to%20avoid%0A%20%20%20%20%20%20%20%20//%20it%20being%20styled%20by%20the%20website's%20stylesheets.%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20modalContainer.attachShadow(%7B%20mode:%20devMode%20?%20'open'%20:%20'closed'%20%7D);%0A%20%20%20%20%20%20%20%20const%20%7B%20styleElement%20%7D%20=%20makeBaseStyleElement('lightMode');%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20const%20pageOverlay%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20pageOverlay.style.cssText%20=%20styles.overlay;%0A%0A%20%20%20%20%20%20%20%20const%20modal%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20modal.style.cssText%20=%20styles.modal;%0A%0A%20%20%20%20%20%20%20%20//%20Title%0A%20%20%20%20%20%20%20%20const%20modalTitle%20=%20createTitleRow('DuckDuckGo',%20null,%20closeModal);%0A%20%20%20%20%20%20%20%20modal.appendChild(modalTitle);%0A%0A%20%20%20%20%20%20%20%20const%20iconElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20iconElement.style.cssText%20=%20styles.icon%20+%20styles.modalIcon;%0A%20%20%20%20%20%20%20%20iconElement.setAttribute('src',%20icon);%0A%20%20%20%20%20%20%20%20iconElement.setAttribute('height',%20'70px');%0A%0A%20%20%20%20%20%20%20%20const%20title%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20title.style.cssText%20=%20styles.modalContentTitle;%0A%20%20%20%20%20%20%20%20title.textContent%20=%20entityData%5Bentity%5D.modalTitle;%0A%0A%20%20%20%20%20%20%20%20//%20Content%0A%20%20%20%20%20%20%20%20const%20modalContent%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20modalContent.style.cssText%20=%20styles.modalContent;%0A%0A%20%20%20%20%20%20%20%20const%20message%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20message.style.cssText%20=%20styles.modalContentText;%0A%20%20%20%20%20%20%20%20message.textContent%20=%20entityData%5Bentity%5D.modalText%20+%20'%20';%0A%20%20%20%20%20%20%20%20message.appendChild(getLearnMoreLink());%0A%0A%20%20%20%20%20%20%20%20modalContent.appendChild(iconElement);%0A%20%20%20%20%20%20%20%20modalContent.appendChild(title);%0A%20%20%20%20%20%20%20%20modalContent.appendChild(message);%0A%0A%20%20%20%20%20%20%20%20//%20Buttons%0A%20%20%20%20%20%20%20%20const%20buttonRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20buttonRow.style.cssText%20=%20styles.modalButtonRow;%0A%20%20%20%20%20%20%20%20const%20allowButton%20=%20makeButton(entityData%5Bentity%5D.modalAcceptText,%20'lightMode');%0A%20%20%20%20%20%20%20%20allowButton.style.cssText%20+=%20styles.modalButton%20+%20'margin-bottom:%208px;';%0A%20%20%20%20%20%20%20%20allowButton.setAttribute('data-key',%20'allow');%0A%20%20%20%20%20%20%20%20allowButton.addEventListener('click',%20function%20doLogin%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20acceptFunction(...acceptFunctionParams);%0A%20%20%20%20%20%20%20%20%20%20%20%20document.body.removeChild(modalContainer);%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20const%20rejectButton%20=%20makeButton(entityData%5Bentity%5D.modalRejectText,%20'cancelMode');%0A%20%20%20%20%20%20%20%20rejectButton.setAttribute('data-key',%20'reject');%0A%20%20%20%20%20%20%20%20rejectButton.style.cssText%20+=%20styles.modalButton;%0A%20%20%20%20%20%20%20%20rejectButton.addEventListener('click',%20closeModal);%0A%0A%20%20%20%20%20%20%20%20buttonRow.appendChild(allowButton);%0A%20%20%20%20%20%20%20%20buttonRow.appendChild(rejectButton);%0A%20%20%20%20%20%20%20%20modalContent.appendChild(buttonRow);%0A%0A%20%20%20%20%20%20%20%20modal.appendChild(modalContent);%0A%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(pageOverlay);%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(modal);%0A%0A%20%20%20%20%20%20%20%20document.body.insertBefore(modalContainer,%20document.body.childNodes%5B0%5D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20the%20%22title%20row%22%20div%20that%20contains%20a%20placeholder's%20heading.%0A%20%20%20%20%20*%20@param%20%7Bstring%7D%20message%0A%20%20%20%20%20*%20%20%20The%20title%20text%20to%20display.%0A%20%20%20%20%20*%20@param%20%7BHTMLAnchorElement?%7D%20%5BtextButton%5D%0A%20%20%20%20%20*%20%20%20The%20link%20to%20display%20with%20the%20title,%20if%20any.%0A%20%20%20%20%20*%20@param%20%7BEventListener%7D%20%5BcloseBtnFn%5D%0A%20%20%20%20%20*%20%20%20If%20provided,%20a%20close%20button%20is%20added%20that%20calls%20this%20function%20when%20clicked.%0A%20%20%20%20%20*%20@returns%20%7BHTMLDivElement%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createTitleRow%20(message,%20textButton,%20closeBtnFn)%20%7B%0A%20%20%20%20%20%20%20%20//%20Create%20row%20container%0A%20%20%20%20%20%20%20%20const%20row%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20row.style.cssText%20=%20styles.titleBox;%0A%0A%20%20%20%20%20%20%20%20//%20Logo%0A%20%20%20%20%20%20%20%20const%20logoContainer%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20logoContainer.style.cssText%20=%20styles.logo;%0A%20%20%20%20%20%20%20%20const%20logoElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20logoElement.setAttribute('src',%20logoImg);%0A%20%20%20%20%20%20%20%20logoElement.setAttribute('height',%20'21px');%0A%20%20%20%20%20%20%20%20logoElement.style.cssText%20=%20styles.logoImg;%0A%20%20%20%20%20%20%20%20logoContainer.appendChild(logoElement);%0A%20%20%20%20%20%20%20%20row.appendChild(logoContainer);%0A%0A%20%20%20%20%20%20%20%20//%20Content%20box%20title%0A%20%20%20%20%20%20%20%20const%20msgElement%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20msgElement.id%20=%20titleID;%20//%20Ensure%20we%20can%20find%20this%20to%20potentially%20hide%20it%20later.%0A%20%20%20%20%20%20%20%20msgElement.textContent%20=%20message;%0A%20%20%20%20%20%20%20%20msgElement.style.cssText%20=%20styles.title;%0A%20%20%20%20%20%20%20%20row.appendChild(msgElement);%0A%0A%20%20%20%20%20%20%20%20//%20Close%20Button%0A%20%20%20%20%20%20%20%20if%20(typeof%20closeBtnFn%20===%20'function')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20closeButton%20=%20document.createElement('button');%0A%20%20%20%20%20%20%20%20%20%20%20%20closeButton.style.cssText%20=%20styles.closeButton;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20closeIconImg%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20closeIconImg.setAttribute('src',%20closeIcon);%0A%20%20%20%20%20%20%20%20%20%20%20%20closeIconImg.setAttribute('height',%20'12px');%0A%20%20%20%20%20%20%20%20%20%20%20%20closeIconImg.style.cssText%20=%20styles.closeIcon;%0A%20%20%20%20%20%20%20%20%20%20%20%20closeButton.appendChild(closeIconImg);%0A%20%20%20%20%20%20%20%20%20%20%20%20closeButton.addEventListener('click',%20closeBtnFn);%0A%20%20%20%20%20%20%20%20%20%20%20%20row.appendChild(closeButton);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20Text%20button%20for%20very%20small%20boxes%0A%20%20%20%20%20%20%20%20if%20(textButton)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20textButton.id%20=%20titleID%20+%20'TextButton';%0A%20%20%20%20%20%20%20%20%20%20%20%20row.appendChild(textButton);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20row%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20a%20placeholder%20element%20(wrapped%20in%20a%20div%20and%20shadowRoot),%20to%20replace%20a%0A%20%20%20%20%20*%20tracking%20element%20with.%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20Widget%20corresponding%20to%20the%20tracking%20element.%0A%20%20%20%20%20*%20@param%20%7BHTMLButtonElement%7D%20button%0A%20%20%20%20%20*%20%20%20Primary%20button%20that%20loads%20the%20original%20tracking%20element%20(and%20removed%20this%0A%20%20%20%20%20*%20%20%20placeholder)%20when%20clicked.%0A%20%20%20%20%20*%20@param%20%7BHTMLAnchorElement?%7D%20textButton%0A%20%20%20%20%20*%20%20%20Link%20to%20display%20next%20to%20the%20title,%20if%20any.%0A%20%20%20%20%20*%20@param%20%7Bstring?%7D%20img%0A%20%20%20%20%20*%20%20%20Source%20of%20image%20to%20display%20in%20the%20placeholder%20(if%20any).%0A%20%20%20%20%20*%20@param%20%7BHTMLDivElement%7D%20%5BbottomRow%5D%0A%20%20%20%20%20*%20%20%20Bottom%20row%20to%20append%20to%20the%20placeholder,%20if%20any.%0A%20%20%20%20%20*%20@returns%20%7B%7B%20contentBlock:%20HTMLDivElement,%20shadowRoot:%20ShadowRoot%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createContentBlock%20(widget,%20button,%20textButton,%20img,%20bottomRow)%20%7B%0A%20%20%20%20%20%20%20%20const%20contentBlock%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentBlock.style.cssText%20=%20styles.wrapperDiv;%0A%0A%20%20%20%20%20%20%20%20contentBlock.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20//%20Put%20everything%20else%20inside%20the%20shadowRoot%20of%20the%20wrapper%20element%20to%0A%20%20%20%20%20%20%20%20//%20reduce%20the%20chances%20of%20the%20website's%20stylesheets%20messing%20up%20the%0A%20%20%20%20%20%20%20%20//%20placeholder's%20appearance.%0A%20%20%20%20%20%20%20%20const%20shadowRootMode%20=%20devMode%20?%20'open'%20:%20'closed';%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20contentBlock.attachShadow(%7B%20mode:%20shadowRootMode%20%7D);%0A%0A%20%20%20%20%20%20%20%20//%20Style%20element%20includes%20our%20font%20&%20overwrites%20page%20styles%0A%20%20%20%20%20%20%20%20const%20%7B%20wrapperClass,%20styleElement%20%7D%20=%20makeBaseStyleElement(widget.getMode());%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20//%20Create%20overall%20grid%20structure%0A%20%20%20%20%20%20%20%20const%20element%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20element.style.cssText%20=%20styles.block%20+%20styles%5Bwidget.getMode()%5D.background%20+%20styles%5Bwidget.getMode()%5D.textFont;%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'youtube-video')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20element.style.cssText%20+=%20styles.youTubeDialogBlock;%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20element.className%20=%20wrapperClass;%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(element);%0A%0A%20%20%20%20%20%20%20%20//%20grid%20of%20three%20rows%0A%20%20%20%20%20%20%20%20const%20titleRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20titleRow.style.cssText%20=%20styles.headerRow;%0A%20%20%20%20%20%20%20%20element.appendChild(titleRow);%0A%20%20%20%20%20%20%20%20titleRow.appendChild(createTitleRow('DuckDuckGo',%20textButton));%0A%0A%20%20%20%20%20%20%20%20const%20contentRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentRow.style.cssText%20=%20styles.content;%0A%0A%20%20%20%20%20%20%20%20if%20(img)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20imageRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20%20%20%20%20imageRow.style.cssText%20=%20styles.imgRow;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20imgElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.style.cssText%20=%20styles.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('src',%20img);%0A%20%20%20%20%20%20%20%20%20%20%20%20imgElement.setAttribute('height',%20'70px');%0A%20%20%20%20%20%20%20%20%20%20%20%20imageRow.appendChild(imgElement);%0A%20%20%20%20%20%20%20%20%20%20%20%20element.appendChild(imageRow);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20contentTitle%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentTitle.style.cssText%20=%20styles.contentTitle;%0A%20%20%20%20%20%20%20%20contentTitle.textContent%20=%20widget.replaceSettings.infoTitle;%0A%20%20%20%20%20%20%20%20contentTitle.id%20=%20'contentTitle';%0A%20%20%20%20%20%20%20%20contentRow.appendChild(contentTitle);%0A%20%20%20%20%20%20%20%20const%20contentText%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20contentText.style.cssText%20=%20styles.contentText;%0A%20%20%20%20%20%20%20%20const%20contentTextSpan%20=%20document.createElement('span');%0A%20%20%20%20%20%20%20%20contentTextSpan.id%20=%20'infoText';%0A%20%20%20%20%20%20%20%20contentTextSpan.textContent%20=%20widget.replaceSettings.infoText%20+%20'%20';%0A%20%20%20%20%20%20%20%20contentText.appendChild(contentTextSpan);%0A%20%20%20%20%20%20%20%20contentText.appendChild(getLearnMoreLink());%0A%20%20%20%20%20%20%20%20contentRow.appendChild(contentText);%0A%20%20%20%20%20%20%20%20element.appendChild(contentRow);%0A%0A%20%20%20%20%20%20%20%20const%20buttonRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20buttonRow.style.cssText%20=%20styles.buttonRow;%0A%20%20%20%20%20%20%20%20buttonRow.appendChild(button);%0A%20%20%20%20%20%20%20%20contentText.appendChild(buttonRow);%0A%0A%20%20%20%20%20%20%20%20if%20(bottomRow)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20contentRow.appendChild(bottomRow);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20/**%20Share%20Feedback%20Link%20*/%0A%20%20%20%20%20%20%20%20if%20(widget.replaceSettings.type%20===%20'youtube-video')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20feedbackRow%20=%20makeShareFeedbackRow();%0A%20%20%20%20%20%20%20%20%20%20%20%20shadowRoot.appendChild(feedbackRow);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20contentBlock,%20shadowRoot%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Create%20the%20content%20block%20to%20replace%20embedded%20YouTube%20videos/iframes%20with.%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20trackingElement%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20@returns%20%7B%7B%20blockingDialog:%20HTMLElement,%20shadowRoot:%20ShadowRoot%20%7D%7D%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createYouTubeBlockingDialog%20(trackingElement,%20widget)%20%7B%0A%20%20%20%20%20%20%20%20const%20button%20=%20makeButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%20%20%20%20%20%20%20%20const%20textButton%20=%20makeTextButton(widget.replaceSettings.buttonText,%20widget.getMode());%0A%0A%20%20%20%20%20%20%20%20const%20bottomRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20bottomRow.style.cssText%20=%20styles.youTubeDialogBottomRow;%0A%20%20%20%20%20%20%20%20const%20previewToggle%20=%20makeToggleButtonWithText(%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.previewToggleText,%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.getMode(),%0A%20%20%20%20%20%20%20%20%20%20%20%20false,%0A%20%20%20%20%20%20%20%20%20%20%20%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20'yt-preview-toggle'%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20previewToggle.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20()%20=%3E%20makeModal(widget.entity,%20()%20=%3E%20sendMessage('setYoutubePreviewsEnabled',%20true),%20widget.entity)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20bottomRow.appendChild(previewToggle);%0A%0A%20%20%20%20%20%20%20%20const%20%7B%20contentBlock,%20shadowRoot%20%7D%20=%20createContentBlock(%0A%20%20%20%20%20%20%20%20%20%20%20%20widget,%20button,%20textButton,%20null,%20bottomRow%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20contentBlock.id%20=%20trackingElement.id;%0A%20%20%20%20%20%20%20%20contentBlock.style.cssText%20+=%20styles.wrapperDiv%20+%20styles.youTubeWrapperDiv;%0A%0A%20%20%20%20%20%20%20%20button.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%20%20%20%20%20%20%20%20textButton.addEventListener('click',%20widget.clickFunction(trackingElement,%20contentBlock));%0A%0A%20%20%20%20%20%20%20%20return%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20blockingDialog:%20contentBlock,%0A%20%20%20%20%20%20%20%20%20%20%20%20shadowRoot%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20Creates%20the%20placeholder%20element%20to%20replace%20a%20YouTube%20video%20iframe%20element%0A%20%20%20%20%20*%20with%20a%20preview%20image.%20Mutates%20widget%20Object%20to%20set%20the%20autoplay%20property%0A%20%20%20%20%20*%20as%20the%20preview%20details%20load.%0A%20%20%20%20%20*%20@param%20%7BHTMLIFrameElement%7D%20originalElement%0A%20%20%20%20%20*%20%20%20The%20YouTube%20video%20iframe%20element.%0A%20%20%20%20%20*%20@param%20%7BDuckWidget%7D%20widget%0A%20%20%20%20%20*%20%20%20The%20widget%20Object.%20We%20mutate%20this%20to%20set%20the%20autoplay%20property.%0A%20%20%20%20%20*%20@returns%20%7B%7B%20youTubePreview:%20HTMLElement,%20shadowRoot:%20ShadowRoot%20%7D%7D%0A%20%20%20%20%20*%20%20%20Object%20containing%20the%20YouTube%20Preview%20element%20and%20its%20shadowRoot.%0A%20%20%20%20%20*/%0A%20%20%20%20function%20createYouTubePreview%20(originalElement,%20widget)%20%7B%0A%20%20%20%20%20%20%20%20const%20youTubePreview%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20youTubePreview.id%20=%20originalElement.id;%0A%20%20%20%20%20%20%20%20youTubePreview.style.cssText%20=%20styles.wrapperDiv%20+%20styles.placeholderWrapperDiv;%0A%0A%20%20%20%20%20%20%20%20youTubePreview.appendChild(makeFontFaceStyleElement());%0A%0A%20%20%20%20%20%20%20%20//%20Protect%20the%20contents%20of%20our%20placeholder%20inside%20a%20shadowRoot,%20to%20avoid%0A%20%20%20%20%20%20%20%20//%20it%20being%20styled%20by%20the%20website's%20stylesheets.%0A%20%20%20%20%20%20%20%20const%20shadowRoot%20=%20youTubePreview.attachShadow(%7B%20mode:%20devMode%20?%20'open'%20:%20'closed'%20%7D);%0A%20%20%20%20%20%20%20%20const%20%7B%20wrapperClass,%20styleElement%20%7D%20=%20makeBaseStyleElement(widget.getMode());%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(styleElement);%0A%0A%20%20%20%20%20%20%20%20const%20youTubePreviewDiv%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.style.cssText%20=%20styles.youTubeDialogDiv;%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.classList.add(wrapperClass);%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(youTubePreviewDiv);%0A%0A%20%20%20%20%20%20%20%20/**%20Preview%20Image%20*/%0A%20%20%20%20%20%20%20%20const%20previewImageWrapper%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20previewImageWrapper.style.cssText%20=%20styles.youTubePreviewWrapperImg;%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.appendChild(previewImageWrapper);%0A%20%20%20%20%20%20%20%20//%20We%20use%20an%20image%20element%20for%20the%20preview%20image%20so%20that%20we%20can%20ensure%0A%20%20%20%20%20%20%20%20//%20the%20referrer%20isn't%20passed.%0A%20%20%20%20%20%20%20%20const%20previewImageElement%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20previewImageElement.setAttribute('referrerPolicy',%20'no-referrer');%0A%20%20%20%20%20%20%20%20previewImageElement.style.cssText%20=%20styles.youTubePreviewImg;%0A%20%20%20%20%20%20%20%20previewImageWrapper.appendChild(previewImageElement);%0A%0A%20%20%20%20%20%20%20%20const%20innerDiv%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20innerDiv.style.cssText%20=%20styles.youTubePlaceholder;%0A%0A%20%20%20%20%20%20%20%20/**%20Top%20section%20*/%0A%20%20%20%20%20%20%20%20const%20topSection%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20topSection.style.cssText%20=%20styles.youTubeTopSection;%0A%20%20%20%20%20%20%20%20innerDiv.appendChild(topSection);%0A%0A%20%20%20%20%20%20%20%20/**%20Video%20Title%20*/%0A%20%20%20%20%20%20%20%20const%20titleElement%20=%20document.createElement('p');%0A%20%20%20%20%20%20%20%20titleElement.style.cssText%20=%20styles.youTubeTitle;%0A%20%20%20%20%20%20%20%20topSection.appendChild(titleElement);%0A%0A%20%20%20%20%20%20%20%20/**%20Text%20Button%20on%20top%20section%20*/%0A%20%20%20%20%20%20%20%20//%20Use%20darkMode%20styles%20because%20the%20preview%20background%20is%20dark%20and%20causes%20poor%20contrast%0A%20%20%20%20%20%20%20%20//%20with%20lightMode%20button,%20making%20it%20hard%20to%20read.%0A%20%20%20%20%20%20%20%20const%20textButton%20=%20makeTextButton(widget.replaceSettings.buttonText,%20'darkMode');%0A%20%20%20%20%20%20%20%20textButton.id%20=%20titleID%20+%20'TextButton';%0A%0A%20%20%20%20%20%20%20%20textButton.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.clickFunction(originalElement,%20youTubePreview)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20topSection.appendChild(textButton);%0A%0A%20%20%20%20%20%20%20%20/**%20Play%20Button%20*/%0A%20%20%20%20%20%20%20%20const%20playButtonRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20playButtonRow.style.cssText%20=%20styles.youTubePlayButtonRow;%0A%0A%20%20%20%20%20%20%20%20const%20playButton%20=%20makeButton('',%20widget.getMode());%0A%20%20%20%20%20%20%20%20playButton.style.cssText%20+=%20styles.youTubePlayButton;%0A%0A%20%20%20%20%20%20%20%20const%20videoPlayImg%20=%20document.createElement('img');%0A%20%20%20%20%20%20%20%20const%20videoPlayIcon%20=%20widget.replaceSettings.placeholder.videoPlayIcon%5Bwidget.getMode()%5D;%0A%20%20%20%20%20%20%20%20videoPlayImg.setAttribute('src',%20videoPlayIcon);%0A%20%20%20%20%20%20%20%20playButton.appendChild(videoPlayImg);%0A%0A%20%20%20%20%20%20%20%20playButton.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.clickFunction(originalElement,%20youTubePreview)%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20playButtonRow.appendChild(playButton);%0A%20%20%20%20%20%20%20%20innerDiv.appendChild(playButtonRow);%0A%0A%20%20%20%20%20%20%20%20/**%20Preview%20Toggle%20*/%0A%20%20%20%20%20%20%20%20const%20previewToggleRow%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20previewToggleRow.style.cssText%20=%20styles.youTubePreviewToggleRow;%0A%0A%20%20%20%20%20%20%20%20const%20previewToggle%20=%20makeToggleButtonWithText(%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.replaceSettings.placeholder.previewToggleEnabledText,%0A%20%20%20%20%20%20%20%20%20%20%20%20widget.getMode(),%0A%20%20%20%20%20%20%20%20%20%20%20%20true,%0A%20%20%20%20%20%20%20%20%20%20%20%20'',%0A%20%20%20%20%20%20%20%20%20%20%20%20styles.youTubePreviewToggleText,%0A%20%20%20%20%20%20%20%20%20%20%20%20'yt-preview-toggle'%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20previewToggle.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20'click',%0A%20%20%20%20%20%20%20%20%20%20%20%20()%20=%3E%20sendMessage('setYoutubePreviewsEnabled',%20false)%0A%20%20%20%20%20%20%20%20);%0A%0A%20%20%20%20%20%20%20%20/**%20Preview%20Info%20Text%20*/%0A%20%20%20%20%20%20%20%20const%20previewText%20=%20document.createElement('div');%0A%20%20%20%20%20%20%20%20previewText.style.cssText%20=%20styles.contentText%20+%20styles.toggleButtonText%20+%20styles.youTubePreviewInfoText;%0A%20%20%20%20%20%20%20%20//%20Since%20this%20string%20contains%20an%20anchor%20element,%20setting%20innerText%20won't%0A%20%20%20%20%20%20%20%20//%20work.%0A%20%20%20%20%20%20%20%20//%20Warning:%20This%20is%20not%20ideal!%20The%20translated%20(and%20original)%20strings%20must%20be%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20checked%20very%20carefully!%20Any%20HTML%20they%20contain%20will%20be%20inserted.%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20Ideally,%20the%20translation%20system%20would%20allow%20only%20certain%20element%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20types%20to%20be%20included,%20and%20would%20avoid%20the%20URLs%20for%20links%20being%0A%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20%20%20%20included%20in%20the%20translations.%0A%20%20%20%20%20%20%20%20previewText.insertAdjacentHTML(%0A%20%20%20%20%20%20%20%20%20%20%20%20'beforeend',%20widget.replaceSettings.placeholder.previewInfoText%0A%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20const%20previewTextLink%20=%20previewText.querySelector('a');%0A%20%20%20%20%20%20%20%20if%20(previewTextLink)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20newPreviewTextLink%20=%20getLearnMoreLink(widget.getMode());%0A%20%20%20%20%20%20%20%20%20%20%20%20newPreviewTextLink.innerText%20=%20previewTextLink.innerText;%0A%20%20%20%20%20%20%20%20%20%20%20%20previewTextLink.replaceWith(newPreviewTextLink);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20previewToggleRow.appendChild(previewToggle);%0A%20%20%20%20%20%20%20%20previewToggleRow.appendChild(previewText);%0A%20%20%20%20%20%20%20%20innerDiv.appendChild(previewToggleRow);%0A%0A%20%20%20%20%20%20%20%20youTubePreviewDiv.appendChild(innerDiv);%0A%0A%20%20%20%20%20%20%20%20//%20We%20use%20.then()%20instead%20of%20await%20here%20to%20show%20the%20placeholder%20right%20away%0A%20%20%20%20%20%20%20%20//%20while%20the%20YouTube%20endpoint%20takes%20it%20time%20to%20respond.%0A%20%20%20%20%20%20%20%20const%20videoURL%20=%20originalElement.src%20%7C%7C%20originalElement.getAttribute('data-src');%0A%20%20%20%20%20%20%20%20getYouTubeVideoDetails(videoURL);%0A%20%20%20%20%20%20%20%20window.addEventListener('ddg-ctp-youTubeVideoDetails',%0A%20%20%20%20%20%20%20%20%20%20%20%20(/**%20@type%20%7BCustomEvent%7D%20*/%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20detail:%20%7B%20videoURL:%20videoURLResp,%20status,%20title,%20previewImage%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(videoURLResp%20!==%20videoURL)%20%7B%20return%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(status%20===%20'success')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20titleElement.innerText%20=%20title;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20titleElement.title%20=%20title;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(previewImage)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20previewImageElement.setAttribute('src',%20previewImage);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20widget.autoplay%20=%20true;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20);%0A%0A%20%20%20%20%20%20%20%20/**%20Share%20Feedback%20Link%20*/%0A%20%20%20%20%20%20%20%20const%20feedbackRow%20=%20makeShareFeedbackRow();%0A%20%20%20%20%20%20%20%20shadowRoot.appendChild(feedbackRow);%0A%0A%20%20%20%20%20%20%20%20return%20%7B%20youTubePreview,%20shadowRoot%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20//%20Convention%20is%20that%20each%20function%20should%20be%20named%20the%20same%20as%20the%20sendMessage%0A%20%20%20%20//%20method%20we%20are%20calling%20into%20eg.%20calling%20%60sendMessage('getClickToLoadState')%60%0A%20%20%20%20//%20will%20result%20in%20a%20response%20routed%20to%20%60updateHandlers.getClickToLoadState()%60.%0A%20%20%20%20const%20messageResponseHandlers%20=%20%7B%0A%20%20%20%20%20%20%20%20getClickToLoadState%20(response)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20devMode%20=%20response.devMode;%0A%20%20%20%20%20%20%20%20%20%20%20%20isYoutubePreviewsEnabled%20=%20response.youtubePreviewsEnabled;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Mark%20the%20feature%20as%20ready,%20to%20allow%20placeholder%20replacements%20to%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20start.%0A%20%20%20%20%20%20%20%20%20%20%20%20readyToDisplayPlaceholdersResolver();%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20setYoutubePreviewsEnabled%20(response)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(response?.messageType%20&&%20typeof%20response?.value%20===%20'boolean')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20response.messageType,%20%7B%20detail:%20response.value%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20getYouTubeVideoDetails%20(response)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(response?.status%20&&%20typeof%20response.videoURL%20===%20'string')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'ddg-ctp-youTubeVideoDetails',%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20detail:%20response%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D,%0A%20%20%20%20%20%20%20%20unblockClickToLoadContent%20()%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20createCustomEvent('ddg-ctp-unblockClickToLoadContent-complete')%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D;%0A%0A%20%20%20%20const%20knownMessageResponseType%20=%20Object.prototype.hasOwnProperty.bind(messageResponseHandlers);%0A%0A%20%20%20%20class%20ClickToLoad%20extends%20ContentFeature%20%7B%0A%20%20%20%20%20%20%20%20async%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20websiteOwner%20=%20args?.site?.parentEntity;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20settings%20=%20args?.featureSettings?.clickToLoad%20%7C%7C%20%7B%7D;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20locale%20=%20args?.locale%20%7C%7C%20'en';%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20localizedConfig%20=%20getConfig(locale);%0A%20%20%20%20%20%20%20%20%20%20%20%20config%20=%20localizedConfig.config;%0A%20%20%20%20%20%20%20%20%20%20%20%20sharedStrings%20=%20localizedConfig.sharedStrings;%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20update%20styles%20if%20asset%20config%20was%20sent%0A%20%20%20%20%20%20%20%20%20%20%20%20styles%20=%20getStyles(this.assetConfig);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(const%20entity%20of%20Object.keys(config))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Strip%20config%20entities%20that%20are%20first-party,%20or%20aren't%20enabled%20in%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20extension's%20clickToLoad%20settings.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20((websiteOwner%20&&%20entity%20===%20websiteOwner)%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20!settings%5Bentity%5D%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20settings%5Bentity%5D.state%20!==%20'enabled')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20delete%20config%5Bentity%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Populate%20the%20entities%20and%20entityData%20data%20structures.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20Remove%20them%20and%20this%20logic,%20they%20seem%20unnecessary.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entities.push(entity);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20shouldShowLoginModal%20=%20!!config%5Bentity%5D.informationalModal;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20currentEntityData%20=%20%7B%20shouldShowLoginModal%20%7D;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(shouldShowLoginModal)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20informationalModal%20%7D%20=%20config%5Bentity%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalIcon%20=%20informationalModal.icon;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalTitle%20=%20informationalModal.messageTitle;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalText%20=%20informationalModal.messageBody;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalAcceptText%20=%20informationalModal.confirmButtonText;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20currentEntityData.modalRejectText%20=%20informationalModal.rejectButtonText;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20entityData%5Bentity%5D%20=%20currentEntityData;%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Listen%20for%20events%20from%20%22surrogate%22%20scripts.%0A%20%20%20%20%20%20%20%20%20%20%20%20addEventListener('ddg-ctp',%20(/**%20@type%20%7BCustomEvent%7D%20*/%20event)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!('detail'%20in%20event))%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20entity%20=%20event.detail?.entity;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(!entities.includes(entity))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Unknown%20entity,%20reject%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(event.detail?.appID)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20appID%20=%20JSON.stringify(event.detail.appID).replace(/%22/g,%20'');%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Handle%20login%20call%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(event.detail?.action%20===%20'login')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(entityData%5Bentity%5D.shouldShowLoginModal)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20makeModal(entity,%20runLogin,%20entity);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20runLogin(entity);%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Request%20the%20current%20state%20of%20Click%20to%20Load%20from%20the%20platform.%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Note:%20When%20the%20response%20is%20received,%20the%20response%20handler%20resolves%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20the%20readyToDisplayPlaceholders%20Promise.%0A%20%20%20%20%20%20%20%20%20%20%20%20sendMessage('getClickToLoadState');%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20readyToDisplayPlaceholders;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Then%20wait%20for%20the%20page%20to%20finish%20loading,%20and%20resolve%20the%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20afterPageLoad%20Promise.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(document.readyState%20===%20'complete')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20afterPageLoadResolver();%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener('load',%20afterPageLoadResolver,%20%7B%20once:%20true%20%7D);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20afterPageLoad;%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20On%20some%20websites,%20the%20%22ddg-ctp-ready%22%20event%20is%20occasionally%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20dispatched%20too%20early,%20before%20the%20listener%20is%20ready%20to%20receive%20it.%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20To%20counter%20that,%20catch%20%22ddg-ctp-surrogate-load%22%20events%20dispatched%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20_after_%20page,%20so%20the%20%22ddg-ctp-ready%22%20event%20can%20be%20dispatched%20again.%0A%20%20%20%20%20%20%20%20%20%20%20%20window.addEventListener(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20'ddg-ctp-surrogate-load',%20()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready'));%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20);%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Then%20wait%20for%20any%20in-progress%20element%20replacements,%20before%20letting%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20the%20surrogate%20scripts%20know%20to%20start.%0A%20%20%20%20%20%20%20%20%20%20%20%20window.setTimeout(()%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready'));%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D,%200);%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20update%20(message)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20Once%20all%20Click%20to%20Load%20messages%20include%20the%20feature%20property,%20drop%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20messages%20that%20don't%20include%20the%20feature%20property%20too.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(message?.feature%20&&%20message?.feature%20!==%20'clickToLoad')%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20messageType%20=%20message?.messageType;%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!messageType)%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Message%20responses.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(messageType%20===%20'response')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20messageResponseType%20=%20message?.responseMessageType;%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(messageResponseType%20&&%20knownMessageResponseType(messageResponseType))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20messageResponseHandlers%5BmessageResponseType%5D(message.response)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Other%20known%20update%20messages.%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(messageType%20===%20'displayClickToLoadPlaceholders')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO:%20Pass%20%60message.options.ruleAction%60%20through,%20that%20way%20only%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20content%20corresponding%20to%20the%20entity%20for%20that%20ruleAction%20need%20to%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20%20%20%20%20%20%20be%20replaced%20with%20a%20placeholder.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20replaceClickToLoadElements()%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20var%20platformFeatures%20=%20%7B%0A%20%20%20%20%20%20%20%20ddg_feature_runtimeChecks:%20RuntimeChecks,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingAudio:%20FingerprintingAudio,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingBattery:%20FingerprintingBattery,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingCanvas:%20FingerprintingCanvas,%0A%20%20%20%20%20%20%20%20ddg_feature_cookie:%20CookieFeature,%0A%20%20%20%20%20%20%20%20ddg_feature_googleRejected:%20GoogleRejected,%0A%20%20%20%20%20%20%20%20ddg_feature_gpc:%20GlobalPrivacyControl,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingHardware:%20FingerprintingHardware,%0A%20%20%20%20%20%20%20%20ddg_feature_referrer:%20Referrer,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingScreenSize:%20FingerprintingScreenSize,%0A%20%20%20%20%20%20%20%20ddg_feature_fingerprintingTemporaryStorage:%20FingerprintingTemporaryStorage,%0A%20%20%20%20%20%20%20%20ddg_feature_navigatorInterface:%20NavigatorInterface,%0A%20%20%20%20%20%20%20%20ddg_feature_elementHiding:%20ElementHiding,%0A%20%20%20%20%20%20%20%20ddg_feature_exceptionHandler:%20ExceptionHandler,%0A%20%20%20%20%20%20%20%20ddg_feature_clickToLoad:%20ClickToLoad%0A%20%20%20%20%7D;%0A%0A%20%20%20%20/*%20global%20false%20*/%0A%0A%20%20%20%20function%20shouldRun%20()%20%7B%0A%20%20%20%20%20%20%20%20//%20don't%20inject%20into%20non-HTML%20documents%20(such%20as%20XML%20documents)%0A%20%20%20%20%20%20%20%20//%20but%20do%20inject%20into%20XHTML%20documents%0A%20%20%20%20%20%20%20%20if%20(document%20instanceof%20Document%20===%20false%20&&%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20document%20instanceof%20XMLDocument%20===%20false%20%7C%7C%0A%20%20%20%20%20%20%20%20%20%20%20%20document.createElement('div')%20instanceof%20HTMLDivElement%20===%20false%0A%20%20%20%20%20%20%20%20))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20true%0A%20%20%20%20%7D%0A%0A%20%20%20%20let%20initArgs%20=%20null;%0A%20%20%20%20const%20updates%20=%20%5B%5D;%0A%20%20%20%20const%20features%20=%20%5B%5D;%0A%20%20%20%20const%20alwaysInitFeatures%20=%20new%20Set(%5B'cookie'%5D);%0A%20%20%20%20const%20performanceMonitor%20=%20new%20PerformanceMonitor();%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@typedef%20%7Bobject%7D%20LoadArgs%0A%20%20%20%20%20*%20@property%20%7Bobject%7D%20site%0A%20%20%20%20%20*%20@property%20%7Bobject%7D%20platform%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20platform.name%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20%5Bplatform.version%5D%0A%20%20%20%20%20*%20@property%20%7Bboolean%7D%20documentOriginIsTracker%0A%20%20%20%20%20*%20@property%20%7Bobject%7D%20%5BbundledConfig%5D%0A%20%20%20%20%20*%20@property%20%7Bstring%7D%20%5BinjectName%5D%0A%20%20%20%20%20*%20@property%20%7Bobject%7D%20trackerLookup%20-%20provided%20currently%20only%20by%20the%20extension%0A%20%20%20%20%20*/%0A%0A%20%20%20%20/**%0A%20%20%20%20%20*%20@param%20%7BLoadArgs%7D%20args%0A%20%20%20%20%20*/%0A%20%20%20%20function%20load%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20mark%20=%20performanceMonitor.mark('load');%0A%20%20%20%20%20%20%20%20if%20(!shouldRun())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20const%20featureNames%20=%20platformSupport%5B%22chrome%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20;%0A%0A%20%20%20%20%20%20%20%20for%20(const%20featureName%20of%20featureNames)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20ContentFeature%20=%20platformFeatures%5B'ddg_feature_'%20+%20featureName%5D;%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20featureInstance%20=%20new%20ContentFeature(featureName);%0A%20%20%20%20%20%20%20%20%20%20%20%20featureInstance.callLoad(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20features.push(%7B%20featureName,%20featureInstance%20%7D);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%7D%0A%0A%20%20%20%20async%20function%20init%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20mark%20=%20performanceMonitor.mark('init');%0A%20%20%20%20%20%20%20%20initArgs%20=%20args;%0A%20%20%20%20%20%20%20%20if%20(!shouldRun())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20registerMessageSecret(args.messageSecret);%0A%20%20%20%20%20%20%20%20initStringExemptionLists(args);%0A%20%20%20%20%20%20%20%20const%20resolvedFeatures%20=%20await%20Promise.all(features);%0A%20%20%20%20%20%20%20%20resolvedFeatures.forEach((%7B%20featureInstance,%20featureName%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!isFeatureBroken(args,%20featureName)%20%7C%7C%20alwaysInitExtensionFeatures(args,%20featureName))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20featureInstance.callInit(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%20%20%20%20//%20Fire%20off%20updates%20that%20came%20in%20faster%20than%20the%20init%0A%20%20%20%20%20%20%20%20while%20(updates.length)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20update%20=%20updates.pop();%0A%20%20%20%20%20%20%20%20%20%20%20%20await%20updateFeaturesInner(update);%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20mark.end();%0A%20%20%20%20%20%20%20%20if%20(args.debug)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20performanceMonitor.measureAll();%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20update%20(args)%20%7B%0A%20%20%20%20%20%20%20%20if%20(!shouldRun())%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20if%20(initArgs%20===%20null)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20updates.push(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20return%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20updateFeaturesInner(args);%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20alwaysInitExtensionFeatures%20(args,%20featureName)%20%7B%0A%20%20%20%20%20%20%20%20return%20args.platform.name%20===%20'extension'%20&&%20alwaysInitFeatures.has(featureName)%0A%20%20%20%20%7D%0A%0A%20%20%20%20async%20function%20updateFeaturesInner%20(args)%20%7B%0A%20%20%20%20%20%20%20%20const%20resolvedFeatures%20=%20await%20Promise.all(features);%0A%20%20%20%20%20%20%20%20resolvedFeatures.forEach((%7B%20featureInstance,%20featureName%20%7D)%20=%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(!isFeatureBroken(initArgs,%20featureName)%20&&%20featureInstance.update)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20featureInstance.update(args);%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D);%0A%20%20%20%20%7D%0A%0A%20%20%20%20exports.init%20=%20init;%0A%20%20%20%20exports.load%20=%20load;%0A%20%20%20%20exports.update%20=%20update;%0A%0A%20%20%20%20return%20exports;%0A%0A%7D)(%7B%7D);%0A")} contentScopeFeatures.load({ platform: { name: 'extension' }, + trackerLookup: ${JSON.stringify(trackerLookup)}, + site: ${JSON.stringify(siteObject)}, documentOriginIsTracker: ${documentOriginIsTracker}, bundledConfig: ${JSON.stringify(bundledConfig)} }) diff --git a/build/contentScope.js b/build/contentScope.js index d392bdfad..550c68567 100644 --- a/build/contentScope.js +++ b/build/contentScope.js @@ -91,7 +91,7 @@ * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ - function isThirdParty () { + function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -293,7 +293,7 @@ /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ function processAttr (configSetting, defaultValue) { @@ -422,6 +422,107 @@ DDGReflect = globalObj.Reflect; } + function isUnprotectedDomain (topLevelHostname, featureList) { + let unprotectedDomain = false; + const domainParts = topLevelHostname.split('.'); + + // walk up the domain to see if it's unprotected + while (domainParts.length > 1 && !unprotectedDomain) { + const partialDomain = domainParts.join('.'); + + unprotectedDomain = featureList.filter(domain => domain.domain === partialDomain).length > 0; + + domainParts.shift(); + } + + return unprotectedDomain + } + + function parseVersionString (versionString) { + const [major = 0, minor = 0, patch = 0] = versionString.split('.').map(Number); + return { + major, + minor, + patch + } + } + + /** + * @param {string} minVersionString + * @param {string} applicationVersionString + * @returns {boolean} + */ + function satisfiesMinVersion (minVersionString, applicationVersionString) { + const { major: minMajor, minor: minMinor, patch: minPatch } = parseVersionString(minVersionString); + const { major, minor, patch } = parseVersionString(applicationVersionString); + + return (major > minMajor || + (major >= minMajor && minor > minMinor) || + (major >= minMajor && minor >= minMinor && patch >= minPatch)) + } + + /** + * @param {string | number | undefined} minSupportedVersion + * @param {string | number | undefined} currentVersion + * @returns {boolean} + */ + function isSupportedVersion (minSupportedVersion, currentVersion) { + if (typeof currentVersion === 'string' && typeof minSupportedVersion === 'string') { + if (satisfiesMinVersion(minSupportedVersion, currentVersion)) { + return true + } + } else if (typeof currentVersion === 'number' && typeof minSupportedVersion === 'number') { + if (minSupportedVersion <= currentVersion) { + return true + } + } + return false + } + + /** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ + function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features); + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); + const enabledFeatures = remoteFeatureNames.filter((featureName) => { + const feature = data.features[featureName]; + // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { + return false + } + } + return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) + }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config + return enabledFeatures + } + + /** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ + function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {}; + const remoteFeatureNames = Object.keys(data.features); + remoteFeatureNames.forEach((featureName) => { + if (!enabledFeatures.includes(featureName)) { + return + } + + featureSettings[featureName] = data.features[featureName].settings; + }); + return featureSettings + } + const windowsSpecificFeatures = ['windowsPermissionUsage']; function isWindowsSpecificFeature (featureName) { @@ -1009,13 +1110,43 @@ return parseJSONPointer(fromPointer); } + /** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + + /** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName; - this._args = null; + this.#args = null; this.monitor = new PerformanceMonitor(); } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -1028,6 +1159,34 @@ return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -1044,10 +1203,11 @@ /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting(); + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName); if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -1067,17 +1227,22 @@ return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name); - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name); + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName); + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName); return result === 'enabled' } @@ -1086,9 +1251,11 @@ * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain; + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || []; return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -1098,7 +1265,7 @@ callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit'); - this._args = args; + this.#args = args; this.platform = args.platform; this.init(args); mark.end(); @@ -1111,14 +1278,23 @@ callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad'); - this._args = args; + this.#args = args; this.platform = args.platform; + this.#bundledConfig = args.bundledConfig; + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version); + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures); + } + this.#trackerLookup = args.trackerLookup; + this.#documentOriginIsTracker = args.documentOriginIsTracker; this.load(args); mark.end(); } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll(); } } @@ -1190,15 +1366,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property]; + let targetOut = target; + if (typeof property === 'string' && property in outputs) { + targetOut = outputs; + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -1255,7 +1433,6 @@ function wrapScriptCodeOverload (code, config) { const processedConfig = {}; for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value); } // Don't do anything if the config is empty @@ -1337,7 +1514,9 @@ // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -1561,6 +1740,13 @@ return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -1570,6 +1756,13 @@ return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -3977,6 +4170,34 @@ } } + /** + * Check if the current document origin is on the tracker list, using the provided lookup trie. + * @param {object} trackerLookup Trie lookup of tracker domains + * @returns {boolean} True iff the origin is a tracker. + */ + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { + const parts = originHostname.split('.').reverse(); + let node = trackerLookup; + for (const sub of parts) { + if (node[sub] === 1) { + return true + } else if (node[sub]) { + node = node[sub]; + } else { + return false + } + } + return false + } + + /** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ + // Initial cookie policy pre init let cookiePolicy = { debug: false, @@ -3985,12 +4206,18 @@ shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) }; + let trackerLookup = {}; let loadedPolicyResolve; @@ -4010,6 +4237,9 @@ }); } + /** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -4018,26 +4248,45 @@ return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } + /** + * @param {Set} scriptOrigins + * @returns {boolean} + */ + function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false; + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup, scriptOrigin)) { + matched = true; + } + } + return matched + } + + /** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true; } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup = this.trackerLookup; + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie; + const { exceptions, settings } = this.bundledConfig.features.cookie; const tabHostname = getTabHostname(); let tabExempted = true; @@ -4051,6 +4300,10 @@ }); cookiePolicy.shouldBlock = !frameExempted && !tabExempted; cookiePolicy.policy = settings.firstPartyCookiePolicy; + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy; + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || []; } // The cookie policy is injected into every frame immediately so that no cookie will @@ -4111,20 +4364,20 @@ try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy; + const { shouldBlock, policy, trackerPolicy } = cookiePolicy; + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy; if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext); return } - // extract cookie expiry from cookie string const cookie = new Cookie(value); // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge; + cookie.maxAge = chosenPolicy.maxAge; debugHelper('restrict', 'expiry', setCookieContext); @@ -4152,19 +4405,23 @@ } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + }; + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie; - args.cookie.debug = args.debug; - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie'); - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie'); - const policy = this.getFeatureSetting('firstPartyCookiePolicy'); - if (policy) { - cookiePolicy.policy = policy; - } + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie); + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy + }; } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false; + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy); } loadedPolicyResolve(); @@ -4446,31 +4703,41 @@ } } + function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }); + } catch { + // todo: Just ignore this exception? + } + } + class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }); - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args); } } + + init (args) { + injectNavigatorInterface(args); + } } let adLabelStrings = []; @@ -4822,7 +5089,7 @@ } } - const logoImg = 'data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAA0aXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarZxpkhw5kqX/4xR1BOzLcQAFIDI36OP392BB5lY9Uy0yyWQyMsLpbgaovkVVYe781/+57l//+lcIPXeXS+t11Or5J4884uSL7r9/xvtv8Pn99/3T88/Pwl+/737/IPKtxJ/p+982f14/+X750xv9ep/11++7/vOT2H/eKPx+4/dP0ifr6/3ni+T78ft++LkQN873RR29/flS188b2a8r7n/8zr8v6/tD/+/+8o3GKu3CB6UYTwrJv//m7wqSfoc0+TPx35Aar/Np8HVJ0b1vxZ83Y0H+cnu//vT+zwv0l0X+9ZX7++r//upvix/nz/fT39ay/qwRX/zbH4Tyt++n3x8T//zB6fcVxb/+IIS4/3E7P7/v3f3e893dzJUVrT8R9RY7/HobXrhY8vT+WuVX43fh6/Z+DX51P72x5dubX/yyMEJkV64LOewwww3n/WnBuMQcT2RPYozGRul7nT0a0dgldlG/wo2NHdups5cWj2Mrc4q/ryW8zx3v8yx0PnkHXhoDb8bu/s+/3P/th/+bX+5ee0vs+++14rqiIovL0M7pv7yKDQn3Z9/KW+Bfv3623/8pfhSqmZdpmTs3OP363mKV8EdspbfPidcV/vxSKLi2f96AJeKzCxcTEjvga0gl1OBbjC0E1rGzQZMrjynHxQ6EUuLmImNOqUbXYo/6bP5OC++1scQa9W2wiY0oqabG3pBTbFbOhfhpuRNDs6SSSym1tNJdGWXWVHMttdZWBXKzpZZbabW11ttosycgsPTaW+999DniSGBgGXW00ccYc0Y3+aDJe01eP/nOiiutvMqqq62+xppG+Fi2YtWadRs2d9xpAxO77rb7Hnue4A5IcfIpp552+hlnXmLtpptvufW22++48/eu/ezqP379L3Yt/OxafDul17Xfu8Z3XWu/3iIITor2jB2LObDjTTtAQEftme8h56id0575EUmKErnIor1xO2jH2MJ8Qiw3/N67P3buP9o3V/p/tG/x/7VzTlv3/2PnHFv3z337N7u2xXP2duzLQq2pT2QfPz99utinSG3++z9H9vER0ogNiCz11FFYzM3HZH6SY2UHQOvr7LCJx9/pYxrz3JXnZbdYl+pjGens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'; + const logoImg = 'data:image/png;base64,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'; const loadingImages = { darkMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E', lightMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E' // 'data:application/octet-stream;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxzdHlsZT4KCQlAa2V5ZnJhbWVzIHJvdGF0ZSB7CgkJCWZyb20gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CgkJCX0KCQkJdG8gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMzU5ZGVnKTsKCQkJfQoJCX0KCTwvc3R5bGU+Cgk8ZyBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTAlIDUwJTsgYW5pbWF0aW9uOiByb3RhdGUgMXMgaW5maW5pdGUgcmV2ZXJzZSBsaW5lYXI7Ij4KCQk8cmVjdCB4PSIxOC4wOTY4IiB5PSIxNi4wODYxIiB3aWR0aD0iMyIgaGVpZ2h0PSI3IiByeD0iMS41IiB0cmFuc2Zvcm09InJvdGF0ZSgxMzYuMTYxIDE4LjA5NjggMTYuMDg2MSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+CQoJCTxyZWN0IHg9IjguNDk4NzgiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CgkJPHJlY3QgeD0iMTkuOTk3NiIgeT0iOC4zNzQ1MSIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgdHJhbnNmb3JtPSJyb3RhdGUoOTAgMTkuOTk3NiA4LjM3NDUxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjIiLz4KCQk8cmVjdCB4PSIxNi4xNzI3IiB5PSIxLjk5MTciIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgMTYuMTcyNyAxLjk5MTcpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuMyIvPgoJCTxyZWN0IHg9IjguOTEzMDkiIHk9IjYuODg1MDEiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDEzNi4xNjEgOC45MTMwOSA2Ljg4NTAxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KCQk8cmVjdCB4PSI2Ljc5NjAyIiB5PSIxMC45OTYiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgNi43OTYwMiAxMC45OTYpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuNyIvPgoJCTxyZWN0IHg9IjciIHk9IjguNjI1NDkiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDkwIDcgOC42MjU0OSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC44Ii8+CQkKCQk8cmVjdCB4PSI4LjQ5ODc4IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjkiLz4KCTwvZz4KPC9zdmc+Cg==' @@ -4835,117 +5102,128 @@ const videoPlayDark = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23222222%22%2F%3E%0A%3C%2Fsvg%3E%0A'; const videoPlayLight = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23FFFFFF%22%2F%3E%0A%3C%2Fsvg%3E'; - const ddgFont = 'data:application/octet-stream;base64,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'; - const ddgFontBold = 'data:application/octet-stream;base64,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'; - var localesJSON = `{"bg":{"facebook.json":{"informationalModalMessageTitle":"При влизане разрешавате на Facebook да Ви проследява","informationalModalMessageBody":"След като влезете, DuckDuckGo не може да блокира проследяването от Facebook в съдържанието на този сайт.","informationalModalConfirmButtonText":"Вход","informationalModalRejectButtonText":"Назад","loginButtonText":"Вход във Facebook","loginBodyText":"Facebook проследява Вашата активност в съответния сайт, когато го използвате за вход.","buttonTextUnblockContent":"Разблокиране на съдържанието","buttonTextUnblockComment":"Разблокиране на коментара","buttonTextUnblockComments":"Разблокиране на коментарите","buttonTextUnblockPost":"Разблокиране на публикацията","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockContent":"DuckDuckGo блокира това съдържание, за да предотврати проследяване от Facebook","infoTitleUnblockComment":"DuckDuckGo блокира този коментар, за да предотврати проследяване от Facebook","infoTitleUnblockComments":"DuckDuckGo блокира тези коментари, за да предотврати проследяване от Facebook","infoTitleUnblockPost":"DuckDuckGo блокира тази публикация, за да предотврати проследяване от Facebook","infoTitleUnblockVideo":"DuckDuckGo блокира това видео, за да предотврати проследяване от Facebook","infoTextUnblockContent":"Блокирахме проследяването от Facebook при зареждане на страницата. Ако разблокирате това съдържание, Facebook ще следи Вашата активност."},"shared.json":{"learnMore":"Научете повече","readAbout":"Прочетете за тази защита на поверителността"},"youtube.json":{"informationalModalMessageTitle":"Активиране на всички прегледи в YouTube?","informationalModalMessageBody":"Показването на преглед позволява на Google (собственик на YouTube) да види част от информацията за Вашето устройство, но все пак осигурява повече поверителност отколкото при възпроизвеждане на видеоклипа.","informationalModalConfirmButtonText":"Активиране на всички прегледи","informationalModalRejectButtonText":"Не, благодаря","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockVideo":"DuckDuckGo блокира този видеоклип в YouTube, за да предотврати проследяване от Google","infoTextUnblockVideo":"Блокирахме проследяването от Google (собственик на YouTube) при зареждане на страницата. Ако разблокирате този видеоклип, Google ще следи Вашата активност.","infoPreviewToggleText":"Прегледите са деактивирани за осигуряване на допълнителна поверителност","infoPreviewToggleEnabledText":"Прегледите са активирани","infoPreviewInfoText":"Научете повече за вградената защита от социални медии на DuckDuckGo"}},"cs":{"facebook.json":{"informationalModalMessageTitle":"Když se přihlásíš přes Facebook, bude tě moct sledovat","informationalModalMessageBody":"Po přihlášení už DuckDuckGo nemůže bránit Facebooku, aby tě na téhle stránce sledoval.","informationalModalConfirmButtonText":"Přihlásit se","informationalModalRejectButtonText":"Zpět","loginButtonText":"Přihlásit se pomocí Facebooku","loginBodyText":"Facebook sleduje tvou aktivitu na webu, když se přihlásíš jeho prostřednictvím.","buttonTextUnblockContent":"Odblokovat obsah","buttonTextUnblockComment":"Odblokovat komentář","buttonTextUnblockComments":"Odblokovat komentáře","buttonTextUnblockPost":"Odblokovat příspěvek","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockContent":"DuckDuckGo zablokoval tenhle obsah, aby Facebooku zabránil tě sledovat","infoTitleUnblockComment":"Služba DuckDuckGo zablokovala tento komentář, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockComments":"Služba DuckDuckGo zablokovala tyto komentáře, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockPost":"DuckDuckGo zablokoval tenhle příspěvek, aby Facebooku zabránil tě sledovat","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video, aby Facebooku zabránil tě sledovat","infoTextUnblockContent":"Při načítání stránky jsme Facebooku zabránili, aby tě sledoval. Když tenhle obsah odblokuješ, Facebook bude mít přístup ke tvé aktivitě."},"shared.json":{"learnMore":"Více informací","readAbout":"Přečti si o téhle ochraně soukromí"},"youtube.json":{"informationalModalMessageTitle":"Zapnout všechny náhledy YouTube?","informationalModalMessageBody":"Zobrazování náhledů umožní společnosti Google (která vlastní YouTube) zobrazit některé informace o tvém zařízení, ale pořád jde o diskrétnější volbu, než je přehrávání videa.","informationalModalConfirmButtonText":"Zapnout všechny náhledy","informationalModalRejectButtonText":"Ne, děkuji","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video z YouTube, aby Googlu zabránil tě sledovat","infoTextUnblockVideo":"Zabránili jsme společnosti Google (která vlastní YouTube), aby tě při načítání stránky sledovala. Pokud toto video odblokuješ, Google získá přístup ke tvé aktivitě.","infoPreviewToggleText":"Náhledy jsou pro větší soukromí vypnuté","infoPreviewToggleEnabledText":"Náhledy jsou zapnuté","infoPreviewInfoText":"Další informace o ochraně DuckDuckGo před sledováním prostřednictvím vloženého obsahu ze sociálních médií"}},"da":{"facebook.json":{"informationalModalMessageTitle":"Når du logger ind med Facebook, kan de spore dig","informationalModalMessageBody":"Når du er logget ind, kan DuckDuckGo ikke blokere for, at indhold fra Facebook sporer dig på dette websted.","informationalModalConfirmButtonText":"Log på","informationalModalRejectButtonText":"Gå tilbage","loginButtonText":"Log ind med Facebook","loginBodyText":"Facebook sporer din aktivitet på et websted, når du bruger dem til at logge ind.","buttonTextUnblockContent":"Fjern blokering af indhold","buttonTextUnblockComment":"Fjern blokering af kommentar","buttonTextUnblockComments":"Fjern blokering af kommentarer","buttonTextUnblockPost":"Fjern blokering af indlæg","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockContent":"DuckDuckGo har blokeret dette indhold for at forhindre Facebook i at spore dig","infoTitleUnblockComment":"DuckDuckGo har blokeret denne kommentar for at forhindre Facebook i at spore dig","infoTitleUnblockComments":"DuckDuckGo har blokeret disse kommentarer for at forhindre Facebook i at spore dig","infoTitleUnblockPost":"DuckDuckGo blokerede dette indlæg for at forhindre Facebook i at spore dig","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne video for at forhindre Facebook i at spore dig","infoTextUnblockContent":"Vi blokerede for, at Facebook sporede dig, da siden blev indlæst. Hvis du ophæver blokeringen af dette indhold, vil Facebook kende din aktivitet."},"shared.json":{"learnMore":"Mere info","readAbout":"Læs om denne beskyttelse af privatlivet"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Med forhåndsvisninger kan Google (som ejer YouTube) se nogle af enhedens oplysninger, men det er stadig mere privat end at afspille videoen.","informationalModalConfirmButtonText":"Aktivér alle forhåndsvisninger","informationalModalRejectButtonText":"Nej tak.","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne YouTube-video for at forhindre Google i at spore dig","infoTextUnblockVideo":"Vi blokerede Google (som ejer YouTube) fra at spore dig, da siden blev indlæst. Hvis du fjerner blokeringen af denne video, vil Google få kendskab til din aktivitet.","infoPreviewToggleText":"Forhåndsvisninger er deaktiveret for at give yderligere privatliv","infoPreviewToggleEnabledText":"Forhåndsvisninger er deaktiveret","infoPreviewInfoText":"Få mere at vide på om DuckDuckGos indbyggede beskyttelse på sociale medier"}},"de":{"facebook.json":{"informationalModalMessageTitle":"Wenn du dich bei Facebook anmeldest, kann Facebook dich tracken","informationalModalMessageBody":"Sobald du angemeldet bist, kann DuckDuckGo nicht mehr verhindern, dass Facebook-Inhalte dich auf dieser Website tracken.","informationalModalConfirmButtonText":"Anmelden","informationalModalRejectButtonText":"Zurück","loginButtonText":"Mit Facebook anmelden","loginBodyText":"Facebook trackt deine Aktivität auf einer Website, wenn du dich über Facebook dort anmeldest.","buttonTextUnblockContent":"Blockierung aufheben","buttonTextUnblockComment":"Blockierung aufheben","buttonTextUnblockComments":"Blockierung aufheben","buttonTextUnblockPost":"Blockierung aufheben","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockContent":"DuckDuckGo hat diesen Inhalt blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComment":"DuckDuckGo hat diesen Kommentar blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComments":"DuckDuckGo hat diese Kommentare blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockPost":"DuckDuckGo hat diesen Beitrag blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockVideo":"DuckDuckGo hat dieses Video blockiert, um zu verhindern, dass Facebook dich trackt","infoTextUnblockContent":"Wir haben Facebook daran gehindert, dich zu tracken, als die Seite geladen wurde. Wenn du die Blockierung für diesen Inhalt aufhebst, kennt Facebook deine Aktivitäten."},"shared.json":{"learnMore":"Mehr erfahren","readAbout":"Weitere Informationen über diesen Datenschutz"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-Vorschauen aktivieren?","informationalModalMessageBody":"Durch das Anzeigen von Vorschauen kann Google (dem YouTube gehört) einige Informationen zu deinem Gerät sehen. Dies ist aber immer noch privater als das Abspielen des Videos.","informationalModalConfirmButtonText":"Alle Vorschauen aktivieren","informationalModalRejectButtonText":"Nein, danke","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockVideo":"DuckDuckGo hat dieses YouTube-Video blockiert, um zu verhindern, dass Google dich trackt.","infoTextUnblockVideo":"Wir haben Google (dem YouTube gehört) daran gehindert, dich beim Laden der Seite zu tracken. Wenn du die Blockierung für dieses Video aufhebst, kennt Google deine Aktivitäten.","infoPreviewToggleText":"Vorschau für mehr Privatsphäre deaktiviert","infoPreviewToggleEnabledText":"Vorschau aktiviert","infoPreviewInfoText":"Erfahre mehr über den DuckDuckGo-Schutz vor eingebetteten Social Media-Inhalten"}},"el":{"facebook.json":{"informationalModalMessageTitle":"Η σύνδεση μέσω Facebook τους επιτρέπει να σας παρακολουθούν","informationalModalMessageBody":"Μόλις συνδεθείτε, το DuckDuckGo δεν μπορεί να εμποδίσει το περιεχόμενο του Facebook από το να σας παρακολουθεί σε αυτόν τον ιστότοπο.","informationalModalConfirmButtonText":"Σύνδεση","informationalModalRejectButtonText":"Επιστροφή","loginButtonText":"Σύνδεση μέσω Facebook","loginBodyText":"Το Facebook παρακολουθεί τη δραστηριότητά σας σε έναν ιστότοπο όταν τον χρησιμοποιείτε για να συνδεθείτε.","buttonTextUnblockContent":"Άρση αποκλεισμού περιεχομένου","buttonTextUnblockComment":"Άρση αποκλεισμού σχολίου","buttonTextUnblockComments":"Άρση αποκλεισμού σχολίων","buttonTextUnblockPost":"Άρση αποκλεισμού ανάρτησης","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockContent":"Το DuckDuckGo απέκλεισε το περιεχόμενο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComment":"Το DuckDuckGo απέκλεισε το σχόλιο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComments":"Το DuckDuckGo απέκλεισε τα σχόλια αυτά για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockPost":"Το DuckDuckGo απέκλεισε την ανάρτηση αυτή για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTextUnblockContent":"Αποκλείσαμε το Facebook από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το περιεχόμενο, το Facebook θα γνωρίζει τη δραστηριότητά σας."},"shared.json":{"learnMore":"Μάθετε περισσότερα","readAbout":"Διαβάστε σχετικά με την παρούσα προστασίας προσωπικών δεδομένων"},"youtube.json":{"informationalModalMessageTitle":"Ενεργοποίηση όλων των προεπισκοπήσεων του YouTube;","informationalModalMessageBody":"Η προβολή των προεπισκοπήσεων θα επιτρέψει στην Google (στην οποία ανήκει το YouTube) να βλέπει ορισμένες από τις πληροφορίες της συσκευής σας, ωστόσο εξακολουθεί να είναι πιο ιδιωτική από την αναπαραγωγή του βίντεο.","informationalModalConfirmButtonText":"Ενεργοποίηση όλων των προεπισκοπήσεων","informationalModalRejectButtonText":"Όχι, ευχαριστώ","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό στο YouTube για να εμποδίσει την Google από το να σας παρακολουθεί","infoTextUnblockVideo":"Αποκλείσαμε την Google (στην οποία ανήκει το YouTube) από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το βίντεο, η Google θα γνωρίζει τη δραστηριότητά σας.","infoPreviewToggleText":"Οι προεπισκοπήσεις απενεργοποιήθηκαν για πρόσθετη προστασία των προσωπικών δεδομένων","infoPreviewToggleEnabledText":"Οι προεπισκοπήσεις ενεργοποιήθηκαν","infoPreviewInfoText":"Μάθετε περισσότερα για την ενσωματωμένη προστασία κοινωνικών μέσων DuckDuckGo"}},"en":{"facebook.json":{"informationalModalMessageTitle":"Logging in with Facebook lets them track you","informationalModalMessageBody":"Once you're logged in, DuckDuckGo can't block Facebook content from tracking you on this site.","informationalModalConfirmButtonText":"Log In","informationalModalRejectButtonText":"Go back","loginButtonText":"Log in with Facebook","loginBodyText":"Facebook tracks your activity on a site when you use them to login.","buttonTextUnblockContent":"Unblock Content","buttonTextUnblockComment":"Unblock Comment","buttonTextUnblockComments":"Unblock Comments","buttonTextUnblockPost":"Unblock Post","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockContent":"DuckDuckGo blocked this content to prevent Facebook from tracking you","infoTitleUnblockComment":"DuckDuckGo blocked this comment to prevent Facebook from tracking you","infoTitleUnblockComments":"DuckDuckGo blocked these comments to prevent Facebook from tracking you","infoTitleUnblockPost":"DuckDuckGo blocked this post to prevent Facebook from tracking you","infoTitleUnblockVideo":"DuckDuckGo blocked this video to prevent Facebook from tracking you","infoTextUnblockContent":"We blocked Facebook from tracking you when the page loaded. If you unblock this content, Facebook will know your activity."},"shared.json":{"learnMore":"Learn More","readAbout":"Read about this privacy protection"},"youtube.json":{"informationalModalMessageTitle":"Enable all YouTube previews?","informationalModalMessageBody":"Showing previews will allow Google (which owns YouTube) to see some of your device’s information, but is still more private than playing the video.","informationalModalConfirmButtonText":"Enable All Previews","informationalModalRejectButtonText":"No Thanks","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockVideo":"DuckDuckGo blocked this YouTube video to prevent Google from tracking you","infoTextUnblockVideo":"We blocked Google (which owns YouTube) from tracking you when the page loaded. If you unblock this video, Google will know your activity.","infoPreviewToggleText":"Previews disabled for additional privacy","infoPreviewToggleEnabledText":"Previews enabled","infoPreviewInfoText":"Learn more about DuckDuckGo Embedded Social Media Protection"}},"es":{"facebook.json":{"informationalModalMessageTitle":"Al iniciar sesión en Facebook, les permites que te rastreen","informationalModalMessageBody":"Una vez que hayas iniciado sesión, DuckDuckGo no puede bloquear el contenido de Facebook para que no te rastree en este sitio.","informationalModalConfirmButtonText":"Iniciar sesión","informationalModalRejectButtonText":"Volver atrás","loginButtonText":"Iniciar sesión con Facebook","loginBodyText":"Facebook rastrea tu actividad en un sitio web cuando lo usas para iniciar sesión.","buttonTextUnblockContent":"Desbloquear contenido","buttonTextUnblockComment":"Desbloquear comentario","buttonTextUnblockComments":"Desbloquear comentarios","buttonTextUnblockPost":"Desbloquear publicación","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockContent":"DuckDuckGo ha bloqueado este contenido para evitar que Facebook te rastree","infoTitleUnblockComment":"DuckDuckGo ha bloqueado este comentario para evitar que Facebook te rastree","infoTitleUnblockComments":"DuckDuckGo ha bloqueado estos comentarios para evitar que Facebook te rastree","infoTitleUnblockPost":"DuckDuckGo ha bloqueado esta publicación para evitar que Facebook te rastree","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo para evitar que Facebook te rastree","infoTextUnblockContent":"Hemos bloqueado el rastreo de Facebook cuando se ha cargado la página. Si desbloqueas este contenido, Facebook tendrá conocimiento de tu actividad."},"shared.json":{"learnMore":"Más información","readAbout":"Lee acerca de esta protección de privacidad"},"youtube.json":{"informationalModalMessageTitle":"¿Habilitar todas las vistas previas de YouTube?","informationalModalMessageBody":"Mostrar vistas previas permitirá a Google (que es el propietario de YouTube) ver parte de la información de tu dispositivo, pero sigue siendo más privado que reproducir el vídeo.","informationalModalConfirmButtonText":"Habilitar todas las vistas previas","informationalModalRejectButtonText":"No, gracias","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo de YouTube para evitar que Google te rastree","infoTextUnblockVideo":"Hemos bloqueado el rastreo de Google (que es el propietario de YouTube) al cargarse la página. Si desbloqueas este vídeo, Goggle tendrá conocimiento de tu actividad.","infoPreviewToggleText":"Vistas previas desactivadas para mayor privacidad","infoPreviewToggleEnabledText":"Vistas previas activadas","infoPreviewInfoText":"Más información sobre la protección integrada de redes sociales DuckDuckGo"}},"et":{"facebook.json":{"informationalModalMessageTitle":"Kui logid Facebookiga sisse, saab Facebook sind jälgida","informationalModalMessageBody":"Kui oled sisse logitud, ei saa DuckDuckGo blokeerida Facebooki sisu sind jälgimast.","informationalModalConfirmButtonText":"Logi sisse","informationalModalRejectButtonText":"Mine tagasi","loginButtonText":"Logi sisse Facebookiga","loginBodyText":"Kui logid sisse Facebookiga, saab Facebook sinu tegevust saidil jälgida.","buttonTextUnblockContent":"Deblokeeri sisu","buttonTextUnblockComment":"Deblokeeri kommentaar","buttonTextUnblockComments":"Deblokeeri kommentaarid","buttonTextUnblockPost":"Deblokeeri postitus","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockContent":"DuckDuckGo blokeeris selle sisu, et Facebook ei saaks sind jälgida","infoTitleUnblockComment":"DuckDuckGo blokeeris selle kommentaari, et Facebook ei saaks sind jälgida","infoTitleUnblockComments":"DuckDuckGo blokeeris need kommentaarid, et Facebook ei saaks sind jälgida","infoTitleUnblockPost":"DuckDuckGo blokeeris selle postituse, et Facebook ei saaks sind jälgida","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle video, et Facebook ei saaks sind jälgida","infoTextUnblockContent":"Blokeerisime lehe laadimise ajal Facebooki jaoks sinu jälgimise. Kui sa selle sisu deblokeerid, saab Facebook sinu tegevust jälgida."},"shared.json":{"learnMore":"Loe edasi","readAbout":"Loe selle privaatsuskaitse kohta"},"youtube.json":{"informationalModalMessageTitle":"Kas lubada kõik YouTube’i eelvaated?","informationalModalMessageBody":"Eelvaate näitamine võimaldab Google’il (kellele YouTube kuulub) näha osa sinu seadme teabest, kuid see on siiski privaatsem kui video esitamine.","informationalModalConfirmButtonText":"Luba kõik eelvaated","informationalModalRejectButtonText":"Ei aitäh","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle YouTube’i video, et takistada Google’it sind jälgimast","infoTextUnblockVideo":"Me blokeerisime lehe laadimise ajal Google’i (kellele YouTube kuulub) jälgimise. Kui sa selle video deblokeerid, saab Google sinu tegevusest teada.","infoPreviewToggleText":"Eelvaated on täiendava privaatsuse tagamiseks keelatud","infoPreviewToggleEnabledText":"Eelvaated on lubatud","infoPreviewInfoText":"Lisateave DuckDuckGo sisseehitatud sotsiaalmeediakaitse kohta"}},"fi":{"facebook.json":{"informationalModalMessageTitle":"Kun kirjaudut sisään Facebook-tunnuksilla, Facebook voi seurata sinua","informationalModalMessageBody":"Kun olet kirjautunut sisään, DuckDuckGo ei voi estää Facebook-sisältöä seuraamasta sinua tällä sivustolla.","informationalModalConfirmButtonText":"Kirjaudu sisään","informationalModalRejectButtonText":"Edellinen","loginButtonText":"Kirjaudu sisään Facebook-tunnuksilla","loginBodyText":"Facebook seuraa toimintaasi sivustolla, kun kirjaudut sisään sen kautta.","buttonTextUnblockContent":"Poista sisällön esto","buttonTextUnblockComment":"Poista kommentin esto","buttonTextUnblockComments":"Poista kommenttien esto","buttonTextUnblockPost":"Poista julkaisun esto","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockContent":"DuckDuckGo esti tämän sisällön estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComment":"DuckDuckGo esti tämän kommentin estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComments":"DuckDuckGo esti nämä kommentit estääkseen Facebookia seuraamasta sinua","infoTitleUnblockPost":"DuckDuckGo esti tämän julkaisun estääkseen Facebookia seuraamasta sinua","infoTitleUnblockVideo":"DuckDuckGo esti tämän videon estääkseen Facebookia seuraamasta sinua","infoTextUnblockContent":"Estimme Facebookia seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän sisällön eston, Facebook saa tietää toimintasi."},"shared.json":{"learnMore":"Lue lisää","readAbout":"Lue tästä yksityisyydensuojasta"},"youtube.json":{"informationalModalMessageTitle":"Otetaanko käyttöön kaikki YouTube-esikatselut?","informationalModalMessageBody":"Kun sallit esikatselun, Google (joka omistaa YouTuben) voi nähdä joitakin laitteesi tietoja, mutta se on silti yksityisempää kuin videon toistaminen.","informationalModalConfirmButtonText":"Ota käyttöön kaikki esikatselut","informationalModalRejectButtonText":"Ei kiitos","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockVideo":"DuckDuckGo esti tämän YouTube-videon, jotta Google ei voi seurata sinua","infoTextUnblockVideo":"Estimme Googlea (joka omistaa YouTuben) seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän videon eston, Google tietää toimintasi.","infoPreviewToggleText":"Esikatselut on poistettu käytöstä yksityisyyden lisäämiseksi","infoPreviewToggleEnabledText":"Esikatselut käytössä","infoPreviewInfoText":"Lue lisää DuckDuckGon upotetusta sosiaalisen median suojauksesta"}},"fr":{"facebook.json":{"informationalModalMessageTitle":"L'identification via Facebook leur permet de vous pister","informationalModalMessageBody":"Une fois que vous êtes connecté(e), DuckDuckGo ne peut pas empêcher le contenu Facebook de vous pister sur ce site.","informationalModalConfirmButtonText":"Connexion","informationalModalRejectButtonText":"Revenir en arrière","loginButtonText":"S'identifier avec Facebook","loginBodyText":"Facebook piste votre activité sur un site lorsque vous l'utilisez pour vous identifier.","buttonTextUnblockContent":"Débloquer le contenu","buttonTextUnblockComment":"Débloquer le commentaire","buttonTextUnblockComments":"Débloquer les commentaires","buttonTextUnblockPost":"Débloquer la publication","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockContent":"DuckDuckGo a bloqué ce contenu pour empêcher Facebook de vous suivre","infoTitleUnblockComment":"DuckDuckGo a bloqué ce commentaire pour empêcher Facebook de vous suivre","infoTitleUnblockComments":"DuckDuckGo a bloqué ces commentaires pour empêcher Facebook de vous suivre","infoTitleUnblockPost":"DuckDuckGo a bloqué cette publication pour empêcher Facebook de vous pister","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo pour empêcher Facebook de vous pister","infoTextUnblockContent":"Nous avons empêché Facebook de vous pister lors du chargement de la page. Si vous débloquez ce contenu, Facebook connaîtra votre activité."},"shared.json":{"learnMore":"En savoir plus","readAbout":"En savoir plus sur cette protection de la confidentialité"},"youtube.json":{"informationalModalMessageTitle":"Activer tous les aperçus YouTube ?","informationalModalMessageBody":"L'affichage des aperçus permettra à Google (propriétaire de YouTube) de voir certaines informations de votre appareil, mais cela reste davantage confidentiel qu'en lisant la vidéo.","informationalModalConfirmButtonText":"Activer tous les aperçus","informationalModalRejectButtonText":"Non merci","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo YouTube pour empêcher Google de vous pister","infoTextUnblockVideo":"Nous avons empêché Google (propriétaire de YouTube) de vous pister lors du chargement de la page. Si vous débloquez cette vidéo, Google connaîtra votre activité.","infoPreviewToggleText":"Aperçus désactivés pour plus de confidentialité","infoPreviewToggleEnabledText":"Aperçus activés","infoPreviewInfoText":"En savoir plus sur la protection intégrée DuckDuckGo des réseaux sociaux"}},"hr":{"facebook.json":{"informationalModalMessageTitle":"Prijava putem Facebooka omogućuje im da te prate","informationalModalMessageBody":"Nakon što se prijaviš, DuckDuckGo ne može blokirati Facebookov sadržaj da te prati na Facebooku.","informationalModalConfirmButtonText":"Prijavljivanje","informationalModalRejectButtonText":"Vrati se","loginButtonText":"Prijavi se putem Facebooka","loginBodyText":"Facebook prati tvoju aktivnost na toj web lokaciji kad je koristiš za prijavu.","buttonTextUnblockContent":"Deblokiranje sadržaja","buttonTextUnblockComment":"Deblokiranje komentara","buttonTextUnblockComments":"Deblokiranje komentara","buttonTextUnblockPost":"Deblokiranje objave","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockContent":"DuckDuckGo je blokirao ovaj sadržaj kako bi spriječio Facebook da te prati","infoTitleUnblockComment":"DuckDuckGo je blokirao ovaj komentar kako bi spriječio Facebook da te prati","infoTitleUnblockComments":"DuckDuckGo je blokirao ove komentare kako bi spriječio Facebook da te prati","infoTitleUnblockPost":"DuckDuckGo je blokirao ovu objavu kako bi spriječio Facebook da te prati","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj video kako bi spriječio Facebook da te prati","infoTextUnblockContent":"Blokirali smo Facebook da te prati kad se stranica učita. Ako deblokiraš ovaj sadržaj, Facebook će znati tvoju aktivnost."},"shared.json":{"learnMore":"Saznajte više","readAbout":"Pročitaj više o ovoj zaštiti privatnosti"},"youtube.json":{"informationalModalMessageTitle":"Omogućiti sve YouTube pretpreglede?","informationalModalMessageBody":"Prikazivanje pretpregleda omogućit će Googleu (u čijem je vlasništvu YouTube) da vidi neke podatke o tvom uređaju, ali je i dalje privatnija opcija od reprodukcije videozapisa.","informationalModalConfirmButtonText":"Omogući sve pretpreglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj YouTube videozapis kako bi spriječio Google da te prati","infoTextUnblockVideo":"Blokirali smo Google (u čijem je vlasništvu YouTube) da te prati kad se stranica učita. Ako deblokiraš ovaj videozapis, Google će znati tvoju aktivnost.","infoPreviewToggleText":"Pretpregledi su onemogućeni radi dodatne privatnosti","infoPreviewToggleEnabledText":"Pretpregledi su omogućeni","infoPreviewInfoText":"Saznaj više o uključenoj DuckDuckGo zaštiti od društvenih medija"}},"hu":{"facebook.json":{"informationalModalMessageTitle":"A Facebookkal való bejelentkezéskor a Facebook nyomon követhet","informationalModalMessageBody":"Miután bejelentkezel, a DuckDuckGo nem fogja tudni blokkolni a Facebook-tartalmat, amely nyomon követ ezen az oldalon.","informationalModalConfirmButtonText":"Bejelentkezés","informationalModalRejectButtonText":"Visszalépés","loginButtonText":"Bejelentkezés Facebookkal","loginBodyText":"Ha a Facebookkal jelentkezel be, nyomon követik a webhelyen végzett tevékenységedet.","buttonTextUnblockContent":"Tartalom feloldása","buttonTextUnblockComment":"Hozzászólás feloldása","buttonTextUnblockComments":"Hozzászólások feloldása","buttonTextUnblockPost":"Bejegyzés feloldása","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockContent":"A DuckDuckGo blokkolta ezt a tartalmat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComment":"A DuckDuckGo blokkolta ezt a hozzászólást, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComments":"A DuckDuckGo blokkolta ezeket a hozzászólásokat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockPost":"A DuckDuckGo blokkolta ezt a bejegyzést, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockVideo":"A DuckDuckGo blokkolta ezt a videót, hogy megakadályozza a Facebookot a nyomon követésedben","infoTextUnblockContent":"Az oldal betöltésekor blokkoltuk a Facebookot a nyomon követésedben. Ha feloldod ezt a tartalmat, a Facebook tudni fogja, hogy milyen tevékenységet végzel."},"shared.json":{"learnMore":"További részletek","readAbout":"Tudj meg többet erről az adatvédelemről"},"youtube.json":{"informationalModalMessageTitle":"Engedélyezed minden YouTube-videó előnézetét?","informationalModalMessageBody":"Az előnézetek megjelenítésével a Google (a YouTube tulajdonosa) láthatja a készülék néhány adatát, de ez adatvédelmi szempontból még mindig előnyösebb, mint a videó lejátszása.","informationalModalConfirmButtonText":"Minden előnézet engedélyezése","informationalModalRejectButtonText":"Nem, köszönöm","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockVideo":"A DuckDuckGo blokkolta a YouTube-videót, hogy a Google ne követhessen nyomon","infoTextUnblockVideo":"Blokkoltuk, hogy a Google (a YouTube tulajdonosa) nyomon követhessen az oldal betöltésekor. Ha feloldod a videó blokkolását, a Google tudni fogja, hogy milyen tevékenységet végzel.","infoPreviewToggleText":"Az előnézetek a fokozott adatvédelem érdekében letiltva","infoPreviewToggleEnabledText":"Az előnézetek engedélyezve","infoPreviewInfoText":"További tudnivalók a DuckDuckGo beágyazott közösségi média elleni védelméről"}},"it":{"facebook.json":{"informationalModalMessageTitle":"L'accesso con Facebook consente di tracciarti","informationalModalMessageBody":"Dopo aver effettuato l'accesso, DuckDuckGo non può bloccare il tracciamento dei contenuti di Facebook su questo sito.","informationalModalConfirmButtonText":"Accedi","informationalModalRejectButtonText":"Torna indietro","loginButtonText":"Accedi con Facebook","loginBodyText":"Facebook tiene traccia della tua attività su un sito quando lo usi per accedere.","buttonTextUnblockContent":"Sblocca contenuti","buttonTextUnblockComment":"Sblocca commento","buttonTextUnblockComments":"Sblocca commenti","buttonTextUnblockPost":"Sblocca post","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockContent":"DuckDuckGo ha bloccato questo contenuto per impedire a Facebook di tracciarti","infoTitleUnblockComment":"DuckDuckGo ha bloccato questo commento per impedire a Facebook di tracciarti","infoTitleUnblockComments":"DuckDuckGo ha bloccato questi commenti per impedire a Facebook di tracciarti","infoTitleUnblockPost":"DuckDuckGo ha bloccato questo post per impedire a Facebook di tracciarti","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video per impedire a Facebook di tracciarti","infoTextUnblockContent":"Abbiamo impedito a Facebook di tracciarti al caricamento della pagina. Se sblocchi questo contenuto, Facebook conoscerà la tua attività."},"shared.json":{"learnMore":"Ulteriori informazioni","readAbout":"Leggi di più su questa protezione della privacy"},"youtube.json":{"informationalModalMessageTitle":"Abilitare tutte le anteprime di YouTube?","informationalModalMessageBody":"La visualizzazione delle anteprime consentirà a Google (che possiede YouTube) di vedere alcune delle informazioni del tuo dispositivo, ma è comunque più privato rispetto alla riproduzione del video.","informationalModalConfirmButtonText":"Abilita tutte le anteprime","informationalModalRejectButtonText":"No, grazie","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video di YouTube per impedire a Google di tracciarti","infoTextUnblockVideo":"Abbiamo impedito a Google (che possiede YouTube) di tracciarti quando la pagina è stata caricata. Se sblocchi questo video, Google conoscerà la tua attività.","infoPreviewToggleText":"Anteprime disabilitate per una maggiore privacy","infoPreviewToggleEnabledText":"Anteprime abilitate","infoPreviewInfoText":"Scopri di più sulla protezione dai social media integrata di DuckDuckGo"}},"lt":{"facebook.json":{"informationalModalMessageTitle":"Prisijungę prie „Facebook“ galite būti sekami","informationalModalMessageBody":"Kai esate prisijungę, „DuckDuckGo“ negali užblokuoti „Facebook“ turinio, todėl esate sekami šioje svetainėje.","informationalModalConfirmButtonText":"Prisijungti","informationalModalRejectButtonText":"Grįžti atgal","loginButtonText":"Prisijunkite su „Facebook“","loginBodyText":"„Facebook“ seka jūsų veiklą svetainėje, kai prisijungiate su šia svetaine.","buttonTextUnblockContent":"Atblokuoti turinį","buttonTextUnblockComment":"Atblokuoti komentarą","buttonTextUnblockComments":"Atblokuoti komentarus","buttonTextUnblockPost":"Atblokuoti įrašą","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockContent":"„DuckDuckGo“ užblokavo šį turinį, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComment":"„DuckDuckGo“ užblokavo šį komentarą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComments":"„DuckDuckGo“ užblokavo šiuos komentarus, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockPost":"„DuckDuckGo“ užblokavo šį įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį vaizdo įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTextUnblockContent":"Užblokavome „Facebook“, kad negalėtų jūsų sekti, kai puslapis buvo įkeltas. Jei atblokuosite šį turinį, „Facebook“ žinos apie jūsų veiklą."},"shared.json":{"learnMore":"Sužinoti daugiau","readAbout":"Skaitykite apie šią privatumo apsaugą"},"youtube.json":{"informationalModalMessageTitle":"Įjungti visas „YouTube“ peržiūras?","informationalModalMessageBody":"Peržiūrų rodymas leis „Google“ (kuriai priklauso „YouTube“) matyti tam tikrą jūsų įrenginio informaciją, tačiau ji vis tiek bus privatesnė nei leidžiant vaizdo įrašą.","informationalModalConfirmButtonText":"Įjungti visas peržiūras","informationalModalRejectButtonText":"Ne, dėkoju","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį „YouTube“ vaizdo įrašą, kad „Google“ negalėtų jūsų sekti","infoTextUnblockVideo":"Užblokavome „Google“ (kuriai priklauso „YouTube“) galimybę sekti jus, kai puslapis buvo įkeltas. Jei atblokuosite šį vaizdo įrašą, „Google“ sužinos apie jūsų veiklą.","infoPreviewToggleText":"Peržiūros išjungtos dėl papildomo privatumo","infoPreviewToggleEnabledText":"Peržiūros įjungtos","infoPreviewInfoText":"Sužinokite daugiau apie „DuckDuckGo“ įdėtąją socialinės žiniasklaidos apsaugą"}},"lv":{"facebook.json":{"informationalModalMessageTitle":"Ja pieteiksies ar Facebook, viņi varēs tevi izsekot","informationalModalMessageBody":"Kad tu piesakies, DuckDuckGo nevar novērst, ka Facebook saturs tevi izseko šajā vietnē.","informationalModalConfirmButtonText":"Pieteikties","informationalModalRejectButtonText":"Atgriezties","loginButtonText":"Pieteikties ar Facebook","loginBodyText":"Facebook izseko tavas aktivitātes vietnē, kad esi pieteicies ar Facebook.","buttonTextUnblockContent":"Atbloķēt saturu","buttonTextUnblockComment":"Atbloķēt komentāru","buttonTextUnblockComments":"Atbloķēt komentārus","buttonTextUnblockPost":"Atbloķēt ziņu","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockContent":"DuckDuckGo bloķēja šo saturu, lai neļautu Facebook tevi izsekot","infoTitleUnblockComment":"DuckDuckGo bloķēja šo komentāru, lai neļautu Facebook tevi izsekot","infoTitleUnblockComments":"DuckDuckGo bloķēja šos komentārus, lai neļautu Facebook tevi izsekot","infoTitleUnblockPost":"DuckDuckGo bloķēja šo ziņu, lai neļautu Facebook tevi izsekot","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo videoklipu, lai neļautu Facebook tevi izsekot","infoTextUnblockContent":"Mēs bloķējām Facebook iespēju tevi izsekot, ielādējot lapu. Ja atbloķēsi šo saturu, Facebook redzēs, ko tu dari."},"shared.json":{"learnMore":"Uzzināt vairāk","readAbout":"Lasi par šo privātuma aizsardzību"},"youtube.json":{"informationalModalMessageTitle":"Vai iespējot visus YouTube priekšskatījumus?","informationalModalMessageBody":"Priekšskatījumu rādīšana ļaus Google (kam pieder YouTube) redzēt daļu tavas ierīces informācijas, taču tas tāpat ir privātāk par videoklipa atskaņošanu.","informationalModalConfirmButtonText":"Iespējot visus priekšskatījumus","informationalModalRejectButtonText":"Nē, paldies","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo YouTube videoklipu, lai neļautu Google tevi izsekot","infoTextUnblockVideo":"Mēs neļāvām Google (kam pieder YouTube) tevi izsekot, kad lapa tika ielādēta. Ja atbloķēsi šo videoklipu, Google zinās, ko tu dari.","infoPreviewToggleText":"Priekšskatījumi ir atspējoti, lai nodrošinātu papildu konfidencialitāti","infoPreviewToggleEnabledText":"Priekšskatījumi ir iespējoti","infoPreviewInfoText":"Uzzini vairāk par DuckDuckGo iegulto sociālo mediju aizsardzību"}},"nb":{"facebook.json":{"informationalModalMessageTitle":"Når du logger på med Facebook, kan de spore deg","informationalModalMessageBody":"Når du er logget på, kan ikke DuckDuckGo hindre Facebook-innhold i å spore deg på dette nettstedet.","informationalModalConfirmButtonText":"Logg inn","informationalModalRejectButtonText":"Gå tilbake","loginButtonText":"Logg på med Facebook","loginBodyText":"Når du logger på med Facebook, sporer de aktiviteten din på nettstedet.","buttonTextUnblockContent":"Opphev blokkering av innhold","buttonTextUnblockComment":"Opphev blokkering av kommentar","buttonTextUnblockComments":"Opphev blokkering av kommentarer","buttonTextUnblockPost":"Opphev blokkering av innlegg","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockContent":"DuckDuckGo blokkerte dette innholdet for å hindre Facebook i å spore deg","infoTitleUnblockComment":"DuckDuckGo blokkerte denne kommentaren for å hindre Facebook i å spore deg","infoTitleUnblockComments":"DuckDuckGo blokkerte disse kommentarene for å hindre Facebook i å spore deg","infoTitleUnblockPost":"DuckDuckGo blokkerte dette innlegget for å hindre Facebook i å spore deg","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne videoen for å hindre Facebook i å spore deg","infoTextUnblockContent":"Vi hindret Facebook i å spore deg da siden ble lastet. Hvis du opphever blokkeringen av dette innholdet, får Facebook vite om aktiviteten din."},"shared.json":{"learnMore":"Finn ut mer","readAbout":"Les om denne personvernfunksjonen"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Forhåndsvisninger gjør det mulig for Google (som eier YouTube) å se enkelte opplysninger om enheten din, men det er likevel mer privat enn å spille av videoen.","informationalModalConfirmButtonText":"Aktiver alle forhåndsvisninger","informationalModalRejectButtonText":"Nei takk","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne YouTube-videoen for å hindre Google i å spore deg","infoTextUnblockVideo":"Vi blokkerte Google (som eier YouTube) mot å spore deg da siden ble lastet. Hvis du opphever blokkeringen av denne videoen, får Google vite om aktiviteten din.","infoPreviewToggleText":"Forhåndsvisninger er deaktivert for å gi deg ekstra personvern","infoPreviewToggleEnabledText":"Forhåndsvisninger er aktivert","infoPreviewInfoText":"Finn ut mer om DuckDuckGos innebygde beskyttelse for sosiale medier"}},"nl":{"facebook.json":{"informationalModalMessageTitle":"Als je inlogt met Facebook, kunnen zij je volgen","informationalModalMessageBody":"Als je eenmaal bent ingelogd, kan DuckDuckGo niet voorkomen dat Facebook je op deze site volgt.","informationalModalConfirmButtonText":"Inloggen","informationalModalRejectButtonText":"Terug","loginButtonText":"Inloggen met Facebook","loginBodyText":"Facebook volgt je activiteit op een site als je Facebook gebruikt om in te loggen.","buttonTextUnblockContent":"Inhoud deblokkeren","buttonTextUnblockComment":"Opmerking deblokkeren","buttonTextUnblockComments":"Opmerkingen deblokkeren","buttonTextUnblockPost":"Bericht deblokkeren","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockContent":"DuckDuckGo heeft deze inhoud geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComment":"DuckDuckGo heeft deze opmerking geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComments":"DuckDuckGo heeft deze opmerkingen geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockPost":"DuckDuckGo heeft dit bericht geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockVideo":"DuckDuckGo heeft deze video geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTextUnblockContent":"We hebben voorkomen dat Facebook je volgde toen de pagina werd geladen. Als je deze inhoud deblokkeert, kan Facebook je activiteit zien."},"shared.json":{"learnMore":"Meer informatie","readAbout":"Lees meer over deze privacybescherming"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-voorbeelden inschakelen?","informationalModalMessageBody":"Bij het tonen van voorbeelden kan Google (eigenaar van YouTube) een deel van de informatie over je apparaat zien, maar blijft je privacy beter beschermd dan als je de video zou afspelen.","informationalModalConfirmButtonText":"Alle voorbeelden inschakelen","informationalModalRejectButtonText":"Nee, bedankt","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockVideo":"DuckDuckGo heeft deze YouTube-video geblokkeerd om te voorkomen dat Google je kan volgen","infoTextUnblockVideo":"We hebben voorkomen dat Google (eigenaar van YouTube) je volgde toen de pagina werd geladen. Als je deze video deblokkeert, kan Google je activiteit zien.","infoPreviewToggleText":"Voorbeelden uitgeschakeld voor extra privacy","infoPreviewToggleEnabledText":"Voorbeelden ingeschakeld","infoPreviewInfoText":"Meer informatie over DuckDuckGo's bescherming tegen ingesloten social media"}},"pl":{"facebook.json":{"informationalModalMessageTitle":"Jeśli zalogujesz się za pośrednictwem Facebooka, będzie on mógł śledzić Twoją aktywność","informationalModalMessageBody":"Po zalogowaniu się DuckDuckGo nie może zablokować możliwości śledzenia Cię przez Facebooka na tej stronie.","informationalModalConfirmButtonText":"Zaloguj się","informationalModalRejectButtonText":"Wróć","loginButtonText":"Zaloguj się za pośrednictwem Facebooka","loginBodyText":"Facebook śledzi Twoją aktywność na stronie, gdy logujesz się za jego pośrednictwem.","buttonTextUnblockContent":"Odblokuj treść","buttonTextUnblockComment":"Odblokuj komentarz","buttonTextUnblockComments":"Odblokuj komentarze","buttonTextUnblockPost":"Odblokuj post","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockContent":"DuckDuckGo zablokował tę treść, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComment":"DuckDuckGo zablokował ten komentarz, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComments":"DuckDuckGo zablokował te komentarze, aby Facebook nie mógł Cię śledzić","infoTitleUnblockPost":"DuckDuckGo zablokował ten post, aby Facebook nie mógł Cię śledzić","infoTitleUnblockVideo":"DuckDuckGo zablokował tę treść wideo, aby Facebook nie mógł Cię śledzić.","infoTextUnblockContent":"Zablokowaliśmy Facebookowi możliwość śledzenia Cię podczas ładowania strony. Jeśli odblokujesz tę treść, Facebook uzyska informacje o Twojej aktywności."},"shared.json":{"learnMore":"Dowiedz się więcej","readAbout":"Dowiedz się więcej o tej ochronie prywatności"},"youtube.json":{"informationalModalMessageTitle":"Włączyć wszystkie podglądy w YouTube?","informationalModalMessageBody":"Wyświetlanie podglądu pozwala Google (który jest właścicielem YouTube) zobaczyć niektóre informacje o Twoim urządzeniu, ale nadal jest to bardziej prywatne niż odtwarzanie filmu.","informationalModalConfirmButtonText":"Włącz wszystkie podglądy","informationalModalRejectButtonText":"Nie, dziękuję","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockVideo":"DuckDuckGo zablokował ten film w YouTube, aby uniemożliwić Google śledzenie Twojej aktywności","infoTextUnblockVideo":"Zablokowaliśmy możliwość śledzenia Cię przez Google (właściciela YouTube) podczas ładowania strony. Jeśli odblokujesz ten film, Google zobaczy Twoją aktywność.","infoPreviewToggleText":"Podglądy zostały wyłączone, aby zapewnić większą ptywatność","infoPreviewToggleEnabledText":"Podglądy włączone","infoPreviewInfoText":"Dowiedz się więcej o zabezpieczeniu osadzonych treści społecznościowych DuckDuckGo"}},"pt":{"facebook.json":{"informationalModalMessageTitle":"Iniciar sessão no Facebook permite que este te rastreie","informationalModalMessageBody":"Depois de iniciares sessão, o DuckDuckGo não poderá bloquear o rastreio por parte do conteúdo do Facebook neste site.","informationalModalConfirmButtonText":"Iniciar sessão","informationalModalRejectButtonText":"Retroceder","loginButtonText":"Iniciar sessão com o Facebook","loginBodyText":"O Facebook rastreia a tua atividade num site quando o usas para iniciares sessão.","buttonTextUnblockContent":"Desbloquear Conteúdo","buttonTextUnblockComment":"Desbloquear Comentário","buttonTextUnblockComments":"Desbloquear Comentários","buttonTextUnblockPost":"Desbloquear Publicação","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockContent":"O DuckDuckGo bloqueou este conteúdo para evitar que o Facebook te rastreie","infoTitleUnblockComment":"O DuckDuckGo bloqueou este comentário para evitar que o Facebook te rastreie","infoTitleUnblockComments":"O DuckDuckGo bloqueou estes comentários para evitar que o Facebook te rastreie","infoTitleUnblockPost":"O DuckDuckGo bloqueou esta publicação para evitar que o Facebook te rastreie","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo para evitar que o Facebook te rastreie","infoTextUnblockContent":"Bloqueámos o rastreio por parte do Facebook quando a página foi carregada. Se desbloqueares este conteúdo, o Facebook fica a saber a tua atividade."},"shared.json":{"learnMore":"Saiba mais","readAbout":"Ler mais sobre esta proteção de privacidade"},"youtube.json":{"informationalModalMessageTitle":"Ativar todas as pré-visualizações do YouTube?","informationalModalMessageBody":"Mostrar visualizações permite à Google (que detém o YouTube) ver algumas das informações do teu dispositivo, mas ainda é mais privado do que reproduzir o vídeo.","informationalModalConfirmButtonText":"Ativar todas as pré-visualizações","informationalModalRejectButtonText":"Não, obrigado","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo do YouTube para impedir que a Google te rastreie","infoTextUnblockVideo":"Bloqueámos o rastreio por parte da Google (que detém o YouTube) quando a página foi carregada. Se desbloqueares este vídeo, a Google fica a saber a tua atividade.","infoPreviewToggleText":"Pré-visualizações desativadas para privacidade adicional","infoPreviewToggleEnabledText":"Pré-visualizações ativadas","infoPreviewInfoText":"Saiba mais sobre a Proteção contra conteúdos de redes sociais incorporados do DuckDuckGo"}},"ro":{"facebook.json":{"informationalModalMessageTitle":"Conectarea cu Facebook îi permite să te urmărească","informationalModalMessageBody":"Odată ce te-ai conectat, DuckDuckGo nu poate împiedica conținutul Facebook să te urmărească pe acest site.","informationalModalConfirmButtonText":"Autentificare","informationalModalRejectButtonText":"Înapoi","loginButtonText":"Conectează-te cu Facebook","loginBodyText":"Facebook urmărește activitatea ta pe un site atunci când îl utilizezi pentru a te conecta.","buttonTextUnblockContent":"Deblochează conținutul","buttonTextUnblockComment":"Deblochează comentariul","buttonTextUnblockComments":"Deblochează comentariile","buttonTextUnblockPost":"Deblochează postarea","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockContent":"DuckDuckGo a blocat acest conținut pentru a împiedica Facebook să te urmărească","infoTitleUnblockComment":"DuckDuckGo a blocat acest comentariu pentru a împiedica Facebook să te urmărească","infoTitleUnblockComments":"DuckDuckGo a blocat aceste comentarii pentru a împiedica Facebook să te urmărească","infoTitleUnblockPost":"DuckDuckGo a blocat această postare pentru a împiedica Facebook să te urmărească","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip pentru a împiedica Facebook să te urmărească","infoTextUnblockContent":"Am împiedicat Facebook să te urmărească atunci când pagina a fost încărcată. Dacă deblochezi acest conținut, Facebook îți va cunoaște activitatea."},"shared.json":{"learnMore":"Află mai multe","readAbout":"Citește despre această protecție a confidențialității"},"youtube.json":{"informationalModalMessageTitle":"Activezi toate previzualizările YouTube?","informationalModalMessageBody":"Afișarea previzualizărilor va permite ca Google (care deține YouTube) să vadă unele dintre informațiile despre dispozitivul tău, dar este totuși mai privată decât redarea videoclipului.","informationalModalConfirmButtonText":"Activează toate previzualizările","informationalModalRejectButtonText":"Nu, mulțumesc","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip de pe YouTube pentru a împiedica Google să te urmărească","infoTextUnblockVideo":"Am împiedicat Google (care deține YouTube) să te urmărească atunci când s-a încărcat pagina. Dacă deblochezi acest videoclip, Google va cunoaște activitatea ta.","infoPreviewToggleText":"Previzualizările au fost dezactivate pentru o confidențialitate suplimentară","infoPreviewToggleEnabledText":"Previzualizări activate","infoPreviewInfoText":"Află mai multe despre Protecția integrată DuckDuckGo pentru rețelele sociale"}},"ru":{"facebook.json":{"informationalModalMessageTitle":"Вход через Facebook позволяет этой социальной сети отслеживать вас","informationalModalMessageBody":"После входа DuckDuckGo не сможет блокировать отслеживание ваших действий с контентом на Facebook.","informationalModalConfirmButtonText":"Войти","informationalModalRejectButtonText":"Вернуться","loginButtonText":"Войти через Facebook","loginBodyText":"При использовании учетной записи Facebook для входа на сайты эта социальная сеть сможет отслеживать на них ваши действия.","buttonTextUnblockContent":"Разблокировать","buttonTextUnblockComment":"Разблокировать","buttonTextUnblockComments":"Разблокировать","buttonTextUnblockPost":"Разблокировать","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockContent":"DuckDuckGo заблокировал этот контент, чтобы вас не отслеживал Facebook","infoTitleUnblockComment":"DuckDuckGo заблокировал этот комментарий, чтобы вас не отслеживал Facebook","infoTitleUnblockComments":"DuckDuckGo заблокировал эти комментарии, чтобы вас не отслеживал Facebook","infoTitleUnblockPost":"DuckDuckGo заблокировал эту публикацию, чтобы вас не отслеживал Facebook","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео, чтобы вас не отслеживал Facebook","infoTextUnblockContent":"Во время загрузки страницы мы помешали Facebook отследить ваши действия. Если разблокировать этот контент, Facebook сможет фиксировать вашу активность."},"shared.json":{"learnMore":"Узнать больше","readAbout":"Подробнее об этом виде защиты конфиденциальности"},"youtube.json":{"informationalModalMessageTitle":"Включить предпросмотр видео из YouTube?","informationalModalMessageBody":"Активация предварительного просмотра позволит Google (владельцу YouTube) получить некоторые сведения о вашем устройстве, однако это более безопасный вариант, чем воспроизведение видео целиком.","informationalModalConfirmButtonText":"Включить предпросмотр","informationalModalRejectButtonText":"Нет, спасибо","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео из YouTube, чтобы вас не отслеживал Google","infoTextUnblockVideo":"Во время загрузки страницы мы помешали Google (владельцу YouTube) отследить ваши действия. Если разблокировать видео, Google сможет фиксировать вашу активность.","infoPreviewToggleText":"Предварительный просмотр отключен для дополнительной защиты конфиденциальности","infoPreviewToggleEnabledText":"Предварительный просмотр включен","infoPreviewInfoText":"Подробнее о защите DuckDuckGo от внедренного контента соцсетей"}},"sk":{"facebook.json":{"informationalModalMessageTitle":"Prihlásenie cez Facebook mu umožní sledovať vás","informationalModalMessageBody":"DuckDuckGo po prihlásení nemôže na tejto lokalite zablokovať sledovanie vašej osoby obsahom Facebooku.","informationalModalConfirmButtonText":"Prihlásiť sa","informationalModalRejectButtonText":"Prejsť späť","loginButtonText":"Prihláste sa pomocou služby Facebook","loginBodyText":"Keď použijete prihlasovanie cez Facebook, Facebook bude na lokalite sledovať vašu aktivitu.","buttonTextUnblockContent":"Odblokovať obsah","buttonTextUnblockComment":"Odblokovať komentár","buttonTextUnblockComments":"Odblokovať komentáre","buttonTextUnblockPost":"Odblokovať príspevok","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockContent":"DuckDuckGo zablokoval tento obsah, aby vás Facebook nesledoval","infoTitleUnblockComment":"DuckDuckGo zablokoval tento komentár, aby zabránil sledovaniu zo strany Facebooku","infoTitleUnblockComments":"DuckDuckGo zablokoval tieto komentáre, aby vás Facebook nesledoval","infoTitleUnblockPost":"DuckDuckGo zablokoval tento príspevok, aby vás Facebook nesledoval","infoTitleUnblockVideo":"DuckDuckGo zablokoval toto video, aby vás Facebook nesledoval","infoTextUnblockContent":"Pri načítaní stránky sme zablokovali Facebook, aby vás nesledoval. Ak tento obsah odblokujete, Facebook bude vedieť o vašej aktivite."},"shared.json":{"learnMore":"Zistite viac","readAbout":"Prečítajte si o tejto ochrane súkromia"},"youtube.json":{"informationalModalMessageTitle":"Chcete povoliť všetky ukážky zo služby YouTube?","informationalModalMessageBody":"Zobrazenie ukážok umožní spoločnosti Google (ktorá vlastní YouTube) vidieť niektoré informácie o vašom zariadení, ale stále je to súkromnejšie ako prehrávanie videa.","informationalModalConfirmButtonText":"Povoliť všetky ukážky","informationalModalRejectButtonText":"Nie, ďakujem","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockVideo":"DuckDuckGo toto video v službe YouTube zablokoval s cieľom predísť tomu, aby vás spoločnosť Google mohla sledovať","infoTextUnblockVideo":"Zablokovali sme pre spoločnosť Google (ktorá vlastní YouTube), aby vás nemohla sledovať, keď sa stránka načíta. Ak toto video odblokujete, Google bude poznať vašu aktivitu.","infoPreviewToggleText":"Ukážky sú zakázané s cieľom zvýšiť ochranu súkromia","infoPreviewToggleEnabledText":"Ukážky sú povolené","infoPreviewInfoText":"Získajte viac informácií o DuckDuckGo, vloženej ochrane sociálnych médií"}},"sl":{"facebook.json":{"informationalModalMessageTitle":"Če se prijavite s Facebookom, vam Facebook lahko sledi","informationalModalMessageBody":"Ko ste enkrat prijavljeni, DuckDuckGo ne more blokirati Facebookove vsebine, da bi vam sledila na tem spletnem mestu.","informationalModalConfirmButtonText":"Prijava","informationalModalRejectButtonText":"Pojdi nazaj","loginButtonText":"Prijavite se s Facebookom","loginBodyText":"Če se prijavite s Facebookom, bo nato spremljal vaša dejanja na spletnem mestu.","buttonTextUnblockContent":"Odblokiraj vsebino","buttonTextUnblockComment":"Odblokiraj komentar","buttonTextUnblockComments":"Odblokiraj komentarje","buttonTextUnblockPost":"Odblokiraj objavo","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockContent":"DuckDuckGo je blokiral to vsebino, da bi Facebooku preprečil sledenje","infoTitleUnblockComment":"DuckDuckGo je blokiral ta komentar, da bi Facebooku preprečil sledenje","infoTitleUnblockComments":"DuckDuckGo je blokiral te komentarje, da bi Facebooku preprečil sledenje","infoTitleUnblockPost":"DuckDuckGo je blokiral to objavo, da bi Facebooku preprečil sledenje","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek, da bi Facebooku preprečil sledenje","infoTextUnblockContent":"Ko se je stran naložila, smo Facebooku preprečili, da bi vam sledil. Če to vsebino odblokirate, bo Facebook izvedel za vaša dejanja."},"shared.json":{"learnMore":"Več","readAbout":"Preberite več o tej zaščiti zasebnosti"},"youtube.json":{"informationalModalMessageTitle":"Želite omogočiti vse YouTubove predoglede?","informationalModalMessageBody":"Prikaz predogledov omogoča Googlu (ki je lastnik YouTuba) vpogled v nekatere podatke o napravi, vendar je še vedno bolj zasebno kot predvajanje videoposnetka.","informationalModalConfirmButtonText":"Omogoči vse predoglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek v YouTubu, da bi Googlu preprečil sledenje","infoTextUnblockVideo":"Googlu (ki je lastnik YouTuba) smo preprečili, da bi vam sledil, ko se je stran naložila. Če odblokirate ta videoposnetek, bo Google izvedel za vašo dejavnost.","infoPreviewToggleText":"Predogledi so zaradi dodatne zasebnosti onemogočeni","infoPreviewToggleEnabledText":"Predogledi so omogočeni","infoPreviewInfoText":"Več o vgrajeni zaščiti družbenih medijev DuckDuckGo"}},"sv":{"facebook.json":{"informationalModalMessageTitle":"Om du loggar in med Facebook kan de spåra dig","informationalModalMessageBody":"När du väl är inloggad kan DuckDuckGo inte hindra Facebooks innehåll från att spåra dig på den här webbplatsen.","informationalModalConfirmButtonText":"Logga in","informationalModalRejectButtonText":"Gå tillbaka","loginButtonText":"Logga in med Facebook","loginBodyText":"Facebook spårar din aktivitet på en webbplats om du använder det för att logga in.","buttonTextUnblockContent":"Avblockera innehåll","buttonTextUnblockComment":"Avblockera kommentar","buttonTextUnblockComments":"Avblockera kommentarer","buttonTextUnblockPost":"Avblockera inlägg","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockContent":"DuckDuckGo blockerade det här innehållet för att förhindra att Facebook spårar dig","infoTitleUnblockComment":"DuckDuckGo blockerade den här kommentaren för att förhindra att Facebook spårar dig","infoTitleUnblockComments":"DuckDuckGo blockerade de här kommentarerna för att förhindra att Facebook spårar dig","infoTitleUnblockPost":"DuckDuckGo blockerade det här inlägget för att förhindra att Facebook spårar dig","infoTitleUnblockVideo":"DuckDuckGo blockerade den här videon för att förhindra att Facebook spårar dig","infoTextUnblockContent":"Vi hindrade Facebook från att spåra dig när sidan lästes in. Om du avblockerar det här innehållet kommer Facebook att känna till din aktivitet."},"shared.json":{"learnMore":"Läs mer","readAbout":"Läs mer om detta integritetsskydd"},"youtube.json":{"informationalModalMessageTitle":"Aktivera alla förhandsvisningar för YouTube?","informationalModalMessageBody":"Genom att visa förhandsvisningar kan Google (som äger YouTube) se en del av enhetens information, men det är ändå mer privat än att spela upp videon.","informationalModalConfirmButtonText":"Aktivera alla förhandsvisningar","informationalModalRejectButtonText":"Nej tack","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockVideo":"DuckDuckGo blockerade den här YouTube-videon för att förhindra att Google spårar dig","infoTextUnblockVideo":"Vi hindrade Google (som äger YouTube) från att spåra dig när sidan laddades. Om du tar bort blockeringen av videon kommer Google att känna till din aktivitet.","infoPreviewToggleText":"Förhandsvisningar har inaktiverats för ytterligare integritet","infoPreviewToggleEnabledText":"Förhandsvisningar aktiverade","infoPreviewInfoText":"Läs mer om DuckDuckGos skydd mot inbäddade sociala medier"}},"tr":{"facebook.json":{"informationalModalMessageTitle":"Facebook ile giriş yapmak, sizi takip etmelerini sağlar","informationalModalMessageBody":"Giriş yaptıktan sonra, DuckDuckGo Facebook içeriğinin sizi bu sitede izlemesini engelleyemez.","informationalModalConfirmButtonText":"Oturum Aç","informationalModalRejectButtonText":"Geri dön","loginButtonText":"Facebook ile giriş yapın","loginBodyText":"Facebook, giriş yapmak için kullandığınızda bir sitedeki etkinliğinizi izler.","buttonTextUnblockContent":"İçeriğin Engelini Kaldır","buttonTextUnblockComment":"Yorumun Engelini Kaldır","buttonTextUnblockComments":"Yorumların Engelini Kaldır","buttonTextUnblockPost":"Gönderinin Engelini Kaldır","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockContent":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu içeriği engelledi","infoTitleUnblockComment":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumu engelledi","infoTitleUnblockComments":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumları engelledi","infoTitleUnblockPost":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu gönderiyi engelledi","infoTitleUnblockVideo":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu videoyu engelledi","infoTextUnblockContent":"Sayfa yüklendiğinde Facebook'un sizi izlemesini engelledik. Bu içeriğin engelini kaldırırsanız Facebook etkinliğinizi öğrenecektir."},"shared.json":{"learnMore":"Daha Fazla Bilgi","readAbout":"Bu gizlilik koruması hakkında bilgi edinin"},"youtube.json":{"informationalModalMessageTitle":"Tüm YouTube önizlemeleri etkinleştirilsin mi?","informationalModalMessageBody":"Önizlemelerin gösterilmesi Google'ın (YouTube'un sahibi) cihazınızın bazı bilgilerini görmesine izin verir, ancak yine de videoyu oynatmaktan daha özeldir.","informationalModalConfirmButtonText":"Tüm Önizlemeleri Etkinleştir","informationalModalRejectButtonText":"Hayır Teşekkürler","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockVideo":"DuckDuckGo, Google'ın sizi izlemesini önlemek için bu YouTube videosunu engelledi","infoTextUnblockVideo":"Sayfa yüklendiğinde Google'ın (YouTube'un sahibi) sizi izlemesini engelledik. Bu videonun engelini kaldırırsanız, Google etkinliğinizi öğrenecektir.","infoPreviewToggleText":"Ek gizlilik için önizlemeler devre dışı bırakıldı","infoPreviewToggleEnabledText":"Önizlemeler etkinleştirildi","infoPreviewInfoText":"DuckDuckGo Yerleşik Sosyal Medya Koruması hakkında daha fazla bilgi edinin"}}}`; /********************************************************* * Style Definitions *********************************************************/ - const styles = { - fontStyle: ` + /** + * Get CSS style defintions for CTL, using the provided AssetConfig for any non-embedded assets + * (e.g. fonts.) + * @param {import('../../content-feature.js').AssetConfig} [assets] + */ + function getStyles (assets) { + let fontStyle = ''; + let regularFontFamily = "system, -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'"; + let boldFontFamily = regularFontFamily; + if (assets?.regularFontUrl && assets?.boldFontUrl) { + fontStyle = ` @font-face{ font-family: DuckDuckGoPrivacyEssentials; - src: url(${ddgFont}); + src: url(${assets.regularFontUrl}); } @font-face{ font-family: DuckDuckGoPrivacyEssentialsBold; font-weight: bold; - src: url(${ddgFontBold}); + src: url(${assets.boldFontUrl}); } - `, - darkMode: { - background: ` + `; + regularFontFamily = 'DuckDuckGoPrivacyEssentials'; + boldFontFamily = 'DuckDuckGoPrivacyEssentialsBold'; + } + return { + fontStyle, + darkMode: { + background: ` background: #111111; `, - textFont: ` + textFont: ` color: rgba(255, 255, 255, 0.9); `, - buttonFont: ` + buttonFont: ` color: #111111; `, - linkFont: ` + linkFont: ` color: #7295F6; `, - buttonBackground: ` + buttonBackground: ` background: #5784FF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #557FF3; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #3969EF; `, - toggleButtonText: ` + toggleButtonText: ` color: #EEEEEE; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #5784FF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - lightMode: { - background: ` + } + }, + lightMode: { + background: ` background: #FFFFFF; `, - textFont: ` + textFont: ` color: #222222; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; `, - linkFont: ` + linkFont: ` color: #3969EF; `, - buttonBackground: ` + buttonBackground: ` background: #3969EF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #2B55CA; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #1E42A4; `, - toggleButtonText: ` + toggleButtonText: ` color: #666666; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #3969EF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - loginMode: { - buttonBackground: ` + } + }, + loginMode: { + buttonBackground: ` background: #666666; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; ` - }, - cancelMode: { - buttonBackground: ` + }, + cancelMode: { + buttonBackground: ` background: rgba(34, 34, 34, 0.1); `, - buttonFont: ` + buttonFont: ` color: #222222; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: rgba(0, 0, 0, 0.12); `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: rgba(0, 0, 0, 0.18); ` - }, - button: ` + }, + button: ` border-radius: 8px; padding: 11px 22px; @@ -4954,7 +5232,7 @@ border-color: #3969EF; border: none; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; font-size: 14px; position: relative; @@ -4962,7 +5240,7 @@ box-shadow: none; z-index: 2147483646; `, - circle: ` + circle: ` border-radius: 50%; width: 18px; height: 18px; @@ -4972,14 +5250,14 @@ top: -8px; right: -8px; `, - loginIcon: ` + loginIcon: ` position: absolute; top: -13px; right: -10px; height: 28px; width: 28px; `, - rectangle: ` + rectangle: ` width: 12px; height: 3px; background: #666666; @@ -4987,7 +5265,7 @@ top: 42.5%; margin: auto; `, - textBubble: ` + textBubble: ` background: #FFFFFF; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 16px; @@ -4998,9 +5276,9 @@ position: absolute; line-height: normal; `, - textBubbleWidth: 360, // Should match the width rule in textBubble - textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble - textArrow: ` + textBubbleWidth: 360, // Should match the width rule in textBubble + textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble + textArrow: ` display: inline-block; background: #FFFFFF; border: solid rgba(0, 0, 0, 0.1); @@ -5011,23 +5289,23 @@ position: relative; top: -9px; `, - arrowDefaultLocationPercent: 50, - hoverTextTitle: ` + arrowDefaultLocationPercent: 50, + hoverTextTitle: ` padding: 0px 12px 12px; margin-top: -5px; `, - hoverTextBody: ` - font-family: DuckDuckGoPrivacyEssentials; + hoverTextBody: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: auto; padding: 17px; text-align: left; `, - hoverContainer: ` + hoverContainer: ` padding-bottom: 10px; `, - buttonTextContainer: ` + buttonTextContainer: ` display: flex; flex-direction: row; align-items: center; @@ -5035,10 +5313,10 @@ padding: 0; margin: 0; `, - headerRow: ` + headerRow: ` `, - block: ` + block: ` box-sizing: border-box; border: 1px solid rgba(0,0,0,0.1); border-radius: 12px; @@ -5048,27 +5326,27 @@ display: flex; flex-direction: column; - font-family: DuckDuckGoPrivacyEssentials; + font-family: ${regularFontFamily}; line-height: 1; `, - youTubeDialogBlock: ` + youTubeDialogBlock: ` height: calc(100% - 30px); max-width: initial; min-height: initial; `, - imgRow: ` + imgRow: ` display: flex; flex-direction: column; margin: 20px 0px; `, - content: ` + content: ` display: flex; flex-direction: column; padding: 16px 0; flex: 1 1 1px; `, - feedbackLink: ` - font-family: DuckDuckGoPrivacyEssentials; + feedbackLink: ` + font-family: ${regularFontFamily}; font-style: normal; font-weight: 400; font-size: 12px; @@ -5076,13 +5354,13 @@ color: #ABABAB; text-decoration: none; `, - feedbackRow: ` + feedbackRow: ` height: 30px; display: flex; justify-content: flex-end; align-items: center; `, - titleBox: ` + titleBox: ` display: flex; padding: 12px; max-height: 44px; @@ -5091,8 +5369,8 @@ margin: 0; margin-bottom: 4px; `, - title: ` - font-family: DuckDuckGoPrivacyEssentials; + title: ` + font-family: ${regularFontFamily}; line-height: 1.4; font-size: 14px; margin: auto 10px; @@ -5104,7 +5382,7 @@ border: none; padding: 0; `, - buttonRow: ` + buttonRow: ` display: flex; height: 100% flex-direction: row; @@ -5112,8 +5390,8 @@ height: 100%; align-items: flex-start; `, - modalContentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + modalContentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; line-height: 21px; @@ -5122,8 +5400,8 @@ border: none; padding: 0px 32px; `, - modalContentText: ` - font-family: DuckDuckGoPrivacyEssentials; + modalContentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: 0px auto 14px; @@ -5131,7 +5409,7 @@ border: none; padding: 0; `, - modalButtonRow: ` + modalButtonRow: ` border: none; padding: 0; margin: auto; @@ -5140,17 +5418,17 @@ flex-direction: column; align-items: center; `, - modalButton: ` + modalButton: ` width: 100%; display: flex; justify-content: center; align-items: center; `, - modalIcon: ` + modalIcon: ` display: block; `, - contentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + contentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; margin: 20px auto 10px; @@ -5158,25 +5436,25 @@ text-align: center; margin-top: auto; `, - contentText: ` - font-family: DuckDuckGoPrivacyEssentials; + contentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; padding: 0px 40px; text-align: center; margin: 0 auto auto; `, - icon: ` + icon: ` height: 80px; width: 80px; margin: auto; `, - closeIcon: ` + closeIcon: ` height: 12px; width: 12px; margin: auto; `, - closeButton: ` + closeButton: ` display: flex; justify-content: center; align-items: center; @@ -5186,7 +5464,7 @@ background: transparent; cursor: pointer; `, - logo: ` + logo: ` flex-basis: 0%; min-width: 20px; height: 21px; @@ -5194,17 +5472,17 @@ padding: 0; margin: 0; `, - logoImg: ` + logoImg: ` height: 21px; width: 21px; `, - loadingImg: ` + loadingImg: ` display: block; margin: 0px 8px 0px 0px; height: 14px; width: 14px; `, - modal: ` + modal: ` width: 340px; padding: 0; margin: auto; @@ -5218,14 +5496,14 @@ border-radius: 12px; border: none; `, - modalContent: ` + modalContent: ` padding: 24px; display: flex; flex-direction: column; border: none; margin: 0; `, - overlay: ` + overlay: ` height: 100%; width: 100%; background-color: #666666; @@ -5238,7 +5516,7 @@ padding: 0; margin: 0; `, - modalContainer: ` + modalContainer: ` height: 100vh; width: 100vw; box-sizing: border-box; @@ -5249,16 +5527,16 @@ margin: 0; padding: 0; `, - headerLinkContainer: ` + headerLinkContainer: ` flex-basis: 100%; display: grid; justify-content: flex-end; `, - headerLink: ` + headerLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; text-decoration: none; cursor: pointer; min-width: 100px; @@ -5266,15 +5544,15 @@ float: right; display: none; `, - generalLink: ` + generalLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; cursor: pointer; text-decoration: none; `, - wrapperDiv: ` + wrapperDiv: ` display: inline-block; border: 0; padding: 0; @@ -5282,12 +5560,12 @@ max-width: 600px; min-height: 300px; `, - toggleButtonWrapper: ` + toggleButtonWrapper: ` display: flex; align-items: center; cursor: pointer; `, - toggleButton: ` + toggleButton: ` cursor: pointer; position: relative; width: 30px; @@ -5299,19 +5577,19 @@ background-color: transparent; text-align: left; `, - toggleButtonBg: ` + toggleButtonBg: ` right: 0; width: 30px; height: 16px; overflow: visible; border-radius: 10px; `, - toggleButtonText: ` + toggleButtonText: ` display: inline-block; margin: 0 0 0 7px; padding: 0; `, - toggleButtonKnob: ` + toggleButtonKnob: ` position: absolute; display: inline-block; width: 14px; @@ -5322,15 +5600,15 @@ top: calc(50% - 14px/2 - 1px); box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.05), 0px 1px 1px rgba(0, 0, 0, 0.1); `, - toggleButtonKnobState: { - active: ` + toggleButtonKnobState: { + active: ` right: 1px; `, - inactive: ` + inactive: ` left: 1px; ` - }, - placeholderWrapperDiv: ` + }, + placeholderWrapperDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5340,7 +5618,7 @@ min-height: 300px; margin: auto; `, - youTubeWrapperDiv: ` + youTubeWrapperDiv: ` position: relative; overflow: hidden; max-width: initial; @@ -5348,7 +5626,7 @@ min-height: 300px; height: 100%; `, - youTubeDialogDiv: ` + youTubeDialogDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5356,14 +5634,14 @@ min-height: initial; height: calc(100% - 30px); `, - youTubeDialogBottomRow: ` + youTubeDialogBottomRow: ` display: flex; flex-direction: column; align-items: center; justify-content: flex-end; margin-top: auto; `, - youTubePlaceholder: ` + youTubePlaceholder: ` display: flex; flex-direction: column; justify-content: flex-start; @@ -5372,7 +5650,7 @@ height: 100%; background: rgba(45, 45, 45, 0.8); `, - youTubePreviewWrapperImg: ` + youTubePreviewWrapperImg: ` position: absolute; display: flex; justify-content: center; @@ -5380,20 +5658,20 @@ width: 100%; height: 100%; `, - youTubePreviewImg: ` + youTubePreviewImg: ` min-width: 100%; min-height: 100%; height: auto; `, - youTubeTopSection: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + youTubeTopSection: ` + font-family: ${boldFontFamily}; flex: 1; display: flex; justify-content: space-between; position: relative; padding: 18px 12px 0; `, - youTubeTitle: ` + youTubeTitle: ` font-size: 14px; font-weight: bold; line-height: 14px; @@ -5405,13 +5683,13 @@ text-overflow: ellipsis; box-sizing: border-box; `, - youTubePlayButtonRow: ` + youTubePlayButtonRow: ` flex: 2; display: flex; align-items: center; justify-content: center; `, - youTubePlayButton: ` + youTubePlayButton: ` display: flex; justify-content: center; align-items: center; @@ -5420,7 +5698,7 @@ padding: 0px 24px; border-radius: 8px; `, - youTubePreviewToggleRow: ` + youTubePreviewToggleRow: ` flex: 1; display: flex; flex-direction: column; @@ -5428,15 +5706,19 @@ align-items: center; padding: 0 12px 18px; `, - youTubePreviewToggleText: ` + youTubePreviewToggleText: ` color: #EEEEEE; font-weight: 400; `, - youTubePreviewInfoText: ` + youTubePreviewInfoText: ` color: #ABABAB; ` - }; + } + } + /** + * @param {string} locale UI locale + */ function getConfig (locale) { const locales = JSON.parse(localesJSON); const fbStrings = locales[locale]['facebook.json']; @@ -5873,6 +6155,7 @@ // @see {getConfig} let config = null; let sharedStrings = null; + let styles = null; // TODO: Remove these redundant data structures and refactor the related code. // There should be no need to have the entity configuration stored in two @@ -6335,6 +6618,16 @@ ]; elementToReplace.style.setProperty('display', 'none', 'important'); + // When iframes are blocked by the declarativeNetRequest API, they are + // collapsed (hidden) automatically. Unfortunately however, there's a bug + // that stops them from being uncollapsed (shown again) if they are removed + // from the DOM after they are collapsed. As a workaround, have the iframe + // load a benign data URI, so that it's uncollapsed, before removing it from + // the DOM. See https://crbug.com/1428971 + const originalSrc = elementToReplace.src; + elementToReplace.src = + 'data:text/plain;charset=utf-8;base64,' + btoa('https://crbug.com/1428971'); + // Add the placeholder element to the page. elementToReplace.parentElement.insertBefore( placeholderElement, elementToReplace @@ -6354,6 +6647,7 @@ // placeholder) can finally be removed from the DOM. elementToReplace.remove(); elementToReplace.style.setProperty('display', ...originalDisplay); + elementToReplace.src = originalSrc; }); } @@ -6744,10 +7038,10 @@ * Creates an anchor element with no destination. It is expected that a click * handler is added to the element later. * @param {string} linkText - * @param {displayMode} [mode='lightMode'] + * @param {displayMode} mode * @returns {HTMLAnchorElement} */ - function makeTextButton (linkText, mode) { + function makeTextButton (linkText, mode = 'lightMode') { const linkElement = document.createElement('a'); linkElement.style.cssText = styles.headerLink + styles[mode].linkFont; linkElement.textContent = linkText; @@ -7471,6 +7765,8 @@ const localizedConfig = getConfig(locale); config = localizedConfig.config; sharedStrings = localizedConfig.sharedStrings; + // update styles if asset config was sent + styles = getStyles(this.assetConfig); for (const entity of Object.keys(config)) { // Strip config entities that are first-party, or aren't enabled in the @@ -7539,6 +7835,16 @@ } await afterPageLoad; + // On some websites, the "ddg-ctp-ready" event is occasionally + // dispatched too early, before the listener is ready to receive it. + // To counter that, catch "ddg-ctp-surrogate-load" events dispatched + // _after_ page, so the "ddg-ctp-ready" event can be dispatched again. + window.addEventListener( + 'ddg-ctp-surrogate-load', () => { + originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready')); + } + ); + // Then wait for any in-progress element replacements, before letting // the surrogate scripts know to start. window.setTimeout(() => { @@ -9528,7 +9834,7 @@ title: 'Tired of targeted YouTube ads and recommendations?' }, videoOverlaySubtitle: { - title: 'Duck Player provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' + title: 'provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' }, videoButtonOpen: { title: 'Watch in Duck Player' @@ -9559,6 +9865,75 @@ } }; + /** + * The following code is originally from https://github.com/mozilla-extensions/secure-proxy/blob/db4d1b0e2bfe0abae416bf04241916f9e4768fd2/src/commons/template.js + */ + class Template { + constructor (strings, values) { + this.values = values; + this.strings = strings; + } + + /** + * Escapes any occurrences of &, ", <, > or / with XML entities. + * + * @param {string} str + * The string to escape. + * @return {string} The escaped string. + */ + escapeXML (str) { + const replacements = { + '&': '&', + '"': '"', + "'": ''', + '<': '<', + '>': '>', + '/': '/' + }; + return String(str).replace(/[&"'<>/]/g, m => replacements[m]) + } + + potentiallyEscape (value) { + if (typeof value === 'object') { + if (value instanceof Array) { + return value.map(val => this.potentiallyEscape(val)).join('') + } + + // If we are an escaped template let join call toString on it + if (value instanceof Template) { + return value + } + + throw new Error('Unknown object to escape') + } + return this.escapeXML(value) + } + + toString () { + const result = []; + + for (const [i, string] of this.strings.entries()) { + result.push(string); + if (i < this.values.length) { + result.push(this.potentiallyEscape(this.values[i])); + } + } + return result.join('') + } + } + + function html (strings, ...values) { + return new Template(strings, values) + } + + /** + * @param {string} string + * @return {Template} + */ + function trustedUnsafe (string) { + return html([string]) + } + const IconOverlay = { /** * Special class used for the overlay hover. For hovering, we use a @@ -9597,20 +9972,20 @@ overlayElement.setAttribute('class', 'ddg-overlay' + (extraClass ? ' ' + extraClass : '')); overlayElement.setAttribute('data-size', size); - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax); + overlayElement.innerHTML = html`
- ${dax} + ${svgIcon}
${i18n.t('playText')}
-
`; + `.toString(); overlayElement.querySelector('a.ddg-play-privately')?.setAttribute('href', href); - overlayElement.querySelector('a.ddg-play-privately')?.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); @@ -9941,12 +10316,15 @@ createOverlay () { const overlayElement = document.createElement('div'); overlayElement.classList.add('ddg-video-player-overlay'); - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax); + overlayElement.innerHTML = html`
-
${dax}
+
${svgIcon}
${i18n.t('videoOverlayTitle')}
-
${i18n.t('videoOverlaySubtitle')}
+
+ ${i18n.t('playText')} ${i18n.t('videoOverlaySubtitle')} +
${i18n.t('videoButtonOpen')} @@ -9957,7 +10335,7 @@
- `; + `.toString(); /** * Set the link * @type {string} @@ -10725,7 +11103,7 @@ if (this.platform.name === 'windows') { const context = new MessagingContext({ context: 'contentScopeScripts', - env: this._args.debug ? 'development' : 'production', + env: this.isDebug ? 'development' : 'production', featureName: this.name }); const config = new WindowsMessagingConfig({ @@ -10812,12 +11190,14 @@ /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** @@ -10895,6 +11275,7 @@ function generateConfig (data, userList) { const topLevelUrl = getTopLevelURL(); + const trackerLookup = {"org":{"cdn77":{"rsc":{"1666210260":1}},"adsrvr":1,"ampproject":1,"browser-update":1,"flowplayer":1,"privacy-center":1,"webvisor":1,"framasoft":1,"do-not-tracker":1,"trackersimulator":1},"io":{"1dmp":1,"1rx":1,"4dex":1,"adnami":1,"aidata":1,"arcspire":1,"bidr":1,"branch":1,"center":1,"concert":1,"connectad":1,"cordial":1,"dcmn":1,"extole":1,"getblue":1,"hbrd":1,"imbox":1,"instana":1,"karte":1,"lytics":1,"marchex":1,"mediago":1,"mrf":1,"myfidevs":1,"narrative":1,"ntv":1,"optad360":1,"oracleinfinity":1,"oribi":1,"p-n":1,"personalizer":1,"pghub":1,"piano":1,"powr":1,"pzz":1,"searchspring":1,"segment":1,"siteimproveanalytics":1,"sjv":1,"sspinc":1,"t13":1,"webgains":1,"wovn":1,"yellowblue":1,"zprk":1,"reviews":1,"appconsent":1,"leadsmonitor":1},"com":{"2020mustang":1,"33across":1,"360yield":1,"3lift":1,"4dsply":1,"4jnzhl0d0":1,"4strokemedia":1,"5d2d04464c":1,"a-mx":1,"a2z":1,"aamsitecertifier":1,"absorbingband":1,"abstractedauthority":1,"abtasty":1,"acexedge":1,"acidpigs":1,"acsbapp":1,"acuityplatform":1,"ad-score":1,"ad-stir":1,"adalyser":1,"adapf":1,"adara":1,"adblade":1,"addthis":1,"addtoany":1,"adelixir":1,"adentifi":1,"adextrem":1,"adgrx":1,"adhese":1,"adition":1,"adkernel":1,"adlightning":1,"adlooxtracking":1,"admanmedia":1,"admedo":1,"adnium":1,"adnxs":1,"adobedtm":1,"adotmob":1,"adpone":1,"adpushup":1,"adroll":1,"adrta":1,"ads-twitter":1,"ads3-adnow":1,"adsafeprotected":1,"adstanding":1,"adswizz":1,"adsymptotic":1,"adtdp":1,"adtechus":1,"adtelligent":1,"adthrive":1,"adtlgc":1,"adtng":1,"adultfriendfinder":1,"advangelists":1,"adventive":1,"advertising":1,"aegpresents":1,"affinity":1,"affirm":1,"agilone":1,"agkn":1,"aimbase":1,"albacross":1,"alcmpn":1,"alexametrics":1,"alicdn":1,"alikeaddition":1,"aliveachiever":1,"aliyuncs":1,"alluringbucket":1,"aloofvest":1,"amazon-adsystem":1,"amazon":1,"amplitude":1,"analytics-egain":1,"aniview":1,"anymind360":1,"amazonaws":{"ap-southeast-2":1,"elb":{"eu-west-2":{"collect-prd-alb-539115803":1},"us-east-1":{"data-allstate-com-715826933":1,"prod-lb-8-1772099769":1,"proxy-mycigna-prod-678433465":1,"www-u45-pnc-com-902993410":1,"www-u46-pnc-com-13593657":1},"eu-west-1":{"devservicesalb-471015105":1,"petfre-content-1201188928":1},"us-east-2":{"elbpiwik-public-1781721271":1},"eu-central-1":{"prod-lb-6-388533732":1,"prod-lb-7-718125029":1,"prod-pub-alb-654989386":1}},"us-east-2":{"s3":{"hb-gretsch-talk":1,"hb-jetpunk":1,"hb-obv2":1}},"eu-central-1":{"s3":{"headless-ssr-prod-bucket":1}}},"app-us1":1,"appboycdn":1,"appdynamics":1,"aralego":1,"arkoselabs":1,"aswpsdkus":1,"atemda":1,"att":1,"attentivemobile":1,"attractionbanana":1,"audioeye":1,"audrte":1,"automaticside":1,"avanser":1,"avmws":1,"aweber":1,"aweprt":1,"azure":1,"b0e8":1,"bagbeam":1,"bandborder":1,"batch":1,"bawdybalance":1,"bc0a":1,"bdstatic":1,"bedsberry":1,"beginnerpancake":1,"benchmarkemail":1,"betweendigital":1,"bfmio":1,"bidderstack":1,"bidtheatre":1,"bimbolive":1,"bing":1,"bizographics":1,"bizrate":1,"bkrtx":1,"blismedia":1,"blogherads":1,"bluecava":1,"bluekai":1,"boatwizard":1,"boilingcredit":1,"boldchat":1,"booking":1,"borderfree":1,"bounceexchange":1,"brainlyads":1,"brand-display":1,"brandmetrics":1,"brealtime":1,"breinify":1,"brightedge":1,"brightfunnel":1,"brightspotcdn":1,"btloader":1,"btstatic":1,"bttrack":1,"btttag":1,"butterbulb":1,"buzzoola":1,"byside":1,"cabnnr":1,"calculatorstatement":1,"callrail":1,"calltracks":1,"capablecup":1,"captcha-delivery":1,"carpentercomparison":1,"cartstack":1,"carvecakes":1,"casalemedia":1,"cdn-btsg":1,"cdnwidget":1,"channeladvisor":1,"chartbeat":1,"chatango":1,"chaturbate":1,"cheqzone":1,"cherriescare":1,"chickensstation":1,"childlikecrowd":1,"childlikeform":1,"cintnetworks":1,"circlelevel":1,"civiccomputing":1,"ck-ie":1,"clcktrax":1,"clearbit":1,"clearbitjs":1,"clickagy":1,"clickcease":1,"clickcertain":1,"clicktripz":1,"clientgear":1,"clksite":1,"cloudflare":1,"cloudflareinsights":1,"cloudflarestream":1,"cloudmaestro":1,"cobaltgroup":1,"cobrowser":1,"cognitivlabs":1,"colossusssp":1,"comm100":1,"googleapis":{"commondatastorage":1,"storage":1},"company-target":1,"condenastdigital":1,"confusedcart":1,"connatix":1,"consentframework":1,"contextweb":1,"conversionruler":1,"convertkit":1,"convertlanguage":1,"cookieinformation":1,"cookiepro":1,"coveo":1,"cpmstar":1,"cquotient":1,"crabbychin":1,"crazyegg":1,"creative-serving":1,"creativecdn":1,"criteo":1,"crowdedmass":1,"crowdriff":1,"crownpeak":1,"crsspxl":1,"ctnsnet":1,"cubchannel":1,"cudasvc":1,"cuddlethehyena":1,"cumbersomecarpenter":1,"curalate":1,"curvedhoney":1,"cutechin":1,"cxense":1,"dailymotion":1,"damdoor":1,"dampdock":1,"dapperfloor":1,"datadoghq-browser-agent":1,"decisivebase":1,"deepintent":1,"defybrick":1,"delivra":1,"demandbase":1,"detectdiscovery":1,"devilishdinner":1,"dimelochat":1,"discreetfield":1,"disqus":1,"dmpxs":1,"dockdigestion":1,"dollardelta":1,"dotomi":1,"doubleverify":1,"drainpaste":1,"dramaticdirection":1,"driftt":1,"dtscdn":1,"dtscout":1,"dwin1":1,"dynamics":1,"dynamicyield":1,"dynatrace":1,"dyntrk":1,"ebaystatic":1,"ecal":1,"eccmp":1,"elasticchange":1,"elfsight":1,"elitrack":1,"eloqua":1,"en25":1,"encouragingthread":1,"ensighten":1,"enviousshape":1,"eqads":1,"ero-advertising":1,"esputnik":1,"evergage":1,"evgnet":1,"exdynsrv":1,"exelator":1,"exoclick":1,"exosrv":1,"expansioneggnog":1,"expertrec":1,"exponea":1,"exponential":1,"extole":1,"ezodn":1,"ezoic":1,"ezoiccdn":1,"facebook":1,"fadewaves":1,"fallaciousfifth":1,"farmergoldfish":1,"fastly-insights":1,"fearlessfaucet":1,"fiftyt":1,"financefear":1,"fitanalytics":1,"five9":1,"fksnk":1,"flashtalking":1,"flipp":1,"floweryflavor":1,"flutteringfireman":1,"flux-cdn":1,"fomo":1,"foresee":1,"forter":1,"fortunatemark":1,"fouanalytics":1,"fox":1,"fqtag":1,"frailfruit":1,"freezingbuilding":1,"fronttoad":1,"fullstory":1,"functionalfeather":1,"fuzzybasketball":1,"gammamaximum":1,"gbqofs":1,"geetest":1,"geistm":1,"geniusmonkey":1,"geoip-js":1,"getbread":1,"getcandid":1,"getclicky":1,"getdrip":1,"getelevar":1,"getpublica":1,"getrockerbox":1,"getshogun":1,"getsitecontrol":1,"glassdoor":1,"gloriousbeef":1,"godpvqnszo":1,"gondolagnome":1,"google-analytics":1,"google":1,"googleadservices":1,"googlehosted":1,"googleoptimize":1,"googlesyndication":1,"googletagmanager":1,"googletagservices":1,"govx":1,"greylabeldelivery":1,"groovehq":1,"gstatic":1,"guarantee-cdn":1,"guiltlessbasketball":1,"gumgum":1,"haltingbadge":1,"hammerhearing":1,"handsomelyhealth":1,"hawksearch":1,"heapanalytics":1,"hellobar":1,"hiconversion":1,"highwebmedia":1,"histats":1,"hlserve":1,"hocgeese":1,"hollowafterthought":1,"honorableland":1,"hotjar":1,"hp":1,"hs-banner":1,"htlbid":1,"htplayground":1,"hubspot":1,"iadvize":1,"ib-ibi":1,"id5-sync":1,"iesnare":1,"igodigital":1,"iheart":1,"iljmp":1,"illiweb":1,"impactcdn":1,"impactradius-event":1,"impactradius-go":1,"impossibleexpansion":1,"impressionmonster":1,"improvedcontactform":1,"improvedigital":1,"imrworldwide":1,"indexww":1,"infolinks":1,"infusionsoft":1,"inmobi":1,"inmoment":1,"inq":1,"inside-graph":1,"instagram":1,"intentiq":1,"intergient":1,"investingchannel":1,"invocacdn":1,"iplsc":1,"ipredictive":1,"iteratehq":1,"ivitrack":1,"j93557g":1,"jaavnacsdw":1,"jimstatic":1,"journity":1,"js7k":1,"juicyads":1,"justanswer":1,"justpremium":1,"kakao":1,"kampyle":1,"kargo":1,"kissmetrics":1,"klarnaservices":1,"klaviyo":1,"knottyswing":1,"kount":1,"krushmedia":1,"ktkjmp":1,"kxcdn":1,"ladesk":1,"ladsp":1,"laughablelizards":1,"leadsrx":1,"lendingtree":1,"levexis":1,"liadm":1,"licdn":1,"lightboxcdn":1,"lijit":1,"linkedin":1,"linksynergy":1,"list-manage":1,"listrakbi":1,"livechatinc":1,"livejasmin":1,"localytics":1,"loggly":1,"loop11":1,"lovelydrum":1,"luckyorange":1,"lunchroomlock":1,"maddeningpowder":1,"mailchimp":1,"mailchimpapp":1,"mailerlite":1,"maillist-manage":1,"marinsm":1,"marketiq":1,"marketo":1,"marriedbelief":1,"matheranalytics":1,"mathtag":1,"maxmind":1,"mczbf":1,"measlymiddle":1,"medallia":1,"media6degrees":1,"mediacategory":1,"mediavine":1,"mediawallahscript":1,"medtargetsystem":1,"megpxs":1,"metricode":1,"metricswpsh":1,"mfadsrvr":1,"mgid":1,"micpn":1,"microadinc":1,"minutemedia-prebid":1,"minutemediaservices":1,"mixpo":1,"mktoresp":1,"mktoweb":1,"ml314":1,"moatads":1,"mobtrakk":1,"monsido":1,"mookie1":1,"mountain":1,"mouseflow":1,"mpeasylink":1,"mql5":1,"mrtnsvr":1,"murdoog":1,"mxpnl":1,"mybestpro":1,"myfinance":1,"myregistry":1,"nappyattack":1,"navistechnologies":1,"neodatagroup":1,"nervoussummer":1,"newrelic":1,"newscgp":1,"nextdoor":1,"ninthdecimal":1,"nitrocdn":1,"noibu":1,"nondescriptnote":1,"nosto":1,"npttech":1,"nuance":1,"nxsttv":1,"omappapi":1,"omnisnippet1":1,"omnisrc":1,"omnitagjs":1,"oneall":1,"onesignal":1,"onetag-sys":1,"oo-syringe":1,"ooyala":1,"opecloud":1,"opentext":1,"opera":1,"opmnstr":1,"optimicdn":1,"optinmonster":1,"optmnstr":1,"optmstr":1,"optnmnstr":1,"optnmstr":1,"oraclecloud":1,"osano":1,"otm-r":1,"outbrain":1,"overconfidentfood":1,"ownlocal":1,"pamelarandom":1,"panickypancake":1,"panoramicplane":1,"parastorage":1,"pardot":1,"parsely":1,"partplanes":1,"patreon":1,"paypal":1,"pbstck":1,"pcmag":1,"peerius":1,"perfdrive":1,"perfectmarket":1,"permutive":1,"picreel":1,"pinimg":1,"pippio":1,"piwikpro":1,"pixlee":1,"pleasantpump":1,"plotrabbit":1,"pluckypocket":1,"pocketfaucet":1,"possibleboats":1,"postaffiliatepro":1,"postrelease":1,"potatoinvention":1,"prepareplanes":1,"pricespider":1,"pricklydebt":1,"profusesupport":1,"proofpoint":1,"protoawe":1,"providesupport":1,"pswec":1,"psyma":1,"ptengine":1,"publir":1,"pubmatic":1,"pubmine":1,"pubnation":1,"puffypurpose":1,"qualaroo":1,"qualtrics":1,"quantcast":1,"quantserve":1,"quantummetric":1,"quietknowledge":1,"quizzicalzephyr":1,"quora":1,"r42tag":1,"railwayreason":1,"rakuten":1,"rambunctiousflock":1,"rangeplayground":1,"realsrv":1,"rebelswing":1,"reconditerake":1,"reconditerespect":1,"recruitics":1,"reddit":1,"redditstatic":1,"rehabilitatereason":1,"reson8":1,"resonantrock":1,"responsiveads":1,"restrainstorm":1,"retargetly":1,"revcontent":1,"rezync":1,"rfihub":1,"rhetoricalloss":1,"richaudience":1,"righteouscrayon":1,"rightfulfall":1,"riotgames":1,"rkdms":1,"rlcdn":1,"rmtag":1,"rncdn5":1,"rnengage":1,"rogersmedia":1,"rokt":1,"route":1,"rubiconproject":1,"s-onetag":1,"saambaa":1,"sablesong":1,"sail-horizon":1,"salesforceliveagent":1,"samestretch":1,"satisfycork":1,"savoryorange":1,"scarabresearch":1,"scaredsnakes":1,"scarfsmash":1,"scatteredstream":1,"scene7":1,"scholarlyiq":1,"scintillatingsilver":1,"scorecardresearch":1,"screechingstove":1,"screenpopper":1,"sddan":1,"sdiapi":1,"seatsmoke":1,"securedvisit":1,"seedtag":1,"sefsdvc":1,"segment":1,"sekindo":1,"selectivesummer":1,"selfishsnake":1,"servebom":1,"servedbyadbutler":1,"servenobid":1,"serverbid":1,"serving-sys":1,"shakegoldfish":1,"shappify":1,"shareaholic":1,"sharethis":1,"sharethrough":1,"shopifyapps":1,"shopperapproved":1,"shrillspoon":1,"sibautomation":1,"sicksmash":1,"sift":1,"siftscience":1,"signifyd":1,"siteimprove":1,"siteimproveanalytics":1,"sitescout":1,"skillfuldrop":1,"sli-spark":1,"slickstream":1,"slopesoap":1,"smadex":1,"smartadserver":1,"smashquartz":1,"smashsurprise":1,"smg":1,"smilewanted":1,"smoggysnakes":1,"snapchat":1,"snapkit":1,"snigelweb":1,"socdm":1,"sojern":1,"songsterritory":1,"sonobi":1,"speedcurve":1,"sphereup":1,"spiceworks":1,"spookyexchange":1,"spookyskate":1,"spookysleet":1,"sportradar":1,"sportradarserving":1,"sportslocalmedia":1,"spotxchange":1,"springserve":1,"srvmath":1,"stackadapt":1,"stakingsmile":1,"statcounter":1,"steadfastseat":1,"steadfastsound":1,"steadfastsystem":1,"steelhousemedia":1,"steepsquirrel":1,"stereoproxy":1,"stereotypedsugar":1,"stickyadstv":1,"stiffgame":1,"straightnest":1,"stripchat":1,"stupendoussleet":1,"stupendoussnow":1,"stupidscene":1,"sulkycook":1,"sumo":1,"sumologic":1,"sundaysky":1,"superficialeyes":1,"superficialsquare":1,"survicate":1,"svonm":1,"symantec":1,"taboola":1,"tagcommander":1,"tailtarget":1,"talkable":1,"taobao":1,"tapad":1,"taptapnetworks":1,"taskanalytics":1,"tealiumiq":1,"technoratimedia":1,"techtarget":1,"tediousticket":1,"teenytinyshirt":1,"tendertest":1,"the-ozone-project":1,"theadex":1,"themoneytizer":1,"theplatform":1,"thestar":1,"thomastorch":1,"threetruck":1,"thrtle":1,"tidaltv":1,"tidiochat":1,"tiktok":1,"tinypass":1,"tiqcdn":1,"tiresomethunder":1,"trackjs":1,"trafficjunky":1,"travelaudience":1,"treasuredata":1,"tremorhub":1,"trendemon":1,"tribalfusion":1,"trovit":1,"trueleadid":1,"truoptik":1,"truste":1,"trustedsite":1,"trustpilot":1,"tsyndicate":1,"tubemogul":1,"turn":1,"tvpixel":1,"tvsquared":1,"tweakwise":1,"twitter":1,"tynt":1,"typicalteeth":1,"u5e":1,"ubembed":1,"uidapi":1,"ultraoranges":1,"unbecominglamp":1,"unbxdapi":1,"undertone":1,"uninterestedquarter":1,"unpkg":1,"unrulymedia":1,"unwieldyhealth":1,"unwieldyplastic":1,"upsellit":1,"urbanairship":1,"usabilla":1,"usbrowserspeed":1,"usemessages":1,"userreport":1,"uservoice":1,"valuecommerce":1,"vengefulgrass":1,"vidazoo":1,"videoplayerhub":1,"vidoomy":1,"viglink":1,"visualwebsiteoptimizer":1,"vivaclix":1,"vk":1,"vlitag":1,"vocento":1,"voicefive":1,"volatilevessel":1,"voraciousgrip":1,"voxmedia":1,"vrtcal":1,"w3counter":1,"walkme":1,"warmafterthought":1,"warmquiver":1,"webcontentassessor":1,"webengage":1,"webeyez":1,"webflow":1,"webtraxs":1,"webtrends-optimize":1,"webtrends":1,"wgplayer":1,"wisepops":1,"worldoftulo":1,"wpadmngr":1,"wpshsdk":1,"wpushsdk":1,"wsod":1,"wt-safetag":1,"wysistat":1,"xg4ken":1,"xiti":1,"xlirdr":1,"xlivrdr":1,"xnxx-cdn":1,"y-track":1,"yahoo":1,"yandex":1,"yieldmo":1,"yieldoptimizer":1,"yimg":1,"yotpo":1,"yottaa":1,"youtube-nocookie":1,"youtube":1,"zatnoh":1,"zemanta":1,"zendesk":1,"zeotap":1,"zeronaught":1,"zestycrime":1,"zonos":1,"zoominfo":1,"zopim":1,"adnxs-simple":1,"createsend1":1,"adventori":1,"facil-iti":1,"provenexpert":1,"veoxa":1,"getflowbox":1,"parchedsofa":1,"adtraction":1,"bannerflow":1,"aboardamusement":1,"absorbingcorn":1,"abstractedamount":1,"actoramusement":1,"actuallysnake":1,"adorableanger":1,"agreeabletouch":1,"aheadday":1,"ancientact":1,"annoyedairport":1,"annoyingacoustics":1,"aquaticowl":1,"aspiringattempt":1,"audioarctic":1,"awarealley":1,"awesomeagreement":1,"awzbijw":1,"basketballbelieve":1,"begintrain":1,"bestboundary":1,"blushingbeast":1,"boredcrown":1,"breadbalance":1,"breakfastboat":1,"bulbbait":1,"burnbubble":1,"bustlingbath":1,"callousbrake":1,"calmcactus":1,"capriciouscorn":1,"caringcast":1,"catschickens":1,"causecherry":1,"chunkycactus":1,"cloisteredcord":1,"closedcows":1,"colossalclouds":1,"colossalcoat":1,"comfortablecheese":1,"conditioncrush":1,"consciouscheese":1,"consciousdirt":1,"coverapparatus":1,"cratecamera":1,"critictruck":1,"curvycry":1,"cushionpig":1,"damageddistance":1,"debonairdust":1,"decisivedrawer":1,"decisiveducks":1,"detailedkitten":1,"diplomahawaii":1,"dk4ywix":1,"dq95d35":1,"energeticladybug":1,"enormousearth":1,"evanescentedge":1,"fadedsnow":1,"fancyactivity":1,"farshake":1,"fastenfather":1,"fatcoil":1,"faultycanvas":1,"firstfrogs":1,"flimsycircle":1,"flimsythought":1,"friendwool":1,"fumblingform":1,"futuristicfifth":1,"giddycoat":1,"giraffepiano":1,"glisteningguide":1,"grayreceipt":1,"greasysquare":1,"grouchypush":1,"haltinggold":1,"handyfield":1,"handyfireman":1,"hearthorn":1,"historicalbeam":1,"horsenectar":1,"hystericalcloth":1,"impulsejewel":1,"incompetentjoke":1,"internalsink":1,"lameletters":1,"livelumber":1,"livelylaugh":1,"lorenzourban":1,"lumpylumber":1,"maliciousmusic":1,"meatydime":1,"memorizeneck":1,"mightyspiders":1,"mixedreading":1,"modularmental":1,"motionlessbag":1,"movemeal":1,"nondescriptcrowd":1,"nostalgicneed":1,"nuttyorganization":1,"optimallimit":1,"outstandingincome":1,"outstandingsnails":1,"panickycurtain":1,"petiteumbrella":1,"placidperson":1,"plantdigestion":1,"punyplant":1,"rabbitbreath":1,"rabbitrifle":1,"raintwig":1,"rainyhand":1,"rainyrule":1,"rangecake":1,"raresummer":1,"readymoon":1,"rebelsubway":1,"receptivereaction":1,"regularplants":1,"repeatsweater":1,"replaceroute":1,"resonantbrush":1,"respectrain":1,"richstring":1,"roofrelation":1,"rusticprice":1,"scaredcomfort":1,"scaredsnake":1,"scientificshirt":1,"scintillatingscissors":1,"screechingfurniture":1,"seashoresociety":1,"secretturtle":1,"shakysurprise":1,"shallowblade":1,"shesubscriptions":1,"shockingship":1,"sillyscrew":1,"sincerebuffalo":1,"sinceresubstance":1,"singroot":1,"sixscissors":1,"soggysponge":1,"somberscarecrow":1,"sordidsmile":1,"sortsail":1,"sortsummer":1,"spellsalsa":1,"spotlessstamp":1,"spottednoise":1,"stalesummer":1,"steadycopper":1,"stepplane":1,"strangesink":1,"stretchsister":1,"strivesidewalk":1,"superficialspring":1,"swellstocking":1,"synonymousrule":1,"tangyamount":1,"tastelesstrees":1,"teenytinycellar":1,"teenytinytongue":1,"terriblethumb":1,"terrifictooth":1,"thirdrespect":1,"ticketaunt":1,"tremendousplastic":1,"troubledtail":1,"typicalairplane":1,"ubiquitousyard":1,"unbecominghall":1,"uncoveredexpert":1,"unequalbrake":1,"unknowncrate":1,"untidyrice":1,"unusedstone":1,"venusgloria":1,"verdantanswer":1,"verseballs":1,"wearbasin":1,"cautiouscredit":1,"confesschairs":1,"chinsnakes":1,"wellgroomedhydrant":1,"heavyplayground":1,"bravecalculator":1,"workoperation":1,"secondhandfall":1,"unablehope":1,"tastelesstrucks":1,"losslace":1,"barbarousbase":1,"supportwaves":1,"protestcopy":1,"automaticturkey":1,"stretchsquirrel":1,"equablekettle":1,"discreetquarter":1,"peacefullimit":1,"gulliblegrip":1,"swelteringsleep":1,"muteknife":1,"aliasanvil":1,"operationchicken":1,"courageousbaby":1,"flowerstreatment":1,"scissorsstatement":1,"furryfork":1,"synonymoussticks":1,"deerbeginner":1,"rhetoricalveil":1,"farsnails":1,"kaputquill":1,"digestiondrawer":1,"meltmilk":1,"endurablebulb":1,"sugarfriction":1,"combcompetition":1,"stakingshock":1,"stretchsneeze":1,"sinkbooks":1,"brotherslocket":1,"cautiouscamera":1,"materialparcel":1,"inputicicle":1,"chargecracker":1,"fewjuice":1,"tumbleicicle":1,"serpentshampoo":1,"nutritiousbean":1,"scrapesleep":1,"bleachbubble":1,"longingtrees":1,"leftliquid":1,"handsomehose":1,"powerfulcopper":1,"painstakingpickle":1,"swankysquare":1,"soundstocking":1,"disagreeabledrop":1,"cushiondrum":1,"ruralrobin":1,"gorgeousedge":1,"strivesquirrel":1,"currentcollar":1,"combativecar":1,"ambiguousafternoon":1,"harborcaption":1,"blushingbread":1,"suggestionbridge":1,"spectacularstamp":1,"skisofa":1,"predictplate":1,"shakyseat":1,"priceypies":1,"livelyreward":1,"stealsteel":1,"shiveringspot":1,"memorizematch":1,"knitstamp":1,"bushesbag":1,"mundanenail":1,"coldbalance":1,"shapecomb":1,"shiverscissors":1,"broadborder":1,"quirkysugar":1,"stingyspoon":1,"billowybelief":1,"crookedcreature":1,"acceptableauthority":1,"sadloaf":1,"separatesort":1,"pailpatch":1,"scribblestring":1,"exhibitsneeze":1,"largebrass":1,"combcattle":1,"materialisticmoon":1,"fixedfold":1,"restructureinvention":1,"scaredstomach":1,"cautiouscherries":1,"tritebadge":1,"motionflowers":1,"ballsbanana":1,"meddleplant":1,"simulateswing":1,"marketspiders":1,"grumpydime":1,"neatshade":1,"samplesamba":1,"samesticks":1,"buttonladybug":1,"mentorsticks":1,"scaredsong":1,"annoyingclover":1,"grainmass":1,"tempertrick":1,"quizzicalpartner":1,"franticroof":1,"cattlecommittee":1,"tangycover":1,"looseloaf":1,"psychedelicarithmetic":1,"radiateprose":1,"shamerain":1,"cleanhaircut":1,"badgevolcano":1,"laboredlocket":1,"zipperxray":1,"stingycrush":1,"sixauthority":1,"thinkitten":1,"strokesystem":1,"hatefulrequest":1},"net":{"2mdn":1,"2o7":1,"incapdns":{"x":{"3exvfbh":1,"5t48cjc":1,"7xjpy4d":1,"dzm868l":1,"ttk8bbo":1}},"3gl":1,"a-mo":1,"acint":1,"adform":1,"adhigh":1,"admixer":1,"adobedc":1,"adspeed":1,"azureedge":{"adv-cloudfilse":1,"afw-static":1,"bayleys-pri-cdn-endpoint":1,"cdne-nxtevo-prd01-ms":1,"discountcodeexpress":1,"fp-cdn":1,"lefigaro":1,"ocpd-content":1,"sdtagging":1,"trenord-europe-trenord-endpoint-prd":1},"adverticum":1,"edgekey":{"akamai-111035":1,"com":{"alicdn":1,"ebay":1,"mtvnservices":1,"nbcuni":1,"nintendo":1,"oneindia":1,"scene7":1,"turner":1,"ziffdavis":1,"ziffdavisinternational":1},"ame":1,"au":1,"br":1,"ca":1,"com-v1":1,"com-v2":1,"gov":1,"in":1,"io":1,"it":1,"net":1,"org":1,"ppll":1,"rakuten":1,"uk":1},"apicit":1,"appier":1,"akamaized":{"assets-momentum":1,"com":{"media-rockstargames-":1,"ntd":1,"vocento":1}},"aticdn":1,"azure":1,"azurefd":1,"bannerflow":1,"bf-tools":1,"bidswitch":1,"bitsngo":1,"blueconic":1,"boldapps":1,"buysellads":1,"cedexis":1,"certona":1,"fastly":{"map":{"cidgroup":1,"condenast":1,"ihrinferno":1,"prisa-us-eu":1,"scribd":1,"target-opus":1,"thriftbooks":1,"ticketmaster4":1,"twitch":1,"vox":1,"appnexus":1},"global":{"shared":{"d2":1,"s2":1},"sni":{"j":1}},"ssl":{"global":{"igao-prod-herokuapp-com":1,"mslc-prod-herokuapp-com":1}}},"confiant-integrations":1,"consentmanager":1,"contentsquare":1,"criteo":1,"crwdcntrl":1,"cloudfront":{"d16jny3kjm2a1j":1,"d16kgn4efacaad":1,"d19l6uotjzm32g":1,"d1af033869koo7":1,"d1bxz6tua5hq87":1,"d1cr9zxt7u0sgu":1,"d1egjda7ggd2ew":1,"d1eh9yux7w8iql":1,"d1gwclp1pmzk26":1,"d1nhstnts0iwzs":1,"d1p5cqqchvbqmy":1,"d1pq45hly7zfel":1,"d1rhs7mhgydok3":1,"d1rw50yn65615p":1,"d1s87id6169zda":1,"d1snv67wdds0p2":1,"d1tprjo2w7krrh":1,"d1vg5xiq7qffdj":1,"d1vo8zfysxy97v":1,"d1y068gyog18cq":1,"d214hhm15p4t1d":1,"d21gpk1vhmjuf5":1,"d244lyzgucnepm":1,"d27cwqlgojh9yd":1,"d2aioe7l2jay46":1,"d2bj4wnxqmm2tk":1,"d2droglu4qf8st":1,"d2eanzqpmoo3ec":1,"d2f4zoo8hyailp":1,"d2hs2r19gv871k":1,"d2j6syf6c0cltf":1,"d2jpq2u2vrjftk":1,"d2qlgd5odkppg5":1,"d2qrdklrsxowl2":1,"d2s6j0ghajv79z":1,"d2tyltutevw8th":1,"d2wo2i8fdcw8of":1,"d2xbocf5uqnw0w":1,"d2y7rifa1cwopa":1,"d2zah9y47r7bi2":1,"d30jydkdo8eo9b":1,"d355prp56x5ntt":1,"d35mt2i8wrf9y1":1,"d38aqfmkl3ge26":1,"d38xvr37kwwhcm":1,"d3fv2pqyjay52z":1,"d3gxe0jmvtuxbc":1,"d3i4yxtzktqr9n":1,"d3jruqy3qmm3fd":1,"d3nn82uaxijpm6":1,"d3o8vwpyaorolj":1,"d3ochae1kou2ub":1,"d3odp2r1osuwn0":1,"d3owq2fdwtdp2j":1,"d3txh7prdum3s8":1,"d3v7mj6iyaqfac":1,"d4egga2bwam6h":1,"d5yoctgpv4cpx":1,"d6tizftlrpuof":1,"d9k0w0y3delq8":1,"dbukjj6eu5tsf":1,"de2pmm85odupd":1,"de7iszmjjjuya":1,"dfx0d9twj2ai":1,"dj28g4s0yd4ph":1,"dn0qt3r0xannq":1,"dokumfe7mps0i":1,"dowpznhhyvkm4":1,"dsh7ky7308k4b":1,"dsx863kqtdxrt":1,"dtpw88eywzb7u":1,"duube1y6ojsji":1,"dzlkq6toxiazj":1,"dzz1zjxa9ulpk":1,"d2638j3z8ek976":1},"akadns":{"com":{"dellcdn":1,"febsec-fidelity":1},"line-zero":1},"demdex":1,"dotmetrics":1,"doubleclick":1,"durationmedia":1,"e-planning":1,"edgecastcdn":1,"emsecure":1,"episerver":1,"esm1":1,"eulerian":1,"everestjs":1,"everesttech":1,"eyeota":1,"ezoic":1,"facebook":1,"fastclick":1,"fbcdn":1,"fonts":1,"edgesuite":{"com":{"fox":1,"iq":1,"tiktokcdn-us":1,"vidio":1,"sky":1},"linkedin":1,"stls":1},"fuseplatform":1,"fwmrm":1,"go-mpulse":1,"hadronid":1,"hs-analytics":1,"hsleadflows":1,"im-apps":1,"impervadns":1,"iocnt":1,"iprom":1,"jsdelivr":1,"kanade-ad":1,"azurewebsites":{"keha-matomo-te-palvelut-prod":1,"neuterbot-client":1,"app-ch-sgtm-prod":1,"app-fnsp-matomo-analytics-prod":1},"krxd":1,"line-scdn":1,"listhub":1,"livecom":1,"livedoor":1,"liveperson":1,"lkqd":1,"llnwd":1,"lpsnmedia":1,"magnetmail":1,"marketo":1,"maxymiser":1,"media":1,"microad":1,"monetate":1,"mxptint":1,"myfonts":1,"myvisualiq":1,"naver":1,"b-cdn":{"nnwwwlive":1,"speedy":1},"nr-data":1,"omtrdc":1,"onecount":1,"online-metrix":1,"openx":1,"opta":1,"owneriq":1,"pages02":1,"pages03":1,"pages04":1,"pages05":1,"pages06":1,"pages08":1,"perimeterx":1,"pingdom":1,"pmdstatic":1,"popads":1,"popcash":1,"primecaster":1,"pro-market":1,"px-cloud":1,"akamaihd":{"pxlclnmdecom-a":1},"r9cdn":1,"rfihub":1,"sancdn":1,"sc-static":1,"semasio":1,"sensic":1,"trafficmanager":{"serviceschipotlecom":1},"sexad":1,"smaato":1,"spreadshirts":1,"storygize":1,"tfaforms":1,"trackcmp":1,"trackedlink":1,"truste-svc":1,"uuidksinc":1,"viafoura":1,"visilabs":1,"visx":1,"w55c":1,"wdsvc":1,"witglobal":1,"yandex":1,"yastatic":1,"yieldlab":1,"ywxi":1,"zdbb":1,"zencdn":1,"zucks":1,"eviltracker":1},"co":{"6sc":1,"ayads":1,"datadome":1,"idio":1,"increasingly":1,"jads":1,"nanorep":1,"nc0":1,"pcdn":1,"prmutv":1,"resetdigital":1,"t":1,"tctm":1,"zip":1},"de":{"71i":1,"adscale":1,"auswaertiges-amt":1,"fiduciagad":1,"ioam":1,"itzbund":1,"werk21system":1},"gt":{"ad":1},"jp":{"adingo":1,"admatrix":1,"auone":1,"co":{"dmm":1,"google":1,"rakuten":1,"yahoo":1},"fout":1,"gmossp-sp":1,"gssprt":1,"ne":{"hatena":1},"impact-ad":1,"microad":1,"nakanohito":1,"ptengine":1,"r10s":1,"reemo-ad":1,"rtoaster":1,"shinobi":1,"team-rec":1,"uncn":1,"yimg":1,"yjtag":1},"pl":{"adocean":1,"dreamlab":1,"gemius":1,"nsaudience":1,"onet":1,"salesmanago":1,"wp":1},"pro":{"adpartner":1,"piwik":1,"usocial":1},"ru":{"adriver":1,"digitaltarget":1,"mail":1,"mindbox":1,"rambler":1,"sape":1,"smi2":1,"tns-counter":1,"top100":1,"ulogin":1,"yandex":1},"re":{"adsco":1},"info":{"adxbid":1,"bitrix":1,"navistechnologies":1,"usergram":1,"webantenna":1},"tv":{"affec":1,"attn":1,"iris":1,"ispot":1,"samba":1,"teads":1,"twitch":1},"dev":{"amazon":1},"us":{"amung":1,"samplicio":1,"slgnt":1,"trkn":1},"media":{"andbeyond":1,"nextday":1,"townsquare":1,"underdog":1},"link":{"app":1},"cloud":{"avct":1,"coremedia":1,"egain":1,"matomo":1},"delivery":{"ay":1,"monu":1},"br":{"com":{"btg360":1,"clearsale":1,"jsuol":1,"shopconvert":1,"shoptarget":1,"soclminer":1},"org":{"ivcbrasil":1}},"ch":{"ch":1,"da-services":1,"google":1},"ms":{"clarity":1},"my":{"cnt":1},"se":{"codigo":1},"me":{"contentexchange":1,"grow":1,"line":1,"loopme":1,"t":1,"channel":1},"to":{"cpx":1,"tawk":1},"chat":{"crisp":1,"gorgias":1},"fr":{"d-bi":1,"open-system":1,"weborama":1},"uk":{"co":{"dailymail":1,"hsbc":1}},"id":{"net":{"detik":1}},"ai":{"e-volution":1,"m2":1,"nrich":1,"wknd":1},"be":{"geoedge":1},"au":{"com":{"google":1,"news":1,"nine":1,"realestate":1,"zipmoney":1,"telstra":1}},"stream":{"ibclick":1},"cz":{"imedia":1,"seznam":1,"trackad":1},"app":{"infusionsoft":1,"permutive":1,"shop":1},"tech":{"ingage":1,"primis":1},"eu":{"kameleoon":1,"medallia":1,"media01":1,"ocdn":1,"rqtrk":1,"slgnt":1,"usercentrics":1},"fi":{"kesko":1,"simpli":1},"live":{"lura":1},"services":{"marketingautomation":1},"sg":{"mediacorp":1},"bi":{"newsroom":1},"fm":{"pdst":1},"ad":{"pixel":1},"xyz":{"playground":1},"it":{"plug":1,"repstatic":1,"stbm":1},"cc":{"popin":1},"network":{"pub":1},"nl":{"rijksoverheid":1,"google":1},"fyi":{"sda":1},"pe":{"shop":1},"es":{"socy":1},"im":{"spot":1},"market":{"spotim":1},"am":{"tru":1},"at":{"waust":1},"gov":{"weather":1},"in":{"zoho":1},"ca":{"bc":{"gov":1}},"no":{"acdn":1,"uio":1},"example":{"ad-company":1},"site":{"ad-company":1,"third-party":{"bad":1,"broken":1}},"pw":{"zlp6s":1}}; return { debug: false, sessionKey: 'randomVal', @@ -10910,7 +11291,8 @@ 'fingerprintingScreenSize', 'navigatorInterface' ] - } + }, + trackerLookup } } @@ -10951,7 +11333,10 @@ const processedConfig = generateConfig(); load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }); // mark this phase as loaded diff --git a/build/firefox/inject.js b/build/firefox/inject.js index c29f53a6a..2403171e3 100644 --- a/build/firefox/inject.js +++ b/build/firefox/inject.js @@ -90,7 +90,7 @@ * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ - function isThirdParty () { + function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -308,7 +308,7 @@ /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ function processAttr (configSetting, defaultValue) { @@ -439,6 +439,133 @@ DDGReflect = globalObj.wrappedJSObject.Reflect; } + function isUnprotectedDomain (topLevelHostname, featureList) { + let unprotectedDomain = false; + const domainParts = topLevelHostname.split('.'); + + // walk up the domain to see if it's unprotected + while (domainParts.length > 1 && !unprotectedDomain) { + const partialDomain = domainParts.join('.'); + + unprotectedDomain = featureList.filter(domain => domain.domain === partialDomain).length > 0; + + domainParts.shift(); + } + + return unprotectedDomain + } + + /** + * @typedef {object} Platform + * @property {'ios' | 'macos' | 'extension' | 'android' | 'windows'} name + * @property {string | number } [version] + */ + + /** + * @typedef {object} UserPreferences + * @property {Platform} platform + * @property {boolean} [debug] + * @property {boolean} [globalPrivacyControl] + * @property {number} [versionNumber] - Android version number only + * @property {string} [versionString] - Non Android version string + * @property {string} sessionKey + */ + + /** + * Used to inialize extension code in the load phase + */ + function computeLimitedSiteObject () { + const topLevelHostname = getTabHostname(); + return { + domain: topLevelHostname + } + } + + function parseVersionString (versionString) { + const [major = 0, minor = 0, patch = 0] = versionString.split('.').map(Number); + return { + major, + minor, + patch + } + } + + /** + * @param {string} minVersionString + * @param {string} applicationVersionString + * @returns {boolean} + */ + function satisfiesMinVersion (minVersionString, applicationVersionString) { + const { major: minMajor, minor: minMinor, patch: minPatch } = parseVersionString(minVersionString); + const { major, minor, patch } = parseVersionString(applicationVersionString); + + return (major > minMajor || + (major >= minMajor && minor > minMinor) || + (major >= minMajor && minor >= minMinor && patch >= minPatch)) + } + + /** + * @param {string | number | undefined} minSupportedVersion + * @param {string | number | undefined} currentVersion + * @returns {boolean} + */ + function isSupportedVersion (minSupportedVersion, currentVersion) { + if (typeof currentVersion === 'string' && typeof minSupportedVersion === 'string') { + if (satisfiesMinVersion(minSupportedVersion, currentVersion)) { + return true + } + } else if (typeof currentVersion === 'number' && typeof minSupportedVersion === 'number') { + if (minSupportedVersion <= currentVersion) { + return true + } + } + return false + } + + /** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ + function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features); + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); + const enabledFeatures = remoteFeatureNames.filter((featureName) => { + const feature = data.features[featureName]; + // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { + return false + } + } + return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) + }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config + return enabledFeatures + } + + /** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ + function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {}; + const remoteFeatureNames = Object.keys(data.features); + remoteFeatureNames.forEach((featureName) => { + if (!enabledFeatures.includes(featureName)) { + return + } + + featureSettings[featureName] = data.features[featureName].settings; + }); + return featureSettings + } + const windowsSpecificFeatures = ['windowsPermissionUsage']; function isWindowsSpecificFeature (featureName) { @@ -571,7 +698,7 @@ } var injectedFeaturesCode = { - "runtimeChecks": "/*! © DuckDuckGo ContentScopeScripts protections https://github.com/duckduckgo/content-scope-scripts/ */\nvar runtimeChecks = (function () {\n 'use strict';\n\n /* global cloneInto, exportFunction, false */\n\n // Only use globalThis for testing this breaks window.wrappedJSObject code in Firefox\n // eslint-disable-next-line no-global-assign\n let globalObj = typeof window === 'undefined' ? globalThis : window;\n let Error$1 = globalObj.Error;\n const CapturedSet = globalObj.Set;\n // Capture prototype to prevent overloading\n const createSet = () => new CapturedSet();\n typeof window === 'undefined' ? null : window.dispatchEvent.bind(window);\n\n /**\n * @returns {HTMLElement} the element to inject the script into\n */\n function getInjectionElement () {\n return document.head || document.documentElement\n }\n\n /**\n * Creates a script element with the given code to avoid Firefox CSP restrictions.\n * @param {string} css\n * @returns {HTMLLinkElement}\n */\n function createStyleElement (css) {\n const style = document.createElement('link');\n style.href = 'data:text/css,' + encodeURIComponent(css);\n style.setAttribute('rel', 'stylesheet');\n style.setAttribute('type', 'text/css');\n return style\n }\n\n /**\n * Injects a script into the page, avoiding CSP restrictions if possible.\n */\n function injectGlobalStyles (css) {\n const style = createStyleElement(css);\n getInjectionElement().appendChild(style);\n }\n\n const exemptionLists = {};\n function shouldExemptUrl (type, url) {\n for (const regex of exemptionLists[type]) {\n if (regex.test(url)) {\n return true\n }\n }\n return false\n }\n\n /**\n * Returns true if hostname is a subset of exceptionDomain or an exact match.\n * @param {string} hostname\n * @param {string} exceptionDomain\n * @returns {boolean}\n */\n function matchHostname (hostname, exceptionDomain) {\n return hostname === exceptionDomain || hostname.endsWith(`.${exceptionDomain}`)\n }\n\n const lineTest = /(\\()?(https?:[^)]+):[0-9]+:[0-9]+(\\))?/;\n function getStackTraceUrls (stack) {\n const urls = createSet();\n try {\n const errorLines = stack.split('\\n');\n // Should cater for Chrome and Firefox stacks, we only care about https? resources.\n for (const line of errorLines) {\n const res = line.match(lineTest);\n if (res) {\n urls.add(new URL(res[2], location.href));\n }\n }\n } catch (e) {\n // Fall through\n }\n return urls\n }\n\n function getStackTraceOrigins (stack) {\n const urls = getStackTraceUrls(stack);\n const origins = createSet();\n for (const url of urls) {\n origins.add(url.hostname);\n }\n return origins\n }\n\n // Checks the stack trace if there are known libraries that are broken.\n function shouldExemptMethod (type) {\n // Short circuit stack tracing if we don't have checks\n if (!(type in exemptionLists) || exemptionLists[type].length === 0) {\n return false\n }\n const stack = getStack();\n const errorFiles = getStackTraceUrls(stack);\n for (const path of errorFiles) {\n if (shouldExemptUrl(type, path.href)) {\n return true\n }\n }\n return false\n }\n\n function camelcase (dashCaseText) {\n return dashCaseText.replace(/-(.)/g, (match, letter) => {\n return letter.toUpperCase()\n })\n }\n\n // We use this method to detect M1 macs and set appropriate API values to prevent sites from detecting fingerprinting protections\n function isAppleSilicon () {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl');\n\n // Best guess if the device is an Apple Silicon\n // https://stackoverflow.com/a/65412357\n // @ts-expect-error - Object is possibly 'null'\n return gl.getSupportedExtensions().indexOf('WEBGL_compressed_texture_etc') !== -1\n }\n\n /**\n * Take configSeting which should be an array of possible values.\n * If a value contains a criteria that is a match for this environment then return that value.\n * Otherwise return the first value that doesn't have a criteria.\n *\n * @param {*[]} configSetting - Config setting which should contain a list of possible values\n * @returns {*|undefined} - The value from the list that best matches the criteria in the config\n */\n function processAttrByCriteria (configSetting) {\n let bestOption;\n for (const item of configSetting) {\n if (item.criteria) {\n if (item.criteria.arch === 'AppleSilicon' && isAppleSilicon()) {\n bestOption = item;\n break\n }\n } else {\n bestOption = item;\n }\n }\n\n return bestOption\n }\n\n const functionMap = {\n /** Useful for debugging APIs in the wild, shouldn't be used */\n debug: (...args) => {\n console.log('debugger', ...args);\n // eslint-disable-next-line no-debugger\n debugger\n },\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n noop: () => { }\n };\n\n /**\n * Handles the processing of a config setting.\n * @param {*} configSetting\n * @param {*} defaultValue\n * @returns\n */\n function processAttr (configSetting, defaultValue) {\n if (configSetting === undefined) {\n return defaultValue\n }\n\n const configSettingType = typeof configSetting;\n switch (configSettingType) {\n case 'object':\n if (Array.isArray(configSetting)) {\n configSetting = processAttrByCriteria(configSetting);\n if (configSetting === undefined) {\n return defaultValue\n }\n }\n\n if (!configSetting.type) {\n return defaultValue\n }\n\n if (configSetting.type === 'function') {\n if (configSetting.functionName && functionMap[configSetting.functionName]) {\n return functionMap[configSetting.functionName]\n }\n }\n\n if (configSetting.type === 'undefined') {\n return undefined\n }\n\n return configSetting.value\n default:\n return defaultValue\n }\n }\n\n function getStack () {\n return new Error$1().stack\n }\n\n /**\n * @template {object} P\n * @typedef {object} ProxyObject

\n * @property {(target?: object, thisArg?: P, args?: object) => void} apply\n */\n\n /**\n * @template [P=object]\n */\n class DDGProxy {\n /**\n * @param {string} featureName\n * @param {P} objectScope\n * @param {string} property\n * @param {ProxyObject

} proxyObject\n */\n constructor (featureName, objectScope, property, proxyObject) {\n this.objectScope = objectScope;\n this.property = property;\n this.featureName = featureName;\n this.camelFeatureName = camelcase(this.featureName);\n const outputHandler = (...args) => {\n const isExempt = shouldExemptMethod(this.camelFeatureName);\n // The normal return value\n if (isExempt) {\n return DDGReflect.apply(...args)\n }\n return proxyObject.apply(...args)\n };\n const getMethod = (target, prop, receiver) => {\n if (prop === 'toString') {\n const method = Reflect.get(target, prop, receiver).bind(target);\n Object.defineProperty(method, 'toString', {\n value: String.toString.bind(String.toString),\n enumerable: false\n });\n return method\n }\n return DDGReflect.get(target, prop, receiver)\n };\n {\n this._native = objectScope[property];\n const handler = {};\n handler.apply = outputHandler;\n handler.get = getMethod;\n this.internal = new globalObj.Proxy(objectScope[property], handler);\n }\n }\n\n // Actually apply the proxy to the native property\n overload () {\n {\n this.objectScope[this.property] = this.internal;\n }\n }\n }\n\n function postDebugMessage (feature, message) {\n if (message.stack) {\n const scriptOrigins = [...getStackTraceOrigins(message.stack)];\n message.scriptOrigins = scriptOrigins;\n }\n globalObj.postMessage({\n action: feature,\n message\n });\n }\n\n let DDGReflect;\n\n // Exports for usage where we have to cross the xray boundary: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts\n {\n DDGReflect = globalObj.Reflect;\n }\n\n function _typeof$2(obj) { \"@babel/helpers - typeof\"; return _typeof$2 = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof$2(obj); }\n function isJSONArray(value) {\n return Array.isArray(value);\n }\n function isJSONObject(value) {\n return value !== null && _typeof$2(value) === 'object' && value.constructor === Object // do not match on classes or Array\n ;\n }\n\n function _typeof$1(obj) { \"@babel/helpers - typeof\"; return _typeof$1 = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof$1(obj); }\n /**\r\n * Test deep equality of two JSON values, objects, or arrays\r\n */\n // TODO: write unit tests\n function isEqual(a, b) {\n // FIXME: this function will return false for two objects with the same keys\n // but different order of keys\n return JSON.stringify(a) === JSON.stringify(b);\n }\n\n /**\r\n * Get all but the last items from an array\r\n */\n // TODO: write unit tests\n function initial(array) {\n return array.slice(0, array.length - 1);\n }\n\n /**\r\n * Get the last item from an array\r\n */\n // TODO: write unit tests\n function last(array) {\n return array[array.length - 1];\n }\n\n /**\r\n * Test whether a value is an Object or an Array (and not a primitive JSON value)\r\n */\n // TODO: write unit tests\n function isObjectOrArray(value) {\n return _typeof$1(value) === 'object' && value !== null;\n }\n\n function _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n function _toPropertyKey(arg) { var key = _toPrimitive(arg, \"string\"); return _typeof(key) === \"symbol\" ? key : String(key); }\n function _toPrimitive(input, hint) { if (_typeof(input) !== \"object\" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || \"default\"); if (_typeof(res) !== \"object\") return res; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (hint === \"string\" ? String : Number)(input); }\n\n /**\n * Shallow clone of an Object, Array, or value\n * Symbols are cloned too.\n */\n function shallowClone(value) {\n if (isJSONArray(value)) {\n // copy array items\n var copy = value.slice();\n\n // copy all symbols\n Object.getOwnPropertySymbols(value).forEach(function (symbol) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n copy[symbol] = value[symbol];\n });\n return copy;\n } else if (isJSONObject(value)) {\n // copy object properties\n var _copy = _objectSpread({}, value);\n\n // copy all symbols\n Object.getOwnPropertySymbols(value).forEach(function (symbol) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n _copy[symbol] = value[symbol];\n });\n return _copy;\n } else {\n return value;\n }\n }\n\n /**\n * Update a value in an object in an immutable way.\n * If the value is unchanged, the original object will be returned\n */\n function applyProp(object, key, value) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (object[key] === value) {\n // return original object unchanged when the new value is identical to the old one\n return object;\n } else {\n var updatedObject = shallowClone(object);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n updatedObject[key] = value;\n return updatedObject;\n }\n }\n\n /**\n * helper function to get a nested property in an object or array\n *\n * @return Returns the field when found, or undefined when the path doesn't exist\n */\n function getIn(object, path) {\n var value = object;\n var i = 0;\n while (i < path.length) {\n if (isJSONObject(value)) {\n value = value[path[i]];\n } else if (isJSONArray(value)) {\n value = value[parseInt(path[i])];\n } else {\n value = undefined;\n }\n i++;\n }\n return value;\n }\n\n /**\n * helper function to replace a nested property in an object with a new value\n * without mutating the object itself.\n *\n * @param object\n * @param path\n * @param value\n * @param [createPath=false]\n * If true, `path` will be created when (partly) missing in\n * the object. For correctly creating nested Arrays or\n * Objects, the function relies on `path` containing number\n * in case of array indexes.\n * If false (default), an error will be thrown when the\n * path doesn't exist.\n * @return Returns a new, updated object or array\n */\n function setIn(object, path, value) {\n var createPath = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n if (path.length === 0) {\n return value;\n }\n var key = path[0];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var updatedValue = setIn(object ? object[key] : undefined, path.slice(1), value, createPath);\n if (isJSONObject(object) || isJSONArray(object)) {\n return applyProp(object, key, updatedValue);\n } else {\n if (createPath) {\n var newObject = IS_INTEGER_REGEX.test(key) ? [] : {};\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n newObject[key] = updatedValue;\n return newObject;\n } else {\n throw new Error('Path does not exist');\n }\n }\n }\n var IS_INTEGER_REGEX = /^\\d+$/;\n\n /**\n * helper function to replace a nested property in an object with a new value\n * without mutating the object itself.\n *\n * @return Returns a new, updated object or array\n */\n function updateIn(object, path, callback) {\n if (path.length === 0) {\n return callback(object);\n }\n if (!isObjectOrArray(object)) {\n throw new Error('Path doesn\\'t exist');\n }\n var key = path[0];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var updatedValue = updateIn(object[key], path.slice(1), callback);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return applyProp(object, key, updatedValue);\n }\n\n /**\n * helper function to delete a nested property in an object\n * without mutating the object itself.\n *\n * @return Returns a new, updated object or array\n */\n function deleteIn(object, path) {\n if (path.length === 0) {\n return object;\n }\n if (!isObjectOrArray(object)) {\n throw new Error('Path does not exist');\n }\n if (path.length === 1) {\n var _key = path[0];\n if (!(_key in object)) {\n // key doesn't exist. return object unchanged\n return object;\n } else {\n var updatedObject = shallowClone(object);\n if (isJSONArray(updatedObject)) {\n updatedObject.splice(parseInt(_key), 1);\n }\n if (isJSONObject(updatedObject)) {\n delete updatedObject[_key];\n }\n return updatedObject;\n }\n }\n var key = path[0];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var updatedValue = deleteIn(object[key], path.slice(1));\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return applyProp(object, key, updatedValue);\n }\n\n /**\n * Insert a new item in an array at a specific index.\n * Example usage:\n *\n * insertAt({arr: [1,2,3]}, ['arr', '2'], 'inserted') // [1,2,'inserted',3]\n */\n function insertAt(document, path, value) {\n var parentPath = path.slice(0, path.length - 1);\n var index = path[path.length - 1];\n return updateIn(document, parentPath, function (items) {\n if (!Array.isArray(items)) {\n throw new TypeError('Array expected at path ' + JSON.stringify(parentPath));\n }\n var updatedItems = shallowClone(items);\n updatedItems.splice(parseInt(index), 0, value);\n return updatedItems;\n });\n }\n\n /**\n * Test whether a path exists in a JSON object\n * @return Returns true if the path exists, else returns false\n */\n function existsIn(document, path) {\n if (document === undefined) {\n return false;\n }\n if (path.length === 0) {\n return true;\n }\n if (document === null) {\n return false;\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return existsIn(document[path[0]], path.slice(1));\n }\n\n /**\n * Parse a JSON Pointer\n */\n function parseJSONPointer(pointer) {\n var path = pointer.split('/');\n path.shift(); // remove the first empty entry\n\n return path.map(function (p) {\n return p.replace(/~1/g, '/').replace(/~0/g, '~');\n });\n }\n\n /**\n * Compile a JSON Pointer\n */\n function compileJSONPointer(path) {\n return path.map(compileJSONPointerProp).join('');\n }\n\n /**\n * Compile a single path property from a JSONPath\n */\n function compileJSONPointerProp(pathProp) {\n return '/' + String(pathProp).replace(/~/g, '~0').replace(/\\//g, '~1');\n }\n\n /**\n * Apply a patch to a JSON object\n * The original JSON object will not be changed,\n * instead, the patch is applied in an immutable way\n */\n function immutableJSONPatch(document, operations, options) {\n var updatedDocument = document;\n for (var i = 0; i < operations.length; i++) {\n validateJSONPatchOperation(operations[i]);\n var operation = operations[i];\n\n // TODO: test before\n if (options && options.before) {\n var result = options.before(updatedDocument, operation);\n if (result !== undefined) {\n if (result.document !== undefined) {\n updatedDocument = result.document;\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (result.json !== undefined) {\n // TODO: deprecated since v5.0.0. Cleanup this warning some day\n throw new Error('Deprecation warning: returned object property \".json\" has been renamed to \".document\"');\n }\n if (result.operation !== undefined) {\n operation = result.operation;\n }\n }\n }\n var previousDocument = updatedDocument;\n var path = parsePath(updatedDocument, operation.path);\n if (operation.op === 'add') {\n updatedDocument = add(updatedDocument, path, operation.value);\n } else if (operation.op === 'remove') {\n updatedDocument = remove(updatedDocument, path);\n } else if (operation.op === 'replace') {\n updatedDocument = replace(updatedDocument, path, operation.value);\n } else if (operation.op === 'copy') {\n updatedDocument = copy(updatedDocument, path, parseFrom(operation.from));\n } else if (operation.op === 'move') {\n updatedDocument = move(updatedDocument, path, parseFrom(operation.from));\n } else if (operation.op === 'test') {\n test(updatedDocument, path, operation.value);\n } else {\n throw new Error('Unknown JSONPatch operation ' + JSON.stringify(operation));\n }\n\n // TODO: test after\n if (options && options.after) {\n var _result = options.after(updatedDocument, operation, previousDocument);\n if (_result !== undefined) {\n updatedDocument = _result;\n }\n }\n }\n return updatedDocument;\n }\n\n /**\n * Replace an existing item\n */\n function replace(document, path, value) {\n return setIn(document, path, value);\n }\n\n /**\n * Remove an item or property\n */\n function remove(document, path) {\n return deleteIn(document, path);\n }\n\n /**\n * Add an item or property\n */\n function add(document, path, value) {\n if (isArrayItem(document, path)) {\n return insertAt(document, path, value);\n } else {\n return setIn(document, path, value);\n }\n }\n\n /**\n * Copy a value\n */\n function copy(document, path, from) {\n var value = getIn(document, from);\n if (isArrayItem(document, path)) {\n return insertAt(document, path, value);\n } else {\n var _value = getIn(document, from);\n return setIn(document, path, _value);\n }\n }\n\n /**\n * Move a value\n */\n function move(document, path, from) {\n var value = getIn(document, from);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var removedJson = deleteIn(document, from);\n return isArrayItem(removedJson, path) ? insertAt(removedJson, path, value) : setIn(removedJson, path, value);\n }\n\n /**\n * Test whether the data contains the provided value at the specified path.\n * Throws an error when the test fails\n */\n function test(document, path, value) {\n if (value === undefined) {\n throw new Error(\"Test failed: no value provided (path: \\\"\".concat(compileJSONPointer(path), \"\\\")\"));\n }\n if (!existsIn(document, path)) {\n throw new Error(\"Test failed: path not found (path: \\\"\".concat(compileJSONPointer(path), \"\\\")\"));\n }\n var actualValue = getIn(document, path);\n if (!isEqual(actualValue, value)) {\n throw new Error(\"Test failed, value differs (path: \\\"\".concat(compileJSONPointer(path), \"\\\")\"));\n }\n }\n function isArrayItem(document, path) {\n if (path.length === 0) {\n return false;\n }\n var parent = getIn(document, initial(path));\n return Array.isArray(parent);\n }\n\n /**\n * Resolve the path index of an array, resolves indexes '-'\n * @returns Returns the resolved path\n */\n function resolvePathIndex(document, path) {\n if (last(path) !== '-') {\n return path;\n }\n var parentPath = initial(path);\n var parent = getIn(document, parentPath);\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return parentPath.concat(parent.length);\n }\n\n /**\n * Validate a JSONPatch operation.\n * Throws an error when there is an issue\n */\n function validateJSONPatchOperation(operation) {\n // TODO: write unit tests\n var ops = ['add', 'remove', 'replace', 'copy', 'move', 'test'];\n if (!ops.includes(operation.op)) {\n throw new Error('Unknown JSONPatch op ' + JSON.stringify(operation.op));\n }\n if (typeof operation.path !== 'string') {\n throw new Error('Required property \"path\" missing or not a string in operation ' + JSON.stringify(operation));\n }\n if (operation.op === 'copy' || operation.op === 'move') {\n if (typeof operation.from !== 'string') {\n throw new Error('Required property \"from\" missing or not a string in operation ' + JSON.stringify(operation));\n }\n }\n }\n function parsePath(document, pointer) {\n return resolvePathIndex(document, parseJSONPointer(pointer));\n }\n function parseFrom(fromPointer) {\n return parseJSONPointer(fromPointer);\n }\n\n /**\n * Performance monitor, holds reference to PerformanceMark instances.\n */\n class PerformanceMonitor {\n constructor () {\n this.marks = [];\n }\n\n /**\n * Create performance marker\n * @param {string} name\n * @returns {PerformanceMark}\n */\n mark (name) {\n const mark = new PerformanceMark(name);\n this.marks.push(mark);\n return mark\n }\n\n /**\n * Measure all performance markers\n */\n measureAll () {\n this.marks.forEach((mark) => {\n mark.measure();\n });\n }\n }\n\n /**\n * Tiny wrapper around performance.mark and performance.measure\n */\n class PerformanceMark {\n /**\n * @param {string} name\n */\n constructor (name) {\n this.name = name;\n performance.mark(this.name + 'Start');\n }\n\n end () {\n performance.mark(this.name + 'End');\n }\n\n measure () {\n performance.measure(this.name, this.name + 'Start', this.name + 'End');\n }\n }\n\n class ContentFeature {\n constructor (featureName) {\n this.name = featureName;\n this._args = null;\n this.monitor = new PerformanceMonitor();\n }\n\n /**\n * @param {import('./utils').Platform} platform\n */\n set platform (platform) {\n this._platform = platform;\n }\n\n get platform () {\n // @ts-expect-error - Type 'Platform | undefined' is not assignable to type 'Platform'\n return this._platform\n }\n\n /**\n * Get the value of a config setting.\n * If the value is not set, return the default value.\n * If the value is not an object, return the value.\n * If the value is an object, check its type property.\n * @param {string} attrName\n * @param {any} defaultValue - The default value to use if the config setting is not set\n * @returns The value of the config setting or the default value\n */\n getFeatureAttr (attrName, defaultValue) {\n const configSetting = this.getFeatureSetting(attrName);\n return processAttr(configSetting, defaultValue)\n }\n\n /**\n * @param {string} featureKeyName\n * @returns {any}\n */\n getFeatureSetting (featureKeyName) {\n let result = this._getFeatureSetting();\n if (featureKeyName === 'domains') {\n throw new Error('domains is a reserved feature setting key name')\n }\n const domainMatch = [...this.matchDomainFeatureSetting('domains')].sort((a, b) => {\n return a.domain.length - b.domain.length\n });\n for (const match of domainMatch) {\n if (match.patchSettings === undefined) {\n continue\n }\n try {\n result = immutableJSONPatch(result, match.patchSettings);\n } catch (e) {\n console.error('Error applying patch settings', e);\n }\n }\n return result?.[featureKeyName]\n }\n\n _getFeatureSetting () {\n const camelFeatureName = camelcase(this.name);\n return this._args.featureSettings?.[camelFeatureName]\n }\n\n /**\n * @param {string} featureKeyName\n * @returns {boolean}\n */\n getFeatureSettingEnabled (featureKeyName) {\n const result = this.getFeatureSetting(featureKeyName);\n return result === 'enabled'\n }\n\n /**\n * @param {string} featureKeyName\n * @return {any[]}\n */\n matchDomainFeatureSetting (featureKeyName) {\n const domains = this._getFeatureSetting()?.[featureKeyName] || [];\n return domains.filter((rule) => {\n return matchHostname(this._args.site.domain, rule.domain)\n })\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n init (args) {\n }\n\n callInit (args) {\n const mark = this.monitor.mark(this.name + 'CallInit');\n this._args = args;\n this.platform = args.platform;\n this.init(args);\n mark.end();\n this.measure();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n load (args) {\n }\n\n callLoad (args) {\n const mark = this.monitor.mark(this.name + 'CallLoad');\n this._args = args;\n this.platform = args.platform;\n this.load(args);\n mark.end();\n }\n\n measure () {\n if (this._args.debug) {\n this.monitor.measureAll();\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n update () {\n }\n }\n\n /**\n * Indent a code block using braces\n * @param {string} string\n * @returns {string}\n */\n function removeIndent (string) {\n const lines = string.split('\\n');\n const indentSize = 2;\n let currentIndent = 0;\n const indentedLines = lines.map((line) => {\n if (line.trim().startsWith('}')) {\n currentIndent -= indentSize;\n }\n const indentedLine = ' '.repeat(currentIndent) + line.trim();\n if (line.trim().endsWith('{')) {\n currentIndent += indentSize;\n }\n\n return indentedLine\n });\n return indentedLines.filter(a => a.trim()).join('\\n')\n }\n\n const lookup = {};\n function getOrGenerateIdentifier (path) {\n if (!(path in lookup)) {\n lookup[path] = generateAlphaIdentifier(Object.keys(lookup).length + 1);\n }\n return lookup[path]\n }\n\n function generateAlphaIdentifier (num) {\n if (num < 1) {\n throw new Error('Input must be a positive integer')\n }\n const charCodeOffset = 97;\n let identifier = '';\n while (num > 0) {\n num--;\n const remainder = num % 26;\n const charCode = remainder + charCodeOffset;\n identifier = String.fromCharCode(charCode) + identifier;\n num = Math.floor(num / 26);\n }\n return '_ddg_' + identifier\n }\n\n /**\n * @param {*} scope\n * @param {Record} outputs\n * @returns {Proxy}\n */\n function constructProxy (scope, outputs) {\n // @ts-expect-error - Expected 2 arguments, but got 1\n if (Object.is(scope)) {\n // Should not happen, but just in case fail safely\n console.error('Runtime checks: Scope must be an object', scope, outputs);\n return scope\n }\n return new Proxy(scope, {\n get (target, property, receiver) {\n const targetObj = target[property];\n if (typeof targetObj === 'function') {\n return (...args) => {\n return Reflect.apply(target[property], target, args)\n }\n } else {\n if (typeof property === 'string' && property in outputs) {\n return Reflect.get(outputs, property, receiver)\n }\n return Reflect.get(target, property, receiver)\n }\n }\n })\n }\n\n function valToString (val) {\n if (typeof val === 'function') {\n return val.toString()\n }\n return JSON.stringify(val)\n }\n\n /**\n * Output scope variable definitions to arbitrary depth\n */\n function stringifyScope (scope, scopePath) {\n let output = '';\n for (const [key, value] of scope) {\n const varOutName = getOrGenerateIdentifier([...scopePath, key]);\n if (value instanceof Map) {\n const proxyName = getOrGenerateIdentifier(['_proxyFor_', varOutName]);\n output += `\n let ${proxyName} = ${scopePath.join('?.')}?.${key} ? ${scopePath.join('.')}.${key} : Object.bind(null);\n `;\n const keys = Array.from(value.keys());\n output += stringifyScope(value, [...scopePath, key]);\n const proxyOut = keys.map((keyName) => `${keyName}: ${getOrGenerateIdentifier([...scopePath, key, keyName])}`);\n output += `\n let ${varOutName} = constructProxy(${proxyName}, {\n ${proxyOut.join(',\\n')}\n });\n `;\n // If we're at the top level, we need to add the window and globalThis variables (Eg: let navigator = parentScope_navigator)\n if (scopePath.length === 1) {\n output += `\n let ${key} = ${varOutName};\n `;\n }\n } else {\n output += `\n let ${varOutName} = ${valToString(value)};\n `;\n }\n }\n return output\n }\n\n /**\n * Code generates wrapping variables for code that is injected into the page\n * @param {*} code\n * @param {*} config\n * @returns {string}\n */\n function wrapScriptCodeOverload (code, config) {\n const processedConfig = {};\n for (const [key, value] of Object.entries(config)) {\n // @ts-expect-error - Expected 2 arguments, but got 1\n processedConfig[key] = processAttr(value);\n }\n // Don't do anything if the config is empty\n if (Object.keys(processedConfig).length === 0) return code\n\n let prepend = '';\n const aggregatedLookup = new Map();\n let currentScope = null;\n /* Convert the config into a map of scopePath -> { key: value } */\n for (const [key, value] of Object.entries(processedConfig)) {\n const path = key.split('.');\n\n currentScope = aggregatedLookup;\n const pathOut = path[path.length - 1];\n // Traverse the path and create the nested objects\n path.slice(0, -1).forEach((pathPart, index) => {\n if (!currentScope.has(pathPart)) {\n currentScope.set(pathPart, new Map());\n }\n currentScope = currentScope.get(pathPart);\n });\n currentScope.set(pathOut, value);\n }\n\n prepend += stringifyScope(aggregatedLookup, ['parentScope']);\n // Stringify top level keys\n const keysOut = [...aggregatedLookup.keys()].map((keyName) => `${keyName}: ${getOrGenerateIdentifier(['parentScope', keyName])}`).join(',\\n');\n prepend += `\n const window = constructProxy(parentScope, {\n ${keysOut}\n });\n const globalThis = constructProxy(parentScope, {\n ${keysOut}\n });\n `;\n return removeIndent(`(function (parentScope) {\n /**\n * DuckDuckGo Runtime Checks injected code.\n * If you're reading this, you're probably trying to debug a site that is breaking due to our runtime checks.\n * Please raise an issues on our GitHub repo: https://github.com/duckduckgo/content-scope-scripts/\n */\n ${constructProxy.toString()}\n ${prepend}\n ${code}\n })(globalThis)\n `)\n }\n\n /* global TrustedScriptURL, TrustedScript */\n\n let stackDomains = [];\n let matchAllStackDomains = false;\n let taintCheck = false;\n let initialCreateElement;\n let tagModifiers = {};\n let shadowDomEnabled = false;\n let scriptOverload = {};\n // Ignore monitoring properties that are only relevant once and already handled\n const defaultIgnoreMonitorList = ['onerror', 'onload'];\n let ignoreMonitorList = defaultIgnoreMonitorList;\n\n /**\n * @param {string} tagName\n * @param {'property' | 'attribute' | 'handler' | 'listener'} filterName\n * @param {string} key\n * @returns {boolean}\n */\n function shouldFilterKey (tagName, filterName, key) {\n if (filterName === 'attribute') {\n key = key.toLowerCase();\n }\n return tagModifiers?.[tagName]?.filters?.[filterName]?.includes(key)\n }\n\n let elementRemovalTimeout;\n const featureName = 'runtimeChecks';\n const taintSymbol = Symbol(featureName);\n const supportedSinks = ['src'];\n // Store the original methods so we can call them without any side effects\n const defaultElementMethods = {\n setAttribute: HTMLElement.prototype.setAttribute,\n getAttribute: HTMLElement.prototype.getAttribute,\n removeAttribute: HTMLElement.prototype.removeAttribute,\n remove: HTMLElement.prototype.remove,\n removeChild: HTMLElement.prototype.removeChild\n };\n const supportedTrustedTypes = 'TrustedScriptURL' in window;\n\n class DDGRuntimeChecks extends HTMLElement {\n #tagName\n #el\n #listeners\n #connected\n #sinks\n\n constructor () {\n super();\n this.#tagName = null;\n this.#el = null;\n this.#listeners = [];\n this.#connected = false;\n this.#sinks = {};\n if (shadowDomEnabled) {\n const shadow = this.attachShadow({ mode: 'open' });\n const style = createStyleElement(`\n :host {\n display: none;\n }\n `);\n shadow.appendChild(style);\n }\n }\n\n /**\n * This method is called once and externally so has to remain public.\n **/\n setTagName (tagName) {\n this.#tagName = tagName;\n\n // Clear the method so it can't be called again\n // @ts-expect-error - error TS2790: The operand of a 'delete' operator must be optional.\n delete this.setTagName;\n }\n\n connectedCallback () {\n // Solves re-entrancy issues from React\n if (this.#connected) return\n this.#connected = true;\n if (!this._transplantElement) {\n // Restore the 'this' object with the DDGRuntimeChecks prototype as sometimes pages will overwrite it.\n Object.setPrototypeOf(this, DDGRuntimeChecks.prototype);\n }\n this._transplantElement();\n }\n\n _monitorProperties (el) {\n // Mutation oberver and observedAttributes don't work on property accessors\n // So instead we need to monitor all properties on the prototypes and forward them to the real element\n let propertyNames = [];\n let proto = Object.getPrototypeOf(el);\n while (proto && proto !== Object.prototype) {\n propertyNames.push(...Object.getOwnPropertyNames(proto));\n proto = Object.getPrototypeOf(proto);\n }\n const classMethods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));\n // Filter away the methods we don't want to monitor from our own class\n propertyNames = propertyNames.filter(prop => !classMethods.includes(prop));\n propertyNames.forEach(prop => {\n if (prop === 'constructor') return\n // May throw, but this is best effort monitoring.\n try {\n Object.defineProperty(this, prop, {\n get () {\n return el[prop]\n },\n set (value) {\n if (shouldFilterKey(this.#tagName, 'property', prop)) return\n if (ignoreMonitorList.includes(prop)) return\n el[prop] = value;\n }\n });\n } catch { }\n });\n }\n\n computeScriptOverload (el) {\n // Short circuit if we don't have any script text\n if (el.textContent === '') return\n // Short circuit if we're in a trusted script environment\n // @ts-expect-error TrustedScript is not defined in the TS lib\n if (supportedTrustedTypes && el.textContent instanceof TrustedScript) return\n\n el.textContent = wrapScriptCodeOverload(el.textContent, scriptOverload);\n }\n\n /**\n * The element has been moved to the DOM, so we can now reflect all changes to a real element.\n * This is to allow us to interrogate the real element before it is moved to the DOM.\n */\n _transplantElement () {\n // Creeate the real element\n const el = initialCreateElement.call(document, this.#tagName);\n\n if (taintCheck) {\n // Add a symbol to the element so we can identify it as a runtime checked element\n Object.defineProperty(el, taintSymbol, { value: true, configurable: false, enumerable: false, writable: false });\n }\n\n // Reflect all attrs to the new element\n for (const attribute of this.getAttributeNames()) {\n if (shouldFilterKey(this.#tagName, 'attribute', attribute)) continue\n defaultElementMethods.setAttribute.call(el, attribute, this.getAttribute(attribute));\n }\n\n // Reflect all props to the new element\n const props = Object.keys(this);\n\n // Nonce isn't enumerable so we need to add it manually\n props.push('nonce');\n\n for (const prop of props) {\n if (shouldFilterKey(this.#tagName, 'property', prop)) continue\n el[prop] = this[prop];\n }\n\n for (const sink of supportedSinks) {\n if (this.#sinks[sink]) {\n el[sink] = this.#sinks[sink];\n }\n }\n\n // Reflect all listeners to the new element\n for (const [...args] of this.#listeners) {\n if (shouldFilterKey(this.#tagName, 'listener', args[0])) continue\n el.addEventListener(...args);\n }\n this.#listeners = [];\n\n // Reflect all 'on' event handlers to the new element\n for (const propName in this) {\n if (propName.startsWith('on')) {\n if (shouldFilterKey(this.#tagName, 'handler', propName)) continue\n const prop = this[propName];\n if (typeof prop === 'function') {\n el[propName] = prop;\n }\n }\n }\n\n // Move all children to the new element\n while (this.firstChild) {\n el.appendChild(this.firstChild);\n }\n\n if (this.#tagName === 'script') {\n this.computeScriptOverload(el);\n }\n\n // Move the new element to the DOM\n try {\n this.insertAdjacentElement('afterend', el);\n } catch (e) { console.warn(e); }\n\n this._monitorProperties(el);\n // TODO pollyfill WeakRef\n this.#el = new WeakRef(el);\n\n // Delay removal of the custom element so if the script calls removeChild it will still be in the DOM and not throw.\n setTimeout(() => {\n this.remove();\n }, elementRemovalTimeout);\n }\n\n _getElement () {\n return this.#el?.deref()\n }\n\n /**\n * Calls a method on the real element if it exists, otherwise calls the method on the DDGRuntimeChecks element.\n * @template {keyof defaultElementMethods} E\n * @param {E} method\n * @param {...Parameters} args\n * @return {ReturnType}\n */\n _callMethod (method, ...args) {\n const el = this._getElement();\n if (el) {\n return defaultElementMethods[method].call(el, ...args)\n }\n // @ts-expect-error TS doesn't like the spread operator\n return super[method](...args)\n }\n\n /* Native DOM element methods we're capturing to supplant values into the constructed node or store data for. */\n\n set src (value) {\n const el = this._getElement();\n if (el) {\n el.src = value;\n return\n }\n this.#sinks.src = value;\n }\n\n get src () {\n const el = this._getElement();\n if (el) {\n return el.src\n }\n // @ts-expect-error TrustedScriptURL is not defined in the TS lib\n if (supportedTrustedTypes && this.#sinks.src instanceof TrustedScriptURL) {\n return this.#sinks.src.toString()\n }\n return this.#sinks.src\n }\n\n getAttribute (name, value) {\n if (shouldFilterKey(this.#tagName, 'attribute', name)) return\n if (supportedSinks.includes(name)) {\n // Use Reflect to avoid infinite recursion\n return Reflect.get(DDGRuntimeChecks.prototype, name, this)\n }\n return this._callMethod('getAttribute', name, value)\n }\n\n setAttribute (name, value) {\n if (shouldFilterKey(this.#tagName, 'attribute', name)) return\n if (supportedSinks.includes(name)) {\n // Use Reflect to avoid infinite recursion\n return Reflect.set(DDGRuntimeChecks.prototype, name, value, this)\n }\n return this._callMethod('setAttribute', name, value)\n }\n\n removeAttribute (name) {\n if (shouldFilterKey(this.#tagName, 'attribute', name)) return\n if (supportedSinks.includes(name)) {\n delete this[name];\n return\n }\n return this._callMethod('removeAttribute', name)\n }\n\n addEventListener (...args) {\n if (shouldFilterKey(this.#tagName, 'listener', args[0])) return\n const el = this._getElement();\n if (el) {\n return el.addEventListener(...args)\n }\n this.#listeners.push([...args]);\n }\n\n removeEventListener (...args) {\n if (shouldFilterKey(this.#tagName, 'listener', args[0])) return\n const el = this._getElement();\n if (el) {\n return el.removeEventListener(...args)\n }\n this.#listeners = this.#listeners.filter((listener) => {\n return listener[0] !== args[0] || listener[1] !== args[1]\n });\n }\n\n toString () {\n const interfaceName = this.#tagName.charAt(0).toUpperCase() + this.#tagName.slice(1);\n return `[object HTML${interfaceName}Element]`\n }\n\n get tagName () {\n return this.#tagName.toUpperCase()\n }\n\n get nodeName () {\n return this.tagName\n }\n\n remove () {\n return this._callMethod('remove')\n }\n\n // @ts-expect-error TS node return here\n removeChild (child) {\n return this._callMethod('removeChild', child)\n }\n }\n\n /**\n * Overrides the instanceof checks to make the custom element interface pass an instanceof check\n * @param {Object} elementInterface\n */\n function overloadInstanceOfChecks (elementInterface) {\n const proxy = new Proxy(elementInterface[Symbol.hasInstance], {\n apply (fn, scope, args) {\n if (args[0] instanceof DDGRuntimeChecks) {\n return true\n }\n return Reflect.apply(fn, scope, args)\n }\n });\n // May throw, but we can ignore it\n try {\n Object.defineProperty(elementInterface, Symbol.hasInstance, {\n value: proxy\n });\n } catch {}\n }\n\n /**\n * Returns true if the tag should be intercepted\n * @param {string} tagName\n * @returns {boolean}\n */\n function shouldInterrogate (tagName) {\n const interestingTags = ['script'];\n if (!interestingTags.includes(tagName)) {\n return false\n }\n if (matchAllStackDomains) {\n isInterrogatingDebugMessage('matchedAllStackDomain');\n return true\n }\n if (taintCheck && document.currentScript?.[taintSymbol]) {\n isInterrogatingDebugMessage('taintCheck');\n return true\n }\n const stack = getStack();\n const scriptOrigins = [...getStackTraceOrigins(stack)];\n const interestingHost = scriptOrigins.find(origin => {\n return stackDomains.some(rule => matchHostname(origin, rule.domain))\n });\n const isInterestingHost = !!interestingHost;\n if (isInterestingHost) {\n isInterrogatingDebugMessage('matchedStackDomain', interestingHost, stack, scriptOrigins);\n }\n return isInterestingHost\n }\n\n function isInterrogatingDebugMessage (matchType, matchedStackDomain, stack, scriptOrigins) {\n postDebugMessage('runtimeChecks', {\n documentUrl: document.location.href,\n matchedStackDomain,\n matchType,\n scriptOrigins,\n stack\n });\n }\n\n function overrideCreateElement () {\n const proxy = new DDGProxy(featureName, Document.prototype, 'createElement', {\n apply (fn, scope, args) {\n if (args.length >= 1) {\n // String() is used to coerce the value to a string (For: ProseMirror/prosemirror-model/src/to_dom.ts)\n const initialTagName = String(args[0]).toLowerCase();\n if (shouldInterrogate(initialTagName)) {\n args[0] = 'ddg-runtime-checks';\n const el = Reflect.apply(fn, scope, args);\n el.setTagName(initialTagName);\n return el\n }\n }\n return Reflect.apply(fn, scope, args)\n }\n });\n proxy.overload();\n initialCreateElement = proxy._native;\n }\n\n class RuntimeChecks extends ContentFeature {\n load () {\n // This shouldn't happen, but if it does we don't want to break the page\n try {\n // @ts-expect-error TS node return here\n customElements.define('ddg-runtime-checks', DDGRuntimeChecks);\n } catch {}\n }\n\n init () {\n let enabled = this.getFeatureSettingEnabled('matchAllDomains');\n if (!enabled) {\n enabled = this.matchDomainFeatureSetting('domains').length > 0;\n }\n if (!enabled) return\n\n taintCheck = this.getFeatureSettingEnabled('taintCheck');\n matchAllStackDomains = this.getFeatureSettingEnabled('matchAllStackDomains');\n stackDomains = this.getFeatureSetting('stackDomains') || [];\n elementRemovalTimeout = this.getFeatureSetting('elementRemovalTimeout') || 1000;\n tagModifiers = this.getFeatureSetting('tagModifiers') || {};\n shadowDomEnabled = this.getFeatureSettingEnabled('shadowDom') || false;\n scriptOverload = this.getFeatureSetting('scriptOverload') || {};\n ignoreMonitorList = this.getFeatureSetting('ignoreMonitorList') || defaultIgnoreMonitorList;\n\n overrideCreateElement();\n\n if (this.getFeatureSettingEnabled('overloadInstanceOf')) {\n overloadInstanceOfChecks(HTMLScriptElement);\n }\n\n if (this.getFeatureSettingEnabled('injectGlobalStyles')) {\n injectGlobalStyles(`\n ddg-runtime-checks {\n display: none;\n }\n `);\n }\n }\n }\n\n return RuntimeChecks;\n\n})();\n" + "runtimeChecks": "/*! © DuckDuckGo ContentScopeScripts protections https://github.com/duckduckgo/content-scope-scripts/ */\nvar runtimeChecks = (function () {\n 'use strict';\n\n /* global cloneInto, exportFunction, false */\n\n // Only use globalThis for testing this breaks window.wrappedJSObject code in Firefox\n // eslint-disable-next-line no-global-assign\n let globalObj = typeof window === 'undefined' ? globalThis : window;\n let Error$1 = globalObj.Error;\n const CapturedSet = globalObj.Set;\n // Capture prototype to prevent overloading\n const createSet = () => new CapturedSet();\n typeof window === 'undefined' ? null : window.dispatchEvent.bind(window);\n\n /**\n * @returns {HTMLElement} the element to inject the script into\n */\n function getInjectionElement () {\n return document.head || document.documentElement\n }\n\n /**\n * Creates a script element with the given code to avoid Firefox CSP restrictions.\n * @param {string} css\n * @returns {HTMLLinkElement}\n */\n function createStyleElement (css) {\n const style = document.createElement('link');\n style.href = 'data:text/css,' + encodeURIComponent(css);\n style.setAttribute('rel', 'stylesheet');\n style.setAttribute('type', 'text/css');\n return style\n }\n\n /**\n * Injects a script into the page, avoiding CSP restrictions if possible.\n */\n function injectGlobalStyles (css) {\n const style = createStyleElement(css);\n getInjectionElement().appendChild(style);\n }\n\n const exemptionLists = {};\n function shouldExemptUrl (type, url) {\n for (const regex of exemptionLists[type]) {\n if (regex.test(url)) {\n return true\n }\n }\n return false\n }\n\n /**\n * Best guess effort of the tabs hostname; where possible always prefer the args.site.domain\n * @returns {string|null} inferred tab hostname\n */\n function getTabHostname () {\n let framingOrigin = null;\n try {\n // @ts-expect-error - globalThis.top is possibly 'null' here\n framingOrigin = globalThis.top.location.href;\n } catch {\n framingOrigin = globalThis.document.referrer;\n }\n\n // Not supported in Firefox\n if ('ancestorOrigins' in globalThis.location && globalThis.location.ancestorOrigins.length) {\n // ancestorOrigins is reverse order, with the last item being the top frame\n framingOrigin = globalThis.location.ancestorOrigins.item(globalThis.location.ancestorOrigins.length - 1);\n }\n\n try {\n // @ts-expect-error - framingOrigin is possibly 'null' here\n framingOrigin = new URL(framingOrigin).hostname;\n } catch {\n framingOrigin = null;\n }\n return framingOrigin\n }\n\n /**\n * Returns true if hostname is a subset of exceptionDomain or an exact match.\n * @param {string} hostname\n * @param {string} exceptionDomain\n * @returns {boolean}\n */\n function matchHostname (hostname, exceptionDomain) {\n return hostname === exceptionDomain || hostname.endsWith(`.${exceptionDomain}`)\n }\n\n const lineTest = /(\\()?(https?:[^)]+):[0-9]+:[0-9]+(\\))?/;\n function getStackTraceUrls (stack) {\n const urls = createSet();\n try {\n const errorLines = stack.split('\\n');\n // Should cater for Chrome and Firefox stacks, we only care about https? resources.\n for (const line of errorLines) {\n const res = line.match(lineTest);\n if (res) {\n urls.add(new URL(res[2], location.href));\n }\n }\n } catch (e) {\n // Fall through\n }\n return urls\n }\n\n function getStackTraceOrigins (stack) {\n const urls = getStackTraceUrls(stack);\n const origins = createSet();\n for (const url of urls) {\n origins.add(url.hostname);\n }\n return origins\n }\n\n // Checks the stack trace if there are known libraries that are broken.\n function shouldExemptMethod (type) {\n // Short circuit stack tracing if we don't have checks\n if (!(type in exemptionLists) || exemptionLists[type].length === 0) {\n return false\n }\n const stack = getStack();\n const errorFiles = getStackTraceUrls(stack);\n for (const path of errorFiles) {\n if (shouldExemptUrl(type, path.href)) {\n return true\n }\n }\n return false\n }\n\n function camelcase (dashCaseText) {\n return dashCaseText.replace(/-(.)/g, (match, letter) => {\n return letter.toUpperCase()\n })\n }\n\n // We use this method to detect M1 macs and set appropriate API values to prevent sites from detecting fingerprinting protections\n function isAppleSilicon () {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl');\n\n // Best guess if the device is an Apple Silicon\n // https://stackoverflow.com/a/65412357\n // @ts-expect-error - Object is possibly 'null'\n return gl.getSupportedExtensions().indexOf('WEBGL_compressed_texture_etc') !== -1\n }\n\n /**\n * Take configSeting which should be an array of possible values.\n * If a value contains a criteria that is a match for this environment then return that value.\n * Otherwise return the first value that doesn't have a criteria.\n *\n * @param {*[]} configSetting - Config setting which should contain a list of possible values\n * @returns {*|undefined} - The value from the list that best matches the criteria in the config\n */\n function processAttrByCriteria (configSetting) {\n let bestOption;\n for (const item of configSetting) {\n if (item.criteria) {\n if (item.criteria.arch === 'AppleSilicon' && isAppleSilicon()) {\n bestOption = item;\n break\n }\n } else {\n bestOption = item;\n }\n }\n\n return bestOption\n }\n\n const functionMap = {\n /** Useful for debugging APIs in the wild, shouldn't be used */\n debug: (...args) => {\n console.log('debugger', ...args);\n // eslint-disable-next-line no-debugger\n debugger\n },\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n noop: () => { }\n };\n\n /**\n * Handles the processing of a config setting.\n * @param {*} configSetting\n * @param {*} [defaultValue]\n * @returns\n */\n function processAttr (configSetting, defaultValue) {\n if (configSetting === undefined) {\n return defaultValue\n }\n\n const configSettingType = typeof configSetting;\n switch (configSettingType) {\n case 'object':\n if (Array.isArray(configSetting)) {\n configSetting = processAttrByCriteria(configSetting);\n if (configSetting === undefined) {\n return defaultValue\n }\n }\n\n if (!configSetting.type) {\n return defaultValue\n }\n\n if (configSetting.type === 'function') {\n if (configSetting.functionName && functionMap[configSetting.functionName]) {\n return functionMap[configSetting.functionName]\n }\n }\n\n if (configSetting.type === 'undefined') {\n return undefined\n }\n\n return configSetting.value\n default:\n return defaultValue\n }\n }\n\n function getStack () {\n return new Error$1().stack\n }\n\n /**\n * @template {object} P\n * @typedef {object} ProxyObject

\n * @property {(target?: object, thisArg?: P, args?: object) => void} apply\n */\n\n /**\n * @template [P=object]\n */\n class DDGProxy {\n /**\n * @param {string} featureName\n * @param {P} objectScope\n * @param {string} property\n * @param {ProxyObject

} proxyObject\n */\n constructor (featureName, objectScope, property, proxyObject) {\n this.objectScope = objectScope;\n this.property = property;\n this.featureName = featureName;\n this.camelFeatureName = camelcase(this.featureName);\n const outputHandler = (...args) => {\n const isExempt = shouldExemptMethod(this.camelFeatureName);\n // The normal return value\n if (isExempt) {\n return DDGReflect.apply(...args)\n }\n return proxyObject.apply(...args)\n };\n const getMethod = (target, prop, receiver) => {\n if (prop === 'toString') {\n const method = Reflect.get(target, prop, receiver).bind(target);\n Object.defineProperty(method, 'toString', {\n value: String.toString.bind(String.toString),\n enumerable: false\n });\n return method\n }\n return DDGReflect.get(target, prop, receiver)\n };\n {\n this._native = objectScope[property];\n const handler = {};\n handler.apply = outputHandler;\n handler.get = getMethod;\n this.internal = new globalObj.Proxy(objectScope[property], handler);\n }\n }\n\n // Actually apply the proxy to the native property\n overload () {\n {\n this.objectScope[this.property] = this.internal;\n }\n }\n }\n\n function postDebugMessage (feature, message) {\n if (message.stack) {\n const scriptOrigins = [...getStackTraceOrigins(message.stack)];\n message.scriptOrigins = scriptOrigins;\n }\n globalObj.postMessage({\n action: feature,\n message\n });\n }\n\n let DDGReflect;\n\n // Exports for usage where we have to cross the xray boundary: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Sharing_objects_with_page_scripts\n {\n DDGReflect = globalObj.Reflect;\n }\n\n function isUnprotectedDomain (topLevelHostname, featureList) {\n let unprotectedDomain = false;\n const domainParts = topLevelHostname.split('.');\n\n // walk up the domain to see if it's unprotected\n while (domainParts.length > 1 && !unprotectedDomain) {\n const partialDomain = domainParts.join('.');\n\n unprotectedDomain = featureList.filter(domain => domain.domain === partialDomain).length > 0;\n\n domainParts.shift();\n }\n\n return unprotectedDomain\n }\n\n function parseVersionString (versionString) {\n const [major = 0, minor = 0, patch = 0] = versionString.split('.').map(Number);\n return {\n major,\n minor,\n patch\n }\n }\n\n /**\n * @param {string} minVersionString\n * @param {string} applicationVersionString\n * @returns {boolean}\n */\n function satisfiesMinVersion (minVersionString, applicationVersionString) {\n const { major: minMajor, minor: minMinor, patch: minPatch } = parseVersionString(minVersionString);\n const { major, minor, patch } = parseVersionString(applicationVersionString);\n\n return (major > minMajor ||\n (major >= minMajor && minor > minMinor) ||\n (major >= minMajor && minor >= minMinor && patch >= minPatch))\n }\n\n /**\n * @param {string | number | undefined} minSupportedVersion\n * @param {string | number | undefined} currentVersion\n * @returns {boolean}\n */\n function isSupportedVersion (minSupportedVersion, currentVersion) {\n if (typeof currentVersion === 'string' && typeof minSupportedVersion === 'string') {\n if (satisfiesMinVersion(minSupportedVersion, currentVersion)) {\n return true\n }\n } else if (typeof currentVersion === 'number' && typeof minSupportedVersion === 'number') {\n if (minSupportedVersion <= currentVersion) {\n return true\n }\n }\n return false\n }\n\n /**\n * Retutns a list of enabled features\n * @param {RemoteConfig} data\n * @param {string | null} topLevelHostname\n * @param {Platform['version']} platformVersion\n * @param {string[]} platformSpecificFeatures\n * @returns {string[]}\n */\n function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) {\n const remoteFeatureNames = Object.keys(data.features);\n const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName));\n const enabledFeatures = remoteFeatureNames.filter((featureName) => {\n const feature = data.features[featureName];\n // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion\n if (feature.minSupportedVersion && platformVersion) {\n if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) {\n return false\n }\n }\n return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions)\n }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config\n return enabledFeatures\n }\n\n /**\n * Returns the relevant feature settings for the enabled features\n * @param {RemoteConfig} data\n * @param {string[]} enabledFeatures\n * @returns {Record}\n */\n function parseFeatureSettings (data, enabledFeatures) {\n /** @type {Record} */\n const featureSettings = {};\n const remoteFeatureNames = Object.keys(data.features);\n remoteFeatureNames.forEach((featureName) => {\n if (!enabledFeatures.includes(featureName)) {\n return\n }\n\n featureSettings[featureName] = data.features[featureName].settings;\n });\n return featureSettings\n }\n\n function _typeof$2(obj) { \"@babel/helpers - typeof\"; return _typeof$2 = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof$2(obj); }\n function isJSONArray(value) {\n return Array.isArray(value);\n }\n function isJSONObject(value) {\n return value !== null && _typeof$2(value) === 'object' && value.constructor === Object // do not match on classes or Array\n ;\n }\n\n function _typeof$1(obj) { \"@babel/helpers - typeof\"; return _typeof$1 = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof$1(obj); }\n /**\r\n * Test deep equality of two JSON values, objects, or arrays\r\n */\n // TODO: write unit tests\n function isEqual(a, b) {\n // FIXME: this function will return false for two objects with the same keys\n // but different order of keys\n return JSON.stringify(a) === JSON.stringify(b);\n }\n\n /**\r\n * Get all but the last items from an array\r\n */\n // TODO: write unit tests\n function initial(array) {\n return array.slice(0, array.length - 1);\n }\n\n /**\r\n * Get the last item from an array\r\n */\n // TODO: write unit tests\n function last(array) {\n return array[array.length - 1];\n }\n\n /**\r\n * Test whether a value is an Object or an Array (and not a primitive JSON value)\r\n */\n // TODO: write unit tests\n function isObjectOrArray(value) {\n return _typeof$1(value) === 'object' && value !== null;\n }\n\n function _typeof(obj) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }, _typeof(obj); }\n function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }\n function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }\n function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n function _toPropertyKey(arg) { var key = _toPrimitive(arg, \"string\"); return _typeof(key) === \"symbol\" ? key : String(key); }\n function _toPrimitive(input, hint) { if (_typeof(input) !== \"object\" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || \"default\"); if (_typeof(res) !== \"object\") return res; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (hint === \"string\" ? String : Number)(input); }\n\n /**\n * Shallow clone of an Object, Array, or value\n * Symbols are cloned too.\n */\n function shallowClone(value) {\n if (isJSONArray(value)) {\n // copy array items\n var copy = value.slice();\n\n // copy all symbols\n Object.getOwnPropertySymbols(value).forEach(function (symbol) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n copy[symbol] = value[symbol];\n });\n return copy;\n } else if (isJSONObject(value)) {\n // copy object properties\n var _copy = _objectSpread({}, value);\n\n // copy all symbols\n Object.getOwnPropertySymbols(value).forEach(function (symbol) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n _copy[symbol] = value[symbol];\n });\n return _copy;\n } else {\n return value;\n }\n }\n\n /**\n * Update a value in an object in an immutable way.\n * If the value is unchanged, the original object will be returned\n */\n function applyProp(object, key, value) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (object[key] === value) {\n // return original object unchanged when the new value is identical to the old one\n return object;\n } else {\n var updatedObject = shallowClone(object);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n updatedObject[key] = value;\n return updatedObject;\n }\n }\n\n /**\n * helper function to get a nested property in an object or array\n *\n * @return Returns the field when found, or undefined when the path doesn't exist\n */\n function getIn(object, path) {\n var value = object;\n var i = 0;\n while (i < path.length) {\n if (isJSONObject(value)) {\n value = value[path[i]];\n } else if (isJSONArray(value)) {\n value = value[parseInt(path[i])];\n } else {\n value = undefined;\n }\n i++;\n }\n return value;\n }\n\n /**\n * helper function to replace a nested property in an object with a new value\n * without mutating the object itself.\n *\n * @param object\n * @param path\n * @param value\n * @param [createPath=false]\n * If true, `path` will be created when (partly) missing in\n * the object. For correctly creating nested Arrays or\n * Objects, the function relies on `path` containing number\n * in case of array indexes.\n * If false (default), an error will be thrown when the\n * path doesn't exist.\n * @return Returns a new, updated object or array\n */\n function setIn(object, path, value) {\n var createPath = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n if (path.length === 0) {\n return value;\n }\n var key = path[0];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var updatedValue = setIn(object ? object[key] : undefined, path.slice(1), value, createPath);\n if (isJSONObject(object) || isJSONArray(object)) {\n return applyProp(object, key, updatedValue);\n } else {\n if (createPath) {\n var newObject = IS_INTEGER_REGEX.test(key) ? [] : {};\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n newObject[key] = updatedValue;\n return newObject;\n } else {\n throw new Error('Path does not exist');\n }\n }\n }\n var IS_INTEGER_REGEX = /^\\d+$/;\n\n /**\n * helper function to replace a nested property in an object with a new value\n * without mutating the object itself.\n *\n * @return Returns a new, updated object or array\n */\n function updateIn(object, path, callback) {\n if (path.length === 0) {\n return callback(object);\n }\n if (!isObjectOrArray(object)) {\n throw new Error('Path doesn\\'t exist');\n }\n var key = path[0];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var updatedValue = updateIn(object[key], path.slice(1), callback);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return applyProp(object, key, updatedValue);\n }\n\n /**\n * helper function to delete a nested property in an object\n * without mutating the object itself.\n *\n * @return Returns a new, updated object or array\n */\n function deleteIn(object, path) {\n if (path.length === 0) {\n return object;\n }\n if (!isObjectOrArray(object)) {\n throw new Error('Path does not exist');\n }\n if (path.length === 1) {\n var _key = path[0];\n if (!(_key in object)) {\n // key doesn't exist. return object unchanged\n return object;\n } else {\n var updatedObject = shallowClone(object);\n if (isJSONArray(updatedObject)) {\n updatedObject.splice(parseInt(_key), 1);\n }\n if (isJSONObject(updatedObject)) {\n delete updatedObject[_key];\n }\n return updatedObject;\n }\n }\n var key = path[0];\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var updatedValue = deleteIn(object[key], path.slice(1));\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return applyProp(object, key, updatedValue);\n }\n\n /**\n * Insert a new item in an array at a specific index.\n * Example usage:\n *\n * insertAt({arr: [1,2,3]}, ['arr', '2'], 'inserted') // [1,2,'inserted',3]\n */\n function insertAt(document, path, value) {\n var parentPath = path.slice(0, path.length - 1);\n var index = path[path.length - 1];\n return updateIn(document, parentPath, function (items) {\n if (!Array.isArray(items)) {\n throw new TypeError('Array expected at path ' + JSON.stringify(parentPath));\n }\n var updatedItems = shallowClone(items);\n updatedItems.splice(parseInt(index), 0, value);\n return updatedItems;\n });\n }\n\n /**\n * Test whether a path exists in a JSON object\n * @return Returns true if the path exists, else returns false\n */\n function existsIn(document, path) {\n if (document === undefined) {\n return false;\n }\n if (path.length === 0) {\n return true;\n }\n if (document === null) {\n return false;\n }\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return existsIn(document[path[0]], path.slice(1));\n }\n\n /**\n * Parse a JSON Pointer\n */\n function parseJSONPointer(pointer) {\n var path = pointer.split('/');\n path.shift(); // remove the first empty entry\n\n return path.map(function (p) {\n return p.replace(/~1/g, '/').replace(/~0/g, '~');\n });\n }\n\n /**\n * Compile a JSON Pointer\n */\n function compileJSONPointer(path) {\n return path.map(compileJSONPointerProp).join('');\n }\n\n /**\n * Compile a single path property from a JSONPath\n */\n function compileJSONPointerProp(pathProp) {\n return '/' + String(pathProp).replace(/~/g, '~0').replace(/\\//g, '~1');\n }\n\n /**\n * Apply a patch to a JSON object\n * The original JSON object will not be changed,\n * instead, the patch is applied in an immutable way\n */\n function immutableJSONPatch(document, operations, options) {\n var updatedDocument = document;\n for (var i = 0; i < operations.length; i++) {\n validateJSONPatchOperation(operations[i]);\n var operation = operations[i];\n\n // TODO: test before\n if (options && options.before) {\n var result = options.before(updatedDocument, operation);\n if (result !== undefined) {\n if (result.document !== undefined) {\n updatedDocument = result.document;\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (result.json !== undefined) {\n // TODO: deprecated since v5.0.0. Cleanup this warning some day\n throw new Error('Deprecation warning: returned object property \".json\" has been renamed to \".document\"');\n }\n if (result.operation !== undefined) {\n operation = result.operation;\n }\n }\n }\n var previousDocument = updatedDocument;\n var path = parsePath(updatedDocument, operation.path);\n if (operation.op === 'add') {\n updatedDocument = add(updatedDocument, path, operation.value);\n } else if (operation.op === 'remove') {\n updatedDocument = remove(updatedDocument, path);\n } else if (operation.op === 'replace') {\n updatedDocument = replace(updatedDocument, path, operation.value);\n } else if (operation.op === 'copy') {\n updatedDocument = copy(updatedDocument, path, parseFrom(operation.from));\n } else if (operation.op === 'move') {\n updatedDocument = move(updatedDocument, path, parseFrom(operation.from));\n } else if (operation.op === 'test') {\n test(updatedDocument, path, operation.value);\n } else {\n throw new Error('Unknown JSONPatch operation ' + JSON.stringify(operation));\n }\n\n // TODO: test after\n if (options && options.after) {\n var _result = options.after(updatedDocument, operation, previousDocument);\n if (_result !== undefined) {\n updatedDocument = _result;\n }\n }\n }\n return updatedDocument;\n }\n\n /**\n * Replace an existing item\n */\n function replace(document, path, value) {\n return setIn(document, path, value);\n }\n\n /**\n * Remove an item or property\n */\n function remove(document, path) {\n return deleteIn(document, path);\n }\n\n /**\n * Add an item or property\n */\n function add(document, path, value) {\n if (isArrayItem(document, path)) {\n return insertAt(document, path, value);\n } else {\n return setIn(document, path, value);\n }\n }\n\n /**\n * Copy a value\n */\n function copy(document, path, from) {\n var value = getIn(document, from);\n if (isArrayItem(document, path)) {\n return insertAt(document, path, value);\n } else {\n var _value = getIn(document, from);\n return setIn(document, path, _value);\n }\n }\n\n /**\n * Move a value\n */\n function move(document, path, from) {\n var value = getIn(document, from);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n var removedJson = deleteIn(document, from);\n return isArrayItem(removedJson, path) ? insertAt(removedJson, path, value) : setIn(removedJson, path, value);\n }\n\n /**\n * Test whether the data contains the provided value at the specified path.\n * Throws an error when the test fails\n */\n function test(document, path, value) {\n if (value === undefined) {\n throw new Error(\"Test failed: no value provided (path: \\\"\".concat(compileJSONPointer(path), \"\\\")\"));\n }\n if (!existsIn(document, path)) {\n throw new Error(\"Test failed: path not found (path: \\\"\".concat(compileJSONPointer(path), \"\\\")\"));\n }\n var actualValue = getIn(document, path);\n if (!isEqual(actualValue, value)) {\n throw new Error(\"Test failed, value differs (path: \\\"\".concat(compileJSONPointer(path), \"\\\")\"));\n }\n }\n function isArrayItem(document, path) {\n if (path.length === 0) {\n return false;\n }\n var parent = getIn(document, initial(path));\n return Array.isArray(parent);\n }\n\n /**\n * Resolve the path index of an array, resolves indexes '-'\n * @returns Returns the resolved path\n */\n function resolvePathIndex(document, path) {\n if (last(path) !== '-') {\n return path;\n }\n var parentPath = initial(path);\n var parent = getIn(document, parentPath);\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return parentPath.concat(parent.length);\n }\n\n /**\n * Validate a JSONPatch operation.\n * Throws an error when there is an issue\n */\n function validateJSONPatchOperation(operation) {\n // TODO: write unit tests\n var ops = ['add', 'remove', 'replace', 'copy', 'move', 'test'];\n if (!ops.includes(operation.op)) {\n throw new Error('Unknown JSONPatch op ' + JSON.stringify(operation.op));\n }\n if (typeof operation.path !== 'string') {\n throw new Error('Required property \"path\" missing or not a string in operation ' + JSON.stringify(operation));\n }\n if (operation.op === 'copy' || operation.op === 'move') {\n if (typeof operation.from !== 'string') {\n throw new Error('Required property \"from\" missing or not a string in operation ' + JSON.stringify(operation));\n }\n }\n }\n function parsePath(document, pointer) {\n return resolvePathIndex(document, parseJSONPointer(pointer));\n }\n function parseFrom(fromPointer) {\n return parseJSONPointer(fromPointer);\n }\n\n /**\n * Performance monitor, holds reference to PerformanceMark instances.\n */\n class PerformanceMonitor {\n constructor () {\n this.marks = [];\n }\n\n /**\n * Create performance marker\n * @param {string} name\n * @returns {PerformanceMark}\n */\n mark (name) {\n const mark = new PerformanceMark(name);\n this.marks.push(mark);\n return mark\n }\n\n /**\n * Measure all performance markers\n */\n measureAll () {\n this.marks.forEach((mark) => {\n mark.measure();\n });\n }\n }\n\n /**\n * Tiny wrapper around performance.mark and performance.measure\n */\n class PerformanceMark {\n /**\n * @param {string} name\n */\n constructor (name) {\n this.name = name;\n performance.mark(this.name + 'Start');\n }\n\n end () {\n performance.mark(this.name + 'End');\n }\n\n measure () {\n performance.measure(this.name, this.name + 'Start', this.name + 'End');\n }\n }\n\n /**\n * @typedef {object} AssetConfig\n * @property {string} regularFontUrl\n * @property {string} boldFontUrl\n */\n\n /**\n * @typedef {object} Site\n * @property {string} domain\n * @property {boolean} isBroken\n * @property {boolean} allowlisted\n * @property {string[]} enabledFeatures\n */\n\n class ContentFeature {\n /** @type {import('./utils.js').RemoteConfig | undefined} */\n #bundledConfig\n /** @type {object | undefined} */\n #trackerLookup\n /** @type {boolean | undefined} */\n #documentOriginIsTracker\n /** @type {Record | undefined} */\n #bundledfeatureSettings\n\n /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */\n #args\n\n constructor (featureName) {\n this.name = featureName;\n this.#args = null;\n this.monitor = new PerformanceMonitor();\n }\n\n get isDebug () {\n return this.#args?.debug || false\n }\n\n /**\n * @param {import('./utils').Platform} platform\n */\n set platform (platform) {\n this._platform = platform;\n }\n\n get platform () {\n // @ts-expect-error - Type 'Platform | undefined' is not assignable to type 'Platform'\n return this._platform\n }\n\n /**\n * @type {AssetConfig | undefined}\n */\n get assetConfig () {\n return this.#args?.assets\n }\n\n /**\n * @returns {boolean}\n */\n get documentOriginIsTracker () {\n return !!this.#documentOriginIsTracker\n }\n\n /**\n * @returns {object}\n **/\n get trackerLookup () {\n return this.#trackerLookup || {}\n }\n\n /**\n * @returns {import('./utils.js').RemoteConfig | undefined}\n **/\n get bundledConfig () {\n return this.#bundledConfig\n }\n\n /**\n * Get the value of a config setting.\n * If the value is not set, return the default value.\n * If the value is not an object, return the value.\n * If the value is an object, check its type property.\n * @param {string} attrName\n * @param {any} defaultValue - The default value to use if the config setting is not set\n * @returns The value of the config setting or the default value\n */\n getFeatureAttr (attrName, defaultValue) {\n const configSetting = this.getFeatureSetting(attrName);\n return processAttr(configSetting, defaultValue)\n }\n\n /**\n * @param {string} featureKeyName\n * @param {string} [featureName]\n * @returns {any}\n */\n getFeatureSetting (featureKeyName, featureName) {\n let result = this._getFeatureSetting(featureName);\n if (featureKeyName === 'domains') {\n throw new Error('domains is a reserved feature setting key name')\n }\n const domainMatch = [...this.matchDomainFeatureSetting('domains')].sort((a, b) => {\n return a.domain.length - b.domain.length\n });\n for (const match of domainMatch) {\n if (match.patchSettings === undefined) {\n continue\n }\n try {\n result = immutableJSONPatch(result, match.patchSettings);\n } catch (e) {\n console.error('Error applying patch settings', e);\n }\n }\n return result?.[featureKeyName]\n }\n\n /**\n * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature\n * @returns {any}\n */\n _getFeatureSetting (featureName) {\n const camelFeatureName = featureName || camelcase(this.name);\n return this.#args?.featureSettings?.[camelFeatureName]\n }\n\n /**\n * @param {string} featureKeyName\n * @param {string} [featureName]\n * @returns {boolean}\n */\n getFeatureSettingEnabled (featureKeyName, featureName) {\n const result = this.getFeatureSetting(featureKeyName, featureName);\n return result === 'enabled'\n }\n\n /**\n * @param {string} featureKeyName\n * @return {any[]}\n */\n matchDomainFeatureSetting (featureKeyName) {\n const domain = this.#args?.site.domain;\n if (!domain) return []\n const domains = this._getFeatureSetting()?.[featureKeyName] || [];\n return domains.filter((rule) => {\n return matchHostname(domain, rule.domain)\n })\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n init (args) {\n }\n\n callInit (args) {\n const mark = this.monitor.mark(this.name + 'CallInit');\n this.#args = args;\n this.platform = args.platform;\n this.init(args);\n mark.end();\n this.measure();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n load (args) {\n }\n\n callLoad (args) {\n const mark = this.monitor.mark(this.name + 'CallLoad');\n this.#args = args;\n this.platform = args.platform;\n this.#bundledConfig = args.bundledConfig;\n // If we have a bundled config, treat it as a regular config\n // This will be overriden by the remote config if it is available\n if (this.#bundledConfig && this.#args) {\n const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version);\n this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures);\n }\n this.#trackerLookup = args.trackerLookup;\n this.#documentOriginIsTracker = args.documentOriginIsTracker;\n this.load(args);\n mark.end();\n }\n\n measure () {\n if (this.#args?.debug) {\n this.monitor.measureAll();\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n update () {\n }\n }\n\n /**\n * Indent a code block using braces\n * @param {string} string\n * @returns {string}\n */\n function removeIndent (string) {\n const lines = string.split('\\n');\n const indentSize = 2;\n let currentIndent = 0;\n const indentedLines = lines.map((line) => {\n if (line.trim().startsWith('}')) {\n currentIndent -= indentSize;\n }\n const indentedLine = ' '.repeat(currentIndent) + line.trim();\n if (line.trim().endsWith('{')) {\n currentIndent += indentSize;\n }\n\n return indentedLine\n });\n return indentedLines.filter(a => a.trim()).join('\\n')\n }\n\n const lookup = {};\n function getOrGenerateIdentifier (path) {\n if (!(path in lookup)) {\n lookup[path] = generateAlphaIdentifier(Object.keys(lookup).length + 1);\n }\n return lookup[path]\n }\n\n function generateAlphaIdentifier (num) {\n if (num < 1) {\n throw new Error('Input must be a positive integer')\n }\n const charCodeOffset = 97;\n let identifier = '';\n while (num > 0) {\n num--;\n const remainder = num % 26;\n const charCode = remainder + charCodeOffset;\n identifier = String.fromCharCode(charCode) + identifier;\n num = Math.floor(num / 26);\n }\n return '_ddg_' + identifier\n }\n\n /**\n * @param {*} scope\n * @param {Record} outputs\n * @returns {Proxy}\n */\n function constructProxy (scope, outputs) {\n // @ts-expect-error - Expected 2 arguments, but got 1\n if (Object.is(scope)) {\n // Should not happen, but just in case fail safely\n console.error('Runtime checks: Scope must be an object', scope, outputs);\n return scope\n }\n return new Proxy(scope, {\n get (target, property, receiver) {\n const targetObj = target[property];\n let targetOut = target;\n if (typeof property === 'string' && property in outputs) {\n targetOut = outputs;\n }\n // Reflects functions with the correct 'this' scope\n if (typeof targetObj === 'function') {\n return (...args) => {\n return Reflect.apply(targetOut[property], target, args)\n }\n } else {\n return Reflect.get(targetOut, property, receiver)\n }\n }\n })\n }\n\n function valToString (val) {\n if (typeof val === 'function') {\n return val.toString()\n }\n return JSON.stringify(val)\n }\n\n /**\n * Output scope variable definitions to arbitrary depth\n */\n function stringifyScope (scope, scopePath) {\n let output = '';\n for (const [key, value] of scope) {\n const varOutName = getOrGenerateIdentifier([...scopePath, key]);\n if (value instanceof Map) {\n const proxyName = getOrGenerateIdentifier(['_proxyFor_', varOutName]);\n output += `\n let ${proxyName} = ${scopePath.join('?.')}?.${key} ? ${scopePath.join('.')}.${key} : Object.bind(null);\n `;\n const keys = Array.from(value.keys());\n output += stringifyScope(value, [...scopePath, key]);\n const proxyOut = keys.map((keyName) => `${keyName}: ${getOrGenerateIdentifier([...scopePath, key, keyName])}`);\n output += `\n let ${varOutName} = constructProxy(${proxyName}, {\n ${proxyOut.join(',\\n')}\n });\n `;\n // If we're at the top level, we need to add the window and globalThis variables (Eg: let navigator = parentScope_navigator)\n if (scopePath.length === 1) {\n output += `\n let ${key} = ${varOutName};\n `;\n }\n } else {\n output += `\n let ${varOutName} = ${valToString(value)};\n `;\n }\n }\n return output\n }\n\n /**\n * Code generates wrapping variables for code that is injected into the page\n * @param {*} code\n * @param {*} config\n * @returns {string}\n */\n function wrapScriptCodeOverload (code, config) {\n const processedConfig = {};\n for (const [key, value] of Object.entries(config)) {\n processedConfig[key] = processAttr(value);\n }\n // Don't do anything if the config is empty\n if (Object.keys(processedConfig).length === 0) return code\n\n let prepend = '';\n const aggregatedLookup = new Map();\n let currentScope = null;\n /* Convert the config into a map of scopePath -> { key: value } */\n for (const [key, value] of Object.entries(processedConfig)) {\n const path = key.split('.');\n\n currentScope = aggregatedLookup;\n const pathOut = path[path.length - 1];\n // Traverse the path and create the nested objects\n path.slice(0, -1).forEach((pathPart, index) => {\n if (!currentScope.has(pathPart)) {\n currentScope.set(pathPart, new Map());\n }\n currentScope = currentScope.get(pathPart);\n });\n currentScope.set(pathOut, value);\n }\n\n prepend += stringifyScope(aggregatedLookup, ['parentScope']);\n // Stringify top level keys\n const keysOut = [...aggregatedLookup.keys()].map((keyName) => `${keyName}: ${getOrGenerateIdentifier(['parentScope', keyName])}`).join(',\\n');\n prepend += `\n const window = constructProxy(parentScope, {\n ${keysOut}\n });\n const globalThis = constructProxy(parentScope, {\n ${keysOut}\n });\n `;\n return removeIndent(`(function (parentScope) {\n /**\n * DuckDuckGo Runtime Checks injected code.\n * If you're reading this, you're probably trying to debug a site that is breaking due to our runtime checks.\n * Please raise an issues on our GitHub repo: https://github.com/duckduckgo/content-scope-scripts/\n */\n ${constructProxy.toString()}\n ${prepend}\n ${code}\n })(globalThis)\n `)\n }\n\n /* global TrustedScriptURL, TrustedScript */\n\n let stackDomains = [];\n let matchAllStackDomains = false;\n let taintCheck = false;\n let initialCreateElement;\n let tagModifiers = {};\n let shadowDomEnabled = false;\n let scriptOverload = {};\n // Ignore monitoring properties that are only relevant once and already handled\n const defaultIgnoreMonitorList = ['onerror', 'onload'];\n let ignoreMonitorList = defaultIgnoreMonitorList;\n\n /**\n * @param {string} tagName\n * @param {'property' | 'attribute' | 'handler' | 'listener'} filterName\n * @param {string} key\n * @returns {boolean}\n */\n function shouldFilterKey (tagName, filterName, key) {\n if (filterName === 'attribute') {\n key = key.toLowerCase();\n }\n return tagModifiers?.[tagName]?.filters?.[filterName]?.includes(key)\n }\n\n let elementRemovalTimeout;\n const featureName = 'runtimeChecks';\n const taintSymbol = Symbol(featureName);\n const supportedSinks = ['src'];\n // Store the original methods so we can call them without any side effects\n const defaultElementMethods = {\n setAttribute: HTMLElement.prototype.setAttribute,\n setAttributeNS: HTMLElement.prototype.setAttributeNS,\n getAttribute: HTMLElement.prototype.getAttribute,\n getAttributeNS: HTMLElement.prototype.getAttributeNS,\n removeAttribute: HTMLElement.prototype.removeAttribute,\n remove: HTMLElement.prototype.remove,\n removeChild: HTMLElement.prototype.removeChild\n };\n const supportedTrustedTypes = 'TrustedScriptURL' in window;\n\n class DDGRuntimeChecks extends HTMLElement {\n #tagName\n #el\n #listeners\n #connected\n #sinks\n\n constructor () {\n super();\n this.#tagName = null;\n this.#el = null;\n this.#listeners = [];\n this.#connected = false;\n this.#sinks = {};\n if (shadowDomEnabled) {\n const shadow = this.attachShadow({ mode: 'open' });\n const style = createStyleElement(`\n :host {\n display: none;\n }\n `);\n shadow.appendChild(style);\n }\n }\n\n /**\n * This method is called once and externally so has to remain public.\n **/\n setTagName (tagName) {\n this.#tagName = tagName;\n\n // Clear the method so it can't be called again\n // @ts-expect-error - error TS2790: The operand of a 'delete' operator must be optional.\n delete this.setTagName;\n }\n\n connectedCallback () {\n // Solves re-entrancy issues from React\n if (this.#connected) return\n this.#connected = true;\n if (!this._transplantElement) {\n // Restore the 'this' object with the DDGRuntimeChecks prototype as sometimes pages will overwrite it.\n Object.setPrototypeOf(this, DDGRuntimeChecks.prototype);\n }\n this._transplantElement();\n }\n\n _monitorProperties (el) {\n // Mutation oberver and observedAttributes don't work on property accessors\n // So instead we need to monitor all properties on the prototypes and forward them to the real element\n let propertyNames = [];\n let proto = Object.getPrototypeOf(el);\n while (proto && proto !== Object.prototype) {\n propertyNames.push(...Object.getOwnPropertyNames(proto));\n proto = Object.getPrototypeOf(proto);\n }\n const classMethods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));\n // Filter away the methods we don't want to monitor from our own class\n propertyNames = propertyNames.filter(prop => !classMethods.includes(prop));\n propertyNames.forEach(prop => {\n if (prop === 'constructor') return\n // May throw, but this is best effort monitoring.\n try {\n Object.defineProperty(this, prop, {\n get () {\n return el[prop]\n },\n set (value) {\n if (shouldFilterKey(this.#tagName, 'property', prop)) return\n if (ignoreMonitorList.includes(prop)) return\n el[prop] = value;\n }\n });\n } catch { }\n });\n }\n\n computeScriptOverload (el) {\n // Short circuit if we don't have any script text\n if (el.textContent === '') return\n // Short circuit if we're in a trusted script environment\n // @ts-expect-error TrustedScript is not defined in the TS lib\n if (supportedTrustedTypes && el.textContent instanceof TrustedScript) return\n\n el.textContent = wrapScriptCodeOverload(el.textContent, scriptOverload);\n }\n\n /**\n * The element has been moved to the DOM, so we can now reflect all changes to a real element.\n * This is to allow us to interrogate the real element before it is moved to the DOM.\n */\n _transplantElement () {\n // Creeate the real element\n const el = initialCreateElement.call(document, this.#tagName);\n\n if (taintCheck) {\n // Add a symbol to the element so we can identify it as a runtime checked element\n Object.defineProperty(el, taintSymbol, { value: true, configurable: false, enumerable: false, writable: false });\n }\n\n // Reflect all attrs to the new element\n for (const attribute of this.getAttributeNames()) {\n if (shouldFilterKey(this.#tagName, 'attribute', attribute)) continue\n defaultElementMethods.setAttribute.call(el, attribute, this.getAttribute(attribute));\n }\n\n // Reflect all props to the new element\n const props = Object.keys(this);\n\n // Nonce isn't enumerable so we need to add it manually\n props.push('nonce');\n\n for (const prop of props) {\n if (shouldFilterKey(this.#tagName, 'property', prop)) continue\n el[prop] = this[prop];\n }\n\n for (const sink of supportedSinks) {\n if (this.#sinks[sink]) {\n el[sink] = this.#sinks[sink];\n }\n }\n\n // Reflect all listeners to the new element\n for (const [...args] of this.#listeners) {\n if (shouldFilterKey(this.#tagName, 'listener', args[0])) continue\n el.addEventListener(...args);\n }\n this.#listeners = [];\n\n // Reflect all 'on' event handlers to the new element\n for (const propName in this) {\n if (propName.startsWith('on')) {\n if (shouldFilterKey(this.#tagName, 'handler', propName)) continue\n const prop = this[propName];\n if (typeof prop === 'function') {\n el[propName] = prop;\n }\n }\n }\n\n // Move all children to the new element\n while (this.firstChild) {\n el.appendChild(this.firstChild);\n }\n\n if (this.#tagName === 'script') {\n this.computeScriptOverload(el);\n }\n\n // Move the new element to the DOM\n try {\n this.insertAdjacentElement('afterend', el);\n } catch (e) { console.warn(e); }\n\n this._monitorProperties(el);\n // TODO pollyfill WeakRef\n this.#el = new WeakRef(el);\n\n // Delay removal of the custom element so if the script calls removeChild it will still be in the DOM and not throw.\n setTimeout(() => {\n this.remove();\n }, elementRemovalTimeout);\n }\n\n _getElement () {\n return this.#el?.deref()\n }\n\n /**\n * Calls a method on the real element if it exists, otherwise calls the method on the DDGRuntimeChecks element.\n * @template {keyof defaultElementMethods} E\n * @param {E} method\n * @param {...Parameters} args\n * @return {ReturnType}\n */\n _callMethod (method, ...args) {\n const el = this._getElement();\n if (el) {\n return defaultElementMethods[method].call(el, ...args)\n }\n // @ts-expect-error TS doesn't like the spread operator\n return super[method](...args)\n }\n\n /* Native DOM element methods we're capturing to supplant values into the constructed node or store data for. */\n\n set src (value) {\n const el = this._getElement();\n if (el) {\n el.src = value;\n return\n }\n this.#sinks.src = value;\n }\n\n get src () {\n const el = this._getElement();\n if (el) {\n return el.src\n }\n // @ts-expect-error TrustedScriptURL is not defined in the TS lib\n if (supportedTrustedTypes && this.#sinks.src instanceof TrustedScriptURL) {\n return this.#sinks.src.toString()\n }\n return this.#sinks.src\n }\n\n getAttribute (name, value) {\n if (shouldFilterKey(this.#tagName, 'attribute', name)) return\n if (supportedSinks.includes(name)) {\n // Use Reflect to avoid infinite recursion\n return Reflect.get(DDGRuntimeChecks.prototype, name, this)\n }\n return this._callMethod('getAttribute', name, value)\n }\n\n getAttributeNS (namespace, name, value) {\n if (namespace) {\n return this._callMethod('getAttributeNS', namespace, name, value)\n }\n return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value])\n }\n\n setAttribute (name, value) {\n if (shouldFilterKey(this.#tagName, 'attribute', name)) return\n if (supportedSinks.includes(name)) {\n // Use Reflect to avoid infinite recursion\n return Reflect.set(DDGRuntimeChecks.prototype, name, value, this)\n }\n return this._callMethod('setAttribute', name, value)\n }\n\n setAttributeNS (namespace, name, value) {\n if (namespace) {\n return this._callMethod('setAttributeNS', namespace, name, value)\n }\n return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value])\n }\n\n removeAttribute (name) {\n if (shouldFilterKey(this.#tagName, 'attribute', name)) return\n if (supportedSinks.includes(name)) {\n delete this[name];\n return\n }\n return this._callMethod('removeAttribute', name)\n }\n\n addEventListener (...args) {\n if (shouldFilterKey(this.#tagName, 'listener', args[0])) return\n const el = this._getElement();\n if (el) {\n return el.addEventListener(...args)\n }\n this.#listeners.push([...args]);\n }\n\n removeEventListener (...args) {\n if (shouldFilterKey(this.#tagName, 'listener', args[0])) return\n const el = this._getElement();\n if (el) {\n return el.removeEventListener(...args)\n }\n this.#listeners = this.#listeners.filter((listener) => {\n return listener[0] !== args[0] || listener[1] !== args[1]\n });\n }\n\n toString () {\n const interfaceName = this.#tagName.charAt(0).toUpperCase() + this.#tagName.slice(1);\n return `[object HTML${interfaceName}Element]`\n }\n\n get tagName () {\n return this.#tagName.toUpperCase()\n }\n\n get nodeName () {\n return this.tagName\n }\n\n remove () {\n return this._callMethod('remove')\n }\n\n // @ts-expect-error TS node return here\n removeChild (child) {\n return this._callMethod('removeChild', child)\n }\n }\n\n /**\n * Overrides the instanceof checks to make the custom element interface pass an instanceof check\n * @param {Object} elementInterface\n */\n function overloadInstanceOfChecks (elementInterface) {\n const proxy = new Proxy(elementInterface[Symbol.hasInstance], {\n apply (fn, scope, args) {\n if (args[0] instanceof DDGRuntimeChecks) {\n return true\n }\n return Reflect.apply(fn, scope, args)\n }\n });\n // May throw, but we can ignore it\n try {\n Object.defineProperty(elementInterface, Symbol.hasInstance, {\n value: proxy\n });\n } catch {}\n }\n\n /**\n * Returns true if the tag should be intercepted\n * @param {string} tagName\n * @returns {boolean}\n */\n function shouldInterrogate (tagName) {\n const interestingTags = ['script'];\n if (!interestingTags.includes(tagName)) {\n return false\n }\n if (matchAllStackDomains) {\n isInterrogatingDebugMessage('matchedAllStackDomain');\n return true\n }\n if (taintCheck && document.currentScript?.[taintSymbol]) {\n isInterrogatingDebugMessage('taintCheck');\n return true\n }\n const stack = getStack();\n const scriptOrigins = [...getStackTraceOrigins(stack)];\n const interestingHost = scriptOrigins.find(origin => {\n return stackDomains.some(rule => matchHostname(origin, rule.domain))\n });\n const isInterestingHost = !!interestingHost;\n if (isInterestingHost) {\n isInterrogatingDebugMessage('matchedStackDomain', interestingHost, stack, scriptOrigins);\n }\n return isInterestingHost\n }\n\n function isInterrogatingDebugMessage (matchType, matchedStackDomain, stack, scriptOrigins) {\n postDebugMessage('runtimeChecks', {\n documentUrl: document.location.href,\n matchedStackDomain,\n matchType,\n scriptOrigins,\n stack\n });\n }\n\n function overrideCreateElement () {\n const proxy = new DDGProxy(featureName, Document.prototype, 'createElement', {\n apply (fn, scope, args) {\n if (args.length >= 1) {\n // String() is used to coerce the value to a string (For: ProseMirror/prosemirror-model/src/to_dom.ts)\n const initialTagName = String(args[0]).toLowerCase();\n if (shouldInterrogate(initialTagName)) {\n args[0] = 'ddg-runtime-checks';\n const el = Reflect.apply(fn, scope, args);\n el.setTagName(initialTagName);\n return el\n }\n }\n return Reflect.apply(fn, scope, args)\n }\n });\n proxy.overload();\n initialCreateElement = proxy._native;\n }\n\n class RuntimeChecks extends ContentFeature {\n load () {\n // This shouldn't happen, but if it does we don't want to break the page\n try {\n // @ts-expect-error TS node return here\n customElements.define('ddg-runtime-checks', DDGRuntimeChecks);\n } catch {}\n }\n\n init () {\n let enabled = this.getFeatureSettingEnabled('matchAllDomains');\n if (!enabled) {\n enabled = this.matchDomainFeatureSetting('domains').length > 0;\n }\n if (!enabled) return\n\n taintCheck = this.getFeatureSettingEnabled('taintCheck');\n matchAllStackDomains = this.getFeatureSettingEnabled('matchAllStackDomains');\n stackDomains = this.getFeatureSetting('stackDomains') || [];\n elementRemovalTimeout = this.getFeatureSetting('elementRemovalTimeout') || 1000;\n tagModifiers = this.getFeatureSetting('tagModifiers') || {};\n shadowDomEnabled = this.getFeatureSettingEnabled('shadowDom') || false;\n scriptOverload = this.getFeatureSetting('scriptOverload') || {};\n ignoreMonitorList = this.getFeatureSetting('ignoreMonitorList') || defaultIgnoreMonitorList;\n\n overrideCreateElement();\n\n if (this.getFeatureSettingEnabled('overloadInstanceOf')) {\n overloadInstanceOfChecks(HTMLScriptElement);\n }\n\n if (this.getFeatureSettingEnabled('injectGlobalStyles')) {\n injectGlobalStyles(`\n ddg-runtime-checks {\n display: none;\n }\n `);\n }\n }\n }\n\n return RuntimeChecks;\n\n})();\n" }; function _typeof$2(obj) { "@babel/helpers - typeof"; return _typeof$2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof$2(obj); } @@ -1036,13 +1163,43 @@ return parseJSONPointer(fromPointer); } + /** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + + /** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName; - this._args = null; + this.#args = null; this.monitor = new PerformanceMonitor(); } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -1055,6 +1212,34 @@ return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -1071,10 +1256,11 @@ /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting(); + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName); if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -1094,17 +1280,22 @@ return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name); - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name); + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName); + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName); return result === 'enabled' } @@ -1113,9 +1304,11 @@ * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain; + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || []; return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -1125,7 +1318,7 @@ callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit'); - this._args = args; + this.#args = args; this.platform = args.platform; this.init(args); mark.end(); @@ -1138,14 +1331,23 @@ callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad'); - this._args = args; + this.#args = args; this.platform = args.platform; + this.#bundledConfig = args.bundledConfig; + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version); + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures); + } + this.#trackerLookup = args.trackerLookup; + this.#documentOriginIsTracker = args.documentOriginIsTracker; this.load(args); mark.end(); } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll(); } } @@ -1217,15 +1419,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property]; + let targetOut = target; + if (typeof property === 'string' && property in outputs) { + targetOut = outputs; + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -1282,7 +1486,6 @@ function wrapScriptCodeOverload (code, config) { const processedConfig = {}; for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value); } // Don't do anything if the config is empty @@ -1364,7 +1567,9 @@ // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -1588,6 +1793,13 @@ return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -1597,6 +1809,13 @@ return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -4004,6 +4223,34 @@ } } + /** + * Check if the current document origin is on the tracker list, using the provided lookup trie. + * @param {object} trackerLookup Trie lookup of tracker domains + * @returns {boolean} True iff the origin is a tracker. + */ + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { + const parts = originHostname.split('.').reverse(); + let node = trackerLookup; + for (const sub of parts) { + if (node[sub] === 1) { + return true + } else if (node[sub]) { + node = node[sub]; + } else { + return false + } + } + return false + } + + /** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ + // Initial cookie policy pre init let cookiePolicy = { debug: false, @@ -4012,12 +4259,18 @@ shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) }; + let trackerLookup = {}; let loadedPolicyResolve; @@ -4037,6 +4290,9 @@ }); } + /** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -4045,26 +4301,45 @@ return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } + /** + * @param {Set} scriptOrigins + * @returns {boolean} + */ + function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false; + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup, scriptOrigin)) { + matched = true; + } + } + return matched + } + + /** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true; } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup = this.trackerLookup; + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie; + const { exceptions, settings } = this.bundledConfig.features.cookie; const tabHostname = getTabHostname(); let tabExempted = true; @@ -4078,6 +4353,10 @@ }); cookiePolicy.shouldBlock = !frameExempted && !tabExempted; cookiePolicy.policy = settings.firstPartyCookiePolicy; + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy; + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || []; } // The cookie policy is injected into every frame immediately so that no cookie will @@ -4138,20 +4417,20 @@ try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy; + const { shouldBlock, policy, trackerPolicy } = cookiePolicy; + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy; if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext); return } - // extract cookie expiry from cookie string const cookie = new Cookie(value); // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge; + cookie.maxAge = chosenPolicy.maxAge; debugHelper('restrict', 'expiry', setCookieContext); @@ -4179,19 +4458,23 @@ } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + }; + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie; - args.cookie.debug = args.debug; - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie'); - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie'); - const policy = this.getFeatureSetting('firstPartyCookiePolicy'); - if (policy) { - cookiePolicy.policy = policy; - } + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie); + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy + }; } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false; + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy); } loadedPolicyResolve(); @@ -4473,31 +4756,41 @@ } } + function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }); + } catch { + // todo: Just ignore this exception? + } + } + class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }); - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args); } } + + init (args) { + injectNavigatorInterface(args); + } } let adLabelStrings = []; @@ -4849,7 +5142,7 @@ } } - const logoImg = 'data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAA0aXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarZxpkhw5kqX/4xR1BOzLcQAFIDI36OP392BB5lY9Uy0yyWQyMsLpbgaovkVVYe781/+57l//+lcIPXeXS+t11Or5J4884uSL7r9/xvtv8Pn99/3T88/Pwl+/737/IPKtxJ/p+982f14/+X750xv9ep/11++7/vOT2H/eKPx+4/dP0ifr6/3ni+T78ft++LkQN873RR29/flS188b2a8r7n/8zr8v6/tD/+/+8o3GKu3CB6UYTwrJv//m7wqSfoc0+TPx35Aar/Np8HVJ0b1vxZ83Y0H+cnu//vT+zwv0l0X+9ZX7++r//upvix/nz/fT39ay/qwRX/zbH4Tyt++n3x8T//zB6fcVxb/+IIS4/3E7P7/v3f3e893dzJUVrT8R9RY7/HobXrhY8vT+WuVX43fh6/Z+DX51P72x5dubX/yyMEJkV64LOewwww3n/WnBuMQcT2RPYozGRul7nT0a0dgldlG/wo2NHdups5cWj2Mrc4q/ryW8zx3v8yx0PnkHXhoDb8bu/s+/3P/th/+bX+5ee0vs+++14rqiIovL0M7pv7yKDQn3Z9/KW+Bfv3623/8pfhSqmZdpmTs3OP363mKV8EdspbfPidcV/vxSKLi2f96AJeKzCxcTEjvga0gl1OBbjC0E1rGzQZMrjynHxQ6EUuLmImNOqUbXYo/6bP5OC++1scQa9W2wiY0oqabG3pBTbFbOhfhpuRNDs6SSSym1tNJdGWXWVHMttdZWBXKzpZZbabW11ttosycgsPTaW+999DniSGBgGXW00ccYc0Y3+aDJe01eP/nOiiutvMqqq62+xppG+Fi2YtWadRs2d9xpAxO77rb7Hnue4A5IcfIpp552+hlnXmLtpptvufW22++48/eu/ezqP379L3Yt/OxafDul17Xfu8Z3XWu/3iIITor2jB2LObDjTTtAQEftme8h56id0575EUmKErnIor1xO2jH2MJ8Qiw3/N67P3buP9o3V/p/tG/x/7VzTlv3/2PnHFv3z337N7u2xXP2duzLQq2pT2QfPz99utinSG3++z9H9vER0ogNiCz11FFYzM3HZH6SY2UHQOvr7LCJx9/pYxrz3JXnZbdYl+pjGens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'; + const logoImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFQAAABUCAYAAAAcaxDBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAABNTSURBVHgBzV0LcFPXmf6PJFt+gkEY8wrYMSEbgst7m02ywZnOZiEJCQlJC+QB25lNs7OzlEJ2ptmZLGayfUy3EEhmW5rM7gCZBtjJgzxmSTvTRSST9IF5pCE0TUosmmBjHIKNZFmWLN2e78hHPvfqXuleSdfONyNLV7q6uve7//uc85vRlwAda25oTFK8lZGn0UPaLI2okUhrTH/KGnU7M+olTevlL0KaeM3e01LaKa/PE2p64dgpGmMwGgN0rGqtS1Ve2cB/fhk/gVbSqI5KAU4wvxlBTdNe9VJ5sOnAb0I0yhg1QiWJTGN3E0gcHQRTpO0dTXJdJ7RjzZJWflHrGaNVdiTRN2kalTfOIU9VLfnqp5ruM9TTxR+dlIqGKX7uI7IDLrl7PFS2zW1iXSMURGqkbaUc0uiprqWqxa1UOXcxVcxdxAmcRoUApMZDH9HAmeMU+8NxQbYV3Ca25ITCwaRY4immcYk0AUgcv3wtJ3CxeLgBEBw++jpF249akusWsSUltGPNoq0aY5vMVLviusU04b5HbJMoVLo/ItRaBUyBp7rGtjTHuNSGj75BkbdeN/2ckdbWdODENioRSkIopFLThl4hpi0wflZzy0pO5D9aEiDsIFfXQagtf4CAXCqronzWHHFc3CQ/f53rZuGYl198zorYEKOyW0shrUUT2rFu8bc1jdqMUplLIkFi9NhRCvOLA4mp/jCVAjAn+N2qJa1UvXSZkGYjQOylfTu4OQjqPxAhl7atef+JnVQEiiK0Y+2ipzSNq7gCXFT9o1vFRRkB6evnFxJ5642SkWgF4fD4OUxYba4dEW4GLr/0bJY2FGsCCiIUMaVWEX6FDB4cF1D/T1uzJANE4uTxPBaoWbbSlNgcZiDIYsl7mg6d6iWHcEyolb0MPLyFxq1Yq9sXqg31ihx9nb4MsCK298VnxQ3XQaNTjJXd49SuOiJUkEmJIyRy7TSgWg2bf5xlK/sO76defpJuq7ZTgMy61Y9Q7bI7de/Dlndvf8xoAhw7K9uECjX3R46okomTm/rEbt0dh1TixIzqDeI9lSPZD/ZDWDT0uT2PXmqYSSvI7HryUT2pkNTB5K121d82oZ+sWQzJbJXbZmRa3GWBces2UuXX7qOKigryeDy6z0A+wqbosaDIdEYLZtdgSiq3qVcfOH6rnWPaIlQE7MTacp1ImHvuL/Ztz63iE+qpZtN2qp8z13IX6Siix4OjYi7gQCdy+6+aADNSecKys3l/+3fyHc+bb4d0nMl+KLfNyIS9vPTfPyAtEbc8jvjevz5F45r/inIBpqF6aSvV/M1twiTYLX4UCpwzYlIRw17TMnIOS5aJ8E5eE5e8Gza2TO17+nTXb3IdLyehaSeUOsBfVsj3pv77z6hsWmNmH5AJycwFQeb3nqfBqvHU399P4XBYPMfjcWK8DOXz+bK+I4mFCo2GGRh479dZpFbMbhGkSvBzvWHTvFkHd53+zNKe5lR5bjc7SPHoE7h3rOPZjwTU/POftlE+4ORS5ZVEly+OvDm1UTw0bldRsmtoaCC/32/6/SvQgDw3rVSY9GibTv2zfps7qasPHl9o9X1LCYXd5HxnKkbIyQPrt2Q+h325uOOxnGqeOQfsE+vXvxnhN7krROzd/6PUlJkU9nOJrK4mrzf7lPxcaiCt0IxE57msgkkpAQdZNf9G8tYFMr8Ns5PoDKV3YDRl47zp7OnTnUGz75tK6HC82SG3jXbTwhM6Q0U1sZvvFERVz77e1PtbwSptLBVwndN/+PNMxocb+OnGu0acJM/7mVa20Cw+Nb2CFCW2qtsIhFUndPml5wq/mAmTiT2yjep2HKKZ/7CF6r+ylKqqqmyTCdRwlcQNRmXfDeDaEP5JgFjUJzLghSDUfM2+m3UVkE4uthvkNvJz1aZAOgpNJbWv3U/jnnyeZi5bQRMmTHBEohFprfmZa6RC9eFwJcCDmg2igI5RCeP3sq7IKJ2BhzdnXosY0Zjz2gHUm0vltAe/TYFAoCgiVUByQGqhQyf5gBxftddwyiqGh3j056RuGKUTjqhoVR8mc8bf/r2wk6VGmtTdIpIoNWRxRwISCk4UtBqlVEeoUTpRaZcAkYWoOtQ8MG+xaaxZKuCmj1u+ltwArlmtS6icABjRVbczhNqRTqfQFvGM57avU21t6aXnvTOd9PKb79O+l9rpnfYOGn/7WlekFFDNnBxykcDweMeqBZnRigyhmAqjHsSY2xbkiLh0Tpw4MbMZiQ5yAo7T1h2/oG89/iL9aHeQLvQ4jynfaQ8JEqsry6lhUi2dPXeJdr/4vmtSCgnVSalqS+HxK30b5GZGD73E1mvyTcNdKEg6m3hsOeWqjKqDuMf+43VOQA09vHoJNTcGqKbKL0h2ipuWNIqHEaloC115c78rRRUM3UhO8Cyyv+HfYZqG2TBiLEpIaDqQHynNVfHCwMhJhrMHtOzguqUi85GAet52y7W0/Ym7aP7caYJMQD6XAnBQmDjhBhAuqh7foA2tUu0FoVnqrngyjE4WdMeb5upy83uXt3DJdGdigwpjJb5UAJn9nAuJSsMIhVR7QejwBC4BqLsaLPcXIp0Az7vLy8szm1Pq3XEYRoh5US45J3UwT6q9BFf7VjynCfWMqDvGtVUUVDrjhWRx8BIF8FaQTk46OGxD7TEBwg1gQoaq9jrzwkjYSU/H/UsXqJMUVGcEz1aIumt1k/OSibDnP3cfoZ/se7cgTw/8ZN+vRdjUzb+/ekUL/fJouhjtFqFylouETu05h/BFnqQv1ah+ya+czKBL1XKQsIV7/F+89VFGygrx9t09V8RzJBrnEnpEhFOAf9a15BZUTjBjUEWSkq0ebj914+uq/SxmYkIqlbL87J3joczrmqp0Ovpue4icAtGCBGJRue1WwQRQJdRYQ2CkNfpI0+bLqqhRVYod4gWpZqof6R8pSr/85u/F880mcWU+IJ6Fs4NkNs8KZKIIT1UNuQWjTwGpsr6B9QE+D6M6GdAbp9Cod8MJWO9FzL+0JHT1innC/kmAlBsLIBRAbIuHCjte3sMVo2o2FyLuP+N8ZCbyAdmCsTgEIZTv8ZHhRp8mVlukRdQ4Pl0wBqLiCYNwZkWRe5d/RQT0cEwNnMx7V7RQKWE26068P0xi7fXc/l2l/8wuoQC4kVzpfwsqz1gdDYuoOqc9FY1QwcD4USxKiUTCchczySoVZGjjG8clqIGTN4M7qsnZJErEPiVHwPA2pSPDrHUAPquFBEXnw5zUoaEhKhpJfh69PEMZ5BoT78q/L394+H6z/oVLj42sNsWDi543yRFyDBI2ulek5KOEA5OnU8EY4Pb7Uz58Gy4s0rBLZtdBrsJ9VDK4R+jlnsIl9NIbRKE2chNQc0hmKckE3CP0Qkh4eTgmNafPi3ina2RCIsOnecHnT87tpl1wQrVQ1npKoqILDKzjA+HrBgYGnBHamb/2CmLiF7Pf940f/jyW3gfSl+DJ1BB/xP6cfi4FrKIIjNfrJBQr1Ea+VGRwzFUenn5w0OFxon/M+XHPYWchjhvAsh4JlTMuQb08rmchua16r5IMzXZ1UCwWc/adpHW4BiLHmkxAF6/rskkW8nC1PCc3jVMHiya185xwTI6cU611ETrp8N64AWN6rg+htD5O6IiEGrMjY23UMTrOiCfYUdsIWFfcx/PTKZ9MYwqjkKnpOefyFCc0FVJ3UEkttmoDxyR+NJ5/hl4GkNDASsuPpz/Mk5QVY0esWi82ajQv3Z3yeSkV1JRZjQNnTvBxmfRd8BdbqEUKygP8ft9sMQXHNq7azE+EO6eoeXGm5vr0A148zn3f4MW0V0+ZlFSRfiLILxufjgJkwA+v7zRDAlROsopHzBPyNR04Ffpk7eJemYKiBioHuuT4TFFpKFf7IT6+ZFV5MoWXhyXXvcBvxrPcsVnPpfINk4SCh2MUsOQN4ZIqoQNqKY+HTGjRIa5QS1FQvq8OGZdkfIYH+ACmgDvGtEeIWl7LaQIKQR/n4dIRcgzjWixdAV4jMSSaFhkPy4yPwmupO9beUtzFsDPHxLMjO6qinJufxq1pYhvbKOUp7AbDHIBI5O5fHEkH/06hrl+F/VT9Da/WH8KzCOw9/qE9WsybmUCKzgjyblRhVe/zRag97GhvD7ejPmd21AhO7BAfVTn/X9sxeCMKw3BM/vqRDEkFCEOWBBuLrMoss3ICaCtWOEuEs6YmpYL4Kwht2nOqt2PN4qCcPYKJ+hOGFyfgQDW33CneKxgfHKOhm253ZkdNgAmw8sYiF3crHzcDpFNNOdEtYgQsCF+EV5mrSzH2aua1Qe2rTZZqO0IxdlSBKOyOEdRpjMYmCYxSe+XrDKFQe9FkahjqFL5i+4MUbUfHGMapnWFl7VIaaXUHMoRC7bmnykip8S4Yp0M7grSjRUqom8PDuZBr4jGPvvZIdQd0Bo0XSvao2+o0RpPp0M4AO+o0rzfAqo+TEVE/o8MLy+hHd1fQQHlxXUDyTzxO6ro/6AhtOtAe5D8flNvG6dCB9ZsLr5MO5/XFSGmlDbMTvN5H2+73c0J99FmAie1CASKdSCdg4nKZjnHVlsLLFar6Mq93XM5TYMxUVFyqZfTMCj+9/NUynVT+9pq864MtYVyfpS5gSCOZ1Zsk69d2ne4MbWqZhuk5YtkwCqh+brvkglks1Ut378ozAmnEUEJMwk1yUurq9AOtF/o76YVP/ofe7v5/ev/ySUqk+LCJ10/Vvuzi9Nnuk/Re8iy9P8tLA34PNfSlhBTubS2n7rps+QC5X/04RZVxjZwg3R5pRHgw4bbvtT2Z7bR0ntxr/J7F0sQFjRrznpT5PSTjqmde0y3VO//dBxxPhtBu30DE49GpU6dSZWVl5v21h2+niC87cbi69hq6a+b91DJxIb392a/of//8PEWTepMBovq9Gnm81vHtA28nOKn2bbedpZiMkk1GdQdMzwI7ahrbJbdBYM9PR6QbxDZs+bFzezpsR41qf2HA/MZ8Ev6Ydn7wfXrglytp95mdWWQCkMBYbIA0zVoCv6ix75hwTcZ+AMb1Wbzuuc2MTPF9skDzgfY2fhsyDU5RNFGX6qFoEnhoMzmBtKNqwRnqXiwY81Aibj1LxQmhgYe2GMh81rgCJiS4sUDOPJBpyXvUYB+NBlSvj0YoaC9kG4hHOamQUDndcUr1NF7tym/ftBzTI7EkPJkjHBuwOeiKa6lR5uijAILliRlgFTIlc/YeyUmoUP2UpvNkxiYt6NXkiNTO9BCWGj5VeXOPjKLrg1bE53ZiUWPfKeOKZCCXqkvkrVQ0HzyxU2Oks6dGA40TwfJnOzaV/SGdhqpqP6V6ak4bCAlM8LTVah9I+1AiwR/mUjoxYn3sdGu5tiwys5q4cDKb97fn7Ytnq/TTvP/4JjXgN/tBqP/0H/w8/0hpV0iM10ej0cxbC+qXWpIhfo+rM8iMRvqFrcQjPhinAX6MSDhMc88O0sLzTLy+0ttHUS79g7FBcUyQXTFobi7kEvGaPB1xUE3KZTdV2I56Ny1peJWSnuX85RRspxeEHRXdY6Rkym4yObvZIB6dM5+0unqxOrmsrIy+iH1O73QeobLyMt2uIDHGJXmiN0Dfv/lp6rzyKSUScQqU1dOc2rnU0j+RVh3ppjs/9tEN5710z4c+uraH0cRwWmL7tDhFEjF6sJ1R3aBe7TGii4Y0+RthsVNscGjFrg8v2MpIHLZq4/EpeXWt2nBCaNVmLFzkamOh3XgH0R3rafz48aLoHEmE6Y5DN9G4upFKMSQQZK6evY6+Oe+fqaYs25zgpp3/7jpyAtx0ZHvGPn1wtt07HjMW0kNwQvnspgpHedmu0xd6N83jkso8raRIavhXL4lbo+baINhKWhk88l//HSWTSUEqsqKTF39H3dEu7q2TQpUDvkn0vZt20arZ3xCfm558XcBR1obsZ8rjT5v26et55t/0DWkgmSy5wgmZ4tqoAHRsWFBHMe8rmqHdpZO2ktoTe7jeVdGMGTPEZLKPL39IG498U5zQfXMepK9f+5CpVBoByep68ls597FqDisTluy1rCzIYkOj0+5Sxdk1S9qYoU2EVfdDQG3Dlly2WqSh6D2CBwDVt0OiEecfX5c1Rg7VxtBNtaFXiARI7Nm9LWusjJvtXc0Hj2+iAlF0y+Cz31i0iXnYVuPUcozBoF+JmdcXDu2zEEXG1YsYEk2wioHsbgYSy2fO4TdzZXpw0WTaoWVzWNEy2F5olAslamqd7awkrMxAKSGXDMp/KGCGdAOa58wbKQh7yVXcob00Q0kIlTAzARIgtparoFu9662Qs10xpJIXgezGmHZQUkKBYWlt4y/Xm30OSUWDA0ygcLPnEqbJXDls3d2BW5pDpCW/Uwqp1B2XXEI+YgHZigNeGJOwCiUY6hw7c0KQCGeTe1IGwzDPNgz3kAtwjVAJO8SqQFkQzgVk+yZZ/HOVz7sEacbpMJYQveq4RBLb6xaRIz81SgCxSfK0esmzXqN09wP3waWRpV6lgdSeQmLKgn6RxgAZcpnnbkFuCf9BFR8KD3K/f3Q0SdSfwpcAHevQVSLVmNLYAg+j+SBYLOrlNQ0TskP4k15swUIp0s5hFvZY/YcvI/4CeAZjCToTSnsAAAAASUVORK5CYII='; const loadingImages = { darkMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E', lightMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E' // 'data:application/octet-stream;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxzdHlsZT4KCQlAa2V5ZnJhbWVzIHJvdGF0ZSB7CgkJCWZyb20gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CgkJCX0KCQkJdG8gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMzU5ZGVnKTsKCQkJfQoJCX0KCTwvc3R5bGU+Cgk8ZyBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTAlIDUwJTsgYW5pbWF0aW9uOiByb3RhdGUgMXMgaW5maW5pdGUgcmV2ZXJzZSBsaW5lYXI7Ij4KCQk8cmVjdCB4PSIxOC4wOTY4IiB5PSIxNi4wODYxIiB3aWR0aD0iMyIgaGVpZ2h0PSI3IiByeD0iMS41IiB0cmFuc2Zvcm09InJvdGF0ZSgxMzYuMTYxIDE4LjA5NjggMTYuMDg2MSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+CQoJCTxyZWN0IHg9IjguNDk4NzgiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CgkJPHJlY3QgeD0iMTkuOTk3NiIgeT0iOC4zNzQ1MSIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgdHJhbnNmb3JtPSJyb3RhdGUoOTAgMTkuOTk3NiA4LjM3NDUxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjIiLz4KCQk8cmVjdCB4PSIxNi4xNzI3IiB5PSIxLjk5MTciIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgMTYuMTcyNyAxLjk5MTcpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuMyIvPgoJCTxyZWN0IHg9IjguOTEzMDkiIHk9IjYuODg1MDEiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDEzNi4xNjEgOC45MTMwOSA2Ljg4NTAxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KCQk8cmVjdCB4PSI2Ljc5NjAyIiB5PSIxMC45OTYiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgNi43OTYwMiAxMC45OTYpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuNyIvPgoJCTxyZWN0IHg9IjciIHk9IjguNjI1NDkiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDkwIDcgOC42MjU0OSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC44Ii8+CQkKCQk8cmVjdCB4PSI4LjQ5ODc4IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjkiLz4KCTwvZz4KPC9zdmc+Cg==' @@ -4862,117 +5155,128 @@ const videoPlayDark = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23222222%22%2F%3E%0A%3C%2Fsvg%3E%0A'; const videoPlayLight = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23FFFFFF%22%2F%3E%0A%3C%2Fsvg%3E'; - const ddgFont = 'data:application/octet-stream;base64,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'; - const ddgFontBold = 'data:application/octet-stream;base64,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'; - var localesJSON = `{"bg":{"facebook.json":{"informationalModalMessageTitle":"При влизане разрешавате на Facebook да Ви проследява","informationalModalMessageBody":"След като влезете, DuckDuckGo не може да блокира проследяването от Facebook в съдържанието на този сайт.","informationalModalConfirmButtonText":"Вход","informationalModalRejectButtonText":"Назад","loginButtonText":"Вход във Facebook","loginBodyText":"Facebook проследява Вашата активност в съответния сайт, когато го използвате за вход.","buttonTextUnblockContent":"Разблокиране на съдържанието","buttonTextUnblockComment":"Разблокиране на коментара","buttonTextUnblockComments":"Разблокиране на коментарите","buttonTextUnblockPost":"Разблокиране на публикацията","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockContent":"DuckDuckGo блокира това съдържание, за да предотврати проследяване от Facebook","infoTitleUnblockComment":"DuckDuckGo блокира този коментар, за да предотврати проследяване от Facebook","infoTitleUnblockComments":"DuckDuckGo блокира тези коментари, за да предотврати проследяване от Facebook","infoTitleUnblockPost":"DuckDuckGo блокира тази публикация, за да предотврати проследяване от Facebook","infoTitleUnblockVideo":"DuckDuckGo блокира това видео, за да предотврати проследяване от Facebook","infoTextUnblockContent":"Блокирахме проследяването от Facebook при зареждане на страницата. Ако разблокирате това съдържание, Facebook ще следи Вашата активност."},"shared.json":{"learnMore":"Научете повече","readAbout":"Прочетете за тази защита на поверителността"},"youtube.json":{"informationalModalMessageTitle":"Активиране на всички прегледи в YouTube?","informationalModalMessageBody":"Показването на преглед позволява на Google (собственик на YouTube) да види част от информацията за Вашето устройство, но все пак осигурява повече поверителност отколкото при възпроизвеждане на видеоклипа.","informationalModalConfirmButtonText":"Активиране на всички прегледи","informationalModalRejectButtonText":"Не, благодаря","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockVideo":"DuckDuckGo блокира този видеоклип в YouTube, за да предотврати проследяване от Google","infoTextUnblockVideo":"Блокирахме проследяването от Google (собственик на YouTube) при зареждане на страницата. Ако разблокирате този видеоклип, Google ще следи Вашата активност.","infoPreviewToggleText":"Прегледите са деактивирани за осигуряване на допълнителна поверителност","infoPreviewToggleEnabledText":"Прегледите са активирани","infoPreviewInfoText":"Научете повече за вградената защита от социални медии на DuckDuckGo"}},"cs":{"facebook.json":{"informationalModalMessageTitle":"Když se přihlásíš přes Facebook, bude tě moct sledovat","informationalModalMessageBody":"Po přihlášení už DuckDuckGo nemůže bránit Facebooku, aby tě na téhle stránce sledoval.","informationalModalConfirmButtonText":"Přihlásit se","informationalModalRejectButtonText":"Zpět","loginButtonText":"Přihlásit se pomocí Facebooku","loginBodyText":"Facebook sleduje tvou aktivitu na webu, když se přihlásíš jeho prostřednictvím.","buttonTextUnblockContent":"Odblokovat obsah","buttonTextUnblockComment":"Odblokovat komentář","buttonTextUnblockComments":"Odblokovat komentáře","buttonTextUnblockPost":"Odblokovat příspěvek","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockContent":"DuckDuckGo zablokoval tenhle obsah, aby Facebooku zabránil tě sledovat","infoTitleUnblockComment":"Služba DuckDuckGo zablokovala tento komentář, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockComments":"Služba DuckDuckGo zablokovala tyto komentáře, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockPost":"DuckDuckGo zablokoval tenhle příspěvek, aby Facebooku zabránil tě sledovat","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video, aby Facebooku zabránil tě sledovat","infoTextUnblockContent":"Při načítání stránky jsme Facebooku zabránili, aby tě sledoval. Když tenhle obsah odblokuješ, Facebook bude mít přístup ke tvé aktivitě."},"shared.json":{"learnMore":"Více informací","readAbout":"Přečti si o téhle ochraně soukromí"},"youtube.json":{"informationalModalMessageTitle":"Zapnout všechny náhledy YouTube?","informationalModalMessageBody":"Zobrazování náhledů umožní společnosti Google (která vlastní YouTube) zobrazit některé informace o tvém zařízení, ale pořád jde o diskrétnější volbu, než je přehrávání videa.","informationalModalConfirmButtonText":"Zapnout všechny náhledy","informationalModalRejectButtonText":"Ne, děkuji","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video z YouTube, aby Googlu zabránil tě sledovat","infoTextUnblockVideo":"Zabránili jsme společnosti Google (která vlastní YouTube), aby tě při načítání stránky sledovala. Pokud toto video odblokuješ, Google získá přístup ke tvé aktivitě.","infoPreviewToggleText":"Náhledy jsou pro větší soukromí vypnuté","infoPreviewToggleEnabledText":"Náhledy jsou zapnuté","infoPreviewInfoText":"Další informace o ochraně DuckDuckGo před sledováním prostřednictvím vloženého obsahu ze sociálních médií"}},"da":{"facebook.json":{"informationalModalMessageTitle":"Når du logger ind med Facebook, kan de spore dig","informationalModalMessageBody":"Når du er logget ind, kan DuckDuckGo ikke blokere for, at indhold fra Facebook sporer dig på dette websted.","informationalModalConfirmButtonText":"Log på","informationalModalRejectButtonText":"Gå tilbage","loginButtonText":"Log ind med Facebook","loginBodyText":"Facebook sporer din aktivitet på et websted, når du bruger dem til at logge ind.","buttonTextUnblockContent":"Fjern blokering af indhold","buttonTextUnblockComment":"Fjern blokering af kommentar","buttonTextUnblockComments":"Fjern blokering af kommentarer","buttonTextUnblockPost":"Fjern blokering af indlæg","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockContent":"DuckDuckGo har blokeret dette indhold for at forhindre Facebook i at spore dig","infoTitleUnblockComment":"DuckDuckGo har blokeret denne kommentar for at forhindre Facebook i at spore dig","infoTitleUnblockComments":"DuckDuckGo har blokeret disse kommentarer for at forhindre Facebook i at spore dig","infoTitleUnblockPost":"DuckDuckGo blokerede dette indlæg for at forhindre Facebook i at spore dig","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne video for at forhindre Facebook i at spore dig","infoTextUnblockContent":"Vi blokerede for, at Facebook sporede dig, da siden blev indlæst. Hvis du ophæver blokeringen af dette indhold, vil Facebook kende din aktivitet."},"shared.json":{"learnMore":"Mere info","readAbout":"Læs om denne beskyttelse af privatlivet"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Med forhåndsvisninger kan Google (som ejer YouTube) se nogle af enhedens oplysninger, men det er stadig mere privat end at afspille videoen.","informationalModalConfirmButtonText":"Aktivér alle forhåndsvisninger","informationalModalRejectButtonText":"Nej tak.","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne YouTube-video for at forhindre Google i at spore dig","infoTextUnblockVideo":"Vi blokerede Google (som ejer YouTube) fra at spore dig, da siden blev indlæst. Hvis du fjerner blokeringen af denne video, vil Google få kendskab til din aktivitet.","infoPreviewToggleText":"Forhåndsvisninger er deaktiveret for at give yderligere privatliv","infoPreviewToggleEnabledText":"Forhåndsvisninger er deaktiveret","infoPreviewInfoText":"Få mere at vide på om DuckDuckGos indbyggede beskyttelse på sociale medier"}},"de":{"facebook.json":{"informationalModalMessageTitle":"Wenn du dich bei Facebook anmeldest, kann Facebook dich tracken","informationalModalMessageBody":"Sobald du angemeldet bist, kann DuckDuckGo nicht mehr verhindern, dass Facebook-Inhalte dich auf dieser Website tracken.","informationalModalConfirmButtonText":"Anmelden","informationalModalRejectButtonText":"Zurück","loginButtonText":"Mit Facebook anmelden","loginBodyText":"Facebook trackt deine Aktivität auf einer Website, wenn du dich über Facebook dort anmeldest.","buttonTextUnblockContent":"Blockierung aufheben","buttonTextUnblockComment":"Blockierung aufheben","buttonTextUnblockComments":"Blockierung aufheben","buttonTextUnblockPost":"Blockierung aufheben","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockContent":"DuckDuckGo hat diesen Inhalt blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComment":"DuckDuckGo hat diesen Kommentar blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComments":"DuckDuckGo hat diese Kommentare blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockPost":"DuckDuckGo hat diesen Beitrag blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockVideo":"DuckDuckGo hat dieses Video blockiert, um zu verhindern, dass Facebook dich trackt","infoTextUnblockContent":"Wir haben Facebook daran gehindert, dich zu tracken, als die Seite geladen wurde. Wenn du die Blockierung für diesen Inhalt aufhebst, kennt Facebook deine Aktivitäten."},"shared.json":{"learnMore":"Mehr erfahren","readAbout":"Weitere Informationen über diesen Datenschutz"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-Vorschauen aktivieren?","informationalModalMessageBody":"Durch das Anzeigen von Vorschauen kann Google (dem YouTube gehört) einige Informationen zu deinem Gerät sehen. Dies ist aber immer noch privater als das Abspielen des Videos.","informationalModalConfirmButtonText":"Alle Vorschauen aktivieren","informationalModalRejectButtonText":"Nein, danke","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockVideo":"DuckDuckGo hat dieses YouTube-Video blockiert, um zu verhindern, dass Google dich trackt.","infoTextUnblockVideo":"Wir haben Google (dem YouTube gehört) daran gehindert, dich beim Laden der Seite zu tracken. Wenn du die Blockierung für dieses Video aufhebst, kennt Google deine Aktivitäten.","infoPreviewToggleText":"Vorschau für mehr Privatsphäre deaktiviert","infoPreviewToggleEnabledText":"Vorschau aktiviert","infoPreviewInfoText":"Erfahre mehr über den DuckDuckGo-Schutz vor eingebetteten Social Media-Inhalten"}},"el":{"facebook.json":{"informationalModalMessageTitle":"Η σύνδεση μέσω Facebook τους επιτρέπει να σας παρακολουθούν","informationalModalMessageBody":"Μόλις συνδεθείτε, το DuckDuckGo δεν μπορεί να εμποδίσει το περιεχόμενο του Facebook από το να σας παρακολουθεί σε αυτόν τον ιστότοπο.","informationalModalConfirmButtonText":"Σύνδεση","informationalModalRejectButtonText":"Επιστροφή","loginButtonText":"Σύνδεση μέσω Facebook","loginBodyText":"Το Facebook παρακολουθεί τη δραστηριότητά σας σε έναν ιστότοπο όταν τον χρησιμοποιείτε για να συνδεθείτε.","buttonTextUnblockContent":"Άρση αποκλεισμού περιεχομένου","buttonTextUnblockComment":"Άρση αποκλεισμού σχολίου","buttonTextUnblockComments":"Άρση αποκλεισμού σχολίων","buttonTextUnblockPost":"Άρση αποκλεισμού ανάρτησης","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockContent":"Το DuckDuckGo απέκλεισε το περιεχόμενο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComment":"Το DuckDuckGo απέκλεισε το σχόλιο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComments":"Το DuckDuckGo απέκλεισε τα σχόλια αυτά για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockPost":"Το DuckDuckGo απέκλεισε την ανάρτηση αυτή για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTextUnblockContent":"Αποκλείσαμε το Facebook από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το περιεχόμενο, το Facebook θα γνωρίζει τη δραστηριότητά σας."},"shared.json":{"learnMore":"Μάθετε περισσότερα","readAbout":"Διαβάστε σχετικά με την παρούσα προστασίας προσωπικών δεδομένων"},"youtube.json":{"informationalModalMessageTitle":"Ενεργοποίηση όλων των προεπισκοπήσεων του YouTube;","informationalModalMessageBody":"Η προβολή των προεπισκοπήσεων θα επιτρέψει στην Google (στην οποία ανήκει το YouTube) να βλέπει ορισμένες από τις πληροφορίες της συσκευής σας, ωστόσο εξακολουθεί να είναι πιο ιδιωτική από την αναπαραγωγή του βίντεο.","informationalModalConfirmButtonText":"Ενεργοποίηση όλων των προεπισκοπήσεων","informationalModalRejectButtonText":"Όχι, ευχαριστώ","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό στο YouTube για να εμποδίσει την Google από το να σας παρακολουθεί","infoTextUnblockVideo":"Αποκλείσαμε την Google (στην οποία ανήκει το YouTube) από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το βίντεο, η Google θα γνωρίζει τη δραστηριότητά σας.","infoPreviewToggleText":"Οι προεπισκοπήσεις απενεργοποιήθηκαν για πρόσθετη προστασία των προσωπικών δεδομένων","infoPreviewToggleEnabledText":"Οι προεπισκοπήσεις ενεργοποιήθηκαν","infoPreviewInfoText":"Μάθετε περισσότερα για την ενσωματωμένη προστασία κοινωνικών μέσων DuckDuckGo"}},"en":{"facebook.json":{"informationalModalMessageTitle":"Logging in with Facebook lets them track you","informationalModalMessageBody":"Once you're logged in, DuckDuckGo can't block Facebook content from tracking you on this site.","informationalModalConfirmButtonText":"Log In","informationalModalRejectButtonText":"Go back","loginButtonText":"Log in with Facebook","loginBodyText":"Facebook tracks your activity on a site when you use them to login.","buttonTextUnblockContent":"Unblock Content","buttonTextUnblockComment":"Unblock Comment","buttonTextUnblockComments":"Unblock Comments","buttonTextUnblockPost":"Unblock Post","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockContent":"DuckDuckGo blocked this content to prevent Facebook from tracking you","infoTitleUnblockComment":"DuckDuckGo blocked this comment to prevent Facebook from tracking you","infoTitleUnblockComments":"DuckDuckGo blocked these comments to prevent Facebook from tracking you","infoTitleUnblockPost":"DuckDuckGo blocked this post to prevent Facebook from tracking you","infoTitleUnblockVideo":"DuckDuckGo blocked this video to prevent Facebook from tracking you","infoTextUnblockContent":"We blocked Facebook from tracking you when the page loaded. If you unblock this content, Facebook will know your activity."},"shared.json":{"learnMore":"Learn More","readAbout":"Read about this privacy protection"},"youtube.json":{"informationalModalMessageTitle":"Enable all YouTube previews?","informationalModalMessageBody":"Showing previews will allow Google (which owns YouTube) to see some of your device’s information, but is still more private than playing the video.","informationalModalConfirmButtonText":"Enable All Previews","informationalModalRejectButtonText":"No Thanks","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockVideo":"DuckDuckGo blocked this YouTube video to prevent Google from tracking you","infoTextUnblockVideo":"We blocked Google (which owns YouTube) from tracking you when the page loaded. If you unblock this video, Google will know your activity.","infoPreviewToggleText":"Previews disabled for additional privacy","infoPreviewToggleEnabledText":"Previews enabled","infoPreviewInfoText":"Learn more about DuckDuckGo Embedded Social Media Protection"}},"es":{"facebook.json":{"informationalModalMessageTitle":"Al iniciar sesión en Facebook, les permites que te rastreen","informationalModalMessageBody":"Una vez que hayas iniciado sesión, DuckDuckGo no puede bloquear el contenido de Facebook para que no te rastree en este sitio.","informationalModalConfirmButtonText":"Iniciar sesión","informationalModalRejectButtonText":"Volver atrás","loginButtonText":"Iniciar sesión con Facebook","loginBodyText":"Facebook rastrea tu actividad en un sitio web cuando lo usas para iniciar sesión.","buttonTextUnblockContent":"Desbloquear contenido","buttonTextUnblockComment":"Desbloquear comentario","buttonTextUnblockComments":"Desbloquear comentarios","buttonTextUnblockPost":"Desbloquear publicación","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockContent":"DuckDuckGo ha bloqueado este contenido para evitar que Facebook te rastree","infoTitleUnblockComment":"DuckDuckGo ha bloqueado este comentario para evitar que Facebook te rastree","infoTitleUnblockComments":"DuckDuckGo ha bloqueado estos comentarios para evitar que Facebook te rastree","infoTitleUnblockPost":"DuckDuckGo ha bloqueado esta publicación para evitar que Facebook te rastree","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo para evitar que Facebook te rastree","infoTextUnblockContent":"Hemos bloqueado el rastreo de Facebook cuando se ha cargado la página. Si desbloqueas este contenido, Facebook tendrá conocimiento de tu actividad."},"shared.json":{"learnMore":"Más información","readAbout":"Lee acerca de esta protección de privacidad"},"youtube.json":{"informationalModalMessageTitle":"¿Habilitar todas las vistas previas de YouTube?","informationalModalMessageBody":"Mostrar vistas previas permitirá a Google (que es el propietario de YouTube) ver parte de la información de tu dispositivo, pero sigue siendo más privado que reproducir el vídeo.","informationalModalConfirmButtonText":"Habilitar todas las vistas previas","informationalModalRejectButtonText":"No, gracias","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo de YouTube para evitar que Google te rastree","infoTextUnblockVideo":"Hemos bloqueado el rastreo de Google (que es el propietario de YouTube) al cargarse la página. Si desbloqueas este vídeo, Goggle tendrá conocimiento de tu actividad.","infoPreviewToggleText":"Vistas previas desactivadas para mayor privacidad","infoPreviewToggleEnabledText":"Vistas previas activadas","infoPreviewInfoText":"Más información sobre la protección integrada de redes sociales DuckDuckGo"}},"et":{"facebook.json":{"informationalModalMessageTitle":"Kui logid Facebookiga sisse, saab Facebook sind jälgida","informationalModalMessageBody":"Kui oled sisse logitud, ei saa DuckDuckGo blokeerida Facebooki sisu sind jälgimast.","informationalModalConfirmButtonText":"Logi sisse","informationalModalRejectButtonText":"Mine tagasi","loginButtonText":"Logi sisse Facebookiga","loginBodyText":"Kui logid sisse Facebookiga, saab Facebook sinu tegevust saidil jälgida.","buttonTextUnblockContent":"Deblokeeri sisu","buttonTextUnblockComment":"Deblokeeri kommentaar","buttonTextUnblockComments":"Deblokeeri kommentaarid","buttonTextUnblockPost":"Deblokeeri postitus","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockContent":"DuckDuckGo blokeeris selle sisu, et Facebook ei saaks sind jälgida","infoTitleUnblockComment":"DuckDuckGo blokeeris selle kommentaari, et Facebook ei saaks sind jälgida","infoTitleUnblockComments":"DuckDuckGo blokeeris need kommentaarid, et Facebook ei saaks sind jälgida","infoTitleUnblockPost":"DuckDuckGo blokeeris selle postituse, et Facebook ei saaks sind jälgida","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle video, et Facebook ei saaks sind jälgida","infoTextUnblockContent":"Blokeerisime lehe laadimise ajal Facebooki jaoks sinu jälgimise. Kui sa selle sisu deblokeerid, saab Facebook sinu tegevust jälgida."},"shared.json":{"learnMore":"Loe edasi","readAbout":"Loe selle privaatsuskaitse kohta"},"youtube.json":{"informationalModalMessageTitle":"Kas lubada kõik YouTube’i eelvaated?","informationalModalMessageBody":"Eelvaate näitamine võimaldab Google’il (kellele YouTube kuulub) näha osa sinu seadme teabest, kuid see on siiski privaatsem kui video esitamine.","informationalModalConfirmButtonText":"Luba kõik eelvaated","informationalModalRejectButtonText":"Ei aitäh","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle YouTube’i video, et takistada Google’it sind jälgimast","infoTextUnblockVideo":"Me blokeerisime lehe laadimise ajal Google’i (kellele YouTube kuulub) jälgimise. Kui sa selle video deblokeerid, saab Google sinu tegevusest teada.","infoPreviewToggleText":"Eelvaated on täiendava privaatsuse tagamiseks keelatud","infoPreviewToggleEnabledText":"Eelvaated on lubatud","infoPreviewInfoText":"Lisateave DuckDuckGo sisseehitatud sotsiaalmeediakaitse kohta"}},"fi":{"facebook.json":{"informationalModalMessageTitle":"Kun kirjaudut sisään Facebook-tunnuksilla, Facebook voi seurata sinua","informationalModalMessageBody":"Kun olet kirjautunut sisään, DuckDuckGo ei voi estää Facebook-sisältöä seuraamasta sinua tällä sivustolla.","informationalModalConfirmButtonText":"Kirjaudu sisään","informationalModalRejectButtonText":"Edellinen","loginButtonText":"Kirjaudu sisään Facebook-tunnuksilla","loginBodyText":"Facebook seuraa toimintaasi sivustolla, kun kirjaudut sisään sen kautta.","buttonTextUnblockContent":"Poista sisällön esto","buttonTextUnblockComment":"Poista kommentin esto","buttonTextUnblockComments":"Poista kommenttien esto","buttonTextUnblockPost":"Poista julkaisun esto","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockContent":"DuckDuckGo esti tämän sisällön estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComment":"DuckDuckGo esti tämän kommentin estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComments":"DuckDuckGo esti nämä kommentit estääkseen Facebookia seuraamasta sinua","infoTitleUnblockPost":"DuckDuckGo esti tämän julkaisun estääkseen Facebookia seuraamasta sinua","infoTitleUnblockVideo":"DuckDuckGo esti tämän videon estääkseen Facebookia seuraamasta sinua","infoTextUnblockContent":"Estimme Facebookia seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän sisällön eston, Facebook saa tietää toimintasi."},"shared.json":{"learnMore":"Lue lisää","readAbout":"Lue tästä yksityisyydensuojasta"},"youtube.json":{"informationalModalMessageTitle":"Otetaanko käyttöön kaikki YouTube-esikatselut?","informationalModalMessageBody":"Kun sallit esikatselun, Google (joka omistaa YouTuben) voi nähdä joitakin laitteesi tietoja, mutta se on silti yksityisempää kuin videon toistaminen.","informationalModalConfirmButtonText":"Ota käyttöön kaikki esikatselut","informationalModalRejectButtonText":"Ei kiitos","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockVideo":"DuckDuckGo esti tämän YouTube-videon, jotta Google ei voi seurata sinua","infoTextUnblockVideo":"Estimme Googlea (joka omistaa YouTuben) seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän videon eston, Google tietää toimintasi.","infoPreviewToggleText":"Esikatselut on poistettu käytöstä yksityisyyden lisäämiseksi","infoPreviewToggleEnabledText":"Esikatselut käytössä","infoPreviewInfoText":"Lue lisää DuckDuckGon upotetusta sosiaalisen median suojauksesta"}},"fr":{"facebook.json":{"informationalModalMessageTitle":"L'identification via Facebook leur permet de vous pister","informationalModalMessageBody":"Une fois que vous êtes connecté(e), DuckDuckGo ne peut pas empêcher le contenu Facebook de vous pister sur ce site.","informationalModalConfirmButtonText":"Connexion","informationalModalRejectButtonText":"Revenir en arrière","loginButtonText":"S'identifier avec Facebook","loginBodyText":"Facebook piste votre activité sur un site lorsque vous l'utilisez pour vous identifier.","buttonTextUnblockContent":"Débloquer le contenu","buttonTextUnblockComment":"Débloquer le commentaire","buttonTextUnblockComments":"Débloquer les commentaires","buttonTextUnblockPost":"Débloquer la publication","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockContent":"DuckDuckGo a bloqué ce contenu pour empêcher Facebook de vous suivre","infoTitleUnblockComment":"DuckDuckGo a bloqué ce commentaire pour empêcher Facebook de vous suivre","infoTitleUnblockComments":"DuckDuckGo a bloqué ces commentaires pour empêcher Facebook de vous suivre","infoTitleUnblockPost":"DuckDuckGo a bloqué cette publication pour empêcher Facebook de vous pister","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo pour empêcher Facebook de vous pister","infoTextUnblockContent":"Nous avons empêché Facebook de vous pister lors du chargement de la page. Si vous débloquez ce contenu, Facebook connaîtra votre activité."},"shared.json":{"learnMore":"En savoir plus","readAbout":"En savoir plus sur cette protection de la confidentialité"},"youtube.json":{"informationalModalMessageTitle":"Activer tous les aperçus YouTube ?","informationalModalMessageBody":"L'affichage des aperçus permettra à Google (propriétaire de YouTube) de voir certaines informations de votre appareil, mais cela reste davantage confidentiel qu'en lisant la vidéo.","informationalModalConfirmButtonText":"Activer tous les aperçus","informationalModalRejectButtonText":"Non merci","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo YouTube pour empêcher Google de vous pister","infoTextUnblockVideo":"Nous avons empêché Google (propriétaire de YouTube) de vous pister lors du chargement de la page. Si vous débloquez cette vidéo, Google connaîtra votre activité.","infoPreviewToggleText":"Aperçus désactivés pour plus de confidentialité","infoPreviewToggleEnabledText":"Aperçus activés","infoPreviewInfoText":"En savoir plus sur la protection intégrée DuckDuckGo des réseaux sociaux"}},"hr":{"facebook.json":{"informationalModalMessageTitle":"Prijava putem Facebooka omogućuje im da te prate","informationalModalMessageBody":"Nakon što se prijaviš, DuckDuckGo ne može blokirati Facebookov sadržaj da te prati na Facebooku.","informationalModalConfirmButtonText":"Prijavljivanje","informationalModalRejectButtonText":"Vrati se","loginButtonText":"Prijavi se putem Facebooka","loginBodyText":"Facebook prati tvoju aktivnost na toj web lokaciji kad je koristiš za prijavu.","buttonTextUnblockContent":"Deblokiranje sadržaja","buttonTextUnblockComment":"Deblokiranje komentara","buttonTextUnblockComments":"Deblokiranje komentara","buttonTextUnblockPost":"Deblokiranje objave","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockContent":"DuckDuckGo je blokirao ovaj sadržaj kako bi spriječio Facebook da te prati","infoTitleUnblockComment":"DuckDuckGo je blokirao ovaj komentar kako bi spriječio Facebook da te prati","infoTitleUnblockComments":"DuckDuckGo je blokirao ove komentare kako bi spriječio Facebook da te prati","infoTitleUnblockPost":"DuckDuckGo je blokirao ovu objavu kako bi spriječio Facebook da te prati","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj video kako bi spriječio Facebook da te prati","infoTextUnblockContent":"Blokirali smo Facebook da te prati kad se stranica učita. Ako deblokiraš ovaj sadržaj, Facebook će znati tvoju aktivnost."},"shared.json":{"learnMore":"Saznajte više","readAbout":"Pročitaj više o ovoj zaštiti privatnosti"},"youtube.json":{"informationalModalMessageTitle":"Omogućiti sve YouTube pretpreglede?","informationalModalMessageBody":"Prikazivanje pretpregleda omogućit će Googleu (u čijem je vlasništvu YouTube) da vidi neke podatke o tvom uređaju, ali je i dalje privatnija opcija od reprodukcije videozapisa.","informationalModalConfirmButtonText":"Omogući sve pretpreglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj YouTube videozapis kako bi spriječio Google da te prati","infoTextUnblockVideo":"Blokirali smo Google (u čijem je vlasništvu YouTube) da te prati kad se stranica učita. Ako deblokiraš ovaj videozapis, Google će znati tvoju aktivnost.","infoPreviewToggleText":"Pretpregledi su onemogućeni radi dodatne privatnosti","infoPreviewToggleEnabledText":"Pretpregledi su omogućeni","infoPreviewInfoText":"Saznaj više o uključenoj DuckDuckGo zaštiti od društvenih medija"}},"hu":{"facebook.json":{"informationalModalMessageTitle":"A Facebookkal való bejelentkezéskor a Facebook nyomon követhet","informationalModalMessageBody":"Miután bejelentkezel, a DuckDuckGo nem fogja tudni blokkolni a Facebook-tartalmat, amely nyomon követ ezen az oldalon.","informationalModalConfirmButtonText":"Bejelentkezés","informationalModalRejectButtonText":"Visszalépés","loginButtonText":"Bejelentkezés Facebookkal","loginBodyText":"Ha a Facebookkal jelentkezel be, nyomon követik a webhelyen végzett tevékenységedet.","buttonTextUnblockContent":"Tartalom feloldása","buttonTextUnblockComment":"Hozzászólás feloldása","buttonTextUnblockComments":"Hozzászólások feloldása","buttonTextUnblockPost":"Bejegyzés feloldása","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockContent":"A DuckDuckGo blokkolta ezt a tartalmat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComment":"A DuckDuckGo blokkolta ezt a hozzászólást, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComments":"A DuckDuckGo blokkolta ezeket a hozzászólásokat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockPost":"A DuckDuckGo blokkolta ezt a bejegyzést, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockVideo":"A DuckDuckGo blokkolta ezt a videót, hogy megakadályozza a Facebookot a nyomon követésedben","infoTextUnblockContent":"Az oldal betöltésekor blokkoltuk a Facebookot a nyomon követésedben. Ha feloldod ezt a tartalmat, a Facebook tudni fogja, hogy milyen tevékenységet végzel."},"shared.json":{"learnMore":"További részletek","readAbout":"Tudj meg többet erről az adatvédelemről"},"youtube.json":{"informationalModalMessageTitle":"Engedélyezed minden YouTube-videó előnézetét?","informationalModalMessageBody":"Az előnézetek megjelenítésével a Google (a YouTube tulajdonosa) láthatja a készülék néhány adatát, de ez adatvédelmi szempontból még mindig előnyösebb, mint a videó lejátszása.","informationalModalConfirmButtonText":"Minden előnézet engedélyezése","informationalModalRejectButtonText":"Nem, köszönöm","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockVideo":"A DuckDuckGo blokkolta a YouTube-videót, hogy a Google ne követhessen nyomon","infoTextUnblockVideo":"Blokkoltuk, hogy a Google (a YouTube tulajdonosa) nyomon követhessen az oldal betöltésekor. Ha feloldod a videó blokkolását, a Google tudni fogja, hogy milyen tevékenységet végzel.","infoPreviewToggleText":"Az előnézetek a fokozott adatvédelem érdekében letiltva","infoPreviewToggleEnabledText":"Az előnézetek engedélyezve","infoPreviewInfoText":"További tudnivalók a DuckDuckGo beágyazott közösségi média elleni védelméről"}},"it":{"facebook.json":{"informationalModalMessageTitle":"L'accesso con Facebook consente di tracciarti","informationalModalMessageBody":"Dopo aver effettuato l'accesso, DuckDuckGo non può bloccare il tracciamento dei contenuti di Facebook su questo sito.","informationalModalConfirmButtonText":"Accedi","informationalModalRejectButtonText":"Torna indietro","loginButtonText":"Accedi con Facebook","loginBodyText":"Facebook tiene traccia della tua attività su un sito quando lo usi per accedere.","buttonTextUnblockContent":"Sblocca contenuti","buttonTextUnblockComment":"Sblocca commento","buttonTextUnblockComments":"Sblocca commenti","buttonTextUnblockPost":"Sblocca post","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockContent":"DuckDuckGo ha bloccato questo contenuto per impedire a Facebook di tracciarti","infoTitleUnblockComment":"DuckDuckGo ha bloccato questo commento per impedire a Facebook di tracciarti","infoTitleUnblockComments":"DuckDuckGo ha bloccato questi commenti per impedire a Facebook di tracciarti","infoTitleUnblockPost":"DuckDuckGo ha bloccato questo post per impedire a Facebook di tracciarti","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video per impedire a Facebook di tracciarti","infoTextUnblockContent":"Abbiamo impedito a Facebook di tracciarti al caricamento della pagina. Se sblocchi questo contenuto, Facebook conoscerà la tua attività."},"shared.json":{"learnMore":"Ulteriori informazioni","readAbout":"Leggi di più su questa protezione della privacy"},"youtube.json":{"informationalModalMessageTitle":"Abilitare tutte le anteprime di YouTube?","informationalModalMessageBody":"La visualizzazione delle anteprime consentirà a Google (che possiede YouTube) di vedere alcune delle informazioni del tuo dispositivo, ma è comunque più privato rispetto alla riproduzione del video.","informationalModalConfirmButtonText":"Abilita tutte le anteprime","informationalModalRejectButtonText":"No, grazie","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video di YouTube per impedire a Google di tracciarti","infoTextUnblockVideo":"Abbiamo impedito a Google (che possiede YouTube) di tracciarti quando la pagina è stata caricata. Se sblocchi questo video, Google conoscerà la tua attività.","infoPreviewToggleText":"Anteprime disabilitate per una maggiore privacy","infoPreviewToggleEnabledText":"Anteprime abilitate","infoPreviewInfoText":"Scopri di più sulla protezione dai social media integrata di DuckDuckGo"}},"lt":{"facebook.json":{"informationalModalMessageTitle":"Prisijungę prie „Facebook“ galite būti sekami","informationalModalMessageBody":"Kai esate prisijungę, „DuckDuckGo“ negali užblokuoti „Facebook“ turinio, todėl esate sekami šioje svetainėje.","informationalModalConfirmButtonText":"Prisijungti","informationalModalRejectButtonText":"Grįžti atgal","loginButtonText":"Prisijunkite su „Facebook“","loginBodyText":"„Facebook“ seka jūsų veiklą svetainėje, kai prisijungiate su šia svetaine.","buttonTextUnblockContent":"Atblokuoti turinį","buttonTextUnblockComment":"Atblokuoti komentarą","buttonTextUnblockComments":"Atblokuoti komentarus","buttonTextUnblockPost":"Atblokuoti įrašą","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockContent":"„DuckDuckGo“ užblokavo šį turinį, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComment":"„DuckDuckGo“ užblokavo šį komentarą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComments":"„DuckDuckGo“ užblokavo šiuos komentarus, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockPost":"„DuckDuckGo“ užblokavo šį įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį vaizdo įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTextUnblockContent":"Užblokavome „Facebook“, kad negalėtų jūsų sekti, kai puslapis buvo įkeltas. Jei atblokuosite šį turinį, „Facebook“ žinos apie jūsų veiklą."},"shared.json":{"learnMore":"Sužinoti daugiau","readAbout":"Skaitykite apie šią privatumo apsaugą"},"youtube.json":{"informationalModalMessageTitle":"Įjungti visas „YouTube“ peržiūras?","informationalModalMessageBody":"Peržiūrų rodymas leis „Google“ (kuriai priklauso „YouTube“) matyti tam tikrą jūsų įrenginio informaciją, tačiau ji vis tiek bus privatesnė nei leidžiant vaizdo įrašą.","informationalModalConfirmButtonText":"Įjungti visas peržiūras","informationalModalRejectButtonText":"Ne, dėkoju","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį „YouTube“ vaizdo įrašą, kad „Google“ negalėtų jūsų sekti","infoTextUnblockVideo":"Užblokavome „Google“ (kuriai priklauso „YouTube“) galimybę sekti jus, kai puslapis buvo įkeltas. Jei atblokuosite šį vaizdo įrašą, „Google“ sužinos apie jūsų veiklą.","infoPreviewToggleText":"Peržiūros išjungtos dėl papildomo privatumo","infoPreviewToggleEnabledText":"Peržiūros įjungtos","infoPreviewInfoText":"Sužinokite daugiau apie „DuckDuckGo“ įdėtąją socialinės žiniasklaidos apsaugą"}},"lv":{"facebook.json":{"informationalModalMessageTitle":"Ja pieteiksies ar Facebook, viņi varēs tevi izsekot","informationalModalMessageBody":"Kad tu piesakies, DuckDuckGo nevar novērst, ka Facebook saturs tevi izseko šajā vietnē.","informationalModalConfirmButtonText":"Pieteikties","informationalModalRejectButtonText":"Atgriezties","loginButtonText":"Pieteikties ar Facebook","loginBodyText":"Facebook izseko tavas aktivitātes vietnē, kad esi pieteicies ar Facebook.","buttonTextUnblockContent":"Atbloķēt saturu","buttonTextUnblockComment":"Atbloķēt komentāru","buttonTextUnblockComments":"Atbloķēt komentārus","buttonTextUnblockPost":"Atbloķēt ziņu","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockContent":"DuckDuckGo bloķēja šo saturu, lai neļautu Facebook tevi izsekot","infoTitleUnblockComment":"DuckDuckGo bloķēja šo komentāru, lai neļautu Facebook tevi izsekot","infoTitleUnblockComments":"DuckDuckGo bloķēja šos komentārus, lai neļautu Facebook tevi izsekot","infoTitleUnblockPost":"DuckDuckGo bloķēja šo ziņu, lai neļautu Facebook tevi izsekot","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo videoklipu, lai neļautu Facebook tevi izsekot","infoTextUnblockContent":"Mēs bloķējām Facebook iespēju tevi izsekot, ielādējot lapu. Ja atbloķēsi šo saturu, Facebook redzēs, ko tu dari."},"shared.json":{"learnMore":"Uzzināt vairāk","readAbout":"Lasi par šo privātuma aizsardzību"},"youtube.json":{"informationalModalMessageTitle":"Vai iespējot visus YouTube priekšskatījumus?","informationalModalMessageBody":"Priekšskatījumu rādīšana ļaus Google (kam pieder YouTube) redzēt daļu tavas ierīces informācijas, taču tas tāpat ir privātāk par videoklipa atskaņošanu.","informationalModalConfirmButtonText":"Iespējot visus priekšskatījumus","informationalModalRejectButtonText":"Nē, paldies","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo YouTube videoklipu, lai neļautu Google tevi izsekot","infoTextUnblockVideo":"Mēs neļāvām Google (kam pieder YouTube) tevi izsekot, kad lapa tika ielādēta. Ja atbloķēsi šo videoklipu, Google zinās, ko tu dari.","infoPreviewToggleText":"Priekšskatījumi ir atspējoti, lai nodrošinātu papildu konfidencialitāti","infoPreviewToggleEnabledText":"Priekšskatījumi ir iespējoti","infoPreviewInfoText":"Uzzini vairāk par DuckDuckGo iegulto sociālo mediju aizsardzību"}},"nb":{"facebook.json":{"informationalModalMessageTitle":"Når du logger på med Facebook, kan de spore deg","informationalModalMessageBody":"Når du er logget på, kan ikke DuckDuckGo hindre Facebook-innhold i å spore deg på dette nettstedet.","informationalModalConfirmButtonText":"Logg inn","informationalModalRejectButtonText":"Gå tilbake","loginButtonText":"Logg på med Facebook","loginBodyText":"Når du logger på med Facebook, sporer de aktiviteten din på nettstedet.","buttonTextUnblockContent":"Opphev blokkering av innhold","buttonTextUnblockComment":"Opphev blokkering av kommentar","buttonTextUnblockComments":"Opphev blokkering av kommentarer","buttonTextUnblockPost":"Opphev blokkering av innlegg","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockContent":"DuckDuckGo blokkerte dette innholdet for å hindre Facebook i å spore deg","infoTitleUnblockComment":"DuckDuckGo blokkerte denne kommentaren for å hindre Facebook i å spore deg","infoTitleUnblockComments":"DuckDuckGo blokkerte disse kommentarene for å hindre Facebook i å spore deg","infoTitleUnblockPost":"DuckDuckGo blokkerte dette innlegget for å hindre Facebook i å spore deg","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne videoen for å hindre Facebook i å spore deg","infoTextUnblockContent":"Vi hindret Facebook i å spore deg da siden ble lastet. Hvis du opphever blokkeringen av dette innholdet, får Facebook vite om aktiviteten din."},"shared.json":{"learnMore":"Finn ut mer","readAbout":"Les om denne personvernfunksjonen"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Forhåndsvisninger gjør det mulig for Google (som eier YouTube) å se enkelte opplysninger om enheten din, men det er likevel mer privat enn å spille av videoen.","informationalModalConfirmButtonText":"Aktiver alle forhåndsvisninger","informationalModalRejectButtonText":"Nei takk","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne YouTube-videoen for å hindre Google i å spore deg","infoTextUnblockVideo":"Vi blokkerte Google (som eier YouTube) mot å spore deg da siden ble lastet. Hvis du opphever blokkeringen av denne videoen, får Google vite om aktiviteten din.","infoPreviewToggleText":"Forhåndsvisninger er deaktivert for å gi deg ekstra personvern","infoPreviewToggleEnabledText":"Forhåndsvisninger er aktivert","infoPreviewInfoText":"Finn ut mer om DuckDuckGos innebygde beskyttelse for sosiale medier"}},"nl":{"facebook.json":{"informationalModalMessageTitle":"Als je inlogt met Facebook, kunnen zij je volgen","informationalModalMessageBody":"Als je eenmaal bent ingelogd, kan DuckDuckGo niet voorkomen dat Facebook je op deze site volgt.","informationalModalConfirmButtonText":"Inloggen","informationalModalRejectButtonText":"Terug","loginButtonText":"Inloggen met Facebook","loginBodyText":"Facebook volgt je activiteit op een site als je Facebook gebruikt om in te loggen.","buttonTextUnblockContent":"Inhoud deblokkeren","buttonTextUnblockComment":"Opmerking deblokkeren","buttonTextUnblockComments":"Opmerkingen deblokkeren","buttonTextUnblockPost":"Bericht deblokkeren","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockContent":"DuckDuckGo heeft deze inhoud geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComment":"DuckDuckGo heeft deze opmerking geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComments":"DuckDuckGo heeft deze opmerkingen geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockPost":"DuckDuckGo heeft dit bericht geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockVideo":"DuckDuckGo heeft deze video geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTextUnblockContent":"We hebben voorkomen dat Facebook je volgde toen de pagina werd geladen. Als je deze inhoud deblokkeert, kan Facebook je activiteit zien."},"shared.json":{"learnMore":"Meer informatie","readAbout":"Lees meer over deze privacybescherming"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-voorbeelden inschakelen?","informationalModalMessageBody":"Bij het tonen van voorbeelden kan Google (eigenaar van YouTube) een deel van de informatie over je apparaat zien, maar blijft je privacy beter beschermd dan als je de video zou afspelen.","informationalModalConfirmButtonText":"Alle voorbeelden inschakelen","informationalModalRejectButtonText":"Nee, bedankt","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockVideo":"DuckDuckGo heeft deze YouTube-video geblokkeerd om te voorkomen dat Google je kan volgen","infoTextUnblockVideo":"We hebben voorkomen dat Google (eigenaar van YouTube) je volgde toen de pagina werd geladen. Als je deze video deblokkeert, kan Google je activiteit zien.","infoPreviewToggleText":"Voorbeelden uitgeschakeld voor extra privacy","infoPreviewToggleEnabledText":"Voorbeelden ingeschakeld","infoPreviewInfoText":"Meer informatie over DuckDuckGo's bescherming tegen ingesloten social media"}},"pl":{"facebook.json":{"informationalModalMessageTitle":"Jeśli zalogujesz się za pośrednictwem Facebooka, będzie on mógł śledzić Twoją aktywność","informationalModalMessageBody":"Po zalogowaniu się DuckDuckGo nie może zablokować możliwości śledzenia Cię przez Facebooka na tej stronie.","informationalModalConfirmButtonText":"Zaloguj się","informationalModalRejectButtonText":"Wróć","loginButtonText":"Zaloguj się za pośrednictwem Facebooka","loginBodyText":"Facebook śledzi Twoją aktywność na stronie, gdy logujesz się za jego pośrednictwem.","buttonTextUnblockContent":"Odblokuj treść","buttonTextUnblockComment":"Odblokuj komentarz","buttonTextUnblockComments":"Odblokuj komentarze","buttonTextUnblockPost":"Odblokuj post","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockContent":"DuckDuckGo zablokował tę treść, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComment":"DuckDuckGo zablokował ten komentarz, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComments":"DuckDuckGo zablokował te komentarze, aby Facebook nie mógł Cię śledzić","infoTitleUnblockPost":"DuckDuckGo zablokował ten post, aby Facebook nie mógł Cię śledzić","infoTitleUnblockVideo":"DuckDuckGo zablokował tę treść wideo, aby Facebook nie mógł Cię śledzić.","infoTextUnblockContent":"Zablokowaliśmy Facebookowi możliwość śledzenia Cię podczas ładowania strony. Jeśli odblokujesz tę treść, Facebook uzyska informacje o Twojej aktywności."},"shared.json":{"learnMore":"Dowiedz się więcej","readAbout":"Dowiedz się więcej o tej ochronie prywatności"},"youtube.json":{"informationalModalMessageTitle":"Włączyć wszystkie podglądy w YouTube?","informationalModalMessageBody":"Wyświetlanie podglądu pozwala Google (który jest właścicielem YouTube) zobaczyć niektóre informacje o Twoim urządzeniu, ale nadal jest to bardziej prywatne niż odtwarzanie filmu.","informationalModalConfirmButtonText":"Włącz wszystkie podglądy","informationalModalRejectButtonText":"Nie, dziękuję","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockVideo":"DuckDuckGo zablokował ten film w YouTube, aby uniemożliwić Google śledzenie Twojej aktywności","infoTextUnblockVideo":"Zablokowaliśmy możliwość śledzenia Cię przez Google (właściciela YouTube) podczas ładowania strony. Jeśli odblokujesz ten film, Google zobaczy Twoją aktywność.","infoPreviewToggleText":"Podglądy zostały wyłączone, aby zapewnić większą ptywatność","infoPreviewToggleEnabledText":"Podglądy włączone","infoPreviewInfoText":"Dowiedz się więcej o zabezpieczeniu osadzonych treści społecznościowych DuckDuckGo"}},"pt":{"facebook.json":{"informationalModalMessageTitle":"Iniciar sessão no Facebook permite que este te rastreie","informationalModalMessageBody":"Depois de iniciares sessão, o DuckDuckGo não poderá bloquear o rastreio por parte do conteúdo do Facebook neste site.","informationalModalConfirmButtonText":"Iniciar sessão","informationalModalRejectButtonText":"Retroceder","loginButtonText":"Iniciar sessão com o Facebook","loginBodyText":"O Facebook rastreia a tua atividade num site quando o usas para iniciares sessão.","buttonTextUnblockContent":"Desbloquear Conteúdo","buttonTextUnblockComment":"Desbloquear Comentário","buttonTextUnblockComments":"Desbloquear Comentários","buttonTextUnblockPost":"Desbloquear Publicação","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockContent":"O DuckDuckGo bloqueou este conteúdo para evitar que o Facebook te rastreie","infoTitleUnblockComment":"O DuckDuckGo bloqueou este comentário para evitar que o Facebook te rastreie","infoTitleUnblockComments":"O DuckDuckGo bloqueou estes comentários para evitar que o Facebook te rastreie","infoTitleUnblockPost":"O DuckDuckGo bloqueou esta publicação para evitar que o Facebook te rastreie","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo para evitar que o Facebook te rastreie","infoTextUnblockContent":"Bloqueámos o rastreio por parte do Facebook quando a página foi carregada. Se desbloqueares este conteúdo, o Facebook fica a saber a tua atividade."},"shared.json":{"learnMore":"Saiba mais","readAbout":"Ler mais sobre esta proteção de privacidade"},"youtube.json":{"informationalModalMessageTitle":"Ativar todas as pré-visualizações do YouTube?","informationalModalMessageBody":"Mostrar visualizações permite à Google (que detém o YouTube) ver algumas das informações do teu dispositivo, mas ainda é mais privado do que reproduzir o vídeo.","informationalModalConfirmButtonText":"Ativar todas as pré-visualizações","informationalModalRejectButtonText":"Não, obrigado","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo do YouTube para impedir que a Google te rastreie","infoTextUnblockVideo":"Bloqueámos o rastreio por parte da Google (que detém o YouTube) quando a página foi carregada. Se desbloqueares este vídeo, a Google fica a saber a tua atividade.","infoPreviewToggleText":"Pré-visualizações desativadas para privacidade adicional","infoPreviewToggleEnabledText":"Pré-visualizações ativadas","infoPreviewInfoText":"Saiba mais sobre a Proteção contra conteúdos de redes sociais incorporados do DuckDuckGo"}},"ro":{"facebook.json":{"informationalModalMessageTitle":"Conectarea cu Facebook îi permite să te urmărească","informationalModalMessageBody":"Odată ce te-ai conectat, DuckDuckGo nu poate împiedica conținutul Facebook să te urmărească pe acest site.","informationalModalConfirmButtonText":"Autentificare","informationalModalRejectButtonText":"Înapoi","loginButtonText":"Conectează-te cu Facebook","loginBodyText":"Facebook urmărește activitatea ta pe un site atunci când îl utilizezi pentru a te conecta.","buttonTextUnblockContent":"Deblochează conținutul","buttonTextUnblockComment":"Deblochează comentariul","buttonTextUnblockComments":"Deblochează comentariile","buttonTextUnblockPost":"Deblochează postarea","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockContent":"DuckDuckGo a blocat acest conținut pentru a împiedica Facebook să te urmărească","infoTitleUnblockComment":"DuckDuckGo a blocat acest comentariu pentru a împiedica Facebook să te urmărească","infoTitleUnblockComments":"DuckDuckGo a blocat aceste comentarii pentru a împiedica Facebook să te urmărească","infoTitleUnblockPost":"DuckDuckGo a blocat această postare pentru a împiedica Facebook să te urmărească","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip pentru a împiedica Facebook să te urmărească","infoTextUnblockContent":"Am împiedicat Facebook să te urmărească atunci când pagina a fost încărcată. Dacă deblochezi acest conținut, Facebook îți va cunoaște activitatea."},"shared.json":{"learnMore":"Află mai multe","readAbout":"Citește despre această protecție a confidențialității"},"youtube.json":{"informationalModalMessageTitle":"Activezi toate previzualizările YouTube?","informationalModalMessageBody":"Afișarea previzualizărilor va permite ca Google (care deține YouTube) să vadă unele dintre informațiile despre dispozitivul tău, dar este totuși mai privată decât redarea videoclipului.","informationalModalConfirmButtonText":"Activează toate previzualizările","informationalModalRejectButtonText":"Nu, mulțumesc","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip de pe YouTube pentru a împiedica Google să te urmărească","infoTextUnblockVideo":"Am împiedicat Google (care deține YouTube) să te urmărească atunci când s-a încărcat pagina. Dacă deblochezi acest videoclip, Google va cunoaște activitatea ta.","infoPreviewToggleText":"Previzualizările au fost dezactivate pentru o confidențialitate suplimentară","infoPreviewToggleEnabledText":"Previzualizări activate","infoPreviewInfoText":"Află mai multe despre Protecția integrată DuckDuckGo pentru rețelele sociale"}},"ru":{"facebook.json":{"informationalModalMessageTitle":"Вход через Facebook позволяет этой социальной сети отслеживать вас","informationalModalMessageBody":"После входа DuckDuckGo не сможет блокировать отслеживание ваших действий с контентом на Facebook.","informationalModalConfirmButtonText":"Войти","informationalModalRejectButtonText":"Вернуться","loginButtonText":"Войти через Facebook","loginBodyText":"При использовании учетной записи Facebook для входа на сайты эта социальная сеть сможет отслеживать на них ваши действия.","buttonTextUnblockContent":"Разблокировать","buttonTextUnblockComment":"Разблокировать","buttonTextUnblockComments":"Разблокировать","buttonTextUnblockPost":"Разблокировать","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockContent":"DuckDuckGo заблокировал этот контент, чтобы вас не отслеживал Facebook","infoTitleUnblockComment":"DuckDuckGo заблокировал этот комментарий, чтобы вас не отслеживал Facebook","infoTitleUnblockComments":"DuckDuckGo заблокировал эти комментарии, чтобы вас не отслеживал Facebook","infoTitleUnblockPost":"DuckDuckGo заблокировал эту публикацию, чтобы вас не отслеживал Facebook","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео, чтобы вас не отслеживал Facebook","infoTextUnblockContent":"Во время загрузки страницы мы помешали Facebook отследить ваши действия. Если разблокировать этот контент, Facebook сможет фиксировать вашу активность."},"shared.json":{"learnMore":"Узнать больше","readAbout":"Подробнее об этом виде защиты конфиденциальности"},"youtube.json":{"informationalModalMessageTitle":"Включить предпросмотр видео из YouTube?","informationalModalMessageBody":"Активация предварительного просмотра позволит Google (владельцу YouTube) получить некоторые сведения о вашем устройстве, однако это более безопасный вариант, чем воспроизведение видео целиком.","informationalModalConfirmButtonText":"Включить предпросмотр","informationalModalRejectButtonText":"Нет, спасибо","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео из YouTube, чтобы вас не отслеживал Google","infoTextUnblockVideo":"Во время загрузки страницы мы помешали Google (владельцу YouTube) отследить ваши действия. Если разблокировать видео, Google сможет фиксировать вашу активность.","infoPreviewToggleText":"Предварительный просмотр отключен для дополнительной защиты конфиденциальности","infoPreviewToggleEnabledText":"Предварительный просмотр включен","infoPreviewInfoText":"Подробнее о защите DuckDuckGo от внедренного контента соцсетей"}},"sk":{"facebook.json":{"informationalModalMessageTitle":"Prihlásenie cez Facebook mu umožní sledovať vás","informationalModalMessageBody":"DuckDuckGo po prihlásení nemôže na tejto lokalite zablokovať sledovanie vašej osoby obsahom Facebooku.","informationalModalConfirmButtonText":"Prihlásiť sa","informationalModalRejectButtonText":"Prejsť späť","loginButtonText":"Prihláste sa pomocou služby Facebook","loginBodyText":"Keď použijete prihlasovanie cez Facebook, Facebook bude na lokalite sledovať vašu aktivitu.","buttonTextUnblockContent":"Odblokovať obsah","buttonTextUnblockComment":"Odblokovať komentár","buttonTextUnblockComments":"Odblokovať komentáre","buttonTextUnblockPost":"Odblokovať príspevok","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockContent":"DuckDuckGo zablokoval tento obsah, aby vás Facebook nesledoval","infoTitleUnblockComment":"DuckDuckGo zablokoval tento komentár, aby zabránil sledovaniu zo strany Facebooku","infoTitleUnblockComments":"DuckDuckGo zablokoval tieto komentáre, aby vás Facebook nesledoval","infoTitleUnblockPost":"DuckDuckGo zablokoval tento príspevok, aby vás Facebook nesledoval","infoTitleUnblockVideo":"DuckDuckGo zablokoval toto video, aby vás Facebook nesledoval","infoTextUnblockContent":"Pri načítaní stránky sme zablokovali Facebook, aby vás nesledoval. Ak tento obsah odblokujete, Facebook bude vedieť o vašej aktivite."},"shared.json":{"learnMore":"Zistite viac","readAbout":"Prečítajte si o tejto ochrane súkromia"},"youtube.json":{"informationalModalMessageTitle":"Chcete povoliť všetky ukážky zo služby YouTube?","informationalModalMessageBody":"Zobrazenie ukážok umožní spoločnosti Google (ktorá vlastní YouTube) vidieť niektoré informácie o vašom zariadení, ale stále je to súkromnejšie ako prehrávanie videa.","informationalModalConfirmButtonText":"Povoliť všetky ukážky","informationalModalRejectButtonText":"Nie, ďakujem","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockVideo":"DuckDuckGo toto video v službe YouTube zablokoval s cieľom predísť tomu, aby vás spoločnosť Google mohla sledovať","infoTextUnblockVideo":"Zablokovali sme pre spoločnosť Google (ktorá vlastní YouTube), aby vás nemohla sledovať, keď sa stránka načíta. Ak toto video odblokujete, Google bude poznať vašu aktivitu.","infoPreviewToggleText":"Ukážky sú zakázané s cieľom zvýšiť ochranu súkromia","infoPreviewToggleEnabledText":"Ukážky sú povolené","infoPreviewInfoText":"Získajte viac informácií o DuckDuckGo, vloženej ochrane sociálnych médií"}},"sl":{"facebook.json":{"informationalModalMessageTitle":"Če se prijavite s Facebookom, vam Facebook lahko sledi","informationalModalMessageBody":"Ko ste enkrat prijavljeni, DuckDuckGo ne more blokirati Facebookove vsebine, da bi vam sledila na tem spletnem mestu.","informationalModalConfirmButtonText":"Prijava","informationalModalRejectButtonText":"Pojdi nazaj","loginButtonText":"Prijavite se s Facebookom","loginBodyText":"Če se prijavite s Facebookom, bo nato spremljal vaša dejanja na spletnem mestu.","buttonTextUnblockContent":"Odblokiraj vsebino","buttonTextUnblockComment":"Odblokiraj komentar","buttonTextUnblockComments":"Odblokiraj komentarje","buttonTextUnblockPost":"Odblokiraj objavo","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockContent":"DuckDuckGo je blokiral to vsebino, da bi Facebooku preprečil sledenje","infoTitleUnblockComment":"DuckDuckGo je blokiral ta komentar, da bi Facebooku preprečil sledenje","infoTitleUnblockComments":"DuckDuckGo je blokiral te komentarje, da bi Facebooku preprečil sledenje","infoTitleUnblockPost":"DuckDuckGo je blokiral to objavo, da bi Facebooku preprečil sledenje","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek, da bi Facebooku preprečil sledenje","infoTextUnblockContent":"Ko se je stran naložila, smo Facebooku preprečili, da bi vam sledil. Če to vsebino odblokirate, bo Facebook izvedel za vaša dejanja."},"shared.json":{"learnMore":"Več","readAbout":"Preberite več o tej zaščiti zasebnosti"},"youtube.json":{"informationalModalMessageTitle":"Želite omogočiti vse YouTubove predoglede?","informationalModalMessageBody":"Prikaz predogledov omogoča Googlu (ki je lastnik YouTuba) vpogled v nekatere podatke o napravi, vendar je še vedno bolj zasebno kot predvajanje videoposnetka.","informationalModalConfirmButtonText":"Omogoči vse predoglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek v YouTubu, da bi Googlu preprečil sledenje","infoTextUnblockVideo":"Googlu (ki je lastnik YouTuba) smo preprečili, da bi vam sledil, ko se je stran naložila. Če odblokirate ta videoposnetek, bo Google izvedel za vašo dejavnost.","infoPreviewToggleText":"Predogledi so zaradi dodatne zasebnosti onemogočeni","infoPreviewToggleEnabledText":"Predogledi so omogočeni","infoPreviewInfoText":"Več o vgrajeni zaščiti družbenih medijev DuckDuckGo"}},"sv":{"facebook.json":{"informationalModalMessageTitle":"Om du loggar in med Facebook kan de spåra dig","informationalModalMessageBody":"När du väl är inloggad kan DuckDuckGo inte hindra Facebooks innehåll från att spåra dig på den här webbplatsen.","informationalModalConfirmButtonText":"Logga in","informationalModalRejectButtonText":"Gå tillbaka","loginButtonText":"Logga in med Facebook","loginBodyText":"Facebook spårar din aktivitet på en webbplats om du använder det för att logga in.","buttonTextUnblockContent":"Avblockera innehåll","buttonTextUnblockComment":"Avblockera kommentar","buttonTextUnblockComments":"Avblockera kommentarer","buttonTextUnblockPost":"Avblockera inlägg","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockContent":"DuckDuckGo blockerade det här innehållet för att förhindra att Facebook spårar dig","infoTitleUnblockComment":"DuckDuckGo blockerade den här kommentaren för att förhindra att Facebook spårar dig","infoTitleUnblockComments":"DuckDuckGo blockerade de här kommentarerna för att förhindra att Facebook spårar dig","infoTitleUnblockPost":"DuckDuckGo blockerade det här inlägget för att förhindra att Facebook spårar dig","infoTitleUnblockVideo":"DuckDuckGo blockerade den här videon för att förhindra att Facebook spårar dig","infoTextUnblockContent":"Vi hindrade Facebook från att spåra dig när sidan lästes in. Om du avblockerar det här innehållet kommer Facebook att känna till din aktivitet."},"shared.json":{"learnMore":"Läs mer","readAbout":"Läs mer om detta integritetsskydd"},"youtube.json":{"informationalModalMessageTitle":"Aktivera alla förhandsvisningar för YouTube?","informationalModalMessageBody":"Genom att visa förhandsvisningar kan Google (som äger YouTube) se en del av enhetens information, men det är ändå mer privat än att spela upp videon.","informationalModalConfirmButtonText":"Aktivera alla förhandsvisningar","informationalModalRejectButtonText":"Nej tack","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockVideo":"DuckDuckGo blockerade den här YouTube-videon för att förhindra att Google spårar dig","infoTextUnblockVideo":"Vi hindrade Google (som äger YouTube) från att spåra dig när sidan laddades. Om du tar bort blockeringen av videon kommer Google att känna till din aktivitet.","infoPreviewToggleText":"Förhandsvisningar har inaktiverats för ytterligare integritet","infoPreviewToggleEnabledText":"Förhandsvisningar aktiverade","infoPreviewInfoText":"Läs mer om DuckDuckGos skydd mot inbäddade sociala medier"}},"tr":{"facebook.json":{"informationalModalMessageTitle":"Facebook ile giriş yapmak, sizi takip etmelerini sağlar","informationalModalMessageBody":"Giriş yaptıktan sonra, DuckDuckGo Facebook içeriğinin sizi bu sitede izlemesini engelleyemez.","informationalModalConfirmButtonText":"Oturum Aç","informationalModalRejectButtonText":"Geri dön","loginButtonText":"Facebook ile giriş yapın","loginBodyText":"Facebook, giriş yapmak için kullandığınızda bir sitedeki etkinliğinizi izler.","buttonTextUnblockContent":"İçeriğin Engelini Kaldır","buttonTextUnblockComment":"Yorumun Engelini Kaldır","buttonTextUnblockComments":"Yorumların Engelini Kaldır","buttonTextUnblockPost":"Gönderinin Engelini Kaldır","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockContent":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu içeriği engelledi","infoTitleUnblockComment":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumu engelledi","infoTitleUnblockComments":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumları engelledi","infoTitleUnblockPost":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu gönderiyi engelledi","infoTitleUnblockVideo":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu videoyu engelledi","infoTextUnblockContent":"Sayfa yüklendiğinde Facebook'un sizi izlemesini engelledik. Bu içeriğin engelini kaldırırsanız Facebook etkinliğinizi öğrenecektir."},"shared.json":{"learnMore":"Daha Fazla Bilgi","readAbout":"Bu gizlilik koruması hakkında bilgi edinin"},"youtube.json":{"informationalModalMessageTitle":"Tüm YouTube önizlemeleri etkinleştirilsin mi?","informationalModalMessageBody":"Önizlemelerin gösterilmesi Google'ın (YouTube'un sahibi) cihazınızın bazı bilgilerini görmesine izin verir, ancak yine de videoyu oynatmaktan daha özeldir.","informationalModalConfirmButtonText":"Tüm Önizlemeleri Etkinleştir","informationalModalRejectButtonText":"Hayır Teşekkürler","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockVideo":"DuckDuckGo, Google'ın sizi izlemesini önlemek için bu YouTube videosunu engelledi","infoTextUnblockVideo":"Sayfa yüklendiğinde Google'ın (YouTube'un sahibi) sizi izlemesini engelledik. Bu videonun engelini kaldırırsanız, Google etkinliğinizi öğrenecektir.","infoPreviewToggleText":"Ek gizlilik için önizlemeler devre dışı bırakıldı","infoPreviewToggleEnabledText":"Önizlemeler etkinleştirildi","infoPreviewInfoText":"DuckDuckGo Yerleşik Sosyal Medya Koruması hakkında daha fazla bilgi edinin"}}}`; /********************************************************* * Style Definitions *********************************************************/ - const styles = { - fontStyle: ` + /** + * Get CSS style defintions for CTL, using the provided AssetConfig for any non-embedded assets + * (e.g. fonts.) + * @param {import('../../content-feature.js').AssetConfig} [assets] + */ + function getStyles (assets) { + let fontStyle = ''; + let regularFontFamily = "system, -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'"; + let boldFontFamily = regularFontFamily; + if (assets?.regularFontUrl && assets?.boldFontUrl) { + fontStyle = ` @font-face{ font-family: DuckDuckGoPrivacyEssentials; - src: url(${ddgFont}); + src: url(${assets.regularFontUrl}); } @font-face{ font-family: DuckDuckGoPrivacyEssentialsBold; font-weight: bold; - src: url(${ddgFontBold}); + src: url(${assets.boldFontUrl}); } - `, - darkMode: { - background: ` + `; + regularFontFamily = 'DuckDuckGoPrivacyEssentials'; + boldFontFamily = 'DuckDuckGoPrivacyEssentialsBold'; + } + return { + fontStyle, + darkMode: { + background: ` background: #111111; `, - textFont: ` + textFont: ` color: rgba(255, 255, 255, 0.9); `, - buttonFont: ` + buttonFont: ` color: #111111; `, - linkFont: ` + linkFont: ` color: #7295F6; `, - buttonBackground: ` + buttonBackground: ` background: #5784FF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #557FF3; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #3969EF; `, - toggleButtonText: ` + toggleButtonText: ` color: #EEEEEE; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #5784FF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - lightMode: { - background: ` + } + }, + lightMode: { + background: ` background: #FFFFFF; `, - textFont: ` + textFont: ` color: #222222; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; `, - linkFont: ` + linkFont: ` color: #3969EF; `, - buttonBackground: ` + buttonBackground: ` background: #3969EF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #2B55CA; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #1E42A4; `, - toggleButtonText: ` + toggleButtonText: ` color: #666666; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #3969EF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - loginMode: { - buttonBackground: ` + } + }, + loginMode: { + buttonBackground: ` background: #666666; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; ` - }, - cancelMode: { - buttonBackground: ` + }, + cancelMode: { + buttonBackground: ` background: rgba(34, 34, 34, 0.1); `, - buttonFont: ` + buttonFont: ` color: #222222; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: rgba(0, 0, 0, 0.12); `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: rgba(0, 0, 0, 0.18); ` - }, - button: ` + }, + button: ` border-radius: 8px; padding: 11px 22px; @@ -4981,7 +5285,7 @@ border-color: #3969EF; border: none; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; font-size: 14px; position: relative; @@ -4989,7 +5293,7 @@ box-shadow: none; z-index: 2147483646; `, - circle: ` + circle: ` border-radius: 50%; width: 18px; height: 18px; @@ -4999,14 +5303,14 @@ top: -8px; right: -8px; `, - loginIcon: ` + loginIcon: ` position: absolute; top: -13px; right: -10px; height: 28px; width: 28px; `, - rectangle: ` + rectangle: ` width: 12px; height: 3px; background: #666666; @@ -5014,7 +5318,7 @@ top: 42.5%; margin: auto; `, - textBubble: ` + textBubble: ` background: #FFFFFF; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 16px; @@ -5025,9 +5329,9 @@ position: absolute; line-height: normal; `, - textBubbleWidth: 360, // Should match the width rule in textBubble - textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble - textArrow: ` + textBubbleWidth: 360, // Should match the width rule in textBubble + textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble + textArrow: ` display: inline-block; background: #FFFFFF; border: solid rgba(0, 0, 0, 0.1); @@ -5038,23 +5342,23 @@ position: relative; top: -9px; `, - arrowDefaultLocationPercent: 50, - hoverTextTitle: ` + arrowDefaultLocationPercent: 50, + hoverTextTitle: ` padding: 0px 12px 12px; margin-top: -5px; `, - hoverTextBody: ` - font-family: DuckDuckGoPrivacyEssentials; + hoverTextBody: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: auto; padding: 17px; text-align: left; `, - hoverContainer: ` + hoverContainer: ` padding-bottom: 10px; `, - buttonTextContainer: ` + buttonTextContainer: ` display: flex; flex-direction: row; align-items: center; @@ -5062,10 +5366,10 @@ padding: 0; margin: 0; `, - headerRow: ` + headerRow: ` `, - block: ` + block: ` box-sizing: border-box; border: 1px solid rgba(0,0,0,0.1); border-radius: 12px; @@ -5075,27 +5379,27 @@ display: flex; flex-direction: column; - font-family: DuckDuckGoPrivacyEssentials; + font-family: ${regularFontFamily}; line-height: 1; `, - youTubeDialogBlock: ` + youTubeDialogBlock: ` height: calc(100% - 30px); max-width: initial; min-height: initial; `, - imgRow: ` + imgRow: ` display: flex; flex-direction: column; margin: 20px 0px; `, - content: ` + content: ` display: flex; flex-direction: column; padding: 16px 0; flex: 1 1 1px; `, - feedbackLink: ` - font-family: DuckDuckGoPrivacyEssentials; + feedbackLink: ` + font-family: ${regularFontFamily}; font-style: normal; font-weight: 400; font-size: 12px; @@ -5103,13 +5407,13 @@ color: #ABABAB; text-decoration: none; `, - feedbackRow: ` + feedbackRow: ` height: 30px; display: flex; justify-content: flex-end; align-items: center; `, - titleBox: ` + titleBox: ` display: flex; padding: 12px; max-height: 44px; @@ -5118,8 +5422,8 @@ margin: 0; margin-bottom: 4px; `, - title: ` - font-family: DuckDuckGoPrivacyEssentials; + title: ` + font-family: ${regularFontFamily}; line-height: 1.4; font-size: 14px; margin: auto 10px; @@ -5131,7 +5435,7 @@ border: none; padding: 0; `, - buttonRow: ` + buttonRow: ` display: flex; height: 100% flex-direction: row; @@ -5139,8 +5443,8 @@ height: 100%; align-items: flex-start; `, - modalContentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + modalContentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; line-height: 21px; @@ -5149,8 +5453,8 @@ border: none; padding: 0px 32px; `, - modalContentText: ` - font-family: DuckDuckGoPrivacyEssentials; + modalContentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: 0px auto 14px; @@ -5158,7 +5462,7 @@ border: none; padding: 0; `, - modalButtonRow: ` + modalButtonRow: ` border: none; padding: 0; margin: auto; @@ -5167,17 +5471,17 @@ flex-direction: column; align-items: center; `, - modalButton: ` + modalButton: ` width: 100%; display: flex; justify-content: center; align-items: center; `, - modalIcon: ` + modalIcon: ` display: block; `, - contentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + contentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; margin: 20px auto 10px; @@ -5185,25 +5489,25 @@ text-align: center; margin-top: auto; `, - contentText: ` - font-family: DuckDuckGoPrivacyEssentials; + contentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; padding: 0px 40px; text-align: center; margin: 0 auto auto; `, - icon: ` + icon: ` height: 80px; width: 80px; margin: auto; `, - closeIcon: ` + closeIcon: ` height: 12px; width: 12px; margin: auto; `, - closeButton: ` + closeButton: ` display: flex; justify-content: center; align-items: center; @@ -5213,7 +5517,7 @@ background: transparent; cursor: pointer; `, - logo: ` + logo: ` flex-basis: 0%; min-width: 20px; height: 21px; @@ -5221,17 +5525,17 @@ padding: 0; margin: 0; `, - logoImg: ` + logoImg: ` height: 21px; width: 21px; `, - loadingImg: ` + loadingImg: ` display: block; margin: 0px 8px 0px 0px; height: 14px; width: 14px; `, - modal: ` + modal: ` width: 340px; padding: 0; margin: auto; @@ -5245,14 +5549,14 @@ border-radius: 12px; border: none; `, - modalContent: ` + modalContent: ` padding: 24px; display: flex; flex-direction: column; border: none; margin: 0; `, - overlay: ` + overlay: ` height: 100%; width: 100%; background-color: #666666; @@ -5265,7 +5569,7 @@ padding: 0; margin: 0; `, - modalContainer: ` + modalContainer: ` height: 100vh; width: 100vw; box-sizing: border-box; @@ -5276,16 +5580,16 @@ margin: 0; padding: 0; `, - headerLinkContainer: ` + headerLinkContainer: ` flex-basis: 100%; display: grid; justify-content: flex-end; `, - headerLink: ` + headerLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; text-decoration: none; cursor: pointer; min-width: 100px; @@ -5293,15 +5597,15 @@ float: right; display: none; `, - generalLink: ` + generalLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; cursor: pointer; text-decoration: none; `, - wrapperDiv: ` + wrapperDiv: ` display: inline-block; border: 0; padding: 0; @@ -5309,12 +5613,12 @@ max-width: 600px; min-height: 300px; `, - toggleButtonWrapper: ` + toggleButtonWrapper: ` display: flex; align-items: center; cursor: pointer; `, - toggleButton: ` + toggleButton: ` cursor: pointer; position: relative; width: 30px; @@ -5326,19 +5630,19 @@ background-color: transparent; text-align: left; `, - toggleButtonBg: ` + toggleButtonBg: ` right: 0; width: 30px; height: 16px; overflow: visible; border-radius: 10px; `, - toggleButtonText: ` + toggleButtonText: ` display: inline-block; margin: 0 0 0 7px; padding: 0; `, - toggleButtonKnob: ` + toggleButtonKnob: ` position: absolute; display: inline-block; width: 14px; @@ -5349,15 +5653,15 @@ top: calc(50% - 14px/2 - 1px); box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.05), 0px 1px 1px rgba(0, 0, 0, 0.1); `, - toggleButtonKnobState: { - active: ` + toggleButtonKnobState: { + active: ` right: 1px; `, - inactive: ` + inactive: ` left: 1px; ` - }, - placeholderWrapperDiv: ` + }, + placeholderWrapperDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5367,7 +5671,7 @@ min-height: 300px; margin: auto; `, - youTubeWrapperDiv: ` + youTubeWrapperDiv: ` position: relative; overflow: hidden; max-width: initial; @@ -5375,7 +5679,7 @@ min-height: 300px; height: 100%; `, - youTubeDialogDiv: ` + youTubeDialogDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5383,14 +5687,14 @@ min-height: initial; height: calc(100% - 30px); `, - youTubeDialogBottomRow: ` + youTubeDialogBottomRow: ` display: flex; flex-direction: column; align-items: center; justify-content: flex-end; margin-top: auto; `, - youTubePlaceholder: ` + youTubePlaceholder: ` display: flex; flex-direction: column; justify-content: flex-start; @@ -5399,7 +5703,7 @@ height: 100%; background: rgba(45, 45, 45, 0.8); `, - youTubePreviewWrapperImg: ` + youTubePreviewWrapperImg: ` position: absolute; display: flex; justify-content: center; @@ -5407,20 +5711,20 @@ width: 100%; height: 100%; `, - youTubePreviewImg: ` + youTubePreviewImg: ` min-width: 100%; min-height: 100%; height: auto; `, - youTubeTopSection: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + youTubeTopSection: ` + font-family: ${boldFontFamily}; flex: 1; display: flex; justify-content: space-between; position: relative; padding: 18px 12px 0; `, - youTubeTitle: ` + youTubeTitle: ` font-size: 14px; font-weight: bold; line-height: 14px; @@ -5432,13 +5736,13 @@ text-overflow: ellipsis; box-sizing: border-box; `, - youTubePlayButtonRow: ` + youTubePlayButtonRow: ` flex: 2; display: flex; align-items: center; justify-content: center; `, - youTubePlayButton: ` + youTubePlayButton: ` display: flex; justify-content: center; align-items: center; @@ -5447,7 +5751,7 @@ padding: 0px 24px; border-radius: 8px; `, - youTubePreviewToggleRow: ` + youTubePreviewToggleRow: ` flex: 1; display: flex; flex-direction: column; @@ -5455,15 +5759,19 @@ align-items: center; padding: 0 12px 18px; `, - youTubePreviewToggleText: ` + youTubePreviewToggleText: ` color: #EEEEEE; font-weight: 400; `, - youTubePreviewInfoText: ` + youTubePreviewInfoText: ` color: #ABABAB; ` - }; + } + } + /** + * @param {string} locale UI locale + */ function getConfig (locale) { const locales = JSON.parse(localesJSON); const fbStrings = locales[locale]['facebook.json']; @@ -5900,6 +6208,7 @@ // @see {getConfig} let config = null; let sharedStrings = null; + let styles = null; // TODO: Remove these redundant data structures and refactor the related code. // There should be no need to have the entity configuration stored in two @@ -6362,6 +6671,16 @@ ]; elementToReplace.style.setProperty('display', 'none', 'important'); + // When iframes are blocked by the declarativeNetRequest API, they are + // collapsed (hidden) automatically. Unfortunately however, there's a bug + // that stops them from being uncollapsed (shown again) if they are removed + // from the DOM after they are collapsed. As a workaround, have the iframe + // load a benign data URI, so that it's uncollapsed, before removing it from + // the DOM. See https://crbug.com/1428971 + const originalSrc = elementToReplace.src; + elementToReplace.src = + 'data:text/plain;charset=utf-8;base64,' + btoa('https://crbug.com/1428971'); + // Add the placeholder element to the page. elementToReplace.parentElement.insertBefore( placeholderElement, elementToReplace @@ -6381,6 +6700,7 @@ // placeholder) can finally be removed from the DOM. elementToReplace.remove(); elementToReplace.style.setProperty('display', ...originalDisplay); + elementToReplace.src = originalSrc; }); } @@ -6771,10 +7091,10 @@ * Creates an anchor element with no destination. It is expected that a click * handler is added to the element later. * @param {string} linkText - * @param {displayMode} [mode='lightMode'] + * @param {displayMode} mode * @returns {HTMLAnchorElement} */ - function makeTextButton (linkText, mode) { + function makeTextButton (linkText, mode = 'lightMode') { const linkElement = document.createElement('a'); linkElement.style.cssText = styles.headerLink + styles[mode].linkFont; linkElement.textContent = linkText; @@ -7498,6 +7818,8 @@ const localizedConfig = getConfig(locale); config = localizedConfig.config; sharedStrings = localizedConfig.sharedStrings; + // update styles if asset config was sent + styles = getStyles(this.assetConfig); for (const entity of Object.keys(config)) { // Strip config entities that are first-party, or aren't enabled in the @@ -7566,6 +7888,16 @@ } await afterPageLoad; + // On some websites, the "ddg-ctp-ready" event is occasionally + // dispatched too early, before the listener is ready to receive it. + // To counter that, catch "ddg-ctp-surrogate-load" events dispatched + // _after_ page, so the "ddg-ctp-ready" event can be dispatched again. + window.addEventListener( + 'ddg-ctp-surrogate-load', () => { + originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready')); + } + ); + // Then wait for any in-progress element replacements, before letting // the surrogate scripts know to start. window.setTimeout(() => { @@ -7639,12 +7971,14 @@ /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** @@ -7766,27 +8100,6 @@ }); } - /** - * Check if the current document origin is on the tracker list, using the provided lookup trie. - * @param {object} trackerLookup Trie lookup of tracker domains - * @returns {boolean} True iff the origin is a tracker. - */ - function isTrackerOrigin (trackerLookup) { - const originHostname = document.location.hostname; - const parts = originHostname.split('.').reverse(); - let node = trackerLookup; - for (const sub of parts) { - if (node[sub] === 1) { - return true - } else if (node[sub]) { - node = node[sub]; - } else { - return false - } - } - return false - } - /** * @module Mozilla integration * @category Content Scope Scripts Integrations @@ -7808,12 +8121,14 @@ } function initCode () { + const trackerLookup = $TRACKER_LOOKUP$; load({ platform: { name: 'extension' }, - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - documentOriginIsTracker: isTrackerOrigin($TRACKER_LOOKUP$), + trackerLookup, + documentOriginIsTracker: isTrackerOrigin(trackerLookup), + site: computeLimitedSiteObject(), // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f bundledConfig: $BUNDLED_CONFIG$ }); diff --git a/build/integration/contentScope.js b/build/integration/contentScope.js index d392bdfad..550c68567 100644 --- a/build/integration/contentScope.js +++ b/build/integration/contentScope.js @@ -91,7 +91,7 @@ * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ - function isThirdParty () { + function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -293,7 +293,7 @@ /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ function processAttr (configSetting, defaultValue) { @@ -422,6 +422,107 @@ DDGReflect = globalObj.Reflect; } + function isUnprotectedDomain (topLevelHostname, featureList) { + let unprotectedDomain = false; + const domainParts = topLevelHostname.split('.'); + + // walk up the domain to see if it's unprotected + while (domainParts.length > 1 && !unprotectedDomain) { + const partialDomain = domainParts.join('.'); + + unprotectedDomain = featureList.filter(domain => domain.domain === partialDomain).length > 0; + + domainParts.shift(); + } + + return unprotectedDomain + } + + function parseVersionString (versionString) { + const [major = 0, minor = 0, patch = 0] = versionString.split('.').map(Number); + return { + major, + minor, + patch + } + } + + /** + * @param {string} minVersionString + * @param {string} applicationVersionString + * @returns {boolean} + */ + function satisfiesMinVersion (minVersionString, applicationVersionString) { + const { major: minMajor, minor: minMinor, patch: minPatch } = parseVersionString(minVersionString); + const { major, minor, patch } = parseVersionString(applicationVersionString); + + return (major > minMajor || + (major >= minMajor && minor > minMinor) || + (major >= minMajor && minor >= minMinor && patch >= minPatch)) + } + + /** + * @param {string | number | undefined} minSupportedVersion + * @param {string | number | undefined} currentVersion + * @returns {boolean} + */ + function isSupportedVersion (minSupportedVersion, currentVersion) { + if (typeof currentVersion === 'string' && typeof minSupportedVersion === 'string') { + if (satisfiesMinVersion(minSupportedVersion, currentVersion)) { + return true + } + } else if (typeof currentVersion === 'number' && typeof minSupportedVersion === 'number') { + if (minSupportedVersion <= currentVersion) { + return true + } + } + return false + } + + /** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ + function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features); + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); + const enabledFeatures = remoteFeatureNames.filter((featureName) => { + const feature = data.features[featureName]; + // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { + return false + } + } + return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) + }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config + return enabledFeatures + } + + /** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ + function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {}; + const remoteFeatureNames = Object.keys(data.features); + remoteFeatureNames.forEach((featureName) => { + if (!enabledFeatures.includes(featureName)) { + return + } + + featureSettings[featureName] = data.features[featureName].settings; + }); + return featureSettings + } + const windowsSpecificFeatures = ['windowsPermissionUsage']; function isWindowsSpecificFeature (featureName) { @@ -1009,13 +1110,43 @@ return parseJSONPointer(fromPointer); } + /** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + + /** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName; - this._args = null; + this.#args = null; this.monitor = new PerformanceMonitor(); } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -1028,6 +1159,34 @@ return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -1044,10 +1203,11 @@ /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting(); + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName); if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -1067,17 +1227,22 @@ return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name); - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name); + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName); + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName); return result === 'enabled' } @@ -1086,9 +1251,11 @@ * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain; + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || []; return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -1098,7 +1265,7 @@ callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit'); - this._args = args; + this.#args = args; this.platform = args.platform; this.init(args); mark.end(); @@ -1111,14 +1278,23 @@ callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad'); - this._args = args; + this.#args = args; this.platform = args.platform; + this.#bundledConfig = args.bundledConfig; + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version); + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures); + } + this.#trackerLookup = args.trackerLookup; + this.#documentOriginIsTracker = args.documentOriginIsTracker; this.load(args); mark.end(); } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll(); } } @@ -1190,15 +1366,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property]; + let targetOut = target; + if (typeof property === 'string' && property in outputs) { + targetOut = outputs; + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -1255,7 +1433,6 @@ function wrapScriptCodeOverload (code, config) { const processedConfig = {}; for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value); } // Don't do anything if the config is empty @@ -1337,7 +1514,9 @@ // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -1561,6 +1740,13 @@ return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -1570,6 +1756,13 @@ return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -3977,6 +4170,34 @@ } } + /** + * Check if the current document origin is on the tracker list, using the provided lookup trie. + * @param {object} trackerLookup Trie lookup of tracker domains + * @returns {boolean} True iff the origin is a tracker. + */ + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { + const parts = originHostname.split('.').reverse(); + let node = trackerLookup; + for (const sub of parts) { + if (node[sub] === 1) { + return true + } else if (node[sub]) { + node = node[sub]; + } else { + return false + } + } + return false + } + + /** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ + // Initial cookie policy pre init let cookiePolicy = { debug: false, @@ -3985,12 +4206,18 @@ shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) }; + let trackerLookup = {}; let loadedPolicyResolve; @@ -4010,6 +4237,9 @@ }); } + /** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -4018,26 +4248,45 @@ return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } + /** + * @param {Set} scriptOrigins + * @returns {boolean} + */ + function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false; + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup, scriptOrigin)) { + matched = true; + } + } + return matched + } + + /** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true; } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup = this.trackerLookup; + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie; + const { exceptions, settings } = this.bundledConfig.features.cookie; const tabHostname = getTabHostname(); let tabExempted = true; @@ -4051,6 +4300,10 @@ }); cookiePolicy.shouldBlock = !frameExempted && !tabExempted; cookiePolicy.policy = settings.firstPartyCookiePolicy; + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy; + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || []; } // The cookie policy is injected into every frame immediately so that no cookie will @@ -4111,20 +4364,20 @@ try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy; + const { shouldBlock, policy, trackerPolicy } = cookiePolicy; + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy; if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext); return } - // extract cookie expiry from cookie string const cookie = new Cookie(value); // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge; + cookie.maxAge = chosenPolicy.maxAge; debugHelper('restrict', 'expiry', setCookieContext); @@ -4152,19 +4405,23 @@ } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + }; + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie; - args.cookie.debug = args.debug; - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie'); - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie'); - const policy = this.getFeatureSetting('firstPartyCookiePolicy'); - if (policy) { - cookiePolicy.policy = policy; - } + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie); + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy + }; } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false; + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy); } loadedPolicyResolve(); @@ -4446,31 +4703,41 @@ } } + function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }); + } catch { + // todo: Just ignore this exception? + } + } + class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }); - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args); } } + + init (args) { + injectNavigatorInterface(args); + } } let adLabelStrings = []; @@ -4822,7 +5089,7 @@ } } - const logoImg = 'data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAA0aXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarZxpkhw5kqX/4xR1BOzLcQAFIDI36OP392BB5lY9Uy0yyWQyMsLpbgaovkVVYe781/+57l//+lcIPXeXS+t11Or5J4884uSL7r9/xvtv8Pn99/3T88/Pwl+/737/IPKtxJ/p+982f14/+X750xv9ep/11++7/vOT2H/eKPx+4/dP0ifr6/3ni+T78ft++LkQN873RR29/flS188b2a8r7n/8zr8v6/tD/+/+8o3GKu3CB6UYTwrJv//m7wqSfoc0+TPx35Aar/Np8HVJ0b1vxZ83Y0H+cnu//vT+zwv0l0X+9ZX7++r//upvix/nz/fT39ay/qwRX/zbH4Tyt++n3x8T//zB6fcVxb/+IIS4/3E7P7/v3f3e893dzJUVrT8R9RY7/HobXrhY8vT+WuVX43fh6/Z+DX51P72x5dubX/yyMEJkV64LOewwww3n/WnBuMQcT2RPYozGRul7nT0a0dgldlG/wo2NHdups5cWj2Mrc4q/ryW8zx3v8yx0PnkHXhoDb8bu/s+/3P/th/+bX+5ee0vs+++14rqiIovL0M7pv7yKDQn3Z9/KW+Bfv3623/8pfhSqmZdpmTs3OP363mKV8EdspbfPidcV/vxSKLi2f96AJeKzCxcTEjvga0gl1OBbjC0E1rGzQZMrjynHxQ6EUuLmImNOqUbXYo/6bP5OC++1scQa9W2wiY0oqabG3pBTbFbOhfhpuRNDs6SSSym1tNJdGWXWVHMttdZWBXKzpZZbabW11ttosycgsPTaW+999DniSGBgGXW00ccYc0Y3+aDJe01eP/nOiiutvMqqq62+xppG+Fi2YtWadRs2d9xpAxO77rb7Hnue4A5IcfIpp552+hlnXmLtpptvufW22++48/eu/ezqP379L3Yt/OxafDul17Xfu8Z3XWu/3iIITor2jB2LObDjTTtAQEftme8h56id0575EUmKErnIor1xO2jH2MJ8Qiw3/N67P3buP9o3V/p/tG/x/7VzTlv3/2PnHFv3z337N7u2xXP2duzLQq2pT2QfPz99utinSG3++z9H9vER0ogNiCz11FFYzM3HZH6SY2UHQOvr7LCJx9/pYxrz3JXnZbdYl+pjGens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'; + const logoImg = 'data:image/png;base64,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'; const loadingImages = { darkMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E', lightMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E' // 'data:application/octet-stream;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxzdHlsZT4KCQlAa2V5ZnJhbWVzIHJvdGF0ZSB7CgkJCWZyb20gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CgkJCX0KCQkJdG8gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMzU5ZGVnKTsKCQkJfQoJCX0KCTwvc3R5bGU+Cgk8ZyBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTAlIDUwJTsgYW5pbWF0aW9uOiByb3RhdGUgMXMgaW5maW5pdGUgcmV2ZXJzZSBsaW5lYXI7Ij4KCQk8cmVjdCB4PSIxOC4wOTY4IiB5PSIxNi4wODYxIiB3aWR0aD0iMyIgaGVpZ2h0PSI3IiByeD0iMS41IiB0cmFuc2Zvcm09InJvdGF0ZSgxMzYuMTYxIDE4LjA5NjggMTYuMDg2MSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+CQoJCTxyZWN0IHg9IjguNDk4NzgiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CgkJPHJlY3QgeD0iMTkuOTk3NiIgeT0iOC4zNzQ1MSIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgdHJhbnNmb3JtPSJyb3RhdGUoOTAgMTkuOTk3NiA4LjM3NDUxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjIiLz4KCQk8cmVjdCB4PSIxNi4xNzI3IiB5PSIxLjk5MTciIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgMTYuMTcyNyAxLjk5MTcpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuMyIvPgoJCTxyZWN0IHg9IjguOTEzMDkiIHk9IjYuODg1MDEiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDEzNi4xNjEgOC45MTMwOSA2Ljg4NTAxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KCQk8cmVjdCB4PSI2Ljc5NjAyIiB5PSIxMC45OTYiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgNi43OTYwMiAxMC45OTYpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuNyIvPgoJCTxyZWN0IHg9IjciIHk9IjguNjI1NDkiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDkwIDcgOC42MjU0OSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC44Ii8+CQkKCQk8cmVjdCB4PSI4LjQ5ODc4IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjkiLz4KCTwvZz4KPC9zdmc+Cg==' @@ -4835,117 +5102,128 @@ const videoPlayDark = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23222222%22%2F%3E%0A%3C%2Fsvg%3E%0A'; const videoPlayLight = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23FFFFFF%22%2F%3E%0A%3C%2Fsvg%3E'; - const ddgFont = 'data:application/octet-stream;base64,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'; - const ddgFontBold = 'data:application/octet-stream;base64,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'; - var localesJSON = `{"bg":{"facebook.json":{"informationalModalMessageTitle":"При влизане разрешавате на Facebook да Ви проследява","informationalModalMessageBody":"След като влезете, DuckDuckGo не може да блокира проследяването от Facebook в съдържанието на този сайт.","informationalModalConfirmButtonText":"Вход","informationalModalRejectButtonText":"Назад","loginButtonText":"Вход във Facebook","loginBodyText":"Facebook проследява Вашата активност в съответния сайт, когато го използвате за вход.","buttonTextUnblockContent":"Разблокиране на съдържанието","buttonTextUnblockComment":"Разблокиране на коментара","buttonTextUnblockComments":"Разблокиране на коментарите","buttonTextUnblockPost":"Разблокиране на публикацията","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockContent":"DuckDuckGo блокира това съдържание, за да предотврати проследяване от Facebook","infoTitleUnblockComment":"DuckDuckGo блокира този коментар, за да предотврати проследяване от Facebook","infoTitleUnblockComments":"DuckDuckGo блокира тези коментари, за да предотврати проследяване от Facebook","infoTitleUnblockPost":"DuckDuckGo блокира тази публикация, за да предотврати проследяване от Facebook","infoTitleUnblockVideo":"DuckDuckGo блокира това видео, за да предотврати проследяване от Facebook","infoTextUnblockContent":"Блокирахме проследяването от Facebook при зареждане на страницата. Ако разблокирате това съдържание, Facebook ще следи Вашата активност."},"shared.json":{"learnMore":"Научете повече","readAbout":"Прочетете за тази защита на поверителността"},"youtube.json":{"informationalModalMessageTitle":"Активиране на всички прегледи в YouTube?","informationalModalMessageBody":"Показването на преглед позволява на Google (собственик на YouTube) да види част от информацията за Вашето устройство, но все пак осигурява повече поверителност отколкото при възпроизвеждане на видеоклипа.","informationalModalConfirmButtonText":"Активиране на всички прегледи","informationalModalRejectButtonText":"Не, благодаря","buttonTextUnblockVideo":"Разблокиране на видеото","infoTitleUnblockVideo":"DuckDuckGo блокира този видеоклип в YouTube, за да предотврати проследяване от Google","infoTextUnblockVideo":"Блокирахме проследяването от Google (собственик на YouTube) при зареждане на страницата. Ако разблокирате този видеоклип, Google ще следи Вашата активност.","infoPreviewToggleText":"Прегледите са деактивирани за осигуряване на допълнителна поверителност","infoPreviewToggleEnabledText":"Прегледите са активирани","infoPreviewInfoText":"Научете повече за вградената защита от социални медии на DuckDuckGo"}},"cs":{"facebook.json":{"informationalModalMessageTitle":"Když se přihlásíš přes Facebook, bude tě moct sledovat","informationalModalMessageBody":"Po přihlášení už DuckDuckGo nemůže bránit Facebooku, aby tě na téhle stránce sledoval.","informationalModalConfirmButtonText":"Přihlásit se","informationalModalRejectButtonText":"Zpět","loginButtonText":"Přihlásit se pomocí Facebooku","loginBodyText":"Facebook sleduje tvou aktivitu na webu, když se přihlásíš jeho prostřednictvím.","buttonTextUnblockContent":"Odblokovat obsah","buttonTextUnblockComment":"Odblokovat komentář","buttonTextUnblockComments":"Odblokovat komentáře","buttonTextUnblockPost":"Odblokovat příspěvek","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockContent":"DuckDuckGo zablokoval tenhle obsah, aby Facebooku zabránil tě sledovat","infoTitleUnblockComment":"Služba DuckDuckGo zablokovala tento komentář, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockComments":"Služba DuckDuckGo zablokovala tyto komentáře, aby Facebooku zabránila ve tvém sledování","infoTitleUnblockPost":"DuckDuckGo zablokoval tenhle příspěvek, aby Facebooku zabránil tě sledovat","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video, aby Facebooku zabránil tě sledovat","infoTextUnblockContent":"Při načítání stránky jsme Facebooku zabránili, aby tě sledoval. Když tenhle obsah odblokuješ, Facebook bude mít přístup ke tvé aktivitě."},"shared.json":{"learnMore":"Více informací","readAbout":"Přečti si o téhle ochraně soukromí"},"youtube.json":{"informationalModalMessageTitle":"Zapnout všechny náhledy YouTube?","informationalModalMessageBody":"Zobrazování náhledů umožní společnosti Google (která vlastní YouTube) zobrazit některé informace o tvém zařízení, ale pořád jde o diskrétnější volbu, než je přehrávání videa.","informationalModalConfirmButtonText":"Zapnout všechny náhledy","informationalModalRejectButtonText":"Ne, děkuji","buttonTextUnblockVideo":"Odblokovat video","infoTitleUnblockVideo":"DuckDuckGo zablokoval tohle video z YouTube, aby Googlu zabránil tě sledovat","infoTextUnblockVideo":"Zabránili jsme společnosti Google (která vlastní YouTube), aby tě při načítání stránky sledovala. Pokud toto video odblokuješ, Google získá přístup ke tvé aktivitě.","infoPreviewToggleText":"Náhledy jsou pro větší soukromí vypnuté","infoPreviewToggleEnabledText":"Náhledy jsou zapnuté","infoPreviewInfoText":"Další informace o ochraně DuckDuckGo před sledováním prostřednictvím vloženého obsahu ze sociálních médií"}},"da":{"facebook.json":{"informationalModalMessageTitle":"Når du logger ind med Facebook, kan de spore dig","informationalModalMessageBody":"Når du er logget ind, kan DuckDuckGo ikke blokere for, at indhold fra Facebook sporer dig på dette websted.","informationalModalConfirmButtonText":"Log på","informationalModalRejectButtonText":"Gå tilbage","loginButtonText":"Log ind med Facebook","loginBodyText":"Facebook sporer din aktivitet på et websted, når du bruger dem til at logge ind.","buttonTextUnblockContent":"Fjern blokering af indhold","buttonTextUnblockComment":"Fjern blokering af kommentar","buttonTextUnblockComments":"Fjern blokering af kommentarer","buttonTextUnblockPost":"Fjern blokering af indlæg","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockContent":"DuckDuckGo har blokeret dette indhold for at forhindre Facebook i at spore dig","infoTitleUnblockComment":"DuckDuckGo har blokeret denne kommentar for at forhindre Facebook i at spore dig","infoTitleUnblockComments":"DuckDuckGo har blokeret disse kommentarer for at forhindre Facebook i at spore dig","infoTitleUnblockPost":"DuckDuckGo blokerede dette indlæg for at forhindre Facebook i at spore dig","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne video for at forhindre Facebook i at spore dig","infoTextUnblockContent":"Vi blokerede for, at Facebook sporede dig, da siden blev indlæst. Hvis du ophæver blokeringen af dette indhold, vil Facebook kende din aktivitet."},"shared.json":{"learnMore":"Mere info","readAbout":"Læs om denne beskyttelse af privatlivet"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Med forhåndsvisninger kan Google (som ejer YouTube) se nogle af enhedens oplysninger, men det er stadig mere privat end at afspille videoen.","informationalModalConfirmButtonText":"Aktivér alle forhåndsvisninger","informationalModalRejectButtonText":"Nej tak.","buttonTextUnblockVideo":"Fjern blokering af video","infoTitleUnblockVideo":"DuckDuckGo har blokeret denne YouTube-video for at forhindre Google i at spore dig","infoTextUnblockVideo":"Vi blokerede Google (som ejer YouTube) fra at spore dig, da siden blev indlæst. Hvis du fjerner blokeringen af denne video, vil Google få kendskab til din aktivitet.","infoPreviewToggleText":"Forhåndsvisninger er deaktiveret for at give yderligere privatliv","infoPreviewToggleEnabledText":"Forhåndsvisninger er deaktiveret","infoPreviewInfoText":"Få mere at vide på om DuckDuckGos indbyggede beskyttelse på sociale medier"}},"de":{"facebook.json":{"informationalModalMessageTitle":"Wenn du dich bei Facebook anmeldest, kann Facebook dich tracken","informationalModalMessageBody":"Sobald du angemeldet bist, kann DuckDuckGo nicht mehr verhindern, dass Facebook-Inhalte dich auf dieser Website tracken.","informationalModalConfirmButtonText":"Anmelden","informationalModalRejectButtonText":"Zurück","loginButtonText":"Mit Facebook anmelden","loginBodyText":"Facebook trackt deine Aktivität auf einer Website, wenn du dich über Facebook dort anmeldest.","buttonTextUnblockContent":"Blockierung aufheben","buttonTextUnblockComment":"Blockierung aufheben","buttonTextUnblockComments":"Blockierung aufheben","buttonTextUnblockPost":"Blockierung aufheben","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockContent":"DuckDuckGo hat diesen Inhalt blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComment":"DuckDuckGo hat diesen Kommentar blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockComments":"DuckDuckGo hat diese Kommentare blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockPost":"DuckDuckGo hat diesen Beitrag blockiert, um zu verhindern, dass Facebook dich trackt","infoTitleUnblockVideo":"DuckDuckGo hat dieses Video blockiert, um zu verhindern, dass Facebook dich trackt","infoTextUnblockContent":"Wir haben Facebook daran gehindert, dich zu tracken, als die Seite geladen wurde. Wenn du die Blockierung für diesen Inhalt aufhebst, kennt Facebook deine Aktivitäten."},"shared.json":{"learnMore":"Mehr erfahren","readAbout":"Weitere Informationen über diesen Datenschutz"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-Vorschauen aktivieren?","informationalModalMessageBody":"Durch das Anzeigen von Vorschauen kann Google (dem YouTube gehört) einige Informationen zu deinem Gerät sehen. Dies ist aber immer noch privater als das Abspielen des Videos.","informationalModalConfirmButtonText":"Alle Vorschauen aktivieren","informationalModalRejectButtonText":"Nein, danke","buttonTextUnblockVideo":"Blockierung aufheben","infoTitleUnblockVideo":"DuckDuckGo hat dieses YouTube-Video blockiert, um zu verhindern, dass Google dich trackt.","infoTextUnblockVideo":"Wir haben Google (dem YouTube gehört) daran gehindert, dich beim Laden der Seite zu tracken. Wenn du die Blockierung für dieses Video aufhebst, kennt Google deine Aktivitäten.","infoPreviewToggleText":"Vorschau für mehr Privatsphäre deaktiviert","infoPreviewToggleEnabledText":"Vorschau aktiviert","infoPreviewInfoText":"Erfahre mehr über den DuckDuckGo-Schutz vor eingebetteten Social Media-Inhalten"}},"el":{"facebook.json":{"informationalModalMessageTitle":"Η σύνδεση μέσω Facebook τους επιτρέπει να σας παρακολουθούν","informationalModalMessageBody":"Μόλις συνδεθείτε, το DuckDuckGo δεν μπορεί να εμποδίσει το περιεχόμενο του Facebook από το να σας παρακολουθεί σε αυτόν τον ιστότοπο.","informationalModalConfirmButtonText":"Σύνδεση","informationalModalRejectButtonText":"Επιστροφή","loginButtonText":"Σύνδεση μέσω Facebook","loginBodyText":"Το Facebook παρακολουθεί τη δραστηριότητά σας σε έναν ιστότοπο όταν τον χρησιμοποιείτε για να συνδεθείτε.","buttonTextUnblockContent":"Άρση αποκλεισμού περιεχομένου","buttonTextUnblockComment":"Άρση αποκλεισμού σχολίου","buttonTextUnblockComments":"Άρση αποκλεισμού σχολίων","buttonTextUnblockPost":"Άρση αποκλεισμού ανάρτησης","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockContent":"Το DuckDuckGo απέκλεισε το περιεχόμενο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComment":"Το DuckDuckGo απέκλεισε το σχόλιο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockComments":"Το DuckDuckGo απέκλεισε τα σχόλια αυτά για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockPost":"Το DuckDuckGo απέκλεισε την ανάρτηση αυτή για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό για να εμποδίσει το Facebook από το να σας παρακολουθεί","infoTextUnblockContent":"Αποκλείσαμε το Facebook από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το περιεχόμενο, το Facebook θα γνωρίζει τη δραστηριότητά σας."},"shared.json":{"learnMore":"Μάθετε περισσότερα","readAbout":"Διαβάστε σχετικά με την παρούσα προστασίας προσωπικών δεδομένων"},"youtube.json":{"informationalModalMessageTitle":"Ενεργοποίηση όλων των προεπισκοπήσεων του YouTube;","informationalModalMessageBody":"Η προβολή των προεπισκοπήσεων θα επιτρέψει στην Google (στην οποία ανήκει το YouTube) να βλέπει ορισμένες από τις πληροφορίες της συσκευής σας, ωστόσο εξακολουθεί να είναι πιο ιδιωτική από την αναπαραγωγή του βίντεο.","informationalModalConfirmButtonText":"Ενεργοποίηση όλων των προεπισκοπήσεων","informationalModalRejectButtonText":"Όχι, ευχαριστώ","buttonTextUnblockVideo":"Άρση αποκλεισμού βίντεο","infoTitleUnblockVideo":"Το DuckDuckGo απέκλεισε το βίντεο αυτό στο YouTube για να εμποδίσει την Google από το να σας παρακολουθεί","infoTextUnblockVideo":"Αποκλείσαμε την Google (στην οποία ανήκει το YouTube) από το να σας παρακολουθεί όταν φορτώθηκε η σελίδα. Εάν κάνετε άρση αποκλεισμού γι' αυτό το βίντεο, η Google θα γνωρίζει τη δραστηριότητά σας.","infoPreviewToggleText":"Οι προεπισκοπήσεις απενεργοποιήθηκαν για πρόσθετη προστασία των προσωπικών δεδομένων","infoPreviewToggleEnabledText":"Οι προεπισκοπήσεις ενεργοποιήθηκαν","infoPreviewInfoText":"Μάθετε περισσότερα για την ενσωματωμένη προστασία κοινωνικών μέσων DuckDuckGo"}},"en":{"facebook.json":{"informationalModalMessageTitle":"Logging in with Facebook lets them track you","informationalModalMessageBody":"Once you're logged in, DuckDuckGo can't block Facebook content from tracking you on this site.","informationalModalConfirmButtonText":"Log In","informationalModalRejectButtonText":"Go back","loginButtonText":"Log in with Facebook","loginBodyText":"Facebook tracks your activity on a site when you use them to login.","buttonTextUnblockContent":"Unblock Content","buttonTextUnblockComment":"Unblock Comment","buttonTextUnblockComments":"Unblock Comments","buttonTextUnblockPost":"Unblock Post","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockContent":"DuckDuckGo blocked this content to prevent Facebook from tracking you","infoTitleUnblockComment":"DuckDuckGo blocked this comment to prevent Facebook from tracking you","infoTitleUnblockComments":"DuckDuckGo blocked these comments to prevent Facebook from tracking you","infoTitleUnblockPost":"DuckDuckGo blocked this post to prevent Facebook from tracking you","infoTitleUnblockVideo":"DuckDuckGo blocked this video to prevent Facebook from tracking you","infoTextUnblockContent":"We blocked Facebook from tracking you when the page loaded. If you unblock this content, Facebook will know your activity."},"shared.json":{"learnMore":"Learn More","readAbout":"Read about this privacy protection"},"youtube.json":{"informationalModalMessageTitle":"Enable all YouTube previews?","informationalModalMessageBody":"Showing previews will allow Google (which owns YouTube) to see some of your device’s information, but is still more private than playing the video.","informationalModalConfirmButtonText":"Enable All Previews","informationalModalRejectButtonText":"No Thanks","buttonTextUnblockVideo":"Unblock Video","infoTitleUnblockVideo":"DuckDuckGo blocked this YouTube video to prevent Google from tracking you","infoTextUnblockVideo":"We blocked Google (which owns YouTube) from tracking you when the page loaded. If you unblock this video, Google will know your activity.","infoPreviewToggleText":"Previews disabled for additional privacy","infoPreviewToggleEnabledText":"Previews enabled","infoPreviewInfoText":"Learn more about DuckDuckGo Embedded Social Media Protection"}},"es":{"facebook.json":{"informationalModalMessageTitle":"Al iniciar sesión en Facebook, les permites que te rastreen","informationalModalMessageBody":"Una vez que hayas iniciado sesión, DuckDuckGo no puede bloquear el contenido de Facebook para que no te rastree en este sitio.","informationalModalConfirmButtonText":"Iniciar sesión","informationalModalRejectButtonText":"Volver atrás","loginButtonText":"Iniciar sesión con Facebook","loginBodyText":"Facebook rastrea tu actividad en un sitio web cuando lo usas para iniciar sesión.","buttonTextUnblockContent":"Desbloquear contenido","buttonTextUnblockComment":"Desbloquear comentario","buttonTextUnblockComments":"Desbloquear comentarios","buttonTextUnblockPost":"Desbloquear publicación","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockContent":"DuckDuckGo ha bloqueado este contenido para evitar que Facebook te rastree","infoTitleUnblockComment":"DuckDuckGo ha bloqueado este comentario para evitar que Facebook te rastree","infoTitleUnblockComments":"DuckDuckGo ha bloqueado estos comentarios para evitar que Facebook te rastree","infoTitleUnblockPost":"DuckDuckGo ha bloqueado esta publicación para evitar que Facebook te rastree","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo para evitar que Facebook te rastree","infoTextUnblockContent":"Hemos bloqueado el rastreo de Facebook cuando se ha cargado la página. Si desbloqueas este contenido, Facebook tendrá conocimiento de tu actividad."},"shared.json":{"learnMore":"Más información","readAbout":"Lee acerca de esta protección de privacidad"},"youtube.json":{"informationalModalMessageTitle":"¿Habilitar todas las vistas previas de YouTube?","informationalModalMessageBody":"Mostrar vistas previas permitirá a Google (que es el propietario de YouTube) ver parte de la información de tu dispositivo, pero sigue siendo más privado que reproducir el vídeo.","informationalModalConfirmButtonText":"Habilitar todas las vistas previas","informationalModalRejectButtonText":"No, gracias","buttonTextUnblockVideo":"Desbloquear vídeo","infoTitleUnblockVideo":"DuckDuckGo ha bloqueado este vídeo de YouTube para evitar que Google te rastree","infoTextUnblockVideo":"Hemos bloqueado el rastreo de Google (que es el propietario de YouTube) al cargarse la página. Si desbloqueas este vídeo, Goggle tendrá conocimiento de tu actividad.","infoPreviewToggleText":"Vistas previas desactivadas para mayor privacidad","infoPreviewToggleEnabledText":"Vistas previas activadas","infoPreviewInfoText":"Más información sobre la protección integrada de redes sociales DuckDuckGo"}},"et":{"facebook.json":{"informationalModalMessageTitle":"Kui logid Facebookiga sisse, saab Facebook sind jälgida","informationalModalMessageBody":"Kui oled sisse logitud, ei saa DuckDuckGo blokeerida Facebooki sisu sind jälgimast.","informationalModalConfirmButtonText":"Logi sisse","informationalModalRejectButtonText":"Mine tagasi","loginButtonText":"Logi sisse Facebookiga","loginBodyText":"Kui logid sisse Facebookiga, saab Facebook sinu tegevust saidil jälgida.","buttonTextUnblockContent":"Deblokeeri sisu","buttonTextUnblockComment":"Deblokeeri kommentaar","buttonTextUnblockComments":"Deblokeeri kommentaarid","buttonTextUnblockPost":"Deblokeeri postitus","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockContent":"DuckDuckGo blokeeris selle sisu, et Facebook ei saaks sind jälgida","infoTitleUnblockComment":"DuckDuckGo blokeeris selle kommentaari, et Facebook ei saaks sind jälgida","infoTitleUnblockComments":"DuckDuckGo blokeeris need kommentaarid, et Facebook ei saaks sind jälgida","infoTitleUnblockPost":"DuckDuckGo blokeeris selle postituse, et Facebook ei saaks sind jälgida","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle video, et Facebook ei saaks sind jälgida","infoTextUnblockContent":"Blokeerisime lehe laadimise ajal Facebooki jaoks sinu jälgimise. Kui sa selle sisu deblokeerid, saab Facebook sinu tegevust jälgida."},"shared.json":{"learnMore":"Loe edasi","readAbout":"Loe selle privaatsuskaitse kohta"},"youtube.json":{"informationalModalMessageTitle":"Kas lubada kõik YouTube’i eelvaated?","informationalModalMessageBody":"Eelvaate näitamine võimaldab Google’il (kellele YouTube kuulub) näha osa sinu seadme teabest, kuid see on siiski privaatsem kui video esitamine.","informationalModalConfirmButtonText":"Luba kõik eelvaated","informationalModalRejectButtonText":"Ei aitäh","buttonTextUnblockVideo":"Deblokeeri video","infoTitleUnblockVideo":"DuckDuckGo blokeeris selle YouTube’i video, et takistada Google’it sind jälgimast","infoTextUnblockVideo":"Me blokeerisime lehe laadimise ajal Google’i (kellele YouTube kuulub) jälgimise. Kui sa selle video deblokeerid, saab Google sinu tegevusest teada.","infoPreviewToggleText":"Eelvaated on täiendava privaatsuse tagamiseks keelatud","infoPreviewToggleEnabledText":"Eelvaated on lubatud","infoPreviewInfoText":"Lisateave DuckDuckGo sisseehitatud sotsiaalmeediakaitse kohta"}},"fi":{"facebook.json":{"informationalModalMessageTitle":"Kun kirjaudut sisään Facebook-tunnuksilla, Facebook voi seurata sinua","informationalModalMessageBody":"Kun olet kirjautunut sisään, DuckDuckGo ei voi estää Facebook-sisältöä seuraamasta sinua tällä sivustolla.","informationalModalConfirmButtonText":"Kirjaudu sisään","informationalModalRejectButtonText":"Edellinen","loginButtonText":"Kirjaudu sisään Facebook-tunnuksilla","loginBodyText":"Facebook seuraa toimintaasi sivustolla, kun kirjaudut sisään sen kautta.","buttonTextUnblockContent":"Poista sisällön esto","buttonTextUnblockComment":"Poista kommentin esto","buttonTextUnblockComments":"Poista kommenttien esto","buttonTextUnblockPost":"Poista julkaisun esto","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockContent":"DuckDuckGo esti tämän sisällön estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComment":"DuckDuckGo esti tämän kommentin estääkseen Facebookia seuraamasta sinua","infoTitleUnblockComments":"DuckDuckGo esti nämä kommentit estääkseen Facebookia seuraamasta sinua","infoTitleUnblockPost":"DuckDuckGo esti tämän julkaisun estääkseen Facebookia seuraamasta sinua","infoTitleUnblockVideo":"DuckDuckGo esti tämän videon estääkseen Facebookia seuraamasta sinua","infoTextUnblockContent":"Estimme Facebookia seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän sisällön eston, Facebook saa tietää toimintasi."},"shared.json":{"learnMore":"Lue lisää","readAbout":"Lue tästä yksityisyydensuojasta"},"youtube.json":{"informationalModalMessageTitle":"Otetaanko käyttöön kaikki YouTube-esikatselut?","informationalModalMessageBody":"Kun sallit esikatselun, Google (joka omistaa YouTuben) voi nähdä joitakin laitteesi tietoja, mutta se on silti yksityisempää kuin videon toistaminen.","informationalModalConfirmButtonText":"Ota käyttöön kaikki esikatselut","informationalModalRejectButtonText":"Ei kiitos","buttonTextUnblockVideo":"Poista videon esto","infoTitleUnblockVideo":"DuckDuckGo esti tämän YouTube-videon, jotta Google ei voi seurata sinua","infoTextUnblockVideo":"Estimme Googlea (joka omistaa YouTuben) seuraamasta sinua, kun sivua ladattiin. Jos poistat tämän videon eston, Google tietää toimintasi.","infoPreviewToggleText":"Esikatselut on poistettu käytöstä yksityisyyden lisäämiseksi","infoPreviewToggleEnabledText":"Esikatselut käytössä","infoPreviewInfoText":"Lue lisää DuckDuckGon upotetusta sosiaalisen median suojauksesta"}},"fr":{"facebook.json":{"informationalModalMessageTitle":"L'identification via Facebook leur permet de vous pister","informationalModalMessageBody":"Une fois que vous êtes connecté(e), DuckDuckGo ne peut pas empêcher le contenu Facebook de vous pister sur ce site.","informationalModalConfirmButtonText":"Connexion","informationalModalRejectButtonText":"Revenir en arrière","loginButtonText":"S'identifier avec Facebook","loginBodyText":"Facebook piste votre activité sur un site lorsque vous l'utilisez pour vous identifier.","buttonTextUnblockContent":"Débloquer le contenu","buttonTextUnblockComment":"Débloquer le commentaire","buttonTextUnblockComments":"Débloquer les commentaires","buttonTextUnblockPost":"Débloquer la publication","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockContent":"DuckDuckGo a bloqué ce contenu pour empêcher Facebook de vous suivre","infoTitleUnblockComment":"DuckDuckGo a bloqué ce commentaire pour empêcher Facebook de vous suivre","infoTitleUnblockComments":"DuckDuckGo a bloqué ces commentaires pour empêcher Facebook de vous suivre","infoTitleUnblockPost":"DuckDuckGo a bloqué cette publication pour empêcher Facebook de vous pister","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo pour empêcher Facebook de vous pister","infoTextUnblockContent":"Nous avons empêché Facebook de vous pister lors du chargement de la page. Si vous débloquez ce contenu, Facebook connaîtra votre activité."},"shared.json":{"learnMore":"En savoir plus","readAbout":"En savoir plus sur cette protection de la confidentialité"},"youtube.json":{"informationalModalMessageTitle":"Activer tous les aperçus YouTube ?","informationalModalMessageBody":"L'affichage des aperçus permettra à Google (propriétaire de YouTube) de voir certaines informations de votre appareil, mais cela reste davantage confidentiel qu'en lisant la vidéo.","informationalModalConfirmButtonText":"Activer tous les aperçus","informationalModalRejectButtonText":"Non merci","buttonTextUnblockVideo":"Débloquer la vidéo","infoTitleUnblockVideo":"DuckDuckGo a bloqué cette vidéo YouTube pour empêcher Google de vous pister","infoTextUnblockVideo":"Nous avons empêché Google (propriétaire de YouTube) de vous pister lors du chargement de la page. Si vous débloquez cette vidéo, Google connaîtra votre activité.","infoPreviewToggleText":"Aperçus désactivés pour plus de confidentialité","infoPreviewToggleEnabledText":"Aperçus activés","infoPreviewInfoText":"En savoir plus sur la protection intégrée DuckDuckGo des réseaux sociaux"}},"hr":{"facebook.json":{"informationalModalMessageTitle":"Prijava putem Facebooka omogućuje im da te prate","informationalModalMessageBody":"Nakon što se prijaviš, DuckDuckGo ne može blokirati Facebookov sadržaj da te prati na Facebooku.","informationalModalConfirmButtonText":"Prijavljivanje","informationalModalRejectButtonText":"Vrati se","loginButtonText":"Prijavi se putem Facebooka","loginBodyText":"Facebook prati tvoju aktivnost na toj web lokaciji kad je koristiš za prijavu.","buttonTextUnblockContent":"Deblokiranje sadržaja","buttonTextUnblockComment":"Deblokiranje komentara","buttonTextUnblockComments":"Deblokiranje komentara","buttonTextUnblockPost":"Deblokiranje objave","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockContent":"DuckDuckGo je blokirao ovaj sadržaj kako bi spriječio Facebook da te prati","infoTitleUnblockComment":"DuckDuckGo je blokirao ovaj komentar kako bi spriječio Facebook da te prati","infoTitleUnblockComments":"DuckDuckGo je blokirao ove komentare kako bi spriječio Facebook da te prati","infoTitleUnblockPost":"DuckDuckGo je blokirao ovu objavu kako bi spriječio Facebook da te prati","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj video kako bi spriječio Facebook da te prati","infoTextUnblockContent":"Blokirali smo Facebook da te prati kad se stranica učita. Ako deblokiraš ovaj sadržaj, Facebook će znati tvoju aktivnost."},"shared.json":{"learnMore":"Saznajte više","readAbout":"Pročitaj više o ovoj zaštiti privatnosti"},"youtube.json":{"informationalModalMessageTitle":"Omogućiti sve YouTube pretpreglede?","informationalModalMessageBody":"Prikazivanje pretpregleda omogućit će Googleu (u čijem je vlasništvu YouTube) da vidi neke podatke o tvom uređaju, ali je i dalje privatnija opcija od reprodukcije videozapisa.","informationalModalConfirmButtonText":"Omogući sve pretpreglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Deblokiranje videozapisa","infoTitleUnblockVideo":"DuckDuckGo je blokirao ovaj YouTube videozapis kako bi spriječio Google da te prati","infoTextUnblockVideo":"Blokirali smo Google (u čijem je vlasništvu YouTube) da te prati kad se stranica učita. Ako deblokiraš ovaj videozapis, Google će znati tvoju aktivnost.","infoPreviewToggleText":"Pretpregledi su onemogućeni radi dodatne privatnosti","infoPreviewToggleEnabledText":"Pretpregledi su omogućeni","infoPreviewInfoText":"Saznaj više o uključenoj DuckDuckGo zaštiti od društvenih medija"}},"hu":{"facebook.json":{"informationalModalMessageTitle":"A Facebookkal való bejelentkezéskor a Facebook nyomon követhet","informationalModalMessageBody":"Miután bejelentkezel, a DuckDuckGo nem fogja tudni blokkolni a Facebook-tartalmat, amely nyomon követ ezen az oldalon.","informationalModalConfirmButtonText":"Bejelentkezés","informationalModalRejectButtonText":"Visszalépés","loginButtonText":"Bejelentkezés Facebookkal","loginBodyText":"Ha a Facebookkal jelentkezel be, nyomon követik a webhelyen végzett tevékenységedet.","buttonTextUnblockContent":"Tartalom feloldása","buttonTextUnblockComment":"Hozzászólás feloldása","buttonTextUnblockComments":"Hozzászólások feloldása","buttonTextUnblockPost":"Bejegyzés feloldása","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockContent":"A DuckDuckGo blokkolta ezt a tartalmat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComment":"A DuckDuckGo blokkolta ezt a hozzászólást, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockComments":"A DuckDuckGo blokkolta ezeket a hozzászólásokat, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockPost":"A DuckDuckGo blokkolta ezt a bejegyzést, hogy megakadályozza a Facebookot a nyomon követésedben","infoTitleUnblockVideo":"A DuckDuckGo blokkolta ezt a videót, hogy megakadályozza a Facebookot a nyomon követésedben","infoTextUnblockContent":"Az oldal betöltésekor blokkoltuk a Facebookot a nyomon követésedben. Ha feloldod ezt a tartalmat, a Facebook tudni fogja, hogy milyen tevékenységet végzel."},"shared.json":{"learnMore":"További részletek","readAbout":"Tudj meg többet erről az adatvédelemről"},"youtube.json":{"informationalModalMessageTitle":"Engedélyezed minden YouTube-videó előnézetét?","informationalModalMessageBody":"Az előnézetek megjelenítésével a Google (a YouTube tulajdonosa) láthatja a készülék néhány adatát, de ez adatvédelmi szempontból még mindig előnyösebb, mint a videó lejátszása.","informationalModalConfirmButtonText":"Minden előnézet engedélyezése","informationalModalRejectButtonText":"Nem, köszönöm","buttonTextUnblockVideo":"Videó feloldása","infoTitleUnblockVideo":"A DuckDuckGo blokkolta a YouTube-videót, hogy a Google ne követhessen nyomon","infoTextUnblockVideo":"Blokkoltuk, hogy a Google (a YouTube tulajdonosa) nyomon követhessen az oldal betöltésekor. Ha feloldod a videó blokkolását, a Google tudni fogja, hogy milyen tevékenységet végzel.","infoPreviewToggleText":"Az előnézetek a fokozott adatvédelem érdekében letiltva","infoPreviewToggleEnabledText":"Az előnézetek engedélyezve","infoPreviewInfoText":"További tudnivalók a DuckDuckGo beágyazott közösségi média elleni védelméről"}},"it":{"facebook.json":{"informationalModalMessageTitle":"L'accesso con Facebook consente di tracciarti","informationalModalMessageBody":"Dopo aver effettuato l'accesso, DuckDuckGo non può bloccare il tracciamento dei contenuti di Facebook su questo sito.","informationalModalConfirmButtonText":"Accedi","informationalModalRejectButtonText":"Torna indietro","loginButtonText":"Accedi con Facebook","loginBodyText":"Facebook tiene traccia della tua attività su un sito quando lo usi per accedere.","buttonTextUnblockContent":"Sblocca contenuti","buttonTextUnblockComment":"Sblocca commento","buttonTextUnblockComments":"Sblocca commenti","buttonTextUnblockPost":"Sblocca post","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockContent":"DuckDuckGo ha bloccato questo contenuto per impedire a Facebook di tracciarti","infoTitleUnblockComment":"DuckDuckGo ha bloccato questo commento per impedire a Facebook di tracciarti","infoTitleUnblockComments":"DuckDuckGo ha bloccato questi commenti per impedire a Facebook di tracciarti","infoTitleUnblockPost":"DuckDuckGo ha bloccato questo post per impedire a Facebook di tracciarti","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video per impedire a Facebook di tracciarti","infoTextUnblockContent":"Abbiamo impedito a Facebook di tracciarti al caricamento della pagina. Se sblocchi questo contenuto, Facebook conoscerà la tua attività."},"shared.json":{"learnMore":"Ulteriori informazioni","readAbout":"Leggi di più su questa protezione della privacy"},"youtube.json":{"informationalModalMessageTitle":"Abilitare tutte le anteprime di YouTube?","informationalModalMessageBody":"La visualizzazione delle anteprime consentirà a Google (che possiede YouTube) di vedere alcune delle informazioni del tuo dispositivo, ma è comunque più privato rispetto alla riproduzione del video.","informationalModalConfirmButtonText":"Abilita tutte le anteprime","informationalModalRejectButtonText":"No, grazie","buttonTextUnblockVideo":"Sblocca video","infoTitleUnblockVideo":"DuckDuckGo ha bloccato questo video di YouTube per impedire a Google di tracciarti","infoTextUnblockVideo":"Abbiamo impedito a Google (che possiede YouTube) di tracciarti quando la pagina è stata caricata. Se sblocchi questo video, Google conoscerà la tua attività.","infoPreviewToggleText":"Anteprime disabilitate per una maggiore privacy","infoPreviewToggleEnabledText":"Anteprime abilitate","infoPreviewInfoText":"Scopri di più sulla protezione dai social media integrata di DuckDuckGo"}},"lt":{"facebook.json":{"informationalModalMessageTitle":"Prisijungę prie „Facebook“ galite būti sekami","informationalModalMessageBody":"Kai esate prisijungę, „DuckDuckGo“ negali užblokuoti „Facebook“ turinio, todėl esate sekami šioje svetainėje.","informationalModalConfirmButtonText":"Prisijungti","informationalModalRejectButtonText":"Grįžti atgal","loginButtonText":"Prisijunkite su „Facebook“","loginBodyText":"„Facebook“ seka jūsų veiklą svetainėje, kai prisijungiate su šia svetaine.","buttonTextUnblockContent":"Atblokuoti turinį","buttonTextUnblockComment":"Atblokuoti komentarą","buttonTextUnblockComments":"Atblokuoti komentarus","buttonTextUnblockPost":"Atblokuoti įrašą","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockContent":"„DuckDuckGo“ užblokavo šį turinį, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComment":"„DuckDuckGo“ užblokavo šį komentarą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockComments":"„DuckDuckGo“ užblokavo šiuos komentarus, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockPost":"„DuckDuckGo“ užblokavo šį įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį vaizdo įrašą, kad „Facebook“ negalėtų jūsų sekti","infoTextUnblockContent":"Užblokavome „Facebook“, kad negalėtų jūsų sekti, kai puslapis buvo įkeltas. Jei atblokuosite šį turinį, „Facebook“ žinos apie jūsų veiklą."},"shared.json":{"learnMore":"Sužinoti daugiau","readAbout":"Skaitykite apie šią privatumo apsaugą"},"youtube.json":{"informationalModalMessageTitle":"Įjungti visas „YouTube“ peržiūras?","informationalModalMessageBody":"Peržiūrų rodymas leis „Google“ (kuriai priklauso „YouTube“) matyti tam tikrą jūsų įrenginio informaciją, tačiau ji vis tiek bus privatesnė nei leidžiant vaizdo įrašą.","informationalModalConfirmButtonText":"Įjungti visas peržiūras","informationalModalRejectButtonText":"Ne, dėkoju","buttonTextUnblockVideo":"Atblokuoti vaizdo įrašą","infoTitleUnblockVideo":"„DuckDuckGo“ užblokavo šį „YouTube“ vaizdo įrašą, kad „Google“ negalėtų jūsų sekti","infoTextUnblockVideo":"Užblokavome „Google“ (kuriai priklauso „YouTube“) galimybę sekti jus, kai puslapis buvo įkeltas. Jei atblokuosite šį vaizdo įrašą, „Google“ sužinos apie jūsų veiklą.","infoPreviewToggleText":"Peržiūros išjungtos dėl papildomo privatumo","infoPreviewToggleEnabledText":"Peržiūros įjungtos","infoPreviewInfoText":"Sužinokite daugiau apie „DuckDuckGo“ įdėtąją socialinės žiniasklaidos apsaugą"}},"lv":{"facebook.json":{"informationalModalMessageTitle":"Ja pieteiksies ar Facebook, viņi varēs tevi izsekot","informationalModalMessageBody":"Kad tu piesakies, DuckDuckGo nevar novērst, ka Facebook saturs tevi izseko šajā vietnē.","informationalModalConfirmButtonText":"Pieteikties","informationalModalRejectButtonText":"Atgriezties","loginButtonText":"Pieteikties ar Facebook","loginBodyText":"Facebook izseko tavas aktivitātes vietnē, kad esi pieteicies ar Facebook.","buttonTextUnblockContent":"Atbloķēt saturu","buttonTextUnblockComment":"Atbloķēt komentāru","buttonTextUnblockComments":"Atbloķēt komentārus","buttonTextUnblockPost":"Atbloķēt ziņu","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockContent":"DuckDuckGo bloķēja šo saturu, lai neļautu Facebook tevi izsekot","infoTitleUnblockComment":"DuckDuckGo bloķēja šo komentāru, lai neļautu Facebook tevi izsekot","infoTitleUnblockComments":"DuckDuckGo bloķēja šos komentārus, lai neļautu Facebook tevi izsekot","infoTitleUnblockPost":"DuckDuckGo bloķēja šo ziņu, lai neļautu Facebook tevi izsekot","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo videoklipu, lai neļautu Facebook tevi izsekot","infoTextUnblockContent":"Mēs bloķējām Facebook iespēju tevi izsekot, ielādējot lapu. Ja atbloķēsi šo saturu, Facebook redzēs, ko tu dari."},"shared.json":{"learnMore":"Uzzināt vairāk","readAbout":"Lasi par šo privātuma aizsardzību"},"youtube.json":{"informationalModalMessageTitle":"Vai iespējot visus YouTube priekšskatījumus?","informationalModalMessageBody":"Priekšskatījumu rādīšana ļaus Google (kam pieder YouTube) redzēt daļu tavas ierīces informācijas, taču tas tāpat ir privātāk par videoklipa atskaņošanu.","informationalModalConfirmButtonText":"Iespējot visus priekšskatījumus","informationalModalRejectButtonText":"Nē, paldies","buttonTextUnblockVideo":"Atbloķēt video","infoTitleUnblockVideo":"DuckDuckGo bloķēja šo YouTube videoklipu, lai neļautu Google tevi izsekot","infoTextUnblockVideo":"Mēs neļāvām Google (kam pieder YouTube) tevi izsekot, kad lapa tika ielādēta. Ja atbloķēsi šo videoklipu, Google zinās, ko tu dari.","infoPreviewToggleText":"Priekšskatījumi ir atspējoti, lai nodrošinātu papildu konfidencialitāti","infoPreviewToggleEnabledText":"Priekšskatījumi ir iespējoti","infoPreviewInfoText":"Uzzini vairāk par DuckDuckGo iegulto sociālo mediju aizsardzību"}},"nb":{"facebook.json":{"informationalModalMessageTitle":"Når du logger på med Facebook, kan de spore deg","informationalModalMessageBody":"Når du er logget på, kan ikke DuckDuckGo hindre Facebook-innhold i å spore deg på dette nettstedet.","informationalModalConfirmButtonText":"Logg inn","informationalModalRejectButtonText":"Gå tilbake","loginButtonText":"Logg på med Facebook","loginBodyText":"Når du logger på med Facebook, sporer de aktiviteten din på nettstedet.","buttonTextUnblockContent":"Opphev blokkering av innhold","buttonTextUnblockComment":"Opphev blokkering av kommentar","buttonTextUnblockComments":"Opphev blokkering av kommentarer","buttonTextUnblockPost":"Opphev blokkering av innlegg","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockContent":"DuckDuckGo blokkerte dette innholdet for å hindre Facebook i å spore deg","infoTitleUnblockComment":"DuckDuckGo blokkerte denne kommentaren for å hindre Facebook i å spore deg","infoTitleUnblockComments":"DuckDuckGo blokkerte disse kommentarene for å hindre Facebook i å spore deg","infoTitleUnblockPost":"DuckDuckGo blokkerte dette innlegget for å hindre Facebook i å spore deg","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne videoen for å hindre Facebook i å spore deg","infoTextUnblockContent":"Vi hindret Facebook i å spore deg da siden ble lastet. Hvis du opphever blokkeringen av dette innholdet, får Facebook vite om aktiviteten din."},"shared.json":{"learnMore":"Finn ut mer","readAbout":"Les om denne personvernfunksjonen"},"youtube.json":{"informationalModalMessageTitle":"Vil du aktivere alle YouTube-forhåndsvisninger?","informationalModalMessageBody":"Forhåndsvisninger gjør det mulig for Google (som eier YouTube) å se enkelte opplysninger om enheten din, men det er likevel mer privat enn å spille av videoen.","informationalModalConfirmButtonText":"Aktiver alle forhåndsvisninger","informationalModalRejectButtonText":"Nei takk","buttonTextUnblockVideo":"Opphev blokkering av video","infoTitleUnblockVideo":"DuckDuckGo blokkerte denne YouTube-videoen for å hindre Google i å spore deg","infoTextUnblockVideo":"Vi blokkerte Google (som eier YouTube) mot å spore deg da siden ble lastet. Hvis du opphever blokkeringen av denne videoen, får Google vite om aktiviteten din.","infoPreviewToggleText":"Forhåndsvisninger er deaktivert for å gi deg ekstra personvern","infoPreviewToggleEnabledText":"Forhåndsvisninger er aktivert","infoPreviewInfoText":"Finn ut mer om DuckDuckGos innebygde beskyttelse for sosiale medier"}},"nl":{"facebook.json":{"informationalModalMessageTitle":"Als je inlogt met Facebook, kunnen zij je volgen","informationalModalMessageBody":"Als je eenmaal bent ingelogd, kan DuckDuckGo niet voorkomen dat Facebook je op deze site volgt.","informationalModalConfirmButtonText":"Inloggen","informationalModalRejectButtonText":"Terug","loginButtonText":"Inloggen met Facebook","loginBodyText":"Facebook volgt je activiteit op een site als je Facebook gebruikt om in te loggen.","buttonTextUnblockContent":"Inhoud deblokkeren","buttonTextUnblockComment":"Opmerking deblokkeren","buttonTextUnblockComments":"Opmerkingen deblokkeren","buttonTextUnblockPost":"Bericht deblokkeren","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockContent":"DuckDuckGo heeft deze inhoud geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComment":"DuckDuckGo heeft deze opmerking geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockComments":"DuckDuckGo heeft deze opmerkingen geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockPost":"DuckDuckGo heeft dit bericht geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTitleUnblockVideo":"DuckDuckGo heeft deze video geblokkeerd om te voorkomen dat Facebook je kan volgen","infoTextUnblockContent":"We hebben voorkomen dat Facebook je volgde toen de pagina werd geladen. Als je deze inhoud deblokkeert, kan Facebook je activiteit zien."},"shared.json":{"learnMore":"Meer informatie","readAbout":"Lees meer over deze privacybescherming"},"youtube.json":{"informationalModalMessageTitle":"Alle YouTube-voorbeelden inschakelen?","informationalModalMessageBody":"Bij het tonen van voorbeelden kan Google (eigenaar van YouTube) een deel van de informatie over je apparaat zien, maar blijft je privacy beter beschermd dan als je de video zou afspelen.","informationalModalConfirmButtonText":"Alle voorbeelden inschakelen","informationalModalRejectButtonText":"Nee, bedankt","buttonTextUnblockVideo":"Video deblokkeren","infoTitleUnblockVideo":"DuckDuckGo heeft deze YouTube-video geblokkeerd om te voorkomen dat Google je kan volgen","infoTextUnblockVideo":"We hebben voorkomen dat Google (eigenaar van YouTube) je volgde toen de pagina werd geladen. Als je deze video deblokkeert, kan Google je activiteit zien.","infoPreviewToggleText":"Voorbeelden uitgeschakeld voor extra privacy","infoPreviewToggleEnabledText":"Voorbeelden ingeschakeld","infoPreviewInfoText":"Meer informatie over DuckDuckGo's bescherming tegen ingesloten social media"}},"pl":{"facebook.json":{"informationalModalMessageTitle":"Jeśli zalogujesz się za pośrednictwem Facebooka, będzie on mógł śledzić Twoją aktywność","informationalModalMessageBody":"Po zalogowaniu się DuckDuckGo nie może zablokować możliwości śledzenia Cię przez Facebooka na tej stronie.","informationalModalConfirmButtonText":"Zaloguj się","informationalModalRejectButtonText":"Wróć","loginButtonText":"Zaloguj się za pośrednictwem Facebooka","loginBodyText":"Facebook śledzi Twoją aktywność na stronie, gdy logujesz się za jego pośrednictwem.","buttonTextUnblockContent":"Odblokuj treść","buttonTextUnblockComment":"Odblokuj komentarz","buttonTextUnblockComments":"Odblokuj komentarze","buttonTextUnblockPost":"Odblokuj post","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockContent":"DuckDuckGo zablokował tę treść, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComment":"DuckDuckGo zablokował ten komentarz, aby Facebook nie mógł Cię śledzić","infoTitleUnblockComments":"DuckDuckGo zablokował te komentarze, aby Facebook nie mógł Cię śledzić","infoTitleUnblockPost":"DuckDuckGo zablokował ten post, aby Facebook nie mógł Cię śledzić","infoTitleUnblockVideo":"DuckDuckGo zablokował tę treść wideo, aby Facebook nie mógł Cię śledzić.","infoTextUnblockContent":"Zablokowaliśmy Facebookowi możliwość śledzenia Cię podczas ładowania strony. Jeśli odblokujesz tę treść, Facebook uzyska informacje o Twojej aktywności."},"shared.json":{"learnMore":"Dowiedz się więcej","readAbout":"Dowiedz się więcej o tej ochronie prywatności"},"youtube.json":{"informationalModalMessageTitle":"Włączyć wszystkie podglądy w YouTube?","informationalModalMessageBody":"Wyświetlanie podglądu pozwala Google (który jest właścicielem YouTube) zobaczyć niektóre informacje o Twoim urządzeniu, ale nadal jest to bardziej prywatne niż odtwarzanie filmu.","informationalModalConfirmButtonText":"Włącz wszystkie podglądy","informationalModalRejectButtonText":"Nie, dziękuję","buttonTextUnblockVideo":"Odblokuj wideo","infoTitleUnblockVideo":"DuckDuckGo zablokował ten film w YouTube, aby uniemożliwić Google śledzenie Twojej aktywności","infoTextUnblockVideo":"Zablokowaliśmy możliwość śledzenia Cię przez Google (właściciela YouTube) podczas ładowania strony. Jeśli odblokujesz ten film, Google zobaczy Twoją aktywność.","infoPreviewToggleText":"Podglądy zostały wyłączone, aby zapewnić większą ptywatność","infoPreviewToggleEnabledText":"Podglądy włączone","infoPreviewInfoText":"Dowiedz się więcej o zabezpieczeniu osadzonych treści społecznościowych DuckDuckGo"}},"pt":{"facebook.json":{"informationalModalMessageTitle":"Iniciar sessão no Facebook permite que este te rastreie","informationalModalMessageBody":"Depois de iniciares sessão, o DuckDuckGo não poderá bloquear o rastreio por parte do conteúdo do Facebook neste site.","informationalModalConfirmButtonText":"Iniciar sessão","informationalModalRejectButtonText":"Retroceder","loginButtonText":"Iniciar sessão com o Facebook","loginBodyText":"O Facebook rastreia a tua atividade num site quando o usas para iniciares sessão.","buttonTextUnblockContent":"Desbloquear Conteúdo","buttonTextUnblockComment":"Desbloquear Comentário","buttonTextUnblockComments":"Desbloquear Comentários","buttonTextUnblockPost":"Desbloquear Publicação","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockContent":"O DuckDuckGo bloqueou este conteúdo para evitar que o Facebook te rastreie","infoTitleUnblockComment":"O DuckDuckGo bloqueou este comentário para evitar que o Facebook te rastreie","infoTitleUnblockComments":"O DuckDuckGo bloqueou estes comentários para evitar que o Facebook te rastreie","infoTitleUnblockPost":"O DuckDuckGo bloqueou esta publicação para evitar que o Facebook te rastreie","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo para evitar que o Facebook te rastreie","infoTextUnblockContent":"Bloqueámos o rastreio por parte do Facebook quando a página foi carregada. Se desbloqueares este conteúdo, o Facebook fica a saber a tua atividade."},"shared.json":{"learnMore":"Saiba mais","readAbout":"Ler mais sobre esta proteção de privacidade"},"youtube.json":{"informationalModalMessageTitle":"Ativar todas as pré-visualizações do YouTube?","informationalModalMessageBody":"Mostrar visualizações permite à Google (que detém o YouTube) ver algumas das informações do teu dispositivo, mas ainda é mais privado do que reproduzir o vídeo.","informationalModalConfirmButtonText":"Ativar todas as pré-visualizações","informationalModalRejectButtonText":"Não, obrigado","buttonTextUnblockVideo":"Desbloquear Vídeo","infoTitleUnblockVideo":"O DuckDuckGo bloqueou este vídeo do YouTube para impedir que a Google te rastreie","infoTextUnblockVideo":"Bloqueámos o rastreio por parte da Google (que detém o YouTube) quando a página foi carregada. Se desbloqueares este vídeo, a Google fica a saber a tua atividade.","infoPreviewToggleText":"Pré-visualizações desativadas para privacidade adicional","infoPreviewToggleEnabledText":"Pré-visualizações ativadas","infoPreviewInfoText":"Saiba mais sobre a Proteção contra conteúdos de redes sociais incorporados do DuckDuckGo"}},"ro":{"facebook.json":{"informationalModalMessageTitle":"Conectarea cu Facebook îi permite să te urmărească","informationalModalMessageBody":"Odată ce te-ai conectat, DuckDuckGo nu poate împiedica conținutul Facebook să te urmărească pe acest site.","informationalModalConfirmButtonText":"Autentificare","informationalModalRejectButtonText":"Înapoi","loginButtonText":"Conectează-te cu Facebook","loginBodyText":"Facebook urmărește activitatea ta pe un site atunci când îl utilizezi pentru a te conecta.","buttonTextUnblockContent":"Deblochează conținutul","buttonTextUnblockComment":"Deblochează comentariul","buttonTextUnblockComments":"Deblochează comentariile","buttonTextUnblockPost":"Deblochează postarea","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockContent":"DuckDuckGo a blocat acest conținut pentru a împiedica Facebook să te urmărească","infoTitleUnblockComment":"DuckDuckGo a blocat acest comentariu pentru a împiedica Facebook să te urmărească","infoTitleUnblockComments":"DuckDuckGo a blocat aceste comentarii pentru a împiedica Facebook să te urmărească","infoTitleUnblockPost":"DuckDuckGo a blocat această postare pentru a împiedica Facebook să te urmărească","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip pentru a împiedica Facebook să te urmărească","infoTextUnblockContent":"Am împiedicat Facebook să te urmărească atunci când pagina a fost încărcată. Dacă deblochezi acest conținut, Facebook îți va cunoaște activitatea."},"shared.json":{"learnMore":"Află mai multe","readAbout":"Citește despre această protecție a confidențialității"},"youtube.json":{"informationalModalMessageTitle":"Activezi toate previzualizările YouTube?","informationalModalMessageBody":"Afișarea previzualizărilor va permite ca Google (care deține YouTube) să vadă unele dintre informațiile despre dispozitivul tău, dar este totuși mai privată decât redarea videoclipului.","informationalModalConfirmButtonText":"Activează toate previzualizările","informationalModalRejectButtonText":"Nu, mulțumesc","buttonTextUnblockVideo":"Deblochează videoclipul","infoTitleUnblockVideo":"DuckDuckGo a blocat acest videoclip de pe YouTube pentru a împiedica Google să te urmărească","infoTextUnblockVideo":"Am împiedicat Google (care deține YouTube) să te urmărească atunci când s-a încărcat pagina. Dacă deblochezi acest videoclip, Google va cunoaște activitatea ta.","infoPreviewToggleText":"Previzualizările au fost dezactivate pentru o confidențialitate suplimentară","infoPreviewToggleEnabledText":"Previzualizări activate","infoPreviewInfoText":"Află mai multe despre Protecția integrată DuckDuckGo pentru rețelele sociale"}},"ru":{"facebook.json":{"informationalModalMessageTitle":"Вход через Facebook позволяет этой социальной сети отслеживать вас","informationalModalMessageBody":"После входа DuckDuckGo не сможет блокировать отслеживание ваших действий с контентом на Facebook.","informationalModalConfirmButtonText":"Войти","informationalModalRejectButtonText":"Вернуться","loginButtonText":"Войти через Facebook","loginBodyText":"При использовании учетной записи Facebook для входа на сайты эта социальная сеть сможет отслеживать на них ваши действия.","buttonTextUnblockContent":"Разблокировать","buttonTextUnblockComment":"Разблокировать","buttonTextUnblockComments":"Разблокировать","buttonTextUnblockPost":"Разблокировать","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockContent":"DuckDuckGo заблокировал этот контент, чтобы вас не отслеживал Facebook","infoTitleUnblockComment":"DuckDuckGo заблокировал этот комментарий, чтобы вас не отслеживал Facebook","infoTitleUnblockComments":"DuckDuckGo заблокировал эти комментарии, чтобы вас не отслеживал Facebook","infoTitleUnblockPost":"DuckDuckGo заблокировал эту публикацию, чтобы вас не отслеживал Facebook","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео, чтобы вас не отслеживал Facebook","infoTextUnblockContent":"Во время загрузки страницы мы помешали Facebook отследить ваши действия. Если разблокировать этот контент, Facebook сможет фиксировать вашу активность."},"shared.json":{"learnMore":"Узнать больше","readAbout":"Подробнее об этом виде защиты конфиденциальности"},"youtube.json":{"informationalModalMessageTitle":"Включить предпросмотр видео из YouTube?","informationalModalMessageBody":"Активация предварительного просмотра позволит Google (владельцу YouTube) получить некоторые сведения о вашем устройстве, однако это более безопасный вариант, чем воспроизведение видео целиком.","informationalModalConfirmButtonText":"Включить предпросмотр","informationalModalRejectButtonText":"Нет, спасибо","buttonTextUnblockVideo":"Разблокировать","infoTitleUnblockVideo":"DuckDuckGo заблокировал это видео из YouTube, чтобы вас не отслеживал Google","infoTextUnblockVideo":"Во время загрузки страницы мы помешали Google (владельцу YouTube) отследить ваши действия. Если разблокировать видео, Google сможет фиксировать вашу активность.","infoPreviewToggleText":"Предварительный просмотр отключен для дополнительной защиты конфиденциальности","infoPreviewToggleEnabledText":"Предварительный просмотр включен","infoPreviewInfoText":"Подробнее о защите DuckDuckGo от внедренного контента соцсетей"}},"sk":{"facebook.json":{"informationalModalMessageTitle":"Prihlásenie cez Facebook mu umožní sledovať vás","informationalModalMessageBody":"DuckDuckGo po prihlásení nemôže na tejto lokalite zablokovať sledovanie vašej osoby obsahom Facebooku.","informationalModalConfirmButtonText":"Prihlásiť sa","informationalModalRejectButtonText":"Prejsť späť","loginButtonText":"Prihláste sa pomocou služby Facebook","loginBodyText":"Keď použijete prihlasovanie cez Facebook, Facebook bude na lokalite sledovať vašu aktivitu.","buttonTextUnblockContent":"Odblokovať obsah","buttonTextUnblockComment":"Odblokovať komentár","buttonTextUnblockComments":"Odblokovať komentáre","buttonTextUnblockPost":"Odblokovať príspevok","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockContent":"DuckDuckGo zablokoval tento obsah, aby vás Facebook nesledoval","infoTitleUnblockComment":"DuckDuckGo zablokoval tento komentár, aby zabránil sledovaniu zo strany Facebooku","infoTitleUnblockComments":"DuckDuckGo zablokoval tieto komentáre, aby vás Facebook nesledoval","infoTitleUnblockPost":"DuckDuckGo zablokoval tento príspevok, aby vás Facebook nesledoval","infoTitleUnblockVideo":"DuckDuckGo zablokoval toto video, aby vás Facebook nesledoval","infoTextUnblockContent":"Pri načítaní stránky sme zablokovali Facebook, aby vás nesledoval. Ak tento obsah odblokujete, Facebook bude vedieť o vašej aktivite."},"shared.json":{"learnMore":"Zistite viac","readAbout":"Prečítajte si o tejto ochrane súkromia"},"youtube.json":{"informationalModalMessageTitle":"Chcete povoliť všetky ukážky zo služby YouTube?","informationalModalMessageBody":"Zobrazenie ukážok umožní spoločnosti Google (ktorá vlastní YouTube) vidieť niektoré informácie o vašom zariadení, ale stále je to súkromnejšie ako prehrávanie videa.","informationalModalConfirmButtonText":"Povoliť všetky ukážky","informationalModalRejectButtonText":"Nie, ďakujem","buttonTextUnblockVideo":"Odblokovať video","infoTitleUnblockVideo":"DuckDuckGo toto video v službe YouTube zablokoval s cieľom predísť tomu, aby vás spoločnosť Google mohla sledovať","infoTextUnblockVideo":"Zablokovali sme pre spoločnosť Google (ktorá vlastní YouTube), aby vás nemohla sledovať, keď sa stránka načíta. Ak toto video odblokujete, Google bude poznať vašu aktivitu.","infoPreviewToggleText":"Ukážky sú zakázané s cieľom zvýšiť ochranu súkromia","infoPreviewToggleEnabledText":"Ukážky sú povolené","infoPreviewInfoText":"Získajte viac informácií o DuckDuckGo, vloženej ochrane sociálnych médií"}},"sl":{"facebook.json":{"informationalModalMessageTitle":"Če se prijavite s Facebookom, vam Facebook lahko sledi","informationalModalMessageBody":"Ko ste enkrat prijavljeni, DuckDuckGo ne more blokirati Facebookove vsebine, da bi vam sledila na tem spletnem mestu.","informationalModalConfirmButtonText":"Prijava","informationalModalRejectButtonText":"Pojdi nazaj","loginButtonText":"Prijavite se s Facebookom","loginBodyText":"Če se prijavite s Facebookom, bo nato spremljal vaša dejanja na spletnem mestu.","buttonTextUnblockContent":"Odblokiraj vsebino","buttonTextUnblockComment":"Odblokiraj komentar","buttonTextUnblockComments":"Odblokiraj komentarje","buttonTextUnblockPost":"Odblokiraj objavo","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockContent":"DuckDuckGo je blokiral to vsebino, da bi Facebooku preprečil sledenje","infoTitleUnblockComment":"DuckDuckGo je blokiral ta komentar, da bi Facebooku preprečil sledenje","infoTitleUnblockComments":"DuckDuckGo je blokiral te komentarje, da bi Facebooku preprečil sledenje","infoTitleUnblockPost":"DuckDuckGo je blokiral to objavo, da bi Facebooku preprečil sledenje","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek, da bi Facebooku preprečil sledenje","infoTextUnblockContent":"Ko se je stran naložila, smo Facebooku preprečili, da bi vam sledil. Če to vsebino odblokirate, bo Facebook izvedel za vaša dejanja."},"shared.json":{"learnMore":"Več","readAbout":"Preberite več o tej zaščiti zasebnosti"},"youtube.json":{"informationalModalMessageTitle":"Želite omogočiti vse YouTubove predoglede?","informationalModalMessageBody":"Prikaz predogledov omogoča Googlu (ki je lastnik YouTuba) vpogled v nekatere podatke o napravi, vendar je še vedno bolj zasebno kot predvajanje videoposnetka.","informationalModalConfirmButtonText":"Omogoči vse predoglede","informationalModalRejectButtonText":"Ne, hvala","buttonTextUnblockVideo":"Odblokiraj videoposnetek","infoTitleUnblockVideo":"DuckDuckGo je blokiral ta videoposnetek v YouTubu, da bi Googlu preprečil sledenje","infoTextUnblockVideo":"Googlu (ki je lastnik YouTuba) smo preprečili, da bi vam sledil, ko se je stran naložila. Če odblokirate ta videoposnetek, bo Google izvedel za vašo dejavnost.","infoPreviewToggleText":"Predogledi so zaradi dodatne zasebnosti onemogočeni","infoPreviewToggleEnabledText":"Predogledi so omogočeni","infoPreviewInfoText":"Več o vgrajeni zaščiti družbenih medijev DuckDuckGo"}},"sv":{"facebook.json":{"informationalModalMessageTitle":"Om du loggar in med Facebook kan de spåra dig","informationalModalMessageBody":"När du väl är inloggad kan DuckDuckGo inte hindra Facebooks innehåll från att spåra dig på den här webbplatsen.","informationalModalConfirmButtonText":"Logga in","informationalModalRejectButtonText":"Gå tillbaka","loginButtonText":"Logga in med Facebook","loginBodyText":"Facebook spårar din aktivitet på en webbplats om du använder det för att logga in.","buttonTextUnblockContent":"Avblockera innehåll","buttonTextUnblockComment":"Avblockera kommentar","buttonTextUnblockComments":"Avblockera kommentarer","buttonTextUnblockPost":"Avblockera inlägg","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockContent":"DuckDuckGo blockerade det här innehållet för att förhindra att Facebook spårar dig","infoTitleUnblockComment":"DuckDuckGo blockerade den här kommentaren för att förhindra att Facebook spårar dig","infoTitleUnblockComments":"DuckDuckGo blockerade de här kommentarerna för att förhindra att Facebook spårar dig","infoTitleUnblockPost":"DuckDuckGo blockerade det här inlägget för att förhindra att Facebook spårar dig","infoTitleUnblockVideo":"DuckDuckGo blockerade den här videon för att förhindra att Facebook spårar dig","infoTextUnblockContent":"Vi hindrade Facebook från att spåra dig när sidan lästes in. Om du avblockerar det här innehållet kommer Facebook att känna till din aktivitet."},"shared.json":{"learnMore":"Läs mer","readAbout":"Läs mer om detta integritetsskydd"},"youtube.json":{"informationalModalMessageTitle":"Aktivera alla förhandsvisningar för YouTube?","informationalModalMessageBody":"Genom att visa förhandsvisningar kan Google (som äger YouTube) se en del av enhetens information, men det är ändå mer privat än att spela upp videon.","informationalModalConfirmButtonText":"Aktivera alla förhandsvisningar","informationalModalRejectButtonText":"Nej tack","buttonTextUnblockVideo":"Avblockera video","infoTitleUnblockVideo":"DuckDuckGo blockerade den här YouTube-videon för att förhindra att Google spårar dig","infoTextUnblockVideo":"Vi hindrade Google (som äger YouTube) från att spåra dig när sidan laddades. Om du tar bort blockeringen av videon kommer Google att känna till din aktivitet.","infoPreviewToggleText":"Förhandsvisningar har inaktiverats för ytterligare integritet","infoPreviewToggleEnabledText":"Förhandsvisningar aktiverade","infoPreviewInfoText":"Läs mer om DuckDuckGos skydd mot inbäddade sociala medier"}},"tr":{"facebook.json":{"informationalModalMessageTitle":"Facebook ile giriş yapmak, sizi takip etmelerini sağlar","informationalModalMessageBody":"Giriş yaptıktan sonra, DuckDuckGo Facebook içeriğinin sizi bu sitede izlemesini engelleyemez.","informationalModalConfirmButtonText":"Oturum Aç","informationalModalRejectButtonText":"Geri dön","loginButtonText":"Facebook ile giriş yapın","loginBodyText":"Facebook, giriş yapmak için kullandığınızda bir sitedeki etkinliğinizi izler.","buttonTextUnblockContent":"İçeriğin Engelini Kaldır","buttonTextUnblockComment":"Yorumun Engelini Kaldır","buttonTextUnblockComments":"Yorumların Engelini Kaldır","buttonTextUnblockPost":"Gönderinin Engelini Kaldır","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockContent":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu içeriği engelledi","infoTitleUnblockComment":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumu engelledi","infoTitleUnblockComments":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu yorumları engelledi","infoTitleUnblockPost":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu gönderiyi engelledi","infoTitleUnblockVideo":"DuckDuckGo, Facebook'un sizi izlemesini önlemek için bu videoyu engelledi","infoTextUnblockContent":"Sayfa yüklendiğinde Facebook'un sizi izlemesini engelledik. Bu içeriğin engelini kaldırırsanız Facebook etkinliğinizi öğrenecektir."},"shared.json":{"learnMore":"Daha Fazla Bilgi","readAbout":"Bu gizlilik koruması hakkında bilgi edinin"},"youtube.json":{"informationalModalMessageTitle":"Tüm YouTube önizlemeleri etkinleştirilsin mi?","informationalModalMessageBody":"Önizlemelerin gösterilmesi Google'ın (YouTube'un sahibi) cihazınızın bazı bilgilerini görmesine izin verir, ancak yine de videoyu oynatmaktan daha özeldir.","informationalModalConfirmButtonText":"Tüm Önizlemeleri Etkinleştir","informationalModalRejectButtonText":"Hayır Teşekkürler","buttonTextUnblockVideo":"Videonun Engelini Kaldır","infoTitleUnblockVideo":"DuckDuckGo, Google'ın sizi izlemesini önlemek için bu YouTube videosunu engelledi","infoTextUnblockVideo":"Sayfa yüklendiğinde Google'ın (YouTube'un sahibi) sizi izlemesini engelledik. Bu videonun engelini kaldırırsanız, Google etkinliğinizi öğrenecektir.","infoPreviewToggleText":"Ek gizlilik için önizlemeler devre dışı bırakıldı","infoPreviewToggleEnabledText":"Önizlemeler etkinleştirildi","infoPreviewInfoText":"DuckDuckGo Yerleşik Sosyal Medya Koruması hakkında daha fazla bilgi edinin"}}}`; /********************************************************* * Style Definitions *********************************************************/ - const styles = { - fontStyle: ` + /** + * Get CSS style defintions for CTL, using the provided AssetConfig for any non-embedded assets + * (e.g. fonts.) + * @param {import('../../content-feature.js').AssetConfig} [assets] + */ + function getStyles (assets) { + let fontStyle = ''; + let regularFontFamily = "system, -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'"; + let boldFontFamily = regularFontFamily; + if (assets?.regularFontUrl && assets?.boldFontUrl) { + fontStyle = ` @font-face{ font-family: DuckDuckGoPrivacyEssentials; - src: url(${ddgFont}); + src: url(${assets.regularFontUrl}); } @font-face{ font-family: DuckDuckGoPrivacyEssentialsBold; font-weight: bold; - src: url(${ddgFontBold}); + src: url(${assets.boldFontUrl}); } - `, - darkMode: { - background: ` + `; + regularFontFamily = 'DuckDuckGoPrivacyEssentials'; + boldFontFamily = 'DuckDuckGoPrivacyEssentialsBold'; + } + return { + fontStyle, + darkMode: { + background: ` background: #111111; `, - textFont: ` + textFont: ` color: rgba(255, 255, 255, 0.9); `, - buttonFont: ` + buttonFont: ` color: #111111; `, - linkFont: ` + linkFont: ` color: #7295F6; `, - buttonBackground: ` + buttonBackground: ` background: #5784FF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #557FF3; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #3969EF; `, - toggleButtonText: ` + toggleButtonText: ` color: #EEEEEE; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #5784FF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - lightMode: { - background: ` + } + }, + lightMode: { + background: ` background: #FFFFFF; `, - textFont: ` + textFont: ` color: #222222; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; `, - linkFont: ` + linkFont: ` color: #3969EF; `, - buttonBackground: ` + buttonBackground: ` background: #3969EF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #2B55CA; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #1E42A4; `, - toggleButtonText: ` + toggleButtonText: ` color: #666666; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #3969EF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - loginMode: { - buttonBackground: ` + } + }, + loginMode: { + buttonBackground: ` background: #666666; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; ` - }, - cancelMode: { - buttonBackground: ` + }, + cancelMode: { + buttonBackground: ` background: rgba(34, 34, 34, 0.1); `, - buttonFont: ` + buttonFont: ` color: #222222; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: rgba(0, 0, 0, 0.12); `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: rgba(0, 0, 0, 0.18); ` - }, - button: ` + }, + button: ` border-radius: 8px; padding: 11px 22px; @@ -4954,7 +5232,7 @@ border-color: #3969EF; border: none; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; font-size: 14px; position: relative; @@ -4962,7 +5240,7 @@ box-shadow: none; z-index: 2147483646; `, - circle: ` + circle: ` border-radius: 50%; width: 18px; height: 18px; @@ -4972,14 +5250,14 @@ top: -8px; right: -8px; `, - loginIcon: ` + loginIcon: ` position: absolute; top: -13px; right: -10px; height: 28px; width: 28px; `, - rectangle: ` + rectangle: ` width: 12px; height: 3px; background: #666666; @@ -4987,7 +5265,7 @@ top: 42.5%; margin: auto; `, - textBubble: ` + textBubble: ` background: #FFFFFF; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 16px; @@ -4998,9 +5276,9 @@ position: absolute; line-height: normal; `, - textBubbleWidth: 360, // Should match the width rule in textBubble - textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble - textArrow: ` + textBubbleWidth: 360, // Should match the width rule in textBubble + textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble + textArrow: ` display: inline-block; background: #FFFFFF; border: solid rgba(0, 0, 0, 0.1); @@ -5011,23 +5289,23 @@ position: relative; top: -9px; `, - arrowDefaultLocationPercent: 50, - hoverTextTitle: ` + arrowDefaultLocationPercent: 50, + hoverTextTitle: ` padding: 0px 12px 12px; margin-top: -5px; `, - hoverTextBody: ` - font-family: DuckDuckGoPrivacyEssentials; + hoverTextBody: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: auto; padding: 17px; text-align: left; `, - hoverContainer: ` + hoverContainer: ` padding-bottom: 10px; `, - buttonTextContainer: ` + buttonTextContainer: ` display: flex; flex-direction: row; align-items: center; @@ -5035,10 +5313,10 @@ padding: 0; margin: 0; `, - headerRow: ` + headerRow: ` `, - block: ` + block: ` box-sizing: border-box; border: 1px solid rgba(0,0,0,0.1); border-radius: 12px; @@ -5048,27 +5326,27 @@ display: flex; flex-direction: column; - font-family: DuckDuckGoPrivacyEssentials; + font-family: ${regularFontFamily}; line-height: 1; `, - youTubeDialogBlock: ` + youTubeDialogBlock: ` height: calc(100% - 30px); max-width: initial; min-height: initial; `, - imgRow: ` + imgRow: ` display: flex; flex-direction: column; margin: 20px 0px; `, - content: ` + content: ` display: flex; flex-direction: column; padding: 16px 0; flex: 1 1 1px; `, - feedbackLink: ` - font-family: DuckDuckGoPrivacyEssentials; + feedbackLink: ` + font-family: ${regularFontFamily}; font-style: normal; font-weight: 400; font-size: 12px; @@ -5076,13 +5354,13 @@ color: #ABABAB; text-decoration: none; `, - feedbackRow: ` + feedbackRow: ` height: 30px; display: flex; justify-content: flex-end; align-items: center; `, - titleBox: ` + titleBox: ` display: flex; padding: 12px; max-height: 44px; @@ -5091,8 +5369,8 @@ margin: 0; margin-bottom: 4px; `, - title: ` - font-family: DuckDuckGoPrivacyEssentials; + title: ` + font-family: ${regularFontFamily}; line-height: 1.4; font-size: 14px; margin: auto 10px; @@ -5104,7 +5382,7 @@ border: none; padding: 0; `, - buttonRow: ` + buttonRow: ` display: flex; height: 100% flex-direction: row; @@ -5112,8 +5390,8 @@ height: 100%; align-items: flex-start; `, - modalContentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + modalContentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; line-height: 21px; @@ -5122,8 +5400,8 @@ border: none; padding: 0px 32px; `, - modalContentText: ` - font-family: DuckDuckGoPrivacyEssentials; + modalContentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: 0px auto 14px; @@ -5131,7 +5409,7 @@ border: none; padding: 0; `, - modalButtonRow: ` + modalButtonRow: ` border: none; padding: 0; margin: auto; @@ -5140,17 +5418,17 @@ flex-direction: column; align-items: center; `, - modalButton: ` + modalButton: ` width: 100%; display: flex; justify-content: center; align-items: center; `, - modalIcon: ` + modalIcon: ` display: block; `, - contentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + contentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; margin: 20px auto 10px; @@ -5158,25 +5436,25 @@ text-align: center; margin-top: auto; `, - contentText: ` - font-family: DuckDuckGoPrivacyEssentials; + contentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; padding: 0px 40px; text-align: center; margin: 0 auto auto; `, - icon: ` + icon: ` height: 80px; width: 80px; margin: auto; `, - closeIcon: ` + closeIcon: ` height: 12px; width: 12px; margin: auto; `, - closeButton: ` + closeButton: ` display: flex; justify-content: center; align-items: center; @@ -5186,7 +5464,7 @@ background: transparent; cursor: pointer; `, - logo: ` + logo: ` flex-basis: 0%; min-width: 20px; height: 21px; @@ -5194,17 +5472,17 @@ padding: 0; margin: 0; `, - logoImg: ` + logoImg: ` height: 21px; width: 21px; `, - loadingImg: ` + loadingImg: ` display: block; margin: 0px 8px 0px 0px; height: 14px; width: 14px; `, - modal: ` + modal: ` width: 340px; padding: 0; margin: auto; @@ -5218,14 +5496,14 @@ border-radius: 12px; border: none; `, - modalContent: ` + modalContent: ` padding: 24px; display: flex; flex-direction: column; border: none; margin: 0; `, - overlay: ` + overlay: ` height: 100%; width: 100%; background-color: #666666; @@ -5238,7 +5516,7 @@ padding: 0; margin: 0; `, - modalContainer: ` + modalContainer: ` height: 100vh; width: 100vw; box-sizing: border-box; @@ -5249,16 +5527,16 @@ margin: 0; padding: 0; `, - headerLinkContainer: ` + headerLinkContainer: ` flex-basis: 100%; display: grid; justify-content: flex-end; `, - headerLink: ` + headerLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; text-decoration: none; cursor: pointer; min-width: 100px; @@ -5266,15 +5544,15 @@ float: right; display: none; `, - generalLink: ` + generalLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; cursor: pointer; text-decoration: none; `, - wrapperDiv: ` + wrapperDiv: ` display: inline-block; border: 0; padding: 0; @@ -5282,12 +5560,12 @@ max-width: 600px; min-height: 300px; `, - toggleButtonWrapper: ` + toggleButtonWrapper: ` display: flex; align-items: center; cursor: pointer; `, - toggleButton: ` + toggleButton: ` cursor: pointer; position: relative; width: 30px; @@ -5299,19 +5577,19 @@ background-color: transparent; text-align: left; `, - toggleButtonBg: ` + toggleButtonBg: ` right: 0; width: 30px; height: 16px; overflow: visible; border-radius: 10px; `, - toggleButtonText: ` + toggleButtonText: ` display: inline-block; margin: 0 0 0 7px; padding: 0; `, - toggleButtonKnob: ` + toggleButtonKnob: ` position: absolute; display: inline-block; width: 14px; @@ -5322,15 +5600,15 @@ top: calc(50% - 14px/2 - 1px); box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.05), 0px 1px 1px rgba(0, 0, 0, 0.1); `, - toggleButtonKnobState: { - active: ` + toggleButtonKnobState: { + active: ` right: 1px; `, - inactive: ` + inactive: ` left: 1px; ` - }, - placeholderWrapperDiv: ` + }, + placeholderWrapperDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5340,7 +5618,7 @@ min-height: 300px; margin: auto; `, - youTubeWrapperDiv: ` + youTubeWrapperDiv: ` position: relative; overflow: hidden; max-width: initial; @@ -5348,7 +5626,7 @@ min-height: 300px; height: 100%; `, - youTubeDialogDiv: ` + youTubeDialogDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -5356,14 +5634,14 @@ min-height: initial; height: calc(100% - 30px); `, - youTubeDialogBottomRow: ` + youTubeDialogBottomRow: ` display: flex; flex-direction: column; align-items: center; justify-content: flex-end; margin-top: auto; `, - youTubePlaceholder: ` + youTubePlaceholder: ` display: flex; flex-direction: column; justify-content: flex-start; @@ -5372,7 +5650,7 @@ height: 100%; background: rgba(45, 45, 45, 0.8); `, - youTubePreviewWrapperImg: ` + youTubePreviewWrapperImg: ` position: absolute; display: flex; justify-content: center; @@ -5380,20 +5658,20 @@ width: 100%; height: 100%; `, - youTubePreviewImg: ` + youTubePreviewImg: ` min-width: 100%; min-height: 100%; height: auto; `, - youTubeTopSection: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + youTubeTopSection: ` + font-family: ${boldFontFamily}; flex: 1; display: flex; justify-content: space-between; position: relative; padding: 18px 12px 0; `, - youTubeTitle: ` + youTubeTitle: ` font-size: 14px; font-weight: bold; line-height: 14px; @@ -5405,13 +5683,13 @@ text-overflow: ellipsis; box-sizing: border-box; `, - youTubePlayButtonRow: ` + youTubePlayButtonRow: ` flex: 2; display: flex; align-items: center; justify-content: center; `, - youTubePlayButton: ` + youTubePlayButton: ` display: flex; justify-content: center; align-items: center; @@ -5420,7 +5698,7 @@ padding: 0px 24px; border-radius: 8px; `, - youTubePreviewToggleRow: ` + youTubePreviewToggleRow: ` flex: 1; display: flex; flex-direction: column; @@ -5428,15 +5706,19 @@ align-items: center; padding: 0 12px 18px; `, - youTubePreviewToggleText: ` + youTubePreviewToggleText: ` color: #EEEEEE; font-weight: 400; `, - youTubePreviewInfoText: ` + youTubePreviewInfoText: ` color: #ABABAB; ` - }; + } + } + /** + * @param {string} locale UI locale + */ function getConfig (locale) { const locales = JSON.parse(localesJSON); const fbStrings = locales[locale]['facebook.json']; @@ -5873,6 +6155,7 @@ // @see {getConfig} let config = null; let sharedStrings = null; + let styles = null; // TODO: Remove these redundant data structures and refactor the related code. // There should be no need to have the entity configuration stored in two @@ -6335,6 +6618,16 @@ ]; elementToReplace.style.setProperty('display', 'none', 'important'); + // When iframes are blocked by the declarativeNetRequest API, they are + // collapsed (hidden) automatically. Unfortunately however, there's a bug + // that stops them from being uncollapsed (shown again) if they are removed + // from the DOM after they are collapsed. As a workaround, have the iframe + // load a benign data URI, so that it's uncollapsed, before removing it from + // the DOM. See https://crbug.com/1428971 + const originalSrc = elementToReplace.src; + elementToReplace.src = + 'data:text/plain;charset=utf-8;base64,' + btoa('https://crbug.com/1428971'); + // Add the placeholder element to the page. elementToReplace.parentElement.insertBefore( placeholderElement, elementToReplace @@ -6354,6 +6647,7 @@ // placeholder) can finally be removed from the DOM. elementToReplace.remove(); elementToReplace.style.setProperty('display', ...originalDisplay); + elementToReplace.src = originalSrc; }); } @@ -6744,10 +7038,10 @@ * Creates an anchor element with no destination. It is expected that a click * handler is added to the element later. * @param {string} linkText - * @param {displayMode} [mode='lightMode'] + * @param {displayMode} mode * @returns {HTMLAnchorElement} */ - function makeTextButton (linkText, mode) { + function makeTextButton (linkText, mode = 'lightMode') { const linkElement = document.createElement('a'); linkElement.style.cssText = styles.headerLink + styles[mode].linkFont; linkElement.textContent = linkText; @@ -7471,6 +7765,8 @@ const localizedConfig = getConfig(locale); config = localizedConfig.config; sharedStrings = localizedConfig.sharedStrings; + // update styles if asset config was sent + styles = getStyles(this.assetConfig); for (const entity of Object.keys(config)) { // Strip config entities that are first-party, or aren't enabled in the @@ -7539,6 +7835,16 @@ } await afterPageLoad; + // On some websites, the "ddg-ctp-ready" event is occasionally + // dispatched too early, before the listener is ready to receive it. + // To counter that, catch "ddg-ctp-surrogate-load" events dispatched + // _after_ page, so the "ddg-ctp-ready" event can be dispatched again. + window.addEventListener( + 'ddg-ctp-surrogate-load', () => { + originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready')); + } + ); + // Then wait for any in-progress element replacements, before letting // the surrogate scripts know to start. window.setTimeout(() => { @@ -9528,7 +9834,7 @@ title: 'Tired of targeted YouTube ads and recommendations?' }, videoOverlaySubtitle: { - title: 'Duck Player provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' + title: 'provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' }, videoButtonOpen: { title: 'Watch in Duck Player' @@ -9559,6 +9865,75 @@ } }; + /** + * The following code is originally from https://github.com/mozilla-extensions/secure-proxy/blob/db4d1b0e2bfe0abae416bf04241916f9e4768fd2/src/commons/template.js + */ + class Template { + constructor (strings, values) { + this.values = values; + this.strings = strings; + } + + /** + * Escapes any occurrences of &, ", <, > or / with XML entities. + * + * @param {string} str + * The string to escape. + * @return {string} The escaped string. + */ + escapeXML (str) { + const replacements = { + '&': '&', + '"': '"', + "'": ''', + '<': '<', + '>': '>', + '/': '/' + }; + return String(str).replace(/[&"'<>/]/g, m => replacements[m]) + } + + potentiallyEscape (value) { + if (typeof value === 'object') { + if (value instanceof Array) { + return value.map(val => this.potentiallyEscape(val)).join('') + } + + // If we are an escaped template let join call toString on it + if (value instanceof Template) { + return value + } + + throw new Error('Unknown object to escape') + } + return this.escapeXML(value) + } + + toString () { + const result = []; + + for (const [i, string] of this.strings.entries()) { + result.push(string); + if (i < this.values.length) { + result.push(this.potentiallyEscape(this.values[i])); + } + } + return result.join('') + } + } + + function html (strings, ...values) { + return new Template(strings, values) + } + + /** + * @param {string} string + * @return {Template} + */ + function trustedUnsafe (string) { + return html([string]) + } + const IconOverlay = { /** * Special class used for the overlay hover. For hovering, we use a @@ -9597,20 +9972,20 @@ overlayElement.setAttribute('class', 'ddg-overlay' + (extraClass ? ' ' + extraClass : '')); overlayElement.setAttribute('data-size', size); - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax); + overlayElement.innerHTML = html`

${i18n.t('playText')}
-
`; + `.toString(); overlayElement.querySelector('a.ddg-play-privately')?.setAttribute('href', href); - overlayElement.querySelector('a.ddg-play-privately')?.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); @@ -9941,12 +10316,15 @@ createOverlay () { const overlayElement = document.createElement('div'); overlayElement.classList.add('ddg-video-player-overlay'); - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax); + overlayElement.innerHTML = html`
-
${dax}
+
${svgIcon}
${i18n.t('videoOverlayTitle')}
-
${i18n.t('videoOverlaySubtitle')}
+
+ ${i18n.t('playText')} ${i18n.t('videoOverlaySubtitle')} +
${i18n.t('videoButtonOpen')} @@ -9957,7 +10335,7 @@
- `; + `.toString(); /** * Set the link * @type {string} @@ -10725,7 +11103,7 @@ if (this.platform.name === 'windows') { const context = new MessagingContext({ context: 'contentScopeScripts', - env: this._args.debug ? 'development' : 'production', + env: this.isDebug ? 'development' : 'production', featureName: this.name }); const config = new WindowsMessagingConfig({ @@ -10812,12 +11190,14 @@ /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** @@ -10895,6 +11275,7 @@ function generateConfig (data, userList) { const topLevelUrl = getTopLevelURL(); + const trackerLookup = {"org":{"cdn77":{"rsc":{"1666210260":1}},"adsrvr":1,"ampproject":1,"browser-update":1,"flowplayer":1,"privacy-center":1,"webvisor":1,"framasoft":1,"do-not-tracker":1,"trackersimulator":1},"io":{"1dmp":1,"1rx":1,"4dex":1,"adnami":1,"aidata":1,"arcspire":1,"bidr":1,"branch":1,"center":1,"concert":1,"connectad":1,"cordial":1,"dcmn":1,"extole":1,"getblue":1,"hbrd":1,"imbox":1,"instana":1,"karte":1,"lytics":1,"marchex":1,"mediago":1,"mrf":1,"myfidevs":1,"narrative":1,"ntv":1,"optad360":1,"oracleinfinity":1,"oribi":1,"p-n":1,"personalizer":1,"pghub":1,"piano":1,"powr":1,"pzz":1,"searchspring":1,"segment":1,"siteimproveanalytics":1,"sjv":1,"sspinc":1,"t13":1,"webgains":1,"wovn":1,"yellowblue":1,"zprk":1,"reviews":1,"appconsent":1,"leadsmonitor":1},"com":{"2020mustang":1,"33across":1,"360yield":1,"3lift":1,"4dsply":1,"4jnzhl0d0":1,"4strokemedia":1,"5d2d04464c":1,"a-mx":1,"a2z":1,"aamsitecertifier":1,"absorbingband":1,"abstractedauthority":1,"abtasty":1,"acexedge":1,"acidpigs":1,"acsbapp":1,"acuityplatform":1,"ad-score":1,"ad-stir":1,"adalyser":1,"adapf":1,"adara":1,"adblade":1,"addthis":1,"addtoany":1,"adelixir":1,"adentifi":1,"adextrem":1,"adgrx":1,"adhese":1,"adition":1,"adkernel":1,"adlightning":1,"adlooxtracking":1,"admanmedia":1,"admedo":1,"adnium":1,"adnxs":1,"adobedtm":1,"adotmob":1,"adpone":1,"adpushup":1,"adroll":1,"adrta":1,"ads-twitter":1,"ads3-adnow":1,"adsafeprotected":1,"adstanding":1,"adswizz":1,"adsymptotic":1,"adtdp":1,"adtechus":1,"adtelligent":1,"adthrive":1,"adtlgc":1,"adtng":1,"adultfriendfinder":1,"advangelists":1,"adventive":1,"advertising":1,"aegpresents":1,"affinity":1,"affirm":1,"agilone":1,"agkn":1,"aimbase":1,"albacross":1,"alcmpn":1,"alexametrics":1,"alicdn":1,"alikeaddition":1,"aliveachiever":1,"aliyuncs":1,"alluringbucket":1,"aloofvest":1,"amazon-adsystem":1,"amazon":1,"amplitude":1,"analytics-egain":1,"aniview":1,"anymind360":1,"amazonaws":{"ap-southeast-2":1,"elb":{"eu-west-2":{"collect-prd-alb-539115803":1},"us-east-1":{"data-allstate-com-715826933":1,"prod-lb-8-1772099769":1,"proxy-mycigna-prod-678433465":1,"www-u45-pnc-com-902993410":1,"www-u46-pnc-com-13593657":1},"eu-west-1":{"devservicesalb-471015105":1,"petfre-content-1201188928":1},"us-east-2":{"elbpiwik-public-1781721271":1},"eu-central-1":{"prod-lb-6-388533732":1,"prod-lb-7-718125029":1,"prod-pub-alb-654989386":1}},"us-east-2":{"s3":{"hb-gretsch-talk":1,"hb-jetpunk":1,"hb-obv2":1}},"eu-central-1":{"s3":{"headless-ssr-prod-bucket":1}}},"app-us1":1,"appboycdn":1,"appdynamics":1,"aralego":1,"arkoselabs":1,"aswpsdkus":1,"atemda":1,"att":1,"attentivemobile":1,"attractionbanana":1,"audioeye":1,"audrte":1,"automaticside":1,"avanser":1,"avmws":1,"aweber":1,"aweprt":1,"azure":1,"b0e8":1,"bagbeam":1,"bandborder":1,"batch":1,"bawdybalance":1,"bc0a":1,"bdstatic":1,"bedsberry":1,"beginnerpancake":1,"benchmarkemail":1,"betweendigital":1,"bfmio":1,"bidderstack":1,"bidtheatre":1,"bimbolive":1,"bing":1,"bizographics":1,"bizrate":1,"bkrtx":1,"blismedia":1,"blogherads":1,"bluecava":1,"bluekai":1,"boatwizard":1,"boilingcredit":1,"boldchat":1,"booking":1,"borderfree":1,"bounceexchange":1,"brainlyads":1,"brand-display":1,"brandmetrics":1,"brealtime":1,"breinify":1,"brightedge":1,"brightfunnel":1,"brightspotcdn":1,"btloader":1,"btstatic":1,"bttrack":1,"btttag":1,"butterbulb":1,"buzzoola":1,"byside":1,"cabnnr":1,"calculatorstatement":1,"callrail":1,"calltracks":1,"capablecup":1,"captcha-delivery":1,"carpentercomparison":1,"cartstack":1,"carvecakes":1,"casalemedia":1,"cdn-btsg":1,"cdnwidget":1,"channeladvisor":1,"chartbeat":1,"chatango":1,"chaturbate":1,"cheqzone":1,"cherriescare":1,"chickensstation":1,"childlikecrowd":1,"childlikeform":1,"cintnetworks":1,"circlelevel":1,"civiccomputing":1,"ck-ie":1,"clcktrax":1,"clearbit":1,"clearbitjs":1,"clickagy":1,"clickcease":1,"clickcertain":1,"clicktripz":1,"clientgear":1,"clksite":1,"cloudflare":1,"cloudflareinsights":1,"cloudflarestream":1,"cloudmaestro":1,"cobaltgroup":1,"cobrowser":1,"cognitivlabs":1,"colossusssp":1,"comm100":1,"googleapis":{"commondatastorage":1,"storage":1},"company-target":1,"condenastdigital":1,"confusedcart":1,"connatix":1,"consentframework":1,"contextweb":1,"conversionruler":1,"convertkit":1,"convertlanguage":1,"cookieinformation":1,"cookiepro":1,"coveo":1,"cpmstar":1,"cquotient":1,"crabbychin":1,"crazyegg":1,"creative-serving":1,"creativecdn":1,"criteo":1,"crowdedmass":1,"crowdriff":1,"crownpeak":1,"crsspxl":1,"ctnsnet":1,"cubchannel":1,"cudasvc":1,"cuddlethehyena":1,"cumbersomecarpenter":1,"curalate":1,"curvedhoney":1,"cutechin":1,"cxense":1,"dailymotion":1,"damdoor":1,"dampdock":1,"dapperfloor":1,"datadoghq-browser-agent":1,"decisivebase":1,"deepintent":1,"defybrick":1,"delivra":1,"demandbase":1,"detectdiscovery":1,"devilishdinner":1,"dimelochat":1,"discreetfield":1,"disqus":1,"dmpxs":1,"dockdigestion":1,"dollardelta":1,"dotomi":1,"doubleverify":1,"drainpaste":1,"dramaticdirection":1,"driftt":1,"dtscdn":1,"dtscout":1,"dwin1":1,"dynamics":1,"dynamicyield":1,"dynatrace":1,"dyntrk":1,"ebaystatic":1,"ecal":1,"eccmp":1,"elasticchange":1,"elfsight":1,"elitrack":1,"eloqua":1,"en25":1,"encouragingthread":1,"ensighten":1,"enviousshape":1,"eqads":1,"ero-advertising":1,"esputnik":1,"evergage":1,"evgnet":1,"exdynsrv":1,"exelator":1,"exoclick":1,"exosrv":1,"expansioneggnog":1,"expertrec":1,"exponea":1,"exponential":1,"extole":1,"ezodn":1,"ezoic":1,"ezoiccdn":1,"facebook":1,"fadewaves":1,"fallaciousfifth":1,"farmergoldfish":1,"fastly-insights":1,"fearlessfaucet":1,"fiftyt":1,"financefear":1,"fitanalytics":1,"five9":1,"fksnk":1,"flashtalking":1,"flipp":1,"floweryflavor":1,"flutteringfireman":1,"flux-cdn":1,"fomo":1,"foresee":1,"forter":1,"fortunatemark":1,"fouanalytics":1,"fox":1,"fqtag":1,"frailfruit":1,"freezingbuilding":1,"fronttoad":1,"fullstory":1,"functionalfeather":1,"fuzzybasketball":1,"gammamaximum":1,"gbqofs":1,"geetest":1,"geistm":1,"geniusmonkey":1,"geoip-js":1,"getbread":1,"getcandid":1,"getclicky":1,"getdrip":1,"getelevar":1,"getpublica":1,"getrockerbox":1,"getshogun":1,"getsitecontrol":1,"glassdoor":1,"gloriousbeef":1,"godpvqnszo":1,"gondolagnome":1,"google-analytics":1,"google":1,"googleadservices":1,"googlehosted":1,"googleoptimize":1,"googlesyndication":1,"googletagmanager":1,"googletagservices":1,"govx":1,"greylabeldelivery":1,"groovehq":1,"gstatic":1,"guarantee-cdn":1,"guiltlessbasketball":1,"gumgum":1,"haltingbadge":1,"hammerhearing":1,"handsomelyhealth":1,"hawksearch":1,"heapanalytics":1,"hellobar":1,"hiconversion":1,"highwebmedia":1,"histats":1,"hlserve":1,"hocgeese":1,"hollowafterthought":1,"honorableland":1,"hotjar":1,"hp":1,"hs-banner":1,"htlbid":1,"htplayground":1,"hubspot":1,"iadvize":1,"ib-ibi":1,"id5-sync":1,"iesnare":1,"igodigital":1,"iheart":1,"iljmp":1,"illiweb":1,"impactcdn":1,"impactradius-event":1,"impactradius-go":1,"impossibleexpansion":1,"impressionmonster":1,"improvedcontactform":1,"improvedigital":1,"imrworldwide":1,"indexww":1,"infolinks":1,"infusionsoft":1,"inmobi":1,"inmoment":1,"inq":1,"inside-graph":1,"instagram":1,"intentiq":1,"intergient":1,"investingchannel":1,"invocacdn":1,"iplsc":1,"ipredictive":1,"iteratehq":1,"ivitrack":1,"j93557g":1,"jaavnacsdw":1,"jimstatic":1,"journity":1,"js7k":1,"juicyads":1,"justanswer":1,"justpremium":1,"kakao":1,"kampyle":1,"kargo":1,"kissmetrics":1,"klarnaservices":1,"klaviyo":1,"knottyswing":1,"kount":1,"krushmedia":1,"ktkjmp":1,"kxcdn":1,"ladesk":1,"ladsp":1,"laughablelizards":1,"leadsrx":1,"lendingtree":1,"levexis":1,"liadm":1,"licdn":1,"lightboxcdn":1,"lijit":1,"linkedin":1,"linksynergy":1,"list-manage":1,"listrakbi":1,"livechatinc":1,"livejasmin":1,"localytics":1,"loggly":1,"loop11":1,"lovelydrum":1,"luckyorange":1,"lunchroomlock":1,"maddeningpowder":1,"mailchimp":1,"mailchimpapp":1,"mailerlite":1,"maillist-manage":1,"marinsm":1,"marketiq":1,"marketo":1,"marriedbelief":1,"matheranalytics":1,"mathtag":1,"maxmind":1,"mczbf":1,"measlymiddle":1,"medallia":1,"media6degrees":1,"mediacategory":1,"mediavine":1,"mediawallahscript":1,"medtargetsystem":1,"megpxs":1,"metricode":1,"metricswpsh":1,"mfadsrvr":1,"mgid":1,"micpn":1,"microadinc":1,"minutemedia-prebid":1,"minutemediaservices":1,"mixpo":1,"mktoresp":1,"mktoweb":1,"ml314":1,"moatads":1,"mobtrakk":1,"monsido":1,"mookie1":1,"mountain":1,"mouseflow":1,"mpeasylink":1,"mql5":1,"mrtnsvr":1,"murdoog":1,"mxpnl":1,"mybestpro":1,"myfinance":1,"myregistry":1,"nappyattack":1,"navistechnologies":1,"neodatagroup":1,"nervoussummer":1,"newrelic":1,"newscgp":1,"nextdoor":1,"ninthdecimal":1,"nitrocdn":1,"noibu":1,"nondescriptnote":1,"nosto":1,"npttech":1,"nuance":1,"nxsttv":1,"omappapi":1,"omnisnippet1":1,"omnisrc":1,"omnitagjs":1,"oneall":1,"onesignal":1,"onetag-sys":1,"oo-syringe":1,"ooyala":1,"opecloud":1,"opentext":1,"opera":1,"opmnstr":1,"optimicdn":1,"optinmonster":1,"optmnstr":1,"optmstr":1,"optnmnstr":1,"optnmstr":1,"oraclecloud":1,"osano":1,"otm-r":1,"outbrain":1,"overconfidentfood":1,"ownlocal":1,"pamelarandom":1,"panickypancake":1,"panoramicplane":1,"parastorage":1,"pardot":1,"parsely":1,"partplanes":1,"patreon":1,"paypal":1,"pbstck":1,"pcmag":1,"peerius":1,"perfdrive":1,"perfectmarket":1,"permutive":1,"picreel":1,"pinimg":1,"pippio":1,"piwikpro":1,"pixlee":1,"pleasantpump":1,"plotrabbit":1,"pluckypocket":1,"pocketfaucet":1,"possibleboats":1,"postaffiliatepro":1,"postrelease":1,"potatoinvention":1,"prepareplanes":1,"pricespider":1,"pricklydebt":1,"profusesupport":1,"proofpoint":1,"protoawe":1,"providesupport":1,"pswec":1,"psyma":1,"ptengine":1,"publir":1,"pubmatic":1,"pubmine":1,"pubnation":1,"puffypurpose":1,"qualaroo":1,"qualtrics":1,"quantcast":1,"quantserve":1,"quantummetric":1,"quietknowledge":1,"quizzicalzephyr":1,"quora":1,"r42tag":1,"railwayreason":1,"rakuten":1,"rambunctiousflock":1,"rangeplayground":1,"realsrv":1,"rebelswing":1,"reconditerake":1,"reconditerespect":1,"recruitics":1,"reddit":1,"redditstatic":1,"rehabilitatereason":1,"reson8":1,"resonantrock":1,"responsiveads":1,"restrainstorm":1,"retargetly":1,"revcontent":1,"rezync":1,"rfihub":1,"rhetoricalloss":1,"richaudience":1,"righteouscrayon":1,"rightfulfall":1,"riotgames":1,"rkdms":1,"rlcdn":1,"rmtag":1,"rncdn5":1,"rnengage":1,"rogersmedia":1,"rokt":1,"route":1,"rubiconproject":1,"s-onetag":1,"saambaa":1,"sablesong":1,"sail-horizon":1,"salesforceliveagent":1,"samestretch":1,"satisfycork":1,"savoryorange":1,"scarabresearch":1,"scaredsnakes":1,"scarfsmash":1,"scatteredstream":1,"scene7":1,"scholarlyiq":1,"scintillatingsilver":1,"scorecardresearch":1,"screechingstove":1,"screenpopper":1,"sddan":1,"sdiapi":1,"seatsmoke":1,"securedvisit":1,"seedtag":1,"sefsdvc":1,"segment":1,"sekindo":1,"selectivesummer":1,"selfishsnake":1,"servebom":1,"servedbyadbutler":1,"servenobid":1,"serverbid":1,"serving-sys":1,"shakegoldfish":1,"shappify":1,"shareaholic":1,"sharethis":1,"sharethrough":1,"shopifyapps":1,"shopperapproved":1,"shrillspoon":1,"sibautomation":1,"sicksmash":1,"sift":1,"siftscience":1,"signifyd":1,"siteimprove":1,"siteimproveanalytics":1,"sitescout":1,"skillfuldrop":1,"sli-spark":1,"slickstream":1,"slopesoap":1,"smadex":1,"smartadserver":1,"smashquartz":1,"smashsurprise":1,"smg":1,"smilewanted":1,"smoggysnakes":1,"snapchat":1,"snapkit":1,"snigelweb":1,"socdm":1,"sojern":1,"songsterritory":1,"sonobi":1,"speedcurve":1,"sphereup":1,"spiceworks":1,"spookyexchange":1,"spookyskate":1,"spookysleet":1,"sportradar":1,"sportradarserving":1,"sportslocalmedia":1,"spotxchange":1,"springserve":1,"srvmath":1,"stackadapt":1,"stakingsmile":1,"statcounter":1,"steadfastseat":1,"steadfastsound":1,"steadfastsystem":1,"steelhousemedia":1,"steepsquirrel":1,"stereoproxy":1,"stereotypedsugar":1,"stickyadstv":1,"stiffgame":1,"straightnest":1,"stripchat":1,"stupendoussleet":1,"stupendoussnow":1,"stupidscene":1,"sulkycook":1,"sumo":1,"sumologic":1,"sundaysky":1,"superficialeyes":1,"superficialsquare":1,"survicate":1,"svonm":1,"symantec":1,"taboola":1,"tagcommander":1,"tailtarget":1,"talkable":1,"taobao":1,"tapad":1,"taptapnetworks":1,"taskanalytics":1,"tealiumiq":1,"technoratimedia":1,"techtarget":1,"tediousticket":1,"teenytinyshirt":1,"tendertest":1,"the-ozone-project":1,"theadex":1,"themoneytizer":1,"theplatform":1,"thestar":1,"thomastorch":1,"threetruck":1,"thrtle":1,"tidaltv":1,"tidiochat":1,"tiktok":1,"tinypass":1,"tiqcdn":1,"tiresomethunder":1,"trackjs":1,"trafficjunky":1,"travelaudience":1,"treasuredata":1,"tremorhub":1,"trendemon":1,"tribalfusion":1,"trovit":1,"trueleadid":1,"truoptik":1,"truste":1,"trustedsite":1,"trustpilot":1,"tsyndicate":1,"tubemogul":1,"turn":1,"tvpixel":1,"tvsquared":1,"tweakwise":1,"twitter":1,"tynt":1,"typicalteeth":1,"u5e":1,"ubembed":1,"uidapi":1,"ultraoranges":1,"unbecominglamp":1,"unbxdapi":1,"undertone":1,"uninterestedquarter":1,"unpkg":1,"unrulymedia":1,"unwieldyhealth":1,"unwieldyplastic":1,"upsellit":1,"urbanairship":1,"usabilla":1,"usbrowserspeed":1,"usemessages":1,"userreport":1,"uservoice":1,"valuecommerce":1,"vengefulgrass":1,"vidazoo":1,"videoplayerhub":1,"vidoomy":1,"viglink":1,"visualwebsiteoptimizer":1,"vivaclix":1,"vk":1,"vlitag":1,"vocento":1,"voicefive":1,"volatilevessel":1,"voraciousgrip":1,"voxmedia":1,"vrtcal":1,"w3counter":1,"walkme":1,"warmafterthought":1,"warmquiver":1,"webcontentassessor":1,"webengage":1,"webeyez":1,"webflow":1,"webtraxs":1,"webtrends-optimize":1,"webtrends":1,"wgplayer":1,"wisepops":1,"worldoftulo":1,"wpadmngr":1,"wpshsdk":1,"wpushsdk":1,"wsod":1,"wt-safetag":1,"wysistat":1,"xg4ken":1,"xiti":1,"xlirdr":1,"xlivrdr":1,"xnxx-cdn":1,"y-track":1,"yahoo":1,"yandex":1,"yieldmo":1,"yieldoptimizer":1,"yimg":1,"yotpo":1,"yottaa":1,"youtube-nocookie":1,"youtube":1,"zatnoh":1,"zemanta":1,"zendesk":1,"zeotap":1,"zeronaught":1,"zestycrime":1,"zonos":1,"zoominfo":1,"zopim":1,"adnxs-simple":1,"createsend1":1,"adventori":1,"facil-iti":1,"provenexpert":1,"veoxa":1,"getflowbox":1,"parchedsofa":1,"adtraction":1,"bannerflow":1,"aboardamusement":1,"absorbingcorn":1,"abstractedamount":1,"actoramusement":1,"actuallysnake":1,"adorableanger":1,"agreeabletouch":1,"aheadday":1,"ancientact":1,"annoyedairport":1,"annoyingacoustics":1,"aquaticowl":1,"aspiringattempt":1,"audioarctic":1,"awarealley":1,"awesomeagreement":1,"awzbijw":1,"basketballbelieve":1,"begintrain":1,"bestboundary":1,"blushingbeast":1,"boredcrown":1,"breadbalance":1,"breakfastboat":1,"bulbbait":1,"burnbubble":1,"bustlingbath":1,"callousbrake":1,"calmcactus":1,"capriciouscorn":1,"caringcast":1,"catschickens":1,"causecherry":1,"chunkycactus":1,"cloisteredcord":1,"closedcows":1,"colossalclouds":1,"colossalcoat":1,"comfortablecheese":1,"conditioncrush":1,"consciouscheese":1,"consciousdirt":1,"coverapparatus":1,"cratecamera":1,"critictruck":1,"curvycry":1,"cushionpig":1,"damageddistance":1,"debonairdust":1,"decisivedrawer":1,"decisiveducks":1,"detailedkitten":1,"diplomahawaii":1,"dk4ywix":1,"dq95d35":1,"energeticladybug":1,"enormousearth":1,"evanescentedge":1,"fadedsnow":1,"fancyactivity":1,"farshake":1,"fastenfather":1,"fatcoil":1,"faultycanvas":1,"firstfrogs":1,"flimsycircle":1,"flimsythought":1,"friendwool":1,"fumblingform":1,"futuristicfifth":1,"giddycoat":1,"giraffepiano":1,"glisteningguide":1,"grayreceipt":1,"greasysquare":1,"grouchypush":1,"haltinggold":1,"handyfield":1,"handyfireman":1,"hearthorn":1,"historicalbeam":1,"horsenectar":1,"hystericalcloth":1,"impulsejewel":1,"incompetentjoke":1,"internalsink":1,"lameletters":1,"livelumber":1,"livelylaugh":1,"lorenzourban":1,"lumpylumber":1,"maliciousmusic":1,"meatydime":1,"memorizeneck":1,"mightyspiders":1,"mixedreading":1,"modularmental":1,"motionlessbag":1,"movemeal":1,"nondescriptcrowd":1,"nostalgicneed":1,"nuttyorganization":1,"optimallimit":1,"outstandingincome":1,"outstandingsnails":1,"panickycurtain":1,"petiteumbrella":1,"placidperson":1,"plantdigestion":1,"punyplant":1,"rabbitbreath":1,"rabbitrifle":1,"raintwig":1,"rainyhand":1,"rainyrule":1,"rangecake":1,"raresummer":1,"readymoon":1,"rebelsubway":1,"receptivereaction":1,"regularplants":1,"repeatsweater":1,"replaceroute":1,"resonantbrush":1,"respectrain":1,"richstring":1,"roofrelation":1,"rusticprice":1,"scaredcomfort":1,"scaredsnake":1,"scientificshirt":1,"scintillatingscissors":1,"screechingfurniture":1,"seashoresociety":1,"secretturtle":1,"shakysurprise":1,"shallowblade":1,"shesubscriptions":1,"shockingship":1,"sillyscrew":1,"sincerebuffalo":1,"sinceresubstance":1,"singroot":1,"sixscissors":1,"soggysponge":1,"somberscarecrow":1,"sordidsmile":1,"sortsail":1,"sortsummer":1,"spellsalsa":1,"spotlessstamp":1,"spottednoise":1,"stalesummer":1,"steadycopper":1,"stepplane":1,"strangesink":1,"stretchsister":1,"strivesidewalk":1,"superficialspring":1,"swellstocking":1,"synonymousrule":1,"tangyamount":1,"tastelesstrees":1,"teenytinycellar":1,"teenytinytongue":1,"terriblethumb":1,"terrifictooth":1,"thirdrespect":1,"ticketaunt":1,"tremendousplastic":1,"troubledtail":1,"typicalairplane":1,"ubiquitousyard":1,"unbecominghall":1,"uncoveredexpert":1,"unequalbrake":1,"unknowncrate":1,"untidyrice":1,"unusedstone":1,"venusgloria":1,"verdantanswer":1,"verseballs":1,"wearbasin":1,"cautiouscredit":1,"confesschairs":1,"chinsnakes":1,"wellgroomedhydrant":1,"heavyplayground":1,"bravecalculator":1,"workoperation":1,"secondhandfall":1,"unablehope":1,"tastelesstrucks":1,"losslace":1,"barbarousbase":1,"supportwaves":1,"protestcopy":1,"automaticturkey":1,"stretchsquirrel":1,"equablekettle":1,"discreetquarter":1,"peacefullimit":1,"gulliblegrip":1,"swelteringsleep":1,"muteknife":1,"aliasanvil":1,"operationchicken":1,"courageousbaby":1,"flowerstreatment":1,"scissorsstatement":1,"furryfork":1,"synonymoussticks":1,"deerbeginner":1,"rhetoricalveil":1,"farsnails":1,"kaputquill":1,"digestiondrawer":1,"meltmilk":1,"endurablebulb":1,"sugarfriction":1,"combcompetition":1,"stakingshock":1,"stretchsneeze":1,"sinkbooks":1,"brotherslocket":1,"cautiouscamera":1,"materialparcel":1,"inputicicle":1,"chargecracker":1,"fewjuice":1,"tumbleicicle":1,"serpentshampoo":1,"nutritiousbean":1,"scrapesleep":1,"bleachbubble":1,"longingtrees":1,"leftliquid":1,"handsomehose":1,"powerfulcopper":1,"painstakingpickle":1,"swankysquare":1,"soundstocking":1,"disagreeabledrop":1,"cushiondrum":1,"ruralrobin":1,"gorgeousedge":1,"strivesquirrel":1,"currentcollar":1,"combativecar":1,"ambiguousafternoon":1,"harborcaption":1,"blushingbread":1,"suggestionbridge":1,"spectacularstamp":1,"skisofa":1,"predictplate":1,"shakyseat":1,"priceypies":1,"livelyreward":1,"stealsteel":1,"shiveringspot":1,"memorizematch":1,"knitstamp":1,"bushesbag":1,"mundanenail":1,"coldbalance":1,"shapecomb":1,"shiverscissors":1,"broadborder":1,"quirkysugar":1,"stingyspoon":1,"billowybelief":1,"crookedcreature":1,"acceptableauthority":1,"sadloaf":1,"separatesort":1,"pailpatch":1,"scribblestring":1,"exhibitsneeze":1,"largebrass":1,"combcattle":1,"materialisticmoon":1,"fixedfold":1,"restructureinvention":1,"scaredstomach":1,"cautiouscherries":1,"tritebadge":1,"motionflowers":1,"ballsbanana":1,"meddleplant":1,"simulateswing":1,"marketspiders":1,"grumpydime":1,"neatshade":1,"samplesamba":1,"samesticks":1,"buttonladybug":1,"mentorsticks":1,"scaredsong":1,"annoyingclover":1,"grainmass":1,"tempertrick":1,"quizzicalpartner":1,"franticroof":1,"cattlecommittee":1,"tangycover":1,"looseloaf":1,"psychedelicarithmetic":1,"radiateprose":1,"shamerain":1,"cleanhaircut":1,"badgevolcano":1,"laboredlocket":1,"zipperxray":1,"stingycrush":1,"sixauthority":1,"thinkitten":1,"strokesystem":1,"hatefulrequest":1},"net":{"2mdn":1,"2o7":1,"incapdns":{"x":{"3exvfbh":1,"5t48cjc":1,"7xjpy4d":1,"dzm868l":1,"ttk8bbo":1}},"3gl":1,"a-mo":1,"acint":1,"adform":1,"adhigh":1,"admixer":1,"adobedc":1,"adspeed":1,"azureedge":{"adv-cloudfilse":1,"afw-static":1,"bayleys-pri-cdn-endpoint":1,"cdne-nxtevo-prd01-ms":1,"discountcodeexpress":1,"fp-cdn":1,"lefigaro":1,"ocpd-content":1,"sdtagging":1,"trenord-europe-trenord-endpoint-prd":1},"adverticum":1,"edgekey":{"akamai-111035":1,"com":{"alicdn":1,"ebay":1,"mtvnservices":1,"nbcuni":1,"nintendo":1,"oneindia":1,"scene7":1,"turner":1,"ziffdavis":1,"ziffdavisinternational":1},"ame":1,"au":1,"br":1,"ca":1,"com-v1":1,"com-v2":1,"gov":1,"in":1,"io":1,"it":1,"net":1,"org":1,"ppll":1,"rakuten":1,"uk":1},"apicit":1,"appier":1,"akamaized":{"assets-momentum":1,"com":{"media-rockstargames-":1,"ntd":1,"vocento":1}},"aticdn":1,"azure":1,"azurefd":1,"bannerflow":1,"bf-tools":1,"bidswitch":1,"bitsngo":1,"blueconic":1,"boldapps":1,"buysellads":1,"cedexis":1,"certona":1,"fastly":{"map":{"cidgroup":1,"condenast":1,"ihrinferno":1,"prisa-us-eu":1,"scribd":1,"target-opus":1,"thriftbooks":1,"ticketmaster4":1,"twitch":1,"vox":1,"appnexus":1},"global":{"shared":{"d2":1,"s2":1},"sni":{"j":1}},"ssl":{"global":{"igao-prod-herokuapp-com":1,"mslc-prod-herokuapp-com":1}}},"confiant-integrations":1,"consentmanager":1,"contentsquare":1,"criteo":1,"crwdcntrl":1,"cloudfront":{"d16jny3kjm2a1j":1,"d16kgn4efacaad":1,"d19l6uotjzm32g":1,"d1af033869koo7":1,"d1bxz6tua5hq87":1,"d1cr9zxt7u0sgu":1,"d1egjda7ggd2ew":1,"d1eh9yux7w8iql":1,"d1gwclp1pmzk26":1,"d1nhstnts0iwzs":1,"d1p5cqqchvbqmy":1,"d1pq45hly7zfel":1,"d1rhs7mhgydok3":1,"d1rw50yn65615p":1,"d1s87id6169zda":1,"d1snv67wdds0p2":1,"d1tprjo2w7krrh":1,"d1vg5xiq7qffdj":1,"d1vo8zfysxy97v":1,"d1y068gyog18cq":1,"d214hhm15p4t1d":1,"d21gpk1vhmjuf5":1,"d244lyzgucnepm":1,"d27cwqlgojh9yd":1,"d2aioe7l2jay46":1,"d2bj4wnxqmm2tk":1,"d2droglu4qf8st":1,"d2eanzqpmoo3ec":1,"d2f4zoo8hyailp":1,"d2hs2r19gv871k":1,"d2j6syf6c0cltf":1,"d2jpq2u2vrjftk":1,"d2qlgd5odkppg5":1,"d2qrdklrsxowl2":1,"d2s6j0ghajv79z":1,"d2tyltutevw8th":1,"d2wo2i8fdcw8of":1,"d2xbocf5uqnw0w":1,"d2y7rifa1cwopa":1,"d2zah9y47r7bi2":1,"d30jydkdo8eo9b":1,"d355prp56x5ntt":1,"d35mt2i8wrf9y1":1,"d38aqfmkl3ge26":1,"d38xvr37kwwhcm":1,"d3fv2pqyjay52z":1,"d3gxe0jmvtuxbc":1,"d3i4yxtzktqr9n":1,"d3jruqy3qmm3fd":1,"d3nn82uaxijpm6":1,"d3o8vwpyaorolj":1,"d3ochae1kou2ub":1,"d3odp2r1osuwn0":1,"d3owq2fdwtdp2j":1,"d3txh7prdum3s8":1,"d3v7mj6iyaqfac":1,"d4egga2bwam6h":1,"d5yoctgpv4cpx":1,"d6tizftlrpuof":1,"d9k0w0y3delq8":1,"dbukjj6eu5tsf":1,"de2pmm85odupd":1,"de7iszmjjjuya":1,"dfx0d9twj2ai":1,"dj28g4s0yd4ph":1,"dn0qt3r0xannq":1,"dokumfe7mps0i":1,"dowpznhhyvkm4":1,"dsh7ky7308k4b":1,"dsx863kqtdxrt":1,"dtpw88eywzb7u":1,"duube1y6ojsji":1,"dzlkq6toxiazj":1,"dzz1zjxa9ulpk":1,"d2638j3z8ek976":1},"akadns":{"com":{"dellcdn":1,"febsec-fidelity":1},"line-zero":1},"demdex":1,"dotmetrics":1,"doubleclick":1,"durationmedia":1,"e-planning":1,"edgecastcdn":1,"emsecure":1,"episerver":1,"esm1":1,"eulerian":1,"everestjs":1,"everesttech":1,"eyeota":1,"ezoic":1,"facebook":1,"fastclick":1,"fbcdn":1,"fonts":1,"edgesuite":{"com":{"fox":1,"iq":1,"tiktokcdn-us":1,"vidio":1,"sky":1},"linkedin":1,"stls":1},"fuseplatform":1,"fwmrm":1,"go-mpulse":1,"hadronid":1,"hs-analytics":1,"hsleadflows":1,"im-apps":1,"impervadns":1,"iocnt":1,"iprom":1,"jsdelivr":1,"kanade-ad":1,"azurewebsites":{"keha-matomo-te-palvelut-prod":1,"neuterbot-client":1,"app-ch-sgtm-prod":1,"app-fnsp-matomo-analytics-prod":1},"krxd":1,"line-scdn":1,"listhub":1,"livecom":1,"livedoor":1,"liveperson":1,"lkqd":1,"llnwd":1,"lpsnmedia":1,"magnetmail":1,"marketo":1,"maxymiser":1,"media":1,"microad":1,"monetate":1,"mxptint":1,"myfonts":1,"myvisualiq":1,"naver":1,"b-cdn":{"nnwwwlive":1,"speedy":1},"nr-data":1,"omtrdc":1,"onecount":1,"online-metrix":1,"openx":1,"opta":1,"owneriq":1,"pages02":1,"pages03":1,"pages04":1,"pages05":1,"pages06":1,"pages08":1,"perimeterx":1,"pingdom":1,"pmdstatic":1,"popads":1,"popcash":1,"primecaster":1,"pro-market":1,"px-cloud":1,"akamaihd":{"pxlclnmdecom-a":1},"r9cdn":1,"rfihub":1,"sancdn":1,"sc-static":1,"semasio":1,"sensic":1,"trafficmanager":{"serviceschipotlecom":1},"sexad":1,"smaato":1,"spreadshirts":1,"storygize":1,"tfaforms":1,"trackcmp":1,"trackedlink":1,"truste-svc":1,"uuidksinc":1,"viafoura":1,"visilabs":1,"visx":1,"w55c":1,"wdsvc":1,"witglobal":1,"yandex":1,"yastatic":1,"yieldlab":1,"ywxi":1,"zdbb":1,"zencdn":1,"zucks":1,"eviltracker":1},"co":{"6sc":1,"ayads":1,"datadome":1,"idio":1,"increasingly":1,"jads":1,"nanorep":1,"nc0":1,"pcdn":1,"prmutv":1,"resetdigital":1,"t":1,"tctm":1,"zip":1},"de":{"71i":1,"adscale":1,"auswaertiges-amt":1,"fiduciagad":1,"ioam":1,"itzbund":1,"werk21system":1},"gt":{"ad":1},"jp":{"adingo":1,"admatrix":1,"auone":1,"co":{"dmm":1,"google":1,"rakuten":1,"yahoo":1},"fout":1,"gmossp-sp":1,"gssprt":1,"ne":{"hatena":1},"impact-ad":1,"microad":1,"nakanohito":1,"ptengine":1,"r10s":1,"reemo-ad":1,"rtoaster":1,"shinobi":1,"team-rec":1,"uncn":1,"yimg":1,"yjtag":1},"pl":{"adocean":1,"dreamlab":1,"gemius":1,"nsaudience":1,"onet":1,"salesmanago":1,"wp":1},"pro":{"adpartner":1,"piwik":1,"usocial":1},"ru":{"adriver":1,"digitaltarget":1,"mail":1,"mindbox":1,"rambler":1,"sape":1,"smi2":1,"tns-counter":1,"top100":1,"ulogin":1,"yandex":1},"re":{"adsco":1},"info":{"adxbid":1,"bitrix":1,"navistechnologies":1,"usergram":1,"webantenna":1},"tv":{"affec":1,"attn":1,"iris":1,"ispot":1,"samba":1,"teads":1,"twitch":1},"dev":{"amazon":1},"us":{"amung":1,"samplicio":1,"slgnt":1,"trkn":1},"media":{"andbeyond":1,"nextday":1,"townsquare":1,"underdog":1},"link":{"app":1},"cloud":{"avct":1,"coremedia":1,"egain":1,"matomo":1},"delivery":{"ay":1,"monu":1},"br":{"com":{"btg360":1,"clearsale":1,"jsuol":1,"shopconvert":1,"shoptarget":1,"soclminer":1},"org":{"ivcbrasil":1}},"ch":{"ch":1,"da-services":1,"google":1},"ms":{"clarity":1},"my":{"cnt":1},"se":{"codigo":1},"me":{"contentexchange":1,"grow":1,"line":1,"loopme":1,"t":1,"channel":1},"to":{"cpx":1,"tawk":1},"chat":{"crisp":1,"gorgias":1},"fr":{"d-bi":1,"open-system":1,"weborama":1},"uk":{"co":{"dailymail":1,"hsbc":1}},"id":{"net":{"detik":1}},"ai":{"e-volution":1,"m2":1,"nrich":1,"wknd":1},"be":{"geoedge":1},"au":{"com":{"google":1,"news":1,"nine":1,"realestate":1,"zipmoney":1,"telstra":1}},"stream":{"ibclick":1},"cz":{"imedia":1,"seznam":1,"trackad":1},"app":{"infusionsoft":1,"permutive":1,"shop":1},"tech":{"ingage":1,"primis":1},"eu":{"kameleoon":1,"medallia":1,"media01":1,"ocdn":1,"rqtrk":1,"slgnt":1,"usercentrics":1},"fi":{"kesko":1,"simpli":1},"live":{"lura":1},"services":{"marketingautomation":1},"sg":{"mediacorp":1},"bi":{"newsroom":1},"fm":{"pdst":1},"ad":{"pixel":1},"xyz":{"playground":1},"it":{"plug":1,"repstatic":1,"stbm":1},"cc":{"popin":1},"network":{"pub":1},"nl":{"rijksoverheid":1,"google":1},"fyi":{"sda":1},"pe":{"shop":1},"es":{"socy":1},"im":{"spot":1},"market":{"spotim":1},"am":{"tru":1},"at":{"waust":1},"gov":{"weather":1},"in":{"zoho":1},"ca":{"bc":{"gov":1}},"no":{"acdn":1,"uio":1},"example":{"ad-company":1},"site":{"ad-company":1,"third-party":{"bad":1,"broken":1}},"pw":{"zlp6s":1}}; return { debug: false, sessionKey: 'randomVal', @@ -10910,7 +11291,8 @@ 'fingerprintingScreenSize', 'navigatorInterface' ] - } + }, + trackerLookup } } @@ -10951,7 +11333,10 @@ const processedConfig = generateConfig(); load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }); // mark this phase as loaded diff --git a/build/integration/pages/duckplayer/js/index.js b/build/integration/pages/duckplayer/js/index.js index 943239538..d70322c7b 100644 --- a/build/integration/pages/duckplayer/js/index.js +++ b/build/integration/pages/duckplayer/js/index.js @@ -725,6 +725,57 @@ } }; + // ../../src/dom-utils.js + var Template = class { + constructor(strings, values) { + this.values = values; + this.strings = strings; + } + /** + * Escapes any occurrences of &, ", <, > or / with XML entities. + * + * @param {string} str + * The string to escape. + * @return {string} The escaped string. + */ + escapeXML(str) { + const replacements = { + "&": "&", + '"': """, + "'": "'", + "<": "<", + ">": ">", + "/": "/" + }; + return String(str).replace(/[&"'<>/]/g, (m) => replacements[m]); + } + potentiallyEscape(value) { + if (typeof value === "object") { + if (value instanceof Array) { + return value.map((val) => this.potentiallyEscape(val)).join(""); + } + if (value instanceof Template) { + return value; + } + throw new Error("Unknown object to escape"); + } + return this.escapeXML(value); + } + toString() { + const result = []; + for (const [i, string] of this.strings.entries()) { + result.push(string); + if (i < this.values.length) { + result.push(this.potentiallyEscape(this.values[i])); + } + } + return result.join(""); + } + }; + function html(strings, ...values) { + return new Template(strings, values); + } + // pages/duckplayer/src/js/index.js var VideoPlayer = { /** @@ -783,7 +834,7 @@ * Show an error instead of the video player iframe */ showVideoError: (errorMessage) => { - VideoPlayer.playerContainer().innerHTML = '
ERROR:
'; + VideoPlayer.playerContainer().innerHTML = html`
ERROR:
`.toString(); document.querySelector(".player-error-message").textContent = errorMessage; }, /** diff --git a/build/tracker-lookup.json b/build/tracker-lookup.json new file mode 100644 index 000000000..dff48b985 --- /dev/null +++ b/build/tracker-lookup.json @@ -0,0 +1 @@ +{"org":{"cdn77":{"rsc":{"1666210260":1}},"adsrvr":1,"ampproject":1,"browser-update":1,"flowplayer":1,"privacy-center":1,"webvisor":1,"framasoft":1,"do-not-tracker":1,"trackersimulator":1},"io":{"1dmp":1,"1rx":1,"4dex":1,"adnami":1,"aidata":1,"arcspire":1,"bidr":1,"branch":1,"center":1,"concert":1,"connectad":1,"cordial":1,"dcmn":1,"extole":1,"getblue":1,"hbrd":1,"imbox":1,"instana":1,"karte":1,"lytics":1,"marchex":1,"mediago":1,"mrf":1,"myfidevs":1,"narrative":1,"ntv":1,"optad360":1,"oracleinfinity":1,"oribi":1,"p-n":1,"personalizer":1,"pghub":1,"piano":1,"powr":1,"pzz":1,"searchspring":1,"segment":1,"siteimproveanalytics":1,"sjv":1,"sspinc":1,"t13":1,"webgains":1,"wovn":1,"yellowblue":1,"zprk":1,"reviews":1,"appconsent":1,"leadsmonitor":1},"com":{"2020mustang":1,"33across":1,"360yield":1,"3lift":1,"4dsply":1,"4jnzhl0d0":1,"4strokemedia":1,"5d2d04464c":1,"a-mx":1,"a2z":1,"aamsitecertifier":1,"absorbingband":1,"abstractedauthority":1,"abtasty":1,"acexedge":1,"acidpigs":1,"acsbapp":1,"acuityplatform":1,"ad-score":1,"ad-stir":1,"adalyser":1,"adapf":1,"adara":1,"adblade":1,"addthis":1,"addtoany":1,"adelixir":1,"adentifi":1,"adextrem":1,"adgrx":1,"adhese":1,"adition":1,"adkernel":1,"adlightning":1,"adlooxtracking":1,"admanmedia":1,"admedo":1,"adnium":1,"adnxs":1,"adobedtm":1,"adotmob":1,"adpone":1,"adpushup":1,"adroll":1,"adrta":1,"ads-twitter":1,"ads3-adnow":1,"adsafeprotected":1,"adstanding":1,"adswizz":1,"adsymptotic":1,"adtdp":1,"adtechus":1,"adtelligent":1,"adthrive":1,"adtlgc":1,"adtng":1,"adultfriendfinder":1,"advangelists":1,"adventive":1,"advertising":1,"aegpresents":1,"affinity":1,"affirm":1,"agilone":1,"agkn":1,"aimbase":1,"albacross":1,"alcmpn":1,"alexametrics":1,"alicdn":1,"alikeaddition":1,"aliveachiever":1,"aliyuncs":1,"alluringbucket":1,"aloofvest":1,"amazon-adsystem":1,"amazon":1,"amplitude":1,"analytics-egain":1,"aniview":1,"anymind360":1,"amazonaws":{"ap-southeast-2":1,"elb":{"eu-west-2":{"collect-prd-alb-539115803":1},"us-east-1":{"data-allstate-com-715826933":1,"prod-lb-8-1772099769":1,"proxy-mycigna-prod-678433465":1,"www-u45-pnc-com-902993410":1,"www-u46-pnc-com-13593657":1},"eu-west-1":{"devservicesalb-471015105":1,"petfre-content-1201188928":1},"us-east-2":{"elbpiwik-public-1781721271":1},"eu-central-1":{"prod-lb-6-388533732":1,"prod-lb-7-718125029":1,"prod-pub-alb-654989386":1}},"us-east-2":{"s3":{"hb-gretsch-talk":1,"hb-jetpunk":1,"hb-obv2":1}},"eu-central-1":{"s3":{"headless-ssr-prod-bucket":1}}},"app-us1":1,"appboycdn":1,"appdynamics":1,"aralego":1,"arkoselabs":1,"aswpsdkus":1,"atemda":1,"att":1,"attentivemobile":1,"attractionbanana":1,"audioeye":1,"audrte":1,"automaticside":1,"avanser":1,"avmws":1,"aweber":1,"aweprt":1,"azure":1,"b0e8":1,"bagbeam":1,"bandborder":1,"batch":1,"bawdybalance":1,"bc0a":1,"bdstatic":1,"bedsberry":1,"beginnerpancake":1,"benchmarkemail":1,"betweendigital":1,"bfmio":1,"bidderstack":1,"bidtheatre":1,"bimbolive":1,"bing":1,"bizographics":1,"bizrate":1,"bkrtx":1,"blismedia":1,"blogherads":1,"bluecava":1,"bluekai":1,"boatwizard":1,"boilingcredit":1,"boldchat":1,"booking":1,"borderfree":1,"bounceexchange":1,"brainlyads":1,"brand-display":1,"brandmetrics":1,"brealtime":1,"breinify":1,"brightedge":1,"brightfunnel":1,"brightspotcdn":1,"btloader":1,"btstatic":1,"bttrack":1,"btttag":1,"butterbulb":1,"buzzoola":1,"byside":1,"cabnnr":1,"calculatorstatement":1,"callrail":1,"calltracks":1,"capablecup":1,"captcha-delivery":1,"carpentercomparison":1,"cartstack":1,"carvecakes":1,"casalemedia":1,"cdn-btsg":1,"cdnwidget":1,"channeladvisor":1,"chartbeat":1,"chatango":1,"chaturbate":1,"cheqzone":1,"cherriescare":1,"chickensstation":1,"childlikecrowd":1,"childlikeform":1,"cintnetworks":1,"circlelevel":1,"civiccomputing":1,"ck-ie":1,"clcktrax":1,"clearbit":1,"clearbitjs":1,"clickagy":1,"clickcease":1,"clickcertain":1,"clicktripz":1,"clientgear":1,"clksite":1,"cloudflare":1,"cloudflareinsights":1,"cloudflarestream":1,"cloudmaestro":1,"cobaltgroup":1,"cobrowser":1,"cognitivlabs":1,"colossusssp":1,"comm100":1,"googleapis":{"commondatastorage":1,"storage":1},"company-target":1,"condenastdigital":1,"confusedcart":1,"connatix":1,"consentframework":1,"contextweb":1,"conversionruler":1,"convertkit":1,"convertlanguage":1,"cookieinformation":1,"cookiepro":1,"coveo":1,"cpmstar":1,"cquotient":1,"crabbychin":1,"crazyegg":1,"creative-serving":1,"creativecdn":1,"criteo":1,"crowdedmass":1,"crowdriff":1,"crownpeak":1,"crsspxl":1,"ctnsnet":1,"cubchannel":1,"cudasvc":1,"cuddlethehyena":1,"cumbersomecarpenter":1,"curalate":1,"curvedhoney":1,"cutechin":1,"cxense":1,"dailymotion":1,"damdoor":1,"dampdock":1,"dapperfloor":1,"datadoghq-browser-agent":1,"decisivebase":1,"deepintent":1,"defybrick":1,"delivra":1,"demandbase":1,"detectdiscovery":1,"devilishdinner":1,"dimelochat":1,"discreetfield":1,"disqus":1,"dmpxs":1,"dockdigestion":1,"dollardelta":1,"dotomi":1,"doubleverify":1,"drainpaste":1,"dramaticdirection":1,"driftt":1,"dtscdn":1,"dtscout":1,"dwin1":1,"dynamics":1,"dynamicyield":1,"dynatrace":1,"dyntrk":1,"ebaystatic":1,"ecal":1,"eccmp":1,"elasticchange":1,"elfsight":1,"elitrack":1,"eloqua":1,"en25":1,"encouragingthread":1,"ensighten":1,"enviousshape":1,"eqads":1,"ero-advertising":1,"esputnik":1,"evergage":1,"evgnet":1,"exdynsrv":1,"exelator":1,"exoclick":1,"exosrv":1,"expansioneggnog":1,"expertrec":1,"exponea":1,"exponential":1,"extole":1,"ezodn":1,"ezoic":1,"ezoiccdn":1,"facebook":1,"fadewaves":1,"fallaciousfifth":1,"farmergoldfish":1,"fastly-insights":1,"fearlessfaucet":1,"fiftyt":1,"financefear":1,"fitanalytics":1,"five9":1,"fksnk":1,"flashtalking":1,"flipp":1,"floweryflavor":1,"flutteringfireman":1,"flux-cdn":1,"fomo":1,"foresee":1,"forter":1,"fortunatemark":1,"fouanalytics":1,"fox":1,"fqtag":1,"frailfruit":1,"freezingbuilding":1,"fronttoad":1,"fullstory":1,"functionalfeather":1,"fuzzybasketball":1,"gammamaximum":1,"gbqofs":1,"geetest":1,"geistm":1,"geniusmonkey":1,"geoip-js":1,"getbread":1,"getcandid":1,"getclicky":1,"getdrip":1,"getelevar":1,"getpublica":1,"getrockerbox":1,"getshogun":1,"getsitecontrol":1,"glassdoor":1,"gloriousbeef":1,"godpvqnszo":1,"gondolagnome":1,"google-analytics":1,"google":1,"googleadservices":1,"googlehosted":1,"googleoptimize":1,"googlesyndication":1,"googletagmanager":1,"googletagservices":1,"govx":1,"greylabeldelivery":1,"groovehq":1,"gstatic":1,"guarantee-cdn":1,"guiltlessbasketball":1,"gumgum":1,"haltingbadge":1,"hammerhearing":1,"handsomelyhealth":1,"hawksearch":1,"heapanalytics":1,"hellobar":1,"hiconversion":1,"highwebmedia":1,"histats":1,"hlserve":1,"hocgeese":1,"hollowafterthought":1,"honorableland":1,"hotjar":1,"hp":1,"hs-banner":1,"htlbid":1,"htplayground":1,"hubspot":1,"iadvize":1,"ib-ibi":1,"id5-sync":1,"iesnare":1,"igodigital":1,"iheart":1,"iljmp":1,"illiweb":1,"impactcdn":1,"impactradius-event":1,"impactradius-go":1,"impossibleexpansion":1,"impressionmonster":1,"improvedcontactform":1,"improvedigital":1,"imrworldwide":1,"indexww":1,"infolinks":1,"infusionsoft":1,"inmobi":1,"inmoment":1,"inq":1,"inside-graph":1,"instagram":1,"intentiq":1,"intergient":1,"investingchannel":1,"invocacdn":1,"iplsc":1,"ipredictive":1,"iteratehq":1,"ivitrack":1,"j93557g":1,"jaavnacsdw":1,"jimstatic":1,"journity":1,"js7k":1,"juicyads":1,"justanswer":1,"justpremium":1,"kakao":1,"kampyle":1,"kargo":1,"kissmetrics":1,"klarnaservices":1,"klaviyo":1,"knottyswing":1,"kount":1,"krushmedia":1,"ktkjmp":1,"kxcdn":1,"ladesk":1,"ladsp":1,"laughablelizards":1,"leadsrx":1,"lendingtree":1,"levexis":1,"liadm":1,"licdn":1,"lightboxcdn":1,"lijit":1,"linkedin":1,"linksynergy":1,"list-manage":1,"listrakbi":1,"livechatinc":1,"livejasmin":1,"localytics":1,"loggly":1,"loop11":1,"lovelydrum":1,"luckyorange":1,"lunchroomlock":1,"maddeningpowder":1,"mailchimp":1,"mailchimpapp":1,"mailerlite":1,"maillist-manage":1,"marinsm":1,"marketiq":1,"marketo":1,"marriedbelief":1,"matheranalytics":1,"mathtag":1,"maxmind":1,"mczbf":1,"measlymiddle":1,"medallia":1,"media6degrees":1,"mediacategory":1,"mediavine":1,"mediawallahscript":1,"medtargetsystem":1,"megpxs":1,"metricode":1,"metricswpsh":1,"mfadsrvr":1,"mgid":1,"micpn":1,"microadinc":1,"minutemedia-prebid":1,"minutemediaservices":1,"mixpo":1,"mktoresp":1,"mktoweb":1,"ml314":1,"moatads":1,"mobtrakk":1,"monsido":1,"mookie1":1,"mountain":1,"mouseflow":1,"mpeasylink":1,"mql5":1,"mrtnsvr":1,"murdoog":1,"mxpnl":1,"mybestpro":1,"myfinance":1,"myregistry":1,"nappyattack":1,"navistechnologies":1,"neodatagroup":1,"nervoussummer":1,"newrelic":1,"newscgp":1,"nextdoor":1,"ninthdecimal":1,"nitrocdn":1,"noibu":1,"nondescriptnote":1,"nosto":1,"npttech":1,"nuance":1,"nxsttv":1,"omappapi":1,"omnisnippet1":1,"omnisrc":1,"omnitagjs":1,"oneall":1,"onesignal":1,"onetag-sys":1,"oo-syringe":1,"ooyala":1,"opecloud":1,"opentext":1,"opera":1,"opmnstr":1,"optimicdn":1,"optinmonster":1,"optmnstr":1,"optmstr":1,"optnmnstr":1,"optnmstr":1,"oraclecloud":1,"osano":1,"otm-r":1,"outbrain":1,"overconfidentfood":1,"ownlocal":1,"pamelarandom":1,"panickypancake":1,"panoramicplane":1,"parastorage":1,"pardot":1,"parsely":1,"partplanes":1,"patreon":1,"paypal":1,"pbstck":1,"pcmag":1,"peerius":1,"perfdrive":1,"perfectmarket":1,"permutive":1,"picreel":1,"pinimg":1,"pippio":1,"piwikpro":1,"pixlee":1,"pleasantpump":1,"plotrabbit":1,"pluckypocket":1,"pocketfaucet":1,"possibleboats":1,"postaffiliatepro":1,"postrelease":1,"potatoinvention":1,"prepareplanes":1,"pricespider":1,"pricklydebt":1,"profusesupport":1,"proofpoint":1,"protoawe":1,"providesupport":1,"pswec":1,"psyma":1,"ptengine":1,"publir":1,"pubmatic":1,"pubmine":1,"pubnation":1,"puffypurpose":1,"qualaroo":1,"qualtrics":1,"quantcast":1,"quantserve":1,"quantummetric":1,"quietknowledge":1,"quizzicalzephyr":1,"quora":1,"r42tag":1,"railwayreason":1,"rakuten":1,"rambunctiousflock":1,"rangeplayground":1,"realsrv":1,"rebelswing":1,"reconditerake":1,"reconditerespect":1,"recruitics":1,"reddit":1,"redditstatic":1,"rehabilitatereason":1,"reson8":1,"resonantrock":1,"responsiveads":1,"restrainstorm":1,"retargetly":1,"revcontent":1,"rezync":1,"rfihub":1,"rhetoricalloss":1,"richaudience":1,"righteouscrayon":1,"rightfulfall":1,"riotgames":1,"rkdms":1,"rlcdn":1,"rmtag":1,"rncdn5":1,"rnengage":1,"rogersmedia":1,"rokt":1,"route":1,"rubiconproject":1,"s-onetag":1,"saambaa":1,"sablesong":1,"sail-horizon":1,"salesforceliveagent":1,"samestretch":1,"satisfycork":1,"savoryorange":1,"scarabresearch":1,"scaredsnakes":1,"scarfsmash":1,"scatteredstream":1,"scene7":1,"scholarlyiq":1,"scintillatingsilver":1,"scorecardresearch":1,"screechingstove":1,"screenpopper":1,"sddan":1,"sdiapi":1,"seatsmoke":1,"securedvisit":1,"seedtag":1,"sefsdvc":1,"segment":1,"sekindo":1,"selectivesummer":1,"selfishsnake":1,"servebom":1,"servedbyadbutler":1,"servenobid":1,"serverbid":1,"serving-sys":1,"shakegoldfish":1,"shappify":1,"shareaholic":1,"sharethis":1,"sharethrough":1,"shopifyapps":1,"shopperapproved":1,"shrillspoon":1,"sibautomation":1,"sicksmash":1,"sift":1,"siftscience":1,"signifyd":1,"siteimprove":1,"siteimproveanalytics":1,"sitescout":1,"skillfuldrop":1,"sli-spark":1,"slickstream":1,"slopesoap":1,"smadex":1,"smartadserver":1,"smashquartz":1,"smashsurprise":1,"smg":1,"smilewanted":1,"smoggysnakes":1,"snapchat":1,"snapkit":1,"snigelweb":1,"socdm":1,"sojern":1,"songsterritory":1,"sonobi":1,"speedcurve":1,"sphereup":1,"spiceworks":1,"spookyexchange":1,"spookyskate":1,"spookysleet":1,"sportradar":1,"sportradarserving":1,"sportslocalmedia":1,"spotxchange":1,"springserve":1,"srvmath":1,"stackadapt":1,"stakingsmile":1,"statcounter":1,"steadfastseat":1,"steadfastsound":1,"steadfastsystem":1,"steelhousemedia":1,"steepsquirrel":1,"stereoproxy":1,"stereotypedsugar":1,"stickyadstv":1,"stiffgame":1,"straightnest":1,"stripchat":1,"stupendoussleet":1,"stupendoussnow":1,"stupidscene":1,"sulkycook":1,"sumo":1,"sumologic":1,"sundaysky":1,"superficialeyes":1,"superficialsquare":1,"survicate":1,"svonm":1,"symantec":1,"taboola":1,"tagcommander":1,"tailtarget":1,"talkable":1,"taobao":1,"tapad":1,"taptapnetworks":1,"taskanalytics":1,"tealiumiq":1,"technoratimedia":1,"techtarget":1,"tediousticket":1,"teenytinyshirt":1,"tendertest":1,"the-ozone-project":1,"theadex":1,"themoneytizer":1,"theplatform":1,"thestar":1,"thomastorch":1,"threetruck":1,"thrtle":1,"tidaltv":1,"tidiochat":1,"tiktok":1,"tinypass":1,"tiqcdn":1,"tiresomethunder":1,"trackjs":1,"trafficjunky":1,"travelaudience":1,"treasuredata":1,"tremorhub":1,"trendemon":1,"tribalfusion":1,"trovit":1,"trueleadid":1,"truoptik":1,"truste":1,"trustedsite":1,"trustpilot":1,"tsyndicate":1,"tubemogul":1,"turn":1,"tvpixel":1,"tvsquared":1,"tweakwise":1,"twitter":1,"tynt":1,"typicalteeth":1,"u5e":1,"ubembed":1,"uidapi":1,"ultraoranges":1,"unbecominglamp":1,"unbxdapi":1,"undertone":1,"uninterestedquarter":1,"unpkg":1,"unrulymedia":1,"unwieldyhealth":1,"unwieldyplastic":1,"upsellit":1,"urbanairship":1,"usabilla":1,"usbrowserspeed":1,"usemessages":1,"userreport":1,"uservoice":1,"valuecommerce":1,"vengefulgrass":1,"vidazoo":1,"videoplayerhub":1,"vidoomy":1,"viglink":1,"visualwebsiteoptimizer":1,"vivaclix":1,"vk":1,"vlitag":1,"vocento":1,"voicefive":1,"volatilevessel":1,"voraciousgrip":1,"voxmedia":1,"vrtcal":1,"w3counter":1,"walkme":1,"warmafterthought":1,"warmquiver":1,"webcontentassessor":1,"webengage":1,"webeyez":1,"webflow":1,"webtraxs":1,"webtrends-optimize":1,"webtrends":1,"wgplayer":1,"wisepops":1,"worldoftulo":1,"wpadmngr":1,"wpshsdk":1,"wpushsdk":1,"wsod":1,"wt-safetag":1,"wysistat":1,"xg4ken":1,"xiti":1,"xlirdr":1,"xlivrdr":1,"xnxx-cdn":1,"y-track":1,"yahoo":1,"yandex":1,"yieldmo":1,"yieldoptimizer":1,"yimg":1,"yotpo":1,"yottaa":1,"youtube-nocookie":1,"youtube":1,"zatnoh":1,"zemanta":1,"zendesk":1,"zeotap":1,"zeronaught":1,"zestycrime":1,"zonos":1,"zoominfo":1,"zopim":1,"adnxs-simple":1,"createsend1":1,"adventori":1,"facil-iti":1,"provenexpert":1,"veoxa":1,"getflowbox":1,"parchedsofa":1,"adtraction":1,"bannerflow":1,"aboardamusement":1,"absorbingcorn":1,"abstractedamount":1,"actoramusement":1,"actuallysnake":1,"adorableanger":1,"agreeabletouch":1,"aheadday":1,"ancientact":1,"annoyedairport":1,"annoyingacoustics":1,"aquaticowl":1,"aspiringattempt":1,"audioarctic":1,"awarealley":1,"awesomeagreement":1,"awzbijw":1,"basketballbelieve":1,"begintrain":1,"bestboundary":1,"blushingbeast":1,"boredcrown":1,"breadbalance":1,"breakfastboat":1,"bulbbait":1,"burnbubble":1,"bustlingbath":1,"callousbrake":1,"calmcactus":1,"capriciouscorn":1,"caringcast":1,"catschickens":1,"causecherry":1,"chunkycactus":1,"cloisteredcord":1,"closedcows":1,"colossalclouds":1,"colossalcoat":1,"comfortablecheese":1,"conditioncrush":1,"consciouscheese":1,"consciousdirt":1,"coverapparatus":1,"cratecamera":1,"critictruck":1,"curvycry":1,"cushionpig":1,"damageddistance":1,"debonairdust":1,"decisivedrawer":1,"decisiveducks":1,"detailedkitten":1,"diplomahawaii":1,"dk4ywix":1,"dq95d35":1,"energeticladybug":1,"enormousearth":1,"evanescentedge":1,"fadedsnow":1,"fancyactivity":1,"farshake":1,"fastenfather":1,"fatcoil":1,"faultycanvas":1,"firstfrogs":1,"flimsycircle":1,"flimsythought":1,"friendwool":1,"fumblingform":1,"futuristicfifth":1,"giddycoat":1,"giraffepiano":1,"glisteningguide":1,"grayreceipt":1,"greasysquare":1,"grouchypush":1,"haltinggold":1,"handyfield":1,"handyfireman":1,"hearthorn":1,"historicalbeam":1,"horsenectar":1,"hystericalcloth":1,"impulsejewel":1,"incompetentjoke":1,"internalsink":1,"lameletters":1,"livelumber":1,"livelylaugh":1,"lorenzourban":1,"lumpylumber":1,"maliciousmusic":1,"meatydime":1,"memorizeneck":1,"mightyspiders":1,"mixedreading":1,"modularmental":1,"motionlessbag":1,"movemeal":1,"nondescriptcrowd":1,"nostalgicneed":1,"nuttyorganization":1,"optimallimit":1,"outstandingincome":1,"outstandingsnails":1,"panickycurtain":1,"petiteumbrella":1,"placidperson":1,"plantdigestion":1,"punyplant":1,"rabbitbreath":1,"rabbitrifle":1,"raintwig":1,"rainyhand":1,"rainyrule":1,"rangecake":1,"raresummer":1,"readymoon":1,"rebelsubway":1,"receptivereaction":1,"regularplants":1,"repeatsweater":1,"replaceroute":1,"resonantbrush":1,"respectrain":1,"richstring":1,"roofrelation":1,"rusticprice":1,"scaredcomfort":1,"scaredsnake":1,"scientificshirt":1,"scintillatingscissors":1,"screechingfurniture":1,"seashoresociety":1,"secretturtle":1,"shakysurprise":1,"shallowblade":1,"shesubscriptions":1,"shockingship":1,"sillyscrew":1,"sincerebuffalo":1,"sinceresubstance":1,"singroot":1,"sixscissors":1,"soggysponge":1,"somberscarecrow":1,"sordidsmile":1,"sortsail":1,"sortsummer":1,"spellsalsa":1,"spotlessstamp":1,"spottednoise":1,"stalesummer":1,"steadycopper":1,"stepplane":1,"strangesink":1,"stretchsister":1,"strivesidewalk":1,"superficialspring":1,"swellstocking":1,"synonymousrule":1,"tangyamount":1,"tastelesstrees":1,"teenytinycellar":1,"teenytinytongue":1,"terriblethumb":1,"terrifictooth":1,"thirdrespect":1,"ticketaunt":1,"tremendousplastic":1,"troubledtail":1,"typicalairplane":1,"ubiquitousyard":1,"unbecominghall":1,"uncoveredexpert":1,"unequalbrake":1,"unknowncrate":1,"untidyrice":1,"unusedstone":1,"venusgloria":1,"verdantanswer":1,"verseballs":1,"wearbasin":1,"cautiouscredit":1,"confesschairs":1,"chinsnakes":1,"wellgroomedhydrant":1,"heavyplayground":1,"bravecalculator":1,"workoperation":1,"secondhandfall":1,"unablehope":1,"tastelesstrucks":1,"losslace":1,"barbarousbase":1,"supportwaves":1,"protestcopy":1,"automaticturkey":1,"stretchsquirrel":1,"equablekettle":1,"discreetquarter":1,"peacefullimit":1,"gulliblegrip":1,"swelteringsleep":1,"muteknife":1,"aliasanvil":1,"operationchicken":1,"courageousbaby":1,"flowerstreatment":1,"scissorsstatement":1,"furryfork":1,"synonymoussticks":1,"deerbeginner":1,"rhetoricalveil":1,"farsnails":1,"kaputquill":1,"digestiondrawer":1,"meltmilk":1,"endurablebulb":1,"sugarfriction":1,"combcompetition":1,"stakingshock":1,"stretchsneeze":1,"sinkbooks":1,"brotherslocket":1,"cautiouscamera":1,"materialparcel":1,"inputicicle":1,"chargecracker":1,"fewjuice":1,"tumbleicicle":1,"serpentshampoo":1,"nutritiousbean":1,"scrapesleep":1,"bleachbubble":1,"longingtrees":1,"leftliquid":1,"handsomehose":1,"powerfulcopper":1,"painstakingpickle":1,"swankysquare":1,"soundstocking":1,"disagreeabledrop":1,"cushiondrum":1,"ruralrobin":1,"gorgeousedge":1,"strivesquirrel":1,"currentcollar":1,"combativecar":1,"ambiguousafternoon":1,"harborcaption":1,"blushingbread":1,"suggestionbridge":1,"spectacularstamp":1,"skisofa":1,"predictplate":1,"shakyseat":1,"priceypies":1,"livelyreward":1,"stealsteel":1,"shiveringspot":1,"memorizematch":1,"knitstamp":1,"bushesbag":1,"mundanenail":1,"coldbalance":1,"shapecomb":1,"shiverscissors":1,"broadborder":1,"quirkysugar":1,"stingyspoon":1,"billowybelief":1,"crookedcreature":1,"acceptableauthority":1,"sadloaf":1,"separatesort":1,"pailpatch":1,"scribblestring":1,"exhibitsneeze":1,"largebrass":1,"combcattle":1,"materialisticmoon":1,"fixedfold":1,"restructureinvention":1,"scaredstomach":1,"cautiouscherries":1,"tritebadge":1,"motionflowers":1,"ballsbanana":1,"meddleplant":1,"simulateswing":1,"marketspiders":1,"grumpydime":1,"neatshade":1,"samplesamba":1,"samesticks":1,"buttonladybug":1,"mentorsticks":1,"scaredsong":1,"annoyingclover":1,"grainmass":1,"tempertrick":1,"quizzicalpartner":1,"franticroof":1,"cattlecommittee":1,"tangycover":1,"looseloaf":1,"psychedelicarithmetic":1,"radiateprose":1,"shamerain":1,"cleanhaircut":1,"badgevolcano":1,"laboredlocket":1,"zipperxray":1,"stingycrush":1,"sixauthority":1,"thinkitten":1,"strokesystem":1,"hatefulrequest":1},"net":{"2mdn":1,"2o7":1,"incapdns":{"x":{"3exvfbh":1,"5t48cjc":1,"7xjpy4d":1,"dzm868l":1,"ttk8bbo":1}},"3gl":1,"a-mo":1,"acint":1,"adform":1,"adhigh":1,"admixer":1,"adobedc":1,"adspeed":1,"azureedge":{"adv-cloudfilse":1,"afw-static":1,"bayleys-pri-cdn-endpoint":1,"cdne-nxtevo-prd01-ms":1,"discountcodeexpress":1,"fp-cdn":1,"lefigaro":1,"ocpd-content":1,"sdtagging":1,"trenord-europe-trenord-endpoint-prd":1},"adverticum":1,"edgekey":{"akamai-111035":1,"com":{"alicdn":1,"ebay":1,"mtvnservices":1,"nbcuni":1,"nintendo":1,"oneindia":1,"scene7":1,"turner":1,"ziffdavis":1,"ziffdavisinternational":1},"ame":1,"au":1,"br":1,"ca":1,"com-v1":1,"com-v2":1,"gov":1,"in":1,"io":1,"it":1,"net":1,"org":1,"ppll":1,"rakuten":1,"uk":1},"apicit":1,"appier":1,"akamaized":{"assets-momentum":1,"com":{"media-rockstargames-":1,"ntd":1,"vocento":1}},"aticdn":1,"azure":1,"azurefd":1,"bannerflow":1,"bf-tools":1,"bidswitch":1,"bitsngo":1,"blueconic":1,"boldapps":1,"buysellads":1,"cedexis":1,"certona":1,"fastly":{"map":{"cidgroup":1,"condenast":1,"ihrinferno":1,"prisa-us-eu":1,"scribd":1,"target-opus":1,"thriftbooks":1,"ticketmaster4":1,"twitch":1,"vox":1,"appnexus":1},"global":{"shared":{"d2":1,"s2":1},"sni":{"j":1}},"ssl":{"global":{"igao-prod-herokuapp-com":1,"mslc-prod-herokuapp-com":1}}},"confiant-integrations":1,"consentmanager":1,"contentsquare":1,"criteo":1,"crwdcntrl":1,"cloudfront":{"d16jny3kjm2a1j":1,"d16kgn4efacaad":1,"d19l6uotjzm32g":1,"d1af033869koo7":1,"d1bxz6tua5hq87":1,"d1cr9zxt7u0sgu":1,"d1egjda7ggd2ew":1,"d1eh9yux7w8iql":1,"d1gwclp1pmzk26":1,"d1nhstnts0iwzs":1,"d1p5cqqchvbqmy":1,"d1pq45hly7zfel":1,"d1rhs7mhgydok3":1,"d1rw50yn65615p":1,"d1s87id6169zda":1,"d1snv67wdds0p2":1,"d1tprjo2w7krrh":1,"d1vg5xiq7qffdj":1,"d1vo8zfysxy97v":1,"d1y068gyog18cq":1,"d214hhm15p4t1d":1,"d21gpk1vhmjuf5":1,"d244lyzgucnepm":1,"d27cwqlgojh9yd":1,"d2aioe7l2jay46":1,"d2bj4wnxqmm2tk":1,"d2droglu4qf8st":1,"d2eanzqpmoo3ec":1,"d2f4zoo8hyailp":1,"d2hs2r19gv871k":1,"d2j6syf6c0cltf":1,"d2jpq2u2vrjftk":1,"d2qlgd5odkppg5":1,"d2qrdklrsxowl2":1,"d2s6j0ghajv79z":1,"d2tyltutevw8th":1,"d2wo2i8fdcw8of":1,"d2xbocf5uqnw0w":1,"d2y7rifa1cwopa":1,"d2zah9y47r7bi2":1,"d30jydkdo8eo9b":1,"d355prp56x5ntt":1,"d35mt2i8wrf9y1":1,"d38aqfmkl3ge26":1,"d38xvr37kwwhcm":1,"d3fv2pqyjay52z":1,"d3gxe0jmvtuxbc":1,"d3i4yxtzktqr9n":1,"d3jruqy3qmm3fd":1,"d3nn82uaxijpm6":1,"d3o8vwpyaorolj":1,"d3ochae1kou2ub":1,"d3odp2r1osuwn0":1,"d3owq2fdwtdp2j":1,"d3txh7prdum3s8":1,"d3v7mj6iyaqfac":1,"d4egga2bwam6h":1,"d5yoctgpv4cpx":1,"d6tizftlrpuof":1,"d9k0w0y3delq8":1,"dbukjj6eu5tsf":1,"de2pmm85odupd":1,"de7iszmjjjuya":1,"dfx0d9twj2ai":1,"dj28g4s0yd4ph":1,"dn0qt3r0xannq":1,"dokumfe7mps0i":1,"dowpznhhyvkm4":1,"dsh7ky7308k4b":1,"dsx863kqtdxrt":1,"dtpw88eywzb7u":1,"duube1y6ojsji":1,"dzlkq6toxiazj":1,"dzz1zjxa9ulpk":1,"d2638j3z8ek976":1},"akadns":{"com":{"dellcdn":1,"febsec-fidelity":1},"line-zero":1},"demdex":1,"dotmetrics":1,"doubleclick":1,"durationmedia":1,"e-planning":1,"edgecastcdn":1,"emsecure":1,"episerver":1,"esm1":1,"eulerian":1,"everestjs":1,"everesttech":1,"eyeota":1,"ezoic":1,"facebook":1,"fastclick":1,"fbcdn":1,"fonts":1,"edgesuite":{"com":{"fox":1,"iq":1,"tiktokcdn-us":1,"vidio":1,"sky":1},"linkedin":1,"stls":1},"fuseplatform":1,"fwmrm":1,"go-mpulse":1,"hadronid":1,"hs-analytics":1,"hsleadflows":1,"im-apps":1,"impervadns":1,"iocnt":1,"iprom":1,"jsdelivr":1,"kanade-ad":1,"azurewebsites":{"keha-matomo-te-palvelut-prod":1,"neuterbot-client":1,"app-ch-sgtm-prod":1,"app-fnsp-matomo-analytics-prod":1},"krxd":1,"line-scdn":1,"listhub":1,"livecom":1,"livedoor":1,"liveperson":1,"lkqd":1,"llnwd":1,"lpsnmedia":1,"magnetmail":1,"marketo":1,"maxymiser":1,"media":1,"microad":1,"monetate":1,"mxptint":1,"myfonts":1,"myvisualiq":1,"naver":1,"b-cdn":{"nnwwwlive":1,"speedy":1},"nr-data":1,"omtrdc":1,"onecount":1,"online-metrix":1,"openx":1,"opta":1,"owneriq":1,"pages02":1,"pages03":1,"pages04":1,"pages05":1,"pages06":1,"pages08":1,"perimeterx":1,"pingdom":1,"pmdstatic":1,"popads":1,"popcash":1,"primecaster":1,"pro-market":1,"px-cloud":1,"akamaihd":{"pxlclnmdecom-a":1},"r9cdn":1,"rfihub":1,"sancdn":1,"sc-static":1,"semasio":1,"sensic":1,"trafficmanager":{"serviceschipotlecom":1},"sexad":1,"smaato":1,"spreadshirts":1,"storygize":1,"tfaforms":1,"trackcmp":1,"trackedlink":1,"truste-svc":1,"uuidksinc":1,"viafoura":1,"visilabs":1,"visx":1,"w55c":1,"wdsvc":1,"witglobal":1,"yandex":1,"yastatic":1,"yieldlab":1,"ywxi":1,"zdbb":1,"zencdn":1,"zucks":1,"eviltracker":1},"co":{"6sc":1,"ayads":1,"datadome":1,"idio":1,"increasingly":1,"jads":1,"nanorep":1,"nc0":1,"pcdn":1,"prmutv":1,"resetdigital":1,"t":1,"tctm":1,"zip":1},"de":{"71i":1,"adscale":1,"auswaertiges-amt":1,"fiduciagad":1,"ioam":1,"itzbund":1,"werk21system":1},"gt":{"ad":1},"jp":{"adingo":1,"admatrix":1,"auone":1,"co":{"dmm":1,"google":1,"rakuten":1,"yahoo":1},"fout":1,"gmossp-sp":1,"gssprt":1,"ne":{"hatena":1},"impact-ad":1,"microad":1,"nakanohito":1,"ptengine":1,"r10s":1,"reemo-ad":1,"rtoaster":1,"shinobi":1,"team-rec":1,"uncn":1,"yimg":1,"yjtag":1},"pl":{"adocean":1,"dreamlab":1,"gemius":1,"nsaudience":1,"onet":1,"salesmanago":1,"wp":1},"pro":{"adpartner":1,"piwik":1,"usocial":1},"ru":{"adriver":1,"digitaltarget":1,"mail":1,"mindbox":1,"rambler":1,"sape":1,"smi2":1,"tns-counter":1,"top100":1,"ulogin":1,"yandex":1},"re":{"adsco":1},"info":{"adxbid":1,"bitrix":1,"navistechnologies":1,"usergram":1,"webantenna":1},"tv":{"affec":1,"attn":1,"iris":1,"ispot":1,"samba":1,"teads":1,"twitch":1},"dev":{"amazon":1},"us":{"amung":1,"samplicio":1,"slgnt":1,"trkn":1},"media":{"andbeyond":1,"nextday":1,"townsquare":1,"underdog":1},"link":{"app":1},"cloud":{"avct":1,"coremedia":1,"egain":1,"matomo":1},"delivery":{"ay":1,"monu":1},"br":{"com":{"btg360":1,"clearsale":1,"jsuol":1,"shopconvert":1,"shoptarget":1,"soclminer":1},"org":{"ivcbrasil":1}},"ch":{"ch":1,"da-services":1,"google":1},"ms":{"clarity":1},"my":{"cnt":1},"se":{"codigo":1},"me":{"contentexchange":1,"grow":1,"line":1,"loopme":1,"t":1,"channel":1},"to":{"cpx":1,"tawk":1},"chat":{"crisp":1,"gorgias":1},"fr":{"d-bi":1,"open-system":1,"weborama":1},"uk":{"co":{"dailymail":1,"hsbc":1}},"id":{"net":{"detik":1}},"ai":{"e-volution":1,"m2":1,"nrich":1,"wknd":1},"be":{"geoedge":1},"au":{"com":{"google":1,"news":1,"nine":1,"realestate":1,"zipmoney":1,"telstra":1}},"stream":{"ibclick":1},"cz":{"imedia":1,"seznam":1,"trackad":1},"app":{"infusionsoft":1,"permutive":1,"shop":1},"tech":{"ingage":1,"primis":1},"eu":{"kameleoon":1,"medallia":1,"media01":1,"ocdn":1,"rqtrk":1,"slgnt":1,"usercentrics":1},"fi":{"kesko":1,"simpli":1},"live":{"lura":1},"services":{"marketingautomation":1},"sg":{"mediacorp":1},"bi":{"newsroom":1},"fm":{"pdst":1},"ad":{"pixel":1},"xyz":{"playground":1},"it":{"plug":1,"repstatic":1,"stbm":1},"cc":{"popin":1},"network":{"pub":1},"nl":{"rijksoverheid":1,"google":1},"fyi":{"sda":1},"pe":{"shop":1},"es":{"socy":1},"im":{"spot":1},"market":{"spotim":1},"am":{"tru":1},"at":{"waust":1},"gov":{"weather":1},"in":{"zoho":1},"ca":{"bc":{"gov":1}},"no":{"acdn":1,"uio":1},"example":{"ad-company":1},"site":{"ad-company":1,"third-party":{"bad":1,"broken":1}},"pw":{"zlp6s":1}} \ No newline at end of file diff --git a/build/windows/contentScope.js b/build/windows/contentScope.js index 362bbbb83..7d8bca8c3 100644 --- a/build/windows/contentScope.js +++ b/build/windows/contentScope.js @@ -86,7 +86,7 @@ * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ - function isThirdParty () { + function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -288,7 +288,7 @@ /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ function processAttr (configSetting, defaultValue) { @@ -449,6 +449,16 @@ * @property {string} sessionKey */ + /** + * Used to inialize extension code in the load phase + */ + function computeLimitedSiteObject () { + const topLevelHostname = getTabHostname(); + return { + domain: topLevelHostname + } + } + /** * Expansion point to add platform specific versioning logic * @param {UserPreferences} preferences @@ -506,16 +516,23 @@ } /** - * @param {{ features: Record; unprotectedTemporary: string[]; }} data + * @typedef RemoteConfig + * @property {Record} features + * @property {string[]} unprotectedTemporary + */ + + /** + * @param {RemoteConfig} data * @param {string[]} userList * @param {UserPreferences} preferences * @param {string[]} platformSpecificFeatures */ function processConfig (data, userList, preferences, platformSpecificFeatures = []) { const topLevelHostname = getTabHostname(); + const site = computeLimitedSiteObject(); const allowlisted = userList.filter(domain => domain === topLevelHostname).length > 0; const remoteFeatureNames = Object.keys(data.features); - const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); + platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); /** @type {Record} */ const output = { ...preferences }; if (output.platform) { @@ -524,37 +541,65 @@ output.platform.version = version; } } + const enabledFeatures = computeEnabledFeatures(data, topLevelHostname, preferences.platform?.version, platformSpecificFeatures); + const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary); + output.site = Object.assign(site, { + isBroken, + allowlisted, + enabledFeatures + }); + // TODO + output.cookie = {}; + + // Copy feature settings from remote config to preferences object + output.featureSettings = parseFeatureSettings(data, enabledFeatures); + output.trackerLookup = {"org":{"cdn77":{"rsc":{"1666210260":1}},"adsrvr":1,"ampproject":1,"browser-update":1,"flowplayer":1,"privacy-center":1,"webvisor":1,"framasoft":1,"do-not-tracker":1,"trackersimulator":1},"io":{"1dmp":1,"1rx":1,"4dex":1,"adnami":1,"aidata":1,"arcspire":1,"bidr":1,"branch":1,"center":1,"concert":1,"connectad":1,"cordial":1,"dcmn":1,"extole":1,"getblue":1,"hbrd":1,"imbox":1,"instana":1,"karte":1,"lytics":1,"marchex":1,"mediago":1,"mrf":1,"myfidevs":1,"narrative":1,"ntv":1,"optad360":1,"oracleinfinity":1,"oribi":1,"p-n":1,"personalizer":1,"pghub":1,"piano":1,"powr":1,"pzz":1,"searchspring":1,"segment":1,"siteimproveanalytics":1,"sjv":1,"sspinc":1,"t13":1,"webgains":1,"wovn":1,"yellowblue":1,"zprk":1,"reviews":1,"appconsent":1,"leadsmonitor":1},"com":{"2020mustang":1,"33across":1,"360yield":1,"3lift":1,"4dsply":1,"4jnzhl0d0":1,"4strokemedia":1,"5d2d04464c":1,"a-mx":1,"a2z":1,"aamsitecertifier":1,"absorbingband":1,"abstractedauthority":1,"abtasty":1,"acexedge":1,"acidpigs":1,"acsbapp":1,"acuityplatform":1,"ad-score":1,"ad-stir":1,"adalyser":1,"adapf":1,"adara":1,"adblade":1,"addthis":1,"addtoany":1,"adelixir":1,"adentifi":1,"adextrem":1,"adgrx":1,"adhese":1,"adition":1,"adkernel":1,"adlightning":1,"adlooxtracking":1,"admanmedia":1,"admedo":1,"adnium":1,"adnxs":1,"adobedtm":1,"adotmob":1,"adpone":1,"adpushup":1,"adroll":1,"adrta":1,"ads-twitter":1,"ads3-adnow":1,"adsafeprotected":1,"adstanding":1,"adswizz":1,"adsymptotic":1,"adtdp":1,"adtechus":1,"adtelligent":1,"adthrive":1,"adtlgc":1,"adtng":1,"adultfriendfinder":1,"advangelists":1,"adventive":1,"advertising":1,"aegpresents":1,"affinity":1,"affirm":1,"agilone":1,"agkn":1,"aimbase":1,"albacross":1,"alcmpn":1,"alexametrics":1,"alicdn":1,"alikeaddition":1,"aliveachiever":1,"aliyuncs":1,"alluringbucket":1,"aloofvest":1,"amazon-adsystem":1,"amazon":1,"amplitude":1,"analytics-egain":1,"aniview":1,"anymind360":1,"amazonaws":{"ap-southeast-2":1,"elb":{"eu-west-2":{"collect-prd-alb-539115803":1},"us-east-1":{"data-allstate-com-715826933":1,"prod-lb-8-1772099769":1,"proxy-mycigna-prod-678433465":1,"www-u45-pnc-com-902993410":1,"www-u46-pnc-com-13593657":1},"eu-west-1":{"devservicesalb-471015105":1,"petfre-content-1201188928":1},"us-east-2":{"elbpiwik-public-1781721271":1},"eu-central-1":{"prod-lb-6-388533732":1,"prod-lb-7-718125029":1,"prod-pub-alb-654989386":1}},"us-east-2":{"s3":{"hb-gretsch-talk":1,"hb-jetpunk":1,"hb-obv2":1}},"eu-central-1":{"s3":{"headless-ssr-prod-bucket":1}}},"app-us1":1,"appboycdn":1,"appdynamics":1,"aralego":1,"arkoselabs":1,"aswpsdkus":1,"atemda":1,"att":1,"attentivemobile":1,"attractionbanana":1,"audioeye":1,"audrte":1,"automaticside":1,"avanser":1,"avmws":1,"aweber":1,"aweprt":1,"azure":1,"b0e8":1,"bagbeam":1,"bandborder":1,"batch":1,"bawdybalance":1,"bc0a":1,"bdstatic":1,"bedsberry":1,"beginnerpancake":1,"benchmarkemail":1,"betweendigital":1,"bfmio":1,"bidderstack":1,"bidtheatre":1,"bimbolive":1,"bing":1,"bizographics":1,"bizrate":1,"bkrtx":1,"blismedia":1,"blogherads":1,"bluecava":1,"bluekai":1,"boatwizard":1,"boilingcredit":1,"boldchat":1,"booking":1,"borderfree":1,"bounceexchange":1,"brainlyads":1,"brand-display":1,"brandmetrics":1,"brealtime":1,"breinify":1,"brightedge":1,"brightfunnel":1,"brightspotcdn":1,"btloader":1,"btstatic":1,"bttrack":1,"btttag":1,"butterbulb":1,"buzzoola":1,"byside":1,"cabnnr":1,"calculatorstatement":1,"callrail":1,"calltracks":1,"capablecup":1,"captcha-delivery":1,"carpentercomparison":1,"cartstack":1,"carvecakes":1,"casalemedia":1,"cdn-btsg":1,"cdnwidget":1,"channeladvisor":1,"chartbeat":1,"chatango":1,"chaturbate":1,"cheqzone":1,"cherriescare":1,"chickensstation":1,"childlikecrowd":1,"childlikeform":1,"cintnetworks":1,"circlelevel":1,"civiccomputing":1,"ck-ie":1,"clcktrax":1,"clearbit":1,"clearbitjs":1,"clickagy":1,"clickcease":1,"clickcertain":1,"clicktripz":1,"clientgear":1,"clksite":1,"cloudflare":1,"cloudflareinsights":1,"cloudflarestream":1,"cloudmaestro":1,"cobaltgroup":1,"cobrowser":1,"cognitivlabs":1,"colossusssp":1,"comm100":1,"googleapis":{"commondatastorage":1,"storage":1},"company-target":1,"condenastdigital":1,"confusedcart":1,"connatix":1,"consentframework":1,"contextweb":1,"conversionruler":1,"convertkit":1,"convertlanguage":1,"cookieinformation":1,"cookiepro":1,"coveo":1,"cpmstar":1,"cquotient":1,"crabbychin":1,"crazyegg":1,"creative-serving":1,"creativecdn":1,"criteo":1,"crowdedmass":1,"crowdriff":1,"crownpeak":1,"crsspxl":1,"ctnsnet":1,"cubchannel":1,"cudasvc":1,"cuddlethehyena":1,"cumbersomecarpenter":1,"curalate":1,"curvedhoney":1,"cutechin":1,"cxense":1,"dailymotion":1,"damdoor":1,"dampdock":1,"dapperfloor":1,"datadoghq-browser-agent":1,"decisivebase":1,"deepintent":1,"defybrick":1,"delivra":1,"demandbase":1,"detectdiscovery":1,"devilishdinner":1,"dimelochat":1,"discreetfield":1,"disqus":1,"dmpxs":1,"dockdigestion":1,"dollardelta":1,"dotomi":1,"doubleverify":1,"drainpaste":1,"dramaticdirection":1,"driftt":1,"dtscdn":1,"dtscout":1,"dwin1":1,"dynamics":1,"dynamicyield":1,"dynatrace":1,"dyntrk":1,"ebaystatic":1,"ecal":1,"eccmp":1,"elasticchange":1,"elfsight":1,"elitrack":1,"eloqua":1,"en25":1,"encouragingthread":1,"ensighten":1,"enviousshape":1,"eqads":1,"ero-advertising":1,"esputnik":1,"evergage":1,"evgnet":1,"exdynsrv":1,"exelator":1,"exoclick":1,"exosrv":1,"expansioneggnog":1,"expertrec":1,"exponea":1,"exponential":1,"extole":1,"ezodn":1,"ezoic":1,"ezoiccdn":1,"facebook":1,"fadewaves":1,"fallaciousfifth":1,"farmergoldfish":1,"fastly-insights":1,"fearlessfaucet":1,"fiftyt":1,"financefear":1,"fitanalytics":1,"five9":1,"fksnk":1,"flashtalking":1,"flipp":1,"floweryflavor":1,"flutteringfireman":1,"flux-cdn":1,"fomo":1,"foresee":1,"forter":1,"fortunatemark":1,"fouanalytics":1,"fox":1,"fqtag":1,"frailfruit":1,"freezingbuilding":1,"fronttoad":1,"fullstory":1,"functionalfeather":1,"fuzzybasketball":1,"gammamaximum":1,"gbqofs":1,"geetest":1,"geistm":1,"geniusmonkey":1,"geoip-js":1,"getbread":1,"getcandid":1,"getclicky":1,"getdrip":1,"getelevar":1,"getpublica":1,"getrockerbox":1,"getshogun":1,"getsitecontrol":1,"glassdoor":1,"gloriousbeef":1,"godpvqnszo":1,"gondolagnome":1,"google-analytics":1,"google":1,"googleadservices":1,"googlehosted":1,"googleoptimize":1,"googlesyndication":1,"googletagmanager":1,"googletagservices":1,"govx":1,"greylabeldelivery":1,"groovehq":1,"gstatic":1,"guarantee-cdn":1,"guiltlessbasketball":1,"gumgum":1,"haltingbadge":1,"hammerhearing":1,"handsomelyhealth":1,"hawksearch":1,"heapanalytics":1,"hellobar":1,"hiconversion":1,"highwebmedia":1,"histats":1,"hlserve":1,"hocgeese":1,"hollowafterthought":1,"honorableland":1,"hotjar":1,"hp":1,"hs-banner":1,"htlbid":1,"htplayground":1,"hubspot":1,"iadvize":1,"ib-ibi":1,"id5-sync":1,"iesnare":1,"igodigital":1,"iheart":1,"iljmp":1,"illiweb":1,"impactcdn":1,"impactradius-event":1,"impactradius-go":1,"impossibleexpansion":1,"impressionmonster":1,"improvedcontactform":1,"improvedigital":1,"imrworldwide":1,"indexww":1,"infolinks":1,"infusionsoft":1,"inmobi":1,"inmoment":1,"inq":1,"inside-graph":1,"instagram":1,"intentiq":1,"intergient":1,"investingchannel":1,"invocacdn":1,"iplsc":1,"ipredictive":1,"iteratehq":1,"ivitrack":1,"j93557g":1,"jaavnacsdw":1,"jimstatic":1,"journity":1,"js7k":1,"juicyads":1,"justanswer":1,"justpremium":1,"kakao":1,"kampyle":1,"kargo":1,"kissmetrics":1,"klarnaservices":1,"klaviyo":1,"knottyswing":1,"kount":1,"krushmedia":1,"ktkjmp":1,"kxcdn":1,"ladesk":1,"ladsp":1,"laughablelizards":1,"leadsrx":1,"lendingtree":1,"levexis":1,"liadm":1,"licdn":1,"lightboxcdn":1,"lijit":1,"linkedin":1,"linksynergy":1,"list-manage":1,"listrakbi":1,"livechatinc":1,"livejasmin":1,"localytics":1,"loggly":1,"loop11":1,"lovelydrum":1,"luckyorange":1,"lunchroomlock":1,"maddeningpowder":1,"mailchimp":1,"mailchimpapp":1,"mailerlite":1,"maillist-manage":1,"marinsm":1,"marketiq":1,"marketo":1,"marriedbelief":1,"matheranalytics":1,"mathtag":1,"maxmind":1,"mczbf":1,"measlymiddle":1,"medallia":1,"media6degrees":1,"mediacategory":1,"mediavine":1,"mediawallahscript":1,"medtargetsystem":1,"megpxs":1,"metricode":1,"metricswpsh":1,"mfadsrvr":1,"mgid":1,"micpn":1,"microadinc":1,"minutemedia-prebid":1,"minutemediaservices":1,"mixpo":1,"mktoresp":1,"mktoweb":1,"ml314":1,"moatads":1,"mobtrakk":1,"monsido":1,"mookie1":1,"mountain":1,"mouseflow":1,"mpeasylink":1,"mql5":1,"mrtnsvr":1,"murdoog":1,"mxpnl":1,"mybestpro":1,"myfinance":1,"myregistry":1,"nappyattack":1,"navistechnologies":1,"neodatagroup":1,"nervoussummer":1,"newrelic":1,"newscgp":1,"nextdoor":1,"ninthdecimal":1,"nitrocdn":1,"noibu":1,"nondescriptnote":1,"nosto":1,"npttech":1,"nuance":1,"nxsttv":1,"omappapi":1,"omnisnippet1":1,"omnisrc":1,"omnitagjs":1,"oneall":1,"onesignal":1,"onetag-sys":1,"oo-syringe":1,"ooyala":1,"opecloud":1,"opentext":1,"opera":1,"opmnstr":1,"optimicdn":1,"optinmonster":1,"optmnstr":1,"optmstr":1,"optnmnstr":1,"optnmstr":1,"oraclecloud":1,"osano":1,"otm-r":1,"outbrain":1,"overconfidentfood":1,"ownlocal":1,"pamelarandom":1,"panickypancake":1,"panoramicplane":1,"parastorage":1,"pardot":1,"parsely":1,"partplanes":1,"patreon":1,"paypal":1,"pbstck":1,"pcmag":1,"peerius":1,"perfdrive":1,"perfectmarket":1,"permutive":1,"picreel":1,"pinimg":1,"pippio":1,"piwikpro":1,"pixlee":1,"pleasantpump":1,"plotrabbit":1,"pluckypocket":1,"pocketfaucet":1,"possibleboats":1,"postaffiliatepro":1,"postrelease":1,"potatoinvention":1,"prepareplanes":1,"pricespider":1,"pricklydebt":1,"profusesupport":1,"proofpoint":1,"protoawe":1,"providesupport":1,"pswec":1,"psyma":1,"ptengine":1,"publir":1,"pubmatic":1,"pubmine":1,"pubnation":1,"puffypurpose":1,"qualaroo":1,"qualtrics":1,"quantcast":1,"quantserve":1,"quantummetric":1,"quietknowledge":1,"quizzicalzephyr":1,"quora":1,"r42tag":1,"railwayreason":1,"rakuten":1,"rambunctiousflock":1,"rangeplayground":1,"realsrv":1,"rebelswing":1,"reconditerake":1,"reconditerespect":1,"recruitics":1,"reddit":1,"redditstatic":1,"rehabilitatereason":1,"reson8":1,"resonantrock":1,"responsiveads":1,"restrainstorm":1,"retargetly":1,"revcontent":1,"rezync":1,"rfihub":1,"rhetoricalloss":1,"richaudience":1,"righteouscrayon":1,"rightfulfall":1,"riotgames":1,"rkdms":1,"rlcdn":1,"rmtag":1,"rncdn5":1,"rnengage":1,"rogersmedia":1,"rokt":1,"route":1,"rubiconproject":1,"s-onetag":1,"saambaa":1,"sablesong":1,"sail-horizon":1,"salesforceliveagent":1,"samestretch":1,"satisfycork":1,"savoryorange":1,"scarabresearch":1,"scaredsnakes":1,"scarfsmash":1,"scatteredstream":1,"scene7":1,"scholarlyiq":1,"scintillatingsilver":1,"scorecardresearch":1,"screechingstove":1,"screenpopper":1,"sddan":1,"sdiapi":1,"seatsmoke":1,"securedvisit":1,"seedtag":1,"sefsdvc":1,"segment":1,"sekindo":1,"selectivesummer":1,"selfishsnake":1,"servebom":1,"servedbyadbutler":1,"servenobid":1,"serverbid":1,"serving-sys":1,"shakegoldfish":1,"shappify":1,"shareaholic":1,"sharethis":1,"sharethrough":1,"shopifyapps":1,"shopperapproved":1,"shrillspoon":1,"sibautomation":1,"sicksmash":1,"sift":1,"siftscience":1,"signifyd":1,"siteimprove":1,"siteimproveanalytics":1,"sitescout":1,"skillfuldrop":1,"sli-spark":1,"slickstream":1,"slopesoap":1,"smadex":1,"smartadserver":1,"smashquartz":1,"smashsurprise":1,"smg":1,"smilewanted":1,"smoggysnakes":1,"snapchat":1,"snapkit":1,"snigelweb":1,"socdm":1,"sojern":1,"songsterritory":1,"sonobi":1,"speedcurve":1,"sphereup":1,"spiceworks":1,"spookyexchange":1,"spookyskate":1,"spookysleet":1,"sportradar":1,"sportradarserving":1,"sportslocalmedia":1,"spotxchange":1,"springserve":1,"srvmath":1,"stackadapt":1,"stakingsmile":1,"statcounter":1,"steadfastseat":1,"steadfastsound":1,"steadfastsystem":1,"steelhousemedia":1,"steepsquirrel":1,"stereoproxy":1,"stereotypedsugar":1,"stickyadstv":1,"stiffgame":1,"straightnest":1,"stripchat":1,"stupendoussleet":1,"stupendoussnow":1,"stupidscene":1,"sulkycook":1,"sumo":1,"sumologic":1,"sundaysky":1,"superficialeyes":1,"superficialsquare":1,"survicate":1,"svonm":1,"symantec":1,"taboola":1,"tagcommander":1,"tailtarget":1,"talkable":1,"taobao":1,"tapad":1,"taptapnetworks":1,"taskanalytics":1,"tealiumiq":1,"technoratimedia":1,"techtarget":1,"tediousticket":1,"teenytinyshirt":1,"tendertest":1,"the-ozone-project":1,"theadex":1,"themoneytizer":1,"theplatform":1,"thestar":1,"thomastorch":1,"threetruck":1,"thrtle":1,"tidaltv":1,"tidiochat":1,"tiktok":1,"tinypass":1,"tiqcdn":1,"tiresomethunder":1,"trackjs":1,"trafficjunky":1,"travelaudience":1,"treasuredata":1,"tremorhub":1,"trendemon":1,"tribalfusion":1,"trovit":1,"trueleadid":1,"truoptik":1,"truste":1,"trustedsite":1,"trustpilot":1,"tsyndicate":1,"tubemogul":1,"turn":1,"tvpixel":1,"tvsquared":1,"tweakwise":1,"twitter":1,"tynt":1,"typicalteeth":1,"u5e":1,"ubembed":1,"uidapi":1,"ultraoranges":1,"unbecominglamp":1,"unbxdapi":1,"undertone":1,"uninterestedquarter":1,"unpkg":1,"unrulymedia":1,"unwieldyhealth":1,"unwieldyplastic":1,"upsellit":1,"urbanairship":1,"usabilla":1,"usbrowserspeed":1,"usemessages":1,"userreport":1,"uservoice":1,"valuecommerce":1,"vengefulgrass":1,"vidazoo":1,"videoplayerhub":1,"vidoomy":1,"viglink":1,"visualwebsiteoptimizer":1,"vivaclix":1,"vk":1,"vlitag":1,"vocento":1,"voicefive":1,"volatilevessel":1,"voraciousgrip":1,"voxmedia":1,"vrtcal":1,"w3counter":1,"walkme":1,"warmafterthought":1,"warmquiver":1,"webcontentassessor":1,"webengage":1,"webeyez":1,"webflow":1,"webtraxs":1,"webtrends-optimize":1,"webtrends":1,"wgplayer":1,"wisepops":1,"worldoftulo":1,"wpadmngr":1,"wpshsdk":1,"wpushsdk":1,"wsod":1,"wt-safetag":1,"wysistat":1,"xg4ken":1,"xiti":1,"xlirdr":1,"xlivrdr":1,"xnxx-cdn":1,"y-track":1,"yahoo":1,"yandex":1,"yieldmo":1,"yieldoptimizer":1,"yimg":1,"yotpo":1,"yottaa":1,"youtube-nocookie":1,"youtube":1,"zatnoh":1,"zemanta":1,"zendesk":1,"zeotap":1,"zeronaught":1,"zestycrime":1,"zonos":1,"zoominfo":1,"zopim":1,"adnxs-simple":1,"createsend1":1,"adventori":1,"facil-iti":1,"provenexpert":1,"veoxa":1,"getflowbox":1,"parchedsofa":1,"adtraction":1,"bannerflow":1,"aboardamusement":1,"absorbingcorn":1,"abstractedamount":1,"actoramusement":1,"actuallysnake":1,"adorableanger":1,"agreeabletouch":1,"aheadday":1,"ancientact":1,"annoyedairport":1,"annoyingacoustics":1,"aquaticowl":1,"aspiringattempt":1,"audioarctic":1,"awarealley":1,"awesomeagreement":1,"awzbijw":1,"basketballbelieve":1,"begintrain":1,"bestboundary":1,"blushingbeast":1,"boredcrown":1,"breadbalance":1,"breakfastboat":1,"bulbbait":1,"burnbubble":1,"bustlingbath":1,"callousbrake":1,"calmcactus":1,"capriciouscorn":1,"caringcast":1,"catschickens":1,"causecherry":1,"chunkycactus":1,"cloisteredcord":1,"closedcows":1,"colossalclouds":1,"colossalcoat":1,"comfortablecheese":1,"conditioncrush":1,"consciouscheese":1,"consciousdirt":1,"coverapparatus":1,"cratecamera":1,"critictruck":1,"curvycry":1,"cushionpig":1,"damageddistance":1,"debonairdust":1,"decisivedrawer":1,"decisiveducks":1,"detailedkitten":1,"diplomahawaii":1,"dk4ywix":1,"dq95d35":1,"energeticladybug":1,"enormousearth":1,"evanescentedge":1,"fadedsnow":1,"fancyactivity":1,"farshake":1,"fastenfather":1,"fatcoil":1,"faultycanvas":1,"firstfrogs":1,"flimsycircle":1,"flimsythought":1,"friendwool":1,"fumblingform":1,"futuristicfifth":1,"giddycoat":1,"giraffepiano":1,"glisteningguide":1,"grayreceipt":1,"greasysquare":1,"grouchypush":1,"haltinggold":1,"handyfield":1,"handyfireman":1,"hearthorn":1,"historicalbeam":1,"horsenectar":1,"hystericalcloth":1,"impulsejewel":1,"incompetentjoke":1,"internalsink":1,"lameletters":1,"livelumber":1,"livelylaugh":1,"lorenzourban":1,"lumpylumber":1,"maliciousmusic":1,"meatydime":1,"memorizeneck":1,"mightyspiders":1,"mixedreading":1,"modularmental":1,"motionlessbag":1,"movemeal":1,"nondescriptcrowd":1,"nostalgicneed":1,"nuttyorganization":1,"optimallimit":1,"outstandingincome":1,"outstandingsnails":1,"panickycurtain":1,"petiteumbrella":1,"placidperson":1,"plantdigestion":1,"punyplant":1,"rabbitbreath":1,"rabbitrifle":1,"raintwig":1,"rainyhand":1,"rainyrule":1,"rangecake":1,"raresummer":1,"readymoon":1,"rebelsubway":1,"receptivereaction":1,"regularplants":1,"repeatsweater":1,"replaceroute":1,"resonantbrush":1,"respectrain":1,"richstring":1,"roofrelation":1,"rusticprice":1,"scaredcomfort":1,"scaredsnake":1,"scientificshirt":1,"scintillatingscissors":1,"screechingfurniture":1,"seashoresociety":1,"secretturtle":1,"shakysurprise":1,"shallowblade":1,"shesubscriptions":1,"shockingship":1,"sillyscrew":1,"sincerebuffalo":1,"sinceresubstance":1,"singroot":1,"sixscissors":1,"soggysponge":1,"somberscarecrow":1,"sordidsmile":1,"sortsail":1,"sortsummer":1,"spellsalsa":1,"spotlessstamp":1,"spottednoise":1,"stalesummer":1,"steadycopper":1,"stepplane":1,"strangesink":1,"stretchsister":1,"strivesidewalk":1,"superficialspring":1,"swellstocking":1,"synonymousrule":1,"tangyamount":1,"tastelesstrees":1,"teenytinycellar":1,"teenytinytongue":1,"terriblethumb":1,"terrifictooth":1,"thirdrespect":1,"ticketaunt":1,"tremendousplastic":1,"troubledtail":1,"typicalairplane":1,"ubiquitousyard":1,"unbecominghall":1,"uncoveredexpert":1,"unequalbrake":1,"unknowncrate":1,"untidyrice":1,"unusedstone":1,"venusgloria":1,"verdantanswer":1,"verseballs":1,"wearbasin":1,"cautiouscredit":1,"confesschairs":1,"chinsnakes":1,"wellgroomedhydrant":1,"heavyplayground":1,"bravecalculator":1,"workoperation":1,"secondhandfall":1,"unablehope":1,"tastelesstrucks":1,"losslace":1,"barbarousbase":1,"supportwaves":1,"protestcopy":1,"automaticturkey":1,"stretchsquirrel":1,"equablekettle":1,"discreetquarter":1,"peacefullimit":1,"gulliblegrip":1,"swelteringsleep":1,"muteknife":1,"aliasanvil":1,"operationchicken":1,"courageousbaby":1,"flowerstreatment":1,"scissorsstatement":1,"furryfork":1,"synonymoussticks":1,"deerbeginner":1,"rhetoricalveil":1,"farsnails":1,"kaputquill":1,"digestiondrawer":1,"meltmilk":1,"endurablebulb":1,"sugarfriction":1,"combcompetition":1,"stakingshock":1,"stretchsneeze":1,"sinkbooks":1,"brotherslocket":1,"cautiouscamera":1,"materialparcel":1,"inputicicle":1,"chargecracker":1,"fewjuice":1,"tumbleicicle":1,"serpentshampoo":1,"nutritiousbean":1,"scrapesleep":1,"bleachbubble":1,"longingtrees":1,"leftliquid":1,"handsomehose":1,"powerfulcopper":1,"painstakingpickle":1,"swankysquare":1,"soundstocking":1,"disagreeabledrop":1,"cushiondrum":1,"ruralrobin":1,"gorgeousedge":1,"strivesquirrel":1,"currentcollar":1,"combativecar":1,"ambiguousafternoon":1,"harborcaption":1,"blushingbread":1,"suggestionbridge":1,"spectacularstamp":1,"skisofa":1,"predictplate":1,"shakyseat":1,"priceypies":1,"livelyreward":1,"stealsteel":1,"shiveringspot":1,"memorizematch":1,"knitstamp":1,"bushesbag":1,"mundanenail":1,"coldbalance":1,"shapecomb":1,"shiverscissors":1,"broadborder":1,"quirkysugar":1,"stingyspoon":1,"billowybelief":1,"crookedcreature":1,"acceptableauthority":1,"sadloaf":1,"separatesort":1,"pailpatch":1,"scribblestring":1,"exhibitsneeze":1,"largebrass":1,"combcattle":1,"materialisticmoon":1,"fixedfold":1,"restructureinvention":1,"scaredstomach":1,"cautiouscherries":1,"tritebadge":1,"motionflowers":1,"ballsbanana":1,"meddleplant":1,"simulateswing":1,"marketspiders":1,"grumpydime":1,"neatshade":1,"samplesamba":1,"samesticks":1,"buttonladybug":1,"mentorsticks":1,"scaredsong":1,"annoyingclover":1,"grainmass":1,"tempertrick":1,"quizzicalpartner":1,"franticroof":1,"cattlecommittee":1,"tangycover":1,"looseloaf":1,"psychedelicarithmetic":1,"radiateprose":1,"shamerain":1,"cleanhaircut":1,"badgevolcano":1,"laboredlocket":1,"zipperxray":1,"stingycrush":1,"sixauthority":1,"thinkitten":1,"strokesystem":1,"hatefulrequest":1},"net":{"2mdn":1,"2o7":1,"incapdns":{"x":{"3exvfbh":1,"5t48cjc":1,"7xjpy4d":1,"dzm868l":1,"ttk8bbo":1}},"3gl":1,"a-mo":1,"acint":1,"adform":1,"adhigh":1,"admixer":1,"adobedc":1,"adspeed":1,"azureedge":{"adv-cloudfilse":1,"afw-static":1,"bayleys-pri-cdn-endpoint":1,"cdne-nxtevo-prd01-ms":1,"discountcodeexpress":1,"fp-cdn":1,"lefigaro":1,"ocpd-content":1,"sdtagging":1,"trenord-europe-trenord-endpoint-prd":1},"adverticum":1,"edgekey":{"akamai-111035":1,"com":{"alicdn":1,"ebay":1,"mtvnservices":1,"nbcuni":1,"nintendo":1,"oneindia":1,"scene7":1,"turner":1,"ziffdavis":1,"ziffdavisinternational":1},"ame":1,"au":1,"br":1,"ca":1,"com-v1":1,"com-v2":1,"gov":1,"in":1,"io":1,"it":1,"net":1,"org":1,"ppll":1,"rakuten":1,"uk":1},"apicit":1,"appier":1,"akamaized":{"assets-momentum":1,"com":{"media-rockstargames-":1,"ntd":1,"vocento":1}},"aticdn":1,"azure":1,"azurefd":1,"bannerflow":1,"bf-tools":1,"bidswitch":1,"bitsngo":1,"blueconic":1,"boldapps":1,"buysellads":1,"cedexis":1,"certona":1,"fastly":{"map":{"cidgroup":1,"condenast":1,"ihrinferno":1,"prisa-us-eu":1,"scribd":1,"target-opus":1,"thriftbooks":1,"ticketmaster4":1,"twitch":1,"vox":1,"appnexus":1},"global":{"shared":{"d2":1,"s2":1},"sni":{"j":1}},"ssl":{"global":{"igao-prod-herokuapp-com":1,"mslc-prod-herokuapp-com":1}}},"confiant-integrations":1,"consentmanager":1,"contentsquare":1,"criteo":1,"crwdcntrl":1,"cloudfront":{"d16jny3kjm2a1j":1,"d16kgn4efacaad":1,"d19l6uotjzm32g":1,"d1af033869koo7":1,"d1bxz6tua5hq87":1,"d1cr9zxt7u0sgu":1,"d1egjda7ggd2ew":1,"d1eh9yux7w8iql":1,"d1gwclp1pmzk26":1,"d1nhstnts0iwzs":1,"d1p5cqqchvbqmy":1,"d1pq45hly7zfel":1,"d1rhs7mhgydok3":1,"d1rw50yn65615p":1,"d1s87id6169zda":1,"d1snv67wdds0p2":1,"d1tprjo2w7krrh":1,"d1vg5xiq7qffdj":1,"d1vo8zfysxy97v":1,"d1y068gyog18cq":1,"d214hhm15p4t1d":1,"d21gpk1vhmjuf5":1,"d244lyzgucnepm":1,"d27cwqlgojh9yd":1,"d2aioe7l2jay46":1,"d2bj4wnxqmm2tk":1,"d2droglu4qf8st":1,"d2eanzqpmoo3ec":1,"d2f4zoo8hyailp":1,"d2hs2r19gv871k":1,"d2j6syf6c0cltf":1,"d2jpq2u2vrjftk":1,"d2qlgd5odkppg5":1,"d2qrdklrsxowl2":1,"d2s6j0ghajv79z":1,"d2tyltutevw8th":1,"d2wo2i8fdcw8of":1,"d2xbocf5uqnw0w":1,"d2y7rifa1cwopa":1,"d2zah9y47r7bi2":1,"d30jydkdo8eo9b":1,"d355prp56x5ntt":1,"d35mt2i8wrf9y1":1,"d38aqfmkl3ge26":1,"d38xvr37kwwhcm":1,"d3fv2pqyjay52z":1,"d3gxe0jmvtuxbc":1,"d3i4yxtzktqr9n":1,"d3jruqy3qmm3fd":1,"d3nn82uaxijpm6":1,"d3o8vwpyaorolj":1,"d3ochae1kou2ub":1,"d3odp2r1osuwn0":1,"d3owq2fdwtdp2j":1,"d3txh7prdum3s8":1,"d3v7mj6iyaqfac":1,"d4egga2bwam6h":1,"d5yoctgpv4cpx":1,"d6tizftlrpuof":1,"d9k0w0y3delq8":1,"dbukjj6eu5tsf":1,"de2pmm85odupd":1,"de7iszmjjjuya":1,"dfx0d9twj2ai":1,"dj28g4s0yd4ph":1,"dn0qt3r0xannq":1,"dokumfe7mps0i":1,"dowpznhhyvkm4":1,"dsh7ky7308k4b":1,"dsx863kqtdxrt":1,"dtpw88eywzb7u":1,"duube1y6ojsji":1,"dzlkq6toxiazj":1,"dzz1zjxa9ulpk":1,"d2638j3z8ek976":1},"akadns":{"com":{"dellcdn":1,"febsec-fidelity":1},"line-zero":1},"demdex":1,"dotmetrics":1,"doubleclick":1,"durationmedia":1,"e-planning":1,"edgecastcdn":1,"emsecure":1,"episerver":1,"esm1":1,"eulerian":1,"everestjs":1,"everesttech":1,"eyeota":1,"ezoic":1,"facebook":1,"fastclick":1,"fbcdn":1,"fonts":1,"edgesuite":{"com":{"fox":1,"iq":1,"tiktokcdn-us":1,"vidio":1,"sky":1},"linkedin":1,"stls":1},"fuseplatform":1,"fwmrm":1,"go-mpulse":1,"hadronid":1,"hs-analytics":1,"hsleadflows":1,"im-apps":1,"impervadns":1,"iocnt":1,"iprom":1,"jsdelivr":1,"kanade-ad":1,"azurewebsites":{"keha-matomo-te-palvelut-prod":1,"neuterbot-client":1,"app-ch-sgtm-prod":1,"app-fnsp-matomo-analytics-prod":1},"krxd":1,"line-scdn":1,"listhub":1,"livecom":1,"livedoor":1,"liveperson":1,"lkqd":1,"llnwd":1,"lpsnmedia":1,"magnetmail":1,"marketo":1,"maxymiser":1,"media":1,"microad":1,"monetate":1,"mxptint":1,"myfonts":1,"myvisualiq":1,"naver":1,"b-cdn":{"nnwwwlive":1,"speedy":1},"nr-data":1,"omtrdc":1,"onecount":1,"online-metrix":1,"openx":1,"opta":1,"owneriq":1,"pages02":1,"pages03":1,"pages04":1,"pages05":1,"pages06":1,"pages08":1,"perimeterx":1,"pingdom":1,"pmdstatic":1,"popads":1,"popcash":1,"primecaster":1,"pro-market":1,"px-cloud":1,"akamaihd":{"pxlclnmdecom-a":1},"r9cdn":1,"rfihub":1,"sancdn":1,"sc-static":1,"semasio":1,"sensic":1,"trafficmanager":{"serviceschipotlecom":1},"sexad":1,"smaato":1,"spreadshirts":1,"storygize":1,"tfaforms":1,"trackcmp":1,"trackedlink":1,"truste-svc":1,"uuidksinc":1,"viafoura":1,"visilabs":1,"visx":1,"w55c":1,"wdsvc":1,"witglobal":1,"yandex":1,"yastatic":1,"yieldlab":1,"ywxi":1,"zdbb":1,"zencdn":1,"zucks":1,"eviltracker":1},"co":{"6sc":1,"ayads":1,"datadome":1,"idio":1,"increasingly":1,"jads":1,"nanorep":1,"nc0":1,"pcdn":1,"prmutv":1,"resetdigital":1,"t":1,"tctm":1,"zip":1},"de":{"71i":1,"adscale":1,"auswaertiges-amt":1,"fiduciagad":1,"ioam":1,"itzbund":1,"werk21system":1},"gt":{"ad":1},"jp":{"adingo":1,"admatrix":1,"auone":1,"co":{"dmm":1,"google":1,"rakuten":1,"yahoo":1},"fout":1,"gmossp-sp":1,"gssprt":1,"ne":{"hatena":1},"impact-ad":1,"microad":1,"nakanohito":1,"ptengine":1,"r10s":1,"reemo-ad":1,"rtoaster":1,"shinobi":1,"team-rec":1,"uncn":1,"yimg":1,"yjtag":1},"pl":{"adocean":1,"dreamlab":1,"gemius":1,"nsaudience":1,"onet":1,"salesmanago":1,"wp":1},"pro":{"adpartner":1,"piwik":1,"usocial":1},"ru":{"adriver":1,"digitaltarget":1,"mail":1,"mindbox":1,"rambler":1,"sape":1,"smi2":1,"tns-counter":1,"top100":1,"ulogin":1,"yandex":1},"re":{"adsco":1},"info":{"adxbid":1,"bitrix":1,"navistechnologies":1,"usergram":1,"webantenna":1},"tv":{"affec":1,"attn":1,"iris":1,"ispot":1,"samba":1,"teads":1,"twitch":1},"dev":{"amazon":1},"us":{"amung":1,"samplicio":1,"slgnt":1,"trkn":1},"media":{"andbeyond":1,"nextday":1,"townsquare":1,"underdog":1},"link":{"app":1},"cloud":{"avct":1,"coremedia":1,"egain":1,"matomo":1},"delivery":{"ay":1,"monu":1},"br":{"com":{"btg360":1,"clearsale":1,"jsuol":1,"shopconvert":1,"shoptarget":1,"soclminer":1},"org":{"ivcbrasil":1}},"ch":{"ch":1,"da-services":1,"google":1},"ms":{"clarity":1},"my":{"cnt":1},"se":{"codigo":1},"me":{"contentexchange":1,"grow":1,"line":1,"loopme":1,"t":1,"channel":1},"to":{"cpx":1,"tawk":1},"chat":{"crisp":1,"gorgias":1},"fr":{"d-bi":1,"open-system":1,"weborama":1},"uk":{"co":{"dailymail":1,"hsbc":1}},"id":{"net":{"detik":1}},"ai":{"e-volution":1,"m2":1,"nrich":1,"wknd":1},"be":{"geoedge":1},"au":{"com":{"google":1,"news":1,"nine":1,"realestate":1,"zipmoney":1,"telstra":1}},"stream":{"ibclick":1},"cz":{"imedia":1,"seznam":1,"trackad":1},"app":{"infusionsoft":1,"permutive":1,"shop":1},"tech":{"ingage":1,"primis":1},"eu":{"kameleoon":1,"medallia":1,"media01":1,"ocdn":1,"rqtrk":1,"slgnt":1,"usercentrics":1},"fi":{"kesko":1,"simpli":1},"live":{"lura":1},"services":{"marketingautomation":1},"sg":{"mediacorp":1},"bi":{"newsroom":1},"fm":{"pdst":1},"ad":{"pixel":1},"xyz":{"playground":1},"it":{"plug":1,"repstatic":1,"stbm":1},"cc":{"popin":1},"network":{"pub":1},"nl":{"rijksoverheid":1,"google":1},"fyi":{"sda":1},"pe":{"shop":1},"es":{"socy":1},"im":{"spot":1},"market":{"spotim":1},"am":{"tru":1},"at":{"waust":1},"gov":{"weather":1},"in":{"zoho":1},"ca":{"bc":{"gov":1}},"no":{"acdn":1,"uio":1},"example":{"ad-company":1},"site":{"ad-company":1,"third-party":{"bad":1,"broken":1}},"pw":{"zlp6s":1}}; + + return output + } + + /** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ + function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features); + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)); const enabledFeatures = remoteFeatureNames.filter((featureName) => { const feature = data.features[featureName]; // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion - if (feature.minSupportedVersion && preferences.platform?.version) { - if (!isSupportedVersion(feature.minSupportedVersion, preferences.platform.version)) { + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { return false } } return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) }).concat(platformSpecificFeaturesNotInRemoteConfig); // only disable platform specific features if it's explicitly disabled in remote config - const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary); - output.site = { - domain: topLevelHostname, - isBroken, - allowlisted, - enabledFeatures - }; - // TODO - output.cookie = {}; + return enabledFeatures + } - // Copy feature settings from remote config to preferences object - output.featureSettings = {}; + /** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ + function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {}; + const remoteFeatureNames = Object.keys(data.features); remoteFeatureNames.forEach((featureName) => { if (!enabledFeatures.includes(featureName)) { return } - output.featureSettings[featureName] = data.features[featureName].settings; + featureSettings[featureName] = data.features[featureName].settings; }); - - return output + return featureSettings } function isGloballyDisabled (args) { @@ -1136,13 +1181,43 @@ return parseJSONPointer(fromPointer); } + /** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + + /** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName; - this._args = null; + this.#args = null; this.monitor = new PerformanceMonitor(); } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -1155,6 +1230,34 @@ return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -1171,10 +1274,11 @@ /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting(); + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName); if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -1194,17 +1298,22 @@ return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name); - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name); + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName); + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName); return result === 'enabled' } @@ -1213,9 +1322,11 @@ * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain; + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || []; return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -1225,7 +1336,7 @@ callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit'); - this._args = args; + this.#args = args; this.platform = args.platform; this.init(args); mark.end(); @@ -1238,14 +1349,23 @@ callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad'); - this._args = args; + this.#args = args; this.platform = args.platform; + this.#bundledConfig = args.bundledConfig; + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version); + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures); + } + this.#trackerLookup = args.trackerLookup; + this.#documentOriginIsTracker = args.documentOriginIsTracker; this.load(args); mark.end(); } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll(); } } @@ -1317,15 +1437,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property]; + let targetOut = target; + if (typeof property === 'string' && property in outputs) { + targetOut = outputs; + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -1382,7 +1504,6 @@ function wrapScriptCodeOverload (code, config) { const processedConfig = {}; for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value); } // Don't do anything if the config is empty @@ -1464,7 +1585,9 @@ // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -1688,6 +1811,13 @@ return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -1697,6 +1827,13 @@ return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -4104,6 +4241,34 @@ } } + /** + * Check if the current document origin is on the tracker list, using the provided lookup trie. + * @param {object} trackerLookup Trie lookup of tracker domains + * @returns {boolean} True iff the origin is a tracker. + */ + function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { + const parts = originHostname.split('.').reverse(); + let node = trackerLookup; + for (const sub of parts) { + if (node[sub] === 1) { + return true + } else if (node[sub]) { + node = node[sub]; + } else { + return false + } + } + return false + } + + /** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ + // Initial cookie policy pre init let cookiePolicy = { debug: false, @@ -4112,12 +4277,18 @@ shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) }; + let trackerLookup = {}; let loadedPolicyResolve; @@ -4137,6 +4308,9 @@ }); } + /** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -4145,26 +4319,45 @@ return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } + /** + * @param {Set} scriptOrigins + * @returns {boolean} + */ + function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false; + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup, scriptOrigin)) { + matched = true; + } + } + return matched + } + + /** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true; } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup = this.trackerLookup; + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie; + const { exceptions, settings } = this.bundledConfig.features.cookie; const tabHostname = getTabHostname(); let tabExempted = true; @@ -4178,6 +4371,10 @@ }); cookiePolicy.shouldBlock = !frameExempted && !tabExempted; cookiePolicy.policy = settings.firstPartyCookiePolicy; + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy; + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || []; } // The cookie policy is injected into every frame immediately so that no cookie will @@ -4238,20 +4435,20 @@ try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy; + const { shouldBlock, policy, trackerPolicy } = cookiePolicy; + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy; if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext); return } - // extract cookie expiry from cookie string const cookie = new Cookie(value); // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge; + cookie.maxAge = chosenPolicy.maxAge; debugHelper('restrict', 'expiry', setCookieContext); @@ -4279,19 +4476,23 @@ } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + }; + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie; - args.cookie.debug = args.debug; - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie'); - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie'); - const policy = this.getFeatureSetting('firstPartyCookiePolicy'); - if (policy) { - cookiePolicy.policy = policy; - } + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie); + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy + }; } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false; + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy); } loadedPolicyResolve(); @@ -4573,31 +4774,41 @@ } } + function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }); + } catch { + // todo: Just ignore this exception? + } + } + class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }); - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args); } } + + init (args) { + injectNavigatorInterface(args); + } } let adLabelStrings = []; @@ -6800,7 +7011,7 @@ title: 'Tired of targeted YouTube ads and recommendations?' }, videoOverlaySubtitle: { - title: 'Duck Player provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' + title: 'provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' }, videoButtonOpen: { title: 'Watch in Duck Player' @@ -6831,6 +7042,75 @@ } }; + /** + * The following code is originally from https://github.com/mozilla-extensions/secure-proxy/blob/db4d1b0e2bfe0abae416bf04241916f9e4768fd2/src/commons/template.js + */ + class Template { + constructor (strings, values) { + this.values = values; + this.strings = strings; + } + + /** + * Escapes any occurrences of &, ", <, > or / with XML entities. + * + * @param {string} str + * The string to escape. + * @return {string} The escaped string. + */ + escapeXML (str) { + const replacements = { + '&': '&', + '"': '"', + "'": ''', + '<': '<', + '>': '>', + '/': '/' + }; + return String(str).replace(/[&"'<>/]/g, m => replacements[m]) + } + + potentiallyEscape (value) { + if (typeof value === 'object') { + if (value instanceof Array) { + return value.map(val => this.potentiallyEscape(val)).join('') + } + + // If we are an escaped template let join call toString on it + if (value instanceof Template) { + return value + } + + throw new Error('Unknown object to escape') + } + return this.escapeXML(value) + } + + toString () { + const result = []; + + for (const [i, string] of this.strings.entries()) { + result.push(string); + if (i < this.values.length) { + result.push(this.potentiallyEscape(this.values[i])); + } + } + return result.join('') + } + } + + function html (strings, ...values) { + return new Template(strings, values) + } + + /** + * @param {string} string + * @return {Template} + */ + function trustedUnsafe (string) { + return html([string]) + } + const IconOverlay = { /** * Special class used for the overlay hover. For hovering, we use a @@ -6869,20 +7149,20 @@ overlayElement.setAttribute('class', 'ddg-overlay' + (extraClass ? ' ' + extraClass : '')); overlayElement.setAttribute('data-size', size); - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax); + overlayElement.innerHTML = html`
- ${dax} + ${svgIcon}
${i18n.t('playText')}
-
`; + `.toString(); overlayElement.querySelector('a.ddg-play-privately')?.setAttribute('href', href); - overlayElement.querySelector('a.ddg-play-privately')?.addEventListener('click', (event) => { event.preventDefault(); event.stopPropagation(); @@ -7213,12 +7493,15 @@ createOverlay () { const overlayElement = document.createElement('div'); overlayElement.classList.add('ddg-video-player-overlay'); - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax); + overlayElement.innerHTML = html`
-
${dax}
+
${svgIcon}
${i18n.t('videoOverlayTitle')}
-
${i18n.t('videoOverlaySubtitle')}
+
+ ${i18n.t('playText')} ${i18n.t('videoOverlaySubtitle')} +
${i18n.t('videoButtonOpen')} @@ -7229,7 +7512,7 @@
- `; + `.toString(); /** * Set the link * @type {string} @@ -7997,7 +8280,7 @@ if (this.platform.name === 'windows') { const context = new MessagingContext({ context: 'contentScopeScripts', - env: this._args.debug ? 'development' : 'production', + env: this.isDebug ? 'development' : 'production', featureName: this.name }); const config = new WindowsMessagingConfig({ @@ -8082,12 +8365,14 @@ /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** @@ -8162,7 +8447,10 @@ } load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }); init(processedConfig); diff --git a/build/windows/pages/duckplayer/js/index.js b/build/windows/pages/duckplayer/js/index.js index e4fa7a4da..ec07acf84 100644 --- a/build/windows/pages/duckplayer/js/index.js +++ b/build/windows/pages/duckplayer/js/index.js @@ -725,6 +725,57 @@ } }; + // ../../src/dom-utils.js + var Template = class { + constructor(strings, values) { + this.values = values; + this.strings = strings; + } + /** + * Escapes any occurrences of &, ", <, > or / with XML entities. + * + * @param {string} str + * The string to escape. + * @return {string} The escaped string. + */ + escapeXML(str) { + const replacements = { + "&": "&", + '"': """, + "'": "'", + "<": "<", + ">": ">", + "/": "/" + }; + return String(str).replace(/[&"'<>/]/g, (m) => replacements[m]); + } + potentiallyEscape(value) { + if (typeof value === "object") { + if (value instanceof Array) { + return value.map((val) => this.potentiallyEscape(val)).join(""); + } + if (value instanceof Template) { + return value; + } + throw new Error("Unknown object to escape"); + } + return this.escapeXML(value); + } + toString() { + const result = []; + for (const [i, string] of this.strings.entries()) { + result.push(string); + if (i < this.values.length) { + result.push(this.potentiallyEscape(this.values[i])); + } + } + return result.join(""); + } + }; + function html(strings, ...values) { + return new Template(strings, values); + } + // pages/duckplayer/src/js/index.js var VideoPlayer = { /** @@ -783,7 +834,7 @@ * Show an error instead of the video player iframe */ showVideoError: (errorMessage) => { - VideoPlayer.playerContainer().innerHTML = '
ERROR:
'; + VideoPlayer.playerContainer().innerHTML = html`
ERROR:
`.toString(); document.querySelector(".player-error-message").textContent = errorMessage; }, /** diff --git a/inject/android.js b/inject/android.js index 6fe51fda7..8c30c465c 100644 --- a/inject/android.js +++ b/inject/android.js @@ -4,6 +4,7 @@ */ import { load, init, update } from '../src/content-scope-features.js' import { processConfig, isGloballyDisabled } from './../src/utils' +import { isTrackerOrigin } from '../src/trackers' const allowedMessages = [ 'getClickToLoadState', @@ -22,7 +23,10 @@ function initCode () { } load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }) const messageSecret = processedConfig.messageSecret diff --git a/inject/apple.js b/inject/apple.js index c87267744..23e06eddd 100644 --- a/inject/apple.js +++ b/inject/apple.js @@ -4,6 +4,7 @@ */ import { load, init } from '../src/content-scope-features.js' import { processConfig, isGloballyDisabled } from './../src/utils' +import { isTrackerOrigin } from '../src/trackers' function initCode () { // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f @@ -13,7 +14,10 @@ function initCode () { } load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }) init(processedConfig) diff --git a/inject/chrome-mv3.js b/inject/chrome-mv3.js index e2a3a4b70..01a887f22 100644 --- a/inject/chrome-mv3.js +++ b/inject/chrome-mv3.js @@ -4,15 +4,19 @@ */ import { load, init, update } from '../src/content-scope-features.js' import { isTrackerOrigin } from '../src/trackers' +import { computeLimitedSiteObject } from '../src/utils.js' const secret = (crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32).toString().replace('0.', '') +const trackerLookup = import.meta.trackerLookup + load({ platform: { name: 'extension' }, - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - documentOriginIsTracker: isTrackerOrigin($TRACKER_LOOKUP$), + trackerLookup, + documentOriginIsTracker: isTrackerOrigin(trackerLookup), + site: computeLimitedSiteObject(), // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f bundledConfig: $BUNDLED_CONFIG$ }) diff --git a/inject/chrome.js b/inject/chrome.js index fe44be601..d70b6b610 100644 --- a/inject/chrome.js +++ b/inject/chrome.js @@ -3,6 +3,7 @@ * @category Content Scope Scripts Integrations */ import { isTrackerOrigin } from '../src/trackers' +import { computeLimitedSiteObject } from '../src/utils' /** * Inject all the overwrites into the page. @@ -38,20 +39,23 @@ function randomString () { } function init () { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - const documentOriginIsTracker = isTrackerOrigin($TRACKER_LOOKUP$) + const trackerLookup = import.meta.trackerLookup + const documentOriginIsTracker = isTrackerOrigin(trackerLookup) // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f const bundledConfig = $BUNDLED_CONFIG$ const randomMethodName = '_d' + randomString() const randomPassword = '_p' + randomString() const reusableMethodName = '_rm' + randomString() const reusableSecret = '_r' + randomString() + const siteObject = computeLimitedSiteObject() const initialScript = ` /* global contentScopeFeatures */ contentScopeFeatures.load({ platform: { name: 'extension' }, + trackerLookup: ${JSON.stringify(trackerLookup)}, + site: ${JSON.stringify(siteObject)}, documentOriginIsTracker: ${documentOriginIsTracker}, bundledConfig: ${JSON.stringify(bundledConfig)} }) diff --git a/inject/integration.js b/inject/integration.js index ffe720072..1dbe950e2 100644 --- a/inject/integration.js +++ b/inject/integration.js @@ -1,4 +1,5 @@ import { load, init } from '../src/content-scope-features.js' +import { isTrackerOrigin } from '../src/trackers' function getTopLevelURL () { try { // FROM: https://stackoverflow.com/a/7739035/73479 @@ -15,6 +16,7 @@ function getTopLevelURL () { function generateConfig (data, userList) { const topLevelUrl = getTopLevelURL() + const trackerLookup = import.meta.trackerLookup return { debug: false, sessionKey: 'randomVal', @@ -30,7 +32,8 @@ function generateConfig (data, userList) { 'fingerprintingScreenSize', 'navigatorInterface' ] - } + }, + trackerLookup } } @@ -71,7 +74,10 @@ async function initCode () { const processedConfig = generateConfig() load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }) // mark this phase as loaded diff --git a/inject/mozilla.js b/inject/mozilla.js index ba0dc5049..364598f15 100644 --- a/inject/mozilla.js +++ b/inject/mozilla.js @@ -4,6 +4,7 @@ */ import { load, init, update } from '../src/content-scope-features.js' import { isTrackerOrigin } from '../src/trackers' +import { computeLimitedSiteObject } from '../src/utils.js' const allowedMessages = [ 'getClickToLoadState', @@ -21,12 +22,14 @@ function randomString () { } function initCode () { + const trackerLookup = import.meta.trackerLookup load({ platform: { name: 'extension' }, - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - documentOriginIsTracker: isTrackerOrigin($TRACKER_LOOKUP$), + trackerLookup, + documentOriginIsTracker: isTrackerOrigin(trackerLookup), + site: computeLimitedSiteObject(), // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f bundledConfig: $BUNDLED_CONFIG$ }) diff --git a/inject/windows.js b/inject/windows.js index 45b6b5dba..a508aa6ea 100644 --- a/inject/windows.js +++ b/inject/windows.js @@ -4,6 +4,7 @@ */ import { load, init } from '../src/content-scope-features.js' import { processConfig, isGloballyDisabled, windowsSpecificFeatures } from './../src/utils' +import { isTrackerOrigin } from '../src/trackers' function initCode () { // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f @@ -13,7 +14,10 @@ function initCode () { } load({ - platform: processedConfig.platform + platform: processedConfig.platform, + trackerLookup: processedConfig.trackerLookup, + documentOriginIsTracker: isTrackerOrigin(processedConfig.trackerLookup), + site: processedConfig.site }) init(processedConfig) diff --git a/integration-test/playwright/page-objects/duckplayer-overlays.js b/integration-test/playwright/page-objects/duckplayer-overlays.js index a8f422b71..718e39e97 100644 --- a/integration-test/playwright/page-objects/duckplayer-overlays.js +++ b/integration-test/playwright/page-objects/duckplayer-overlays.js @@ -58,6 +58,9 @@ export class DuckplayerOverlays { async overlayBlocksVideo () { await this.page.locator('ddg-video-overlay').waitFor({ state: 'visible', timeout: 1000 }) await this.page.getByRole('link', { name: 'Watch in Duck Player' }).waitFor({ state: 'visible', timeout: 1000 }) + await this.page + .getByText('Duck Player provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.') + .waitFor({ timeout: 100 }) } async smallOverlayShows () { diff --git a/integration-test/test-pages.js b/integration-test/test-pages.js index dc3ff83cb..b063ffad4 100644 --- a/integration-test/test-pages.js +++ b/integration-test/test-pages.js @@ -21,7 +21,7 @@ describe('Test integration pages', () => { await teardown() }) - it('Script that should not execute', async () => { + it('Should be successful page script check', async () => { const pages = { 'runtime-checks/pages/basic-run.html': 'runtime-checks/config/basic-run.json', 'runtime-checks/pages/filter-props.html': 'runtime-checks/config/filter-props.json', diff --git a/integration-test/test-pages/runtime-checks/config/script-overload.json b/integration-test/test-pages/runtime-checks/config/script-overload.json index aab2ac26f..30609444b 100644 --- a/integration-test/test-pages/runtime-checks/config/script-overload.json +++ b/integration-test/test-pages/runtime-checks/config/script-overload.json @@ -28,6 +28,10 @@ "navigator.mediaSession.doesNotExist.depth.a.lot": { "type": "string", "value": "boop" + }, + "navigator.getBattery": { + "type": "function", + "functionName": "noop" } } } diff --git a/integration-test/test-pages/runtime-checks/pages/basic-run.html b/integration-test/test-pages/runtime-checks/pages/basic-run.html index a8ae3c1e0..d141b33bb 100644 --- a/integration-test/test-pages/runtime-checks/pages/basic-run.html +++ b/integration-test/test-pages/runtime-checks/pages/basic-run.html @@ -176,6 +176,32 @@ ]; }); + test('Support namespaces', async () => { + const scriptElement = document.createElement('script'); + scriptElement.id = 'scriptyNS'; + scriptElement.setAttribute('type', 'application/javascript'); + scriptElement.setAttributeNS(null, 'src', 'test://url'); + + const getAttributeNS = scriptElement.getAttributeNS(null, 'src'); + const getAttribute = scriptElement.getAttribute('src'); + + document.body.appendChild(scriptElement); + const hadInspectorNode = scriptElement === document.querySelector('ddg-runtime-checks:last-of-type'); + // Continue to modify the script element after it has been added to the DOM + scriptElement.madeUpProp = 'val'; + const instanceofResult = scriptElement instanceof HTMLScriptElement; + const scripty = document.querySelector('#scriptyNS'); + + return [ + { name: 'hadInspectorNode', result: hadInspectorNode, expected: true }, + { name: 'expect script to match', result: scripty, expected: scriptElement }, + { name: 'scripty.getAttribute', result: getAttribute, expected: 'test://url' }, + { name: 'scripty.getAttributeNS', result: getAttribute, expected: 'test://url' }, + { name: 'scripty.type', result: scripty.type, expected: 'application/javascript' }, + { name: 'scripty.id', result: scripty.id, expected: 'scriptyNS' } + ]; + }); + // eslint-disable-next-line no-undef renderResults(); diff --git a/integration-test/test-pages/runtime-checks/pages/script-overload.html b/integration-test/test-pages/runtime-checks/pages/script-overload.html index 8068a77f3..5a9119797 100644 --- a/integration-test/test-pages/runtime-checks/pages/script-overload.html +++ b/integration-test/test-pages/runtime-checks/pages/script-overload.html @@ -84,6 +84,37 @@ ]; }); + test('Script should overload methods', async () => { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + window.scriptOutput = false; + window.scriptyRan = false; + const scriptElement = document.createElement('script'); + scriptElement.innerText = ` + window.scriptyRan = true; + /* Stringify to avoid undefined being trimmed */ + window.scriptOutput = { + b: ""+window.navigator.getBattery() + } + `; + scriptElement.id = 'overloadedScriptFn'; + scriptElement.setAttribute('type', 'application/javascript'); + document.body.appendChild(scriptElement); + const instanceofResult = scriptElement instanceof HTMLScriptElement; + const scripty = document.querySelector('script#overloadedScriptFn'); + const nodeAndFakeNodeMatch = scripty === scriptElement; + // We shouldn't break out of the context we're overloading + const doesntMatchParentContext = navigator.userAgent !== 'testingThisOut'; + return [ + { name: 'instanceof matches HTMLScriptElement', result: instanceofResult, expected: true }, + { name: 'script ran', result: window.scriptyRan, expected: true }, + { name: 'node and fake node match', result: nodeAndFakeNodeMatch, expected: false }, + { name: 'battery API is overloaded', result: window.scriptOutput, expected: { + b: 'undefined' + } }, + { name: 'user agent doesnt match parent context', result: doesntMatchParentContext, expected: true } + ]; + }); + renderResults(); diff --git a/package-lock.json b/package-lock.json index 245f09469..22c45fca4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,22 +23,22 @@ "@rollup/plugin-commonjs": "^24.1.0", "@rollup/plugin-node-resolve": "^15.0.2", "@rollup/plugin-replace": "^5.0.2", - "@types/chrome": "^0.0.231", + "@types/chrome": "^0.0.233", "@types/jasmine": "^4.3.1", - "@typescript-eslint/eslint-plugin": "^5.58.0", - "@typescript-eslint/parser": "^5.59.0", - "eslint": "^8.38.0", + "@typescript-eslint/eslint-plugin": "^5.59.1", + "@typescript-eslint/parser": "^5.59.1", + "eslint": "^8.39.0", "eslint-config-standard": "^17.0.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.1.1", "jasmine": "^4.6.0", "minimist": "^1.2.8", - "puppeteer": "^19.9.1", - "rollup": "^3.20.6", + "puppeteer": "^19.11.1", + "rollup": "^3.21.0", "rollup-plugin-import-css": "^3.2.1", "rollup-plugin-svg-import": "^2.0.0", - "typedoc": "^0.24.4", + "typedoc": "^0.24.6", "typescript": "^5.0.4" } }, @@ -159,9 +159,9 @@ "link": true }, "node_modules/@esbuild/android-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.17.tgz", - "integrity": "sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", + "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", "cpu": [ "arm" ], @@ -175,9 +175,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz", - "integrity": "sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", + "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", "cpu": [ "arm64" ], @@ -191,9 +191,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.17.tgz", - "integrity": "sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", + "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", "cpu": [ "x64" ], @@ -207,9 +207,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz", - "integrity": "sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", + "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", "cpu": [ "arm64" ], @@ -223,9 +223,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz", - "integrity": "sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", + "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", "cpu": [ "x64" ], @@ -239,9 +239,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz", - "integrity": "sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", + "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", "cpu": [ "arm64" ], @@ -255,9 +255,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz", - "integrity": "sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", + "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", "cpu": [ "x64" ], @@ -271,9 +271,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz", - "integrity": "sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", + "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", "cpu": [ "arm" ], @@ -287,9 +287,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz", - "integrity": "sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", + "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", "cpu": [ "arm64" ], @@ -303,9 +303,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz", - "integrity": "sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", + "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", "cpu": [ "ia32" ], @@ -319,9 +319,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz", - "integrity": "sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", + "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", "cpu": [ "loong64" ], @@ -335,9 +335,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz", - "integrity": "sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", + "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", "cpu": [ "mips64el" ], @@ -351,9 +351,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz", - "integrity": "sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", + "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", "cpu": [ "ppc64" ], @@ -367,9 +367,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz", - "integrity": "sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", + "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", "cpu": [ "riscv64" ], @@ -383,9 +383,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz", - "integrity": "sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", + "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", "cpu": [ "s390x" ], @@ -399,9 +399,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz", - "integrity": "sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", + "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", "cpu": [ "x64" ], @@ -415,9 +415,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz", - "integrity": "sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", + "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", "cpu": [ "x64" ], @@ -431,9 +431,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz", - "integrity": "sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", + "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", "cpu": [ "x64" ], @@ -447,9 +447,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz", - "integrity": "sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", + "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", "cpu": [ "x64" ], @@ -463,9 +463,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz", - "integrity": "sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", + "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", "cpu": [ "arm64" ], @@ -479,9 +479,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz", - "integrity": "sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", + "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", "cpu": [ "ia32" ], @@ -495,9 +495,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz", - "integrity": "sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", + "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", "cpu": [ "x64" ], @@ -558,9 +558,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", + "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -669,9 +669,9 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-0.4.1.tgz", - "integrity": "sha512-4IICvy1McAkT/HyNZHIs7sp8ngBX1dmO0TPQ+FWq9ATQMqI8p+Ulm5A3kS2wYDh5HDHHkYrrETOu6rlj64VuTw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-0.5.0.tgz", + "integrity": "sha512-Uw6oB7VvmPRLE4iKsjuOh8zgDabhNX67dzo8U/BB0f9527qx+4eeUs+korU98OhG5C4ubg7ufBgVi63XYwS6TQ==", "dev": true, "dependencies": { "debug": "4.3.4", @@ -862,9 +862,9 @@ "dev": true }, "node_modules/@types/chrome": { - "version": "0.0.231", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.231.tgz", - "integrity": "sha512-K3dSpeorWAj2UA/1GRUbny34+PARsH/k8bj8dRZQusSqNE323QEGils9ty1LaVyR1DnfLMD9PX8cV5Q+EhwAvQ==", + "version": "0.0.233", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.233.tgz", + "integrity": "sha512-T3HUW8LDhHfYPbUkOZilhnqX04sZqEFIQO0OIG8byZ7PBIk2jYys1AkNg56UbtKbsh3dABmOniK+0Q3oyo7Sxg==", "dev": true, "dependencies": { "@types/filesystem": "*", @@ -945,15 +945,15 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", - "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz", + "integrity": "sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/type-utils": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/type-utils": "5.59.1", + "@typescript-eslint/utils": "5.59.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -979,14 +979,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", - "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.1.tgz", + "integrity": "sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", "debug": "^4.3.4" }, "engines": { @@ -1005,88 +1005,14 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.59.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz", - "integrity": "sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.1.tgz", + "integrity": "sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0" + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1097,13 +1023,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", - "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.1.tgz", + "integrity": "sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/typescript-estree": "5.59.1", + "@typescript-eslint/utils": "5.59.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1124,9 +1050,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.58.0.tgz", - "integrity": "sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.1.tgz", + "integrity": "sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1137,13 +1063,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz", - "integrity": "sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.1.tgz", + "integrity": "sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1164,17 +1090,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", - "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.1.tgz", + "integrity": "sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1212,12 +1138,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz", - "integrity": "sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz", + "integrity": "sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/types": "5.59.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1575,9 +1501,9 @@ "dev": true }, "node_modules/chromium-bidi": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.6.tgz", - "integrity": "sha512-TQOkWRaLI/IWvoP8XC+7jO4uHTIiAUiklXU1T0qszlUFEai9LgKXIBXy3pOS3EnQZ3bQtMbKUPkug0fTAEHCSw==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.7.tgz", + "integrity": "sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ==", "dev": true, "dependencies": { "mitt": "3.0.0" @@ -1870,9 +1796,9 @@ } }, "node_modules/esbuild": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", - "integrity": "sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", + "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", "dev": true, "hasInstallScript": true, "bin": { @@ -1882,28 +1808,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.17", - "@esbuild/android-arm64": "0.17.17", - "@esbuild/android-x64": "0.17.17", - "@esbuild/darwin-arm64": "0.17.17", - "@esbuild/darwin-x64": "0.17.17", - "@esbuild/freebsd-arm64": "0.17.17", - "@esbuild/freebsd-x64": "0.17.17", - "@esbuild/linux-arm": "0.17.17", - "@esbuild/linux-arm64": "0.17.17", - "@esbuild/linux-ia32": "0.17.17", - "@esbuild/linux-loong64": "0.17.17", - "@esbuild/linux-mips64el": "0.17.17", - "@esbuild/linux-ppc64": "0.17.17", - "@esbuild/linux-riscv64": "0.17.17", - "@esbuild/linux-s390x": "0.17.17", - "@esbuild/linux-x64": "0.17.17", - "@esbuild/netbsd-x64": "0.17.17", - "@esbuild/openbsd-x64": "0.17.17", - "@esbuild/sunos-x64": "0.17.17", - "@esbuild/win32-arm64": "0.17.17", - "@esbuild/win32-ia32": "0.17.17", - "@esbuild/win32-x64": "0.17.17" + "@esbuild/android-arm": "0.17.18", + "@esbuild/android-arm64": "0.17.18", + "@esbuild/android-x64": "0.17.18", + "@esbuild/darwin-arm64": "0.17.18", + "@esbuild/darwin-x64": "0.17.18", + "@esbuild/freebsd-arm64": "0.17.18", + "@esbuild/freebsd-x64": "0.17.18", + "@esbuild/linux-arm": "0.17.18", + "@esbuild/linux-arm64": "0.17.18", + "@esbuild/linux-ia32": "0.17.18", + "@esbuild/linux-loong64": "0.17.18", + "@esbuild/linux-mips64el": "0.17.18", + "@esbuild/linux-ppc64": "0.17.18", + "@esbuild/linux-riscv64": "0.17.18", + "@esbuild/linux-s390x": "0.17.18", + "@esbuild/linux-x64": "0.17.18", + "@esbuild/netbsd-x64": "0.17.18", + "@esbuild/openbsd-x64": "0.17.18", + "@esbuild/sunos-x64": "0.17.18", + "@esbuild/win32-arm64": "0.17.18", + "@esbuild/win32-ia32": "0.17.18", + "@esbuild/win32-x64": "0.17.18" } }, "node_modules/escalade": { @@ -1928,15 +1854,15 @@ } }, "node_modules/eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", + "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", + "@eslint/js": "8.39.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -1946,7 +1872,7 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", + "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.0", "espree": "^9.5.1", "esquery": "^1.4.2", @@ -2277,9 +2203,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2287,6 +2213,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-utils": { @@ -3888,28 +3817,28 @@ } }, "node_modules/puppeteer": { - "version": "19.9.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.9.1.tgz", - "integrity": "sha512-Ii8yZySNdpPzeKAK6ROFQ+gAi04igoZ0cPsBE1LW9fmzkqQTqbJpEGhJ/5gBS8oVqkQ2CNFA4BskJl75zaWWgA==", + "version": "19.11.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.11.1.tgz", + "integrity": "sha512-39olGaX2djYUdhaQQHDZ0T0GwEp+5f9UB9HmEP0qHfdQHIq0xGQZuAZ5TLnJIc/88SrPLpEflPC+xUqOTv3c5g==", "dev": true, "hasInstallScript": true, "dependencies": { - "@puppeteer/browsers": "0.4.1", + "@puppeteer/browsers": "0.5.0", "cosmiconfig": "8.1.3", "https-proxy-agent": "5.0.1", "progress": "2.0.3", "proxy-from-env": "1.1.0", - "puppeteer-core": "19.9.1" + "puppeteer-core": "19.11.1" } }, "node_modules/puppeteer-core": { - "version": "19.9.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.9.1.tgz", - "integrity": "sha512-46JGqhqTgYO5DuUMRGUiMCKM/86uHMsMCK7Fw7cbY/p+eCKLIPGVyQyI/E0UcGYa0+OH3dz0ResaDdHxqCgDDw==", + "version": "19.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.11.1.tgz", + "integrity": "sha512-qcuC2Uf0Fwdj9wNtaTZ2OvYRraXpAK+puwwVW8ofOhOgLPZyz1c68tsorfIZyCUOpyBisjr+xByu7BMbEYMepA==", "dev": true, "dependencies": { - "@puppeteer/browsers": "0.4.1", - "chromium-bidi": "0.4.6", + "@puppeteer/browsers": "0.5.0", + "chromium-bidi": "0.4.7", "cross-fetch": "3.1.5", "debug": "4.3.4", "devtools-protocol": "0.0.1107588", @@ -4077,9 +4006,9 @@ } }, "node_modules/rollup": { - "version": "3.20.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.6.tgz", - "integrity": "sha512-2yEB3nQXp/tBQDN0hJScJQheXdvU2wFhh6ld7K/aiZ1vYcak6N/BKjY1QrU6BvO2JWYS8bEs14FRaxXosxy2zw==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.0.tgz", + "integrity": "sha512-ANPhVcyeHvYdQMUyCbczy33nbLzI7RzrBje4uvNiTDJGIMtlKoOStmympwr9OtS1LZxiDmE2wvxHyVhoLtf1KQ==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -4517,9 +4446,9 @@ } }, "node_modules/typedoc": { - "version": "0.24.4", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.4.tgz", - "integrity": "sha512-vQuliyGhJEGeKzzCFHbkS3m0gHoIL6cfr0fHf6eX658iGELtq2J9mWe0b+X5McEYgFoMuHFt5Py3Zug6Sxjn/Q==", + "version": "0.24.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", + "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", "dev": true, "dependencies": { "lunr": "^2.3.9", @@ -4851,7 +4780,7 @@ "devDependencies": { "@duckduckgo/messaging": "*", "@playwright/test": "^1.32.3", - "esbuild": "^0.17.17", + "esbuild": "^0.17.18", "http-server": "^14.1.1" } } @@ -4951,156 +4880,156 @@ "version": "file:packages/messaging" }, "@esbuild/android-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.17.tgz", - "integrity": "sha512-E6VAZwN7diCa3labs0GYvhEPL2M94WLF8A+czO8hfjREXxba8Ng7nM5VxV+9ihNXIY1iQO1XxUU4P7hbqbICxg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", + "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.17.tgz", - "integrity": "sha512-jaJ5IlmaDLFPNttv0ofcwy/cfeY4bh/n705Tgh+eLObbGtQBK3EPAu+CzL95JVE4nFAliyrnEu0d32Q5foavqg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", + "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.17.tgz", - "integrity": "sha512-446zpfJ3nioMC7ASvJB1pszHVskkw4u/9Eu8s5yvvsSDTzYh4p4ZIRj0DznSl3FBF0Z/mZfrKXTtt0QCoFmoHA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", + "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.17.tgz", - "integrity": "sha512-m/gwyiBwH3jqfUabtq3GH31otL/0sE0l34XKpSIqR7NjQ/XHQ3lpmQHLHbG8AHTGCw8Ao059GvV08MS0bhFIJQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", + "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.17.tgz", - "integrity": "sha512-4utIrsX9IykrqYaXR8ob9Ha2hAY2qLc6ohJ8c0CN1DR8yWeMrTgYFjgdeQ9LIoTOfLetXjuCu5TRPHT9yKYJVg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", + "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.17.tgz", - "integrity": "sha512-4PxjQII/9ppOrpEwzQ1b0pXCsFLqy77i0GaHodrmzH9zq2/NEhHMAMJkJ635Ns4fyJPFOlHMz4AsklIyRqFZWA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", + "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.17.tgz", - "integrity": "sha512-lQRS+4sW5S3P1sv0z2Ym807qMDfkmdhUYX30GRBURtLTrJOPDpoU0kI6pVz1hz3U0+YQ0tXGS9YWveQjUewAJw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", + "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.17.tgz", - "integrity": "sha512-biDs7bjGdOdcmIk6xU426VgdRUpGg39Yz6sT9Xp23aq+IEHDb/u5cbmu/pAANpDB4rZpY/2USPhCA+w9t3roQg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", + "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.17.tgz", - "integrity": "sha512-2+pwLx0whKY1/Vqt8lyzStyda1v0qjJ5INWIe+d8+1onqQxHLLi3yr5bAa4gvbzhZqBztifYEu8hh1La5+7sUw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", + "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.17.tgz", - "integrity": "sha512-IBTTv8X60dYo6P2t23sSUYym8fGfMAiuv7PzJ+0LcdAndZRzvke+wTVxJeCq4WgjppkOpndL04gMZIFvwoU34Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", + "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.17.tgz", - "integrity": "sha512-WVMBtcDpATjaGfWfp6u9dANIqmU9r37SY8wgAivuKmgKHE+bWSuv0qXEFt/p3qXQYxJIGXQQv6hHcm7iWhWjiw==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", + "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.17.tgz", - "integrity": "sha512-2kYCGh8589ZYnY031FgMLy0kmE4VoGdvfJkxLdxP4HJvWNXpyLhjOvxVsYjYZ6awqY4bgLR9tpdYyStgZZhi2A==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", + "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.17.tgz", - "integrity": "sha512-KIdG5jdAEeAKogfyMTcszRxy3OPbZhq0PPsW4iKKcdlbk3YE4miKznxV2YOSmiK/hfOZ+lqHri3v8eecT2ATwQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", + "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.17.tgz", - "integrity": "sha512-Cj6uWLBR5LWhcD/2Lkfg2NrkVsNb2sFM5aVEfumKB2vYetkA/9Uyc1jVoxLZ0a38sUhFk4JOVKH0aVdPbjZQeA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", + "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.17.tgz", - "integrity": "sha512-lK+SffWIr0XsFf7E0srBjhpkdFVJf3HEgXCwzkm69kNbRar8MhezFpkIwpk0qo2IOQL4JE4mJPJI8AbRPLbuOQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", + "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.17.tgz", - "integrity": "sha512-XcSGTQcWFQS2jx3lZtQi7cQmDYLrpLRyz1Ns1DzZCtn898cWfm5Icx/DEWNcTU+T+tyPV89RQtDnI7qL2PObPg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", + "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.17.tgz", - "integrity": "sha512-RNLCDmLP5kCWAJR+ItLM3cHxzXRTe4N00TQyQiimq+lyqVqZWGPAvcyfUBM0isE79eEZhIuGN09rAz8EL5KdLA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", + "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.17.tgz", - "integrity": "sha512-PAXswI5+cQq3Pann7FNdcpSUrhrql3wKjj3gVkmuz6OHhqqYxKvi6GgRBoaHjaG22HV/ZZEgF9TlS+9ftHVigA==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", + "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.17.tgz", - "integrity": "sha512-V63egsWKnx/4V0FMYkr9NXWrKTB5qFftKGKuZKFIrAkO/7EWLFnbBZNM1CvJ6Sis+XBdPws2YQSHF1Gqf1oj/Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", + "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.17.tgz", - "integrity": "sha512-YtUXLdVnd6YBSYlZODjWzH+KzbaubV0YVd6UxSfoFfa5PtNJNaW+1i+Hcmjpg2nEe0YXUCNF5bkKy1NnBv1y7Q==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", + "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.17.tgz", - "integrity": "sha512-yczSLRbDdReCO74Yfc5tKG0izzm+lPMYyO1fFTcn0QNwnKmc3K+HdxZWLGKg4pZVte7XVgcFku7TIZNbWEJdeQ==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", + "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.17.tgz", - "integrity": "sha512-FNZw7H3aqhF9OyRQbDDnzUApDXfC1N6fgBhkqEO2jvYCJ+DxMTfZVqg3AX0R1khg1wHTBRD5SdcibSJ+XF6bFg==", + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", + "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", "dev": true, "optional": true }, @@ -5137,9 +5066,9 @@ } }, "@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", + "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", "dev": true }, "@fingerprintjs/fingerprintjs": { @@ -5218,9 +5147,9 @@ } }, "@puppeteer/browsers": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-0.4.1.tgz", - "integrity": "sha512-4IICvy1McAkT/HyNZHIs7sp8ngBX1dmO0TPQ+FWq9ATQMqI8p+Ulm5A3kS2wYDh5HDHHkYrrETOu6rlj64VuTw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-0.5.0.tgz", + "integrity": "sha512-Uw6oB7VvmPRLE4iKsjuOh8zgDabhNX67dzo8U/BB0f9527qx+4eeUs+korU98OhG5C4ubg7ufBgVi63XYwS6TQ==", "dev": true, "requires": { "debug": "4.3.4", @@ -5344,9 +5273,9 @@ } }, "@types/chrome": { - "version": "0.0.231", - "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.231.tgz", - "integrity": "sha512-K3dSpeorWAj2UA/1GRUbny34+PARsH/k8bj8dRZQusSqNE323QEGils9ty1LaVyR1DnfLMD9PX8cV5Q+EhwAvQ==", + "version": "0.0.233", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.233.tgz", + "integrity": "sha512-T3HUW8LDhHfYPbUkOZilhnqX04sZqEFIQO0OIG8byZ7PBIk2jYys1AkNg56UbtKbsh3dABmOniK+0Q3oyo7Sxg==", "dev": true, "requires": { "@types/filesystem": "*", @@ -5427,15 +5356,15 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz", - "integrity": "sha512-vxHvLhH0qgBd3/tW6/VccptSfc8FxPQIkmNTVLWcCOVqSBvqpnKkBTYrhcGlXfSnd78azwe+PsjYFj0X34/njA==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz", + "integrity": "sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/type-utils": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/type-utils": "5.59.1", + "@typescript-eslint/utils": "5.59.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -5445,96 +5374,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", - "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.1.tgz", + "integrity": "sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", "debug": "^4.3.4" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" - } - }, - "@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.59.0", - "eslint-visitor-keys": "^3.3.0" - } - } } }, "@typescript-eslint/scope-manager": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.58.0.tgz", - "integrity": "sha512-b+w8ypN5CFvrXWQb9Ow9T4/6LC2MikNf1viLkYTiTbkQl46CnR69w7lajz1icW0TBsYmlpg+mRzFJ4LEJ8X9NA==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.1.tgz", + "integrity": "sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0" + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1" } }, "@typescript-eslint/type-utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.58.0.tgz", - "integrity": "sha512-FF5vP/SKAFJ+LmR9PENql7fQVVgGDOS+dq3j+cKl9iW/9VuZC/8CFmzIP0DLKXfWKpRHawJiG70rVH+xZZbp8w==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.1.tgz", + "integrity": "sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.58.0", - "@typescript-eslint/utils": "5.58.0", + "@typescript-eslint/typescript-estree": "5.59.1", + "@typescript-eslint/utils": "5.59.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.58.0.tgz", - "integrity": "sha512-JYV4eITHPzVQMnHZcYJXl2ZloC7thuUHrcUmxtzvItyKPvQ50kb9QXBkgNAt90OYMqwaodQh2kHutWZl1fc+1g==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.1.tgz", + "integrity": "sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.58.0.tgz", - "integrity": "sha512-cRACvGTodA+UxnYM2uwA2KCwRL7VAzo45syNysqlMyNyjw0Z35Icc9ihPJZjIYuA5bXJYiJ2YGUB59BqlOZT1Q==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.1.tgz", + "integrity": "sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/visitor-keys": "5.58.0", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/visitor-keys": "5.59.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -5543,17 +5429,17 @@ } }, "@typescript-eslint/utils": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.58.0.tgz", - "integrity": "sha512-gAmLOTFXMXOC+zP1fsqm3VceKSBQJNzV385Ok3+yzlavNHZoedajjS4UyS21gabJYcobuigQPs/z71A9MdJFqQ==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.1.tgz", + "integrity": "sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.58.0", - "@typescript-eslint/types": "5.58.0", - "@typescript-eslint/typescript-estree": "5.58.0", + "@typescript-eslint/scope-manager": "5.59.1", + "@typescript-eslint/types": "5.59.1", + "@typescript-eslint/typescript-estree": "5.59.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -5577,12 +5463,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.58.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.58.0.tgz", - "integrity": "sha512-/fBraTlPj0jwdyTwLyrRTxv/3lnU2H96pNTVM6z3esTWLtA5MZ9ghSMJ7Rb+TtUAdtEw9EyJzJ0EydIMKxQ9gA==", + "version": "5.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz", + "integrity": "sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.58.0", + "@typescript-eslint/types": "5.59.1", "eslint-visitor-keys": "^3.3.0" } }, @@ -5829,9 +5715,9 @@ "dev": true }, "chromium-bidi": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.6.tgz", - "integrity": "sha512-TQOkWRaLI/IWvoP8XC+7jO4uHTIiAUiklXU1T0qszlUFEai9LgKXIBXy3pOS3EnQZ3bQtMbKUPkug0fTAEHCSw==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.7.tgz", + "integrity": "sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ==", "dev": true, "requires": { "mitt": "3.0.0" @@ -6065,33 +5951,33 @@ } }, "esbuild": { - "version": "0.17.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.17.tgz", - "integrity": "sha512-/jUywtAymR8jR4qsa2RujlAF7Krpt5VWi72Q2yuLD4e/hvtNcFQ0I1j8m/bxq238pf3/0KO5yuXNpuLx8BE1KA==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.17.17", - "@esbuild/android-arm64": "0.17.17", - "@esbuild/android-x64": "0.17.17", - "@esbuild/darwin-arm64": "0.17.17", - "@esbuild/darwin-x64": "0.17.17", - "@esbuild/freebsd-arm64": "0.17.17", - "@esbuild/freebsd-x64": "0.17.17", - "@esbuild/linux-arm": "0.17.17", - "@esbuild/linux-arm64": "0.17.17", - "@esbuild/linux-ia32": "0.17.17", - "@esbuild/linux-loong64": "0.17.17", - "@esbuild/linux-mips64el": "0.17.17", - "@esbuild/linux-ppc64": "0.17.17", - "@esbuild/linux-riscv64": "0.17.17", - "@esbuild/linux-s390x": "0.17.17", - "@esbuild/linux-x64": "0.17.17", - "@esbuild/netbsd-x64": "0.17.17", - "@esbuild/openbsd-x64": "0.17.17", - "@esbuild/sunos-x64": "0.17.17", - "@esbuild/win32-arm64": "0.17.17", - "@esbuild/win32-ia32": "0.17.17", - "@esbuild/win32-x64": "0.17.17" + "version": "0.17.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", + "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.17.18", + "@esbuild/android-arm64": "0.17.18", + "@esbuild/android-x64": "0.17.18", + "@esbuild/darwin-arm64": "0.17.18", + "@esbuild/darwin-x64": "0.17.18", + "@esbuild/freebsd-arm64": "0.17.18", + "@esbuild/freebsd-x64": "0.17.18", + "@esbuild/linux-arm": "0.17.18", + "@esbuild/linux-arm64": "0.17.18", + "@esbuild/linux-ia32": "0.17.18", + "@esbuild/linux-loong64": "0.17.18", + "@esbuild/linux-mips64el": "0.17.18", + "@esbuild/linux-ppc64": "0.17.18", + "@esbuild/linux-riscv64": "0.17.18", + "@esbuild/linux-s390x": "0.17.18", + "@esbuild/linux-x64": "0.17.18", + "@esbuild/netbsd-x64": "0.17.18", + "@esbuild/openbsd-x64": "0.17.18", + "@esbuild/sunos-x64": "0.17.18", + "@esbuild/win32-arm64": "0.17.18", + "@esbuild/win32-ia32": "0.17.18", + "@esbuild/win32-x64": "0.17.18" } }, "escalade": { @@ -6107,15 +5993,15 @@ "dev": true }, "eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "version": "8.39.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", + "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", + "@eslint/js": "8.39.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -6125,7 +6011,7 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", + "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.0", "espree": "^9.5.1", "esquery": "^1.4.2", @@ -6412,9 +6298,9 @@ "requires": {} }, "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -7518,27 +7404,27 @@ "dev": true }, "puppeteer": { - "version": "19.9.1", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.9.1.tgz", - "integrity": "sha512-Ii8yZySNdpPzeKAK6ROFQ+gAi04igoZ0cPsBE1LW9fmzkqQTqbJpEGhJ/5gBS8oVqkQ2CNFA4BskJl75zaWWgA==", + "version": "19.11.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.11.1.tgz", + "integrity": "sha512-39olGaX2djYUdhaQQHDZ0T0GwEp+5f9UB9HmEP0qHfdQHIq0xGQZuAZ5TLnJIc/88SrPLpEflPC+xUqOTv3c5g==", "dev": true, "requires": { - "@puppeteer/browsers": "0.4.1", + "@puppeteer/browsers": "0.5.0", "cosmiconfig": "8.1.3", "https-proxy-agent": "5.0.1", "progress": "2.0.3", "proxy-from-env": "1.1.0", - "puppeteer-core": "19.9.1" + "puppeteer-core": "19.11.1" } }, "puppeteer-core": { - "version": "19.9.1", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.9.1.tgz", - "integrity": "sha512-46JGqhqTgYO5DuUMRGUiMCKM/86uHMsMCK7Fw7cbY/p+eCKLIPGVyQyI/E0UcGYa0+OH3dz0ResaDdHxqCgDDw==", + "version": "19.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.11.1.tgz", + "integrity": "sha512-qcuC2Uf0Fwdj9wNtaTZ2OvYRraXpAK+puwwVW8ofOhOgLPZyz1c68tsorfIZyCUOpyBisjr+xByu7BMbEYMepA==", "dev": true, "requires": { - "@puppeteer/browsers": "0.4.1", - "chromium-bidi": "0.4.6", + "@puppeteer/browsers": "0.5.0", + "chromium-bidi": "0.4.7", "cross-fetch": "3.1.5", "debug": "4.3.4", "devtools-protocol": "0.0.1107588", @@ -7638,9 +7524,9 @@ } }, "rollup": { - "version": "3.20.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.6.tgz", - "integrity": "sha512-2yEB3nQXp/tBQDN0hJScJQheXdvU2wFhh6ld7K/aiZ1vYcak6N/BKjY1QrU6BvO2JWYS8bEs14FRaxXosxy2zw==", + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.0.tgz", + "integrity": "sha512-ANPhVcyeHvYdQMUyCbczy33nbLzI7RzrBje4uvNiTDJGIMtlKoOStmympwr9OtS1LZxiDmE2wvxHyVhoLtf1KQ==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -7770,7 +7656,7 @@ "requires": { "@duckduckgo/messaging": "*", "@playwright/test": "^1.32.3", - "esbuild": "^0.17.17", + "esbuild": "^0.17.18", "http-server": "^14.1.1" } }, @@ -7966,9 +7852,9 @@ } }, "typedoc": { - "version": "0.24.4", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.4.tgz", - "integrity": "sha512-vQuliyGhJEGeKzzCFHbkS3m0gHoIL6cfr0fHf6eX658iGELtq2J9mWe0b+X5McEYgFoMuHFt5Py3Zug6Sxjn/Q==", + "version": "0.24.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.6.tgz", + "integrity": "sha512-c3y3h45xJv3qYwKDAwU6Cl+26CjT0ZvblHzfHJ+SjQDM4p1mZxtgHky4lhmG0+nNarRht8kADfZlbspJWdZarQ==", "dev": true, "requires": { "lunr": "^2.3.9", diff --git a/package.json b/package.json index 4cda17728..a67bd1676 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "postinstall": "npm run copy-sjcl", "copy-sjcl": "node scripts/generateSJCL.js", "bundle-config": "node scripts/bundleConfig.mjs", - "build": "npm run build-locales && npm run build-firefox && npm run build-chrome && npm run build-apple && npm run build-android && npm run build-windows && npm run build-integration && npm run build-chrome-mv3", + "build": "npm run build-locales && npm run bundle-trackers && npm run build-firefox && npm run build-chrome && npm run build-apple && npm run build-android && npm run build-windows && npm run build-integration && npm run build-chrome-mv3", "build-locales": "node scripts/buildLocales.js --dir src/locales/click-to-load --output build/locales/ctl-locales.js", "build-firefox": "node scripts/inject.js --platform firefox", "build-chrome": "node scripts/inject.js --platform chrome", @@ -19,6 +19,7 @@ "build-android": "node scripts/inject.js --platform android", "build-windows": "node scripts/inject.js --platform windows", "build-integration": "node scripts/inject.js --platform integration", + "bundle-trackers": "node scripts/bundleTrackers.mjs --output build/tracker-lookup.json", "docs": "typedoc", "docs-watch": "typedoc --watch", "postbuild": "npm run build --workspaces --if-present", @@ -58,22 +59,22 @@ "@rollup/plugin-commonjs": "^24.1.0", "@rollup/plugin-node-resolve": "^15.0.2", "@rollup/plugin-replace": "^5.0.2", - "@types/chrome": "^0.0.231", + "@types/chrome": "^0.0.233", "@types/jasmine": "^4.3.1", - "@typescript-eslint/eslint-plugin": "^5.58.0", - "@typescript-eslint/parser": "^5.59.0", - "eslint": "^8.38.0", + "@typescript-eslint/eslint-plugin": "^5.59.1", + "@typescript-eslint/parser": "^5.59.1", + "eslint": "^8.39.0", "eslint-config-standard": "^17.0.0", "eslint-plugin-import": "^2.27.5", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^6.1.1", "jasmine": "^4.6.0", "minimist": "^1.2.8", - "puppeteer": "^19.9.1", - "rollup": "^3.20.6", + "puppeteer": "^19.11.1", + "rollup": "^3.21.0", "rollup-plugin-import-css": "^3.2.1", "rollup-plugin-svg-import": "^2.0.0", - "typedoc": "^0.24.4", + "typedoc": "^0.24.6", "typescript": "^5.0.4" } } diff --git a/packages/special-pages/package.json b/packages/special-pages/package.json index 5ae4c9da2..bbb274bf2 100644 --- a/packages/special-pages/package.json +++ b/packages/special-pages/package.json @@ -22,6 +22,6 @@ "@playwright/test": "^1.32.3", "http-server": "^14.1.1", "@duckduckgo/messaging": "*", - "esbuild": "^0.17.17" + "esbuild": "^0.17.18" } } diff --git a/packages/special-pages/pages/duckplayer/src/js/index.js b/packages/special-pages/pages/duckplayer/src/js/index.js index f664f2f9f..45bde1426 100644 --- a/packages/special-pages/pages/duckplayer/src/js/index.js +++ b/packages/special-pages/pages/duckplayer/src/js/index.js @@ -36,6 +36,7 @@ import { MessagingContext, TestTransportConfig } from '../../../../../messaging/index.js' import { DuckPlayerPageMessages, UserValues } from './messages' +import { html } from '../../../../../../src/dom-utils' // for docs export { DuckPlayerPageMessages, UserValues } @@ -107,7 +108,7 @@ const VideoPlayer = { * Show an error instead of the video player iframe */ showVideoError: (errorMessage) => { - VideoPlayer.playerContainer().innerHTML = '
ERROR:
' + VideoPlayer.playerContainer().innerHTML = html`
ERROR:
`.toString() // @ts-expect-error - Type 'HTMLElement | null' is not assignable to type 'HTMLElement'. document.querySelector('.player-error-message').textContent = errorMessage diff --git a/scripts/bundleTrackers.mjs b/scripts/bundleTrackers.mjs new file mode 100644 index 000000000..51296c1ca --- /dev/null +++ b/scripts/bundleTrackers.mjs @@ -0,0 +1,33 @@ +import fetch from 'node-fetch' +import { writeFileSync } from 'fs' +import { parseArgs, write } from './script-utils.js' + +const tdsUrl = 'https://staticcdn.duckduckgo.com/trackerblocking/v4/tds.json' +const resp = await fetch(tdsUrl) +const tds = await resp.json() + +// Build a trie of tracker domains, starting with the broadest subdomain. Leaves are set to 1 to indicate success +// i.e. lookup['com']['example'] === 1 if example.com is a tracker domain +const trackerLookupTrie = {} +function insert (domainParts, node) { + if (domainParts.length === 1) { + node[domainParts[0]] = 1 + } else if (node[domainParts[0]]) { + insert(domainParts.slice(1), node[domainParts[0]]) + } else { + node[domainParts[0]] = {} + insert(domainParts.slice(1), node[domainParts[0]]) + } +} +Object.keys(tds.trackers).forEach((tracker) => { + insert(tracker.split('.').reverse(), trackerLookupTrie) +}) + +const outputString = JSON.stringify(trackerLookupTrie) +const args = parseArgs(process.argv.slice(2), []) +if (args.output) { + write([args.output], outputString) +} else { + // Used by the extension code + console.log(outputString) +} diff --git a/scripts/generateSJCL.js b/scripts/generateSJCL.js index e333f6f90..fa5e63f7d 100644 --- a/scripts/generateSJCL.js +++ b/scripts/generateSJCL.js @@ -1,5 +1,4 @@ -// @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f -import fs from 'fs/promises' +import { readFile, writeFile } from 'fs/promises' import { existsSync } from 'fs' // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f import util from 'util' @@ -18,14 +17,14 @@ async function init () { } await exec('cd node_modules/sjcl/ && perl ./configure --no-export --compress=none --without-all --with-hmac --with-codecHex && make') - const sjclFileContents = await fs.readFile('node_modules/sjcl/sjcl.js') + const sjclFileContents = await readFile('node_modules/sjcl/sjcl.js') // Reexport the file as es6 module format const contents = `// @ts-nocheck export const sjcl = (() => { ${sjclFileContents} return sjcl; })()` - fs.writeFile('lib/sjcl.js', contents) + writeFile('lib/sjcl.js', contents) } init() diff --git a/scripts/utils/build.js b/scripts/utils/build.js index 042f38608..8a3310849 100644 --- a/scripts/utils/build.js +++ b/scripts/utils/build.js @@ -5,6 +5,7 @@ import resolve from '@rollup/plugin-node-resolve' import css from 'rollup-plugin-import-css' import svg from 'rollup-plugin-svg-import' import { runtimeInjected, platformSupport } from '../../src/features.js' +import { readFileSync } from 'fs' /** * This is a helper function to require all files in a directory @@ -81,9 +82,11 @@ export async function rollupScript (params) { supportsMozProxies = false } = params + const trackerLookupData = readFileSync('./build/tracker-lookup.json', 'utf8') + const extensions = ['firefox', 'chrome', 'chrome-mv3'] + const trackerLookup = extensions.includes(platform) ? '$TRACKER_LOOKUP$' : trackerLookupData // The code is using a global, that we define here which means once tree shaken we get a browser specific output. const mozProxies = supportsMozProxies - const plugins = [ css(), svg({ @@ -98,7 +101,9 @@ export async function rollupScript (params) { values: { // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f mozProxies, - 'import.meta.injectName': JSON.stringify(platform) + 'import.meta.injectName': JSON.stringify(platform), + // To be replaced by the extension, but prevents tree shaking + 'import.meta.trackerLookup': trackerLookup } }), prefixPlugin(prefixMessage) diff --git a/src/content-feature.js b/src/content-feature.js index 53a60dad8..a28559c6f 100644 --- a/src/content-feature.js +++ b/src/content-feature.js @@ -1,14 +1,44 @@ -import { camelcase, matchHostname, processAttr } from './utils.js' +import { camelcase, getTabHostname, matchHostname, processAttr, computeEnabledFeatures, parseFeatureSettings } from './utils.js' import { immutableJSONPatch } from 'immutable-json-patch' import { PerformanceMonitor } from './performance.js' +/** + * @typedef {object} AssetConfig + * @property {string} regularFontUrl + * @property {string} boldFontUrl + */ + +/** + * @typedef {object} Site + * @property {string} domain + * @property {boolean} isBroken + * @property {boolean} allowlisted + * @property {string[]} enabledFeatures + */ + export default class ContentFeature { + /** @type {import('./utils.js').RemoteConfig | undefined} */ + #bundledConfig + /** @type {object | undefined} */ + #trackerLookup + /** @type {boolean | undefined} */ + #documentOriginIsTracker + /** @type {Record | undefined} */ + #bundledfeatureSettings + + /** @type {{ debug: boolean, featureSettings: Record, assets: AssetConfig | undefined, site: Site } | null} */ + #args + constructor (featureName) { this.name = featureName - this._args = null + this.#args = null this.monitor = new PerformanceMonitor() } + get isDebug () { + return this.#args?.debug || false + } + /** * @param {import('./utils').Platform} platform */ @@ -21,6 +51,34 @@ export default class ContentFeature { return this._platform } + /** + * @type {AssetConfig | undefined} + */ + get assetConfig () { + return this.#args?.assets + } + + /** + * @returns {boolean} + */ + get documentOriginIsTracker () { + return !!this.#documentOriginIsTracker + } + + /** + * @returns {object} + **/ + get trackerLookup () { + return this.#trackerLookup || {} + } + + /** + * @returns {import('./utils.js').RemoteConfig | undefined} + **/ + get bundledConfig () { + return this.#bundledConfig + } + /** * Get the value of a config setting. * If the value is not set, return the default value. @@ -37,10 +95,11 @@ export default class ContentFeature { /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {any} */ - getFeatureSetting (featureKeyName) { - let result = this._getFeatureSetting() + getFeatureSetting (featureKeyName, featureName) { + let result = this._getFeatureSetting(featureName) if (featureKeyName === 'domains') { throw new Error('domains is a reserved feature setting key name') } @@ -60,17 +119,22 @@ export default class ContentFeature { return result?.[featureKeyName] } - _getFeatureSetting () { - const camelFeatureName = camelcase(this.name) - return this._args.featureSettings?.[camelFeatureName] + /** + * @param {string} [featureName] - The name of the feature to get the settings for; defaults to the name of the feature + * @returns {any} + */ + _getFeatureSetting (featureName) { + const camelFeatureName = featureName || camelcase(this.name) + return this.#args?.featureSettings?.[camelFeatureName] } /** * @param {string} featureKeyName + * @param {string} [featureName] * @returns {boolean} */ - getFeatureSettingEnabled (featureKeyName) { - const result = this.getFeatureSetting(featureKeyName) + getFeatureSettingEnabled (featureKeyName, featureName) { + const result = this.getFeatureSetting(featureKeyName, featureName) return result === 'enabled' } @@ -79,9 +143,11 @@ export default class ContentFeature { * @return {any[]} */ matchDomainFeatureSetting (featureKeyName) { + const domain = this.#args?.site.domain + if (!domain) return [] const domains = this._getFeatureSetting()?.[featureKeyName] || [] return domains.filter((rule) => { - return matchHostname(this._args.site.domain, rule.domain) + return matchHostname(domain, rule.domain) }) } @@ -91,7 +157,7 @@ export default class ContentFeature { callInit (args) { const mark = this.monitor.mark(this.name + 'CallInit') - this._args = args + this.#args = args this.platform = args.platform this.init(args) mark.end() @@ -104,14 +170,23 @@ export default class ContentFeature { callLoad (args) { const mark = this.monitor.mark(this.name + 'CallLoad') - this._args = args + this.#args = args this.platform = args.platform + this.#bundledConfig = args.bundledConfig + // If we have a bundled config, treat it as a regular config + // This will be overriden by the remote config if it is available + if (this.#bundledConfig && this.#args) { + const enabledFeatures = computeEnabledFeatures(args.bundledConfig, getTabHostname(), this.platform.version) + this.#args.featureSettings = parseFeatureSettings(args.bundledConfig, enabledFeatures) + } + this.#trackerLookup = args.trackerLookup + this.#documentOriginIsTracker = args.documentOriginIsTracker this.load(args) mark.end() } measure () { - if (this._args.debug) { + if (this.#args?.debug) { this.monitor.measureAll() } } diff --git a/src/content-scope-features.js b/src/content-scope-features.js index 8b25d496b..a9031a11e 100644 --- a/src/content-scope-features.js +++ b/src/content-scope-features.js @@ -25,12 +25,14 @@ const performanceMonitor = new PerformanceMonitor() /** * @typedef {object} LoadArgs + * @property {object} site * @property {object} platform * @property {string} platform.name * @property {string} [platform.version] - * @property {boolean} [documentOriginIsTracker] + * @property {boolean} documentOriginIsTracker * @property {object} [bundledConfig] * @property {string} [injectName] + * @property {object} trackerLookup - provided currently only by the extension */ /** diff --git a/src/dom-utils.js b/src/dom-utils.js new file mode 100644 index 000000000..83ce983c7 --- /dev/null +++ b/src/dom-utils.js @@ -0,0 +1,68 @@ +/** + * The following code is originally from https://github.com/mozilla-extensions/secure-proxy/blob/db4d1b0e2bfe0abae416bf04241916f9e4768fd2/src/commons/template.js + */ +class Template { + constructor (strings, values) { + this.values = values + this.strings = strings + } + + /** + * Escapes any occurrences of &, ", <, > or / with XML entities. + * + * @param {string} str + * The string to escape. + * @return {string} The escaped string. + */ + escapeXML (str) { + const replacements = { + '&': '&', + '"': '"', + "'": ''', + '<': '<', + '>': '>', + '/': '/' + } + return String(str).replace(/[&"'<>/]/g, m => replacements[m]) + } + + potentiallyEscape (value) { + if (typeof value === 'object') { + if (value instanceof Array) { + return value.map(val => this.potentiallyEscape(val)).join('') + } + + // If we are an escaped template let join call toString on it + if (value instanceof Template) { + return value + } + + throw new Error('Unknown object to escape') + } + return this.escapeXML(value) + } + + toString () { + const result = [] + + for (const [i, string] of this.strings.entries()) { + result.push(string) + if (i < this.values.length) { + result.push(this.potentiallyEscape(this.values[i])) + } + } + return result.join('') + } +} + +export function html (strings, ...values) { + return new Template(strings, values) +} + +/** + * @param {string} string + * @return {Template} + */ +export function trustedUnsafe (string) { + return html([string]) +} diff --git a/src/features/click-to-load.js b/src/features/click-to-load.js index 670554c16..196ff45d5 100644 --- a/src/features/click-to-load.js +++ b/src/features/click-to-load.js @@ -1,6 +1,6 @@ import { createCustomEvent, sendMessage, originalWindowDispatchEvent } from '../utils.js' import { logoImg, loadingImages, closeIcon } from './click-to-load/ctl-assets.js' -import { styles, getConfig } from './click-to-load/ctl-config.js' +import { getStyles, getConfig } from './click-to-load/ctl-config.js' import ContentFeature from '../content-feature.js' /** @@ -22,6 +22,7 @@ const titleID = 'DuckDuckGoPrivacyEssentialsCTLElementTitle' // @see {getConfig} let config = null let sharedStrings = null +let styles = null // TODO: Remove these redundant data structures and refactor the related code. // There should be no need to have the entity configuration stored in two @@ -484,6 +485,16 @@ function replaceTrackingElement (widget, trackingElement, placeholderElement) { ] elementToReplace.style.setProperty('display', 'none', 'important') + // When iframes are blocked by the declarativeNetRequest API, they are + // collapsed (hidden) automatically. Unfortunately however, there's a bug + // that stops them from being uncollapsed (shown again) if they are removed + // from the DOM after they are collapsed. As a workaround, have the iframe + // load a benign data URI, so that it's uncollapsed, before removing it from + // the DOM. See https://crbug.com/1428971 + const originalSrc = elementToReplace.src + elementToReplace.src = + 'data:text/plain;charset=utf-8;base64,' + btoa('https://crbug.com/1428971') + // Add the placeholder element to the page. elementToReplace.parentElement.insertBefore( placeholderElement, elementToReplace @@ -503,6 +514,7 @@ function replaceTrackingElement (widget, trackingElement, placeholderElement) { // placeholder) can finally be removed from the DOM. elementToReplace.remove() elementToReplace.style.setProperty('display', ...originalDisplay) + elementToReplace.src = originalSrc }) } @@ -893,10 +905,10 @@ function makeBaseStyleElement (mode = 'lightMode') { * Creates an anchor element with no destination. It is expected that a click * handler is added to the element later. * @param {string} linkText - * @param {displayMode} [mode='lightMode'] + * @param {displayMode} mode * @returns {HTMLAnchorElement} */ -function makeTextButton (linkText, mode) { +function makeTextButton (linkText, mode = 'lightMode') { const linkElement = document.createElement('a') linkElement.style.cssText = styles.headerLink + styles[mode].linkFont linkElement.textContent = linkText @@ -1620,6 +1632,8 @@ export default class ClickToLoad extends ContentFeature { const localizedConfig = getConfig(locale) config = localizedConfig.config sharedStrings = localizedConfig.sharedStrings + // update styles if asset config was sent + styles = getStyles(this.assetConfig) for (const entity of Object.keys(config)) { // Strip config entities that are first-party, or aren't enabled in the @@ -1688,6 +1702,16 @@ export default class ClickToLoad extends ContentFeature { } await afterPageLoad + // On some websites, the "ddg-ctp-ready" event is occasionally + // dispatched too early, before the listener is ready to receive it. + // To counter that, catch "ddg-ctp-surrogate-load" events dispatched + // _after_ page, so the "ddg-ctp-ready" event can be dispatched again. + window.addEventListener( + 'ddg-ctp-surrogate-load', () => { + originalWindowDispatchEvent(createCustomEvent('ddg-ctp-ready')) + } + ) + // Then wait for any in-progress element replacements, before letting // the surrogate scripts know to start. window.setTimeout(() => { diff --git a/src/features/click-to-load/ctl-assets.js b/src/features/click-to-load/ctl-assets.js index 3c21df4b9..da40e4d43 100644 --- a/src/features/click-to-load/ctl-assets.js +++ b/src/features/click-to-load/ctl-assets.js @@ -1,4 +1,4 @@ -export const logoImg = 'data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAA0aXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjarZxpkhw5kqX/4xR1BOzLcQAFIDI36OP392BB5lY9Uy0yyWQyMsLpbgaovkVVYe781/+57l//+lcIPXeXS+t11Or5J4884uSL7r9/xvtv8Pn99/3T88/Pwl+/737/IPKtxJ/p+982f14/+X750xv9ep/11++7/vOT2H/eKPx+4/dP0ifr6/3ni+T78ft++LkQN873RR29/flS188b2a8r7n/8zr8v6/tD/+/+8o3GKu3CB6UYTwrJv//m7wqSfoc0+TPx35Aar/Np8HVJ0b1vxZ83Y0H+cnu//vT+zwv0l0X+9ZX7++r//upvix/nz/fT39ay/qwRX/zbH4Tyt++n3x8T//zB6fcVxb/+IIS4/3E7P7/v3f3e893dzJUVrT8R9RY7/HobXrhY8vT+WuVX43fh6/Z+DX51P72x5dubX/yyMEJkV64LOewwww3n/WnBuMQcT2RPYozGRul7nT0a0dgldlG/wo2NHdups5cWj2Mrc4q/ryW8zx3v8yx0PnkHXhoDb8bu/s+/3P/th/+bX+5ee0vs+++14rqiIovL0M7pv7yKDQn3Z9/KW+Bfv3623/8pfhSqmZdpmTs3OP363mKV8EdspbfPidcV/vxSKLi2f96AJeKzCxcTEjvga0gl1OBbjC0E1rGzQZMrjynHxQ6EUuLmImNOqUbXYo/6bP5OC++1scQa9W2wiY0oqabG3pBTbFbOhfhpuRNDs6SSSym1tNJdGWXWVHMttdZWBXKzpZZbabW11ttosycgsPTaW+999DniSGBgGXW00ccYc0Y3+aDJe01eP/nOiiutvMqqq62+xppG+Fi2YtWadRs2d9xpAxO77rb7Hnue4A5IcfIpp552+hlnXmLtpptvufW22++48/eu/ezqP379L3Yt/OxafDul17Xfu8Z3XWu/3iIITor2jB2LObDjTTtAQEftme8h56id0575EUmKErnIor1xO2jH2MJ8Qiw3/N67P3buP9o3V/p/tG/x/7VzTlv3/2PnHFv3z337N7u2xXP2duzLQq2pT2QfPz99utinSG3++z9H9vER0ogNiCz11FFYzM3HZH6SY2UHQOvr7LCJx9/pYxrz3JXnZbdYl+pjGens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' +export const logoImg = 'data:image/png;base64,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' export const loadingImages = { darkMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E', lightMode: 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20viewBox%3D%220%200%2020%2020%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%40keyframes%20rotate%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20from%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%280deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20to%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20transform%3A%20rotate%28359deg%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%3Cg%20style%3D%22transform-origin%3A%2050%25%2050%25%3B%20animation%3A%20rotate%201s%20infinite%20reverse%20linear%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2218.0968%22%20y%3D%2216.0861%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%2018.0968%2016.0861%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.1%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.4%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2219.9976%22%20y%3D%228.37451%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%2019.9976%208.37451%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.2%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%2216.1727%22%20y%3D%221.9917%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%2016.1727%201.9917%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.3%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.91309%22%20y%3D%226.88501%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%28136.161%208.91309%206.88501%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%226.79602%22%20y%3D%2210.996%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2846.1607%206.79602%2010.996%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.7%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%227%22%20y%3D%228.62549%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20transform%3D%22rotate%2890%207%208.62549%29%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.8%22%2F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20x%3D%228.49878%22%20y%3D%2213%22%20width%3D%223%22%20height%3D%227%22%20rx%3D%221.5%22%20fill%3D%22%23111111%22%20fill-opacity%3D%220.9%22%2F%3E%0A%20%20%20%20%20%20%20%20%3C%2Fg%3E%0A%20%20%20%20%3C%2Fsvg%3E' // 'data:application/octet-stream;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxzdHlsZT4KCQlAa2V5ZnJhbWVzIHJvdGF0ZSB7CgkJCWZyb20gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7CgkJCX0KCQkJdG8gewoJCQkJdHJhbnNmb3JtOiByb3RhdGUoMzU5ZGVnKTsKCQkJfQoJCX0KCTwvc3R5bGU+Cgk8ZyBzdHlsZT0idHJhbnNmb3JtLW9yaWdpbjogNTAlIDUwJTsgYW5pbWF0aW9uOiByb3RhdGUgMXMgaW5maW5pdGUgcmV2ZXJzZSBsaW5lYXI7Ij4KCQk8cmVjdCB4PSIxOC4wOTY4IiB5PSIxNi4wODYxIiB3aWR0aD0iMyIgaGVpZ2h0PSI3IiByeD0iMS41IiB0cmFuc2Zvcm09InJvdGF0ZSgxMzYuMTYxIDE4LjA5NjggMTYuMDg2MSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC4xIi8+CQoJCTxyZWN0IHg9IjguNDk4NzgiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC40Ii8+CgkJPHJlY3QgeD0iMTkuOTk3NiIgeT0iOC4zNzQ1MSIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgdHJhbnNmb3JtPSJyb3RhdGUoOTAgMTkuOTk3NiA4LjM3NDUxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjIiLz4KCQk8cmVjdCB4PSIxNi4xNzI3IiB5PSIxLjk5MTciIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgMTYuMTcyNyAxLjk5MTcpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuMyIvPgoJCTxyZWN0IHg9IjguOTEzMDkiIHk9IjYuODg1MDEiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDEzNi4xNjEgOC45MTMwOSA2Ljg4NTAxKSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjYiLz4KCQk8cmVjdCB4PSI2Ljc5NjAyIiB5PSIxMC45OTYiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDQ2LjE2MDcgNi43OTYwMiAxMC45OTYpIiBmaWxsPSIjZmZmZmZmIiBmaWxsLW9wYWNpdHk9IjAuNyIvPgoJCTxyZWN0IHg9IjciIHk9IjguNjI1NDkiIHdpZHRoPSIzIiBoZWlnaHQ9IjciIHJ4PSIxLjUiIHRyYW5zZm9ybT0icm90YXRlKDkwIDcgOC42MjU0OSkiIGZpbGw9IiNmZmZmZmYiIGZpbGwtb3BhY2l0eT0iMC44Ii8+CQkKCQk8cmVjdCB4PSI4LjQ5ODc4IiB5PSIxMyIgd2lkdGg9IjMiIGhlaWdodD0iNyIgcng9IjEuNSIgZmlsbD0iI2ZmZmZmZiIgZmlsbC1vcGFjaXR5PSIwLjkiLz4KCTwvZz4KPC9zdmc+Cg==' @@ -10,6 +10,3 @@ export const blockedFBLogo = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2280%22% export const blockedYTVideo = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2275%22%20height%3D%2275%22%20viewBox%3D%220%200%2075%2075%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Crect%20x%3D%226.75%22%20y%3D%2215.75%22%20width%3D%2256.25%22%20height%3D%2239%22%20rx%3D%2213.5%22%20fill%3D%22%23DE5833%22%2F%3E%0A%20%20%3Cmask%20id%3D%22path-2-outside-1_885_11045%22%20maskUnits%3D%22userSpaceOnUse%22%20x%3D%2223.75%22%20y%3D%2222.5%22%20width%3D%2224%22%20height%3D%2226%22%20fill%3D%22black%22%3E%0A%20%20%3Crect%20fill%3D%22white%22%20x%3D%2223.75%22%20y%3D%2222.5%22%20width%3D%2224%22%20height%3D%2226%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M41.9425%2037.5279C43.6677%2036.492%2043.6677%2033.9914%2041.9425%2032.9555L31.0394%2026.4088C29.262%2025.3416%2027%2026.6218%2027%2028.695L27%2041.7884C27%2043.8615%2029.262%2045.1418%2031.0394%2044.0746L41.9425%2037.5279Z%22%2F%3E%0A%20%20%3C%2Fmask%3E%0A%20%20%3Cpath%20d%3D%22M41.9425%2037.5279C43.6677%2036.492%2043.6677%2033.9914%2041.9425%2032.9555L31.0394%2026.4088C29.262%2025.3416%2027%2026.6218%2027%2028.695L27%2041.7884C27%2043.8615%2029.262%2045.1418%2031.0394%2044.0746L41.9425%2037.5279Z%22%20fill%3D%22white%22%2F%3E%0A%20%20%3Cpath%20d%3D%22M30.0296%2044.6809L31.5739%2047.2529L30.0296%2044.6809ZM30.0296%2025.8024L31.5739%2023.2304L30.0296%2025.8024ZM42.8944%2036.9563L44.4387%2039.5283L42.8944%2036.9563ZM41.35%2036.099L28.4852%2028.3744L31.5739%2023.2304L44.4387%2030.955L41.35%2036.099ZM30%2027.5171L30%2042.9663L24%2042.9663L24%2027.5171L30%2027.5171ZM28.4852%2042.1089L41.35%2034.3843L44.4387%2039.5283L31.5739%2047.2529L28.4852%2042.1089ZM30%2042.9663C30%2042.1888%2029.1517%2041.7087%2028.4852%2042.1089L31.5739%2047.2529C28.2413%2049.2539%2024%2046.8535%2024%2042.9663L30%2042.9663ZM28.4852%2028.3744C29.1517%2028.7746%2030%2028.2945%2030%2027.5171L24%2027.5171C24%2023.6299%2028.2413%2021.2294%2031.5739%2023.2304L28.4852%2028.3744ZM44.4387%2030.955C47.6735%2032.8974%2047.6735%2037.586%2044.4387%2039.5283L41.35%2034.3843C40.7031%2034.7728%2040.7031%2035.7105%2041.35%2036.099L44.4387%2030.955Z%22%20fill%3D%22%23BC4726%22%20mask%3D%22url(%23path-2-outside-1_885_11045)%22%2F%3E%0A%20%20%3Ccircle%20cx%3D%2257.75%22%20cy%3D%2252.5%22%20r%3D%2213.5%22%20fill%3D%22%23E0E0E0%22%2F%3E%0A%20%20%3Crect%20x%3D%2248.75%22%20y%3D%2250.25%22%20width%3D%2218%22%20height%3D%224.5%22%20rx%3D%221.5%22%20fill%3D%22%23666666%22%2F%3E%0A%20%20%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M57.9853%2015.8781C58.2046%2016.1015%2058.5052%2016.2262%2058.8181%2016.2238C59.1311%2016.2262%2059.4316%2016.1015%2059.6509%2015.8781L62.9821%2012.5469C63.2974%2012.2532%2063.4272%2011.8107%2063.3206%2011.3931C63.2139%2010.9756%2062.8879%2010.6495%2062.4703%2010.5429C62.0528%2010.4363%2061.6103%2010.5661%2061.3165%2010.8813L57.9853%2014.2125C57.7627%2014.4325%2057.6374%2014.7324%2057.6374%2015.0453C57.6374%2015.3583%2057.7627%2015.6582%2057.9853%2015.8781ZM61.3598%2018.8363C61.388%2019.4872%2061.9385%2019.9919%2062.5893%2019.9637L62.6915%2019.9559L66.7769%2019.6023C67.4278%2019.5459%2067.9097%2018.9726%2067.8533%2018.3217C67.7968%2017.6708%2067.2235%2017.1889%2066.5726%2017.2453L62.4872%2017.6067C61.8363%2017.6349%2061.3316%2018.1854%2061.3598%2018.8363Z%22%20fill%3D%22%23AAAAAA%22%20fill-opacity%3D%220.6%22%2F%3E%0A%20%20%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M10.6535%2015.8781C10.4342%2016.1015%2010.1336%2016.2262%209.82067%2016.2238C9.5077%2016.2262%209.20717%2016.1015%208.98787%2015.8781L5.65667%2012.5469C5.34138%2012.2532%205.2116%2011.8107%205.31823%2011.3931C5.42487%2010.9756%205.75092%2010.6495%206.16847%2010.5429C6.58602%2010.4363%207.02848%2010.5661%207.32227%2010.8813L10.6535%2014.2125C10.8761%2014.4325%2011.0014%2014.7324%2011.0014%2015.0453C11.0014%2015.3583%2010.8761%2015.6582%2010.6535%2015.8781ZM7.2791%2018.8362C7.25089%2019.4871%206.7004%2019.9919%206.04954%2019.9637L5.9474%2019.9558L1.86197%2019.6023C1.44093%2019.5658%201.07135%2019.3074%200.892432%2018.9246C0.713515%2018.5417%200.752449%2018.0924%200.994567%2017.7461C1.23669%2017.3997%201.6452%2017.2088%202.06624%2017.2453L6.15167%2017.6067C6.80254%2017.6349%207.3073%2018.1854%207.2791%2018.8362Z%22%20fill%3D%22%23AAAAAA%22%20fill-opacity%3D%220.6%22%2F%3E%0A%3C%2Fsvg%3E%0A' export const videoPlayDark = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23222222%22%2F%3E%0A%3C%2Fsvg%3E%0A' export const videoPlayLight = 'data:image/svg+xml;utf8,%3Csvg%20width%3D%2222%22%20height%3D%2226%22%20viewBox%3D%220%200%2022%2026%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%3Cpath%20d%3D%22M21%2011.2679C22.3333%2012.0377%2022.3333%2013.9622%2021%2014.732L3%2025.1244C1.66667%2025.8942%202.59376e-06%2024.9319%202.66105e-06%2023.3923L3.56958e-06%202.60769C3.63688e-06%201.06809%201.66667%200.105844%203%200.875644L21%2011.2679Z%22%20fill%3D%22%23FFFFFF%22%2F%3E%0A%3C%2Fsvg%3E' - -export const ddgFont = 'data:application/octet-stream;base64,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' -export const ddgFontBold = 'data:application/octet-stream;base64,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' diff --git a/src/features/click-to-load/ctl-config.js b/src/features/click-to-load/ctl-config.js index a897dcb63..e6e427504 100644 --- a/src/features/click-to-load/ctl-config.js +++ b/src/features/click-to-load/ctl-config.js @@ -1,5 +1,5 @@ import { - blockedFBLogo, ddgFont, ddgFontBold, blockedYTVideo, videoPlayDark, videoPlayLight + blockedFBLogo, blockedYTVideo, videoPlayDark, videoPlayLight } from './ctl-assets.js' import localesJSON from '../../../build/locales/ctl-locales.js' @@ -7,109 +7,123 @@ import localesJSON from '../../../build/locales/ctl-locales.js' /********************************************************* * Style Definitions *********************************************************/ -export const styles = { - fontStyle: ` +/** + * Get CSS style defintions for CTL, using the provided AssetConfig for any non-embedded assets + * (e.g. fonts.) + * @param {import('../../content-feature.js').AssetConfig} [assets] + */ +export function getStyles (assets) { + let fontStyle = '' + let regularFontFamily = "system, -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'" + let boldFontFamily = regularFontFamily + if (assets?.regularFontUrl && assets?.boldFontUrl) { + fontStyle = ` @font-face{ font-family: DuckDuckGoPrivacyEssentials; - src: url(${ddgFont}); + src: url(${assets.regularFontUrl}); } @font-face{ font-family: DuckDuckGoPrivacyEssentialsBold; font-weight: bold; - src: url(${ddgFontBold}); + src: url(${assets.boldFontUrl}); } - `, - darkMode: { - background: ` + ` + regularFontFamily = 'DuckDuckGoPrivacyEssentials' + boldFontFamily = 'DuckDuckGoPrivacyEssentialsBold' + } + return { + fontStyle, + darkMode: { + background: ` background: #111111; `, - textFont: ` + textFont: ` color: rgba(255, 255, 255, 0.9); `, - buttonFont: ` + buttonFont: ` color: #111111; `, - linkFont: ` + linkFont: ` color: #7295F6; `, - buttonBackground: ` + buttonBackground: ` background: #5784FF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #557FF3; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #3969EF; `, - toggleButtonText: ` + toggleButtonText: ` color: #EEEEEE; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #5784FF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - lightMode: { - background: ` + } + }, + lightMode: { + background: ` background: #FFFFFF; `, - textFont: ` + textFont: ` color: #222222; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; `, - linkFont: ` + linkFont: ` color: #3969EF; `, - buttonBackground: ` + buttonBackground: ` background: #3969EF; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: #2B55CA; `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: #1E42A4; `, - toggleButtonText: ` + toggleButtonText: ` color: #666666; `, - toggleButtonBgState: { - active: ` + toggleButtonBgState: { + active: ` background: #3969EF; `, - inactive: ` + inactive: ` background-color: #666666; ` - } - }, - loginMode: { - buttonBackground: ` + } + }, + loginMode: { + buttonBackground: ` background: #666666; `, - buttonFont: ` + buttonFont: ` color: #FFFFFF; ` - }, - cancelMode: { - buttonBackground: ` + }, + cancelMode: { + buttonBackground: ` background: rgba(34, 34, 34, 0.1); `, - buttonFont: ` + buttonFont: ` color: #222222; `, - buttonBackgroundHover: ` + buttonBackgroundHover: ` background: rgba(0, 0, 0, 0.12); `, - buttonBackgroundPress: ` + buttonBackgroundPress: ` background: rgba(0, 0, 0, 0.18); ` - }, - button: ` + }, + button: ` border-radius: 8px; padding: 11px 22px; @@ -118,7 +132,7 @@ export const styles = { border-color: #3969EF; border: none; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; font-size: 14px; position: relative; @@ -126,7 +140,7 @@ export const styles = { box-shadow: none; z-index: 2147483646; `, - circle: ` + circle: ` border-radius: 50%; width: 18px; height: 18px; @@ -136,14 +150,14 @@ export const styles = { top: -8px; right: -8px; `, - loginIcon: ` + loginIcon: ` position: absolute; top: -13px; right: -10px; height: 28px; width: 28px; `, - rectangle: ` + rectangle: ` width: 12px; height: 3px; background: #666666; @@ -151,7 +165,7 @@ export const styles = { top: 42.5%; margin: auto; `, - textBubble: ` + textBubble: ` background: #FFFFFF; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 16px; @@ -162,9 +176,9 @@ export const styles = { position: absolute; line-height: normal; `, - textBubbleWidth: 360, // Should match the width rule in textBubble - textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble - textArrow: ` + textBubbleWidth: 360, // Should match the width rule in textBubble + textBubbleLeftShift: 100, // Should match the CSS left: rule in textBubble + textArrow: ` display: inline-block; background: #FFFFFF; border: solid rgba(0, 0, 0, 0.1); @@ -175,23 +189,23 @@ export const styles = { position: relative; top: -9px; `, - arrowDefaultLocationPercent: 50, - hoverTextTitle: ` + arrowDefaultLocationPercent: 50, + hoverTextTitle: ` padding: 0px 12px 12px; margin-top: -5px; `, - hoverTextBody: ` - font-family: DuckDuckGoPrivacyEssentials; + hoverTextBody: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: auto; padding: 17px; text-align: left; `, - hoverContainer: ` + hoverContainer: ` padding-bottom: 10px; `, - buttonTextContainer: ` + buttonTextContainer: ` display: flex; flex-direction: row; align-items: center; @@ -199,10 +213,10 @@ export const styles = { padding: 0; margin: 0; `, - headerRow: ` + headerRow: ` `, - block: ` + block: ` box-sizing: border-box; border: 1px solid rgba(0,0,0,0.1); border-radius: 12px; @@ -212,27 +226,27 @@ export const styles = { display: flex; flex-direction: column; - font-family: DuckDuckGoPrivacyEssentials; + font-family: ${regularFontFamily}; line-height: 1; `, - youTubeDialogBlock: ` + youTubeDialogBlock: ` height: calc(100% - 30px); max-width: initial; min-height: initial; `, - imgRow: ` + imgRow: ` display: flex; flex-direction: column; margin: 20px 0px; `, - content: ` + content: ` display: flex; flex-direction: column; padding: 16px 0; flex: 1 1 1px; `, - feedbackLink: ` - font-family: DuckDuckGoPrivacyEssentials; + feedbackLink: ` + font-family: ${regularFontFamily}; font-style: normal; font-weight: 400; font-size: 12px; @@ -240,13 +254,13 @@ export const styles = { color: #ABABAB; text-decoration: none; `, - feedbackRow: ` + feedbackRow: ` height: 30px; display: flex; justify-content: flex-end; align-items: center; `, - titleBox: ` + titleBox: ` display: flex; padding: 12px; max-height: 44px; @@ -255,8 +269,8 @@ export const styles = { margin: 0; margin-bottom: 4px; `, - title: ` - font-family: DuckDuckGoPrivacyEssentials; + title: ` + font-family: ${regularFontFamily}; line-height: 1.4; font-size: 14px; margin: auto 10px; @@ -268,7 +282,7 @@ export const styles = { border: none; padding: 0; `, - buttonRow: ` + buttonRow: ` display: flex; height: 100% flex-direction: row; @@ -276,8 +290,8 @@ export const styles = { height: 100%; align-items: flex-start; `, - modalContentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + modalContentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; line-height: 21px; @@ -286,8 +300,8 @@ export const styles = { border: none; padding: 0px 32px; `, - modalContentText: ` - font-family: DuckDuckGoPrivacyEssentials; + modalContentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; margin: 0px auto 14px; @@ -295,7 +309,7 @@ export const styles = { border: none; padding: 0; `, - modalButtonRow: ` + modalButtonRow: ` border: none; padding: 0; margin: auto; @@ -304,17 +318,17 @@ export const styles = { flex-direction: column; align-items: center; `, - modalButton: ` + modalButton: ` width: 100%; display: flex; justify-content: center; align-items: center; `, - modalIcon: ` + modalIcon: ` display: block; `, - contentTitle: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + contentTitle: ` + font-family: ${boldFontFamily}; font-size: 17px; font-weight: bold; margin: 20px auto 10px; @@ -322,25 +336,25 @@ export const styles = { text-align: center; margin-top: auto; `, - contentText: ` - font-family: DuckDuckGoPrivacyEssentials; + contentText: ` + font-family: ${regularFontFamily}; font-size: 14px; line-height: 21px; padding: 0px 40px; text-align: center; margin: 0 auto auto; `, - icon: ` + icon: ` height: 80px; width: 80px; margin: auto; `, - closeIcon: ` + closeIcon: ` height: 12px; width: 12px; margin: auto; `, - closeButton: ` + closeButton: ` display: flex; justify-content: center; align-items: center; @@ -350,7 +364,7 @@ export const styles = { background: transparent; cursor: pointer; `, - logo: ` + logo: ` flex-basis: 0%; min-width: 20px; height: 21px; @@ -358,17 +372,17 @@ export const styles = { padding: 0; margin: 0; `, - logoImg: ` + logoImg: ` height: 21px; width: 21px; `, - loadingImg: ` + loadingImg: ` display: block; margin: 0px 8px 0px 0px; height: 14px; width: 14px; `, - modal: ` + modal: ` width: 340px; padding: 0; margin: auto; @@ -382,14 +396,14 @@ export const styles = { border-radius: 12px; border: none; `, - modalContent: ` + modalContent: ` padding: 24px; display: flex; flex-direction: column; border: none; margin: 0; `, - overlay: ` + overlay: ` height: 100%; width: 100%; background-color: #666666; @@ -402,7 +416,7 @@ export const styles = { padding: 0; margin: 0; `, - modalContainer: ` + modalContainer: ` height: 100vh; width: 100vw; box-sizing: border-box; @@ -413,16 +427,16 @@ export const styles = { margin: 0; padding: 0; `, - headerLinkContainer: ` + headerLinkContainer: ` flex-basis: 100%; display: grid; justify-content: flex-end; `, - headerLink: ` + headerLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; text-decoration: none; cursor: pointer; min-width: 100px; @@ -430,15 +444,15 @@ export const styles = { float: right; display: none; `, - generalLink: ` + generalLink: ` line-height: 1.4; font-size: 14px; font-weight: bold; - font-family: DuckDuckGoPrivacyEssentialsBold; + font-family: ${boldFontFamily}; cursor: pointer; text-decoration: none; `, - wrapperDiv: ` + wrapperDiv: ` display: inline-block; border: 0; padding: 0; @@ -446,12 +460,12 @@ export const styles = { max-width: 600px; min-height: 300px; `, - toggleButtonWrapper: ` + toggleButtonWrapper: ` display: flex; align-items: center; cursor: pointer; `, - toggleButton: ` + toggleButton: ` cursor: pointer; position: relative; width: 30px; @@ -463,19 +477,19 @@ export const styles = { background-color: transparent; text-align: left; `, - toggleButtonBg: ` + toggleButtonBg: ` right: 0; width: 30px; height: 16px; overflow: visible; border-radius: 10px; `, - toggleButtonText: ` + toggleButtonText: ` display: inline-block; margin: 0 0 0 7px; padding: 0; `, - toggleButtonKnob: ` + toggleButtonKnob: ` position: absolute; display: inline-block; width: 14px; @@ -486,15 +500,15 @@ export const styles = { top: calc(50% - 14px/2 - 1px); box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.05), 0px 1px 1px rgba(0, 0, 0, 0.1); `, - toggleButtonKnobState: { - active: ` + toggleButtonKnobState: { + active: ` right: 1px; `, - inactive: ` + inactive: ` left: 1px; ` - }, - placeholderWrapperDiv: ` + }, + placeholderWrapperDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -504,7 +518,7 @@ export const styles = { min-height: 300px; margin: auto; `, - youTubeWrapperDiv: ` + youTubeWrapperDiv: ` position: relative; overflow: hidden; max-width: initial; @@ -512,7 +526,7 @@ export const styles = { min-height: 300px; height: 100%; `, - youTubeDialogDiv: ` + youTubeDialogDiv: ` position: relative; overflow: hidden; border-radius: 12px; @@ -520,14 +534,14 @@ export const styles = { min-height: initial; height: calc(100% - 30px); `, - youTubeDialogBottomRow: ` + youTubeDialogBottomRow: ` display: flex; flex-direction: column; align-items: center; justify-content: flex-end; margin-top: auto; `, - youTubePlaceholder: ` + youTubePlaceholder: ` display: flex; flex-direction: column; justify-content: flex-start; @@ -536,7 +550,7 @@ export const styles = { height: 100%; background: rgba(45, 45, 45, 0.8); `, - youTubePreviewWrapperImg: ` + youTubePreviewWrapperImg: ` position: absolute; display: flex; justify-content: center; @@ -544,20 +558,20 @@ export const styles = { width: 100%; height: 100%; `, - youTubePreviewImg: ` + youTubePreviewImg: ` min-width: 100%; min-height: 100%; height: auto; `, - youTubeTopSection: ` - font-family: DuckDuckGoPrivacyEssentialsBold; + youTubeTopSection: ` + font-family: ${boldFontFamily}; flex: 1; display: flex; justify-content: space-between; position: relative; padding: 18px 12px 0; `, - youTubeTitle: ` + youTubeTitle: ` font-size: 14px; font-weight: bold; line-height: 14px; @@ -569,13 +583,13 @@ export const styles = { text-overflow: ellipsis; box-sizing: border-box; `, - youTubePlayButtonRow: ` + youTubePlayButtonRow: ` flex: 2; display: flex; align-items: center; justify-content: center; `, - youTubePlayButton: ` + youTubePlayButton: ` display: flex; justify-content: center; align-items: center; @@ -584,7 +598,7 @@ export const styles = { padding: 0px 24px; border-radius: 8px; `, - youTubePreviewToggleRow: ` + youTubePreviewToggleRow: ` flex: 1; display: flex; flex-direction: column; @@ -592,15 +606,19 @@ export const styles = { align-items: center; padding: 0 12px 18px; `, - youTubePreviewToggleText: ` + youTubePreviewToggleText: ` color: #EEEEEE; font-weight: 400; `, - youTubePreviewInfoText: ` + youTubePreviewInfoText: ` color: #ABABAB; ` + } } +/** + * @param {string} locale UI locale + */ export function getConfig (locale) { const locales = JSON.parse(localesJSON) const fbStrings = locales[locale]['facebook.json'] diff --git a/src/features/cookie.js b/src/features/cookie.js index 3caa9e35d..b1d8025e5 100644 --- a/src/features/cookie.js +++ b/src/features/cookie.js @@ -1,6 +1,15 @@ -import { defineProperty, postDebugMessage, getStackTraceOrigins, getStack, isBeingFramed, isThirdParty, getTabHostname, matchHostname } from '../utils.js' +import { defineProperty, postDebugMessage, getStackTraceOrigins, getStack, isBeingFramed, isThirdPartyFrame, getTabHostname, matchHostname } from '../utils.js' import { Cookie } from '../cookie.js' import ContentFeature from '../content-feature.js' +import { isTrackerOrigin } from '../trackers.js' + +/** + * @typedef ExtensionCookiePolicy + * @property {boolean} isFrame + * @property {boolean} isTracker + * @property {boolean} shouldBlock + * @property {boolean} isThirdPartyFrame + */ // Initial cookie policy pre init let cookiePolicy = { @@ -10,12 +19,18 @@ let cookiePolicy = { shouldBlock: true, shouldBlockTrackerCookie: true, shouldBlockNonTrackerCookie: false, - isThirdParty: isThirdParty(), + isThirdPartyFrame: isThirdPartyFrame(), policy: { threshold: 604800, // 7 days maxAge: 604800 // 7 days - } + }, + trackerPolicy: { + threshold: 86400, // 1 day + maxAge: 86400 // 1 day + }, + allowlist: /** @type {{ host: string }[]} */([]) } +let trackerLookup = {} let loadedPolicyResolve @@ -35,6 +50,9 @@ function debugHelper (action, reason, ctx) { }) } +/** + * @returns {boolean} + */ function shouldBlockTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockTrackerCookie && isTrackingCookie() } @@ -43,26 +61,45 @@ function shouldBlockNonTrackingCookie () { return cookiePolicy.shouldBlock && cookiePolicy.shouldBlockNonTrackerCookie && isNonTrackingCookie() } +/** + * @param {Set} scriptOrigins + * @returns {boolean} + */ +function isFirstPartyTrackerScript (scriptOrigins) { + let matched = false + for (const scriptOrigin of scriptOrigins) { + if (cookiePolicy.allowlist.find((allowlistOrigin) => matchHostname(allowlistOrigin.host, scriptOrigin))) { + return false + } + if (isTrackerOrigin(trackerLookup, scriptOrigin)) { + matched = true + } + } + return matched +} + +/** + * @returns {boolean} + */ function isTrackingCookie () { - return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } function isNonTrackingCookie () { - return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdParty + return cookiePolicy.isFrame && !cookiePolicy.isTracker && cookiePolicy.isThirdPartyFrame } export default class CookieFeature extends ContentFeature { - load (args) { - // Feature is only relevant to the extension and windows, we should skip for other platforms for now as the config testing is broken. - if (this.platform.name !== 'extension' && this.platform.name !== 'windows') { - return - } - if (args.documentOriginIsTracker) { + load () { + if (this.documentOriginIsTracker) { cookiePolicy.isTracker = true } - if (args.bundledConfig) { + if (this.trackerLookup) { + trackerLookup = this.trackerLookup + } + if (this.bundledConfig) { // use the bundled config to get a best-effort at the policy, before the background sends the real one - const { exceptions, settings } = args.bundledConfig.features.cookie + const { exceptions, settings } = this.bundledConfig.features.cookie const tabHostname = getTabHostname() let tabExempted = true @@ -76,6 +113,10 @@ export default class CookieFeature extends ContentFeature { }) cookiePolicy.shouldBlock = !frameExempted && !tabExempted cookiePolicy.policy = settings.firstPartyCookiePolicy + cookiePolicy.trackerPolicy = settings.firstPartyTrackerCookiePolicy + // Allows for ad click conversion detection as described by https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/. + // This only applies when the resources that would set these cookies are unblocked. + cookiePolicy.allowlist = this.getFeatureSetting('allowlist', 'adClickAttribution') || [] } // The cookie policy is injected into every frame immediately so that no cookie will @@ -136,20 +177,20 @@ export default class CookieFeature extends ContentFeature { try { // wait for config before doing same-site tests loadPolicyThen(() => { - const { shouldBlock, policy } = cookiePolicy + const { shouldBlock, policy, trackerPolicy } = cookiePolicy + const chosenPolicy = isFirstPartyTrackerScript(scriptOrigins) ? trackerPolicy : policy if (!shouldBlock) { debugHelper('ignore', 'disabled', setCookieContext) return } - // extract cookie expiry from cookie string const cookie = new Cookie(value) // apply cookie policy - if (cookie.getExpiry() > policy.threshold) { + if (cookie.getExpiry() > chosenPolicy.threshold) { // check if the cookie still exists if (document.cookie.split(';').findIndex(kv => kv.trim().startsWith(cookie.parts[0].trim())) !== -1) { - cookie.maxAge = policy.maxAge + cookie.maxAge = chosenPolicy.maxAge debugHelper('restrict', 'expiry', setCookieContext) @@ -177,19 +218,23 @@ export default class CookieFeature extends ContentFeature { } init (args) { + const restOfPolicy = { + debug: this.isDebug, + shouldBlockTrackerCookie: this.getFeatureSettingEnabled('trackerCookie'), + shouldBlockNonTrackerCookie: this.getFeatureSettingEnabled('nonTrackerCookie'), + allowlist: this.getFeatureSetting('allowlist', 'adClickAttribution') || [], + policy: this.getFeatureSetting('firstPartyCookiePolicy'), + trackerPolicy: this.getFeatureSetting('firstPartyTrackerCookiePolicy') + } + // The extension provides some additional info about the cookie policy, let's use that over our guesses if (args.cookie) { - cookiePolicy = args.cookie - args.cookie.debug = args.debug - - cookiePolicy.shouldBlockTrackerCookie = this.getFeatureSettingEnabled('trackerCookie') - cookiePolicy.shouldBlockNonTrackerCookie = this.getFeatureSettingEnabled('nonTrackerCookie') - const policy = this.getFeatureSetting('firstPartyCookiePolicy') - if (policy) { - cookiePolicy.policy = policy + const extensionCookiePolicy = /** @type {ExtensionCookiePolicy} */(args.cookie) + cookiePolicy = { + ...extensionCookiePolicy, + ...restOfPolicy } } else { - // no cookie information - disable protections - cookiePolicy.shouldBlock = false + cookiePolicy = Object.assign(cookiePolicy, restOfPolicy) } loadedPolicyResolve() diff --git a/src/features/duck-player.js b/src/features/duck-player.js index 2e623422d..eeb84e51b 100644 --- a/src/features/duck-player.js +++ b/src/features/duck-player.js @@ -30,7 +30,7 @@ export default class DuckPlayerFeature extends ContentFeature { if (this.platform.name === 'windows') { const context = new MessagingContext({ context: 'contentScopeScripts', - env: this._args.debug ? 'development' : 'production', + env: this.isDebug ? 'development' : 'production', featureName: this.name }) const config = new WindowsMessagingConfig({ diff --git a/src/features/duckplayer/components/ddg-video-overlay.js b/src/features/duckplayer/components/ddg-video-overlay.js index 743044eda..9abd985c5 100644 --- a/src/features/duckplayer/components/ddg-video-overlay.js +++ b/src/features/duckplayer/components/ddg-video-overlay.js @@ -3,6 +3,7 @@ import dax from '../assets/dax.svg' import { i18n } from '../text.js' import { appendImageAsBackground } from '../util.js' import { VideoOverlayManager } from '../video-overlay-manager.js' +import { html, trustedUnsafe } from '../../../dom-utils.js' /** * The custom element that we use to present our UI elements @@ -54,12 +55,15 @@ export class DDGVideoOverlay extends HTMLElement { createOverlay () { const overlayElement = document.createElement('div') overlayElement.classList.add('ddg-video-player-overlay') - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax) + overlayElement.innerHTML = html`
-
${dax}
+
${svgIcon}
${i18n.t('videoOverlayTitle')}
-
${i18n.t('videoOverlaySubtitle')}
+
+ ${i18n.t('playText')} ${i18n.t('videoOverlaySubtitle')} +
${i18n.t('videoButtonOpen')} @@ -70,7 +74,7 @@ export class DDGVideoOverlay extends HTMLElement {
- ` + `.toString() /** * Set the link * @type {string} diff --git a/src/features/duckplayer/icon-overlay.js b/src/features/duckplayer/icon-overlay.js index 92c835f82..9c2826f40 100644 --- a/src/features/duckplayer/icon-overlay.js +++ b/src/features/duckplayer/icon-overlay.js @@ -2,6 +2,7 @@ import { addTrustedEventListener, appendElement, VideoParams } from './util' import dax from './assets/dax.svg' import { i18n } from './text.js' import { OpenInDuckPlayerMsg } from './overlay-messages.js' +import { html, trustedUnsafe } from '../../dom-utils.js' export const IconOverlay = { /** @@ -41,20 +42,20 @@ export const IconOverlay = { overlayElement.setAttribute('class', 'ddg-overlay' + (extraClass ? ' ' + extraClass : '')) overlayElement.setAttribute('data-size', size) - overlayElement.innerHTML = ` + const svgIcon = trustedUnsafe(dax) + overlayElement.innerHTML = html`
- ${dax} + ${svgIcon}
${i18n.t('playText')}
-
` + `.toString() overlayElement.querySelector('a.ddg-play-privately')?.setAttribute('href', href) - overlayElement.querySelector('a.ddg-play-privately')?.addEventListener('click', (event) => { event.preventDefault() event.stopPropagation() diff --git a/src/features/duckplayer/text.js b/src/features/duckplayer/text.js index f602acc3e..2ad55db44 100644 --- a/src/features/duckplayer/text.js +++ b/src/features/duckplayer/text.js @@ -9,7 +9,7 @@ const text = { title: 'Tired of targeted YouTube ads and recommendations?' }, videoOverlaySubtitle: { - title: 'Duck Player provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' + title: 'provides a clean viewing experience without personalized ads and prevents viewing activity from influencing your YouTube recommendations.' }, videoButtonOpen: { title: 'Watch in Duck Player' diff --git a/src/features/navigator-interface.js b/src/features/navigator-interface.js index f56cc68e5..f22eb439f 100644 --- a/src/features/navigator-interface.js +++ b/src/features/navigator-interface.js @@ -1,29 +1,39 @@ import { defineProperty, DDGPromise } from '../utils' import ContentFeature from '../content-feature' +function injectNavigatorInterface (args) { + try { + // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f + if (navigator.duckduckgo) { + return + } + if (!args.platform || !args.platform.name) { + return + } + defineProperty(Navigator.prototype, 'duckduckgo', { + value: { + platform: args.platform.name, + isDuckDuckGo () { + return DDGPromise.resolve(true) + } + }, + enumerable: true, + configurable: false, + writable: false + }) + } catch { + // todo: Just ignore this exception? + } +} + export default class NavigatorInterface extends ContentFeature { - init (args) { - try { - // @ts-expect-error https://app.asana.com/0/1201614831475344/1203979574128023/f - if (navigator.duckduckgo) { - return - } - if (!args.platform || !args.platform.name) { - return - } - defineProperty(Navigator.prototype, 'duckduckgo', { - value: { - platform: args.platform.name, - isDuckDuckGo () { - return DDGPromise.resolve(true) - } - }, - enumerable: true, - configurable: false, - writable: false - }) - } catch { - // todo: Just ignore this exception? + load (args) { + if (this.matchDomainFeatureSetting('privilegedDomains').length) { + injectNavigatorInterface(args) } } + + init (args) { + injectNavigatorInterface(args) + } } diff --git a/src/features/runtime-checks.js b/src/features/runtime-checks.js index d3d5fddba..43120db78 100644 --- a/src/features/runtime-checks.js +++ b/src/features/runtime-checks.js @@ -35,7 +35,9 @@ const supportedSinks = ['src'] // Store the original methods so we can call them without any side effects const defaultElementMethods = { setAttribute: HTMLElement.prototype.setAttribute, + setAttributeNS: HTMLElement.prototype.setAttributeNS, getAttribute: HTMLElement.prototype.getAttribute, + getAttributeNS: HTMLElement.prototype.getAttributeNS, removeAttribute: HTMLElement.prototype.removeAttribute, remove: HTMLElement.prototype.remove, removeChild: HTMLElement.prototype.removeChild @@ -259,6 +261,13 @@ class DDGRuntimeChecks extends HTMLElement { return this._callMethod('getAttribute', name, value) } + getAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('getAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.getAttribute, this, [name, value]) + } + setAttribute (name, value) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { @@ -268,6 +277,13 @@ class DDGRuntimeChecks extends HTMLElement { return this._callMethod('setAttribute', name, value) } + setAttributeNS (namespace, name, value) { + if (namespace) { + return this._callMethod('setAttributeNS', namespace, name, value) + } + return Reflect.apply(DDGRuntimeChecks.prototype.setAttribute, this, [name, value]) + } + removeAttribute (name) { if (shouldFilterKey(this.#tagName, 'attribute', name)) return if (supportedSinks.includes(name)) { diff --git a/src/features/runtime-checks/script-overload.js b/src/features/runtime-checks/script-overload.js index 2b7c50f56..63fd1752a 100644 --- a/src/features/runtime-checks/script-overload.js +++ b/src/features/runtime-checks/script-overload.js @@ -62,15 +62,17 @@ function constructProxy (scope, outputs) { return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property] + let targetOut = target + if (typeof property === 'string' && property in outputs) { + targetOut = outputs + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) @@ -127,7 +129,6 @@ function stringifyScope (scope, scopePath) { export function wrapScriptCodeOverload (code, config) { const processedConfig = {} for (const [key, value] of Object.entries(config)) { - // @ts-expect-error - Expected 2 arguments, but got 1 processedConfig[key] = processAttr(value) } // Don't do anything if the config is empty diff --git a/src/globals.d.ts b/src/globals.d.ts index 5e20e23bd..193d6bcd6 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -15,7 +15,8 @@ declare namespace contentScopeFeatures { interface ImportMeta { env: 'production' | 'development' platform?: 'windows' | 'integration' - injectName?: string + injectName?: string, + trackerLookup?: Record } declare module '*.svg' { diff --git a/src/trackers.js b/src/trackers.js index 2358f945f..1f0291feb 100644 --- a/src/trackers.js +++ b/src/trackers.js @@ -4,8 +4,7 @@ * @param {object} trackerLookup Trie lookup of tracker domains * @returns {boolean} True iff the origin is a tracker. */ -export function isTrackerOrigin (trackerLookup) { - const originHostname = document.location.hostname +export function isTrackerOrigin (trackerLookup, originHostname = document.location.hostname) { const parts = originHostname.split('.').reverse() let node = trackerLookup for (const sub of parts) { diff --git a/src/utils.js b/src/utils.js index b0add3771..2025d50f3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -99,7 +99,7 @@ export function isBeingFramed () { * Best guess effort if the document is third party * @returns {boolean} if we infer the document is third party */ -export function isThirdParty () { +export function isThirdPartyFrame () { if (!isBeingFramed()) { return false } @@ -107,6 +107,19 @@ export function isThirdParty () { return !matchHostname(globalThis.location.hostname, getTabHostname()) } +function isThirdPartyOrigin (hostname) { + return matchHostname(globalThis.location.hostname, hostname) +} + +export function hasThirdPartyOrigin (scriptOrigins) { + for (const origin of scriptOrigins) { + if (isThirdPartyOrigin(origin)) { + return true + } + } + return false +} + /** * Best guess effort of the tabs hostname; where possible always prefer the args.site.domain * @returns {string|null} inferred tab hostname @@ -319,7 +332,7 @@ const functionMap = { /** * Handles the processing of a config setting. * @param {*} configSetting - * @param {*} defaultValue + * @param {*} [defaultValue] * @returns */ export function processAttr (configSetting, defaultValue) { @@ -493,6 +506,16 @@ export function isUnprotectedDomain (topLevelHostname, featureList) { * @property {string} sessionKey */ +/** + * Used to inialize extension code in the load phase + */ +export function computeLimitedSiteObject () { + const topLevelHostname = getTabHostname() + return { + domain: topLevelHostname + } +} + /** * Expansion point to add platform specific versioning logic * @param {UserPreferences} preferences @@ -550,13 +573,20 @@ function isSupportedVersion (minSupportedVersion, currentVersion) { } /** - * @param {{ features: Record; unprotectedTemporary: string[]; }} data + * @typedef RemoteConfig + * @property {Record} features + * @property {string[]} unprotectedTemporary + */ + +/** + * @param {RemoteConfig} data * @param {string[]} userList * @param {UserPreferences} preferences * @param {string[]} platformSpecificFeatures */ export function processConfig (data, userList, preferences, platformSpecificFeatures = []) { const topLevelHostname = getTabHostname() + const site = computeLimitedSiteObject() const allowlisted = userList.filter(domain => domain === topLevelHostname).length > 0 const remoteFeatureNames = Object.keys(data.features) const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)) @@ -568,37 +598,65 @@ export function processConfig (data, userList, preferences, platformSpecificFeat output.platform.version = version } } + const enabledFeatures = computeEnabledFeatures(data, topLevelHostname, preferences.platform?.version, platformSpecificFeatures) + const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary) + output.site = Object.assign(site, { + isBroken, + allowlisted, + enabledFeatures + }) + // TODO + output.cookie = {} + + // Copy feature settings from remote config to preferences object + output.featureSettings = parseFeatureSettings(data, enabledFeatures) + output.trackerLookup = import.meta.trackerLookup + + return output +} + +/** + * Retutns a list of enabled features + * @param {RemoteConfig} data + * @param {string | null} topLevelHostname + * @param {Platform['version']} platformVersion + * @param {string[]} platformSpecificFeatures + * @returns {string[]} + */ +export function computeEnabledFeatures (data, topLevelHostname, platformVersion, platformSpecificFeatures = []) { + const remoteFeatureNames = Object.keys(data.features) + const platformSpecificFeaturesNotInRemoteConfig = platformSpecificFeatures.filter((featureName) => !remoteFeatureNames.includes(featureName)) const enabledFeatures = remoteFeatureNames.filter((featureName) => { const feature = data.features[featureName] // Check that the platform supports minSupportedVersion checks and that the feature has a minSupportedVersion - if (feature.minSupportedVersion && preferences.platform?.version) { - if (!isSupportedVersion(feature.minSupportedVersion, preferences.platform.version)) { + if (feature.minSupportedVersion && platformVersion) { + if (!isSupportedVersion(feature.minSupportedVersion, platformVersion)) { return false } } return feature.state === 'enabled' && !isUnprotectedDomain(topLevelHostname, feature.exceptions) }).concat(platformSpecificFeaturesNotInRemoteConfig) // only disable platform specific features if it's explicitly disabled in remote config - const isBroken = isUnprotectedDomain(topLevelHostname, data.unprotectedTemporary) - output.site = { - domain: topLevelHostname, - isBroken, - allowlisted, - enabledFeatures - } - // TODO - output.cookie = {} + return enabledFeatures +} - // Copy feature settings from remote config to preferences object - output.featureSettings = {} +/** + * Returns the relevant feature settings for the enabled features + * @param {RemoteConfig} data + * @param {string[]} enabledFeatures + * @returns {Record} + */ +export function parseFeatureSettings (data, enabledFeatures) { + /** @type {Record} */ + const featureSettings = {} + const remoteFeatureNames = Object.keys(data.features) remoteFeatureNames.forEach((featureName) => { if (!enabledFeatures.includes(featureName)) { return } - output.featureSettings[featureName] = data.features[featureName].settings + featureSettings[featureName] = data.features[featureName].settings }) - - return output + return featureSettings } export function isGloballyDisabled (args) { diff --git a/tsconfig.json b/tsconfig.json index 1f42f355b..2512d6174 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,15 @@ { "compilerOptions": { "target": "es2021", - "module": "ES2020", + "module": "ESNext", "moduleResolution": "node", "alwaysStrict": true, "allowJs": true, "checkJs": true, "noEmit": true, "noImplicitReturns": true, - "strictNullChecks": true + "strictNullChecks": true, + "resolveJsonModule": true, }, "include": [ "src", diff --git a/unit-test/dom-utils.js b/unit-test/dom-utils.js new file mode 100644 index 000000000..fb86f184f --- /dev/null +++ b/unit-test/dom-utils.js @@ -0,0 +1,29 @@ +import { html } from '../src/dom-utils.js' + +describe('dom-utils.js - escapedTemplate', () => { + const tests = [ + { title: 'single', input: () => html`

Foo

`, expected: '

Foo

' }, + { title: 'siblings', input: () => html`

Foo

Bar

`, expected: '

Foo

Bar

' }, + { title: 'nested', input: () => html`
${html`

${'Nested'}

`}
`, expected: '

Nested

' }, + { + title: 'loop', + input: () => { + const items = [{ value: 'foo' }, { value: 'bar' }] + return html`

Heading

+
    + ${items.map(item => html`
  • ${item.value}
  • `)}; +
` + }, + expected: `

Heading

+
    +
  • foo
  • bar
  • ; +
` + } + ] + for (const test of tests) { + it(`should generate ${test.title}`, () => { + const actual = test.input().toString() + expect(actual).toEqual(test.expected) + }) + } +}) diff --git a/unit-test/script-overload-snapshots/out/1.js b/unit-test/script-overload-snapshots/out/1.js index 23631acb1..52a5848b3 100644 --- a/unit-test/script-overload-snapshots/out/1.js +++ b/unit-test/script-overload-snapshots/out/1.js @@ -14,15 +14,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property] + let targetOut = target + if (typeof property === 'string' && property in outputs) { + targetOut = outputs + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) diff --git a/unit-test/script-overload-snapshots/out/2.js b/unit-test/script-overload-snapshots/out/2.js index b6e3f2929..9077785f0 100644 --- a/unit-test/script-overload-snapshots/out/2.js +++ b/unit-test/script-overload-snapshots/out/2.js @@ -14,15 +14,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property] + let targetOut = target + if (typeof property === 'string' && property in outputs) { + targetOut = outputs + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) diff --git a/unit-test/script-overload-snapshots/out/3.js b/unit-test/script-overload-snapshots/out/3.js index 862998eb0..e43eab71d 100644 --- a/unit-test/script-overload-snapshots/out/3.js +++ b/unit-test/script-overload-snapshots/out/3.js @@ -14,15 +14,17 @@ return new Proxy(scope, { get (target, property, receiver) { const targetObj = target[property] + let targetOut = target + if (typeof property === 'string' && property in outputs) { + targetOut = outputs + } + // Reflects functions with the correct 'this' scope if (typeof targetObj === 'function') { return (...args) => { - return Reflect.apply(target[property], target, args) + return Reflect.apply(targetOut[property], target, args) } } else { - if (typeof property === 'string' && property in outputs) { - return Reflect.get(outputs, property, receiver) - } - return Reflect.get(target, property, receiver) + return Reflect.get(targetOut, property, receiver) } } }) diff --git a/unit-test/utils.js b/unit-test/utils.js index 61b201e30..3066cbe57 100644 --- a/unit-test/utils.js +++ b/unit-test/utils.js @@ -86,7 +86,9 @@ describe('Helpers checks', () => { version: 99 }, versionNumber: 99, - sessionKey: 'testSessionKey' + sessionKey: 'testSessionKey', + // import.meta.trackerLookup is undefined because we've not overloaded it + trackerLookup: undefined }) }) @@ -161,7 +163,8 @@ describe('Helpers checks', () => { version: '0.9.9' }, versionString: '0.9.9', - sessionKey: 'testSessionKey' + sessionKey: 'testSessionKey', + trackerLookup: undefined }) }) diff --git a/unit-test/verify-artifacts.js b/unit-test/verify-artifacts.js index f38c92e2f..469d13cb9 100644 --- a/unit-test/verify-artifacts.js +++ b/unit-test/verify-artifacts.js @@ -13,43 +13,72 @@ if (process.platform === 'win32') { } const checks = { - android: [ - { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE, path: join(BUILD, 'android/contentScope.js') } - ], - chrome: [ - { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE_CHROME, path: join(BUILD, 'chrome/inject.js') } - ], - 'chrome-mv3': [ - { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE, path: join(BUILD, 'chrome-mv3/inject.js') }, - { kind: 'containsString', text: 'cloneInto(', path: join(BUILD, 'chrome-mv3/inject.js'), includes: false } - ], - firefox: [ - { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE, path: join(BUILD, 'firefox/inject.js') }, - { kind: 'containsString', text: 'cloneInto(', path: join(BUILD, 'firefox/inject.js'), includes: true } - ], - integration: [], - windows: [ - { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE, path: join(BUILD, 'windows/contentScope.js') } - ], - apple: [ - { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE, path: join(APPLE_BUILD, 'contentScope.js') } - ] + android: { + file: join(BUILD, 'android/contentScope.js'), + tests: [ + { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, + { kind: 'containsString', text: 'output.trackerLookup = {', includes: true } + ] + }, + chrome: { + file: join(BUILD, 'chrome/inject.js'), + tests: [ + { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE_CHROME }, + { kind: 'containsString', text: '$TRACKER_LOOKUP$', includes: true } + ] + }, + 'chrome-mv3': { + file: join(BUILD, 'chrome-mv3/inject.js'), + tests: [ + { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, + { kind: 'containsString', text: 'cloneInto(', includes: false }, + { kind: 'containsString', text: '$TRACKER_LOOKUP$', includes: true } + ] + }, + firefox: { + file: join(BUILD, 'firefox/inject.js'), + tests: [ + { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, + { kind: 'containsString', text: 'cloneInto(', includes: true }, + { kind: 'containsString', text: '$TRACKER_LOOKUP$', includes: true } + ] + }, + integration: { + file: join(BUILD, 'integration/contentScope.js'), + tests: [ + { kind: 'containsString', text: 'const trackerLookup = {', includes: true } + ] + }, + windows: { + file: join(BUILD, 'windows/contentScope.js'), + tests: [ + { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, + { kind: 'containsString', text: 'output.trackerLookup = {', includes: true } + ] + }, + apple: { + file: join(APPLE_BUILD, 'contentScope.js'), + tests: [ + { kind: 'maxFileSize', value: CSS_OUTPUT_SIZE }, + { kind: 'containsString', text: 'output.trackerLookup = {', includes: true } + ] + } } describe('checks', () => { for (const [platformName, platformChecks] of Object.entries(checks)) { - for (const check of platformChecks) { - const localPath = relative(ROOT, check.path) + for (const check of platformChecks.tests) { + const localPath = relative(ROOT, platformChecks.file) if (check.kind === 'maxFileSize') { it(`${platformName}: '${localPath}' is smaller than ${check.value}`, () => { - const stats = statSync(check.path) - // @ts-expect-error - can't infer that value is a number without adding types + const stats = statSync(platformChecks.file) expect(stats.size).toBeLessThan(check.value) }) } if (check.kind === 'containsString') { it(`${platformName}: '${localPath}' contains ${check.text}`, () => { const fileContents = readFileSync(localPath).toString() + // @ts-expect-error - can't infer that value is a number without adding types const includes = fileContents.includes(check.text) if (check.includes) { expect(includes).toBeTrue()