Left: | ||
Right: |
OLD | NEW |
---|---|
(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, compileScript} = 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 const {getScriptsForDomain} = Snippets; | |
29 | |
30 const remoteURL = "https://easylist-downloads.adblockplus.org/snippets.js"; | |
31 | |
32 let libraries = {local: "", remote: ""}; | |
33 let executableCode = new Map(); | |
34 | |
35 function fetchText(url) | |
36 { | |
37 return fetch(url, {cache: "no-cache"}).then( | |
38 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.
| |
39 ); | |
40 } | |
41 | |
42 function updateLibrary(name, text) | |
43 { | |
44 libraries[name] = text; | |
45 | |
46 executableCode.clear(); | |
47 } | |
48 | |
49 function checkLibrarySignature(url, text) | |
50 { | |
51 return fetchText(`${url}.sig`).then( | |
52 signature => fetchText(browser.extension.getURL("/key")).then( | |
53 key => verifySignature(key.replace(/=/g, ""), signature, text) | |
54 ) | |
55 ); | |
56 } | |
57 | |
58 function loadLibrary(name, url, {verify = true} = {}) | |
59 { | |
60 fetchText(url).then(text => | |
61 { | |
62 if (text != libraries[name]) | |
63 { | |
64 let check = verify ? checkLibrarySignature(url, text) : | |
65 Promise.resolve(true); | |
66 check.then(ok => | |
67 { | |
68 if (ok) | |
69 updateLibrary(name, text); | |
70 }); | |
71 } | |
72 }); | |
73 } | |
74 | |
75 function loadLocalLibrary() | |
76 { | |
77 loadLibrary("local", browser.extension.getURL("/snippets.js"), | |
78 {verify: false}); | |
79 } | |
80 | |
81 function loadRemoteLibrary() | |
82 { | |
83 loadLibrary("remote", remoteURL); | |
84 } | |
85 | |
86 function getExecutableCode(script) | |
87 { | |
88 let code = executableCode.get(script); | |
89 if (code) | |
90 return code; | |
91 | |
92 code = compileScript(script, [libraries.local, libraries.remote]); | |
93 | |
94 executableCode.set(script, code); | |
95 return code; | |
96 } | |
97 | |
98 function injectCode(script, tabId, frameId) | |
99 { | |
100 try | |
101 { | |
102 browser.tabs.executeScript(tabId, { | |
103 code: getExecutableCode(script), | |
104 frameId, | |
105 matchAboutBlank: true, | |
106 runAt: "document_start" | |
107 }) | |
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.
| |
108 .catch(error => | |
109 { | |
110 // Sometimes a frame is added and removed very quickly, in such cases we | |
111 // simply ignore the error. | |
112 if (error.message == "The frame was removed.") | |
113 return; | |
114 | |
115 throw error; | |
116 }); | |
117 } | |
118 catch (error) | |
119 { | |
120 } | |
121 } | |
122 | |
123 loadLocalLibrary(); | |
124 | |
125 // Only Chrome supports dynamic loading of JS. | |
126 if (info.platform == "chromium") | |
127 { | |
128 loadRemoteLibrary(); | |
129 | |
130 // Download every 24 hours. | |
131 setInterval(loadRemoteLibrary, 24 * 60 * 60 * 1000); | |
132 } | |
133 | |
134 browser.webNavigation.onCommitted.addListener(({tabId, frameId, url}) => | |
135 { | |
136 // There's a bug in Chrome that causes webNavigation.onCommitted to get | |
137 // dispatched twice if there's a URL filter present, therefore we must listen | |
138 // for all URLs and do an explicit check here. | |
139 // https://crbug.com/827855 | |
140 if (!/^(https?:\/\/|about:blank\b|about:srcdoc\b)/.test(url)) | |
141 return; | |
142 | |
143 let page = new ext.Page({id: tabId, url}); | |
144 let frame = ext.getFrame(tabId, frameId); | |
145 | |
146 if (checkWhitelisted(page, frame, null, typeMap.DOCUMENT | typeMap.ELEMHIDE)) | |
147 return; | |
148 | |
149 let hostname = extractHostFromFrame(frame); | |
150 | |
151 for (let script of getScriptsForDomain(hostname)) | |
152 injectCode(script, tabId, frameId); | |
153 }); | |
OLD | NEW |