From 255c68baa4880fb83f312e9e44e993fe8f379c53 Mon Sep 17 00:00:00 2001 From: gorhill Date: Tue, 20 Jan 2015 19:39:13 -0500 Subject: [PATCH] this fixes #536 --- platform/chromium/vapi-background.js | 94 ++++++++++++++++++++++------ platform/firefox/vapi-background.js | 33 ++++++---- platform/safari/vapi-background.js | 11 +++- src/js/background.js | 4 +- src/js/pagestore.js | 3 +- src/js/static-net-filtering.js | 7 ++- src/js/traffic.js | 35 +++-------- src/js/ublock.js | 20 ------ 8 files changed, 119 insertions(+), 88 deletions(-) diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 21d6c7723..9af049fdf 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -38,6 +38,8 @@ var manifest = chrome.runtime.getManifest(); vAPI.chrome = true; +var noopFunc = function(){}; + /******************************************************************************/ vAPI.app = { @@ -280,7 +282,7 @@ vAPI.messaging = { ports: {}, listeners: {}, defaultHandler: null, - NOOPFUNC: function(){}, + NOOPFUNC: noopFunc, UNHANDLED: 'vAPI.messaging.notHandled' }; @@ -382,25 +384,81 @@ vAPI.messaging.broadcast = function(message) { /******************************************************************************/ -vAPI.net = { - registerListeners: function() { - var listeners = [ - 'onBeforeRequest', - 'onBeforeSendHeaders', - 'onHeadersReceived' - ]; +vAPI.net = {}; - for ( var i = 0; i < listeners.length; i++ ) { - chrome.webRequest[listeners[i]].addListener( - this[listeners[i]].callback, - { - 'urls': this[listeners[i]].urls || [''], - 'types': this[listeners[i]].types || [] - }, - this[listeners[i]].extra - ); +/******************************************************************************/ + +vAPI.net.registerListeners = function() { + var µb = µBlock; + var µburi = µb.URI; + + var normalizeRequestDetails = function(details) { + µburi.set(details.url); + + details.tabId = details.tabId.toString(); + details.hostname = µburi.hostnameFromURI(details.url); + + var type = details.type; + if ( type !== 'other' ) { + return; } - } + var path = µburi.path; + var pos = path.lastIndexOf('.'); + if ( pos === -1 ) { + return; + } + var ext = path.slice(pos) + '.'; + if ( '.eot.ttf.otf.svg.woff.woff2.'.indexOf(ext) !== -1 ) { + details.type = 'font'; + return; + } + if ( '.ico.'.indexOf(ext) !== -1 ) { + details.type = 'image'; + return; + } + // https://code.google.com/p/chromium/issues/detail?id=410382 + if ( type === 'other' ) { + details.type = 'object'; + return; + } + }; + + var onBeforeRequestClient = this.onBeforeRequest.callback; + var onBeforeRequest = function(details) { + normalizeRequestDetails(details); + return onBeforeRequestClient(details); + }; + chrome.webRequest.onBeforeRequest.addListener( + onBeforeRequest, + { + 'urls': this.onBeforeRequest.urls || [''], + 'types': this.onBeforeRequest.types || [] + }, + this.onBeforeRequest.extra + ); + + chrome.webRequest.onBeforeSendHeaders.addListener( + this.onBeforeSendHeaders.callback, + { + 'urls': this.onBeforeSendHeaders.urls || [''], + 'types': this.onBeforeSendHeaders.types || [] + }, + this.onBeforeSendHeaders.extra + ); + + var onHeadersReceivedClient = this.onHeadersReceived.callback; + var onHeadersReceived = function(details) { + normalizeRequestDetails(details); + return onHeadersReceivedClient(details); + }; + chrome.webRequest.onHeadersReceived.addListener( + onHeadersReceived, + { + 'urls': this.onHeadersReceived.urls || [''], + 'types': this.onHeadersReceived.types || [] + }, + this.onHeadersReceived.extra + ); }; /******************************************************************************/ diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index eb57d588e..33b191627 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -785,6 +785,7 @@ var httpObserver = { contractID: '@' + location.host + '/net-channel-event-sinks;1', 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, @@ -795,7 +796,9 @@ var httpObserver = { 5: 'object', 6: 'main_frame', 7: 'sub_frame', - 11: 'xmlhttprequest' + 11: 'xmlhttprequest', + 12: 'object', + 14: 'font' }, lastRequest: { url: null, @@ -892,11 +895,12 @@ var httpObserver = { } var result = onBeforeRequest.callback({ - url: channel.URI.asciiSpec, - type: type, - tabId: details.tabId, frameId: details.frameId, - parentFrameId: details.parentFrameId + hostname: channel.URI.asciiHost, + parentFrameId: details.parentFrameId, + tabId: details.tabId, + type: type, + url: channel.URI.asciiSpec }); if ( !result || typeof result !== 'object' ) { @@ -906,7 +910,9 @@ var httpObserver = { if ( result.cancel === true ) { channel.cancel(this.ABORT); return true; - } else if ( result.redirectUrl ) { + } + + if ( result.redirectUrl ) { channel.redirectionLimit = 1; channel.redirectTo( Services.io.newURI(result.redirectUrl, null, null) @@ -954,10 +960,11 @@ var httpObserver = { } result = vAPI.net.onHeadersReceived.callback({ - url: URI.asciiSpec, - tabId: channelData[1], + hostname: URI.asciiHost, parentFrameId: channelData[0] === this.MAIN_FRAME ? -1 : 0, - responseHeaders: result ? [{name: topic, value: result}] : [] + responseHeaders: result ? [{name: topic, value: result}] : [], + tabId: channelData[1], + url: URI.asciiSpec }); if ( result ) { @@ -1098,11 +1105,11 @@ vAPI.net.registerListeners = function() { // data: and about:blank if ( details.url.charAt(0) !== 'h' ) { vAPI.net.onBeforeRequest.callback({ - url: 'http://' + details.url.slice(0, details.url.indexOf(':')), - type: 'main_frame', - tabId: vAPI.tabs.getTabId(e.target), frameId: details.frameId, - parentFrameId: details.parentFrameId + parentFrameId: details.parentFrameId, + tabId: vAPI.tabs.getTabId(e.target), + type: 'main_frame', + url: 'http://' + details.url.slice(0, details.url.indexOf(':')) }); return; } diff --git a/platform/safari/vapi-background.js b/platform/safari/vapi-background.js index 3853a93a5..f96761fd0 100644 --- a/platform/safari/vapi-background.js +++ b/platform/safari/vapi-background.js @@ -591,6 +591,8 @@ vAPI.net = {}; /******************************************************************************/ vAPI.net.registerListeners = function() { + var µb = µBlock; + // Since it's not used this.onBeforeSendHeaders = null; this.onHeadersReceived = null; @@ -615,9 +617,11 @@ vAPI.net.registerListeners = function() { } if ( e.message.isURLWhiteListed ) { - block = µBlock.URI.hostnameFromURI(e.message.isURLWhiteListed); - block = µBlock.URI.domainFromHostname(block) || block; - e.message = !!µBlock.netWhitelist[block]; + block = µb.URI.hostnameFromURI(e.message.isURLWhiteListed); + block = µb.URI.domainFromHostname(block) || block; + + // TODO: revise, this can't work properly + e.message = !!µb.netWhitelist[block]; return e.message; } @@ -659,6 +663,7 @@ vAPI.net.registerListeners = function() { return true; } + e.message.hostname = µb.URI.hostnameFromURI(e.message.url); e.message.tabId = vAPI.tabs.getTabId(e.target); block = onBeforeRequest(e.message); diff --git a/src/js/background.js b/src/js/background.js index 4306d65b9..5f09784a5 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -19,14 +19,14 @@ Home: https://github.com/gorhill/uBlock */ -/* global vAPI */ /* exported µBlock */ -'use strict'; /******************************************************************************/ var µBlock = (function() { +'use strict'; + /******************************************************************************/ var oneSecond = 1000; diff --git a/src/js/pagestore.js b/src/js/pagestore.js index 3b7ab5f00..2b94bc3ed 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -67,7 +67,6 @@ var logEntryJunkyardMax = 100; LogEntry.prototype.init = function(details, result) { this.tstamp = Date.now(); this.url = details.requestURL; - this.domain = details.requestDomain; this.hostname = details.requestHostname; this.type = details.requestType; this.result = result; @@ -77,7 +76,7 @@ LogEntry.prototype.init = function(details, result) { /******************************************************************************/ LogEntry.prototype.dispose = function() { - this.url = this.domain = this.hostname = this.type = this.result = ''; + this.url = this.hostname = this.type = this.result = ''; if ( logEntryJunkyard.length < logEntryJunkyardMax ) { logEntryJunkyard.push(this); } diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 8013e3c41..1e81d4a1a 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -68,6 +68,7 @@ var typeNameToTypeValue = { 'inline-script': 14 << 4, 'popup': 15 << 4 }; +var typeOtherToTypeValue = typeNameToTypeValue['other']; const BlockAnyTypeAnyParty = BlockAction | AnyType | AnyParty; const BlockAnyType = BlockAction | AnyType; @@ -1754,7 +1755,8 @@ FilterContainer.prototype.matchStringExactType = function(context, requestURL, r // This will be used by hostname-based filters pageHostname = context.pageHostname || ''; - var type = typeNameToTypeValue[requestType]; + // Be prepared to support unknown types + var type = typeNameToTypeValue[requestType] || typeOtherToTypeValue; var categories = this.categories; var bucket; @@ -1814,7 +1816,8 @@ FilterContainer.prototype.matchStringExactType = function(context, requestURL, r FilterContainer.prototype.matchString = function(context) { // https://github.com/gorhill/uBlock/issues/519 // Use exact type match for anything beyond `other` - var type = typeNameToTypeValue[context.requestType]; + // Also, be prepared to support unknown types + var type = typeNameToTypeValue[context.requestType] || typeOtherToTypeValue; if ( type > 8 << 4 ) { return this.matchStringExactType(context, context.requestURL, context.requestType); } diff --git a/src/js/traffic.js b/src/js/traffic.js index be14fb273..0bd3182da 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -56,26 +56,6 @@ var onBeforeRequest = function(details) { return; } - // Commented out until (and if ever) there is a fix for: - // https://code.google.com/p/chromium/issues/detail?id=410382 - // - // Try to transpose generic `other` category into something more meaningful. - if ( requestType === 'other' ) { - requestType = µb.transposeType('other', µb.URI.set(requestURL).path); - // https://github.com/gorhill/uBlock/issues/206 - // https://code.google.com/p/chromium/issues/detail?id=410382 - // Work around the issue of Chromium not properly setting the type for - // `object` requests. Unclear whether this issue will be fixed, hence - // this workaround to prevent torch-and-pitchfork mobs because ads are - // no longer blocked in videos. - // https://github.com/gorhill/uBlock/issues/281 - // Looks like Chrome 38 (but not 39) doesn't provide the expected request - // header `X-Requested-With`. Sigh. - if ( requestType === 'other' ) { - requestType = 'object'; - } - } - // Lookup the page store associated with this tab id. pageStore = µb.pageStoreFromTabId(tabId); if ( !pageStore ) { @@ -94,7 +74,7 @@ var onBeforeRequest = function(details) { // Setup context and evaluate requestContext.requestURL = requestURL; - requestContext.requestHostname = µb.URI.hostnameFromURI(requestURL); + requestContext.requestHostname = details.hostname; requestContext.requestType = requestType; var result = pageStore.filterRequest(requestContext); @@ -217,7 +197,7 @@ var onBeforeSendHeaders = function(details) { var result = µb.staticNetFilteringEngine.matchStringExactType(pageDetails, requestURL, 'popup'); // Not blocked? - if ( result === '' || result.slice(0, 2) === '@@' ) { + if ( µb.isAllowResult(result) ) { return; } @@ -254,8 +234,7 @@ var onHeadersReceived = function(details) { //} var requestURL = details.url; - var requestHostname = µb.URI.hostnameFromURI(requestURL); - var requestDomain = µb.URI.domainFromHostname(requestHostname); + var requestHostname = details.hostname; // https://github.com/gorhill/uBlock/issues/525 // When we are dealing with the root frame, due to fix to issue #516, it @@ -266,11 +245,12 @@ var onHeadersReceived = function(details) { // inline scripts. var context; if ( details.parentFrameId === -1 ) { + var contextDomain = µb.URI.domainFromHostname(requestHostname); context = { rootHostname: requestHostname, - rootDomain: requestDomain, + rootDomain: contextDomain, pageHostname: requestHostname, - pageDomain: requestDomain + pageDomain: contextDomain }; } else { context = pageStore; @@ -282,7 +262,6 @@ var onHeadersReceived = function(details) { // URLs-different type context.requestURL = requestURL + '{inline-script}'; context.requestHostname = requestHostname; - context.requestDomain = requestDomain; context.requestType = 'inline-script'; var result = pageStore.filterRequest(context); @@ -323,7 +302,7 @@ var headerStartsWith = function(headers, prefix) { var prefixLen = prefix.length; var i = headers.length; while ( i-- ) { - if ( headers[i].name.slice(0, prefixLen).toLowerCase() === prefix ) { + if ( headers[i].name.toLowerCase().lastIndexOf(prefix, 0) === 0 ) { return headers[i].value; } } diff --git a/src/js/ublock.js b/src/js/ublock.js index 791b1d1bd..e595cf787 100644 --- a/src/js/ublock.js +++ b/src/js/ublock.js @@ -281,26 +281,6 @@ var matchWhitelistDirective = function(url, hostname, directive) { /******************************************************************************/ -µBlock.transposeType = function(type, path) { - if ( type !== 'other' ) { - return type; - } - var pos = path.lastIndexOf('.'); - if ( pos === -1 ) { - return type; - } - var ext = path.slice(pos) + '.'; - if ( '.eot.ttf.otf.svg.woff.woff2.'.indexOf(ext) !== -1 ) { - return 'font'; - } - if ( '.ico.'.indexOf(ext) !== -1 ) { - return 'image'; - } - return type; -}; - -/******************************************************************************/ - µBlock.elementPickerExec = function(tabId, targetElement) { this.elementPickerTarget = targetElement || ''; vAPI.tabs.injectScript(tabId, { file: 'js/element-picker.js' });