Files
i2p.plugins.firefox/src/i2p.chromium.base.profile/extensions/noscript.js/content/content.js
idk 224e248828 update index.html
Former-commit-id: 1aeb795450
Former-commit-id: a7fc182903a537a77ef31f322034e9c99a2cd9d5
2022-08-31 20:58:42 -04:00

232 lines
6.6 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';
//
debug = () => {};
function _(...args) {
let fakeLang = navigator.language === "en-US" &&
browser.i18n.getUILanguage() !== "en-US";
return (_ = (template, ...substitutions) => {
let [key, defTemplate] = template.split("|");
return fakeLang
? (defTemplate || key).replace(/\$([1-9])/g,
(m, p) => substitutions[parseInt(p) - 1] || "$" + p)
: browser.i18n.getMessage(template, ...substitutions);
})(...args);
}
function createHTMLElement(name) {
return document.createElementNS("http://www.w3.org/1999/xhtml", name);
}
var seen = {
_map: new Map(),
_list: null,
record(event) {
let key = event.request.key;
if (this._map.has(key)) return;
this._map.set(key, event);
this._list = null;
},
recordAll(events) {
this._map.clear();
for (let e of events) this.record(e);
},
get list() {
return this._list || (this._list = [...this._map.values()]);
}
}
Messages.addHandler({
seen(event) {
let {allowed, policyType, request, ownFrame, serviceWorker} = event;
if (serviceWorker) {
for (let e of seen.list) {
let {request} = e;
if (e.serviceWorker === serviceWorker ||
(request.type === "main_frame" || request.type === "sub_frame") &&
new URL(request.url).origin === serviceWorker) {
seen.record(event);
break;
}
}
return;
}
if (window.top === window) {
seen.record(event);
}
if (ownFrame) {
if (!allowed && PlaceHolder.canReplace(policyType)) {
request.embeddingDocument = ns.embeddingDocument;
PlaceHolder.create(policyType, request);
}
}
},
allSeen(event) {
seen.recordAll(event.seen);
notifyPage();
},
collect(event) {
let list = seen.list;
debug("COLLECT", list);
return list;
},
store(event) {
if (document.URL !== event.url) return;
let {data} = event;
let attr = sha256(data.concat(Math.random()));
document.documentElement.dataset[attr] = data;
return attr;
},
retrieve(event) {
if (document.URL !== event.url) return;
let {attr, preserve} = event;
if (!attr) {
// legacy, < 11.0.39rc8
return document.documentElement.lastChild.textContent;
}
let data = document.documentElement.dataset[attr];
if (!preserve) delete document.documentElement.dataset[attr];
return data;
}
});
debug(`Loading NoScript in document %s, scripting=%s, readyState %s`,
document.URL, ns.canScript, document.readyState);
var notifyPage = async () => {
debug("Page %s shown, %s", document.URL, document.readyState);
if (document.readyState === "complete") {
try {
await Messages.send("pageshow", {seen: seen.list, canScript: ns.canScript});
return true;
} catch (e) {
debug(e);
if (Messages.isMissingEndpoint(e)) {
window.setTimeout(notifyPage, 2000);
}
}
}
return false;
}
window.addEventListener("pageshow", notifyPage);
let violations = new Set();
let documentOrigin = new URL(document.URL).origin;
window.addEventListener("securitypolicyviolation", e => {
if (!e.isTrusted) return;
let {violatedDirective, originalPolicy} = e;
let type = violatedDirective.split("-", 1)[0]; // e.g. script-src 'none' => script
let url = e.blockedURI;
if (type === "media" && /^data\b/.test(url) && (!CSP.isMediaBlocker(originalPolicy) ||
ns.embeddingDocument || !document.querySelector("video,audio")))
return;
if (!ns.CSP || !(CSP.normalize(originalPolicy).includes(ns.CSP))) {
// this seems to come from page's own CSP
return;
}
let documentUrl = document.URL;
let origin;
if (!(url && url.includes(":"))) {
url = documentUrl;
origin = documentOrigin;
} else {
({origin} = new URL(url));
}
let key = RequestKey.create(origin, type, documentOrigin);
if (violations.has(key)) return;
violations.add(key);
if (type === "frame") type = "sub_frame";
seen.record({
policyType: type,
request: {
key,
url,
type,
documentUrl,
},
allowed: false
});
Messages.send("violation", {url, type});
}, true);
ns.on("capabilities", () => {
seen.record({
request: {
key: "noscript-probe",
url: document.URL,
documentUrl: document.URL,
type: window === window.top ? "main_frame" : "script",
},
allowed: ns.canScript
});
if (!(ns.policy.isTorBrowser || ns.allows("unchecked_css"))) {
// protection against CSS PP0, not needed on the Tor Browser because of its
// noisy DNS resolution: https://orenlab.sise.bgu.ac.il/p/PP0
let prefetchCallback =
false &&
(location.hostname === 'localhost' && location.search.includes("debug_prefetch"))
? (rule, url) => {
debug("Prefetching %s from CSS", url, rule.cssText);
url.hostname = `prefetch.${url.hostname}`;
return false; // let default processing continue with the modified hostname
} : null;
prefetchCSSResources(true, prefetchCallback);
}
if (!ns.canScript) {
try {
if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
(async () => {
for (let r of await navigator.serviceWorker.getRegistrations()) {
await r.unregister();
}
})();
}
} catch (e) {
debug(e);
}
onScriptDisabled();
}
notifyPage();
});
ns.fetchPolicy();
notifyPage();
addEventListener("DOMContentLoaded", e => {
if (ns.canScript) return;
for (let m of document.querySelectorAll("meta[http-equiv=refresh]")) {
if (/^[^,;]*[,;](?:\W*url[^=]*=)?[^!#$%&()*+,/:;=?@[\]\w.,~-]*data:/i.test(m.getAttribute("content"))) {
let url = m.getAttribute("content").replace(/.*?(?=data:)/i, "");
log(`Blocking refresh to ${url}`);
window.stop();
}
}
});