diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index 2556688..1e7bd97 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) {