diff options
author | Deathamns <deathamns@gmail.com> | 2014-12-01 16:23:19 +0100 |
---|---|---|
committer | Deathamns <deathamns@gmail.com> | 2014-12-01 20:47:23 +0100 |
commit | c0e11d81825e3a51faddad06076b5fcb3b1baf5c (patch) | |
tree | 3a4d4bdde1b437074c36cccdc0583d1c5f98d3e0 /meta | |
parent | 98464a56fe4fa2a28372018640d648a1f772ea36 (diff) | |
download | uBlock-c0e11d81825e3a51faddad06076b5fcb3b1baf5c.zip uBlock-c0e11d81825e3a51faddad06076b5fcb3b1baf5c.tar.gz uBlock-c0e11d81825e3a51faddad06076b5fcb3b1baf5c.tar.bz2 |
Safari: fix vAPI.tabs.close() + cleanup
Diffstat (limited to 'meta')
-rw-r--r-- | meta/safariextz/Info.plist | 91 | ||||
-rw-r--r-- | meta/safariextz/Settings.plist | 22 | ||||
-rw-r--r-- | meta/safariextz/sitepatch-safari.js | 81 | ||||
-rw-r--r-- | meta/safariextz/update_safariextz.plist | 21 | ||||
-rw-r--r-- | meta/safariextz/vapi-background.js | 753 | ||||
-rw-r--r-- | meta/safariextz/vapi-client.js | 405 | ||||
-rw-r--r-- | meta/safariextz/vapi-common.js | 156 |
7 files changed, 0 insertions, 1529 deletions
diff --git a/meta/safariextz/Info.plist b/meta/safariextz/Info.plist deleted file mode 100644 index 50134bc..0000000 --- a/meta/safariextz/Info.plist +++ /dev/null @@ -1,91 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>Author</key> - <string>Raymond Hill</string> - <key>Builder Version</key> - <string>534.57.2</string> - <key>CFBundleDisplayName</key> - <string>µBlock</string> - <key>CFBundleIdentifier</key> - <string>net.gorhill.uBlock</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleShortVersionString</key> - <string>0.7.0.10</string> - <key>CFBundleVersion</key> - <string>1456132</string> - <key>Chrome</key> - <dict> - <key>Database Quota</key> - <real>52428800</real> - <key>Global Page</key> - <string>background.html</string> - <key>Popovers</key> - <array> - <dict> - <key>Filename</key> - <string>popup.html</string> - <key>Height</key> - <real>310</real> - <key>Identifier</key> - <string>popover</string> - <key>Width</key> - <real>180</real> - </dict> - </array> - <key>Toolbar Items</key> - <array> - <dict> - <key>Identifier</key> - <string>toolbarItem</string> - <key>Image</key> - <string>img/icon16.png</string> - <key>Label</key> - <string>µBlock</string> - <key>Popover</key> - <string>popover</string> - </dict> - </array> - </dict> - <key>Content</key> - <dict> - <key>Scripts</key> - <dict> - <key>End</key> - <array> - <string>js/contentscript-end.js</string> - </array> - <key>Start</key> - <array> - <string>js/vapi-client.js</string> - <string>js/contentscript-start.js</string> - </array> - </dict> - <key>Whitelist</key> - <array> - <string>http://*/*</string> - <string>https://*/*</string> - </array> - </dict> - <key>Description</key> - <string>Finally, an efficient blocker. Easy on CPU and memory.</string> - <key>ExtensionInfoDictionaryVersion</key> - <string>1.0</string> - <key>Permissions</key> - <dict> - <key>Website Access</key> - <dict> - <key>Include Secure Pages</key> - <true/> - <key>Level</key> - <string>All</string> - </dict> - </dict> - <!-- <key>Update Manifest URL</key> - <string>https://github.com/gorhill/uBlockupdate_safariextz.plist</string> --> - <key>Website</key> - <string>https://github.com/gorhill/uBlock</string> -</dict> -</plist> diff --git a/meta/safariextz/Settings.plist b/meta/safariextz/Settings.plist deleted file mode 100644 index 40cc1ff..0000000 --- a/meta/safariextz/Settings.plist +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<array> - <dict> - <key>DefaultValue</key> - <false/> - <key>FalseValue</key> - <false/> - <key>Key</key> - <string>open_prefs</string> - <key>Secure</key> - <false/> - <key>Title</key> - <string>Click to see the Preferences</string> - <key>TrueValue</key> - <true/> - <key>Type</key> - <string>CheckBox</string> - </dict> -</array> -</plist> diff --git a/meta/safariextz/sitepatch-safari.js b/meta/safariextz/sitepatch-safari.js deleted file mode 100644 index b99a28e..0000000 --- a/meta/safariextz/sitepatch-safari.js +++ /dev/null @@ -1,81 +0,0 @@ -// Adding new URL requires to whitelist it in the background script too (addContentScriptFromURL) -// Note that the sitePach function will be converted to a string, and injected -// into the web-page in order to run in that scope. Because of this, variables -// from the extension scope won't be accessible in the sitePatch function. -'use strict'; - -self.vAPI = self.vAPI || {}; - -if (/^www\.youtube(-nocookie)?\.com/.test(location.host)) { - vAPI.sitePatch = function() { - // disable spf - window.ytspf = {}; - Object.defineProperty(ytspf, 'enabled', {'value': false}); - - // based on ExtendTube's ad removing solution - var p, yt = {}, config_ = {}, ytplayer = {}, playerConfig = { args: {} }; - - Object.defineProperties(yt, { - 'playerConfig': { - get: function() { return playerConfig; }, - set: function(data) { - if (data && typeof data === 'object' - && data.args && typeof data.args === 'object') { - var nope = /ad\d?_|afv|watermark|adsense|xfp/; - - for (var prop in data.args) { - if (nope.test(prop) && !/policy/.test(prop)) { - delete data.args[prop]; - } - } - } - - playerConfig = data; - - var playerRoot = document.querySelector('[data-swf-config]'); - if (playerRoot) - playerRoot.dataset.swfConfig = JSON.stringify(yt.playerConfig); - } - }, - 'config_': { - get: function() { return config_; }, - set: function(value) { config_ = value; } - } - }); - - Object.defineProperty(config_, 'PLAYER_CONFIG', { - get: function() { return yt.playerConfig; }, - set: function(value) { yt.playerConfig = value; } - }); - - Object.defineProperty(ytplayer, 'config', { - get: function() { return playerConfig; }, - set: function(value) { yt.playerConfig = value; } - }); - - if (window.yt) { - for (p in window.yt) { yt[p] = window.yt[p]; } - window.yt = yt; - } - else { - Object.defineProperty(window, 'yt', { - get: function() { return yt; }, - set: function() {} - }); - } - - if (window.ytplayer) { - for (p in window.ytplayer) { ytplayer[p] = window.ytplayer[p]; } - window.ytplayer = ytplayer; - } - else { - Object.defineProperty(window, 'ytplayer', { - get: function() { return ytplayer; }, - set: function() {} - }); - } - }; -} -/*else if (check url) { - vAPI.sitePatch do something -}*/ diff --git a/meta/safariextz/update_safariextz.plist b/meta/safariextz/update_safariextz.plist deleted file mode 100644 index 0681b05..0000000 --- a/meta/safariextz/update_safariextz.plist +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> - <dict> - <key>Extension Updates</key> - <array> - <dict> - <key>CFBundleIdentifier</key> - <string>net.gorhill.uBlock</string> - <key>Developer Identifier</key> - <string></string> - <key>CFBundleShortVersionString</key> - <string>0.7.0.10</string> - <key>CFBundleVersion</key> - <string>1456132</string> - <key>URL</key> - <string>https://.../uBlock.safariextz</string> - </dict> - </array> - </dict> -</plist> diff --git a/meta/safariextz/vapi-background.js b/meta/safariextz/vapi-background.js deleted file mode 100644 index d4a78d6..0000000 --- a/meta/safariextz/vapi-background.js +++ /dev/null @@ -1,753 +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 -*/ - -/* global µBlock, SafariBrowserTab */ -// For background page - -/******************************************************************************/ - -(function() { - -'use strict'; - -/******************************************************************************/ - -self.vAPI = self.vAPI || {}; - -vAPI.safari = true; - -/******************************************************************************/ - -// addContentScriptFromURL allows whitelisting, -// so load sitepaching this way, instead of adding it to the Info.plist - -safari.extension.addContentScriptFromURL( - safari.extension.baseURI + 'js/sitepatch-safari.js', - [ - 'http://www.youtube.com/*', - 'https://www.youtube.com/*', - 'http://www.youtube-nocookie.com/*', - 'https://www.youtube-nocookie.com/*' - ] -); - -/******************************************************************************/ - -safari.extension.settings.addEventListener('change', function(e) { - if (e.key === 'open_prefs') { - vAPI.tabs.open({url: 'dashboard.html', active: true}); - } -}, false); - -/******************************************************************************/ - -vAPI.storage = { - _storage: safari.extension.settings, - QUOTA_BYTES: 52428800, // copied from Info.plist - get: function(keys, callback) { - if (typeof callback !== 'function') { - return; - } - - var i, value, result = {}; - - if (keys === null) { - for (i in this._storage) { - value = this._storage[i]; - - if (typeof value === 'string') { - result[i] = JSON.parse(value); - } - } - } - else if (typeof keys === 'string') { - value = this._storage[keys]; - - if (typeof value === 'string') { - result[keys] = JSON.parse(value); - } - } - else if (Array.isArray(keys)) { - for ( i = 0; i < keys.length; ++i) { - value = this._storage[i]; - - if (typeof value === 'string') { - result[keys[i]] = JSON.parse(value); - } - } - } - else if (typeof keys === 'object') { - for (i in keys) { - value = this._storage[i]; - - if (typeof value === 'string') { - result[i] = JSON.parse(value); - } - else { - result[i] = keys[i]; - } - } - } - - callback(result); - }, - set: function(details, callback) { - for (var key in details) { - this._storage.setItem(key, JSON.stringify(details[key])); - } - - if (typeof callback === 'function') { - callback(); - } - }, - remove: function(keys) { - if (typeof keys === 'string') { - keys = [keys]; - } - - for (var i = 0; i < keys.length; ++i) { - this._storage.removeItem(keys[i]); - } - }, - clear: function(callback) { - this._storage.clear(); - callback(); - }, - getBytesInUse: function(keys, callback) { - var key, size = 0; - - if (keys === null) { - for (key in this._storage) { - size += (this._storage[key] || '').length; - } - } - else { - if (typeof keys === 'string') { - keys = [keys]; - } - - for (key = 0; key < keys.length; ++key) { - size += (this._storage[keys[key]] || '').length; - } - } - - callback(size); - } -}; - -/******************************************************************************/ - -vAPI.tabs = { - stack: {}, - stackID: 1 -}; - -/******************************************************************************/ - -vAPI.tabs.registerListeners = function() { - var onNavigation = this.onNavigation; - - if (typeof onNavigation === 'function') { - this.onNavigation = function(e) { - // e.url is not present for local files or data URIs, - // or probably for those URLs which we don't have access to - if (!e.target || !e.target.url) { - return; - } - - onNavigation({ - frameId: 0, - tabId: vAPI.tabs.getTabId(e.target), - url: e.target.url - }); - }; - - 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') { } */ -}; - -/******************************************************************************/ - -vAPI.tabs.getTabId = function(tab) { - for (var i in vAPI.tabs.stack) { - if (vAPI.tabs.stack[i] === tab) { - return +i; - } - } - - return -1; -}; - -/******************************************************************************/ - -vAPI.tabs.get = function(tabId, callback) { - var tab; - - if (tabId === null) { - tab = safari.application.activeBrowserWindow.activeTab; - tabId = this.getTabId(tab); - } - else { - tab = this.stack[tabId]; - } - - if (!tab) { - callback(); - return; - } - - callback({ - id: tabId, - index: tab.browserWindow.tabs.indexOf(tab), - windowId: safari.application.browserWindows.indexOf(tab.browserWindow), - active: tab === tab.browserWindow.activeTab, - url: tab.url, - 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 - -/******************************************************************************/ - -vAPI.tabs.open = function(details) { - if (!details.url) { - return null; - } - // extension pages - if (!/^[\w-]{2,}:/.test(details.url)) { - details.url = vAPI.getURL(details.url); - } - - var curWin, tab; - - if (details.select) { - tab = safari.application.browserWindows.some(function(win) { - var rgxHash = /#.*/; - // this is questionable - var url = details.url.replace(rgxHash, ''); - - for (var i = 0; i < win.tabs.length; ++i) { - if (win.tabs[i].url.replace(rgxHash, '') === url) { - win.tabs[i].activate(); - return true; - } - } - }); - - if (tab) { - return; - } - } - - if (details.active === undefined) { - details.active = true; - } - - curWin = safari.application.activeBrowserWindow; - - // it must be calculated before opening a new tab, - // otherwise the new tab will be the active tab here - if (details.index === -1) { - details.index = curWin.tabs.indexOf(curWin.activeTab) + 1; - } - - tab = details.tabId && this.stack[details.tabId] - || curWin.openTab(details.active ? 'foreground' : 'background'); - - if (details.index !== undefined) { - curWin.insertTab(tab, details.index); - } - - tab.url = details.url; -}; - -/******************************************************************************/ - -vAPI.tabs.close = function(tab) { - if (!(tab instanceof SafariBrowserTab)) { - tab = this.stack[tab]; - } - - if (tab) { - tab.close(); - } -}; - -/******************************************************************************/ - -vAPI.tabs.injectScript = function(tabId, details, callback) { - var tab; - - if (tabId) { - tab = this.stack[tabId]; - } - else { - tab = safari.application.activeBrowserWindow.activeTab; - } - - if (details.file) { - var xhr = new XMLHttpRequest; - xhr.overrideMimeType('application/x-javascript;charset=utf-8'); - xhr.open('GET', details.file, false); - xhr.send(); - details.code = xhr.responseText; - } - - tab.page.dispatchMessage('broadcast', { - portName: 'vAPI', - msg: { - cmd: 'runScript', - details: details - } - }); - - if (typeof callback === 'function') { - setTimeout(callback, 13); - } -}; - -/******************************************************************************/ - -// bind tabs to unique IDs - -(function() { - var wins = safari.application.browserWindows, i = wins.length, j; - var tabs = []; - - while (i--) { - j = wins[i].tabs.length; - - while (j--) { - tabs.push(wins[i].tabs[j]); - } - } - - return tabs; -})().forEach(function(tab) { - vAPI.tabs.stack[vAPI.tabs.stackID++] = tab; -}); - -/******************************************************************************/ - -safari.application.addEventListener('open', function(e) { - // ignore windows - if (e.target instanceof SafariBrowserTab) { - vAPI.tabs.stack[vAPI.tabs.stackID++] = e.target; - } -}, true); - -/******************************************************************************/ - -safari.application.addEventListener('close', function(e) { - // ignore windows - if (!(e.target instanceof SafariBrowserTab)) { - return; - } - - var tabId = vAPI.tabs.getTabId(e.target); - - if (tabId > -1) { - // to not add another listener, put this here - // instead of vAPI.tabs.registerListeners - if (typeof vAPI.tabs.onClosed === 'function') { - vAPI.tabs.onClosed(tabId); - } - - delete vAPI.tabIcons[tabId]; - delete vAPI.tabs.stack[tabId]; - } -}, true); - -/******************************************************************************/ - -// update badge when tab is activated -safari.application.addEventListener('activate', function(e) { - // hide popover, since in some cases won't close by itself - var items = safari.extension.toolbarItems; - - for (var i = 0; i < items.length; ++i) { - if (items[i].browserWindow === safari.application.activeBrowserWindow) { - if (items[i].popover) { - items[i].popover.hide(); - } - - break; - } - } - - // ignore windows - if (!(e.target instanceof SafariBrowserTab)) { - return; - } - - // update the badge, when tab is selected - vAPI.setIcon(); -}, true); - -/******************************************************************************/ - -// reload the popup when that is opened -safari.application.addEventListener('popover', function(e) { - e.target.contentWindow.document.body.textContent = ''; - e.target.contentWindow.location.reload(); -}, true); - -/******************************************************************************/ - -vAPI.tabIcons = { /*tabId: {badge: 0, img: dict}*/ }; -vAPI.setIcon = function(tabId, img, badge) { - var curTabId = vAPI.tabs.getTabId( - safari.application.activeBrowserWindow.activeTab - ); - - // from 'activate' event - if (tabId === undefined) { - tabId = curTabId; - } - else { - vAPI.tabIcons[tabId] = { - badge: badge || 0/*, - img: img*/ - }; - } - - if (tabId !== curTabId) { - return; - } - - // if the selected tab has the same ID, then update the badge too, - // or always update it when changing tabs ('activate' event) - var items = safari.extension.toolbarItems, i = items.length; - - while (i--) { - if (items[i].browserWindow === safari.application.activeBrowserWindow) { - if (vAPI.tabIcons[tabId]) { - items[i].badge = vAPI.tabIcons[tabId].badge; - // items[i].img = vAPI.tabIcons[tabId].img; - } - else { - items[i].badge = 0; - } - - return; - } - } -}; - -/******************************************************************************/ - -vAPI.messaging = { - listeners: {}, - defaultHandler: null, - NOOPFUNC: function(){}, - UNHANDLED: 'vAPI.messaging.notHandled' -}; - -/******************************************************************************/ - -vAPI.messaging.listen = function(listenerName, callback) { - this.listeners[listenerName] = callback; -}; - -/******************************************************************************/ - -vAPI.messaging.onMessage = function(request) { - var callback = vAPI.messaging.NOOPFUNC; - if ( request.message.requestId !== undefined ) { - callback = function(response) { - request.target.page.dispatchMessage( - request.name, - { - requestId: request.message.requestId, - portName: request.message.portName, - msg: response !== undefined ? response : null - } - ); - }; - } - - var sender = { - tab: { - id: vAPI.tabs.getTabId(request.target) - } - }; - - // Specific handler - var r = vAPI.messaging.UNHANDLED; - var listener = vAPI.messaging.listeners[request.message.portName]; - if ( typeof listener === 'function' ) { - r = listener(request.message.msg, sender, callback); - } - if ( r !== vAPI.messaging.UNHANDLED ) { - return; - } - - // Default handler - r = vAPI.messaging.defaultHandler(request.message.msg, sender, callback); - if ( r !== vAPI.messaging.UNHANDLED ) { - return; - } - - console.error('µBlock> messaging > unknown request: %o', request.message); - - // Unhandled: - // Need to callback anyways in case caller expected an answer, or - // else there is a memory leak on caller's side - callback(); -}; - -/******************************************************************************/ - -vAPI.messaging.setup = function(defaultHandler) { - // Already setup? - if ( this.defaultHandler !== null ) { - return; - } - - if ( typeof defaultHandler !== 'function' ) { - defaultHandler = function(){ return vAPI.messaging.UNHANDLED; }; - } - this.defaultHandler = defaultHandler; - - // the third parameter must stay false (bubbling), so later - // onBeforeRequest will use true (capturing), where we can invoke - // stopPropagation() (this way this.onMessage won't be fired) - safari.application.addEventListener('message', this.onMessage, false); -}; - -/******************************************************************************/ - -vAPI.messaging.broadcast = function(message) { - message = { - broadcast: true, - msg: message - }; - - for (var tabId in vAPI.tabs.stack) { - vAPI.tabs.stack[tabId].page.dispatchMessage('broadcast', message); - } -}; - -/******************************************************************************/ - -vAPI.net = {} - -/******************************************************************************/ - -vAPI.net.registerListeners = function() { - var onBeforeRequest = this.onBeforeRequest; - - if (typeof onBeforeRequest.callback === 'function') { - if (!Array.isArray(onBeforeRequest.types)) { - onBeforeRequest.types = []; - } - - onBeforeRequest = onBeforeRequest.callback; - this.onBeforeRequest.callback = function(e) { - var block; - - if (e.name !== 'canLoad') { - return; - } - - // no stopPropagation if it was called from beforeNavigate event - if (e.stopPropagation) { - e.stopPropagation(); - } - - if (e.message.isWhiteListed) { - block = µBlock.URI.hostnameFromURI(e.message.isWhiteListed); - block = µBlock.URI.domainFromHostname(block) || block; - e.message = !!µBlock.netWhitelist[block]; - return e.message; - } - - // blocking unwanted pop-ups - 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; - } - } - - e.message = true; - return; - } - - block = vAPI.net.onBeforeRequest; - - if (block.types.indexOf(e.message.type) < 0) { - return true; - } - - e.message.tabId = vAPI.tabs.getTabId(e.target); - block = onBeforeRequest(e.message); - - // truthy return value will allow the request, - // except when redirectUrl is present - if (block && typeof block === 'object') { - if (block.cancel) { - e.message = false; - } - else if (e.message.type === 'script' - && typeof block.redirectUrl === "string") { - e.message = block.redirectUrl; - } - else { - e.message = true; - } - } - else { - e.message = true; - } - - return e.message; - }; - - safari.application.addEventListener('message', this.onBeforeRequest.callback, true); - } -}; - -/******************************************************************************/ - -vAPI.contextMenu = {}; - -/******************************************************************************/ - -vAPI.contextMenu.create = function(details, callback) { - var contexts = details.contexts; - var menuItemId = details.id; - var menuTitle = details.title; - - if (Array.isArray(contexts) && contexts.length) { - contexts = contexts.indexOf('all') === -1 ? contexts : null; - } - else { - // default in Chrome - contexts = ['page']; - } - - this.onContextMenu = function(e) { - var uI = e.userInfo; - - if (uI && /^https?:\/\//i.test(uI.pageUrl)) { - if (contexts) { - var invalidContext = true; - - for (var i = 0; i < contexts.length; ++i) { - if (contexts[i] === 'frame') { - if (uI.insideFrame) { - invalidContext = false; - break; - } - } - else if (contexts[i] === 'link') { - if (uI.linkHref) { - invalidContext = false; - break; - } - } - else if (contexts[i] === 'image') { - if (uI.srcUrl) { - invalidContext = false; - break; - } - } - else if (contexts[i] === 'audio' - || contexts[i] === 'video') { - if (uI.srcUrl && uI.tagName === contexts[i]) { - invalidContext = false; - break; - } - } - else if (contexts[i] === 'editable') { - if (uI.editable) { - invalidContext = false; - break; - } - } - else if (contexts[i] === 'page') { - if (!(uI.insideFrame || uI.linkHref - || uI.mediaType || uI.editable)) { - invalidContext = false; - break; - } - } - } - - if (invalidContext) { - return; - } - } - - e.contextMenu.appendContextMenuItem(menuItemId, menuTitle); - } - }; - - this.onContextMenuCmd = function(e) { - if (e.command === menuItemId) { - var tab = e.currentTarget.activeBrowserWindow.activeTab; - e.userInfo.menuItemId = menuItemId; - callback(e.userInfo, tab ? { - id: vAPI.tabs.getTabId(tab), - url: tab.url - } : undefined); - } - }; - - safari.application.addEventListener('contextmenu', this.onContextMenu); - safari.application.addEventListener("command", this.onContextMenuCmd); -}; - -/******************************************************************************/ - -vAPI.contextMenu.remove = function() { - safari.application.removeEventListener('contextmenu', this.onContextMenu); - safari.application.removeEventListener("command", this.onContextMenuCmd); - this.onContextMenu = null; - this.onContextMenuCmd = null; -}; - -/******************************************************************************/ - -vAPI.lastError = function() { - return null; -}; - -/******************************************************************************/ - -})(); diff --git a/meta/safariextz/vapi-client.js b/meta/safariextz/vapi-client.js deleted file mode 100644 index 65e4002..0000000 --- a/meta/safariextz/vapi-client.js +++ /dev/null @@ -1,405 +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 -*/ - -// For non background pages - -/******************************************************************************/ - -(function() { - -'use strict'; - -/******************************************************************************/ - -self.vAPI = self.vAPI || {}; -self.vAPI.safari = true; - -/******************************************************************************/ - -var messagingConnector = function(response) { - if ( !response ) { - return; - } - - var channel, listener; - - if ( response.broadcast === true ) { - for ( channel in vAPI.messaging.channels ) { - listener = vAPI.messaging.channels[channel].listener; - if ( typeof listener === 'function' ) { - listener(response.msg); - } - } - return; - } - - if ( response.requestId ) { - listener = vAPI.messaging.listeners[response.requestId]; - delete vAPI.messaging.listeners[response.requestId]; - delete response.requestId; - } - - if ( !listener ) { - channel = vAPI.messaging.channels[response.portName]; - listener = channel && channel.listener; - } - - if ( typeof listener === 'function' ) { - listener(response.msg); - } -}; - -/******************************************************************************/ - -var uniqueId = function() { - return parseInt(Math.random() * 1e10, 10).toString(36); -}; - -/******************************************************************************/ - -// relevant? -// https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/MessagesandProxies/MessagesandProxies.html#//apple_ref/doc/uid/TP40009977-CH14-SW12 -vAPI.messaging = { - channels: {}, - listeners: {}, - requestId: 1, - connectorId: uniqueId(), - - setup: function() { - this.connector = function(msg) { - // messages from the background script are sent to every frame, - // so we need to check the connectorId to accept only - // what is meant for the current context - if (msg.name === vAPI.messaging.connectorId - || msg.name === 'broadcast') { - messagingConnector(msg.message); - } - }; - safari.self.addEventListener('message', this.connector, false); - - this.channels['vAPI'] = { - listener: function(msg) { - if (msg.cmd === 'runScript' && msg.details.code) { - Function(msg.details.code).call(self); - } - } - }; - }, - close: function() { - if (this.connector) { - safari.self.removeEventListener('message', this.connector, false); - this.connector = null; - this.channels = {}; - this.listeners = {}; - } - }, - channel: function(channelName, callback) { - if ( !channelName ) { - return; - } - - this.channels[channelName] = { - portName: channelName, - listener: typeof callback === 'function' ? callback : null, - send: function(message, callback) { - if (!vAPI.messaging.connector) { - vAPI.messaging.setup(); - } - - message = { - portName: this.portName, - msg: message - }; - - if ( callback ) { - message.requestId = vAPI.messaging.requestId++; - vAPI.messaging.listeners[message.requestId] = callback; - } - - // popover content doesn't know messaging... - if (safari.extension.globalPage) { - if (!safari.self.visible) { - return; - } - - safari.extension.globalPage.contentWindow - .vAPI.messaging.onMessage({ - name: vAPI.messaging.connectorId, - message: message, - target: { - page: { - dispatchMessage: function(name, msg) { - messagingConnector(msg); - } - } - } - }); - } - else { - safari.self.tab.dispatchMessage( - vAPI.messaging.connectorId, - message - ); - } - }, - close: function() { - delete vAPI.messaging.channels[this.portName]; - } - }; - - return this.channels[channelName]; - } -}; - -/******************************************************************************/ - -// content scripts are loaded into extension pages by default, but they shouldn't - -if (location.protocol === "safari-extension:") { - return; -} - -/******************************************************************************/ - -window.MutationObserver = window.MutationObserver || window.WebKitMutationObserver; - -if (!window.MutationObserver) { - // dummy, minimalistic shim for older versions (<6) - // only supports node insertions, but currently we don't use it for anything else - window.MutationObserver = function(handler) { - this.observe = function(target) { - target.addEventListener('DOMNodeInserted', function(e) { - handler([{addedNodes: [e.target]}]); - }, true); - }; - }; -} - -/******************************************************************************/ - -var beforeLoadEvent = document.createEvent('Event'); -beforeLoadEvent.initEvent('beforeload'); - -/******************************************************************************/ - -var frameId = window === window.top ? 0 : Date.now() % 1E5; -var linkHelper = document.createElement('a'); -var onBeforeLoad = function(e, details) { - if (e.url && e.url.slice(0, 5) === 'data:') { - return; - } - - linkHelper.href = details ? details.url : e.url; - - if (!/^https?:/.test(linkHelper.protocol)) { - return; - } - - if (details) { - details.url = linkHelper.href; - } - else { - details = { - url: linkHelper.href - }; - - switch (e.target.nodeName.toLowerCase()) { - case 'frame': - case 'iframe': - details.type = 'sub_frame'; - break; - case 'script': - details.type = 'script'; - break; - case 'img': - case 'input': // type=image - details.type = 'image'; - break; - case 'object': - case 'embed': - details.type = 'object'; - break; - case 'link': - var rel = e.target.rel.trim().toLowerCase(); - - if (rel.indexOf('icon') > -1) { - details.type = 'image'; - break; - } - else if (rel === 'stylesheet') { - details.type = 'stylesheet'; - break; - } - default: - details.type = 'other'; - } - - // This can run even before the first DOMSubtreeModified event fired - if (firstMutation) { - firstMutation(); - } - } - - // tabId is determined in the background script - // details.tabId = null; - details.frameId = frameId; - details.parentFrameId = frameId ? 0 : -1; - details.timeStamp = Date.now(); - - var response = safari.self.tab.canLoad(e, details); - - if (!response) { - if (details.type === 'main_frame') { - window.stop(); - } - else { - e.preventDefault(); - } - - return false; - } - // local mirroring, response is a data: URL here - else if (typeof response === 'string' && details.type === 'script') { - // Content Security Policy with disallowed inline scripts may break things - e.preventDefault(); - details = document.createElement('script'); - details.textContent = atob(response.slice(response.indexOf(',', 20) + 1)); - - if (e.target.hasAttribute('defer') && document.readyState === 'loading') { - var jsOnLoad = function(ev) { - this.removeEventListener(ev.type, jsOnLoad, true); - this.body.removeChild(this.body.appendChild(details)); - }; - - document.addEventListener('DOMContentLoaded', jsOnLoad, true); - } - else { - e.target.parentNode.insertBefore(details, e.target); - details.parentNode.removeChild(details); - } - } -}; - -document.addEventListener('beforeload', onBeforeLoad, true); - -/******************************************************************************/ - -// block pop-ups, intercept xhr requests, and apply site patches -var firstMutation = function() { - document.removeEventListener('DOMSubtreeModified', firstMutation, true); - firstMutation = null; - var randEventName = parseInt(Math.random() * 1e15, 10).toString(36); - - window.addEventListener(randEventName, function(e) { - var result = onBeforeLoad(beforeLoadEvent, e.detail); - - if (result === false) { - e.detail.url = false; - } - }, true); - - // 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));", - "};" - ]; - - if (vAPI.sitePatch - && !safari.self.tab.canLoad(beforeLoadEvent, {isWhiteListed: location.href})) { - tmpScript.push('(' + vAPI.sitePatch + ')();'); - } - - tmpScript.push("})();"); - tmpJS.textContent = tmpScript.join(''); - document.documentElement.removeChild(document.documentElement.appendChild(tmpJS)); -}; - -document.addEventListener('DOMSubtreeModified', firstMutation, true); - -/******************************************************************************/ - -var onContextMenu = function(e) { - var details = { - tagName: e.target.tagName.toLowerCase(), - pageUrl: location.href, - insideFrame: window !== window.top - }; - - details.editable = details.tagName === 'textarea' || details.tagName === 'input'; - - if ('checked' in e.target) { - details.checked = e.target.checked; - } - - if (details.tagName === 'a') { - details.linkUrl = e.target.href; - } - - if ('src' in e.target) { - details.srcUrl = e.target.src; - - if (details.tagName === 'img') { - details.mediaType = 'image'; - } - else if (details.tagName === 'video' || details.tagName === 'audio') { - details.mediaType = details.tagName; - } - } - - safari.self.tab.setContextMenuEventUserInfo(e, details); -}; - -self.addEventListener('contextmenu', onContextMenu, true); - -/******************************************************************************/ - -// 'main_frame' simulation -if (frameId === 0) { - onBeforeLoad(beforeLoadEvent, { - url: location.href, - type: 'main_frame' - }); -} - -/******************************************************************************/ - -self.vAPI.canExecuteContentScript = function() { - return /^https?:/.test(location.protocol); -}; - -/******************************************************************************/ - -})(); - -/******************************************************************************/ diff --git a/meta/safariextz/vapi-common.js b/meta/safariextz/vapi-common.js deleted file mode 100644 index 2021d77..0000000 --- a/meta/safariextz/vapi-common.js +++ /dev/null @@ -1,156 +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 -*/ - -// For background page or non-background pages - -/******************************************************************************/ - -(function() { - -'use strict'; - -self.vAPI = self.vAPI || {}; - -/******************************************************************************/ - -// http://www.w3.org/International/questions/qa-scripts#directions - -var setScriptDirection = function(language) { - document.body.setAttribute( - 'dir', - ~['ar', 'he', 'fa', 'ps', 'ur'].indexOf(language) ? 'rtl' : 'ltr' - ); -}; - -/******************************************************************************/ - -vAPI.download = function(details) { - if ( !details.url ) { - return; - } - - var a = document.createElement('a'); - - if ( 'download' in a ) { - a.href = details.url; - a.setAttribute('download', details.filename || ''); - a.dispatchEvent(new MouseEvent('click')); - return; - } - - var messager = vAPI.messaging.channel('_download'); - messager.send({ - what: 'gotoURL', - details: { - url: details.url, - index: -1 - } - }); - messager.close(); -}; - -/******************************************************************************/ - -vAPI.getURL = function(path) { - return safari.extension.baseURI + path; -}; - -/******************************************************************************/ - -// supported languages -// first language is the default -vAPI.i18nData = [ - "en", "ar", "cs", "da", "de", "el", "es", "et", "fi", "fr", "he", "hi", - "hr", "hu", "id", "it", "ja", "mr", "nb", "nl", "pl", "pt_BR", "pt_PT", - "ro", "ru", "sv", "tr", "uk", "vi", "zh_CN" -]; - -vAPI.i18n = navigator.language.replace('-', '_'); - -if (vAPI.i18nData.indexOf(vAPI.i18n) === -1) { - vAPI.i18n = vAPI.i18n.slice(0, 2); - - if (vAPI.i18nData.indexOf(vAPI.i18n) === -1) { - vAPI.i18n = vAPI.i18nData[0]; - } -} - -setScriptDirection(vAPI.i18n); - -var xhr = new XMLHttpRequest; -xhr.overrideMimeType('application/json;charset=utf-8'); -xhr.open('GET', './_locales/' + vAPI.i18n + '/messages.json', false); -xhr.send(); -vAPI.i18nData = JSON.parse(xhr.responseText); - -for (var i18nKey in vAPI.i18nData) { - vAPI.i18nData[i18nKey] = vAPI.i18nData[i18nKey].message; -} - -vAPI.i18n = function(s) { - return this.i18nData[s] || s; -}; - -/******************************************************************************/ - -// update popover size to its content -if (safari.self.identifier === 'popover') { - var onLoaded = function() { - // Initial dimensions are set in Info.plist - var pWidth = safari.self.width; - var pHeight = safari.self.height; - var upadteTimer = null; - var resizePopover = function() { - if (upadteTimer) { - return; - } - - upadteTimer = setTimeout(function() { - safari.self.width = Math.max(pWidth, document.body.clientWidth); - safari.self.height = Math.max(pHeight, document.body.clientHeight); - upadteTimer = null; - }, 20); - }; - - var mutObs = window.MutationObserver || window.WebkitMutationObserver; - - if (mutObs) { - (new mutObs(resizePopover)).observe(document, { - childList: true, - attributes: true, - characterData: true, - subtree: true - }); - } - else { - // Safari doesn't support DOMAttrModified - document.addEventListener('DOMSubtreeModified', resizePopover); - } - }; - - window.addEventListener('load', onLoaded); -} - -/******************************************************************************/ - -})(); - -/******************************************************************************/ |