diff --git a/platform/firefox/frameModule.js b/platform/firefox/frameModule.js
index 5b7419404..ae469a078 100644
--- a/platform/firefox/frameModule.js
+++ b/platform/firefox/frameModule.js
@@ -63,7 +63,7 @@ const contentObserver = {
},
QueryInterface: (function() {
- let {XPCOMUtils} = Cu.import('resource://gre/modules/XPCOMUtils.jsm', {});
+ let {XPCOMUtils} = Cu.import('resource://gre/modules/XPCOMUtils.jsm', null);
return XPCOMUtils.generateQI([
Ci.nsIFactory,
@@ -117,7 +117,7 @@ const contentObserver = {
return this.ACCEPT;
}
- var opener;
+ let openerURL;
if ( location.scheme !== 'http' && location.scheme !== 'https' ) {
if ( type !== this.MAIN_FRAME ) {
@@ -127,10 +127,10 @@ const contentObserver = {
context = context.contentWindow || context;
try {
- opener = context.opener.location.href;
+ openerURL = context.opener.location.href;
} catch (ex) {}
- let isPopup = location.spec === 'about:blank' && opener;
+ let isPopup = location.spec === 'about:blank' && openerURL;
if ( location.scheme !== 'data' && !isPopup ) {
return this.ACCEPT;
@@ -139,7 +139,7 @@ const contentObserver = {
context = context.contentWindow || context;
try {
- opener = context.opener.location.href;
+ openerURL = context.opener.location.href;
} catch (ex) {}
} else {
context = (context.ownerDocument || context).defaultView;
@@ -150,7 +150,7 @@ const contentObserver = {
if ( context.top && context.location ) {
// https://bugzil.la/1092216
getMessageManager(context).sendRpcMessage(this.cpMessageName, {
- opener: opener || null,
+ openerURL: openerURL || null,
url: location.spec,
type: type,
frameId: type === this.MAIN_FRAME ? -1 : (context === context.top ? 0 : 1),
@@ -215,14 +215,19 @@ const contentObserver = {
);
}.bind(sandbox);
sandbox.removeMessageListener = function() {
- messager.removeMessageListener(
- this._sandboxId_,
- this._messageListener_
- );
- messager.removeMessageListener(
- hostName + ':broadcast',
- this._messageListener_
- );
+ try {
+ messager.removeMessageListener(
+ this._sandboxId_,
+ this._messageListener_
+ );
+ messager.removeMessageListener(
+ hostName + ':broadcast',
+ this._messageListener_
+ );
+ } catch (ex) {
+ // It throws sometimes, mostly when the popup closes
+ }
+
this._messageListener_ = null;
}.bind(sandbox);
diff --git a/platform/firefox/frameScript.js b/platform/firefox/frameScript.js
index c97e9acab..560eca251 100644
--- a/platform/firefox/frameScript.js
+++ b/platform/firefox/frameScript.js
@@ -19,6 +19,8 @@
Home: https://github.com/gorhill/uBlock
*/
+'use strict';
+
/******************************************************************************/
Components.utils.import(
diff --git a/platform/firefox/install.rdf b/platform/firefox/install.rdf
index 0ba00168c..9cbbd7f58 100644
--- a/platform/firefox/install.rdf
+++ b/platform/firefox/install.rdf
@@ -18,7 +18,7 @@
{{ec8030f7-c20a-464f-9b0e-13a3a9e97384}}
29.0
- 37.0
+ 38.0
@@ -27,7 +27,7 @@
{{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}}
2.26
- 2.34
+ 2.35
diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js
index 255668893..1e7bd97fc 100644
--- a/platform/firefox/vapi-background.js
+++ b/platform/firefox/vapi-background.js
@@ -42,7 +42,7 @@ vAPI.firefox = true;
// TODO: read these data from somewhere...
vAPI.app = {
name: 'µBlock',
- version: '0.8.2.3'
+ version: '0.8.5.0'
};
/******************************************************************************/
@@ -248,7 +248,7 @@ var windowWatcher = {
onTabClose: function(e) {
var tabId = vAPI.tabs.getTabId(e.target);
vAPI.tabs.onClosed(tabId);
- delete vAPI.tabIcons[tabId];
+ delete vAPI.toolbarButton.tabs[tabId];
},
onTabSelect: function(e) {
@@ -279,7 +279,6 @@ var windowWatcher = {
tC.addEventListener('TabClose', windowWatcher.onTabClose);
tC.addEventListener('TabSelect', windowWatcher.onTabSelect);
- vAPI.toolbarButton.register(this.document);
vAPI.contextMenu.register(this.document);
// when new window is opened TabSelect doesn't run on the selected tab?
@@ -334,13 +333,11 @@ vAPI.tabs.registerListeners = function() {
}
Services.ww.registerNotification(windowWatcher);
- vAPI.toolbarButton.init();
vAPI.unload.push(function() {
Services.ww.unregisterNotification(windowWatcher);
for ( var win of vAPI.tabs.getWindows() ) {
- vAPI.toolbarButton.unregister(win.document);
vAPI.contextMenu.unregister(win.document);
win.removeEventListener('DOMContentLoaded', windowWatcher.onReady);
@@ -600,19 +597,19 @@ vAPI.tabs.injectScript = function(tabId, details, callback) {
/******************************************************************************/
-vAPI.tabIcons = { /*tabId: {badge: 0, img: boolean}*/ };
vAPI.setIcon = function(tabId, iconStatus, badge) {
// If badge is undefined, then setIcon was called from the TabSelect event
- var curWin = badge === undefined
+ var win = badge === undefined
? iconStatus
: Services.wm.getMostRecentWindow('navigator:browser');
- var curTabId = vAPI.tabs.getTabId(curWin.gBrowser.selectedTab);
+ var curTabId = vAPI.tabs.getTabId(win.gBrowser.selectedTab);
+ var tb = vAPI.toolbarButton;
// from 'TabSelect' event
if ( tabId === undefined ) {
tabId = curTabId;
} else if ( badge !== undefined ) {
- vAPI.tabIcons[tabId] = {
+ tb.tabs[tabId] = {
badge: badge,
img: iconStatus === 'on'
};
@@ -622,166 +619,23 @@ vAPI.setIcon = function(tabId, iconStatus, badge) {
return;
}
- var button = curWin.document.getElementById(vAPI.toolbarButton.widgetId);
+ var button = win.document.getElementById(tb.id);
if ( !button ) {
return;
}
- /*if ( !button.classList.contains('badged-button') ) {
- button.classList.add('badged-button');
- }*/
-
- var icon = vAPI.tabIcons[tabId];
+ var icon = tb.tabs[tabId];
button.setAttribute('badge', icon && icon.badge || '');
- iconStatus = !button.image || !icon || !icon.img ? '-off' : '';
- button.image = vAPI.getURL('img/browsericons/icon16' + iconStatus + '.svg');
-};
-/******************************************************************************/
-
-vAPI.toolbarButton = {
- widgetId: location.host + '-button',
- panelId: location.host + '-panel'
-};
-
-/******************************************************************************/
-
-vAPI.toolbarButton.init = function() {
- const {CustomizableUI} = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-
- CustomizableUI.createWidget({
- id: this.widgetId,
- type: 'view',
- viewId: this.panelId,
- defaultArea: CustomizableUI.AREA_NAVBAR,
- label: vAPI.app.name,
- tooltiptext: vAPI.app.name,
- onViewShowing: function({target}) {
- var hash = CustomizableUI.getWidget(vAPI.toolbarButton.widgetId)
- .areaType === CustomizableUI.TYPE_TOOLBAR ? '' : '#body';
-
- target.firstChild.setAttribute(
- 'src',
- vAPI.getURL('popup.html' + hash)
- );
- },
- onViewHiding: function({target}) {
- target.firstChild.setAttribute('src', 'about:blank');
- }
- });
-
- this.closePopup = function({target}) {
- CustomizableUI.hidePanelForNode(
- target.ownerDocument.getElementById(vAPI.toolbarButton.panelId)
- );
- };
-
- vAPI.messaging.globalMessageManager.addMessageListener(
- location.host + ':closePopup',
- this.closePopup
- );
-
- vAPI.unload.push(function() {
- CustomizableUI.destroyWidget(vAPI.toolbarButton.widgetId);
- vAPI.messaging.globalMessageManager.removeMessageListener(
- location.host + ':closePopup',
- vAPI.toolbarButton.closePopup
- );
- });
-};
-
-/******************************************************************************/
-
-// it runs with windowWatcher when a window is opened
-// vAPI.tabs.registerListeners initializes it
-
-vAPI.toolbarButton.register = function(doc) {
- var panel = doc.createElement('panelview');
- panel.setAttribute('id', this.panelId);
-
- var iframe = doc.createElement('iframe');
- iframe.setAttribute('type', 'content');
-
- doc.getElementById('PanelUI-multiView')
- .appendChild(panel)
- .appendChild(iframe);
-
- var updateTimer = null;
- var delayedResize = function() {
- if ( updateTimer ) {
- return;
- }
-
- updateTimer = setTimeout(resizePopup, 20);
- };
-
- var resizePopup = function() {
- var panelStyle = panel.style;
- var body = iframe.contentDocument.body;
- panelStyle.width = iframe.style.width = body.clientWidth + 'px';
- panelStyle.height = iframe.style.height = body.clientHeight + 'px';
- updateTimer = null;
- };
-
- var onPopupReady = function() {
- var win = this.contentWindow;
-
- if ( !win || win.location.host !== location.host ) {
- return;
- }
-
- new win.MutationObserver(delayedResize).observe(win.document, {
- childList: true,
- attributes: true,
- characterData: true,
- subtree: true
- });
-
- delayedResize();
- };
-
- iframe.addEventListener('load', onPopupReady, true);
-
- if ( !this.styleURI ) {
- this.styleURI = 'data:text/css,' + encodeURIComponent([
- '#' + this.widgetId + ' {',
- 'list-style-image: url(',
- vAPI.getURL('img/browsericons/icon16-off.svg'),
- ');',
- '}',
- '#' + this.widgetId + '[badge]:not([badge=""])::after {',
- 'position: absolute;',
- 'margin-left: -16px;',
- 'margin-top: 3px;',
- 'padding: 1px 2px;',
- 'font-size: 9px;',
- 'font-weight: bold;',
- 'color: #fff;',
- 'background: #666;',
- 'content: attr(badge);',
- '}',
- '#' + this.panelId + ', #' + this.panelId + ' > iframe {',
- 'width: 180px;',
- 'height: 310px;',
- 'overflow: hidden !important;',
- '}'
- ].join(''));
-
- this.styleURI = Services.io.newURI(this.styleURI, null, null);
+ if ( !icon || !icon.img ) {
+ icon = '';
+ }
+ else {
+ icon = 'url(' + vAPI.getURL('img/browsericons/icon16.svg') + ')';
}
- doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIDOMWindowUtils).loadSheet(this.styleURI, 1);
-};
-
-/******************************************************************************/
-
-vAPI.toolbarButton.unregister = function(doc) {
- var panel = doc.getElementById(this.panelId);
- panel.parentNode.removeChild(panel);
- doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIDOMWindowUtils).removeSheet(this.styleURI, 1);
+ button.style.listStyleImage = icon;
};
/******************************************************************************/
@@ -933,7 +787,7 @@ var httpObserver = {
tabId: null,
frameId: null,
parentFrameId: null,
- opener: null
+ openerURL: null
},
get componentRegistrar() {
@@ -946,7 +800,7 @@ var httpObserver = {
},
QueryInterface: (function() {
- var {XPCOMUtils} = Cu.import('resource://gre/modules/XPCOMUtils.jsm', {});
+ var {XPCOMUtils} = Cu.import('resource://gre/modules/XPCOMUtils.jsm', null);
return XPCOMUtils.generateQI([
Ci.nsIFactory,
@@ -1113,12 +967,12 @@ var httpObserver = {
var sourceTabId = null;
// popup candidate (only for main_frame type)
- if ( lastRequest.opener ) {
+ if ( lastRequest.openerURL ) {
for ( var tab of vAPI.tabs.getAll() ) {
var tabURI = tab.linkedBrowser.currentURI;
// not the best approach
- if ( tabURI.spec === this.lastRequest.opener ) {
+ if ( tabURI.spec === this.lastRequest.openerURL ) {
sourceTabId = vAPI.tabs.getTabId(tab);
break;
}
@@ -1205,6 +1059,9 @@ vAPI.net = {};
/******************************************************************************/
vAPI.net.registerListeners = function() {
+ // Since it's not used
+ this.onBeforeSendHeaders = null;
+
this.onBeforeRequest.types = new Set(this.onBeforeRequest.types);
var shouldLoadListenerMessageName = location.host + ':shouldLoad';
@@ -1229,7 +1086,7 @@ vAPI.net.registerListeners = function() {
lastRequest.tabId = vAPI.tabs.getTabId(e.target);
lastRequest.frameId = details.frameId;
lastRequest.parentFrameId = details.parentFrameId;
- lastRequest.opener = details.opener;
+ lastRequest.openerURL = details.openerURL;
};
vAPI.messaging.globalMessageManager.addMessageListener(
@@ -1251,6 +1108,192 @@ vAPI.net.registerListeners = function() {
/******************************************************************************/
+vAPI.toolbarButton = {
+ id: location.host + '-button',
+ type: 'view',
+ viewId: location.host + '-panel',
+ label: vAPI.app.name,
+ tooltiptext: vAPI.app.name,
+ tabs: {/*tabId: {badge: 0, img: boolean}*/}
+};
+
+/******************************************************************************/
+
+vAPI.toolbarButton.init = function() {
+ var {CustomizableUI} = Cu.import('resource:///modules/CustomizableUI.jsm', null);
+ this.defaultArea = CustomizableUI.AREA_NAVBAR;
+ this.styleURI = [
+ '#' + this.id + ' {',
+ 'list-style-image: url(',
+ vAPI.getURL('img/browsericons/icon16-off.svg'),
+ ');',
+ '}',
+ '#' + this.viewId + ', #' + this.viewId + ' > iframe {',
+ 'width: 160px;',
+ 'height: 290px;',
+ 'overflow: hidden !important;',
+ '}'
+ ];
+
+ var platformVersion = Services.appinfo.platformVersion;
+
+ if ( Services.vc.compare(platformVersion, '36.0') < 0 ) {
+ this.styleURI.push(
+ '#' + this.id + '[badge]:not([badge=""])::after {',
+ 'position: absolute;',
+ 'margin-left: -16px;',
+ 'margin-top: 3px;',
+ 'padding: 1px 2px;',
+ 'font-size: 9px;',
+ 'font-weight: bold;',
+ 'color: #fff;',
+ 'background: #666;',
+ 'content: attr(badge);',
+ '}'
+ );
+ }
+
+ this.styleURI = Services.io.newURI(
+ 'data:text/css,' + encodeURIComponent(this.styleURI.join('')),
+ null,
+ null
+ );
+
+ this.closePopup = function({target}) {
+ CustomizableUI.hidePanelForNode(
+ target.ownerDocument.getElementById(vAPI.toolbarButton.viewId)
+ );
+ };
+
+ CustomizableUI.createWidget(this);
+ vAPI.messaging.globalMessageManager.addMessageListener(
+ location.host + ':closePopup',
+ this.closePopup
+ );
+
+ vAPI.unload.push(function() {
+ CustomizableUI.destroyWidget(this.id);
+ vAPI.messaging.globalMessageManager.removeMessageListener(
+ location.host + ':closePopup',
+ this.closePopup
+ );
+
+ for ( var win of vAPI.tabs.getWindows() ) {
+ var panel = win.document.getElementById(this.viewId);
+ panel.parentNode.removeChild(panel);
+ win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils)
+ .removeSheet(this.styleURI, 1);
+ }
+ }.bind(this));
+};
+
+/******************************************************************************/
+
+vAPI.toolbarButton.onBeforeCreated = function(doc) {
+ var panel = doc.createElement('panelview');
+ panel.setAttribute('id', this.viewId);
+
+ var iframe = doc.createElement('iframe');
+ iframe.setAttribute('type', 'content');
+
+ doc.getElementById('PanelUI-multiView')
+ .appendChild(panel)
+ .appendChild(iframe);
+
+ var updateTimer = null;
+ var delayedResize = function() {
+ if ( updateTimer ) {
+ return;
+ }
+
+ updateTimer = setTimeout(resizePopup, 50);
+ };
+ var resizePopup = function() {
+ var body = iframe.contentDocument.body;
+ panel.parentNode.style.maxWidth = 'none';
+ panel.style.width = iframe.style.width = body.clientWidth + 'px';
+ panel.style.height = iframe.style.height = body.clientHeight + 'px';
+ updateTimer = null;
+ };
+ var onPopupReady = function() {
+ var win = this.contentWindow;
+
+ if ( !win || win.location.host !== location.host ) {
+ return;
+ }
+
+ new win.MutationObserver(delayedResize).observe(win.body, {
+ attributes: true,
+ characterData: true,
+ subtree: true
+ });
+
+ delayedResize();
+ };
+
+ iframe.addEventListener('load', onPopupReady, true);
+
+ doc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils)
+ .loadSheet(this.styleURI, 1);
+};
+
+/******************************************************************************/
+
+vAPI.toolbarButton.onCreated = function(button) {
+ var platformVersion = Services.appinfo.platformVersion;
+
+ if ( Services.vc.compare(platformVersion, '36.0') < 0 ) {
+ return;
+ }
+
+ button.setAttribute('badge', '');
+ button.classList.add('badged-button');
+
+ setTimeout(function() {
+ var badge = button.ownerDocument.getAnonymousElementByAttribute(
+ button,
+ 'class',
+ 'toolbarbutton-badge'
+ );
+
+ if ( !badge ) {
+ return;
+ }
+
+ badge.style.cssText = [
+ 'position: absolute;',
+ 'bottom: 0;',
+ 'right: 0;',
+ 'padding: 1px;',
+ 'background: #666;',
+ 'color: #fff;',
+ 'font-size: 9px;',
+ 'font-weight: bold;'
+ ].join('');
+ }, 1000);
+};
+
+/******************************************************************************/
+
+vAPI.toolbarButton.onViewShowing = function({target}) {
+ target.firstChild.setAttribute('src', vAPI.getURL('popup.html'));
+};
+
+/******************************************************************************/
+
+vAPI.toolbarButton.onViewHiding = function({target}) {
+ target.parentNode.style.maxWidth = '';
+ target.firstChild.setAttribute('src', 'about:blank');
+};
+
+/******************************************************************************/
+
+vAPI.toolbarButton.init();
+
+/******************************************************************************/
+
vAPI.contextMenu = {
contextMap: {
frame: 'inFrame',
@@ -1267,6 +1310,11 @@ vAPI.contextMenu = {
vAPI.contextMenu.displayMenuItem = function(e) {
var doc = e.target.ownerDocument;
var gContextMenu = doc.defaultView.gContextMenu;
+
+ if ( !gContextMenu.browser ) {
+ return;
+ }
+
var menuitem = doc.getElementById(vAPI.contextMenu.menuItemId);
if ( /^https?$/.test(gContextMenu.browser.currentURI.scheme) === false) {
diff --git a/platform/firefox/vapi-common.js b/platform/firefox/vapi-common.js
index 949b7e909..14dbbe37c 100644
--- a/platform/firefox/vapi-common.js
+++ b/platform/firefox/vapi-common.js
@@ -85,7 +85,7 @@ vAPI.i18n = (function() {
try {
return stringBundle.GetStringFromName(s);
} catch (ex) {
- return s;
+ return '';
}
};
})();
diff --git a/platform/safari/Info.plist b/platform/safari/Info.plist
index b12663242..938976a51 100644
--- a/platform/safari/Info.plist
+++ b/platform/safari/Info.plist
@@ -84,7 +84,7 @@
+ https://raw.githubusercontent.com/gorhill/uBlock/master/dist/Update.plist -->
Website
https://github.com/gorhill/uBlock
diff --git a/platform/safari/vapi-background.js b/platform/safari/vapi-background.js
index 87d31bf54..3ca98dec1 100644
--- a/platform/safari/vapi-background.js
+++ b/platform/safari/vapi-background.js
@@ -602,6 +602,10 @@ vAPI.net = {};
/******************************************************************************/
vAPI.net.registerListeners = function() {
+ // Since it's not used
+ this.onBeforeSendHeaders = null;
+ this.onHeadersReceived = null;
+
var onBeforeRequest = this.onBeforeRequest;
if ( !Array.isArray(onBeforeRequest.types) ) {
diff --git a/platform/safari/vapi-common.js b/platform/safari/vapi-common.js
index 59d39fe21..36690cd3c 100644
--- a/platform/safari/vapi-common.js
+++ b/platform/safari/vapi-common.js
@@ -74,12 +74,13 @@ vAPI.getURL = function(path) {
/******************************************************************************/
-// supported languages
-// first language is the default
+// Supported languages
+// First language is the default
+
vAPI.i18nData = [
- 'en', 'ar', 'cs', 'da', 'de', 'el', 'es', 'et', 'fi', 'fil', 'fr', 'he',
- 'hi', 'hr', 'hu', 'id', 'it', 'ja', 'mr', 'nb', 'nl', 'pl', 'pt-BR',
- 'pt-PT', 'ro', 'ru', 'sv', 'tr', 'uk', 'vi', 'zh-CN'
+ 'en', 'ar', 'ca', 'cs', 'da', 'de', 'el', 'es', 'et', 'fi', 'fil',
+ 'fr', 'he', 'hi', 'hr', 'hu', 'id', 'it', 'ja', 'mr', 'nb', 'nl', 'pl',
+ 'pt-BR', 'pt-PT', 'ro', 'ru', 'sv', 'tr', 'uk', 'vi', 'zh-CN', 'zh-TW'
];
vAPI.i18n = navigator.language;
diff --git a/src/css/popup.css b/src/css/popup.css
index ccc0d6fb6..0303ced42 100644
--- a/src/css/popup.css
+++ b/src/css/popup.css
@@ -7,9 +7,6 @@ body {
padding: 0;
white-space: nowrap;
}
-#body:target {
- float: none;
- }
h1,h2,h3,h4 {
background-color: #444;
border: 0;
diff --git a/tools/make-firefox-meta.py b/tools/make-firefox-meta.py
index 49967ca1a..55922d546 100644
--- a/tools/make-firefox-meta.py
+++ b/tools/make-firefox-meta.py
@@ -25,7 +25,7 @@ target_locale_dir = pj(build_dir, 'locale')
language_codes = []
description = ''
-for alpha2 in os.listdir(source_locale_dir):
+for alpha2 in sorted(os.listdir(source_locale_dir)):
locale_path = pj(source_locale_dir, alpha2, 'messages.json')
with open(locale_path, encoding='utf-8') as f:
string_data = json.load(f, object_pairs_hook=OrderedDict)