diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-17 18:10:23 +0200 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-10-17 18:10:23 +0200 |
commit | ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7 (patch) | |
tree | f5f542e168df6b8da261ee0d95476a254fff9139 /platform | |
parent | 2a260e13033aa80f474f3c7ca2f7f4ca4aec2f54 (diff) | |
parent | 230639d959468fc67c7ca5cf0249009eee0853b8 (diff) | |
download | uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.zip uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.tar.gz uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.tar.bz2 |
Merge branch 'upstream'
Diffstat (limited to 'platform')
-rw-r--r-- | platform/chromium/manifest.json | 2 | ||||
-rw-r--r-- | platform/chromium/vapi-background.js | 8 | ||||
-rw-r--r-- | platform/firefox/bootstrap.js | 12 | ||||
-rw-r--r-- | platform/firefox/frameModule.js | 47 | ||||
-rw-r--r-- | platform/firefox/frameScript.js | 33 | ||||
-rw-r--r-- | platform/firefox/install.rdf | 21 | ||||
-rw-r--r-- | platform/firefox/vapi-background.js | 287 | ||||
-rw-r--r-- | platform/firefox/vapi-client.js | 37 | ||||
-rw-r--r-- | platform/opera/manifest.json | 2 |
9 files changed, 352 insertions, 97 deletions
diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index 7c25ce9..81c3148 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "uBlock Origin", - "version": "1.1.1", + "version": "1.3.0", "default_locale": "en", "description": "__MSG_extShortDesc__", diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 79d929e..853accb 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -1017,7 +1017,7 @@ vAPI.cloud = (function() { // Mind chrome.storage.sync.QUOTA_BYTES_PER_ITEM (8192 at time of writing) var maxChunkSize = Math.floor(chrome.storage.sync.QUOTA_BYTES_PER_ITEM * 0.75); - // Mind chrome.storage.sync.QUOTA_BYTES_PER_ITEM (8192 at time of writing) + // Mind chrome.storage.sync.QUOTA_BYTES (128 kB at time of writing) var maxStorageSize = chrome.storage.sync.QUOTA_BYTES; var options = { @@ -1029,8 +1029,8 @@ vAPI.cloud = (function() { // We "poll" at specific index in order to get a rough idea of how // large is the stored string. // This allows reading a single item with only 2 sync operations -- a - // good thing given chrome.storage.syncMAX_WRITE_OPERATIONS_PER_MINUTE - // and chrome.storage.syncMAX_WRITE_OPERATIONS_PER_HOUR. + // good thing given chrome.storage.sync.MAX_WRITE_OPERATIONS_PER_MINUTE + // and chrome.storage.sync.MAX_WRITE_OPERATIONS_PER_HOUR. var getCoarseChunkCount = function(dataKey, callback) { var bin = {}; @@ -1085,7 +1085,7 @@ vAPI.cloud = (function() { bin.size = JSON.stringify(bin).length; var item = JSON.stringify(bin); - // Chunkify taking into account QUOTA_BYTES_PER_ITEM: + // Chunkify taking into account QUOTA_BYTES_PER_ITEM: // https://developer.chrome.com/extensions/storage#property-sync // "The maximum size (in bytes) of each individual item in sync // "storage, as measured by the JSON stringification of its value diff --git a/platform/firefox/bootstrap.js b/platform/firefox/bootstrap.js index d1adfc4..c765d98 100644 --- a/platform/firefox/bootstrap.js +++ b/platform/firefox/bootstrap.js @@ -19,7 +19,7 @@ Home: https://github.com/gorhill/uBlock */ -/* global ADDON_UNINSTALL, APP_SHUTDOWN, APP_STARTUP */ +/* global ADDON_UNINSTALL, APP_SHUTDOWN */ /* exported startup, shutdown, install, uninstall */ 'use strict'; @@ -48,7 +48,7 @@ const restartListener = { /******************************************************************************/ -function startup(data, reason) { +function startup(data/*, reason*/) { if ( data !== undefined ) { version = data.version; } @@ -86,7 +86,13 @@ function startup(data, reason) { ); }; - if ( reason !== APP_STARTUP ) { + var ready = false; + try { + ready = appShell.hiddenDOMWindow && + appShell.hiddenDOMWindow.document; + } catch (ex) { + } + if ( ready ) { onReady(); return; } diff --git a/platform/firefox/frameModule.js b/platform/firefox/frameModule.js index a11720e..37de2b5 100644 --- a/platform/firefox/frameModule.js +++ b/platform/firefox/frameModule.js @@ -23,6 +23,7 @@ /******************************************************************************/ +// https://github.com/gorhill/uBlock/issues/800 this.EXPORTED_SYMBOLS = ['contentObserver', 'LocationChangeListener']; const {interfaces: Ci, utils: Cu} = Components; @@ -30,6 +31,7 @@ const {Services} = Cu.import('resource://gre/modules/Services.jsm', null); const {XPCOMUtils} = Cu.import('resource://gre/modules/XPCOMUtils.jsm', null); const hostName = Services.io.newURI(Components.stack.filename, null, null).host; +const rpcEmitterName = hostName + ':child-process-message'; //Cu.import('resource://gre/modules/devtools/Console.jsm'); @@ -61,7 +63,7 @@ const getMessageManager = function(win) { /******************************************************************************/ -const contentObserver = { +var contentObserver = { classDescription: 'content-policy for ' + hostName, classID: Components.ID('{7afbd130-cbaf-46c2-b944-f5d24305f484}'), contractID: '@' + hostName + '/content-policy;1', @@ -239,9 +241,25 @@ const contentObserver = { wantXHRConstructor: false }); + if ( Services.cpmm ) { + sandbox.rpc = function(details) { + var svc = Services; + if ( svc === undefined ) { return; } + var cpmm = svc.cpmm; + if ( !cpmm ) { return; } + var r = cpmm.sendSyncMessage(rpcEmitterName, details); + if ( Array.isArray(r) ) { + return r[0]; + } + }; + } else { + sandbox.rpc = function() {}; + } + sandbox.injectScript = function(script) { - if ( Services !== undefined ) { - Services.scriptloader.loadSubScript(script, sandbox); + var svc = Services; + if ( svc !== undefined ) { + svc.scriptloader.loadSubScript(script, sandbox); } else { // Sandbox appears void. // I've seen this happens, need to investigate why. @@ -258,9 +276,10 @@ const contentObserver = { sandbox.removeMessageListener(); sandbox.addMessageListener = sandbox.injectScript = + sandbox.outerShutdown = sandbox.removeMessageListener = - sandbox.sendAsyncMessage = - sandbox.outerShutdown = function(){}; + sandbox.rpc = + sandbox.sendAsyncMessage = function(){}; sandbox.vAPI = {}; messager = null; }; @@ -405,20 +424,26 @@ const contentObserver = { const locationChangedMessageName = hostName + ':locationChanged'; -const LocationChangeListener = function(docShell) { +var LocationChangeListener = function(docShell) { if ( !docShell ) { return; } var requestor = docShell.QueryInterface(Ci.nsIInterfaceRequestor); var ds = requestor.getInterface(Ci.nsIWebProgress); + if ( !ds ) { + return; + } var mm = requestor.getInterface(Ci.nsIContentFrameMessageManager); - - if ( ds && mm && typeof mm.sendAsyncMessage === 'function' ) { - this.docShell = ds; - this.messageManager = mm; - ds.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_LOCATION); + if ( !mm ) { + return; + } + if ( typeof mm.sendAsyncMessage !== 'function' ) { + return; } + this.docShell = ds; + this.messageManager = mm; + ds.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_LOCATION); }; LocationChangeListener.prototype.QueryInterface = XPCOMUtils.generateQI([ diff --git a/platform/firefox/frameScript.js b/platform/firefox/frameScript.js index fdee50c..17cd84f 100644 --- a/platform/firefox/frameScript.js +++ b/platform/firefox/frameScript.js @@ -19,13 +19,11 @@ Home: https://github.com/gorhill/uBlock */ -/* global addMessageListener, removeMessageListener, docShell */ - /******************************************************************************/ -var locationChangeListener; // Keep alive while frameScript is alive +// https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment -(function() { +(function(context) { 'use strict'; @@ -52,25 +50,36 @@ let injectContentScripts = function(win) { }; let onLoadCompleted = function() { - removeMessageListener('ublock0-load-completed', onLoadCompleted); - injectContentScripts(content); + context.removeMessageListener('ublock0-load-completed', onLoadCompleted); + injectContentScripts(context.content); }; +context.addMessageListener('ublock0-load-completed', onLoadCompleted); -addMessageListener('ublock0-load-completed', onLoadCompleted); +let shutdown = function(ev) { + if ( ev.target !== context ) { + return; + } + context.removeMessageListener('ublock0-load-completed', onLoadCompleted); + context.removeEventListener('unload', shutdown); + context.locationChangeListener = null; + LocationChangeListener = null; + contentObserver = null; +}; +context.addEventListener('unload', shutdown); -if ( docShell ) { +if ( context.docShell ) { let Ci = Components.interfaces; - let wp = docShell.QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebProgress); + let wp = context.docShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebProgress); let dw = wp.DOMWindow; if ( dw === dw.top ) { - locationChangeListener = new LocationChangeListener(docShell); + context.locationChangeListener = new LocationChangeListener(context.docShell); } } /******************************************************************************/ -})(); +})(this); /******************************************************************************/ diff --git a/platform/firefox/install.rdf b/platform/firefox/install.rdf index 42ec05a..5f5b7ec 100644 --- a/platform/firefox/install.rdf +++ b/platform/firefox/install.rdf @@ -9,6 +9,7 @@ <creator>{author}</creator> <developer>Deathamns</developer> <developer>Alex Vallat</developer> + <developer>Manuel Reimer</developer> <type>2</type> <bootstrap>true</bootstrap> <multiprocessCompatible>true</multiprocessCompatible> @@ -38,7 +39,7 @@ <r:Description> <id>{{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}}</id> <minVersion>2.21</minVersion> - <maxVersion>2.37</maxVersion> + <maxVersion>2.38</maxVersion> </r:Description> </targetApplication> @@ -50,5 +51,23 @@ <maxVersion>26.*</maxVersion> </r:Description> </targetApplication> + + <!-- Conkeror --> + <targetApplication> + <r:Description> + <id>{{a79fe89b-6662-4ff4-8e88-09950ad4dfde}}</id> + <minVersion>0.1</minVersion> + <maxVersion>9.9</maxVersion> + </r:Description> + </targetApplication> + + <!-- Thunderbird --> + <targetApplication> + <r:Description> + <id>{{3550f703-e582-4d05-9a08-453d09bdfdc6}}</id> + <minVersion>38.3.0</minVersion> + <maxVersion>45.0</maxVersion> + </r:Description> + </targetApplication> </r:Description> </r:RDF> diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index a74fd23..0a4b98d 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -40,6 +40,7 @@ const {Services} = Cu.import('resource://gre/modules/Services.jsm', null); var vAPI = self.vAPI = self.vAPI || {}; vAPI.firefox = true; vAPI.fennec = Services.appinfo.ID === '{aa3c5121-dab2-40e2-81ca-7ea25febc110}'; +vAPI.thunderbird = Services.appinfo.ID === '{3550f703-e582-4d05-9a08-453d09bdfdc6}'; /******************************************************************************/ @@ -70,7 +71,7 @@ vAPI.localStorage.setDefaultBool('forceLegacyToolbarButton', false); var cleanupTasks = []; // This must be updated manually, every time a new task is added/removed -var expectedNumberOfCleanups = 7; +var expectedNumberOfCleanups = 8; window.addEventListener('unload', function() { if ( typeof vAPI.app.onShutdown === 'function' ) { @@ -90,10 +91,11 @@ window.addEventListener('unload', function() { } // frameModule needs to be cleared too + var frameModuleURL = vAPI.getURL('frameModule.js'); var frameModule = {}; - Cu.import(vAPI.getURL('frameModule.js'), frameModule); + Cu.import(frameModuleURL, frameModule); frameModule.contentObserver.unregister(); - Cu.unload(vAPI.getURL('frameModule.js')); + Cu.unload(frameModuleURL); }); /******************************************************************************/ @@ -522,9 +524,23 @@ vAPI.storage = (function() { /******************************************************************************/ -var getTabBrowser = function(win) { - return vAPI.fennec && win.BrowserApp || win.gBrowser || null; -}; +var getTabBrowser = (function() { + if ( vAPI.fennec ) { + return function(win) { + return win.BrowserApp || null; + }; + } + + if ( vAPI.thunderbird ) { + return function(win) { + return win.document.getElementById('tabmail') || null; + }; + } + + return function(win) { + return win.gBrowser || null; + }; +})(); /******************************************************************************/ @@ -557,6 +573,16 @@ vAPI.noTabId = '-1'; vAPI.tabs = {}; + +/******************************************************************************/ + +vAPI.tabs.mostRecentWindowId = (function() { + if ( vAPI.thunderbird ) { + return 'mail:3pane'; + } + return 'navigator:browser'; +})(); + /******************************************************************************/ vAPI.tabs.registerListeners = function() { @@ -656,7 +682,7 @@ vAPI.tabs.getAll = function(window) { /******************************************************************************/ vAPI.tabs.getWindows = function() { - var winumerator = Services.wm.getEnumerator('navigator:browser'); + var winumerator = Services.wm.getEnumerator(this.mostRecentWindowId); var windows = []; while ( winumerator.hasMoreElements() ) { @@ -728,11 +754,13 @@ vAPI.tabs.open = function(details) { } } - var win = Services.wm.getMostRecentWindow('navigator:browser'); + var win = Services.wm.getMostRecentWindow(this.mostRecentWindowId); var tabBrowser = getTabBrowser(win); if ( vAPI.fennec ) { - tabBrowser.addTab(details.url, {selected: details.active !== false}); + tabBrowser.addTab(details.url, { + selected: details.active !== false + }); // Note that it's impossible to move tabs on Fennec, so don't bother return; } @@ -749,6 +777,15 @@ vAPI.tabs.open = function(details) { return; } + if ( vAPI.thunderbird ) { + tabBrowser.openTab('contentTab', { + contentPage: details.url, + background: !details.active + }); + // TODO: Should be possible to move tabs on Thunderbird + return; + } + if ( details.index === -1 ) { details.index = tabBrowser.browsers.indexOf(tabBrowser.selectedBrowser) + 1; } @@ -780,13 +817,16 @@ vAPI.tabs.replace = function(tabId, url) { /******************************************************************************/ -vAPI.tabs._remove = function(tab, tabBrowser) { - if ( vAPI.fennec ) { - tabBrowser.closeTab(tab); - return; +vAPI.tabs._remove = (function() { + if ( vAPI.fennec || vAPI.thunderbird ) { + return function(tab, tabBrowser) { + tabBrowser.closeTab(tab); + }; } - tabBrowser.removeTab(tab); -}; + return function(tab, tabBrowser) { + tabBrowser.removeTab(tab); + }; +})(); /******************************************************************************/ @@ -875,6 +915,10 @@ var tabWatcher = (function() { var tabIdGenerator = 1; var indexFromBrowser = function(browser) { + // TODO: Add support for this + if ( vAPI.thunderbird ) { + return -1; + } var win = getOwnerWindow(browser); if ( !win ) { return -1; @@ -920,22 +964,36 @@ var tabWatcher = (function() { return tabbrowser.tabs[i]; }; - var browserFromTarget = function(target) { - if ( !target ) { - return null; - } + var browserFromTarget = (function() { if ( vAPI.fennec ) { - if ( target.browser ) { // target is a tab - target = target.browser; - } - } else if ( target.linkedPanel ) { // target is a tab - target = target.linkedBrowser; + return function(target) { + if ( !target ) { return null; } + if ( target.browser ) { // target is a tab + target = target.browser; + } + return target.localName === 'browser' ? target : null; + }; } - if ( target.localName !== 'browser' ) { - return null; + if ( vAPI.thunderbird ) { + return function(target) { + if ( !target ) { return null; } + if ( target.mode ) { // target is object with tab info + var browserFunc = target.mode.getBrowser || target.mode.tabType.getBrowser; + if ( browserFunc ) { + return browserFunc.call(target.mode.tabType, target); + } + } + return target.localName === 'browser' ? target : null; + }; } - return target; - }; + return function(target) { + if ( !target ) { return null; } + if ( target.linkedPanel ) { // target is a tab + target = target.linkedBrowser; + } + return target.localName === 'browser' ? target : null; + }; + })(); var tabIdFromTarget = function(target) { var browser = browserFromTarget(target); @@ -965,13 +1023,20 @@ var tabWatcher = (function() { }; var currentBrowser = function() { - var win = Services.wm.getMostRecentWindow('navigator:browser'); + var win = Services.wm.getMostRecentWindow(vAPI.tabs.mostRecentWindowId); // https://github.com/gorhill/uBlock/issues/399 // getTabBrowser() can return null at browser launch time. var tabBrowser = getTabBrowser(win); if ( tabBrowser === null ) { return null; } + if ( vAPI.thunderbird ) { + // Directly at startup the first tab may not be initialized + if ( tabBrowser.tabInfo.length === 0 ) { + return null; + } + return tabBrowser.getBrowserForSelectedTab() || null; + } return browserFromTarget(tabBrowser.selectedTab); }; @@ -986,17 +1051,21 @@ var tabWatcher = (function() { } }; - // https://developer.mozilla.org/en-US/docs/Web/Events/TabOpen - var onOpen = function({target}) { - var tabId = tabIdFromTarget(target); - var browser = browserFromTabId(tabId); - vAPI.tabs.onNavigation({ - frameId: 0, - tabId: tabId, - url: browser.currentURI.asciiSpec, - }); + var removeTarget = function(target) { + onClose({ target: target }); }; + // https://developer.mozilla.org/en-US/docs/Web/Events/TabOpen + //var onOpen = function({target}) { + // var tabId = tabIdFromTarget(target); + // var browser = browserFromTabId(tabId); + // vAPI.tabs.onNavigation({ + // frameId: 0, + // tabId: tabId, + // url: browser.currentURI.asciiSpec, + // }); + //}; + // https://developer.mozilla.org/en-US/docs/Web/Events/TabShow var onShow = function({target}) { tabIdFromTarget(target); @@ -1021,29 +1090,29 @@ var tabWatcher = (function() { return false; } + if ( typeof vAPI.toolbarButton.attachToNewWindow === 'function' ) { + vAPI.toolbarButton.attachToNewWindow(window); + } + var tabContainer; if ( tabBrowser.deck ) { // Fennec tabContainer = tabBrowser.deck; } else if ( tabBrowser.tabContainer ) { // Firefox tabContainer = tabBrowser.tabContainer; vAPI.contextMenu.register(window.document); - } else { - return true; - } - - if ( typeof vAPI.toolbarButton.attachToNewWindow === 'function' ) { - vAPI.toolbarButton.attachToNewWindow(window); } // https://github.com/gorhill/uBlock/issues/697 // Ignore `TabShow` events: unfortunately the `pending` attribute is // not set when a tab is opened as a result of session restore -- it is // set *after* the event is fired in such case. - //tabContainer.addEventListener('TabOpen', onOpen); - tabContainer.addEventListener('TabShow', onShow); - tabContainer.addEventListener('TabClose', onClose); - // when new window is opened TabSelect doesn't run on the selected tab? - tabContainer.addEventListener('TabSelect', onSelect); + if ( tabContainer ) { + //tabContainer.addEventListener('TabOpen', onOpen); + tabContainer.addEventListener('TabShow', onShow); + tabContainer.addEventListener('TabClose', onClose); + // when new window is opened TabSelect doesn't run on the selected tab? + tabContainer.addEventListener('TabSelect', onSelect); + } return true; }; @@ -1092,7 +1161,9 @@ var tabWatcher = (function() { // To keep in mind: not all windows are tab containers, // sometimes the window IS the tab. var tabs; - if ( tabBrowser.tabs ) { + if ( vAPI.thunderbird ) { + tabs = tabBrowser.tabInfo; + } else if ( tabBrowser.tabs ) { tabs = tabBrowser.tabs; } else if ( tabBrowser.localName === 'browser' ) { tabs = [tabBrowser]; @@ -1101,8 +1172,10 @@ var tabWatcher = (function() { } var browser, URI, tabId; - for ( var tab of tabs ) { - browser = tabWatcher.browserFromTarget(tab); + var tabindex = tabs.length, tab; + while ( tabindex-- ) { + tab = tabs[tabindex]; + browser = browserFromTarget(tab); if ( browser === null ) { continue; } @@ -1111,7 +1184,6 @@ var tabWatcher = (function() { if ( URI.schemeIs('chrome') && URI.host === location.host ) { vAPI.tabs._remove(tab, getTabBrowser(this)); } - browser = browserFromTarget(tab); tabId = browserToTabIdMap.get(browser); if ( tabId !== undefined ) { removeBrowserEntry(tabId, browser); @@ -1137,14 +1209,19 @@ var tabWatcher = (function() { // Initialize map with existing active tabs var start = function() { - var tabBrowser, tab; + var tabBrowser, tabs, tab; for ( var win of vAPI.tabs.getWindows() ) { onWindowLoad.call(win); tabBrowser = getTabBrowser(win); if ( tabBrowser === null ) { continue; } - for ( tab of tabBrowser.tabs ) { + // `tabBrowser.tabs` may not exist (Thunderbird). + tabs = tabBrowser.tabs; + if ( !tabs ) { + continue; + } + for ( tab of tabs ) { if ( vAPI.fennec || !tab.hasAttribute('pending') ) { tabIdFromTarget(tab); } @@ -1173,6 +1250,7 @@ var tabWatcher = (function() { browserFromTarget: browserFromTarget, currentBrowser: currentBrowser, indexFromTarget: indexFromTarget, + removeTarget: removeTarget, start: start, tabFromBrowser: tabFromBrowser, tabIdFromTarget: tabIdFromTarget @@ -1185,7 +1263,7 @@ vAPI.setIcon = function(tabId, iconStatus, badge) { // If badge is undefined, then setIcon was called from the TabSelect event var win = badge === undefined ? iconStatus - : Services.wm.getMostRecentWindow('navigator:browser'); + : Services.wm.getMostRecentWindow(vAPI.tabs.mostRecentWindowId); var curTabId = tabWatcher.tabIdFromTarget(getTabBrowser(win).selectedTab); var tb = vAPI.toolbarButton; @@ -1208,7 +1286,7 @@ vAPI.messaging = { return Cc['@mozilla.org/globalmessagemanager;1'] .getService(Ci.nsIMessageListenerManager); }, - frameScript: vAPI.getURL('frameScript.js'), + frameScriptURL: vAPI.getURL('frameScript.js'), listeners: {}, defaultHandler: null, NOOPFUNC: function(){}, @@ -1438,7 +1516,7 @@ vAPI.messaging.setup = function(defaultHandler) { this.onMessage ); - this.globalMessageManager.loadFrameScript(this.frameScript, true); + this.globalMessageManager.loadFrameScript(this.frameScriptURL, true); cleanupTasks.push(function() { var gmm = vAPI.messaging.globalMessageManager; @@ -1452,7 +1530,7 @@ vAPI.messaging.setup = function(defaultHandler) { }) ); - gmm.removeDelayedFrameScript(vAPI.messaging.frameScript); + gmm.removeDelayedFrameScript(vAPI.messaging.frameScriptURL); gmm.removeMessageListener( location.host + ':background', vAPI.messaging.onMessage @@ -1472,6 +1550,60 @@ vAPI.messaging.broadcast = function(message) { }; /******************************************************************************/ +/******************************************************************************/ + +// Synchronous messaging: Firefox allows this. Chromium does not allow this. + +// Sometimes there is no way around synchronous messaging, as long as: +// - the code at the other end execute fast and return quickly. +// - it's not abused. +// Original rationale is <https://github.com/gorhill/uBlock/issues/756>. +// Synchronous messaging is a good solution for this case because: +// - It's done only *once* per page load. (Keep in mind there is already a +// sync message sent for each single network request on a page and it's not +// an issue, because the code executed is trivial, which is the key -- see +// shouldLoadListener below). +// - The code at the other end is fast. +// Though vAPI.rpcReceiver was brought forth because of this one case, I +// generalized the concept for whatever future need for synchronous messaging +// which might arise. + +// https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview#Content_frame_message_manager + +vAPI.rpcReceiver = (function() { + var calls = Object.create(null); + var childProcessMessageName = location.host + ':child-process-message'; + + var onChildProcessMessage = function(ev) { + var msg = ev.data; + if ( !msg ) { return; } + var fn = calls[msg.fnName]; + if ( typeof fn === 'function' ) { + return fn(msg); + } + }; + + if ( Services.ppmm ) { + Services.ppmm.addMessageListener( + childProcessMessageName, + onChildProcessMessage + ); + } + + cleanupTasks.push(function() { + if ( Services.ppmm ) { + Services.ppmm.removeMessageListener( + childProcessMessageName, + onChildProcessMessage + ); + } + }); + + return calls; +})(); + +/******************************************************************************/ +/******************************************************************************/ var httpObserver = { classDescription: 'net-channel-event-sinks for ' + location.host, @@ -1865,7 +1997,11 @@ vAPI.net.registerListeners = function() { var tabId = tabWatcher.tabIdFromTarget(e.target); var sourceTabId = null; - // Popup candidate + // Popup candidate: this code path is taken only for when a new top + // document loads, i.e. only once per document load. TODO: evaluate for + // popup filtering in an asynchrous manner -- it's not really required + // to evaluate on the spot. Still, there is currently no harm given + // this code path is typically taken only once per page load. if ( details.openerURL ) { for ( var browser of tabWatcher.browsers() ) { var URI = browser.currentURI; @@ -1899,8 +2035,9 @@ vAPI.net.registerListeners = function() { } } - //console.log('shouldLoadListener:', details.url); - + // We are being called synchronously from the content process, so we + // must return ASAP. The code below merely record the details of the + // request into a ring buffer for later retrieval by the HTTP observer. var pendingReq = httpObserver.createPendingRequest(details.url); pendingReq.frameId = details.frameId; pendingReq.parentFrameId = details.parentFrameId; @@ -1918,10 +2055,22 @@ vAPI.net.registerListeners = function() { var locationChangedListener = function(e) { var browser = e.target; + // I have seen this happens (at startup time) + if ( !browser.currentURI ) { + return; + } + // https://github.com/gorhill/uBlock/issues/697 // Dismiss event if the associated tab is pending. var tab = tabWatcher.tabFromBrowser(browser); if ( !vAPI.fennec && tab && tab.hasAttribute('pending') ) { + // https://github.com/gorhill/uBlock/issues/820 + // Firefox quirk: it happens the `pending` attribute was not + // present for certain tabs at startup -- and this can cause + // unwanted [browser <--> tab id] associations internally. + // Dispose of these if it is found the `pending` attribute is + // set. + tabWatcher.removeTarget(tab); return; } @@ -2131,9 +2280,12 @@ vAPI.toolbarButton = { resizeTimer = null; var body = iframe.contentDocument.body; panel.parentNode.style.maxWidth = 'none'; + + // https://github.com/gorhill/uMatrix/issues/362 + panel.parentNode.style.opacity = '1'; + // https://github.com/chrisaljoudi/uBlock/issues/730 // Voodoo programming: this recipe works - var clientHeight = body.clientHeight; iframe.style.height = toPx(clientHeight); panel.style.height = toPx(clientHeight + panel.boxObject.height - panel.clientHeight); @@ -2202,7 +2354,8 @@ vAPI.toolbarButton = { var addLegacyToolbarButton = function(window) { var document = window.document; - var toolbox = document.getElementById('navigator-toolbox') || document.getElementById('mail-toolbox'); + var toolbox = document.getElementById('navigator-toolbox') || + document.getElementById('mail-toolbox'); if ( !toolbox ) { return; } @@ -2766,6 +2919,12 @@ vAPI.contextMenu.register = function(doc) { } var contextMenu = doc.getElementById('contentAreaContextMenu'); + + // This can happen (Thunderbird). + if ( contextMenu === null ) { + return; + } + var menuitem = doc.createElement('menuitem'); menuitem.setAttribute('id', this.menuItemId); menuitem.setAttribute('label', this.menuLabel); diff --git a/platform/firefox/vapi-client.js b/platform/firefox/vapi-client.js index bd6facd..b8715e8 100644 --- a/platform/firefox/vapi-client.js +++ b/platform/firefox/vapi-client.js @@ -31,6 +31,13 @@ /******************************************************************************/ +// Not all sandboxes are given an rpc function, so assign a dummy one if it is +// missing -- this avoids the need for testing before use. + +self.rpc = self.rpc || function(){}; + +/******************************************************************************/ + var vAPI = self.vAPI = self.vAPI || {}; vAPI.firefox = true; vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) + @@ -67,6 +74,30 @@ vAPI.shutdown = (function() { /******************************************************************************/ +(function() { + var hostname = location.hostname; + if ( !hostname ) { + return; + } + var filters = self.rpc({ + fnName: 'getScriptTagFilters', + url: location.href, + hostname: hostname + }); + if ( typeof filters !== 'string' || filters === '' ) { + return; + } + var reFilters = new RegExp(filters); + document.addEventListener('beforescriptexecute', function(ev) { + if ( reFilters.test(ev.target.textContent) ) { + ev.preventDefault(); + ev.stopPropagation(); + } + }); +})(); + +/******************************************************************************/ + vAPI.messaging = { channels: {}, pending: {}, @@ -254,6 +285,12 @@ MessagingChannel.prototype.send = function(message, callback) { MessagingChannel.prototype.sendTo = function(message, toTabId, toChannel, callback) { var messaging = vAPI.messaging; + if ( !messaging ) { + if ( typeof callback === 'function' ) { + callback(); + } + return; + } // Too large a gap between the last request and the last response means // the main process is no longer reachable: memory leaks and bad // performance become a risk -- especially for long-lived, dynamic diff --git a/platform/opera/manifest.json b/platform/opera/manifest.json index 6ebbd32..b177b61 100644 --- a/platform/opera/manifest.json +++ b/platform/opera/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "uBlock Origin", - "version": "1.1.1", + "version": "1.3.0", "default_locale": "en", "description": "__MSG_extShortDesc__", |