aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bg/ExternalLicenses.js34
-rw-r--r--content/externalLicenseChecker.js23
-rw-r--r--main_background.js34
3 files changed, 59 insertions, 32 deletions
diff --git a/bg/ExternalLicenses.js b/bg/ExternalLicenses.js
index 74692d7..0b2c911 100644
--- a/bg/ExternalLicenses.js
+++ b/bg/ExternalLicenses.js
@@ -35,13 +35,24 @@ let licensesByURL = new Map();
}
}
+let cachedHrefs = new Map();
+
var ExternalLicenses = {
+ purgeCache(tabId) {
+ cachedHrefs.delete(tabId);
+ },
+
async check(script) {
- let {url, tabId, frameId} = script;
+ let {url, tabId, frameId, documentUrl} = script;
+ let tabCache = cachedHrefs.get(tabId);
+ let frameCache = tabCache && tabCache.get(frameId);
+ let cache = frameCache && frameCache.get(documentUrl);
let scriptInfo = await browser.tabs.sendMessage(tabId, {
action: "checkLicensedScript",
- url
+ url,
+ cache,
}, {frameId});
+
if (!(scriptInfo && scriptInfo.licenseURLs.length)) {
return null;
}
@@ -65,12 +76,24 @@ var ExternalLicenses = {
/**
* moves / creates external license references before any script in the page
- * if needed, to have them ready when the first script load is triggered
+ * if needed, to have them ready when the first script load is triggered.
+ * It also caches the external licens href by page URL, to help not actually
+ * modify the rendered HTML but rather feed the content script on demand.
* Returns true if the document has been actually modified, false otherwise.
*/
- optimizeDocument(document) {
+ optimizeDocument(document, cachePointer) {
+ let cache = {};
+ let {tabId, frameId, documentUrl} = cachePointer;
+ let frameCache = cachedHrefs.get(tabId);
+ if (!frameCache) {
+ cachedHrefs.set(tabId, frameCache = new Map());
+ }
+ frameCache.set(frameId, new Map([[documentUrl, cache]]));
+
let link = document.querySelector(`link[rel="jslicense"], link[data-jslicense="1"], a[rel="jslicense"], a[data-jslicense="1"]`);
if (link) {
+ let href = link.getAttribute("href");
+ cache.webLabels = {href};
let move = () => !!document.head.insertBefore(link, document.head.firstChild);
if (link.parentNode === document.head) {
for (let node; node = link.previousElementSibling;) {
@@ -82,12 +105,13 @@ var ExternalLicenses = {
if (link.tagName.toUpperCase() === "A") {
let newLink = document.createElement("link");
newLink.rel = "jslicense";
- newLink.setAttribute("href", link.getAttribute("href"));
+ newLink.setAttribute("href", href);
link = newLink;
}
return move();
}
}
+
return false;
}
};
diff --git a/content/externalLicenseChecker.js b/content/externalLicenseChecker.js
index f150cea..be09ef1 100644
--- a/content/externalLicenseChecker.js
+++ b/content/externalLicenseChecker.js
@@ -22,12 +22,12 @@
{
let licensedScripts = null;
- let fetchWebLabels = async (map = new Map()) => {
+ let fetchWebLabels = async args => {
// see https://www.gnu.org/software/librejs/free-your-javascript.html#step3
-
+ let {map, cache} = args;
let link = document.querySelector(`link[rel="jslicense"], link[data-jslicense="1"], a[rel="jslicense"], a[data-jslicense="1"]`);
- if (link) try {
- let baseURL = link.href;
+ let baseURL = link ? link.href : cache.webLabels && new URL(cache.webLabels.href, document.baseURI);
+ if (baseURL) try {
let response = await fetch(baseURL);
if (!response.ok) throw `${response.status} ${response.statusText}`;
let doc = new DOMParser().parseFromString(
@@ -55,16 +55,16 @@
return map;
}
- let fetchLicenseInfo = async () => {
+ let fetchLicenseInfo = async cache => {
let map = new Map();
-
+ let args = {map, cache};
// in the fetchXxx methods we add to a map whatever license(s)
// URLs and source code references we can find in various formats
// (WebLabels is currently the only implementation), keyed by script URLs.
await Promise.all([
- fetchWebLabels(map),
- // fetchXmlSpdx(),
- // fetchTxtSpdx(),
+ fetchWebLabels(args),
+ // fetchXmlSpdx(args),
+ // fetchTxtSpdx(args),
// ...
]);
return map;
@@ -72,8 +72,8 @@
let handlers = {
async checkLicensedScript(m) {
- let {url} = m;
- if (!licensedScripts) licensedScripts = await fetchLicenseInfo();
+ let {url, cache} = m;
+ if (!licensedScripts) licensedScripts = await fetchLicenseInfo(cache);
return licensedScripts.get(url);
}
}
@@ -82,7 +82,6 @@
if (m.action in handlers) try {
debug("Received message", m);
let result = await handlers[m.action](m);
- console.debug("Returning", result);
return result;
} catch (e) {
console.error(e);
diff --git a/main_background.js b/main_background.js
index a521d22..e2c3635 100644
--- a/main_background.js
+++ b/main_background.js
@@ -424,6 +424,7 @@ function delete_removed_tab_info(tab_id, remove_info){
if(activeMessagePorts[tab_id] !== undefined){
delete activeMessagePorts[tab_id];
}
+ ExternalLicenses.purgeCache(tab_id);
}
/**
@@ -855,14 +856,14 @@ var ResponseHandler = {
*/
async pre(response) {
let {request} = response;
- let {url, type, tabId, frameId} = request;
+ let {url, type, tabId, frameId, documentUrl} = request;
url = ListStore.urlItem(url);
let site = ListStore.siteItem(url);
let blacklistedSite = blacklist.contains(site);
let blacklisted = blacklistedSite || blacklist.contains(url);
- let topUrl = request.frameAncestors && request.frameAncestors.pop() || request.documentUrl;
+ let topUrl = request.frameAncestors && request.frameAncestors.pop() || documentUrl;
if (blacklisted) {
if (type === "script") {
@@ -886,7 +887,7 @@ var ResponseHandler = {
"whitelisted": [url, whitelistedSite ? `User whitelisted ${site}` : "Whitelisted by user"]});
return ResponseProcessor.ACCEPT;
} else {
- let scriptInfo = await ExternalLicenses.check({url, tabId, frameId});
+ let scriptInfo = await ExternalLicenses.check({url, tabId, frameId, documentUrl});
if (scriptInfo) {
let verdict, ret;
let msg = scriptInfo.toString();
@@ -991,23 +992,26 @@ function read_metadata(meta_element){
return false;
}
}
-
/**
+
* Reads/changes the HTML of a page and the scripts within it.
*/
-function edit_html(html,url,tabid,wl){
+function edit_html(html, documentUrl, tabId, frameId, whitelisted){
+
return new Promise((resolve, reject) => {
- if(wl == true){
- // Don't bother, page is whitelisted
- resolve(html);
- }
-
+
var parser = new DOMParser();
var html_doc = parser.parseFromString(html, "text/html");
// moves external licenses reference, if any, before any <SCRIPT> element
- ExternalLicenses.optimizeDocument(html_doc);
+ ExternalLicenses.optimizeDocument(html_doc, {tabId, frameId, documentUrl});
+
+ if (whitelisted) { // don't bother rewriting
+ resolve(null);
+ }
+
+ let url = ListStore.urlItem(documentUrl);
var amt_scripts = 0;
var total_scripts = 0;
@@ -1030,7 +1034,7 @@ function edit_html(html,url,tabid,wl){
license = legacy_license_lib.check(first_script_src);
if(read_metadata(meta_element) || license != false ){
console.log("Valid license for intrinsic events found");
- addReportEntry(tabid, url, {url, "accepted":[url, `Global license for the page: ${license}`]});
+ addReportEntry(tabId, url, {url, "accepted":[url, `Global license for the page: ${license}`]});
// Do not process inline scripts
scripts="";
}else{
@@ -1072,7 +1076,7 @@ function edit_html(html,url,tabid,wl){
for(var i = 0; i < scripts.length; i++){
if (scripts[i].src == ""){
if (scripts[i].type=="" || scripts[i].type=="text/javascript"){
- var edit_script = get_script(scripts[i].innerHTML,url,tabid,wl,i);
+ var edit_script = get_script(scripts[i].innerHTML, url, tabId, whitelisted, i);
edit_script.then(function(edited){
var edited_source = edited[0];
var unedited_source = html_doc.scripts[edited[1]].innerHTML.trim();
@@ -1099,12 +1103,12 @@ function edit_html(html,url,tabid,wl){
*/
async function handle_html(response, whitelisted) {
let {text, request} = response;
- let {url, tabId, type} = request;
+ let {url, tabId, frameId, type} = request;
if (type === "main_frame") {
activityReports[tabId] = await createReport({url, tabId});
updateBadge(tabId);
}
- return await edit_html(text, ListStore.urlItem(url), tabId, whitelisted);
+ return await edit_html(text, url, tabId, frameId, whitelisted);
}
var whitelist = new ListStore("pref_whitelist", Storage.CSV);