From 7cd060a15f995215941641428a866bee8c109563 Mon Sep 17 00:00:00 2001 From: gorhill Date: Tue, 21 Apr 2015 16:22:29 -0400 Subject: [PATCH] refactoring, fixing script/frame blocking on FF, etc., more to do --- platform/firefox/vapi-background.js | 39 +-- src/js/async.js | 30 +-- src/js/background.js | 10 +- src/js/cookies.js | 18 +- src/js/info.js | 38 +-- src/js/messaging.js | 109 ++++---- src/js/pagestats.js | 73 ++++-- src/js/start.js | 12 +- src/js/tab.js | 387 ++++++++++++---------------- src/js/traffic.js | 281 +++++++++----------- 10 files changed, 471 insertions(+), 526 deletions(-) diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index ccc70a3..8ded8b3 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -1002,9 +1002,10 @@ var httpObserver = { ABORT: Components.results.NS_BINDING_ABORTED, ACCEPT: Components.results.NS_SUCCEEDED, // Request types: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIContentPolicy#Constants - MAIN_FRAME: Ci.nsIContentPolicy.TYPE_DOCUMENT, - VALID_CSP_TARGETS: 1 << Ci.nsIContentPolicy.TYPE_DOCUMENT | - 1 << Ci.nsIContentPolicy.TYPE_SUBDOCUMENT, + frameTypeMap: { + 6: 'main_frame', + 7: 'sub_frame' + }, typeMap: { 1: 'other', 2: 'script', @@ -1128,13 +1129,15 @@ var httpObserver = { return true; } - /*if ( result.redirectUrl ) { - channel.redirectionLimit = 1; - channel.redirectTo( - Services.io.newURI(result.redirectUrl, null, null) - ); + // For the time being, will block instead of redirecting + // TODO: figure a better way of blocking embedded frames. + // Maybe blocking network requests, then having a content script + // revisit the DOM to replace blocked frame with something more + // friendly. Will see. + if ( typeof result === 'object' && result.redirectUrl ) { + channel.cancel(this.ABORT); return true; - }*/ + } } var onBeforeSendHeaders = vAPI.net.onBeforeSendHeaders; @@ -1158,7 +1161,7 @@ var httpObserver = { } var URI = channel.URI; - var channelData, result; + var channelData, type, result; if ( topic === 'http-on-examine-response' ) { if ( !(channel instanceof Ci.nsIWritablePropertyBag) ) { @@ -1175,7 +1178,8 @@ var httpObserver = { return; } - if ( (1 << channelData[4] & this.VALID_CSP_TARGETS) === 0 ) { + type = this.frameTypeMap[channelData[4]]; + if ( !type ) { return; } @@ -1191,7 +1195,9 @@ var httpObserver = { hostname: URI.asciiHost, parentFrameId: channelData[1], responseHeaders: result ? [{name: topic, value: result}] : [], + statusLine: channel.responseStatus.toString(), tabId: channelData[3], + type: type, url: URI.asciiSpec }); @@ -1469,7 +1475,7 @@ vAPI.toolbarButton.init = function() { 'font-size: 9px;', 'font-weight: bold;', 'color: #fff;', - 'background: #666;', + 'background: #000;', 'content: attr(badge);', '}' ); @@ -1503,7 +1509,7 @@ vAPI.toolbarButton.init = function() { this.CUIEvents.updateBadgeStyle = function() { var css = [ - 'background: #666', + 'background: #000', 'color: #fff' ].join(';'); @@ -1592,18 +1598,19 @@ vAPI.toolbarButton.onBeforeCreated = function(doc) { if ( updateTimer ) { return; } - updateTimer = setTimeout(resizePopup, 10); }; var resizePopup = function() { updateTimer = null; var body = iframe.contentDocument.body; panel.parentNode.style.maxWidth = 'none'; + // We set a limit for height + var height = Math.min(body.clientHeight, 600); // https://github.com/chrisaljoudi/uBlock/issues/730 // Voodoo programming: this recipe works - panel.style.height = iframe.style.height = body.clientHeight.toString() + 'px'; + panel.style.height = iframe.style.height = height.toString() + 'px'; panel.style.width = iframe.style.width = body.clientWidth.toString() + 'px'; - if ( iframe.clientHeight !== body.clientHeight || iframe.clientWidth !== body.clientWidth ) { + if ( iframe.clientHeight !== height || iframe.clientWidth !== body.clientWidth ) { delayedResize(); } }; diff --git a/src/js/async.js b/src/js/async.js index 5520cf3..a0ec58f 100644 --- a/src/js/async.js +++ b/src/js/async.js @@ -133,30 +133,12 @@ return asyncJobManager; // Update visual of extension icon. // A time out is used to coalesce adjacent requests to update badge. -µMatrix.updateBadgeAsync = (function(){ - var µm = µMatrix; - - // Cache callback definition, it was a bad idea to define this one inside - // updateBadgeAsync - var updateBadge = function(tabId) { - var µm = µMatrix; - var pageStore = µm.pageStatsFromTabId(tabId); - if ( pageStore ) { - pageStore.updateBadge(tabId); - return; - } - vAPI.setIcon(tabId, null, '?'); - }; - - var updateBadgeAsync = function(tabId) { - if ( vAPI.isBehindTheSceneTabId(tabId) ) { - return; - } - µm.asyncJobs.add('updateBadge-' + tabId, tabId, updateBadge, 500); - }; - - return updateBadgeAsync; -})(); +µMatrix.updateBadgeAsync = function(tabId) { + var pageStore = this.pageStoreFromTabId(tabId); + if ( pageStore ) { + pageStore.updateBadge(); + } +}; /******************************************************************************/ diff --git a/src/js/background.js b/src/js/background.js index 465142f..e091cd0 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -98,17 +98,13 @@ return { // urls stats are kept on the back burner while waiting to be reactivated // in a tab or another. - pageStats: {}, // TODO: rename + pageStores: {}, + pageStoreCemetery: {}, // A map of redirects, to allow reverse lookup of redirects from landing // page, so that redirection can be reported to the user. redirectRequests: {}, - // tabs are used to redirect stats collection to a specific url stats - // structure. - pageUrlToTabId: {}, - tabIdToPageUrl: {}, - // page url => permission scope tMatrix: null, pMatrix: null, @@ -129,7 +125,7 @@ return { // record what chromium is doing behind the scene behindTheSceneURL: 'http://chromium-behind-the-scene/', - behindTheSceneTabId: 0x7FFFFFFF, + behindTheSceneTabId: vAPI.noTabId, behindTheSceneMaxReq: 250, behindTheSceneScope: 'chromium-behind-the-scene', diff --git a/src/js/cookies.js b/src/js/cookies.js index a55faaf..f9e3fcf 100644 --- a/src/js/cookies.js +++ b/src/js/cookies.js @@ -197,8 +197,7 @@ var recordPageCookiesAsync = function(pageStats) { if ( !pageStats ) { return; } - var pageURL = µm.pageUrlFromPageStats(pageStats); - recordPageCookiesQueue[pageURL] = pageStats; + recordPageCookiesQueue[pageStats.pageUrl] = pageStats; µm.asyncJobs.add( 'cookieHunterPageRecord', null, @@ -220,6 +219,10 @@ var cookieLogEntryBuilder = [ ]; var recordPageCookie = function(pageStore, cookieKey) { + if ( vAPI.isBehindTheSceneTabId(pageStore.tabId) ) { + return; + } + var cookieEntry = cookieDict[cookieKey]; var block = µm.mustBlock(pageStore.pageHostname, cookieEntry.hostname, 'cookie'); @@ -263,8 +266,7 @@ var removePageCookiesAsync = function(pageStats) { if ( !pageStats ) { return; } - var pageURL = µm.pageUrlFromPageStats(pageStats); - removePageCookiesQueue[pageURL] = pageStats; + removePageCookiesQueue[pageStats.pageUrl] = pageStats; µm.asyncJobs.add( 'cookieHunterPageRemove', null, @@ -508,13 +510,13 @@ vAPI.cookies.onChanged = function(changeInfo) { // Go through all pages and update if needed, as one cookie can be used // by many web pages, so they need to be recorded for all these pages. - var pageStores = µm.pageStats; + var pageStores = µm.pageStores; var pageStore; - for ( var pageURL in pageStores ) { - if ( pageStores.hasOwnProperty(pageURL) === false ) { + for ( var tabId in pageStores ) { + if ( pageStores.hasOwnProperty(tabId) === false ) { continue; } - pageStore = pageStores[pageURL]; + pageStore = pageStores[tabId]; if ( !cookieMatchDomains(cookieKey, pageStore.allHostnamesString) ) { continue; } diff --git a/src/js/info.js b/src/js/info.js index dd64424..b6a5859 100644 --- a/src/js/info.js +++ b/src/js/info.js @@ -31,7 +31,7 @@ var messager = vAPI.messaging.channel('info.js'); -var targetUrl = 'all'; +var targetTabId = null; var maxRequests = 500; var cachedUserSettings = {}; @@ -55,7 +55,7 @@ function updateRequestData(callback) { }; var request = { what: 'getRequestLogs', - pageURL: targetUrl !== 'all' ? targetUrl : null + tabId: targetTabId }; messager.send(request, onResponseReceived); } @@ -65,7 +65,7 @@ function updateRequestData(callback) { function clearRequestData() { var request = { what: 'clearRequestLogs', - pageURL: targetUrl !== 'all' ? targetUrl : null + tabId: targetTabId }; messager.send(request); } @@ -108,7 +108,7 @@ var renderLocalized = function(id, map) { /******************************************************************************/ function renderPageUrls() { - var onResponseReceived = function(r) { + var onResponseReceived = function(result) { var i, n; var select = uDom('#selectPageUrls'); @@ -118,25 +118,25 @@ function renderPageUrls() { n = builtinOptions.length; for ( i = 0; i < n; i++ ) { option = builtinOptions.at(i).clone(); - if ( option.val() === targetUrl ) { + if ( option.val() === targetTabId ) { option.attr('selected', true); } select.append(option); } - var pageURLs = r.pageURLs.sort(); - var pageURL, option; - n = pageURLs.length; + var entries = result.pageURLs.sort(); + var entry, pageURL, option; + n = entries.length; for ( i = 0; i < n; i++ ) { - pageURL = pageURLs[i]; + entry = entries[i]; // Behind-the-scene entry is always present, no need to recreate it - if ( pageURL === r.behindTheSceneURL ) { + if ( entry.pageURL === result.behindTheSceneURL ) { continue; } option = uDom('