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)