notes/.config/chromium/Default/Extensions/doojmbjmlfjjnbmnoijecmcbfeoakpjm/11.4.6_0/content/staticNS.js

179 lines
5.3 KiB
JavaScript

/*
* NoScript - a Firefox extension for whitelist driven safe JavaScript execution
*
* Copyright (C) 2005-2021 Giorgio Maone <https://maone.net>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
{
'use strict';
let listenersMap = new Map();
let backlog = new Set();
let ns = {
get embeddingDocument() {
delete this.embeddingDocument;
return this.embeddingDocument = CSP.isEmbedType(document.contentType);
},
on(eventName, listener) {
let listeners = listenersMap.get(eventName);
if (!listeners) listenersMap.set(eventName, listeners = new Set());
listeners.add(listener);
if (backlog.has(eventName)) this.fire(eventName, listener);
},
detach(eventName, listener) {
let listeners = listenersMap.get(eventName);
if (listeners) listeners.delete(listener);
},
fire(eventName, listener = null) {
if (listener) {
listener({type:eventName, source: this});
return;
}
let listeners = listenersMap.get(eventName);
if (listeners) {
for (let l of listeners) {
this.fire(eventName, l);
}
}
backlog.add(eventName);
},
fetchPolicy(sync = false) {
if (this.policy) return;
let url = document.URL;
debug(`Fetching policy from document %s, readyState %s`,
url, document.readyState
);
if (this.domPolicy) {
debug("Injected policy found!");
try {
this.setup(this.domPolicy);
return;
} catch(e) {
error(e);
}
}
if (this.syncFetchPolicy) {
// extra hops to ensure that scripts don't run when CSP has not been set through HTTP headers
this.syncFetchPolicy();
return;
}
this.pendingSyncFetchPolicy = true;
if (!sync) {
queueMicrotask(() => this.fetchPolicy(true));
return;
}
if (url.startsWith("blob:")) {
url = location.origin;
} else if (/^(?:javascript|about):/.test(url)) {
url = document.readyState === "loading" || !document.domain
? document.baseURI
: `${window.isSecureContext ? "https" : "http"}://${document.domain}`;
debug("Fetching policy for actual URL %s (was %s)", url, document.URL);
}
if (!this.syncFetchPolicy) {
this.fetchLikeNoTomorrow(url);
}
},
fetchLikeNoTomorrow(url, setup = this.setup.bind(this)) {
let msg = {id: "fetchChildPolicy", url};
let asyncFetch = (async () => {
let policy = null;
for (let attempts = 10; !(policy || this.policy) && attempts-- > 0;) {
try {
debug(`Retrieving policy asynchronously (${attempts} attempts left).`);
policy = await Messages.send(msg.id, msg) || this.domPolicy;
debug("Asynchronous policy", policy);
} catch (e) {
error(e, "(Asynchronous policy fetch)");
}
}
setup(policy);
});
if (!this.syncFetchPolicy && this.embeddingDocument) {
asyncFetch();
return;
}
debug(`Synchronously fetching policy for ${url}.`);
let policy = null;
let attempts = 100;
let refetch = () => {
try {
policy = browser.runtime.sendSyncMessage(msg) || this.domPolicy;
} catch (e) {
error(e);
}
if (policy) {
setup(policy);
} else if (attempts-- > 0) {
debug(`Couldn't retrieve policy synchronously (${attempts} attempts left).`);
if (asyncFetch) {
asyncFetch();
asyncFetch = null;
}
queueMicrotask(refetch);
}
};
refetch();
},
setup(policy) {
if (this.policy) return false;
if (!policy) {
policy = {permissions: {capabilities: []}, localFallback: true};
}
this.policy = policy;
if (!policy.permissions || policy.unrestricted) {
this.allows = () => true;
this.capabilities = Object.assign(
new Set(["script"]), { has() { return true; } });
} else {
let perms = policy.permissions;
if (!perms.capabilities.includes("script") && /^file:\/\/\/(?:[^#?]+\/)?$/.test(document.URL)) {
// allow browser UI scripts for directory navigation
perms.capabilities.push("script");
}
this.capabilities = new Set(perms.capabilities);
this.CSP = new DocumentCSP(document).apply(this.capabilities, this.embeddingDocument);
}
this.canScript = this.allows("script");
this.fire("capabilities");
return true;
},
policy: null,
allows(cap) {
return this.capabilities && this.capabilities.has(cap);
},
};
window.ns = window.ns ? Object.assign(ns, window.ns) : ns;
}