diff options
| -rw-r--r-- | bg/ExternalLicenses.js | 34 | ||||
| -rw-r--r-- | content/externalLicenseChecker.js | 23 | ||||
| -rw-r--r-- | main_background.js | 34 | 
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);  | 
