aboutsummaryrefslogtreecommitdiffstats
path: root/platform
diff options
context:
space:
mode:
authorWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2015-10-17 18:10:23 +0200
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2015-10-17 18:10:23 +0200
commitea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7 (patch)
treef5f542e168df6b8da261ee0d95476a254fff9139 /platform
parent2a260e13033aa80f474f3c7ca2f7f4ca4aec2f54 (diff)
parent230639d959468fc67c7ca5cf0249009eee0853b8 (diff)
downloaduBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.zip
uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.tar.gz
uBlock-ea0c3f8ecde7d6e418ddfc8c6f58cb2bbf1e84c7.tar.bz2
Merge branch 'upstream'
Diffstat (limited to 'platform')
-rw-r--r--platform/chromium/manifest.json2
-rw-r--r--platform/chromium/vapi-background.js8
-rw-r--r--platform/firefox/bootstrap.js12
-rw-r--r--platform/firefox/frameModule.js47
-rw-r--r--platform/firefox/frameScript.js33
-rw-r--r--platform/firefox/install.rdf21
-rw-r--r--platform/firefox/vapi-background.js287
-rw-r--r--platform/firefox/vapi-client.js37
-rw-r--r--platform/opera/manifest.json2
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__",