From 14bed707e5c9891d4502e276a757bbef014e6b4e Mon Sep 17 00:00:00 2001
From: hackademix
Date: Fri, 22 Feb 2019 00:41:05 +0100
Subject: Deduplicate inline scripts and provide widgets to show them in main
UI.
---
html/display_panel/content/display-panel.html | 4 ++-
html/display_panel/content/main_panel.js | 11 +++++-
html/display_panel/content/panel-styles.css | 14 ++++++++
main_background.js | 48 +++++++++++++++++----------
4 files changed, 57 insertions(+), 20 deletions(-)
diff --git a/html/display_panel/content/display-panel.html b/html/display_panel/content/display-panel.html
index 0e4df97..5eccf60 100644
--- a/html/display_panel/content/display-panel.html
+++ b/html/display_panel/content/display-panel.html
@@ -73,7 +73,8 @@
diff --git a/html/display_panel/content/main_panel.js b/html/display_panel/content/main_panel.js
index 7934fee..60eae55 100644
--- a/html/display_panel/content/main_panel.js
+++ b/html/display_panel/content/main_panel.js
@@ -55,6 +55,10 @@ liTemplate.remove();
document.querySelector("#info").addEventListener("click", e => {
let button = e.target;
+ if (button.matches(".toggle-source")) {
+ let sourceContainer = button.parentNode.querySelector(".source").classList.toggle("visible");
+ return;
+ }
if (!button.matches(".buttons > button")) return;
let li = button.closest("li");
let entry = li && li._scriptEntry || [currentReport.url, "Page's site"];
@@ -111,7 +115,7 @@ function createList(data, group){
container.classList.add("empty");
}
// generate list
- let viewSourceToHuman = /^view-source:(.*)#line(\d+)\(([^)]*)\).*/;
+ let viewSourceToHuman = /^view-source:(.*)#line(\d+)\(([^)]*)\)[^]*/;
for (let entry of entries) {
let [scriptId, reason] = entry;
let li = liTemplate.cloneNode(true);
@@ -119,6 +123,11 @@ function createList(data, group){
a.href = scriptId.split("(")[0];
if (scriptId.startsWith("view-source:")) {
a.target ="LibreJS-ViewSource";
+ let source = scriptId.split("\n")[1];
+ if (source) {
+ li.querySelector(".source").textContent = decodeURIComponent(source);
+ li.querySelector(".toggle-source").style.display = "inline";
+ }
scriptId = scriptId.replace(viewSourceToHuman, "$3 at line $2 of $1");
}
a.textContent = scriptId;
diff --git a/html/display_panel/content/panel-styles.css b/html/display_panel/content/panel-styles.css
index d5c3528..1bacc01 100644
--- a/html/display_panel/content/panel-styles.css
+++ b/html/display_panel/content/panel-styles.css
@@ -109,6 +109,20 @@ button:disabled {
color: #888 !important;
}
+button.toggle-source {
+ display: none;
+}
+pre.source {
+ display: none;
+ background: white;
+ border: 1px solid #444;
+ padding: .5em;
+ overflow: auto;
+ max-height: 8em;
+ white-space: pre-wrap;
+}
+pre.source.visible { display: block }
+
span.accepted, span.blocked {
color:#008e00;
font-size:145%;
diff --git a/main_background.js b/main_background.js
index 65ffe60..324c68e 100644
--- a/main_background.js
+++ b/main_background.js
@@ -1064,6 +1064,7 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
// Do not process inline scripts
scripts = [];
} else {
+ let dejaVu = new Map(); // deduplication map & edited script cache
let modified = false;
// Deal with intrinsic events
let intrinsecindex = 0;
@@ -1071,21 +1072,27 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
for (let element of html_doc.all) {
let line = -1;
for (let attr of element.attributes) {
- if (attr.name.startsWith("on") || (attr.name === "href" && attr.value.toLowerCase().startsWith("javascript:"))){
+ let {name, value} = attr;
+ value = value.trim();
+ if (name.startsWith("on") || (name === "href" && value.toLowerCase().startsWith("javascript:"))){
intrinsecindex++;
if (line === -1) {
line = findLine(intrinsicFinder);
}
try {
- let url = `view-source:${documentUrl}#line${line}(<${element.tagName} ${attr.name}>)(${intrinsicIndex})`;
- let edited = await get_script(attr.value, url, tabId, whitelist.contains(url));
- if (edited) {
- let value = edited;
- if (value !== attr.value) {
- modified = true;
- attr.value = value;
- }
- }
+ let key = `<${element.tagName} ${name}="${value}">`;
+ let edited;
+ if (dejaVu.has(key)) {
+ edited = dejaVu.get(key);
+ } else {
+ let url = `view-source:${documentUrl}#line${line}(<${element.tagName} ${name}>)\n${encodeURIComponent(value.trim())}`;
+ edited = await get_script(value, url, tabId, whitelist.contains(documentUrl));
+ dejaVu.set(key, edited);
+ }
+ if (edited && edited !== value) {
+ modified = true;
+ attr.value = edited;
+ }
} catch (e) {
console.error(e);
}
@@ -1099,14 +1106,19 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
let script = scripts[i];
let line = findLine(scriptFinder);
if (!script.src && !(script.type && script.type !== "text/javascript")) {
- let source = script.textContent;
- let url = `view-source:${documentUrl}#line${line}(