Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/scriptInjection.js

Issue 29737561: Issue 6539, 6782 - Implement support for snippets (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Rebase Created May 2, 2018, 7:50 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/cssInjection.js ('k') | metadata.chrome » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/scriptInjection.js
===================================================================
new file mode 100644
--- /dev/null
+++ b/lib/scriptInjection.js
@@ -0,0 +1,153 @@
+/*
+ * This file is part of Adblock Plus <https://adblockplus.org/>,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * Adblock Plus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * Adblock Plus 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 Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+"use strict";
+
+const {RegExpFilter} = require("../adblockpluscore/lib/filterClasses");
+const {Snippets, compileScript} = require("../adblockpluscore/lib/snippets");
+const {verifySignature} = require("../adblockpluscore/lib/rsa");
+const {extractHostFromFrame} = require("./url");
+const {checkWhitelisted} = require("./whitelisting");
+const info = require("../buildtools/info");
+
+const {typeMap} = RegExpFilter;
+const {getScriptsForDomain} = Snippets;
+
+const remoteURL = "https://easylist-downloads.adblockplus.org/snippets.js";
+
+let libraries = {local: "", remote: ""};
+let executableCode = new Map();
+
+function fetchText(url)
+{
+ return fetch(url, {cache: "no-cache"}).then(
+ response => response.ok ? response.text() : ""
hub 2018/05/09 12:23:00 you should return a promise if response is not ok.
Manish Jethani 2018/05/09 13:47:38 The function already returns a promise. That promi
hub 2018/05/09 14:27:07 ok.
+ );
+}
+
+function updateLibrary(name, text)
+{
+ libraries[name] = text;
+
+ executableCode.clear();
+}
+
+function checkLibrarySignature(url, text)
+{
+ return fetchText(`${url}.sig`).then(
+ signature => fetchText(browser.extension.getURL("/key")).then(
+ key => verifySignature(key.replace(/=/g, ""), signature, text)
+ )
+ );
+}
+
+function loadLibrary(name, url, {verify = true} = {})
+{
+ fetchText(url).then(text =>
+ {
+ if (text != libraries[name])
+ {
+ let check = verify ? checkLibrarySignature(url, text) :
+ Promise.resolve(true);
+ check.then(ok =>
+ {
+ if (ok)
+ updateLibrary(name, text);
+ });
+ }
+ });
+}
+
+function loadLocalLibrary()
+{
+ loadLibrary("local", browser.extension.getURL("/snippets.js"),
+ {verify: false});
+}
+
+function loadRemoteLibrary()
+{
+ loadLibrary("remote", remoteURL);
+}
+
+function getExecutableCode(script)
+{
+ let code = executableCode.get(script);
+ if (code)
+ return code;
+
+ code = compileScript(script, [libraries.local, libraries.remote]);
+
+ executableCode.set(script, code);
+ return code;
+}
+
+function injectCode(script, tabId, frameId)
+{
+ try
+ {
+ browser.tabs.executeScript(tabId, {
+ code: getExecutableCode(script),
+ frameId,
+ matchAboutBlank: true,
+ runAt: "document_start"
+ })
hub 2018/05/09 17:19:49 shouldn't we log that the filter was applied (ie i
Manish Jethani 2018/05/23 05:12:45 You're right, let me look into that.
+ .catch(error =>
+ {
+ // Sometimes a frame is added and removed very quickly, in such cases we
+ // simply ignore the error.
+ if (error.message == "The frame was removed.")
+ return;
+
+ throw error;
+ });
+ }
+ catch (error)
+ {
+ }
+}
+
+loadLocalLibrary();
+
+// Only Chrome supports dynamic loading of JS.
+if (info.platform == "chromium")
+{
+ loadRemoteLibrary();
+
+ // Download every 24 hours.
+ setInterval(loadRemoteLibrary, 24 * 60 * 60 * 1000);
+}
+
+browser.webNavigation.onCommitted.addListener(({tabId, frameId, url}) =>
+{
+ // There's a bug in Chrome that causes webNavigation.onCommitted to get
+ // dispatched twice if there's a URL filter present, therefore we must listen
+ // for all URLs and do an explicit check here.
+ // https://crbug.com/827855
+ if (!/^(https?:\/\/|about:blank\b|about:srcdoc\b)/.test(url))
+ return;
+
+ let page = new ext.Page({id: tabId, url});
+ let frame = ext.getFrame(tabId, frameId);
+
+ if (checkWhitelisted(page, frame, null, typeMap.DOCUMENT | typeMap.ELEMHIDE))
+ return;
+
+ let hostname = extractHostFromFrame(frame);
+
+ for (let script of getScriptsForDomain(hostname))
+ injectCode(script, tabId, frameId);
+});
« no previous file with comments | « lib/cssInjection.js ('k') | metadata.chrome » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld