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: Created Feb. 25, 2014, 5:52 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];
Wladimir Palant 2014/03/06 15:32:20 What about tabs we don't know?
Sebastian Noack 2014/03/06 19:54:49 Done.
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
257 chrome.webRequest.onBeforeRequest.addListener(function(details) 208 chrome.tabs.query({}, function(tabs)
258 { 209 {
259 // the high-level code isn't interested in requests that aren't related 210 // unfortunatelly we can't retrieve frames already loaded.
Sebastian Noack 2014/03/06 19:54:49 Cool. Done.
260 // to a tab and since those can only be handled in Chrome, we ignore 211 // But we can retrieve the top level url of every tab and
261 // them here instead of in the browser independent high-level code. 212 // use it as fallback when we encounter an unknown frame.
262 if (details.tabId == -1) 213 for (var i = 0; i < tabs.length; i++)
Wladimir Palant 2014/03/06 15:32:20 Nit: Please always put brackets around multiline b
263 return; 214 framesOfTabs[tabs[i].id] = {
215 __proto__: null,
264 216
265 var page = new Page({id: details.tabId}); 217 0: {
266 var frames = framesOfTabs[details.tabId]; 218 url: tabs[i].url,
219 parent: null
220 }
221 };
267 222
268 if (!frames) 223 chrome.webRequest.onBeforeRequest.addListener(function(details)
269 { 224 {
270 frames = framesOfTabs[details.tabId] = []; 225 if (details.tabId == -1)
271
272 // assume that the first request belongs to the top frame. Chrome
273 // may give the top frame the type "object" instead of "main_frame".
274 // https://code.google.com/p/chromium/issues/detail?id=281711
275 if (frameId == 0)
276 details.type = "main_frame";
277 }
278
279 var frameId;
280 if (details.type == "main_frame" || details.type == "sub_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; 226 return;
301 227
302 // however when the src of the frame is a javascript: or data: URL, we 228 var isMainFrame = details.type == "main_frame" || (
303 // don't know the frame either. But since we know the top-level frame we 229 // assume that the first request belongs to the top frame. Chrome
304 // can just pretend that we are in the top-level frame, in order to have 230 // may give the top frame the type "object" instead of "main_frame".
305 // at least most domain-based filter rules working. 231 // https://code.google.com/p/chromium/issues/detail?id=281711
306 frameId = 0; 232 details.frameId == 0 && !(details.tabId in framesOfTabs)
307 if (details.type == "sub_frame") 233 );
308 frames[details.frameId].parent = frameId;
309 }
310 234
311 var frame = new Frame({frameId: frameId, tabId: details.tabId}); 235 var frames;
236 var frame;
237 if (isMainFrame)
238 {
239 frames = framesOfTabs[details.tabId] = {__proto__: null};
240 frame = null;
241 }
242 else
243 {
244 // we are looking for the frame that contains the element that
245 // is about to load, however if a frame is loading the surrounding
246 // frame is indicated by parentFrameId instead of frameId
247 var frameId;
248 if (details.type == "sub_frame")
249 frameId = details.parentFrameId;
250 else
251 frameId = details.frameId;
312 252
313 if (!ext.webRequest.onBeforeRequest._dispatch(details.url, details.type, pag e, frame)) 253 frames = framesOfTabs[details.tabId];
314 return {cancel: true}; 254 frame = frames[frameId] || frames[0];
315 }, {urls: ["<all_urls>"]}, ["blocking"]); 255
256 if (!ext.webRequest.onBeforeRequest._dispatch(details.url, details.type, new Page({id: details.tabId}), frame))
257 return {cancel: true};
258 }
259
260 if (isMainFrame || details.type == "sub_frame")
261 frames[details.frameId] = {url: details.url, parent: frame};
262 }, {urls: ["<all_urls>"]}, ["blocking"]);
263
264
265 /* Message passing */
266
267 ext._setupMessageListener(function(sender)
268 {
269 return {
270 page: new Page(sender.tab),
271 frame: {
272 url: sender.url,
273 get parent()
274 {
275 var frames = framesOfTabs[sender.tab.id];
276
277 for (var frameId in frames)
278 {
279 if (frames[frameId].url == sender.url)
280 return frames[frameId].parent;
281 }
282
283 return frames[0];
284 }
285 }
286 };
287 });
288 });
316 289
317 290
318 /* Context menus */ 291 /* Context menus */
319 292
320 var contextMenuItems = []; 293 var contextMenuItems = [];
321 var isContextMenuHidden = true; 294 var isContextMenuHidden = true;
322 295
323 ext.contextMenus = { 296 ext.contextMenus = {
324 addMenuItem: function(title, contexts, onclick) 297 addMenuItem: function(title, contexts, onclick)
325 { 298 {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 }, 332 },
360 hideMenuItems: function() 333 hideMenuItems: function()
361 { 334 {
362 if (isContextMenuHidden) 335 if (isContextMenuHidden)
363 return; 336 return;
364 337
365 chrome.contextMenus.removeAll(); 338 chrome.contextMenus.removeAll();
366 isContextMenuHidden = true; 339 isContextMenuHidden = true;
367 } 340 }
368 }; 341 };
369
370
371 /* Message passing */
372
373 ext._setupMessageListener(function(sender)
374 {
375 return {
376 page: new Page(sender.tab),
377 frame: new Frame({url: sender.url, tabId: sender.tab.id})
378 };
379 });
380 })(); 342 })();
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