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

Side by Side Diff: chrome/ext/background.js

Issue 5133931611422720: Simplified and removed memory leaks from code dealing with frames on Chrome (Closed)
Patch Set: Addressed comment Created March 31, 2014, 3:43 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 | popupBlocker.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 <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 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 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 { 184 {
185 chrome.browserAction.setBadgeText({ 185 chrome.browserAction.setBadgeText({
186 tabId: this._tabId, 186 tabId: this._tabId,
187 text: badge.number.toString() 187 text: badge.number.toString()
188 }); 188 });
189 } 189 }
190 } 190 }
191 }; 191 };
192 192
193 193
194 /* Frames */
195
196 var framesOfTabs = {__proto__: null};
197
198 var Frame = ext.Frame = function(params)
199 {
200 this._frameId = params.frameId;
201 this._tabId = params.tabId;
202 this._url = params.url;
203 };
204 Frame.prototype = {
205 get url()
206 {
207 if (this._url != null)
208 return this._url;
209
210 var frames = framesOfTabs[this._tabId];
211 if (frames)
212 {
213 var frame = frames[this._frameId];
214 if (frame)
215 return frame.url;
216 }
217 },
218 get parent()
219 {
220 var frames = framesOfTabs[this._tabId];
221 if (frames)
222 {
223 var frame;
224 if (this._frameId != null)
225 frame = frames[this._frameId];
226 else
227 {
228 // the frame ID wasn't available when we created
229 // the Frame object (e.g. for the onMessage event),
230 // so we have to find the frame details by their URL.
231 for (var frameId in frames)
232 {
233 if (frames[frameId].url == this._url)
234 {
235 frame = frames[frameId];
236 break;
237 }
238 }
239 }
240
241 if (!frame || frame.parent == -1)
242 return null;
243
244 return new Frame({frameId: frame.parent, tabId: this._tabId});
245 }
246 }
247 };
248
249
250 /* Web requests */ 194 /* Web requests */
251 195
196 var framesOfTabs = {__proto__: null};
197
198 ext.getFrame = function(tabId, frameId)
199 {
200 return (framesOfTabs[tabId] || {})[frameId];
201 };
202
252 ext.webRequest = { 203 ext.webRequest = {
253 onBeforeRequest: new ext._EventTarget(true), 204 onBeforeRequest: new ext._EventTarget(true),
254 handlerBehaviorChanged: chrome.webRequest.handlerBehaviorChanged 205 handlerBehaviorChanged: chrome.webRequest.handlerBehaviorChanged
255 }; 206 };
256 207
208 chrome.tabs.query({}, function(tabs)
209 {
210 tabs.forEach(function(tab)
211 {
212 chrome.webNavigation.getAllFrames({tabId: tab.id}, function(details)
213 {
214 if (details && details.length > 0)
215 {
216 var frames = framesOfTabs[tab.id] = {__proto__: null};
217
218 for (var i = 0; i < details.length; i++)
219 frames[details[i].frameId] = {url: details[i].url, parent: null};
220
221 for (var i = 0; i < details.length; i++)
222 {
223 var parentFrameId = details[i].parentFrameId;
224
225 if (parentFrameId != -1)
226 frames[details[i].frameId].parent = frames[parentFrameId];
227 }
228 }
229 });
230 });
231 });
232
257 chrome.webRequest.onBeforeRequest.addListener(function(details) 233 chrome.webRequest.onBeforeRequest.addListener(function(details)
258 { 234 {
259 // the high-level code isn't interested in requests that aren't related
260 // to a tab and since those can only be handled in Chrome, we ignore
261 // them here instead of in the browser independent high-level code.
262 if (details.tabId == -1) 235 if (details.tabId == -1)
263 return; 236 return;
264 237
265 var page = new Page({id: details.tabId}); 238 var isMainFrame = details.type == "main_frame" || (
266 var frames = framesOfTabs[details.tabId];
267
268 if (!frames)
269 {
270 frames = framesOfTabs[details.tabId] = [];
271
272 // assume that the first request belongs to the top frame. Chrome 239 // assume that the first request belongs to the top frame. Chrome
273 // may give the top frame the type "object" instead of "main_frame". 240 // may give the top frame the type "object" instead of "main_frame".
274 // https://code.google.com/p/chromium/issues/detail?id=281711 241 // https://code.google.com/p/chromium/issues/detail?id=281711
275 if (frameId == 0) 242 details.frameId == 0 && !(details.tabId in framesOfTabs)
276 details.type = "main_frame"; 243 );
244
245 var frames = null;
246 if (!isMainFrame)
247 frames = framesOfTabs[details.tabId];
248 if (!frames)
249 frames = framesOfTabs[details.tabId] = {__proto__: null};
250
251 var frame = null;
252 if (!isMainFrame)
253 {
254 // we are looking for the frame that contains the element that
255 // is about to load, however if a frame is loading the surrounding
256 // frame is indicated by parentFrameId instead of frameId
257 var frameId;
258 if (details.type == "sub_frame")
259 frameId = details.parentFrameId;
260 else
261 frameId = details.frameId;
262
263 frame = frames[frameId] || frames[0];
264
265 if (frame && !ext.webRequest.onBeforeRequest._dispatch(details.url, detail s.type, new Page({id: details.tabId}), frame))
266 return {cancel: true};
277 } 267 }
278 268
279 var frameId; 269 if (isMainFrame || details.type == "sub_frame")
280 if (details.type == "main_frame" || details.type == "sub_frame") 270 frames[details.frameId] = {url: details.url, parent: frame};
281 {
282 frameId = details.parentFrameId;
283 frames[details.frameId] = {url: details.url, parent: frameId};
284
285 // the high-level code isn't interested in top frame requests and
286 // since those can only be handled in Chrome, we ignore them here
287 // instead of in the browser independent high-level code.
288 if (details.type == "main_frame")
289 return;
290 }
291 else
292 frameId = details.frameId;
293
294 if (!(frameId in frames))
295 {
296 // the high-level code relies on the frame. So ignore the request if we
297 // don't even know the top-level frame. That can happen for example when
298 // the extension was just (re)loaded.
299 if (!(0 in frames))
300 return;
301
302 // however when the src of the frame is a javascript: or data: URL, we
303 // don't know the frame either. But since we know the top-level frame we
304 // can just pretend that we are in the top-level frame, in order to have
305 // at least most domain-based filter rules working.
306 frameId = 0;
307 if (details.type == "sub_frame")
308 frames[details.frameId].parent = frameId;
309 }
310
311 var frame = new Frame({frameId: frameId, tabId: details.tabId});
312
313 if (!ext.webRequest.onBeforeRequest._dispatch(details.url, details.type, pag e, frame))
314 return {cancel: true};
315 }, {urls: ["<all_urls>"]}, ["blocking"]); 271 }, {urls: ["<all_urls>"]}, ["blocking"]);
316 272
317 273
318 /* Context menus */ 274 /* Context menus */
319 275
320 var contextMenuItems = []; 276 var contextMenuItems = [];
321 var isContextMenuHidden = true; 277 var isContextMenuHidden = true;
322 278
323 ext.contextMenus = { 279 ext.contextMenus = {
324 addMenuItem: function(title, contexts, onclick) 280 addMenuItem: function(title, contexts, onclick)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 } 323 }
368 }; 324 };
369 325
370 326
371 /* Message passing */ 327 /* Message passing */
372 328
373 ext._setupMessageListener(function(sender) 329 ext._setupMessageListener(function(sender)
374 { 330 {
375 return { 331 return {
376 page: new Page(sender.tab), 332 page: new Page(sender.tab),
377 frame: new Frame({url: sender.url, tabId: sender.tab.id}) 333 frame: {
334 url: sender.url,
335 get parent()
336 {
337 var frames = framesOfTabs[sender.tab.id];
338
339 if (!frames)
340 return null;
341
342 for (var frameId in frames)
343 {
344 if (frames[frameId].url == sender.url)
345 return frames[frameId].parent;
346 }
347
348 return frames[0];
349 }
350 }
378 }; 351 };
379 }); 352 });
380 353
381 354
382 /* Storage */ 355 /* Storage */
383 356
384 ext.storage = localStorage; 357 ext.storage = localStorage;
385 })(); 358 })();
OLDNEW
« no previous file with comments | « no previous file | popupBlocker.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld