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

Delta Between Two Patch Sets: chrome/ext/background.js

Issue 29374674: Issue 4864 - Start using ESLint for adblockpluschrome (Closed)
Left Patch Set: Stop using commonjs Created Feb. 21, 2017, 5:08 a.m.
Right Patch Set: Use .includes again Created March 31, 2017, 8:37 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « chrome/devtools.js ('k') | chrome/ext/common.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-2016 Eyeo GmbH 3 * Copyright (C) 2006-2017 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
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 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/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 "use strict"; 18 "use strict";
19 19
20 (function()
20 { 21 {
21 /* Pages */ 22 /* Pages */
22 23
23 let Page = ext.Page = function(tab) 24 let Page = ext.Page = function(tab)
24 { 25 {
25 this.id = tab.id; 26 this.id = tab.id;
26 this._url = tab.url && new URL(tab.url); 27 this._url = tab.url && new URL(tab.url);
27 28
28 this.browserAction = new BrowserAction(tab.id); 29 this.browserAction = new BrowserAction(tab.id);
29 this.contextMenus = new ContextMenus(this); 30 this.contextMenus = new ContextMenus(this);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 if (!frames) 112 if (!frames)
112 frames = framesOfTabs[tabId] = Object.create(null); 113 frames = framesOfTabs[tabId] = Object.create(null);
113 114
114 let frame = frames[frameId]; 115 let frame = frames[frameId];
115 if (!frame) 116 if (!frame)
116 frame = frames[frameId] = {}; 117 frame = frames[frameId] = {};
117 118
118 return frame; 119 return frame;
119 } 120 }
120 121
121 chrome.webNavigation.onBeforeNavigate.addListener(details => 122 function updatePageFrameStructure(frameId, tabId, url, parentFrameId)
122 {
123 // Capture parent frame here because onCommitted doesn't get this info.
124 let frame = createFrame(details.tabId, details.frameId);
125 frame.parent = framesOfTabs[details.tabId][details.parentFrameId] || null;
126 });
127
128 let eagerlyUpdatedPages = new ext.PageMap();
129
130 ext._updatePageFrameStructure = (frameId, tabId, url, eager) =>
131 { 123 {
132 if (frameId == 0) 124 if (frameId == 0)
133 { 125 {
134 let page = new Page({id: tabId, url}); 126 let page = new Page({id: tabId, url});
135 127
136 if (eagerlyUpdatedPages.get(page) != url) 128 ext._removeFromAllPageMaps(tabId);
137 { 129
138 ext._removeFromAllPageMaps(tabId); 130 chrome.tabs.get(tabId, () =>
139 131 {
140 // When a sitekey header is received we must immediately update the page 132 // If the tab is prerendered, chrome.tabs.get() sets
141 // structure in order to record and use the key. We want to avoid 133 // chrome.runtime.lastError and we have to dispatch the onLoading event,
142 // trashing the page structure if the onCommitted event is then fired 134 // since the onUpdated event isn't dispatched for prerendered tabs.
143 // for the page. 135 // However, we have to keep relying on the unUpdated event for tabs that
144 if (eager) 136 // are already visible. Otherwise browser action changes get overridden
145 eagerlyUpdatedPages.set(page, url); 137 // when Chrome automatically resets them on navigation.
146 138 if (chrome.runtime.lastError)
147 chrome.tabs.get(tabId, () => 139 ext.pages.onLoading._dispatch(page);
148 { 140 });
149 // If the tab is prerendered, chrome.tabs.get() sets 141 }
150 // chrome.runtime.lastError and we have to dispatch the 142
151 // onLoading event, since the onUpdated event isn't 143 // Update frame parent and URL in frame structure
152 // dispatched for prerendered tabs. However, we have to
153 // keep relying on the unUpdated event for tabs that are
154 // already visible. Otherwise browser action changes get
155 // overridden when Chrome automatically resets them on
156 // navigation.
157 if (chrome.runtime.lastError)
158 ext.pages.onLoading._dispatch(page);
159 });
160 }
161 }
162
163 // Update frame URL in frame structure
164 let frame = createFrame(tabId, frameId); 144 let frame = createFrame(tabId, frameId);
165 frame.url = new URL(url); 145 frame.url = new URL(url);
166 }; 146 frame.parent = framesOfTabs[tabId][parentFrameId] || null;
167 147 }
168 chrome.webNavigation.onCommitted.addListener(details => 148
169 { 149 chrome.webRequest.onHeadersReceived.addListener(details =>
170 ext._updatePageFrameStructure(details.frameId, details.tabId, details.url); 150 {
151 // We have to update the frame structure when switching to a new
152 // document, so that we process any further requests made by that
153 // document in the right context. Unfortunately, we cannot rely
154 // on webNavigation.onCommitted since it isn't guaranteed to fire
155 // before any subresources start downloading[1]. As an
156 // alternative we use webRequest.onHeadersReceived for HTTP(S)
157 // URLs, being careful to ignore any responses that won't cause
158 // the document to be replaced.
159 // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=665843
160
161 // The request has been processed without replacing the document.
162 // https://chromium.googlesource.com/chromium/src/+/02d3f50b/content/browser /frame_host/navigation_request.cc#473
163 if (details.statusCode == 204 || details.statusCode == 205)
164 return;
165
166 for (let header of details.responseHeaders)
167 {
168 let headerName = header.name.toLowerCase();
169
170 // For redirects we must wait for the next response in order
171 // to know if the document will be replaced. Note: Chrome
172 // performs a redirect only if there is a "Location" header with
173 // a non-empty value and a known redirect status code.
174 // https://chromium.googlesource.com/chromium/src/+/39a7d96/net/http/http_ response_headers.cc#929
175 if (headerName == "location" && header.value &&
176 (details.statusCode == 301 || details.statusCode == 302 ||
177 details.statusCode == 303 || details.statusCode == 307 ||
178 details.statusCode == 308))
179 return;
180
181 // If the response initiates a download the document won't be
182 // replaced. Chrome initiates a download if there is a
183 // "Content-Disposition" with a valid and non-empty value other
184 // than "inline".
185 // https://chromium.googlesource.com/chromium/src/+/02d3f50b/content/brows er/loader/mime_sniffing_resource_handler.cc#534
186 // https://chromium.googlesource.com/chromium/src/+/02d3f50b/net/http/http _content_disposition.cc#374
187 // https://chromium.googlesource.com/chromium/src/+/16e2688e/net/http/http _util.cc#431
188 if (headerName == "content-disposition")
189 {
190 let disposition = header.value.split(";")[0].replace(/[ \t]+$/, "");
191 if (disposition.toLowerCase() != "inline" &&
192 /^[\x21-\x7E]+$/.test(disposition) &&
193 !/[()<>@,;:\\"/[\]?={}]/.test(disposition))
194 return;
195 }
196
197 // The value of the "Content-Type" header also determines if Chrome will
198 // initiate a download, or otherwise how the response will be rendered.
199 // We only need to consider responses which will result in a navigation
200 // and be rendered as HTML or similar.
201 // Note: Chrome might render the response as HTML if the "Content-Type"
202 // header is missing, invalid or unknown.
203 // https://chromium.googlesource.com/chromium/src/+/99f41af9/net/http/http _util.cc#66
204 // https://chromium.googlesource.com/chromium/src/+/3130418a/net/base/mime _sniffer.cc#667
205 if (headerName == "content-type")
206 {
207 let mediaType = header.value.split(/[ \t;(]/)[0].toLowerCase();
208 if (mediaType.includes("/") &&
209 mediaType != "*/*" &&
210 mediaType != "application/unknown" &&
211 mediaType != "unknown/unknown" &&
212 mediaType != "text/html" &&
213 mediaType != "text/xml" &&
214 mediaType != "application/xml" &&
215 mediaType != "application/xhtml+xml" &&
216 mediaType != "image/svg+xml")
217 return;
218 }
219 }
220
221 updatePageFrameStructure(details.frameId, details.tabId, details.url,
222 details.parentFrameId);
223 },
224 {types: ["main_frame", "sub_frame"], urls: ["http://*/*", "https://*/*"]},
225 ["responseHeaders"]);
226
227 chrome.webNavigation.onBeforeNavigate.addListener(details =>
228 {
229 // Since we can only listen for HTTP(S) responses using
230 // webRequest.onHeadersReceived we must update the page structure here for
231 // other navigations.
232 let url = new URL(details.url);
233 if (url.protocol != "http:" && url.protocol != "https:")
234 {
235 updatePageFrameStructure(details.frameId, details.tabId, details.url,
236 details.parentFrameId);
237 }
171 }); 238 });
172 239
173 function forgetTab(tabId) 240 function forgetTab(tabId)
174 { 241 {
175 ext.pages.onRemoved._dispatch(tabId); 242 ext.pages.onRemoved._dispatch(tabId);
176 243
177 ext._removeFromAllPageMaps(tabId); 244 ext._removeFromAllPageMaps(tabId);
178 delete framesOfTabs[tabId]; 245 delete framesOfTabs[tabId];
179 } 246 }
180 247
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 { 315 {
249 if (addedTabId == this._tabId) 316 if (addedTabId == this._tabId)
250 { 317 {
251 chrome.tabs.onReplaced.removeListener(onReplaced); 318 chrome.tabs.onReplaced.removeListener(onReplaced);
252 this._applyChanges(); 319 this._applyChanges();
253 } 320 }
254 }; 321 };
255 chrome.tabs.onReplaced.addListener(onReplaced); 322 chrome.tabs.onReplaced.addListener(onReplaced);
256 } 323 }
257 else 324 else
325 {
258 this._applyChanges(); 326 this._applyChanges();
327 }
259 }); 328 });
260 }, 329 },
261 _addChange(name, value) 330 _addChange(name, value)
262 { 331 {
263 if (!this._changes) 332 if (!this._changes)
264 { 333 {
265 this._changes = {}; 334 this._changes = {};
266 this._queueChanges(); 335 this._queueChanges();
267 } 336 }
268 337
269 this._changes[name] = value; 338 this._changes[name] = value;
270 }, 339 },
271 setIcon(path) 340 setIcon(path)
272 { 341 {
273 this._addChange("iconPath", path); 342 this._addChange("iconPath", path);
274 }, 343 },
275 setBadge(badge) 344 setBadge(badge)
276 { 345 {
277 if (!badge) 346 if (!badge)
347 {
278 this._addChange("badgeText", ""); 348 this._addChange("badgeText", "");
349 }
279 else 350 else
280 { 351 {
281 if ("number" in badge) 352 if ("number" in badge)
282 this._addChange("badgeText", badge.number.toString()); 353 this._addChange("badgeText", badge.number.toString());
283 354
284 if ("color" in badge) 355 if ("color" in badge)
285 this._addChange("badgeColor", badge.color); 356 this._addChange("badgeColor", badge.color);
286 } 357 }
287 } 358 }
288 }; 359 };
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 let results = ext.webRequest.onBeforeRequest._dispatch( 536 let results = ext.webRequest.onBeforeRequest._dispatch(
466 new URL(details.url), 537 new URL(details.url),
467 type.toUpperCase(), 538 type.toUpperCase(),
468 new Page({id: details.tabId}), 539 new Page({id: details.tabId}),
469 frame 540 frame
470 ); 541 );
471 542
472 if (results.indexOf(false) != -1) 543 if (results.indexOf(false) != -1)
473 return {cancel: true}; 544 return {cancel: true};
474 } 545 }
475 }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); 546 }, {urls: ["<all_urls>"]}, ["blocking"]);
476 547
477 548
478 /* Message passing */ 549 /* Message passing */
479 550
480 chrome.runtime.onMessage.addListener((message, rawSender, sendResponse) => 551 chrome.runtime.onMessage.addListener((message, rawSender, sendResponse) =>
481 { 552 {
482 let sender = {}; 553 let sender = {};
483 554
484 // Add "page" and "frame" if the message was sent by a content script. 555 // Add "page" and "frame" if the message was sent by a content script.
485 // If sent by popup or the background page itself, there is no "tab". 556 // If sent by popup or the background page itself, there is no "tab".
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 onChanged: chrome.storage.onChanged 601 onChanged: chrome.storage.onChanged
531 }; 602 };
532 603
533 /* Options */ 604 /* Options */
534 605
535 if ("openOptionsPage" in chrome.runtime) 606 if ("openOptionsPage" in chrome.runtime)
536 { 607 {
537 ext.showOptions = callback => 608 ext.showOptions = callback =>
538 { 609 {
539 if (!callback) 610 if (!callback)
611 {
540 chrome.runtime.openOptionsPage(); 612 chrome.runtime.openOptionsPage();
613 }
541 else 614 else
542 { 615 {
543 chrome.runtime.openOptionsPage(() => 616 chrome.runtime.openOptionsPage(() =>
544 { 617 {
545 if (chrome.runtime.lastError) 618 if (chrome.runtime.lastError)
546 return; 619 return;
547 620
548 chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs => 621 chrome.tabs.query({active: true, lastFocusedWindow: true}, tabs =>
549 { 622 {
550 if (tabs.length > 0) 623 if (tabs.length > 0)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 { 655 {
583 let tab = tabs[0]; 656 let tab = tabs[0];
584 657
585 chrome.windows.update(tab.windowId, {focused: true}); 658 chrome.windows.update(tab.windowId, {focused: true});
586 chrome.tabs.update(tab.id, {active: true}); 659 chrome.tabs.update(tab.id, {active: true});
587 660
588 if (callback) 661 if (callback)
589 callback(new Page(tab)); 662 callback(new Page(tab));
590 } 663 }
591 else 664 else
665 {
592 ext.pages.open(optionsUrl, callback); 666 ext.pages.open(optionsUrl, callback);
667 }
593 }); 668 });
594 }); 669 });
595 }; 670 };
596 } 671 }
597 672
598 /* Windows */ 673 /* Windows */
599 ext.windows = { 674 ext.windows = {
600 create(createData, callback) 675 create(createData, callback)
601 { 676 {
602 chrome.windows.create(createData, createdWindow => 677 chrome.windows.create(createData, createdWindow =>
603 { 678 {
604 afterTabLoaded(callback)(createdWindow.tabs[0]); 679 afterTabLoaded(callback)(createdWindow.tabs[0]);
605 }); 680 });
606 } 681 }
607 }; 682 };
608 } 683 }());
LEFTRIGHT

Powered by Google App Engine
This is Rietveld