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

Side by Side Diff: lib/requestBlocker.js

Issue 29739594: Issue 6543 - Match requests without tabId/frameId in their originating context (Closed)
Patch Set: Use URL patterns to find tabs for initiator Created April 4, 2018, 1:01 a.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 | « lib/popupBlocker.js ('k') | lib/url.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 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 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 // WEBRTC gets addressed through a workaround, even if the webRequest API is 66 // WEBRTC gets addressed through a workaround, even if the webRequest API is
67 // lacking support to block this kind of a request. 67 // lacking support to block this kind of a request.
68 yield "WEBRTC"; 68 yield "WEBRTC";
69 69
70 // POPUP, CSP and ELEMHIDE filters aren't mapped to resource types. 70 // POPUP, CSP and ELEMHIDE filters aren't mapped to resource types.
71 yield "POPUP"; 71 yield "POPUP";
72 yield "ELEMHIDE"; 72 yield "ELEMHIDE";
73 yield "CSP"; 73 yield "CSP";
74 }()); 74 }());
75 75
76 function onBeforeRequestAsync(tabId, url, type, docDomain, 76 function getRelatedTabIds(details)
77 thirdParty, sitekey,
78 specificOnly, filter)
79 { 77 {
80 let tabIds = tabId != -1 ? [tabId] : []; 78 // This is the common case, the request is associated with a single tab.
79 // If tabId is -1, its not (e.g. the request was sent by
80 // a Service/Shared Worker) and we have to identify the related tabs.
81 if (details.tabId != -1)
82 return Promise.resolve([details.tabId]);
81 83
82 if (filter) 84 let url; // Firefox provides "originUrl" indicating the
83 FilterNotifier.emit("filter.hitCount", filter, 0, 0, tabIds); 85 if (details.originUrl) // URL of the tab that caused this request.
86 url = details.originUrl; // In case of Service/Shared Worker, this is the
87 // URL of the tab that caused the worker to spawn.
84 88
85 devtools.logRequest( 89 else if (details.initiator) // Chromium >=63 provides "intiator" which
86 tabIds, url, type, docDomain, 90 url = details.initiator + "/*"; // is equivalent to "originUrl" on Firefox
87 thirdParty, sitekey, 91 // except that its not a full URL but just
88 specificOnly, filter 92 // an origin (proto + host).
89 ); 93 else
94 return Promise.resolve([]);
kzar 2018/04/05 10:31:51 I wonder if there is a situation where details.ini
Sebastian Noack 2018/04/05 16:56:33 There are two scenarios (I have seen in my testing
kzar 2018/04/09 14:39:18 Sounds reasonable to me, maybe add a note to the i
Sebastian Noack 2018/04/09 21:08:20 There you go: https://issues.adblockplus.org/ticke
95
96 return browser.tabs.query({url}).then(tabs => tabs.map(tab => tab.id));
97 }
98
99 function logRequest(details, url, type, docDomain, thirdParty,
100 sitekey, specificOnly, filter)
101 {
102 getRelatedTabIds(details).then(tabIds =>
103 {
104 if (filter)
105 FilterNotifier.emit("filter.hitCount", filter, 0, 0, tabIds);
106
107 devtools.logRequest(
108 tabIds, url, type, docDomain,
109 thirdParty, sitekey,
110 specificOnly, filter
111 );
112 });
90 } 113 }
91 114
92 browser.webRequest.onBeforeRequest.addListener(details => 115 browser.webRequest.onBeforeRequest.addListener(details =>
93 { 116 {
94 // Never block top-level documents. 117 // Never block top-level documents.
95 if (details.type == "main_frame") 118 if (details.type == "main_frame")
96 return; 119 return;
97 120
98 // Filter out requests from non web protocols. Ideally, we'd explicitly 121 // Filter out requests from non web protocols. Ideally, we'd explicitly
99 // specify the protocols we are interested in (i.e. http://, https://, 122 // specify the protocols we are interested in (i.e. http://, https://,
100 // ws:// and wss://) with the url patterns, given below, when adding this 123 // ws:// and wss://) with the url patterns, given below, when adding this
101 // listener. But unfortunately, Chrome <=57 doesn't support the WebSocket 124 // listener. But unfortunately, Chrome <=57 doesn't support the WebSocket
102 // protocol and is causing an error if it is given. 125 // protocol and is causing an error if it is given.
103 let url = new URL(details.url); 126 let url = new URL(details.url);
104 if (url.protocol != "http:" && url.protocol != "https:" && 127 if (url.protocol != "http:" && url.protocol != "https:" &&
105 url.protocol != "ws:" && url.protocol != "wss:") 128 url.protocol != "ws:" && url.protocol != "wss:")
106 return; 129 return;
107 130
108 // Firefox (only) allows to intercept requests sent by the browser 131 let originUrl = null;
109 // and other extensions. We don't want to block these.
110 if (details.originUrl) 132 if (details.originUrl)
111 { 133 {
112 let originUrl = new URL(details.originUrl); 134 originUrl = new URL(details.originUrl);
135
136 // Firefox (only) allows to intercept requests sent by the browser
137 // and other extensions. We don't want to block these.
113 if (originUrl.protocol == "chrome:" || 138 if (originUrl.protocol == "chrome:" ||
114 originUrl.protocol == "moz-extension:") 139 originUrl.protocol == "moz-extension:")
115 return; 140 return;
116 } 141 }
142 // Fallback to "initiator" on Chrome >=63. It doesn't include the
143 // path (unlike "originUrl" on Firefox), but is still good enough
144 // (in case the tab/frame is unknown) for the $domain filter option
145 // and most document exception rules which only match the domain part.
146 else if (details.initiator)
147 originUrl = new URL(details.initiator);
117 148
118 let frame = ext.getFrame( 149 let page = null;
119 details.tabId, 150 let frame = null;
120 // We are looking for the frame that contains the element which 151 if (details.tabId != -1)
121 // has triggered this request. For most requests (e.g. images) we 152 {
122 // can just use the request's frame ID, but for subdocument requests 153 page = new ext.Page({id: details.tabId});
123 // (e.g. iframes) we must instead use the request's parent frame ID. 154 frame = ext.getFrame(
124 details.type == "sub_frame" ? details.parentFrameId : details.frameId 155 details.tabId,
125 ); 156 // We are looking for the frame that contains the element which
157 // has triggered this request. For most requests (e.g. images) we
158 // can just use the request's frame ID, but for subdocument requests
159 // (e.g. iframes) we must instead use the request's parent frame ID.
160 details.type == "sub_frame" ? details.parentFrameId : details.frameId
161 );
162 }
126 163
127 let docDomain = null; 164 if (checkWhitelisted(page, frame, originUrl))
128 let sitekey = null; 165 return;
129 let thirdParty = false;
130 let specificOnly = false;
131
132 if (frame)
133 {
134 let page = new ext.Page({id: details.tabId});
135
136 if (checkWhitelisted(page, frame))
137 return;
138
139 docDomain = extractHostFromFrame(frame);
140 sitekey = getKey(page, frame);
141 thirdParty = isThirdParty(url, docDomain);
142 specificOnly = !!checkWhitelisted(page, frame,
143 RegExpFilter.typeMap.GENERICBLOCK);
144 }
145 166
146 let urlString = stringifyURL(url); 167 let urlString = stringifyURL(url);
147 let type = resourceTypes.get(details.type) || "OTHER"; 168 let type = resourceTypes.get(details.type) || "OTHER";
169 let docDomain = extractHostFromFrame(frame, originUrl);
170 let thirdParty = isThirdParty(url, docDomain);
171 let sitekey = getKey(page, frame, originUrl);
172 let specificOnly = !!checkWhitelisted(page, frame, originUrl,
173 RegExpFilter.typeMap.GENERICBLOCK);
174
148 let filter = defaultMatcher.matchesAny( 175 let filter = defaultMatcher.matchesAny(
149 urlString, RegExpFilter.typeMap[type], 176 urlString, RegExpFilter.typeMap[type],
150 docDomain, thirdParty, sitekey, specificOnly 177 docDomain, thirdParty, sitekey, specificOnly
151 ); 178 );
152 179
153 setTimeout(onBeforeRequestAsync, 0, details.tabId, urlString, 180 logRequest(details, urlString, type, docDomain,
154 type, docDomain, 181 thirdParty, sitekey, specificOnly, filter);
155 thirdParty, sitekey,
156 specificOnly, filter);
157 182
158 if (filter instanceof BlockingFilter) 183 if (filter instanceof BlockingFilter)
159 return {cancel: true}; 184 return {cancel: true};
160 }, {urls: ["<all_urls>"]}, ["blocking"]); 185 }, {urls: ["<all_urls>"]}, ["blocking"]);
161 186
162 port.on("filters.collapse", (message, sender) => 187 port.on("filters.collapse", (message, sender) =>
163 { 188 {
164 if (checkWhitelisted(sender.page, sender.frame)) 189 if (checkWhitelisted(sender.page, sender.frame))
165 return false; 190 return false;
166 191
167 let typeMask = RegExpFilter.typeMap[message.mediatype]; 192 let typeMask = RegExpFilter.typeMap[message.mediatype];
168 let documentHost = extractHostFromFrame(sender.frame); 193 let documentHost = extractHostFromFrame(sender.frame);
169 let sitekey = getKey(sender.page, sender.frame); 194 let sitekey = getKey(sender.page, sender.frame);
170 let blocked = false; 195 let blocked = false;
171 196
172 let specificOnly = checkWhitelisted( 197 let specificOnly = checkWhitelisted(
173 sender.page, sender.frame, 198 sender.page, sender.frame, null,
174 RegExpFilter.typeMap.GENERICBLOCK 199 RegExpFilter.typeMap.GENERICBLOCK
175 ); 200 );
176 201
177 for (let url of message.urls) 202 for (let url of message.urls)
178 { 203 {
179 let urlObj = new URL(url, message.baseURL); 204 let urlObj = new URL(url, message.baseURL);
180 let filter = defaultMatcher.matchesAny( 205 let filter = defaultMatcher.matchesAny(
181 stringifyURL(urlObj), 206 stringifyURL(urlObj),
182 typeMask, documentHost, 207 typeMask, documentHost,
183 isThirdParty(urlObj, documentHost), 208 isThirdParty(urlObj, documentHost),
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 264
240 port.on("request.blockedByRTCWrapper", (msg, sender) => 265 port.on("request.blockedByRTCWrapper", (msg, sender) =>
241 { 266 {
242 return ext.webRequest.onBeforeRequest._dispatch( 267 return ext.webRequest.onBeforeRequest._dispatch(
243 new URL(msg.url), 268 new URL(msg.url),
244 "webrtc", 269 "webrtc",
245 sender.page, 270 sender.page,
246 sender.frame 271 sender.frame
247 ).includes(false); 272 ).includes(false);
248 }); 273 });
OLDNEW
« no previous file with comments | « lib/popupBlocker.js ('k') | lib/url.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld