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

Side by Side Diff: lib/scriptInjection.js

Issue 29737561: Issue 6539, 6782 - Implement support for snippets (Closed) Base URL: https://hg.adblockplus.org/adblockpluschrome/
Patch Set: Use adblockpluscore/lib/snippets.js for script parsing Created April 25, 2018, 6:30 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | metadata.chrome » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 "use strict";
19
20 const {RegExpFilter} = require("../adblockpluscore/lib/filterClasses");
21 const {Snippets} = require("../adblockpluscore/lib/snippets");
22 const {verifySignature} = require("../adblockpluscore/lib/rsa");
23 const {extractHostFromFrame} = require("./url");
24 const {checkWhitelisted} = require("./whitelisting");
25 const info = require("../buildtools/info");
26
27 const {typeMap} = RegExpFilter;
28
29 const remoteURL = "https://easylist-downloads.adblockplus.org/snippets.js";
30
31 let libraries = {local: "", remote: ""};
32 let executableCode = new Map();
33
34 function fetchText(url)
35 {
36 return fetch(url, {cache: "no-cache"}).then(
37 response => response.ok ? response.text() : ""
38 );
39 }
40
41 function updateLibrary(name, text)
42 {
43 libraries[name] = text;
44
45 executableCode.clear();
46 }
47
48 function checkLibrarySignature(url, text)
49 {
50 return fetchText(`${url}.sig`).then(
51 signature => fetchText(browser.extension.getURL("/key")).then(
52 key => verifySignature(key.replace(/=/g, ""), signature, text)
53 )
54 );
55 }
56
57 function loadLibrary(name, url, {verify = true} = {})
58 {
59 fetchText(url).then(text =>
60 {
61 if (text != libraries[name])
62 {
63 let check = verify ? checkLibrarySignature(url, text) :
64 Promise.resolve(true);
65 check.then(ok =>
66 {
67 if (ok)
68 updateLibrary(name, text);
69 });
70 }
71 });
72 }
73
74 function loadLocalLibrary()
75 {
76 loadLibrary("local", browser.extension.getURL("/snippets.js"),
77 {verify: false});
78 }
79
80 function loadRemoteLibrary()
81 {
82 loadLibrary("remote", remoteURL);
83 }
84
85 function getExecutableCode(script)
86 {
87 let code = executableCode.get(script);
88 if (code)
89 return code;
90
91 let parsedScript = Snippets.parseScript(script);
92
93 code = `
94 "use strict";
95 {
96 let localImports = Object.create(null);
97 let remoteImports = Object.create(null);
98 new Function("exports", ${JSON.stringify(libraries.local)})(
99 localImports
100 );
101 new Function("exports", ${JSON.stringify(libraries.remote)})(
102 remoteImports
103 );
104 let imports = Object.assign(Object.create(null),
105 localImports,
106 remoteImports);
107 let jsonScript = ${JSON.stringify(parsedScript)};
108 for (let [name, ...args] of jsonScript)
109 {
110 if (Object.prototype.hasOwnProperty.call(imports, name))
111 {
112 let value = imports[name];
113 if (typeof value == "function")
114 value(...args);
115 }
116 }
117 }
118 `;
119
120 executableCode.set(script, code);
121 return code;
122 }
123
124 function injectCode(script, tabId, frameId)
125 {
126 try
127 {
128 browser.tabs.executeScript(tabId, {
129 code: getExecutableCode(script),
130 frameId,
131 matchAboutBlank: true,
132 runAt: "document_start"
133 });
134 }
135 catch (error)
136 {
137 }
138 }
139
140 loadLocalLibrary();
141
142 // Only Chrome supports dynamic loading of JS.
143 if (info.platform == "chromium")
144 {
145 loadRemoteLibrary();
146
147 // Download every 24 hours.
148 setInterval(loadRemoteLibrary, 24 * 60 * 60 * 1000);
149 }
150
151 browser.webNavigation.onCommitted.addListener(({tabId, frameId, url}) =>
152 {
153 // There's a bug in Chrome that causes webNavigation.onCommitted to get
154 // dispatched twice if there's a URL filter present, therefore we must listen
155 // for all URLs and do an explicit check here.
156 // https://crbug.com/827855
157 if (!/^(https?:\/\/|about:blank\b|about:srcdoc\b)/.test(url))
158 return;
159
160 let page = new ext.Page({id: tabId, url});
161 let frame = ext.getFrame(tabId, frameId);
162
163 if (checkWhitelisted(page, frame, null, typeMap.DOCUMENT | typeMap.ELEMHIDE))
164 return;
165
166 let hostname = extractHostFromFrame(frame);
167
168 for (let {code} of Snippets.getScriptsForDomain(hostname))
169 injectCode(code, tabId, frameId);
170 });
OLDNEW
« no previous file with comments | « no previous file | metadata.chrome » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld