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

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

Issue 6615790883176448: Issue 2034 - Respect chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES (Closed)
Left Patch Set: Created Feb. 23, 2015, 5:18 p.m.
Right Patch Set: Renamed overlooked variable name Created April 10, 2015, 7:02 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 | « no previous file | webrequest.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-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 /* Web requests */ 320 /* Web requests */
321 321
322 var framesOfTabs = Object.create(null); 322 var framesOfTabs = Object.create(null);
323 323
324 ext.getFrame = function(tabId, frameId) 324 ext.getFrame = function(tabId, frameId)
325 { 325 {
326 return (framesOfTabs[tabId] || {})[frameId]; 326 return (framesOfTabs[tabId] || {})[frameId];
327 }; 327 };
328 328
329 var handlerBehaviorChangedQuota = chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANG ED_CALLS_PER_10_MINUTES; 329 var handlerBehaviorChangedQuota = chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANG ED_CALLS_PER_10_MINUTES;
330 var handlerBehaviorChangedQuotaExceeded = false; 330
331 var handlerBehaviorChangedPending = false; 331 function propagateHandlerBehaviorChange()
332 332 {
333 function handlerBehaviorChanged()
334 {
335 chrome.webRequest.handlerBehaviorChanged();
336 handlerBehaviorChangedQuota--;
337
338 // Make sure to not call handlerBehaviorChanged() more often than allowed 333 // Make sure to not call handlerBehaviorChanged() more often than allowed
339 // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES. 334 // by chrome.webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES.
340 // Otherwise Chrome notifies the user that this extension is causing issues. 335 // Otherwise Chrome notifies the user that this extension is causing issues.
341 setTimeout(function() 336 if (handlerBehaviorChangedQuota > 0)
342 { 337 {
343 handlerBehaviorChangedQuota++; 338 chrome.webNavigation.onBeforeNavigate.removeListener(propagateHandlerBehav iorChange);
344 339 chrome.webRequest.handlerBehaviorChanged();
345 // If the quota were exceeded, call handlerBehaviorChanged() 340
346 // delayed, when 10 minutes since the first call within the 341 handlerBehaviorChangedQuota--;
347 // past 10 minutes passed. 342 setTimeout(function() { handlerBehaviorChangedQuota++; }, 600000);
348 if (handlerBehaviorChangedQuotaExceeded) 343 }
349 {
350 handlerBehaviorChangedQuotaExceeded = false;
351 handlerBehaviorChanged();
352 }
353 }, 600000);
354 } 344 }
Wladimir Palant 2015/02/23 18:25:26 Is this really a good approach? I think that we sh
Sebastian Noack 2015/02/23 19:12:08 We call handlerBehaviorChanged() only if it did. T
Wladimir Palant 2015/02/23 19:22:42 If users are changing filters frequently (more oft
Sebastian Noack 2015/04/09 07:04:55 How about this: The new patch defers handlerBehavi
355 345
356 ext.webRequest = { 346 ext.webRequest = {
357 onBeforeRequest: new ext._EventTarget(), 347 onBeforeRequest: new ext._EventTarget(),
358 handlerBehaviorChanged: function() 348 handlerBehaviorChanged: function()
359 { 349 {
360 if (handlerBehaviorChangedQuota > 0) 350 // Defer handlerBehaviorChanged() until navigation occurs.
361 { 351 // There wouldn't be any visible effect when calling it earlier,
362 // Call handlerBehaviorChanged() asynchronously, and only if it 352 // but it's an expensive operation and that way we avoid to call
363 // hasn't been scheduled yet. That way we avoid to call it multiple 353 // it multiple times, if multiple filters are added/removed.
364 // times, if multiple filters were added/removed simultanously. 354 var onBeforeNavigate = chrome.webNavigation.onBeforeNavigate;
365 if (!handlerBehaviorChangedPending) 355 if (!onBeforeNavigate.hasListener(propagateHandlerBehaviorChange))
366 { 356 onBeforeNavigate.addListener(propagateHandlerBehaviorChange);
367 handlerBehaviorChangedPending = true; 357 }
368 358 };
369 setTimeout(function() 359
370 { 360 // Since Chrome 38 requests of type 'object' (e.g. requests
371 handlerBehaviorChanged(); 361 // initiated by Flash) are mistakenly reported with the type 'other'.
372 handlerBehaviorChangedPending = false; 362 // https://code.google.com/p/chromium/issues/detail?id=410382
373 }, 0); 363 if (parseInt(navigator.userAgent.match(/\bChrome\/(\d+)/)[1], 10) >= 38)
374 } 364 {
375 } 365 ext.webRequest.indistinguishableTypes = [
376 else 366 ["OTHER", "OBJECT", "OBJECT_SUBREQUEST"]
377 { 367 ];
378 handlerBehaviorChangedQuotaExceeded = true; 368 }
379 } 369 else
380 } 370 {
381 }; 371 ext.webRequest.indistinguishableTypes = [
372 ["OBJECT", "OBJECT_SUBREQUEST"],
373 ["OTHER", "MEDIA", "FONT"]
374 ];
375 }
382 376
383 chrome.tabs.query({}, function(tabs) 377 chrome.tabs.query({}, function(tabs)
384 { 378 {
385 tabs.forEach(function(tab) 379 tabs.forEach(function(tab)
386 { 380 {
387 chrome.webNavigation.getAllFrames({tabId: tab.id}, function(details) 381 chrome.webNavigation.getAllFrames({tabId: tab.id}, function(details)
388 { 382 {
389 if (details && details.length > 0) 383 if (details && details.length > 0)
390 { 384 {
391 var frames = framesOfTabs[tab.id] = Object.create(null); 385 var frames = framesOfTabs[tab.id] = Object.create(null);
(...skipping 16 matching lines...) Expand all
408 chrome.webRequest.onBeforeRequest.addListener(function(details) 402 chrome.webRequest.onBeforeRequest.addListener(function(details)
409 { 403 {
410 try 404 try
411 { 405 {
412 // the high-level code isn't interested in requests that aren't related 406 // the high-level code isn't interested in requests that aren't related
413 // to a tab and since those can only be handled in Chrome, we ignore 407 // to a tab and since those can only be handled in Chrome, we ignore
414 // them here instead of in the browser independent high-level code. 408 // them here instead of in the browser independent high-level code.
415 if (details.tabId == -1) 409 if (details.tabId == -1)
416 return; 410 return;
417 411
418 var requestType = details.type; 412 var isMainFrame = details.type == "main_frame" || (
419 var isMainFrame = requestType == "main_frame" || (
420 413
421 // assume that the first request belongs to the top frame. Chrome 414 // assume that the first request belongs to the top frame. Chrome
422 // may give the top frame the type "object" instead of "main_frame". 415 // may give the top frame the type "object" instead of "main_frame".
423 // https://code.google.com/p/chromium/issues/detail?id=281711 416 // https://code.google.com/p/chromium/issues/detail?id=281711
424 details.frameId == 0 && !(details.tabId in framesOfTabs) 417 details.frameId == 0 && !(details.tabId in framesOfTabs)
425 ); 418 );
426 419
427 var frames = null; 420 var frames = null;
428 if (!isMainFrame) 421 if (!isMainFrame)
429 frames = framesOfTabs[details.tabId]; 422 frames = framesOfTabs[details.tabId];
430 if (!frames) 423 if (!frames)
431 frames = framesOfTabs[details.tabId] = Object.create(null); 424 frames = framesOfTabs[details.tabId] = Object.create(null);
432 425
433 var frame = null; 426 var frame = null;
434 var url = new URL(details.url); 427 var url = new URL(details.url);
435 if (!isMainFrame) 428 if (!isMainFrame)
436 { 429 {
437 // we are looking for the frame that contains the element that 430 // we are looking for the frame that contains the element that
438 // is about to load, however if a frame is loading the surrounding 431 // is about to load, however if a frame is loading the surrounding
439 // frame is indicated by parentFrameId instead of frameId 432 // frame is indicated by parentFrameId instead of frameId
440 var frameId; 433 var frameId;
441 if (requestType == "sub_frame") 434 var requestType;
435 if (details.type == "sub_frame")
436 {
442 frameId = details.parentFrameId; 437 frameId = details.parentFrameId;
438 requestType = "SUBDOCUMENT";
439 }
443 else 440 else
441 {
444 frameId = details.frameId; 442 frameId = details.frameId;
443 requestType = details.type.toUpperCase();
444 }
445 445
446 frame = frames[frameId] || frames[Object.keys(frames)[0]]; 446 frame = frames[frameId] || frames[Object.keys(frames)[0]];
447 447
448 if (frame) 448 if (frame)
449 { 449 {
450 // Since Chrome 38 requests of type 'object' (e.g. requests
451 // initiated by Flash) are mistakenly reported with the type 'other'.
452 // https://code.google.com/p/chromium/issues/detail?id=410382
453 if (requestType == "other" && parseInt(navigator.userAgent.match(/\bCh rome\/(\d+)/)[1], 10) >= 38)
454 requestType = "object";
455
456 var results = ext.webRequest.onBeforeRequest._dispatch( 450 var results = ext.webRequest.onBeforeRequest._dispatch(
457 url, 451 url,
458 requestType, 452 requestType,
459 new Page({id: details.tabId}), 453 new Page({id: details.tabId}),
460 frame 454 frame
461 ); 455 );
462 456
463 if (results.indexOf(false) != -1) 457 if (results.indexOf(false) != -1)
464 return {cancel: true}; 458 return {cancel: true};
465 } 459 }
466 } 460 }
467 461
468 if (isMainFrame || details.type == "sub_frame") 462 if (isMainFrame || details.type == "sub_frame")
469 frames[details.frameId] = {url: url, parent: frame}; 463 frames[details.frameId] = {url: url, parent: frame};
470 } 464 }
471 catch (e) 465 catch (e)
472 { 466 {
473 // recent versions of Chrome cancel the request when an error occurs in 467 // recent versions of Chrome cancel the request when an error occurs in
474 // the onBeforeRequest listener. However in our case it is preferred, to 468 // the onBeforeRequest listener. However in our case it is preferred, to
475 // let potentially some ads through, rather than blocking legit requests. 469 // let potentially some ads through, rather than blocking legit requests.
476 console.error(e); 470 console.error(e);
477 } 471 }
478 }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]); 472 }, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]);
479 473
480 474
481 /* Message passing */ 475 /* Message passing */
482 476
483 chrome.runtime.onMessage.addListener(function(message, rawSender, sendResponse ) 477 chrome.runtime.onMessage.addListener(function(message, rawSender, sendResponse )
484 { 478 {
485 var sender = { 479 var sender = {};
486 page: new Page(rawSender.tab), 480
487 frame: { 481 // Add "page" and "frame" if the message was sent by a content script.
482 // If sent by popup or the background page itself, there is no "tab".
483 if ("tab" in rawSender)
484 {
485 sender.page = new Page(rawSender.tab);
486 sender.frame = {
488 url: new URL(rawSender.url), 487 url: new URL(rawSender.url),
489 get parent() 488 get parent()
490 { 489 {
491 var frames = framesOfTabs[rawSender.tab.id]; 490 var frames = framesOfTabs[rawSender.tab.id];
492 491
493 if (!frames) 492 if (!frames)
494 return null; 493 return null;
495 494
496 if ("frameId" in rawSender) 495 if ("frameId" in rawSender)
497 { 496 {
498 // Chrome 41+ 497 // Chrome 41+
499 var frame = frames[rawSender.frameId]; 498 var frame = frames[rawSender.frameId];
500 if (frame) 499 if (frame)
501 return frame.parent; 500 return frame.parent;
502 } 501 }
503 else 502 else
504 { 503 {
505 // Chrome 28-40 504 // Chrome 28-40
506 for (var frameId in frames) 505 for (var frameId in frames)
507 { 506 {
508 if (frames[frameId].url.href == this.url.href) 507 if (frames[frameId].url.href == this.url.href)
509 return frames[frameId].parent; 508 return frames[frameId].parent;
510 } 509 }
511 } 510 }
512 511
513 return frames[0]; 512 return frames[0];
514 } 513 }
515 } 514 };
516 }; 515 }
517 516
518 return ext.onMessage._dispatch(message, sender, sendResponse).indexOf(true) != -1; 517 return ext.onMessage._dispatch(message, sender, sendResponse).indexOf(true) != -1;
519 }); 518 });
520 519
521 // We have to ensure there is at least one listener for the onConnect event. 520 // We have to ensure there is at least one listener for the onConnect event.
522 // Otherwise we can't connect a port later, which we need to do in order to 521 // Otherwise we can't connect a port later, which we need to do in order to
523 // detect when the extension is reloaded, disabled or uninstalled. 522 // detect when the extension is reloaded, disabled or uninstalled.
524 chrome.runtime.onConnect.addListener(function() {}); 523 chrome.runtime.onConnect.addListener(function() {});
525 524
526 525
(...skipping 17 matching lines...) Expand all
544 if (!win.incognito) 543 if (!win.incognito)
545 queryInfo.windowId = win.id; 544 queryInfo.windowId = win.id;
546 545
547 chrome.tabs.query(queryInfo, function(tabs) 546 chrome.tabs.query(queryInfo, function(tabs)
548 { 547 {
549 if (tabs.length > 0) 548 if (tabs.length > 0)
550 { 549 {
551 var tab = tabs[0]; 550 var tab = tabs[0];
552 551
553 chrome.windows.update(tab.windowId, {focused: true}); 552 chrome.windows.update(tab.windowId, {focused: true});
554 chrome.tabs.highlight( 553 chrome.tabs.update(tab.id, {active: true});
555 {
556 windowId: tab.windowId,
557 tabs: [tab.index]
558 },
559 function() {}
560 );
561 554
562 if (callback) 555 if (callback)
563 callback(new Page(tab)); 556 callback(new Page(tab));
564 } 557 }
565 else 558 else
566 { 559 {
567 ext.pages.open(optionsUrl, callback); 560 ext.pages.open(optionsUrl, callback);
568 } 561 }
569 }); 562 });
570 }); 563 });
571 }; 564 };
572 })(); 565 })();
LEFTRIGHT
« no previous file | webrequest.js » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
This is Rietveld