From c0e11d81825e3a51faddad06076b5fcb3b1baf5c Mon Sep 17 00:00:00 2001 From: Deathamns Date: Mon, 1 Dec 2014 16:23:19 +0100 Subject: [PATCH 1/4] Safari: fix vAPI.tabs.close() + cleanup --- meta/safariextz/Info.plist | 91 ------------------- meta/safariextz/Settings.plist | 22 ----- platform/safari/Info.plist | 91 +++++++++++++++++++ platform/safari/Settings.plist | 22 +++++ .../safari}/sitepatch-safari.js | 0 .../safari}/update_safariextz.plist | 4 +- .../safari}/vapi-background.js | 39 +++++--- .../safari}/vapi-client.js | 33 ++++--- .../safari}/vapi-common.js | 1 - tools/make-safari.sh | 6 +- 10 files changed, 164 insertions(+), 145 deletions(-) delete mode 100644 meta/safariextz/Info.plist delete mode 100644 meta/safariextz/Settings.plist create mode 100644 platform/safari/Info.plist create mode 100644 platform/safari/Settings.plist rename {meta/safariextz => platform/safari}/sitepatch-safari.js (100%) rename {meta/safariextz => platform/safari}/update_safariextz.plist (90%) rename {meta/safariextz => platform/safari}/vapi-background.js (95%) rename {meta/safariextz => platform/safari}/vapi-client.js (95%) rename {meta/safariextz => platform/safari}/vapi-common.js (99%) diff --git a/meta/safariextz/Info.plist b/meta/safariextz/Info.plist deleted file mode 100644 index 50134bc3a..000000000 --- a/meta/safariextz/Info.plist +++ /dev/null @@ -1,91 +0,0 @@ - - - - - Author - Raymond Hill - Builder Version - 534.57.2 - CFBundleDisplayName - µBlock - CFBundleIdentifier - net.gorhill.uBlock - CFBundleInfoDictionaryVersion - 6.0 - CFBundleShortVersionString - 0.7.0.10 - CFBundleVersion - 1456132 - Chrome - - Database Quota - 52428800 - Global Page - background.html - Popovers - - - Filename - popup.html - Height - 310 - Identifier - popover - Width - 180 - - - Toolbar Items - - - Identifier - toolbarItem - Image - img/icon16.png - Label - µBlock - Popover - popover - - - - Content - - Scripts - - End - - js/contentscript-end.js - - Start - - js/vapi-client.js - js/contentscript-start.js - - - Whitelist - - http://*/* - https://*/* - - - Description - Finally, an efficient blocker. Easy on CPU and memory. - ExtensionInfoDictionaryVersion - 1.0 - Permissions - - Website Access - - Include Secure Pages - - Level - All - - - - Website - https://github.com/gorhill/uBlock - - diff --git a/meta/safariextz/Settings.plist b/meta/safariextz/Settings.plist deleted file mode 100644 index 40cc1ff16..000000000 --- a/meta/safariextz/Settings.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - DefaultValue - - FalseValue - - Key - open_prefs - Secure - - Title - Click to see the Preferences - TrueValue - - Type - CheckBox - - - diff --git a/platform/safari/Info.plist b/platform/safari/Info.plist new file mode 100644 index 000000000..084209322 --- /dev/null +++ b/platform/safari/Info.plist @@ -0,0 +1,91 @@ + + + + + Author + Raymond Hill + Builder Version + 534.57.2 + CFBundleDisplayName + µBlock + CFBundleIdentifier + net.gorhill.uBlock + CFBundleInfoDictionaryVersion + 6.0 + CFBundleShortVersionString + 0.7.0.11 + CFBundleVersion + 1 + Chrome + + Database Quota + 52428800 + Global Page + background.html + Popovers + + + Filename + popup.html + Height + 310 + Identifier + popover + Width + 180 + + + Toolbar Items + + + Identifier + toolbarItem + Image + img/icon16.png + Label + µBlock + Popover + popover + + + + Content + + Scripts + + End + + js/contentscript-end.js + + Start + + js/vapi-client.js + js/contentscript-start.js + + + Whitelist + + http://*/* + https://*/* + + + Description + Finally, an efficient blocker. Easy on CPU and memory. + ExtensionInfoDictionaryVersion + 1.0 + Permissions + + Website Access + + Include Secure Pages + + Level + All + + + + Website + https://github.com/gorhill/uBlock + + diff --git a/platform/safari/Settings.plist b/platform/safari/Settings.plist new file mode 100644 index 000000000..6c80bbb43 --- /dev/null +++ b/platform/safari/Settings.plist @@ -0,0 +1,22 @@ + + + + + + DefaultValue + + FalseValue + + Key + open_prefs + Secure + + Title + Click to see the Preferences + TrueValue + + Type + CheckBox + + + diff --git a/meta/safariextz/sitepatch-safari.js b/platform/safari/sitepatch-safari.js similarity index 100% rename from meta/safariextz/sitepatch-safari.js rename to platform/safari/sitepatch-safari.js diff --git a/meta/safariextz/update_safariextz.plist b/platform/safari/update_safariextz.plist similarity index 90% rename from meta/safariextz/update_safariextz.plist rename to platform/safari/update_safariextz.plist index 0681b05e6..f82911e17 100644 --- a/meta/safariextz/update_safariextz.plist +++ b/platform/safari/update_safariextz.plist @@ -10,9 +10,9 @@ Developer Identifier CFBundleShortVersionString - 0.7.0.10 + 0.7.0.11 CFBundleVersion - 1456132 + 1 URL https://.../uBlock.safariextz diff --git a/meta/safariextz/vapi-background.js b/platform/safari/vapi-background.js similarity index 95% rename from meta/safariextz/vapi-background.js rename to platform/safari/vapi-background.js index d4a78d6bc..4976eb1df 100644 --- a/meta/safariextz/vapi-background.js +++ b/platform/safari/vapi-background.js @@ -132,6 +132,10 @@ vAPI.storage = { callback(); }, getBytesInUse: function(keys, callback) { + if (typeof callback !== 'function') { + return; + } + var key, size = 0; if (keys === null) { @@ -230,15 +234,16 @@ vAPI.tabs.get = function(tabId, callback) { title: tab.title }); }; -// properties of the details object: -// url: 'URL', // the address that will be opened -// tabId: 1, // the tab is used if set, instead of creating a new one -// index: -1, // undefined: end of the list, -1: following tab, or after index -// active: false, // opens the tab in background - true and undefined: foreground -// select: true // if a tab is already opened with that url, then select it instead of opening a new one /******************************************************************************/ +// properties of the details object: +// url: 'URL', // the address that will be opened +// tabId: 1, // the tab is used if set, instead of creating a new one +// index: -1, // undefined: end of the list, -1: following tab, or after index +// active: false, // opens the tab in background - true and undefined: foreground +// select: true // if a tab is already opened with that url, then select it instead of opening a new one + vAPI.tabs.open = function(details) { if (!details.url) { return null; @@ -293,13 +298,19 @@ vAPI.tabs.open = function(details) { /******************************************************************************/ -vAPI.tabs.close = function(tab) { - if (!(tab instanceof SafariBrowserTab)) { - tab = this.stack[tab]; +vAPI.tabs.close = function(tabIds) { + if (tabIds instanceof SafariBrowserTab) { + tabIds = this.getTabId(tabIds); } - if (tab) { - tab.close(); + if (!Array.isArray(tabIds)) { + tabIds = [tabIds]; + } + + for (var i = 0; i < tabIds.length; i++) { + if (this.stack[tabIds[i]]) { + this.stack[tabIds[i]].close(); + } } }; @@ -638,7 +649,11 @@ vAPI.net.registerListeners = function() { return e.message; }; - safari.application.addEventListener('message', this.onBeforeRequest.callback, true); + safari.application.addEventListener( + 'message', + this.onBeforeRequest.callback, + true + ); } }; diff --git a/meta/safariextz/vapi-client.js b/platform/safari/vapi-client.js similarity index 95% rename from meta/safariextz/vapi-client.js rename to platform/safari/vapi-client.js index 65e40029e..ca4e0b826 100644 --- a/meta/safariextz/vapi-client.js +++ b/platform/safari/vapi-client.js @@ -30,7 +30,7 @@ /******************************************************************************/ self.vAPI = self.vAPI || {}; -self.vAPI.safari = true; +vAPI.safari = true; /******************************************************************************/ @@ -39,11 +39,15 @@ var messagingConnector = function(response) { return; } + var channels = vAPI.messaging.channels; var channel, listener; if ( response.broadcast === true ) { - for ( channel in vAPI.messaging.channels ) { - listener = vAPI.messaging.channels[channel].listener; + for ( channel in channels ) { + if ( channels.hasOwnProperty(channel) === false ) { + continue; + } + listener = channels[channel].listener; if ( typeof listener === 'function' ) { listener(response.msg); } @@ -58,7 +62,7 @@ var messagingConnector = function(response) { } if ( !listener ) { - channel = vAPI.messaging.channels[response.portName]; + channel = channels[response.portName]; listener = channel && channel.listener; } @@ -171,9 +175,16 @@ vAPI.messaging = { /******************************************************************************/ -// content scripts are loaded into extension pages by default, but they shouldn't +vAPI.canExecuteContentScript = function() { + return /^https?:/.test(location.protocol); +}; -if (location.protocol === "safari-extension:") { +/******************************************************************************/ + +// This file can be included into extensin pages, +// but the following code should run only in content pages. + +if (location.protocol === 'safari-extension:') { return; } @@ -358,7 +369,7 @@ var onContextMenu = function(e) { details.editable = details.tagName === 'textarea' || details.tagName === 'input'; - if ('checked' in e.target) { + if (e.target.hasOwnProperty('checked')) { details.checked = e.target.checked; } @@ -366,7 +377,7 @@ var onContextMenu = function(e) { details.linkUrl = e.target.href; } - if ('src' in e.target) { + if (e.target.hasOwnProperty('src')) { details.srcUrl = e.target.src; if (details.tagName === 'img') { @@ -394,12 +405,6 @@ if (frameId === 0) { /******************************************************************************/ -self.vAPI.canExecuteContentScript = function() { - return /^https?:/.test(location.protocol); -}; - -/******************************************************************************/ - })(); /******************************************************************************/ diff --git a/meta/safariextz/vapi-common.js b/platform/safari/vapi-common.js similarity index 99% rename from meta/safariextz/vapi-common.js rename to platform/safari/vapi-common.js index 2021d7765..f7f1a6405 100644 --- a/meta/safariextz/vapi-common.js +++ b/platform/safari/vapi-common.js @@ -55,7 +55,6 @@ vAPI.download = function(details) { a.dispatchEvent(new MouseEvent('click')); return; } - var messager = vAPI.messaging.channel('_download'); messager.send({ what: 'gotoURL', diff --git a/tools/make-safari.sh b/tools/make-safari.sh index 6a5eb5226..5975ccbdb 100644 --- a/tools/make-safari.sh +++ b/tools/make-safari.sh @@ -16,7 +16,7 @@ cp -R src/_locales $DES/ cp src/*.html $DES/ cp src/img/icon_128.png $DES/Icon.png cp platform/vapi-appinfo.js $DES/js/ -cp meta/safariextz/*.js $DES/js/ -cp meta/safariextz/Info.plist $DES/ -cp meta/safariextz/Settings.plist $DES/ +cp platform/safariextz/*.js $DES/js/ +cp platform/safariextz/Info.plist $DES/ +cp platform/safariextz/Settings.plist $DES/ echo "*** uBlock.safariextension: Package done." From f3bb1013101d79684d38f434d54464980252b820 Mon Sep 17 00:00:00 2001 From: Deathamns Date: Mon, 1 Dec 2014 16:30:17 +0100 Subject: [PATCH 2/4] Safari: (semi)support vAPI.tabs.onUpdated() --- platform/safari/vapi-background.js | 18 ++++++---- platform/safari/vapi-client.js | 57 +++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/platform/safari/vapi-background.js b/platform/safari/vapi-background.js index 4976eb1df..620a878fc 100644 --- a/platform/safari/vapi-background.js +++ b/platform/safari/vapi-background.js @@ -187,12 +187,9 @@ vAPI.tabs.registerListeners = function() { safari.application.addEventListener('navigate', this.onNavigation, true); } - // ?? - /* if (typeof this.onUpdated === 'function') { } */ - // onClosed handled in the main tab-close event - // onPopup is handled in window.open on web-pages? - /* if (typeof onPopup === 'function') { } */ + // onUpdated handled via monitoring the history.pushState on web-pages + // onPopup is handled in window.open on web-pages }; /******************************************************************************/ @@ -603,8 +600,17 @@ vAPI.net.registerListeners = function() { return e.message; } + // when the URL changes, but the document doesn't + if (e.message.type === 'popstate') { + vAPI.tabs.onUpdated( + vAPI.tabs.getTabId(e.target), + {url: e.message.url}, + {url: e.message.url} + ); + return; + } // blocking unwanted pop-ups - if (e.message.type === 'popup') { + else if (e.message.type === 'popup') { if (typeof vAPI.tabs.onPopup === 'function') { e.message.type = 'main_frame'; e.message.sourceTabId = vAPI.tabs.getTabId(e.target); diff --git a/platform/safari/vapi-client.js b/platform/safari/vapi-client.js index ca4e0b826..e0af31ee6 100644 --- a/platform/safari/vapi-client.js +++ b/platform/safari/vapi-client.js @@ -330,28 +330,51 @@ var firstMutation = function() { // the extension context is unable to reach the page context, // also this only works when Content Security Policy allows inline scripts var tmpJS = document.createElement('script'); - var tmpScript = ["(function() {", - "var block = function(u, t) {", - "var e = document.createEvent('CustomEvent'),", - "d = {url: u, type: t};", - "e.initCustomEvent('" + randEventName + "', !1, !1, d);", - "dispatchEvent(e);", - "return d.url === !1;", - "}, wo = open, xo = XMLHttpRequest.prototype.open;", - "open = function(u) {", - "return block(u, 'popup') ? null : wo.apply(this, [].slice.call(arguments));", - "};", - "XMLHttpRequest.prototype.open = function(m, u, s) {", - "return xo.apply(this, block(u, 'xmlhttprequest') ? ['HEAD', u, s] : [].slice.call(arguments));", - "};" + var tmpScript = ['(function() {', + 'var block = function(u, t) {', + 'var e = document.createEvent("CustomEvent"),', + 'd = {url: u, type: t};', + 'e.initCustomEvent("' + randEventName + '", !1, !1, d);', + 'dispatchEvent(e);', + 'return d.url === !1;', + '}, wo = open, xo = XMLHttpRequest.prototype.open;', + 'open = function(u) {', + 'return block(u, "popup") ? null : wo.apply(this, arguments);', + '};', + 'XMLHttpRequest.prototype.open = function(m, u, s) {', + 'return xo.apply(this, block(u, "xmlhttprequest") ? ["HEAD", u, s] : arguments);', + '};' ]; - if (vAPI.sitePatch - && !safari.self.tab.canLoad(beforeLoadEvent, {isWhiteListed: location.href})) { + if (frameId === 0) { + tmpScript.push( + 'var pS = history.pushState, rS = history.replaceState,', + 'onpopstate = function(e) {', + 'if (!e || e.state !== null) block(location.href, "popstate");', + '};', + 'window.addEventListener("popstate", onpopstate, true);', + 'history.pushState = function() {', + 'var r = pS.apply(this, arguments);', + 'onpopstate();', + 'return r;', + '};', + 'history.replaceState = function() {', + 'var r = pR.apply(this, arguments);', + 'onpopstate();', + 'return r;', + '};' + ); + } + + var block = safari.self.tab.canLoad(beforeLoadEvent, { + isWhiteListed: location.href + }); + + if (vAPI.sitePatch && !block) { tmpScript.push('(' + vAPI.sitePatch + ')();'); } - tmpScript.push("})();"); + tmpScript.push('})();'); tmpJS.textContent = tmpScript.join(''); document.documentElement.removeChild(document.documentElement.appendChild(tmpJS)); }; From d93d70b4aea8a732dea1e95cdfaba1d19b55772e Mon Sep 17 00:00:00 2001 From: Deathamns Date: Mon, 1 Dec 2014 20:16:18 +0100 Subject: [PATCH 3/4] Safari: vAPI.tabs.close() to vAPI.tabs.remove() --- platform/safari/vapi-background.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/safari/vapi-background.js b/platform/safari/vapi-background.js index 620a878fc..ee37fe263 100644 --- a/platform/safari/vapi-background.js +++ b/platform/safari/vapi-background.js @@ -295,7 +295,7 @@ vAPI.tabs.open = function(details) { /******************************************************************************/ -vAPI.tabs.close = function(tabIds) { +vAPI.tabs.remove = function(tabIds) { if (tabIds instanceof SafariBrowserTab) { tabIds = this.getTabId(tabIds); } From 2a26448734a3f003629b32d43a9272c85784c4ea Mon Sep 17 00:00:00 2001 From: Deathamns Date: Mon, 1 Dec 2014 20:45:00 +0100 Subject: [PATCH 4/4] Safari: slightly better pop-up blocking --- .gitignore | 1 - platform/safari/Info.plist | 2 +- platform/safari/vapi-background.js | 51 +++++++++++++++++++++++------- platform/safari/vapi-client.js | 2 +- platform/vapi-appinfo.js | 43 ------------------------- src/js/tab.js | 9 ++---- tools/make-safari.sh | 7 ++-- 7 files changed, 48 insertions(+), 67 deletions(-) delete mode 100644 platform/vapi-appinfo.js diff --git a/.gitignore b/.gitignore index b5ba1f15a..d550bf20c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ *.bak *.pem -/meta/safariextz/certs/ /dist/build/ \ No newline at end of file diff --git a/platform/safari/Info.plist b/platform/safari/Info.plist index 084209322..dab006b6f 100644 --- a/platform/safari/Info.plist +++ b/platform/safari/Info.plist @@ -13,7 +13,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleShortVersionString - 0.7.0.11 + 0.7.2.0 CFBundleVersion 1 Chrome diff --git a/platform/safari/vapi-background.js b/platform/safari/vapi-background.js index ee37fe263..9a662f208 100644 --- a/platform/safari/vapi-background.js +++ b/platform/safari/vapi-background.js @@ -36,6 +36,13 @@ vAPI.safari = true; /******************************************************************************/ +vAPI.app = { + name: 'µBlock', + version: '0.7.2.0' +}; + +/******************************************************************************/ + // addContentScriptFromURL allows whitelisting, // so load sitepaching this way, instead of adding it to the Info.plist @@ -568,10 +575,32 @@ vAPI.messaging.broadcast = function(message) { /******************************************************************************/ -vAPI.net = {} +safari.application.addEventListener('beforeNavigate', function(e) { + if (!vAPI.tabs.expectPopUpFrom || e.url === 'about:blank') { + return; + } + + var details = { + url: e.url, + tabId: vAPI.tabs.getTabId(e.target), + sourceTabId: vAPI.tabs.expectPopUpFrom + }; + + vAPI.tabs.expectPopUpFrom = null; + + if (vAPI.tabs.onPopup(details)) { + e.preventDefault(); + + if (vAPI.tabs.stack[details.sourceTabId]) { + vAPI.tabs.stack[details.sourceTabId].activate(); + } + } +}, true); /******************************************************************************/ +vAPI.net = {} + vAPI.net.registerListeners = function() { var onBeforeRequest = this.onBeforeRequest; @@ -611,17 +640,17 @@ vAPI.net.registerListeners = function() { } // blocking unwanted pop-ups else if (e.message.type === 'popup') { - if (typeof vAPI.tabs.onPopup === 'function') { - e.message.type = 'main_frame'; - e.message.sourceTabId = vAPI.tabs.getTabId(e.target); - - if (vAPI.tabs.onPopup(e.message)) { - e.message = false; - return; - } + if (e.message.url === 'about:blank') { + vAPI.tabs.expectPopUpFrom = vAPI.tabs.getTabId(e.target); + e.message = true; + return; } - e.message = true; + e.message = !vAPI.tabs.onPopup({ + url: e.message.url, + tabId: 0, + sourceTabId: vAPI.tabs.getTabId(e.target) + }); return; } @@ -637,7 +666,7 @@ vAPI.net.registerListeners = function() { // truthy return value will allow the request, // except when redirectUrl is present if (block && typeof block === 'object') { - if (block.cancel) { + if (block.cancel === true) { e.message = false; } else if (e.message.type === 'script' diff --git a/platform/safari/vapi-client.js b/platform/safari/vapi-client.js index e0af31ee6..8bfbeb7e6 100644 --- a/platform/safari/vapi-client.js +++ b/platform/safari/vapi-client.js @@ -220,7 +220,7 @@ var onBeforeLoad = function(e, details) { linkHelper.href = details ? details.url : e.url; - if (!/^https?:/.test(linkHelper.protocol)) { + if (!(/^https?:/.test(linkHelper.protocol) || (details && details.type === 'popup'))) { return; } diff --git a/platform/vapi-appinfo.js b/platform/vapi-appinfo.js deleted file mode 100644 index b2b2cdcf0..000000000 --- a/platform/vapi-appinfo.js +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - - µBlock - a Chromium browser extension to block requests. - Copyright (C) 2014 The µBlock authors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see {http://www.gnu.org/licenses/}. - - Home: https://github.com/gorhill/uBlock -*/ - -// Can be included anywhere if it's needed - -/* global self */ - -/******************************************************************************/ - -(function(){ - -'use strict'; - -/******************************************************************************/ - -self.vAPI = self.vAPI || {}; - -self.vAPI.app = { - name: 'µBlock', - version: '0.7.2.0' -}; - -/******************************************************************************/ - -})(); \ No newline at end of file diff --git a/src/js/tab.js b/src/js/tab.js index 69dff3aa3..3b3a2f791 100644 --- a/src/js/tab.js +++ b/src/js/tab.js @@ -80,15 +80,12 @@ vAPI.tabs.onPopup = function(details) { // Blocked - // Safari blocks before the pop-up opens, so there is no window to remove. - // TODO: Can't this test be done within the platform-specific code? - if ( vAPI.safari ) { - return true; - } - // It is a popup, block and remove the tab. µBlock.unbindTabFromPageStats(details.tabId); vAPI.tabs.remove(details.tabId); + + // for Safari + return true; }; vAPI.tabs.registerListeners(); diff --git a/tools/make-safari.sh b/tools/make-safari.sh index 5975ccbdb..89f89942a 100644 --- a/tools/make-safari.sh +++ b/tools/make-safari.sh @@ -15,8 +15,7 @@ cp -R src/lib $DES/ cp -R src/_locales $DES/ cp src/*.html $DES/ cp src/img/icon_128.png $DES/Icon.png -cp platform/vapi-appinfo.js $DES/js/ -cp platform/safariextz/*.js $DES/js/ -cp platform/safariextz/Info.plist $DES/ -cp platform/safariextz/Settings.plist $DES/ +cp platform/safari/*.js $DES/js/ +cp platform/safari/Info.plist $DES/ +cp platform/safari/Settings.plist $DES/ echo "*** uBlock.safariextension: Package done."