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 comments Created March 6, 2014, 7:35 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-2013 Eyeo GmbH 3 * Copyright (C) 2006-2013 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 {
220 var parentFrameId = details[i].parentFrameId;
221
222 frames[details[i].frameId] = {
223 url: details[i].url,
224 parent: parentFrameId != -1 ? frames[parentFrameId] : null
Wladimir Palant 2014/03/06 20:58:18 I don't think that parent frames are guaranteed to
Sebastian Noack 2014/03/06 21:11:55 I tested it and it lists the frames top-down. But
Wladimir Palant 2014/03/21 14:17:35 I think a second pass is exactly what we should im
Sebastian Noack 2014/03/31 15:43:44 Done.
225 };
226 }
227 }
228 });
229 });
230 });
231
257 chrome.webRequest.onBeforeRequest.addListener(function(details) 232 chrome.webRequest.onBeforeRequest.addListener(function(details)
258 { 233 {
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) 234 if (details.tabId == -1)
263 return; 235 return;
264 236
265 var page = new Page({id: details.tabId}); 237 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 238 // assume that the first request belongs to the top frame. Chrome
273 // may give the top frame the type "object" instead of "main_frame". 239 // may give the top frame the type "object" instead of "main_frame".
274 // https://code.google.com/p/chromium/issues/detail?id=281711 240 // https://code.google.com/p/chromium/issues/detail?id=281711
275 if (frameId == 0) 241 details.frameId == 0 && !(details.tabId in framesOfTabs)
276 details.type = "main_frame"; 242 );
243
244 var frames = null;
245 if (!isMainFrame)
246 frames = framesOfTabs[details.tabId];
247 if (!frames)
248 frames = framesOfTabs[details.tabId] = {__proto__: null};
249
250 var frame = null;
251 if (!isMainFrame)
252 {
253 // we are looking for the frame that contains the element that
254 // is about to load, however if a frame is loading the surrounding
255 // frame is indicated by parentFrameId instead of frameId
256 var frameId;
257 if (details.type == "sub_frame")
258 frameId = details.parentFrameId;
259 else
260 frameId = details.frameId;
261
262 frame = frames[frameId] || frames[0];
263
264 if (frame && !ext.webRequest.onBeforeRequest._dispatch(details.url, detail s.type, new Page({id: details.tabId}), frame))
265 return {cancel: true};
277 } 266 }
278 267
279 var frameId; 268 if (isMainFrame || details.type == "sub_frame")
280 if (details.type == "main_frame" || details.type == "sub_frame") 269 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"]); 270 }, {urls: ["<all_urls>"]}, ["blocking"]);
316 271
317 272
318 /* Context menus */ 273 /* Context menus */
319 274
320 var contextMenuItems = []; 275 var contextMenuItems = [];
321 var isContextMenuHidden = true; 276 var isContextMenuHidden = true;
322 277
323 ext.contextMenus = { 278 ext.contextMenus = {
324 addMenuItem: function(title, contexts, onclick) 279 addMenuItem: function(title, contexts, onclick)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 } 322 }
368 }; 323 };
369 324
370 325
371 /* Message passing */ 326 /* Message passing */
372 327
373 ext._setupMessageListener(function(sender) 328 ext._setupMessageListener(function(sender)
374 { 329 {
375 return { 330 return {
376 page: new Page(sender.tab), 331 page: new Page(sender.tab),
377 frame: new Frame({url: sender.url, tabId: sender.tab.id}) 332 frame: {
333 url: sender.url,
334 get parent()
335 {
336 var frames = framesOfTabs[sender.tab.id];
337
338 if (!frames)
339 return null;
340
341 for (var frameId in frames)
342 {
343 if (frames[frameId].url == sender.url)
344 return frames[frameId].parent;
345 }
346
347 return frames[0];
348 }
349 }
378 }; 350 };
379 }); 351 });
380 })(); 352 })();
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