aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFESTO.md6
-rw-r--r--README.md44
-rwxr-xr-ximport-crowdin.sh67
-rw-r--r--js/messaging-client.js141
-rw-r--r--js/messaging.js252
-rwxr-xr-xmake-chrome.sh18
-rwxr-xr-xmake-noassets.sh15
-rw-r--r--meta/config.json31
-rw-r--r--meta/crx/manifest.json62
-rw-r--r--meta/crx/update_crx.xml6
-rw-r--r--meta/safariextz/Info.plist87
-rw-r--r--meta/safariextz/update_safariextz.plist21
-rw-r--r--src/1p-filters.html (renamed from 1p-filters.html)13
-rw-r--r--src/3p-filters.html (renamed from 3p-filters.html)17
-rw-r--r--src/Info.plist87
-rw-r--r--src/_locales/ar/messages.json (renamed from _locales/ar/messages.json)0
-rw-r--r--src/_locales/cs/messages.json (renamed from _locales/cs/messages.json)0
-rw-r--r--src/_locales/da/messages.json (renamed from _locales/da/messages.json)0
-rw-r--r--src/_locales/de/messages.json (renamed from _locales/de/messages.json)0
-rw-r--r--src/_locales/el/messages.json (renamed from _locales/el/messages.json)0
-rw-r--r--src/_locales/en/messages.json (renamed from _locales/en/messages.json)0
-rw-r--r--src/_locales/es/messages.json (renamed from _locales/es/messages.json)0
-rw-r--r--src/_locales/et/messages.json (renamed from _locales/et/messages.json)0
-rw-r--r--src/_locales/fi/messages.json (renamed from _locales/fi/messages.json)0
-rw-r--r--src/_locales/fr/messages.json (renamed from _locales/fr/messages.json)0
-rw-r--r--src/_locales/he/messages.json (renamed from _locales/he/messages.json)0
-rw-r--r--src/_locales/hi/messages.json (renamed from _locales/hi/messages.json)0
-rw-r--r--src/_locales/hr/messages.json (renamed from _locales/hr/messages.json)0
-rw-r--r--src/_locales/hu/messages.json (renamed from _locales/hu/messages.json)0
-rw-r--r--src/_locales/id/messages.json (renamed from _locales/id/messages.json)0
-rw-r--r--src/_locales/it/messages.json (renamed from _locales/it/messages.json)0
-rw-r--r--src/_locales/ja/messages.json (renamed from _locales/ja/messages.json)0
-rw-r--r--src/_locales/mr/messages.json (renamed from _locales/mr/messages.json)0
-rw-r--r--src/_locales/nb/messages.json (renamed from _locales/nb/messages.json)0
-rw-r--r--src/_locales/nl/messages.json (renamed from _locales/nl/messages.json)0
-rw-r--r--src/_locales/pl/messages.json (renamed from _locales/pl/messages.json)0
-rw-r--r--src/_locales/pt_BR/messages.json (renamed from _locales/pt_BR/messages.json)0
-rw-r--r--src/_locales/pt_PT/messages.json (renamed from _locales/pt_PT/messages.json)0
-rw-r--r--src/_locales/ro/messages.json (renamed from _locales/ro/messages.json)0
-rw-r--r--src/_locales/ru/messages.json (renamed from _locales/ru/messages.json)0
-rw-r--r--src/_locales/sv/messages.json (renamed from _locales/sv/messages.json)0
-rw-r--r--src/_locales/tr/messages.json (renamed from _locales/tr/messages.json)0
-rw-r--r--src/_locales/uk/messages.json (renamed from _locales/uk/messages.json)0
-rw-r--r--src/_locales/vi/messages.json (renamed from _locales/vi/messages.json)0
-rw-r--r--src/_locales/zh_CN/messages.json (renamed from _locales/zh_CN/messages.json)0
-rw-r--r--src/about.html (renamed from about.html)15
-rw-r--r--src/asset-viewer.html (renamed from asset-viewer.html)10
-rw-r--r--src/assets/checksums.txt (renamed from assets/checksums.txt)0
-rw-r--r--src/assets/thirdparties/abp.mozilla-hispano.org/nauscopio/filtros.txt (renamed from assets/thirdparties/abp.mozilla-hispano.org/nauscopio/filtros.txt)0
-rw-r--r--src/assets/thirdparties/adblock-chinalist.googlecode.com/svn/trunk/adblock.txt (renamed from assets/thirdparties/adblock-chinalist.googlecode.com/svn/trunk/adblock.txt)0
-rw-r--r--src/assets/thirdparties/adblock-czechoslovaklist.googlecode.com/svn/filters.txt (renamed from assets/thirdparties/adblock-czechoslovaklist.googlecode.com/svn/filters.txt)0
-rw-r--r--src/assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt (renamed from assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt)0
-rw-r--r--src/assets/thirdparties/adblock.gardar.net/is.abp.txt (renamed from assets/thirdparties/adblock.gardar.net/is.abp.txt)0
-rw-r--r--src/assets/thirdparties/adblock.schack.dk/block.txt (renamed from assets/thirdparties/adblock.schack.dk/block.txt)0
-rw-r--r--src/assets/thirdparties/cjxlist1.googlecode.com/svn/cjxlist.txt (renamed from assets/thirdparties/cjxlist1.googlecode.com/svn/cjxlist.txt)0
-rw-r--r--src/assets/thirdparties/dl.dropboxusercontent.com/u/1289327/abpxfiles/filtri.txt (renamed from assets/thirdparties/dl.dropboxusercontent.com/u/1289327/abpxfiles/filtri.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/advblock.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/advblock.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/bitblock.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/bitblock.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/easylist.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/easylist.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/easylist_noelemhide.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/easylist_noelemhide.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistchina.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/easylistchina.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistdutch.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/easylistdutch.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistgermany.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/easylistgermany.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistitaly.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/easylistitaly.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/easyprivacy.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/easyprivacy.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-annoyance.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-annoyance.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-social.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-social.txt)0
-rw-r--r--src/assets/thirdparties/easylist-downloads.adblockplus.org/liste_fr.txt (renamed from assets/thirdparties/easylist-downloads.adblockplus.org/liste_fr.txt)0
-rw-r--r--src/assets/thirdparties/gitorious.org/adblock-latvian/adblock-latvian/raw/master_lists/latvian-list.txt (renamed from assets/thirdparties/gitorious.org/adblock-latvian/adblock-latvian/raw/master_lists/latvian-list.txt)0
-rw-r--r--src/assets/thirdparties/home.fredfiber.no/langsholt/adblock.txt (renamed from assets/thirdparties/home.fredfiber.no/langsholt/adblock.txt)0
-rw-r--r--src/assets/thirdparties/hosts-file.net/ad-servers (renamed from assets/thirdparties/hosts-file.net/ad-servers)0
-rw-r--r--src/assets/thirdparties/indonesianadblockrules.googlecode.com/hg/subscriptions/abpindo.txt (renamed from assets/thirdparties/indonesianadblockrules.googlecode.com/hg/subscriptions/abpindo.txt)0
-rw-r--r--src/assets/thirdparties/liste-ar-adblock.googlecode.com/hg/Liste_AR.txt (renamed from assets/thirdparties/liste-ar-adblock.googlecode.com/hg/Liste_AR.txt)0
-rw-r--r--src/assets/thirdparties/margevicius.lt/easylistlithuania.txt (renamed from assets/thirdparties/margevicius.lt/easylistlithuania.txt)0
-rw-r--r--src/assets/thirdparties/mirror1.malwaredomains.com/files/README.md (renamed from assets/thirdparties/mirror1.malwaredomains.com/files/README.md)0
-rw-r--r--src/assets/thirdparties/mirror1.malwaredomains.com/files/immortal_domains.txt (renamed from assets/thirdparties/mirror1.malwaredomains.com/files/immortal_domains.txt)0
-rw-r--r--src/assets/thirdparties/mirror1.malwaredomains.com/files/justdomains (renamed from assets/thirdparties/mirror1.malwaredomains.com/files/justdomains)0
-rw-r--r--src/assets/thirdparties/pgl.yoyo.org/as/README.md (renamed from assets/thirdparties/pgl.yoyo.org/as/README.md)0
-rw-r--r--src/assets/thirdparties/pgl.yoyo.org/as/serverlist (renamed from assets/thirdparties/pgl.yoyo.org/as/serverlist)0
-rw-r--r--src/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat (renamed from assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat)0
-rw-r--r--src/assets/thirdparties/raw.githubusercontent.com/AdBlockPlusIsrael/EasyListHebrew/master/EasyListHebrew.txt (renamed from assets/thirdparties/raw.githubusercontent.com/AdBlockPlusIsrael/EasyListHebrew/master/EasyListHebrew.txt)0
-rw-r--r--src/assets/thirdparties/raw.githubusercontent.com/adblockpolska/Adblock_PL_List/master/adblock_polska.txt (renamed from assets/thirdparties/raw.githubusercontent.com/adblockpolska/Adblock_PL_List/master/adblock_polska.txt)0
-rw-r--r--src/assets/thirdparties/raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt (renamed from assets/thirdparties/raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt)0
-rw-r--r--src/assets/thirdparties/raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt (renamed from assets/thirdparties/raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt)0
-rw-r--r--src/assets/thirdparties/raw.githubusercontent.com/wiltteri/wiltteri.txt/master/wiltteri.txt (renamed from assets/thirdparties/raw.githubusercontent.com/wiltteri/wiltteri.txt/master/wiltteri.txt)0
-rw-r--r--src/assets/thirdparties/someonewhocares.org/hosts/hosts (renamed from assets/thirdparties/someonewhocares.org/hosts/hosts)0
-rw-r--r--src/assets/thirdparties/spam404bl.com/spam404scamlist.txt (renamed from assets/thirdparties/spam404bl.com/spam404scamlist.txt)0
-rw-r--r--src/assets/thirdparties/stanev.org/abp/adblock_bg.txt (renamed from assets/thirdparties/stanev.org/abp/adblock_bg.txt)0
-rw-r--r--src/assets/thirdparties/winhelp2002.mvps.org/hosts.txt (renamed from assets/thirdparties/winhelp2002.mvps.org/hosts.txt)0
-rw-r--r--src/assets/thirdparties/www.fanboy.co.nz/enhancedstats.txt (renamed from assets/thirdparties/www.fanboy.co.nz/enhancedstats.txt)0
-rw-r--r--src/assets/thirdparties/www.fanboy.co.nz/fanboy-antifacebook.txt (renamed from assets/thirdparties/www.fanboy.co.nz/fanboy-antifacebook.txt)0
-rw-r--r--src/assets/thirdparties/www.fanboy.co.nz/fanboy-swedish.txt (renamed from assets/thirdparties/www.fanboy.co.nz/fanboy-swedish.txt)0
-rw-r--r--src/assets/thirdparties/www.fanboy.co.nz/fanboy-ultimate.txt (renamed from assets/thirdparties/www.fanboy.co.nz/fanboy-ultimate.txt)0
-rw-r--r--src/assets/thirdparties/www.fanboy.co.nz/fanboy-vietnam.txt (renamed from assets/thirdparties/www.fanboy.co.nz/fanboy-vietnam.txt)0
-rw-r--r--src/assets/thirdparties/www.hufilter.hu/hufilter.txt (renamed from assets/thirdparties/www.hufilter.hu/hufilter.txt)0
-rw-r--r--src/assets/thirdparties/www.malwaredomainlist.com/hostslist/README.md (renamed from assets/thirdparties/www.malwaredomainlist.com/hostslist/README.md)0
-rw-r--r--src/assets/thirdparties/www.malwaredomainlist.com/hostslist/hosts.txt (renamed from assets/thirdparties/www.malwaredomainlist.com/hostslist/hosts.txt)0
-rw-r--r--src/assets/thirdparties/www.void.gr/kargig/void-gr-filters.txt (renamed from assets/thirdparties/www.void.gr/kargig/void-gr-filters.txt)0
-rw-r--r--src/assets/ublock/filter-lists.json (renamed from assets/ublock/filter-lists.json)0
-rw-r--r--src/assets/ublock/filters.txt (renamed from assets/ublock/filters.txt)0
-rw-r--r--src/assets/ublock/mirror-candidates.txt (renamed from assets/ublock/mirror-candidates.txt)0
-rw-r--r--src/assets/ublock/privacy.txt (renamed from assets/ublock/privacy.txt)0
-rw-r--r--[-rwxr-xr-x]src/assets/update-3rdparties.sh (renamed from assets/update-3rdparties.sh)0
-rw-r--r--[-rwxr-xr-x]src/assets/update-checksums.sh (renamed from assets/update-checksums.sh)0
-rw-r--r--[-rwxr-xr-x]src/assets/update-git.sh (renamed from assets/update-git.sh)0
-rw-r--r--src/background.html (renamed from background.html)3
-rw-r--r--src/css/1p-filters.css (renamed from css/1p-filters.css)0
-rw-r--r--src/css/3p-filters.css (renamed from css/3p-filters.css)0
-rw-r--r--src/css/about.css (renamed from css/about.css)0
-rw-r--r--src/css/common.css (renamed from css/common.css)4
-rw-r--r--src/css/dashboard-common.css (renamed from css/dashboard-common.css)3
-rw-r--r--src/css/fonts/OFL.txt (renamed from css/fonts/OFL.txt)0
-rw-r--r--src/css/fonts/fontawesome-webfont.ttf (renamed from css/fonts/fontawesome-webfont.ttf)bin112160 -> 112160 bytes
-rw-r--r--src/css/popup.css (renamed from css/popup.css)41
-rw-r--r--src/css/whitelist.css (renamed from css/whitelist.css)0
-rw-r--r--src/dashboard.html (renamed from dashboard.html)27
-rw-r--r--src/icon.png (renamed from img/icon_128.png)bin880 -> 880 bytes
-rw-r--r--src/img/browsericons/icon19-off.png (renamed from img/browsericons/icon19-off.png)bin273 -> 273 bytes
-rw-r--r--src/img/browsericons/icon19.png (renamed from img/browsericons/icon19.png)bin308 -> 308 bytes
-rw-r--r--src/img/browsericons/icon38-off.png (renamed from img/browsericons/icon38-off.png)bin421 -> 421 bytes
-rw-r--r--src/img/browsericons/icon38.png (renamed from img/browsericons/icon38.png)bin399 -> 399 bytes
-rw-r--r--src/img/help16.png (renamed from img/help16.png)bin371 -> 371 bytes
-rw-r--r--src/img/icon_128.pngbin0 -> 880 bytes
-rw-r--r--src/img/icon_16.png (renamed from img/icon_16.png)bin275 -> 275 bytes
-rw-r--r--src/img/ublock.svg (renamed from img/ublock.svg)0
-rw-r--r--src/js/1p-filters.js (renamed from js/1p-filters.js)10
-rw-r--r--src/js/3p-filters.js (renamed from js/3p-filters.js)58
-rw-r--r--src/js/about.js (renamed from js/about.js)19
-rw-r--r--src/js/asset-viewer.js (renamed from js/asset-viewer.js)6
-rw-r--r--src/js/assets.js (renamed from js/assets.js)46
-rw-r--r--src/js/async.js (renamed from js/async.js)4
-rw-r--r--src/js/background.js (renamed from js/background.js)5
-rw-r--r--src/js/contentscript-end.js (renamed from js/contentscript-end.js)148
-rw-r--r--src/js/contentscript-start.js (renamed from js/contentscript-start.js)111
-rw-r--r--src/js/contextmenu.js (renamed from js/contextmenu.js)46
-rw-r--r--src/js/cosmetic-filtering.js (renamed from js/cosmetic-filtering.js)10
-rw-r--r--src/js/dashboard-common.js (renamed from js/dashboard-common.js)0
-rw-r--r--src/js/dashboard.js (renamed from js/dashboard.js)3
-rw-r--r--src/js/element-picker.js (renamed from js/element-picker.js)139
-rw-r--r--src/js/i18n.js (renamed from js/i18n.js)8
-rw-r--r--src/js/js-loader.js37
-rw-r--r--src/js/liquid-dict.js (renamed from js/liquid-dict.js)2
-rw-r--r--src/js/messaging.js (renamed from js/messaging-handlers.js)126
-rw-r--r--src/js/mirrors.js (renamed from js/mirrors.js)28
-rw-r--r--src/js/net-filtering.js (renamed from js/net-filtering.js)8
-rw-r--r--src/js/pagestore.js (renamed from js/pagestore.js)6
-rw-r--r--src/js/popup.js (renamed from js/popup.js)67
-rw-r--r--src/js/profiler.js (renamed from js/profiler.js)2
-rw-r--r--src/js/settings.js (renamed from js/settings.js)8
-rw-r--r--src/js/start.js (renamed from js/start.js)0
-rw-r--r--src/js/stats.js (renamed from js/stats.js)19
-rw-r--r--src/js/storage.js (renamed from js/storage.js)47
-rw-r--r--src/js/tab.js (renamed from js/tab.js)125
-rw-r--r--src/js/traffic.js (renamed from js/traffic.js)100
-rw-r--r--src/js/ublock.js (renamed from js/ublock.js)2
-rw-r--r--src/js/udom.js (renamed from js/udom.js)0
-rw-r--r--src/js/uritools.js (renamed from js/uritools.js)2
-rw-r--r--src/js/utils.js (renamed from js/utils.js)15
-rw-r--r--src/js/vapi-background.js848
-rw-r--r--src/js/vapi-client.js335
-rw-r--r--src/js/vapi-common.js62
-rw-r--r--src/js/whitelist.js (renamed from js/whitelist.js)10
-rw-r--r--src/js/xal.js (renamed from js/xal.js)37
-rw-r--r--src/lib/publicsuffixlist.min.js (renamed from lib/publicsuffixlist.min.js)0
-rw-r--r--src/lib/punycode.min.js (renamed from lib/punycode.min.js)0
-rw-r--r--src/lib/yamd5.js (renamed from lib/yamd5.js)0
-rw-r--r--src/locales.json1
-rw-r--r--src/manifest.json (renamed from manifest.json)74
-rw-r--r--src/popup.html (renamed from popup.html)12
-rw-r--r--src/settings.html (renamed from settings.html)17
-rw-r--r--src/stats.html (renamed from stats.html)13
-rw-r--r--src/whitelist.html (renamed from whitelist.html)15
-rw-r--r--tools/build_meta.py87
-rw-r--r--tools/import-crowdin.sh67
-rw-r--r--tools/make-chrome.sh17
-rw-r--r--[-rwxr-xr-x]tools/make-clean.sh (renamed from make-clean.sh)2
-rw-r--r--tools/make-noassets.sh15
-rwxr-xr-xtools/make-opera.sh (renamed from make-opera.sh)6
178 files changed, 2420 insertions, 1375 deletions
diff --git a/MANIFESTO.md b/MANIFESTO.md
index 14ea119..24f6155 100644
--- a/MANIFESTO.md
+++ b/MANIFESTO.md
@@ -2,9 +2,9 @@
1. The **user decides** what web content is acceptable or not in their browser.
-The µBlock project does not support Adblock Plus' _"Acceptable Ads Manifesto"_,
-because the _"Acceptable Ads"_ marketing campaign is really the business
+The µBlock project does not support Adblock Plus' _"Acceptable Ads Manifesto"_,
+because the _"Acceptable Ads"_ marketing campaign is really the business
plan of a for-profit entity.
-Users are best placed to know what is or is not acceptable to them. µBlock's
+Users are best placed to know what is or is not acceptable to them. µBlock's
sole purpose is to give users the mean to enforce their own choices.
diff --git a/README.md b/README.md
index 7f4b796..f312218 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,10 @@
**Foreword:** Using a blocker is **NOT** [theft](https://twitter.com/LeaVerou/status/518154828166725632). Do not fall for this creepy idea. The _ultimate_ logical consequence of "blocking = theft" is the criminalisation of the inalienable right to privacy.
-See [releases page](https://github.com/gorhill/uBlock/releases) for recent changes.
+See [releases page](https://github.com/gorhill/uBlock/releases) for recent changes.
See [Wiki](https://github.com/gorhill/uBlock/wiki) for more information.
-An efficient blocker for Chromium-based browsers. Fast and lean. Written from scratch. Development
+An efficient blocker for Chromium-based browsers. Fast and lean. Written from scratch. Development
through benchmarking.
**µBlock is not an "ad blocker", it's a blocker in the broad sense**, which happens to block ads through its support of [Adblock Plus filter syntax](https://adblockplus.org/en/filters). µBlock [extends](https://github.com/gorhill/uBlock/wiki/Filter-syntax-extensions) the syntax.
@@ -25,31 +25,31 @@ My main goal with µBlock is to help users neutralize as much as can be privacy-
<p align="center">
Chromium on Linux 64-bit<br>
<img src="https://raw.githubusercontent.com/gorhill/uBlock/master/doc/img/ss-chromium-2.png" /><br><br>
-<sup>The screenshots above were taken after visiting links in
-<a href="https://github.com/gorhill/uBlock/wiki/Reference-benchmark">reference benchmark</a>
-plus a bit of random browsing. All blockers were active at the same time,
-thus they had to deal with exactly the same workload. Before the screenshots were
-taken, I left the browser idle for many minutes so as to let the browser's
+<sup>The screenshots above were taken after visiting links in
+<a href="https://github.com/gorhill/uBlock/wiki/Reference-benchmark">reference benchmark</a>
+plus a bit of random browsing. All blockers were active at the same time,
+thus they had to deal with exactly the same workload. Before the screenshots were
+taken, I left the browser idle for many minutes so as to let the browser's
garbage collector kicks in. Also, after a while idling, it's good to open the dev
-console for each extension and force a garbage collection cycle by clicking a couple of times
-the trashcan icon in the _Timeline_ tab (this caused a ~15MB drop for µBlock and Adguard in Opera)
+console for each extension and force a garbage collection cycle by clicking a couple of times
+the trashcan icon in the _Timeline_ tab (this caused a ~15MB drop for µBlock and Adguard in Opera)
as garbage collectors sometimes work in a very lazy way, so I did this for each extension.</sup>
</p>
<p align="center">
Being lean doesn't mean blocking less.<br>
<img src="https://raw.githubusercontent.com/gorhill/uBlock/master/doc/benchmarks/privex-201409-30.png" /><br>
-<sup>For details of benchmark, see latest
+<sup>For details of benchmark, see latest
<a href="https://github.com/gorhill/uBlock/wiki/%C2%B5Block-and-others:-Blocking-ads,-trackers,-malwares">µBlock and others: Blocking ads, trackers, malwares</a>.
</p>
## Installation
-From the [Chrome store](https://chrome.google.com/webstore/detail/µblock/cjpalhdlnbpafiamejdnhcphjbkeiagm),
+From the [Chrome store](https://chrome.google.com/webstore/detail/µblock/cjpalhdlnbpafiamejdnhcphjbkeiagm),
the [Opera store](https://addons.opera.com/en-gb/extensions/details/ublock/), or [manually](https://github.com/gorhill/uBlock/tree/master/dist#install).
-To benefit from the higher efficiency, it is of course not advised to use an
-inefficient blocker at the same time. µBlock will do as well or better than the
+To benefit from the higher efficiency, it is of course not advised to use an
+inefficient blocker at the same time. µBlock will do as well or better than the
popular blockers out there.
Also of interest: [About the required permissions](https://github.com/gorhill/uBlock/wiki/About-the-required-permissions).
@@ -61,8 +61,8 @@ I think it is pretty obvious, except for this I suppose:
![Popup](https://raw.githubusercontent.com/gorhill/uBlock/master/doc/img/popup-1.png)&emsp; ![Popup](https://raw.githubusercontent.com/gorhill/uBlock/master/doc/img/popup-2.png)
The big power button is to disable/enable µBlock **for the specific hostname
-which can be extracted from the URL address of the current page**. (It applies to
-the current web site only, it is **not** a global power button.) The state of the power
+which can be extracted from the URL address of the current page**. (It applies to
+the current web site only, it is **not** a global power button.) The state of the power
switch for a specific site will be remembered.
The right-hand screenshot shows optional [dynamic filtering](https://github.com/gorhill/uBlock/wiki/Dynamic-filtering) at work.
@@ -71,22 +71,22 @@ The right-hand screenshot shows optional [dynamic filtering](https://github.com/
µBlock is born out of [HTTP Switchboard](https://github.com/gorhill/httpswitchboard).
All the niceties of HTTPSB have been removed, and what is left is a straightforward
-blocker which support EasyList and the likes, and also support host files.
+blocker which support EasyList and the likes, and also support host files.
Cosmetic filters ("element hiding") are supported.
There is nothing more to it. But it does what popular blockers out there do, at a
-fraction of CPU and memory usage for the same blocking power. Also, no unique user id
+fraction of CPU and memory usage for the same blocking power. Also, no unique user id
and no home means no phoning home (some popular blockers do this, just be careful).
Free. Open source. For users by users. No donations sought.
-Without the preset lists of filters, this extension is nothing. So if ever you
-really do want to contribute something, think about the people working hard
-to maintain the filter lists you are using, which were made available to use by
+Without the preset lists of filters, this extension is nothing. So if ever you
+really do want to contribute something, think about the people working hard
+to maintain the filter lists you are using, which were made available to use by
all for free.
-You may contribute by helping to translate this project. I created an
-[entry on Crowdin](https://crowdin.net/project/ublock), where you may contribute
+You may contribute by helping to translate this project. I created an
+[entry on Crowdin](https://crowdin.net/project/ublock), where you may contribute
to the translation work.
## License
diff --git a/import-crowdin.sh b/import-crowdin.sh
deleted file mode 100755
index abc4b34..0000000
--- a/import-crowdin.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-#
-# This script assumes a linux environment
-
-echo "*** uBlock: Importing from Crowdin archive"
-rm -r ~/Downloads/crowdin
-unzip -q ~/Downloads/ublock.zip -d ~/Downloads/crowdin
-cp ~/Downloads/crowdin/ar/messages.json ./_locales/ar/messages.json
-cp ~/Downloads/crowdin/cs/messages.json ./_locales/cs/messages.json
-cp ~/Downloads/crowdin/da/messages.json ./_locales/da/messages.json
-cp ~/Downloads/crowdin/el/messages.json ./_locales/el/messages.json
-cp ~/Downloads/crowdin/es-ES/messages.json ./_locales/es/messages.json
-cp ~/Downloads/crowdin/et/messages.json ./_locales/et/messages.json
-cp ~/Downloads/crowdin/fi/messages.json ./_locales/fi/messages.json
-cp ~/Downloads/crowdin/he/messages.json ./_locales/he/messages.json
-cp ~/Downloads/crowdin/hi/messages.json ./_locales/hi/messages.json
-cp ~/Downloads/crowdin/hr/messages.json ./_locales/hr/messages.json
-cp ~/Downloads/crowdin/hu/messages.json ./_locales/hu/messages.json
-cp ~/Downloads/crowdin/id/messages.json ./_locales/id/messages.json
-cp ~/Downloads/crowdin/it/messages.json ./_locales/it/messages.json
-cp ~/Downloads/crowdin/ja/messages.json ./_locales/ja/messages.json
-cp ~/Downloads/crowdin/mr/messages.json ./_locales/mr/messages.json
-cp ~/Downloads/crowdin/no/messages.json ./_locales/nb/messages.json
-cp ~/Downloads/crowdin/nl/messages.json ./_locales/nl/messages.json
-cp ~/Downloads/crowdin/pl/messages.json ./_locales/pl/messages.json
-cp ~/Downloads/crowdin/pt-BR/messages.json ./_locales/pt_BR/messages.json
-cp ~/Downloads/crowdin/pt-PT/messages.json ./_locales/pt_PT/messages.json
-cp ~/Downloads/crowdin/ro/messages.json ./_locales/ro/messages.json
-cp ~/Downloads/crowdin/ru/messages.json ./_locales/ru/messages.json
-cp ~/Downloads/crowdin/sv-SE/messages.json ./_locales/sv/messages.json
-cp ~/Downloads/crowdin/tr/messages.json ./_locales/tr/messages.json
-cp ~/Downloads/crowdin/uk/messages.json ./_locales/uk/messages.json
-cp ~/Downloads/crowdin/vi/messages.json ./_locales/vi/messages.json
-cp ~/Downloads/crowdin/zh-CN/messages.json ./_locales/zh_CN/messages.json
-
-#
-
-cp ~/Downloads/crowdin/ar/description.txt ./dist/description/description-ar.txt
-cp ~/Downloads/crowdin/cs/description.txt ./dist/description/description-cs.txt
-cp ~/Downloads/crowdin/da/description.txt ./dist/description/description-da.txt
-#cp ~/Downloads/crowdin/el/description.txt ./dist/description/description-el.txt
-cp ~/Downloads/crowdin/es-ES/description.txt ./dist/description/description-es.txt
-cp ~/Downloads/crowdin/et/description.txt ./dist/description/description-et.txt
-cp ~/Downloads/crowdin/fi/description.txt ./dist/description/description-fi.txt
-cp ~/Downloads/crowdin/he/description.txt ./dist/description/description-he.txt
-cp ~/Downloads/crowdin/hr/description.txt ./dist/description/description-hr.txt
-cp ~/Downloads/crowdin/hu/description.txt ./dist/description/description-hu.txt
-cp ~/Downloads/crowdin/id/description.txt ./dist/description/description-id.txt
-cp ~/Downloads/crowdin/it/description.txt ./dist/description/description-it.txt
-#cp ~/Downloads/crowdin/ja/description.txt ./dist/description/description-ja.txt
-cp ~/Downloads/crowdin/no/description.txt ./dist/description/description-no.txt
-cp ~/Downloads/crowdin/nl/description.txt ./dist/description/description-nl.txt
-cp ~/Downloads/crowdin/pl/description.txt ./dist/description/description-pl.txt
-cp ~/Downloads/crowdin/pt-BR/description.txt ./dist/description/description-pt_BR.txt
-cp ~/Downloads/crowdin/pt-PT/description.txt ./dist/description/description-pt_PT.txt
-cp ~/Downloads/crowdin/ro/description.txt ./dist/description/description-ro.txt
-cp ~/Downloads/crowdin/ru/description.txt ./dist/description/description-ru.txt
-cp ~/Downloads/crowdin/sv-SE/description.txt ./dist/description/description-sv.txt
-cp ~/Downloads/crowdin/tr/description.txt ./dist/description/description-tr.txt
-cp ~/Downloads/crowdin/uk/description.txt ./dist/description/description-uk.txt
-#cp ~/Downloads/crowdin/vi/description.txt ./dist/description/description-vi.txt
-cp ~/Downloads/crowdin/zh-CN/description.txt ./dist/description/description-zh_CN.txt
-
-#
-
-rm -r ~/Downloads/crowdin
-echo "*** uBlock: Import done."
diff --git a/js/messaging-client.js b/js/messaging-client.js
deleted file mode 100644
index 660fa1a..0000000
--- a/js/messaging-client.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/*******************************************************************************
-
- µBlock - a Chromium browser extension to block requests.
- Copyright (C) 2014 Raymond Hill
-
- 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
-*/
-
-// This is the reference client-side implementation of µBlock's messaging
-// infrastructure. The "server"-side implementation is in messaging.js.
-
-// The client-side implementation creates a port in order to connect to
-// µBlock's background page. With this port we can "ask", "tell" or "announce":
-//
-// "ask": send a request and expect an answer using a callback.
-// "tell": send a request with no expectation of an answer.
-// "announce": send a request to be relayed to all connections -- no answer
-// expected.
-//
-// The tricky part in this implementation is to ensure all the requests are
-// uniquely identified, so that the background-page can keep track of these
-// until it is ready to send back an answer, which will be tagged with the
-// same id. The uniqueness must be true for all ports which connect to the
-// background page at any given time.
-//
-// Currently using Math.random() to generate this id... I don't know about the
-// implementation of Math.random(), but as long as I have a good expectation
-// of uniqueness, it's ok, we are not dealing with critical stuff here.
-
-/* global chrome */
-
-var messaging = (function(name){
- var port = null;
- var requestId = 1;
- var requestIdToCallbackMap = {};
- var listenCallback = null;
-
- var onPortMessage = function(details) {
- if ( typeof details.id !== 'number' ) {
- return;
- }
- // Announcement?
- if ( details.id < 0 ) {
- if ( listenCallback ) {
- listenCallback(details.msg);
- }
- return;
- }
- var callback = requestIdToCallbackMap[details.id];
- if ( !callback ) {
- return;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[details.id];
- callback(details.msg);
- };
-
- var start = function(name) {
- port = chrome.runtime.connect({ name: name });
- port.onMessage.addListener(onPortMessage);
-
- // https://github.com/gorhill/uBlock/issues/193
- port.onDisconnect.addListener(stop);
- };
-
- var stop = function() {
- listenCallback = null;
- port.disconnect();
- port = null;
- flushCallbacks();
- };
-
- if ( typeof name === 'string' && name !== '' ) {
- start(name);
- }
-
- var ask = function(msg, callback) {
- if ( port === null ) {
- if ( typeof callback === 'function' ) {
- callback();
- }
- return;
- }
- if ( callback === undefined ) {
- tell(msg);
- return;
- }
- var id = requestId++;
- port.postMessage({ id: id, msg: msg });
- requestIdToCallbackMap[id] = callback;
- };
-
- var tell = function(msg) {
- if ( port !== null ) {
- port.postMessage({ id: 0, msg: msg });
- }
- };
-
- var listen = function(callback) {
- listenCallback = callback;
- };
-
- var flushCallbacks = function() {
- var callback;
- for ( var id in requestIdToCallbackMap ) {
- if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) {
- continue;
- }
- callback = requestIdToCallbackMap[id];
- if ( !callback ) {
- continue;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[id];
- callback();
- }
- };
-
- return {
- start: start,
- stop: stop,
- ask: ask,
- tell: tell,
- listen: listen
- };
-})();
diff --git a/js/messaging.js b/js/messaging.js
deleted file mode 100644
index a6a00c8..0000000
--- a/js/messaging.js
+++ /dev/null
@@ -1,252 +0,0 @@
-/*******************************************************************************
-
- µBlock - a Chromium browser extension to block requests.
- Copyright (C) 2014 Raymond Hill
-
- 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 chrome, µBlock */
-
-// So there might be memory leaks related to the direct use of sendMessage(),
-// as per https://code.google.com/p/chromium/issues/detail?id=320723. The issue
-// is not marked as resolved, and the last message from chromium dev is:
-//
-// "You can construct Port objects (runtime.connect) and emulate sendMessage
-// "behaviour. The bug is that sendMessage doesn't clean up its Ports."
-//
-// So the point here is to have an infrastructure which allows relying more on
-// direct use of Port objects rather than going through sendMessage().
-
-/******************************************************************************/
-/*******************************************************************************
-
-// Here this is the "server"-side implementation.
-//
-// Reference client-side implementation is found in:
-//
-// messaging-client.js
-//
-// For instance, it needs to be cut & pasted for content scripts since
-// I can not include in a simple way js file content from another js file.
-
-*******************************************************************************/
-/******************************************************************************/
-
-µBlock.messaging = (function() {
-
-/******************************************************************************/
-
-var runtimeIdGenerator = 1;
-var nameToPortMap = {};
-var nameToListenerMap = {};
-var nullFunc = function(){};
-
-/******************************************************************************/
-
-var listenerNameFromPortName = function(portName) {
- var pos = portName.indexOf('/');
- if ( pos === -1 ) {
- return '';
- }
- return portName.slice(0, pos);
-};
-
-var listenerFromPortName = function(portName) {
- return nameToListenerMap[listenerNameFromPortName(portName)];
-};
-
-/******************************************************************************/
-
-var listen = function(portName, callback) {
- var listener = nameToListenerMap[portName];
- if ( listener && listener !== callback ) {
- throw 'Only one listener allowed';
- }
- nameToListenerMap[portName] = callback;
-};
-
-/******************************************************************************/
-
-var tell = function(target, msg) {
- target += '/';
- for ( var portName in nameToPortMap ) {
- if ( nameToPortMap.hasOwnProperty(portName) === false ) {
- continue;
- }
- if ( portName.indexOf(target) === 0 ) {
- nameToPortMap[portName].postMessage({ id: -1, msg: msg });
- }
- }
-};
-
-/******************************************************************************/
-
-var announce = function(msg) {
- // Background page handler
- defaultHandler(msg, null, nullFunc);
-
- // Extension pages & content scripts handlers
- for ( var portName in nameToPortMap ) {
- if ( nameToPortMap.hasOwnProperty(portName) === false ) {
- continue;
- }
- nameToPortMap[portName].postMessage({ id: -1, msg: msg });
- }
-};
-
-/******************************************************************************/
-
-var onMessage = function(request, port) {
- var reqId = request.id;
- // Annoucement: dispatch everywhere.
- if ( reqId < 0 ) {
- announce(request.msg);
- return;
- }
- var listener = listenerFromPortName(port.name) || defaultHandler;
- // Being told
- if ( reqId === 0 ) {
- listener(request.msg, port.sender, nullFunc);
- return;
- }
- // Being asked
- listener(request.msg, port.sender, function(response) {
- port.postMessage({
- id: reqId,
- msg: response !== undefined ? response : null
- });
- });
-};
-
-/******************************************************************************/
-
-// Default is for commonly used messages.
-
-function defaultHandler(request, sender, callback) {
- var µb = µBlock;
-
- // Async
- switch ( request.what ) {
- case 'getAssetContent':
- return µb.assets.getLocal(request.url, callback);
-
- case 'loadUbiquitousAllowRules':
- return µb.loadUbiquitousWhitelists();
-
- default:
- break;
- }
-
- // Sync
- var response;
-
- switch ( request.what ) {
- case 'contextMenuEvent':
- µb.contextMenuClientX = request.clientX;
- µb.contextMenuClientY = request.clientY;
- break;
-
- case 'forceReloadTab':
- µb.forceReload(request.pageURL);
- break;
-
- case 'getUserSettings':
- response = µb.userSettings;
- break;
-
- case 'gotoExtensionURL':
- µb.utils.gotoExtensionURL(request.url);
- break;
-
- case 'gotoURL':
- µb.utils.gotoURL(request);
- break;
-
- case 'reloadAllFilters':
- µb.reloadPresetBlacklists(request.switches, request.update);
- break;
-
- case 'userSettings':
- response = µb.changeUserSettings(request.name, request.value);
- break;
-
- default:
- // console.error('µBlock> messaging.js / defaultHandler > unknown request: %o', request);
- break;
- }
-
- callback(response);
-}
-
-// https://www.youtube.com/watch?v=rrzRgUAHqc8
-
-/******************************************************************************/
-
-// Port disconnected, relay this information to apropriate listener.
-
-var onDisconnect = function(port) {
- // Notify listener of the disconnection -- using a reserved message id.
- var listener = listenerFromPortName(port.name) || defaultHandler;
- var msg = {
- 'what': 'disconnected',
- 'which': listenerNameFromPortName(port.name)
- };
- listener(msg, port.sender, nullFunc);
-
- // Cleanup port if no longer in use.
- if ( nameToPortMap.hasOwnProperty(port.name) ) {
- delete nameToPortMap[port.name];
- port.onMessage.removeListener(onMessage);
- port.onDisconnect.removeListener(onDisconnect);
- }
-};
-
-/******************************************************************************/
-
-var onConnect = function(port) {
- // We must have a port name.
- if ( typeof port.name !== 'string' || port.name === '' ) {
- console.error('µBlock> messaging.js / onConnectHandler(): no port name!');
- return;
- }
-
- // Ensure port name is unique
- port.name += '/' + runtimeIdGenerator++;
-
- nameToPortMap[port.name] = port;
- port.onMessage.addListener(onMessage);
- port.onDisconnect.addListener(onDisconnect);
-};
-
-/******************************************************************************/
-
-chrome.runtime.onConnect.addListener(onConnect);
-
-/******************************************************************************/
-
-return {
- listen: listen,
- tell: tell,
- announce: announce,
- defaultHandler: defaultHandler
-};
-
-/******************************************************************************/
-
-})();
-
-/******************************************************************************/
diff --git a/make-chrome.sh b/make-chrome.sh
deleted file mode 100755
index 95f648c..0000000
--- a/make-chrome.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-#
-# This script assumes a linux environment
-
-echo "*** uBlock: Creating web store package"
-echo "*** uBlock: Copying files"
-cp -R assets dist/ublock/
-rm dist/ublock/assets/*.sh
-cp -R css dist/ublock/
-cp -R img dist/ublock/
-cp -R js dist/ublock/
-cp -R lib dist/ublock/
-cp -R _locales dist/ublock/
-cp *.html dist/ublock/
-cp *.txt dist/ublock/
-cp manifest.json dist/ublock/
-echo "*** uBlock: Package done."
-
diff --git a/make-noassets.sh b/make-noassets.sh
deleted file mode 100755
index 43ee2c1..0000000
--- a/make-noassets.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-#
-# This script assumes a linux environment
-
-echo "*** uBlock: Creating web store package"
-echo "*** uBlock: Copying files"
-cp -R css dist/ublock/
-cp -R img dist/ublock/
-cp -R js dist/ublock/
-cp -R lib dist/ublock/
-cp -R _locales dist/ublock/
-cp *.html dist/ublock/
-cp *.txt dist/ublock/
-cp manifest.json dist/ublock/
-echo "*** uBlock: Package done."
diff --git a/meta/config.json b/meta/config.json
new file mode 100644
index 0000000..f5b8010
--- /dev/null
+++ b/meta/config.json
@@ -0,0 +1,31 @@
+{
+ "name": "µBlock",
+ "clean_name": "ublock",
+ "url": "https://github.com/gorhill/uBlock",
+ "author": "Raymond Hill",
+ "author_email": "rhill@raymondhill.net",
+ "author_www": "http://raymondhill.net/",
+ "version": "0.7.0.7",
+ "def_lang": "en",
+ "vendors": {
+ "crx": {
+ "app_id": "cjpalhdlnbpafiamejdnhcphjbkeiagm",
+ "manifest": "manifest.json",
+ "locales": "_locales",
+ "file_ext": ".crx",
+ "cert_key": "../meta/crx/key.pem"
+ },
+ "safariextz": {
+ "app_id": "net.gorhill.uBlock",
+ "dir": "uBlock.safariextension",
+ "manifest": {
+ "Info": "Info.plist",
+ "Settings": "Settings.plist"
+ },
+ "file_ext": ".safariextz",
+ "developer_identifier": "T7HSFKB9M5",
+ "cert_dir": "../meta/safariextz/certs/",
+ "cert_key": "../meta/safariextz/certs/key.pem"
+ }
+ }
+} \ No newline at end of file
diff --git a/meta/crx/manifest.json b/meta/crx/manifest.json
new file mode 100644
index 0000000..22641fa
--- /dev/null
+++ b/meta/crx/manifest.json
@@ -0,0 +1,62 @@
+{
+ "manifest_version": 2,
+ "minimum_chrome_version": "22.0",
+ "default_locale": "{def_lang}",
+ "update_url": "https://clients2.google.com/service/update2/crx",
+
+ "version": "{version}",
+ "name": "__MSG_extName__",
+ "description": "__MSG_extShortDesc__",
+ "homepage_url": "{url}",
+ "author": "{author}",
+ "developer": {
+ "name": "{author}",
+ "email": "{author_email}"
+ },
+
+ "icons": {
+ "16": "img/icon_16.png",
+ "128": "img/icon_128.png"
+ },
+
+ "permissions": [
+ "contextMenus",
+ "downloads",
+ "storage",
+ "tabs",
+ "unlimitedStorage",
+ "webNavigation",
+ "webRequest",
+ "webRequestBlocking",
+ "http://*/*",
+ "https://*/*"
+ ],
+
+ "background": {
+ "page": "background.html"
+ },
+ "options_page": "dashboard.html",
+ "content_scripts": [
+ {
+ "matches": ["http://*/*", "https://*/*"],
+ "js": ["js/vapi-client.js", "js/contentscript-start.js"],
+ "run_at": "document_start",
+ "all_frames": true
+ },
+ {
+ "matches": ["http://*/*", "https://*/*"],
+ "js": ["js/contentscript-end.js"],
+ "run_at": "document_end",
+ "all_frames": true
+ }
+ ],
+
+ "browser_action": {
+ "default_icon": {
+ "19": "img/browsericons/icon19-off.png",
+ "38": "img/browsericons/icon38-off.png"
+ },
+ "default_title": "{name}",
+ "default_popup": "popup.html"
+ }
+} \ No newline at end of file
diff --git a/meta/crx/update_crx.xml b/meta/crx/update_crx.xml
new file mode 100644
index 0000000..74078e8
--- /dev/null
+++ b/meta/crx/update_crx.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gupdate xmlns="http://www.google.com/update2/response" protocol="2.0">
+ <app appid="{app_id}">
+ <updatecheck codebase="{url}{name}.crx" version="{version}"/>
+ </app>
+</gupdate>
diff --git a/meta/safariextz/Info.plist b/meta/safariextz/Info.plist
new file mode 100644
index 0000000..125dc1b
--- /dev/null
+++ b/meta/safariextz/Info.plist
@@ -0,0 +1,87 @@
+<?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>{author}</string>
+ <key>Builder Version</key>
+ <string>534.57.2</string>
+ <key>CFBundleDisplayName</key>
+ <string>{name}</string>
+ <key>CFBundleIdentifier</key>
+ <string>{app_id}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleShortVersionString</key>
+ <string>{version}</string>
+ <key>CFBundleVersion</key>
+ <string>{build_number}</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>Identifier</key>
+ <string>popover</string>
+ <key>Filename</key>
+ <string>popup.html</string>
+ </dict>
+ </array>
+ <key>Toolbar Items</key>
+ <array>
+ <dict>
+ <key>Identifier</key>
+ <string>toolbarItem</string>
+ <key>Image</key>
+ <string>img/icon_16.png</string>
+ <key>Label</key>
+ <string>{name}</string>
+ <key>Popover</key>
+ <string>popover</string>
+ </dict>
+ </array>
+ </dict>
+ <key>Content</key>
+ <dict>
+ <key>Scripts</key>
+ <dict>
+ <key>Start</key>
+ <array>
+ <string>js/vapi-client.js</string>
+ <string>js/contentscript-start.js</string>
+ </array>
+ <key>End</key>
+ <array>
+ <string>js/contentscript-end.js</string>
+ </array>
+ </dict>
+ <key>Whitelist</key>
+ <array>
+ <string>http://*/*</string>
+ <string>https://*/*</string>
+ </array>
+ </dict>
+ <key>Description</key>
+ <string>{description}</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>{url}update_safariextz.plist</string> -->
+ <key>Website</key>
+ <string>{url}</string>
+</dict>
+</plist>
diff --git a/meta/safariextz/update_safariextz.plist b/meta/safariextz/update_safariextz.plist
new file mode 100644
index 0000000..4c4f28b
--- /dev/null
+++ b/meta/safariextz/update_safariextz.plist
@@ -0,0 +1,21 @@
+<?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>{app_id}</string>
+ <key>Developer Identifier</key>
+ <string>{developer_identifier}</string>
+ <key>CFBundleShortVersionString</key>
+ <string>{version}</string>
+ <key>CFBundleVersion</key>
+ <string>{build_number}</string>
+ <key>URL</key>
+ <string>{url}{name}.safariextz</string>
+ </dict>
+ </array>
+ </dict>
+</plist>
diff --git a/1p-filters.html b/src/1p-filters.html
index 2b34321..957b3d8 100644
--- a/1p-filters.html
+++ b/src/1p-filters.html
@@ -18,11 +18,14 @@
<p><button id="userFiltersApply" disabled="true" data-i18n="1pApplyChanges"></button></p>
</div>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/dashboard-common.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/1p-filters.js"></script>
+<script src="js/js-loader.js" data-jsList="
+js/vapi-common.js
+js/vapi-client.js
+js/udom.js
+js/i18n.js
+js/dashboard-common.js
+js/1p-filters.js
+"></script>
</body>
</html>
diff --git a/3p-filters.html b/src/3p-filters.html
index a8c3d02..9a424ba 100644
--- a/3p-filters.html
+++ b/src/3p-filters.html
@@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
-<title>HTTP Switchboard — Ubiquitous rules</title>
+<title>µBlock — Ubiquitous rules</title>
<link rel="stylesheet" type="text/css" href="css/common.css">
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css">
<link rel="stylesheet" type="text/css" href="css/3p-filters.css">
@@ -31,11 +31,16 @@
<div id="busyOverlay"></div>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/dashboard-common.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/3p-filters.js"></script>
+<script src="js/js-loader.js" data-jsList="
+lib/publicsuffixlist.min.js
+js/vapi-common.js
+js/vapi-client.js
+js/udom.js
+js/i18n.js
+js/uritools.js
+js/dashboard-common.js
+js/3p-filters.js
+"></script>
</body>
</html>
diff --git a/src/Info.plist b/src/Info.plist
new file mode 100644
index 0000000..4bf24ae
--- /dev/null
+++ b/src/Info.plist
@@ -0,0 +1,87 @@
+<?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.7</string>
+ <key>CFBundleVersion</key>
+ <string>1452035</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>Identifier</key>
+ <string>popover</string>
+ <key>Filename</key>
+ <string>popup.html</string>
+ </dict>
+ </array>
+ <key>Toolbar Items</key>
+ <array>
+ <dict>
+ <key>Identifier</key>
+ <string>toolbarItem</string>
+ <key>Image</key>
+ <string>img/icon_16.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>Start</key>
+ <array>
+ <string>js/vapi-client.js</string>
+ <string>js/contentscript-start.js</string>
+ </array>
+ <key>End</key>
+ <array>
+ <string>js/contentscript-end.js</string>
+ </array>
+ </dict>
+ <key>Whitelist</key>
+ <array>
+ <string>http://*/*</string>
+ <string>https://*/*</string>
+ </array>
+ </dict>
+ <key>Description</key>
+ <string>Finally, an efficient blocker for Chromium-based browsers. 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/_locales/ar/messages.json b/src/_locales/ar/messages.json
index 5e81040..5e81040 100644
--- a/_locales/ar/messages.json
+++ b/src/_locales/ar/messages.json
diff --git a/_locales/cs/messages.json b/src/_locales/cs/messages.json
index fa1bf35..fa1bf35 100644
--- a/_locales/cs/messages.json
+++ b/src/_locales/cs/messages.json
diff --git a/_locales/da/messages.json b/src/_locales/da/messages.json
index a727922..a727922 100644
--- a/_locales/da/messages.json
+++ b/src/_locales/da/messages.json
diff --git a/_locales/de/messages.json b/src/_locales/de/messages.json
index eb4f651..eb4f651 100644
--- a/_locales/de/messages.json
+++ b/src/_locales/de/messages.json
diff --git a/_locales/el/messages.json b/src/_locales/el/messages.json
index b3d004a..b3d004a 100644
--- a/_locales/el/messages.json
+++ b/src/_locales/el/messages.json
diff --git a/_locales/en/messages.json b/src/_locales/en/messages.json
index 06c1fe6..06c1fe6 100644
--- a/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
diff --git a/_locales/es/messages.json b/src/_locales/es/messages.json
index 4a074c2..4a074c2 100644
--- a/_locales/es/messages.json
+++ b/src/_locales/es/messages.json
diff --git a/_locales/et/messages.json b/src/_locales/et/messages.json
index b3cc8ca..b3cc8ca 100644
--- a/_locales/et/messages.json
+++ b/src/_locales/et/messages.json
diff --git a/_locales/fi/messages.json b/src/_locales/fi/messages.json
index 4c7bb62..4c7bb62 100644
--- a/_locales/fi/messages.json
+++ b/src/_locales/fi/messages.json
diff --git a/_locales/fr/messages.json b/src/_locales/fr/messages.json
index c30b447..c30b447 100644
--- a/_locales/fr/messages.json
+++ b/src/_locales/fr/messages.json
diff --git a/_locales/he/messages.json b/src/_locales/he/messages.json
index 49c7dc2..49c7dc2 100644
--- a/_locales/he/messages.json
+++ b/src/_locales/he/messages.json
diff --git a/_locales/hi/messages.json b/src/_locales/hi/messages.json
index d5f21c5..d5f21c5 100644
--- a/_locales/hi/messages.json
+++ b/src/_locales/hi/messages.json
diff --git a/_locales/hr/messages.json b/src/_locales/hr/messages.json
index a530d2e..a530d2e 100644
--- a/_locales/hr/messages.json
+++ b/src/_locales/hr/messages.json
diff --git a/_locales/hu/messages.json b/src/_locales/hu/messages.json
index a180a57..a180a57 100644
--- a/_locales/hu/messages.json
+++ b/src/_locales/hu/messages.json
diff --git a/_locales/id/messages.json b/src/_locales/id/messages.json
index 78bec1b..78bec1b 100644
--- a/_locales/id/messages.json
+++ b/src/_locales/id/messages.json
diff --git a/_locales/it/messages.json b/src/_locales/it/messages.json
index a70f3bc..a70f3bc 100644
--- a/_locales/it/messages.json
+++ b/src/_locales/it/messages.json
diff --git a/_locales/ja/messages.json b/src/_locales/ja/messages.json
index a06e499..a06e499 100644
--- a/_locales/ja/messages.json
+++ b/src/_locales/ja/messages.json
diff --git a/_locales/mr/messages.json b/src/_locales/mr/messages.json
index 7498c45..7498c45 100644
--- a/_locales/mr/messages.json
+++ b/src/_locales/mr/messages.json
diff --git a/_locales/nb/messages.json b/src/_locales/nb/messages.json
index cd836c5..cd836c5 100644
--- a/_locales/nb/messages.json
+++ b/src/_locales/nb/messages.json
diff --git a/_locales/nl/messages.json b/src/_locales/nl/messages.json
index 43d0c11..43d0c11 100644
--- a/_locales/nl/messages.json
+++ b/src/_locales/nl/messages.json
diff --git a/_locales/pl/messages.json b/src/_locales/pl/messages.json
index f597670..f597670 100644
--- a/_locales/pl/messages.json
+++ b/src/_locales/pl/messages.json
diff --git a/_locales/pt_BR/messages.json b/src/_locales/pt_BR/messages.json
index e1ca8fe..e1ca8fe 100644
--- a/_locales/pt_BR/messages.json
+++ b/src/_locales/pt_BR/messages.json
diff --git a/_locales/pt_PT/messages.json b/src/_locales/pt_PT/messages.json
index 8cdc130..8cdc130 100644
--- a/_locales/pt_PT/messages.json
+++ b/src/_locales/pt_PT/messages.json
diff --git a/_locales/ro/messages.json b/src/_locales/ro/messages.json
index 55d3258..55d3258 100644
--- a/_locales/ro/messages.json
+++ b/src/_locales/ro/messages.json
diff --git a/_locales/ru/messages.json b/src/_locales/ru/messages.json
index ed7590f..ed7590f 100644
--- a/_locales/ru/messages.json
+++ b/src/_locales/ru/messages.json
diff --git a/_locales/sv/messages.json b/src/_locales/sv/messages.json
index 56135a0..56135a0 100644
--- a/_locales/sv/messages.json
+++ b/src/_locales/sv/messages.json
diff --git a/_locales/tr/messages.json b/src/_locales/tr/messages.json
index dbe9380..dbe9380 100644
--- a/_locales/tr/messages.json
+++ b/src/_locales/tr/messages.json
diff --git a/_locales/uk/messages.json b/src/_locales/uk/messages.json
index 7311e78..7311e78 100644
--- a/_locales/uk/messages.json
+++ b/src/_locales/uk/messages.json
diff --git a/_locales/vi/messages.json b/src/_locales/vi/messages.json
index beae0b4..beae0b4 100644
--- a/_locales/vi/messages.json
+++ b/src/_locales/vi/messages.json
diff --git a/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json
index 94d0f1a..94d0f1a 100644
--- a/_locales/zh_CN/messages.json
+++ b/src/_locales/zh_CN/messages.json
diff --git a/about.html b/src/about.html
index f46fb05..f6589be 100644
--- a/about.html
+++ b/src/about.html
@@ -13,7 +13,7 @@
<h2>µBlock <span id="aboutVersion"></span></h2>
<ul>
<li><a href="https://github.com/gorhill/uBlock/releases" data-i18n="aboutChangelog"></a>
- <li><a href="https://github.com/gorhill/ublock" data-i18n="aboutCode"></a>
+ <li><a href="https://github.com/gorhill/uBlock" data-i18n="aboutCode"></a>
<li><span data-i18n="aboutContributors"></span>
<ul>
<li><a href="https://github.com/gorhill/uBlock/graphs/contributors">Github</a>
@@ -31,11 +31,14 @@
<p><button type="button" id="reset" data-i18n="aboutResetDataButton">Start from scratch...</button>
</div>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/dashboard-common.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/about.js"></script>
+<script src="js/js-loader.js" data-jsList="
+js/vapi-common.js
+js/vapi-client.js
+js/udom.js
+js/i18n.js
+js/dashboard-common.js
+js/about.js
+"></script>
</body>
</html>
diff --git a/asset-viewer.html b/src/asset-viewer.html
index 3e1ed0b..b3b6ffe 100644
--- a/asset-viewer.html
+++ b/src/asset-viewer.html
@@ -12,8 +12,12 @@
</head>
<body>
<div id="content"></div>
-<script src="js/udom.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/asset-viewer.js"></script>
+
+<script src="js/js-loader.js" data-jsList="
+js/udom.js
+js/vapi-client.js
+js/asset-viewer.js
+"></script>
+
</body>
</html>
diff --git a/assets/checksums.txt b/src/assets/checksums.txt
index 78bdae5..78bdae5 100644
--- a/assets/checksums.txt
+++ b/src/assets/checksums.txt
diff --git a/assets/thirdparties/abp.mozilla-hispano.org/nauscopio/filtros.txt b/src/assets/thirdparties/abp.mozilla-hispano.org/nauscopio/filtros.txt
index 7d2f562..7d2f562 100644
--- a/assets/thirdparties/abp.mozilla-hispano.org/nauscopio/filtros.txt
+++ b/src/assets/thirdparties/abp.mozilla-hispano.org/nauscopio/filtros.txt
diff --git a/assets/thirdparties/adblock-chinalist.googlecode.com/svn/trunk/adblock.txt b/src/assets/thirdparties/adblock-chinalist.googlecode.com/svn/trunk/adblock.txt
index 49e5120..49e5120 100644
--- a/assets/thirdparties/adblock-chinalist.googlecode.com/svn/trunk/adblock.txt
+++ b/src/assets/thirdparties/adblock-chinalist.googlecode.com/svn/trunk/adblock.txt
diff --git a/assets/thirdparties/adblock-czechoslovaklist.googlecode.com/svn/filters.txt b/src/assets/thirdparties/adblock-czechoslovaklist.googlecode.com/svn/filters.txt
index a097eee..a097eee 100644
--- a/assets/thirdparties/adblock-czechoslovaklist.googlecode.com/svn/filters.txt
+++ b/src/assets/thirdparties/adblock-czechoslovaklist.googlecode.com/svn/filters.txt
diff --git a/assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt b/src/assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt
index a3e3cd8..a3e3cd8 100644
--- a/assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt
+++ b/src/assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt
diff --git a/assets/thirdparties/adblock.gardar.net/is.abp.txt b/src/assets/thirdparties/adblock.gardar.net/is.abp.txt
index 7d62e11..7d62e11 100644
--- a/assets/thirdparties/adblock.gardar.net/is.abp.txt
+++ b/src/assets/thirdparties/adblock.gardar.net/is.abp.txt
diff --git a/assets/thirdparties/adblock.schack.dk/block.txt b/src/assets/thirdparties/adblock.schack.dk/block.txt
index 51f0876..51f0876 100644
--- a/assets/thirdparties/adblock.schack.dk/block.txt
+++ b/src/assets/thirdparties/adblock.schack.dk/block.txt
diff --git a/assets/thirdparties/cjxlist1.googlecode.com/svn/cjxlist.txt b/src/assets/thirdparties/cjxlist1.googlecode.com/svn/cjxlist.txt
index 3d28719..3d28719 100644
--- a/assets/thirdparties/cjxlist1.googlecode.com/svn/cjxlist.txt
+++ b/src/assets/thirdparties/cjxlist1.googlecode.com/svn/cjxlist.txt
diff --git a/assets/thirdparties/dl.dropboxusercontent.com/u/1289327/abpxfiles/filtri.txt b/src/assets/thirdparties/dl.dropboxusercontent.com/u/1289327/abpxfiles/filtri.txt
index 67f8545..67f8545 100644
--- a/assets/thirdparties/dl.dropboxusercontent.com/u/1289327/abpxfiles/filtri.txt
+++ b/src/assets/thirdparties/dl.dropboxusercontent.com/u/1289327/abpxfiles/filtri.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/advblock.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/advblock.txt
index 2b9128e..2b9128e 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/advblock.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/advblock.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/bitblock.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/bitblock.txt
index 667a239..667a239 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/bitblock.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/bitblock.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/easylist.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylist.txt
index 2ffb443..2ffb443 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/easylist.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylist.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/easylist_noelemhide.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylist_noelemhide.txt
index 0dcd0c1..0dcd0c1 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/easylist_noelemhide.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylist_noelemhide.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistchina.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistchina.txt
index a11efbe..a11efbe 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistchina.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistchina.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistdutch.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistdutch.txt
index 88b248b..88b248b 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistdutch.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistdutch.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistgermany.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistgermany.txt
index 7a992eb..7a992eb 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistgermany.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistgermany.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistitaly.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistitaly.txt
index 5cdddc5..5cdddc5 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/easylistitaly.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easylistitaly.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/easyprivacy.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easyprivacy.txt
index 169486e..169486e 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/easyprivacy.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/easyprivacy.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-annoyance.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-annoyance.txt
index e3d7b22..e3d7b22 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-annoyance.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-annoyance.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-social.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-social.txt
index c096102..c096102 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-social.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/fanboy-social.txt
diff --git a/assets/thirdparties/easylist-downloads.adblockplus.org/liste_fr.txt b/src/assets/thirdparties/easylist-downloads.adblockplus.org/liste_fr.txt
index d46186a..d46186a 100644
--- a/assets/thirdparties/easylist-downloads.adblockplus.org/liste_fr.txt
+++ b/src/assets/thirdparties/easylist-downloads.adblockplus.org/liste_fr.txt
diff --git a/assets/thirdparties/gitorious.org/adblock-latvian/adblock-latvian/raw/master_lists/latvian-list.txt b/src/assets/thirdparties/gitorious.org/adblock-latvian/adblock-latvian/raw/master_lists/latvian-list.txt
index c901045..c901045 100644
--- a/assets/thirdparties/gitorious.org/adblock-latvian/adblock-latvian/raw/master_lists/latvian-list.txt
+++ b/src/assets/thirdparties/gitorious.org/adblock-latvian/adblock-latvian/raw/master_lists/latvian-list.txt
diff --git a/assets/thirdparties/home.fredfiber.no/langsholt/adblock.txt b/src/assets/thirdparties/home.fredfiber.no/langsholt/adblock.txt
index f2a4e90..f2a4e90 100644
--- a/assets/thirdparties/home.fredfiber.no/langsholt/adblock.txt
+++ b/src/assets/thirdparties/home.fredfiber.no/langsholt/adblock.txt
diff --git a/assets/thirdparties/hosts-file.net/ad-servers b/src/assets/thirdparties/hosts-file.net/ad-servers
index 9ae2519..9ae2519 100644
--- a/assets/thirdparties/hosts-file.net/ad-servers
+++ b/src/assets/thirdparties/hosts-file.net/ad-servers
diff --git a/assets/thirdparties/indonesianadblockrules.googlecode.com/hg/subscriptions/abpindo.txt b/src/assets/thirdparties/indonesianadblockrules.googlecode.com/hg/subscriptions/abpindo.txt
index 70d8201..70d8201 100644
--- a/assets/thirdparties/indonesianadblockrules.googlecode.com/hg/subscriptions/abpindo.txt
+++ b/src/assets/thirdparties/indonesianadblockrules.googlecode.com/hg/subscriptions/abpindo.txt
diff --git a/assets/thirdparties/liste-ar-adblock.googlecode.com/hg/Liste_AR.txt b/src/assets/thirdparties/liste-ar-adblock.googlecode.com/hg/Liste_AR.txt
index 3767bfc..3767bfc 100644
--- a/assets/thirdparties/liste-ar-adblock.googlecode.com/hg/Liste_AR.txt
+++ b/src/assets/thirdparties/liste-ar-adblock.googlecode.com/hg/Liste_AR.txt
diff --git a/assets/thirdparties/margevicius.lt/easylistlithuania.txt b/src/assets/thirdparties/margevicius.lt/easylistlithuania.txt
index 5b326d0..5b326d0 100644
--- a/assets/thirdparties/margevicius.lt/easylistlithuania.txt
+++ b/src/assets/thirdparties/margevicius.lt/easylistlithuania.txt
diff --git a/assets/thirdparties/mirror1.malwaredomains.com/files/README.md b/src/assets/thirdparties/mirror1.malwaredomains.com/files/README.md
index 0a9ac6a..0a9ac6a 100644
--- a/assets/thirdparties/mirror1.malwaredomains.com/files/README.md
+++ b/src/assets/thirdparties/mirror1.malwaredomains.com/files/README.md
diff --git a/assets/thirdparties/mirror1.malwaredomains.com/files/immortal_domains.txt b/src/assets/thirdparties/mirror1.malwaredomains.com/files/immortal_domains.txt
index 59d7a57..59d7a57 100644
--- a/assets/thirdparties/mirror1.malwaredomains.com/files/immortal_domains.txt
+++ b/src/assets/thirdparties/mirror1.malwaredomains.com/files/immortal_domains.txt
diff --git a/assets/thirdparties/mirror1.malwaredomains.com/files/justdomains b/src/assets/thirdparties/mirror1.malwaredomains.com/files/justdomains
index c1b8013..c1b8013 100644
--- a/assets/thirdparties/mirror1.malwaredomains.com/files/justdomains
+++ b/src/assets/thirdparties/mirror1.malwaredomains.com/files/justdomains
diff --git a/assets/thirdparties/pgl.yoyo.org/as/README.md b/src/assets/thirdparties/pgl.yoyo.org/as/README.md
index 18d17ad..18d17ad 100644
--- a/assets/thirdparties/pgl.yoyo.org/as/README.md
+++ b/src/assets/thirdparties/pgl.yoyo.org/as/README.md
diff --git a/assets/thirdparties/pgl.yoyo.org/as/serverlist b/src/assets/thirdparties/pgl.yoyo.org/as/serverlist
index 45e9b71..45e9b71 100644
--- a/assets/thirdparties/pgl.yoyo.org/as/serverlist
+++ b/src/assets/thirdparties/pgl.yoyo.org/as/serverlist
diff --git a/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat b/src/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat
index 8ae5d97..8ae5d97 100644
--- a/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat
+++ b/src/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat
diff --git a/assets/thirdparties/raw.githubusercontent.com/AdBlockPlusIsrael/EasyListHebrew/master/EasyListHebrew.txt b/src/assets/thirdparties/raw.githubusercontent.com/AdBlockPlusIsrael/EasyListHebrew/master/EasyListHebrew.txt
index 705c4f9..705c4f9 100644
--- a/assets/thirdparties/raw.githubusercontent.com/AdBlockPlusIsrael/EasyListHebrew/master/EasyListHebrew.txt
+++ b/src/assets/thirdparties/raw.githubusercontent.com/AdBlockPlusIsrael/EasyListHebrew/master/EasyListHebrew.txt
diff --git a/assets/thirdparties/raw.githubusercontent.com/adblockpolska/Adblock_PL_List/master/adblock_polska.txt b/src/assets/thirdparties/raw.githubusercontent.com/adblockpolska/Adblock_PL_List/master/adblock_polska.txt
index dc4cafb..dc4cafb 100644
--- a/assets/thirdparties/raw.githubusercontent.com/adblockpolska/Adblock_PL_List/master/adblock_polska.txt
+++ b/src/assets/thirdparties/raw.githubusercontent.com/adblockpolska/Adblock_PL_List/master/adblock_polska.txt
diff --git a/assets/thirdparties/raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt b/src/assets/thirdparties/raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt
index 5d4e3df..5d4e3df 100644
--- a/assets/thirdparties/raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt
+++ b/src/assets/thirdparties/raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt
diff --git a/assets/thirdparties/raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt b/src/assets/thirdparties/raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt
index f8d1104..f8d1104 100644
--- a/assets/thirdparties/raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt
+++ b/src/assets/thirdparties/raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt
diff --git a/assets/thirdparties/raw.githubusercontent.com/wiltteri/wiltteri.txt/master/wiltteri.txt b/src/assets/thirdparties/raw.githubusercontent.com/wiltteri/wiltteri.txt/master/wiltteri.txt
index af49005..af49005 100644
--- a/assets/thirdparties/raw.githubusercontent.com/wiltteri/wiltteri.txt/master/wiltteri.txt
+++ b/src/assets/thirdparties/raw.githubusercontent.com/wiltteri/wiltteri.txt/master/wiltteri.txt
diff --git a/assets/thirdparties/someonewhocares.org/hosts/hosts b/src/assets/thirdparties/someonewhocares.org/hosts/hosts
index 841d13d..841d13d 100644
--- a/assets/thirdparties/someonewhocares.org/hosts/hosts
+++ b/src/assets/thirdparties/someonewhocares.org/hosts/hosts
diff --git a/assets/thirdparties/spam404bl.com/spam404scamlist.txt b/src/assets/thirdparties/spam404bl.com/spam404scamlist.txt
index c201efa..c201efa 100644
--- a/assets/thirdparties/spam404bl.com/spam404scamlist.txt
+++ b/src/assets/thirdparties/spam404bl.com/spam404scamlist.txt
diff --git a/assets/thirdparties/stanev.org/abp/adblock_bg.txt b/src/assets/thirdparties/stanev.org/abp/adblock_bg.txt
index b661d8d..b661d8d 100644
--- a/assets/thirdparties/stanev.org/abp/adblock_bg.txt
+++ b/src/assets/thirdparties/stanev.org/abp/adblock_bg.txt
diff --git a/assets/thirdparties/winhelp2002.mvps.org/hosts.txt b/src/assets/thirdparties/winhelp2002.mvps.org/hosts.txt
index e608435..e608435 100644
--- a/assets/thirdparties/winhelp2002.mvps.org/hosts.txt
+++ b/src/assets/thirdparties/winhelp2002.mvps.org/hosts.txt
diff --git a/assets/thirdparties/www.fanboy.co.nz/enhancedstats.txt b/src/assets/thirdparties/www.fanboy.co.nz/enhancedstats.txt
index 2fba203..2fba203 100644
--- a/assets/thirdparties/www.fanboy.co.nz/enhancedstats.txt
+++ b/src/assets/thirdparties/www.fanboy.co.nz/enhancedstats.txt
diff --git a/assets/thirdparties/www.fanboy.co.nz/fanboy-antifacebook.txt b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-antifacebook.txt
index 9f3c9bd..9f3c9bd 100644
--- a/assets/thirdparties/www.fanboy.co.nz/fanboy-antifacebook.txt
+++ b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-antifacebook.txt
diff --git a/assets/thirdparties/www.fanboy.co.nz/fanboy-swedish.txt b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-swedish.txt
index 42f301a..42f301a 100644
--- a/assets/thirdparties/www.fanboy.co.nz/fanboy-swedish.txt
+++ b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-swedish.txt
diff --git a/assets/thirdparties/www.fanboy.co.nz/fanboy-ultimate.txt b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-ultimate.txt
index 2aaef3d..2aaef3d 100644
--- a/assets/thirdparties/www.fanboy.co.nz/fanboy-ultimate.txt
+++ b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-ultimate.txt
diff --git a/assets/thirdparties/www.fanboy.co.nz/fanboy-vietnam.txt b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-vietnam.txt
index 921ee42..921ee42 100644
--- a/assets/thirdparties/www.fanboy.co.nz/fanboy-vietnam.txt
+++ b/src/assets/thirdparties/www.fanboy.co.nz/fanboy-vietnam.txt
diff --git a/assets/thirdparties/www.hufilter.hu/hufilter.txt b/src/assets/thirdparties/www.hufilter.hu/hufilter.txt
index b60d4b0..b60d4b0 100644
--- a/assets/thirdparties/www.hufilter.hu/hufilter.txt
+++ b/src/assets/thirdparties/www.hufilter.hu/hufilter.txt
diff --git a/assets/thirdparties/www.malwaredomainlist.com/hostslist/README.md b/src/assets/thirdparties/www.malwaredomainlist.com/hostslist/README.md
index 99891af..99891af 100644
--- a/assets/thirdparties/www.malwaredomainlist.com/hostslist/README.md
+++ b/src/assets/thirdparties/www.malwaredomainlist.com/hostslist/README.md
diff --git a/assets/thirdparties/www.malwaredomainlist.com/hostslist/hosts.txt b/src/assets/thirdparties/www.malwaredomainlist.com/hostslist/hosts.txt
index 96d42e4..96d42e4 100644
--- a/assets/thirdparties/www.malwaredomainlist.com/hostslist/hosts.txt
+++ b/src/assets/thirdparties/www.malwaredomainlist.com/hostslist/hosts.txt
diff --git a/assets/thirdparties/www.void.gr/kargig/void-gr-filters.txt b/src/assets/thirdparties/www.void.gr/kargig/void-gr-filters.txt
index 0ac01ea..0ac01ea 100644
--- a/assets/thirdparties/www.void.gr/kargig/void-gr-filters.txt
+++ b/src/assets/thirdparties/www.void.gr/kargig/void-gr-filters.txt
diff --git a/assets/ublock/filter-lists.json b/src/assets/ublock/filter-lists.json
index 40c5de9..40c5de9 100644
--- a/assets/ublock/filter-lists.json
+++ b/src/assets/ublock/filter-lists.json
diff --git a/assets/ublock/filters.txt b/src/assets/ublock/filters.txt
index 8975e64..8975e64 100644
--- a/assets/ublock/filters.txt
+++ b/src/assets/ublock/filters.txt
diff --git a/assets/ublock/mirror-candidates.txt b/src/assets/ublock/mirror-candidates.txt
index 69568a8..69568a8 100644
--- a/assets/ublock/mirror-candidates.txt
+++ b/src/assets/ublock/mirror-candidates.txt
diff --git a/assets/ublock/privacy.txt b/src/assets/ublock/privacy.txt
index c616c29..c616c29 100644
--- a/assets/ublock/privacy.txt
+++ b/src/assets/ublock/privacy.txt
diff --git a/assets/update-3rdparties.sh b/src/assets/update-3rdparties.sh
index eab1ff3..eab1ff3 100755..100644
--- a/assets/update-3rdparties.sh
+++ b/src/assets/update-3rdparties.sh
diff --git a/assets/update-checksums.sh b/src/assets/update-checksums.sh
index b42e291..b42e291 100755..100644
--- a/assets/update-checksums.sh
+++ b/src/assets/update-checksums.sh
diff --git a/assets/update-git.sh b/src/assets/update-git.sh
index 282ae90..282ae90 100755..100644
--- a/assets/update-git.sh
+++ b/src/assets/update-git.sh
diff --git a/background.html b/src/background.html
index f106c01..438d2b4 100644
--- a/background.html
+++ b/src/background.html
@@ -8,6 +8,8 @@
<script src="lib/punycode.min.js"></script>
<script src="lib/publicsuffixlist.min.js"></script>
<script src="lib/yamd5.js"></script>
+<script src="js/vapi-common.js"></script>
+<script src="js/vapi-background.js"></script>
<script src="js/background.js"></script>
<script src="js/xal.js"></script>
<script src="js/async.js"></script>
@@ -24,7 +26,6 @@
<script src="js/uritools.js"></script>
<script src="js/tab.js"></script>
<script src="js/traffic.js"></script>
-<script src="js/messaging-handlers.js"></script>
<script src="js/contextmenu.js"></script>
<script src="js/mirrors.js"></script>
<script src="js/start.js"></script>
diff --git a/css/1p-filters.css b/src/css/1p-filters.css
index 8413e6b..8413e6b 100644
--- a/css/1p-filters.css
+++ b/src/css/1p-filters.css
diff --git a/css/3p-filters.css b/src/css/3p-filters.css
index 9e3b009..9e3b009 100644
--- a/css/3p-filters.css
+++ b/src/css/3p-filters.css
diff --git a/css/about.css b/src/css/about.css
index 1d682b2..1d682b2 100644
--- a/css/about.css
+++ b/src/css/about.css
diff --git a/css/common.css b/src/css/common.css
index 3c28d36..391478f 100644
--- a/css/common.css
+++ b/src/css/common.css
@@ -32,7 +32,7 @@
font: 11px sans-serif;
left: 0;
line-height: 130%;
- min-width: 55vw;
+ min-width: 55%;
padding: 4px 6px;
position: absolute;
text-align: __MSG_@@bidi_start_edge__;
@@ -45,7 +45,7 @@
*[data-tip][data-tip-anchor="top"]:hover:after {
bottom: 105%;
__MSG_@@bidi_start_edge__: auto;
- __MSG_@@bidi_end_edge__: -10vw;
+ __MSG_@@bidi_end_edge__: -10%;
top: auto;
}
@keyframes tooltip {
diff --git a/css/dashboard-common.css b/src/css/dashboard-common.css
index db2dca1..4ec0ef6 100644
--- a/css/dashboard-common.css
+++ b/src/css/dashboard-common.css
@@ -44,9 +44,10 @@ div > p:last-child {
padding: 0 0 4px 0;
width: 16px;
height: 16px;
- background: url('/img/help16.png') no-repeat right bottom 1px;
+ background: url('../img/help16.png') no-repeat;
cursor: pointer;
opacity: 0.5;
+ vertical-align: middle;
}
.whatisthis:hover {
opacity: 1.0;
diff --git a/css/fonts/OFL.txt b/src/css/fonts/OFL.txt
index f1a20ac..f1a20ac 100644
--- a/css/fonts/OFL.txt
+++ b/src/css/fonts/OFL.txt
diff --git a/css/fonts/fontawesome-webfont.ttf b/src/css/fonts/fontawesome-webfont.ttf
index 96a3639..96a3639 100644
--- a/css/fonts/fontawesome-webfont.ttf
+++ b/src/css/fonts/fontawesome-webfont.ttf
Binary files differ
diff --git a/css/popup.css b/src/css/popup.css
index 4dcce83..794cfef 100644
--- a/css/popup.css
+++ b/src/css/popup.css
@@ -6,6 +6,8 @@ body {
background-color: white;
direction: __MSG_@@bidi_dir__;
min-width: 180px;
+ overflow: hidden;
+ display: inline-block;
}
h1,h2,h3,h4 {
margin: 0;
@@ -27,7 +29,7 @@ a {
margin-left: 1em;
font-weight: normal;
font-size: 11px;
- }
+ }
body > div {
padding: 4px 12px 0 12px;
}
@@ -77,12 +79,12 @@ p {
.tool:hover {
color: #444;
}
-
+
#dynamicFilteringToggler {
margin: 0;
border: 0;
padding: 0;
- width: 100vw;
+ width: 100%;
text-align: center;
cursor: pointer;
position: relative;
@@ -93,7 +95,7 @@ p {
color: #aaa;
position: absolute;
bottom: 0;
- width: 25vw;
+ width: 25%;
display: none;
pointer-events: none;
}
@@ -104,13 +106,13 @@ p {
left: 0;
}
#dynamicFilteringToggler > div:nth-of-type(2) {
- left: 25vw;
+ left: 25%;
}
#dynamicFilteringToggler > div:nth-of-type(3) {
- left: 50vw;
+ left: 50%;
}
#dynamicFilteringToggler > div:nth-of-type(4) {
- left: 75vw;
+ left: 75%;
}
#dynamicFilteringToggler a {
padding: 0 2px 0 8px;
@@ -167,36 +169,36 @@ p {
}
.dynamicFiltering > div:nth-of-type(1) {
left: 0;
- width: 7vw;
+ width: 7%;
height: 100%;
}
.dynamicFiltering > div:nth-of-type(2) {
- left: 7vw;
- width: 18vw;
+ left: 7%;
+ width: 18%;
height: 100%;
}
.dynamicFiltering > div:nth-of-type(3) {
- left: 25vw;
- width: 25vw;
+ left: 25%;
+ width: 25%;
height: 100%;
}
.dynamicFiltering > div:nth-of-type(4) {
- left: 50vw;
- width: 25vw;
+ left: 50%;
+ width: 25%;
height: 100%;
}
.dynamicFiltering > div:nth-of-type(5) {
- left: 75vw;
- width: 25vw;
+ left: 75%;
+ width: 25%;
height: 100%;
}
.dynamicFiltering > div:nth-of-type(6) {
left: 0;
- width: 50vw;
+ width: 50%;
}
.dynamicFiltering > div:nth-of-type(7) {
- left: 50vw;
- width: 50vw;
+ left: 50%;
+ width: 50%;
}
.dynamicFiltering > div.label {
margin: 0;
@@ -208,6 +210,7 @@ p {
font: 12px monospace;
text-align: center;
top: 50%;
+ -webkit-transform: translateY(-50%);
transform: translateY(-50%);
background-color: transparent;
}
diff --git a/css/whitelist.css b/src/css/whitelist.css
index 96030cd..96030cd 100644
--- a/css/whitelist.css
+++ b/src/css/whitelist.css
diff --git a/dashboard.html b/src/dashboard.html
index b1e8001..7dbaef9 100644
--- a/dashboard.html
+++ b/src/dashboard.html
@@ -4,14 +4,14 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title data-i18n="dashboardName"></title>
<style>
-body {
+html, body {
margin: 0;
border: 0;
padding: 0;
font: 15px httpsb,sans-serif;
position: relative;
- width: 100vw;
- height: 100vh;
+ width: 100%;
+ height: 100%;
overflow: hidden;
}
#dashboard-nav {
@@ -19,15 +19,15 @@ body {
border: 0;
padding: 0;
position: absolute;
+ width: 100%;
top: 0;
- width: 100vw;
height: 50px;
z-index: 10;
}
#dashboard-nav-widgets {
margin: 0;
border-bottom: 1px solid #ccc;
- padding: 4px 0 0 0;
+ padding: 4px 0 0;
white-space: nowrap;
background-color: white;
}
@@ -67,11 +67,10 @@ iframe {
border: 0;
padding: 0;
background-color: transparent;
- overflow: auto;
- position: absolute;
- top: 50px;
width: 100%;
- height: calc(100% - 50px);
+ height: 100%;
+ border-top: 50px solid transparent;
+ box-sizing: border-box;
}
</style>
<link href='css/common.css' rel='stylesheet' type='text/css'>
@@ -92,8 +91,12 @@ iframe {
<iframe src=""></iframe>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/dashboard.js"></script>
+<script src="js/js-loader.js" data-jsList="
+js/vapi-common.js
+js/udom.js
+js/i18n.js
+js/dashboard.js
+"></script>
+
</body>
</html>
diff --git a/img/icon_128.png b/src/icon.png
index 165e37d..165e37d 100644
--- a/img/icon_128.png
+++ b/src/icon.png
Binary files differ
diff --git a/img/browsericons/icon19-off.png b/src/img/browsericons/icon19-off.png
index f978164..f978164 100644
--- a/img/browsericons/icon19-off.png
+++ b/src/img/browsericons/icon19-off.png
Binary files differ
diff --git a/img/browsericons/icon19.png b/src/img/browsericons/icon19.png
index 53a7250..53a7250 100644
--- a/img/browsericons/icon19.png
+++ b/src/img/browsericons/icon19.png
Binary files differ
diff --git a/img/browsericons/icon38-off.png b/src/img/browsericons/icon38-off.png
index 8932c9c..8932c9c 100644
--- a/img/browsericons/icon38-off.png
+++ b/src/img/browsericons/icon38-off.png
Binary files differ
diff --git a/img/browsericons/icon38.png b/src/img/browsericons/icon38.png
index ebbe79d..ebbe79d 100644
--- a/img/browsericons/icon38.png
+++ b/src/img/browsericons/icon38.png
Binary files differ
diff --git a/img/help16.png b/src/img/help16.png
index 4bfac0b..4bfac0b 100644
--- a/img/help16.png
+++ b/src/img/help16.png
Binary files differ
diff --git a/src/img/icon_128.png b/src/img/icon_128.png
new file mode 100644
index 0000000..165e37d
--- /dev/null
+++ b/src/img/icon_128.png
Binary files differ
diff --git a/img/icon_16.png b/src/img/icon_16.png
index 8ab836f..8ab836f 100644
--- a/img/icon_16.png
+++ b/src/img/icon_16.png
Binary files differ
diff --git a/img/ublock.svg b/src/img/ublock.svg
index 963b3cd..963b3cd 100644
--- a/img/ublock.svg
+++ b/src/img/ublock.svg
diff --git a/js/1p-filters.js b/src/js/1p-filters.js
index 037692c..4dae5e8 100644
--- a/js/1p-filters.js
+++ b/src/js/1p-filters.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, messaging, uDom */
+/* global chrome, vAPI, uDom */
/******************************************************************************/
@@ -31,7 +31,7 @@ var cachedUserFilters = '';
/******************************************************************************/
-messaging.start('1p-filters.js');
+var messager = vAPI.messaging.channel('1p-filters.js');
/******************************************************************************/
@@ -54,13 +54,13 @@ function renderUserFilters() {
cachedUserFilters = details.content.trim();
uDom('#userFilters').val(details.content);
};
- messaging.ask({ what: 'readUserFilters' }, onRead);
+ messager.send({ what: 'readUserFilters' }, onRead);
}
/******************************************************************************/
function allFiltersApplyHandler() {
- messaging.tell({ what: 'reloadAllFilters' });
+ messager.send({ what: 'reloadAllFilters' });
uDom('#userFiltersApply').prop('disabled', true );
}
@@ -120,7 +120,7 @@ function userFiltersApplyHandler() {
what: 'writeUserFilters',
content: uDom('#userFilters').val()
};
- messaging.ask(request, onWritten);
+ messager.send(request, onWritten);
}
/******************************************************************************/
diff --git a/js/3p-filters.js b/src/js/3p-filters.js
index 0f1cb58..9bd92c0 100644
--- a/js/3p-filters.js
+++ b/src/js/3p-filters.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, messaging, uDom */
+/* global vAPI, uDom */
/******************************************************************************/
@@ -27,7 +27,7 @@
/******************************************************************************/
-var userListName = chrome.i18n.getMessage('1pPageName');
+var userListName = vAPI.i18n('1pPageName');
var listDetails = {};
var cosmeticSwitch = true;
var externalLists = '';
@@ -40,8 +40,6 @@ var re3rdPartyRepoAsset = /^assets\/thirdparties\/([^\/]+)/;
/******************************************************************************/
-messaging.start('3p-filters.js');
-
var onMessage = function(msg) {
switch ( msg.what ) {
case 'loadUbiquitousBlacklistCompleted':
@@ -53,13 +51,7 @@ var onMessage = function(msg) {
}
};
-messaging.listen(onMessage);
-
-/******************************************************************************/
-
-var getµb = function() {
- return chrome.extension.getBackgroundPage().µBlock;
-};
+var messager = vAPI.messaging.channel('3p-filters.js', onMessage);
/******************************************************************************/
@@ -74,8 +66,6 @@ var renderNumber = function(value) {
var renderBlacklists = function() {
uDom('body').toggleClass('busy', true);
- var µb = getµb();
-
// Assemble a pretty blacklist name if possible
var listNameFromListKey = function(listKey) {
if ( listKey === listDetails.userFiltersPath ) {
@@ -99,7 +89,7 @@ var renderBlacklists = function() {
return '';
}
var hostname = matches[1];
- var domain = µb.URI.domainFromHostname(hostname);
+ var domain = µBlock.URI.domainFromHostname(hostname);
if ( domain === '' ) {
return '';
}
@@ -113,9 +103,9 @@ var renderBlacklists = function() {
return html.join('');
};
- var purgeButtontext = chrome.i18n.getMessage('3pExternalListPurge');
- var updateButtontext = chrome.i18n.getMessage('3pExternalListNew');
- var obsoleteButtontext = chrome.i18n.getMessage('3pExternalListObsolete');
+ var purgeButtontext = vAPI.i18n('3pExternalListPurge');
+ var updateButtontext = vAPI.i18n('3pExternalListNew');
+ var obsoleteButtontext = vAPI.i18n('3pExternalListObsolete');
var liTemplate = [
'<li class="listDetails">',
'<input type="checkbox" {{checked}}>',
@@ -126,7 +116,7 @@ var renderBlacklists = function() {
'{{homeURL}}',
': ',
'<span class="dim">',
- chrome.i18n.getMessage('3pListsOfBlockedHostsPerListStats'),
+ vAPI.i18n('3pListsOfBlockedHostsPerListStats'),
'</span>'
].join('');
@@ -177,14 +167,14 @@ var renderBlacklists = function() {
var htmlFromBranch = function(groupKey, listKeys) {
var html = [
'<li>',
- chrome.i18n.getMessage('3pGroup' + groupKey.charAt(0).toUpperCase() + groupKey.slice(1)),
+ vAPI.i18n('3pGroup' + groupKey.charAt(0).toUpperCase() + groupKey.slice(1)),
'<ul>'
];
if ( !listKeys ) {
return html.join('');
}
listKeys.sort(function(a, b) {
- return listDetails.available[a].title.localeCompare(listDetails.available[b].title);
+ return (listDetails.available[a].title || "").localeCompare(listDetails.available[b].title || "");
});
for ( var i = 0; i < listKeys.length; i++ ) {
html.push(htmlFromLeaf(listKeys[i]));
@@ -247,7 +237,7 @@ var renderBlacklists = function() {
}
uDom('#listsOfBlockedHostsPrompt').text(
- chrome.i18n.getMessage('3pListsOfBlockedHostsPrompt')
+ vAPI.i18n('3pListsOfBlockedHostsPrompt')
.replace('{{netFilterCount}}', renderNumber(details.netFilterCount))
.replace('{{cosmeticFilterCount}}', renderNumber(details.cosmeticFilterCount))
);
@@ -259,7 +249,7 @@ var renderBlacklists = function() {
updateWidgets();
};
- messaging.ask({ what: 'getLists' }, onListsReceived);
+ messager.send({ what: 'getLists' }, onListsReceived);
};
/******************************************************************************/
@@ -337,9 +327,13 @@ var onListCheckboxChanged = function() {
/******************************************************************************/
var onListLinkClicked = function(ev) {
- messaging.tell({
- what: 'gotoExtensionURL',
- url: 'asset-viewer.html?url=' + uDom(this).attr('href')
+ messager.send({
+ what: 'gotoURL',
+ details: {
+ url: 'asset-viewer.html?url=' + uDom(this).attr('href'),
+ select: true,
+ index: -1
+ }
});
ev.preventDefault();
};
@@ -353,7 +347,7 @@ var onPurgeClicked = function() {
if ( !href ) {
return;
}
- messaging.tell({ what: 'purgeCache', path: href });
+ messager.send({ what: 'purgeCache', path: href });
button.remove();
if ( li.descendants('input').first().prop('checked') ) {
cacheWasPurged = true;
@@ -369,7 +363,7 @@ var reloadAll = function(update) {
uDom('body').toggleClass('busy', true);
// Reload blacklists
- messaging.tell({
+ messager.send({
what: 'userSettings',
name: 'parseAllABPHideFilters',
value: listDetails.cosmetic
@@ -389,7 +383,7 @@ var reloadAll = function(update) {
off: lis.subset(i, 1).descendants('input').prop('checked') === false
});
}
- messaging.tell({
+ messager.send({
what: 'reloadAllFilters',
switches: switches,
update: update
@@ -418,13 +412,13 @@ var buttonPurgeAllHandler = function() {
var onCompleted = function() {
renderBlacklists();
};
- messaging.ask({ what: 'purgeAllCaches' }, onCompleted);
+ messager.send({ what: 'purgeAllCaches' }, onCompleted);
};
/******************************************************************************/
var autoUpdateCheckboxChanged = function() {
- messaging.tell({
+ messager.send({
what: 'userSettings',
name: 'autoUpdate',
value: this.checked
@@ -445,7 +439,7 @@ var renderExternalLists = function() {
uDom('#externalLists').val(details);
externalLists = details;
};
- messaging.ask({ what: 'userSettings', name: 'externalLists' }, onReceived);
+ messager.send({ what: 'userSettings', name: 'externalLists' }, onReceived);
};
/******************************************************************************/
@@ -461,7 +455,7 @@ var externalListsChangeHandler = function() {
var externalListsApplyHandler = function() {
externalLists = uDom('#externalLists').val();
- messaging.tell({
+ messager.send({
what: 'userSettings',
name: 'externalLists',
value: externalLists
diff --git a/js/about.js b/src/js/about.js
index 4dcb575..bd1b180 100644
--- a/js/about.js
+++ b/src/js/about.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, messaging, uDom */
+/* global µBlock, uDom */
/******************************************************************************/
@@ -27,7 +27,7 @@ uDom.onLoad(function() {
/******************************************************************************/
-messaging.start('about.js');
+var messager = vAPI.messaging.channel('about.js');
/******************************************************************************/
@@ -37,10 +37,10 @@ var exportToFile = function() {
'url': 'data:text/plain,' + encodeURIComponent(JSON.stringify(userData)),
'filename': 'ublock-backup.txt',
'saveAs': true
- });
+});
};
- messaging.ask({ what: 'getUserData' }, onUserDataReady);
+ messager.send({ what: 'getUserData' }, onUserDataReady);
};
/******************************************************************************/
@@ -57,12 +57,11 @@ var handleImportFilePicker = function() {
return;
}
var time = new Date(userData.timeStamp);
- var msg = chrome.i18n
- .getMessage('aboutRestoreDataConfirm')
+ var msg = vAPI.i18n('aboutRestoreDataConfirm')
.replace('{{time}}', time.toLocaleString());
var proceed = window.confirm(msg);
if ( proceed ) {
- messaging.tell({ what: 'restoreUserData', userData: userData });
+ messager.send({ what: 'restoreUserData', userData: userData });
}
};
@@ -92,20 +91,20 @@ var startImportFilePicker = function() {
/******************************************************************************/
var resetUserData = function() {
- var msg = chrome.i18n.getMessage('aboutResetDataConfirm');
+ var msg = vAPI.i18n('aboutResetDataConfirm');
var proceed = window.confirm(msg);
if ( proceed ) {
- messaging.tell({ what: 'resetUserData' });
+ messager.send({ what: 'resetUserData' });
}
};
/******************************************************************************/
-uDom('#aboutVersion').html(chrome.runtime.getManifest().version);
uDom('#export').on('click', exportToFile);
uDom('#import').on('click', startImportFilePicker);
uDom('#reset').on('click', resetUserData);
uDom('#restoreFilePicker').on('change', handleImportFilePicker);
+uDom('#aboutVersion').html(µBlock.version);
/******************************************************************************/
diff --git a/js/asset-viewer.js b/src/js/asset-viewer.js
index 7614959..2167ac8 100644
--- a/js/asset-viewer.js
+++ b/src/js/asset-viewer.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, messaging, uDom */
+/* global chrome, vAPI, uDom */
/******************************************************************************/
@@ -27,7 +27,7 @@
/******************************************************************************/
-messaging.start('asset-viewer.js');
+var messager = vAPI.messaging.channel('asset-viewer.js');
/******************************************************************************/
@@ -43,7 +43,7 @@ if ( !matches || matches.length !== 2 ) {
return;
}
-messaging.ask({ what : 'getAssetContent', url: matches[1] }, onAssetContentReceived);
+messager.send({ what : 'getAssetContent', url: matches[1] }, onAssetContentReceived);
/******************************************************************************/
diff --git a/js/assets.js b/src/js/assets.js
index 26f881a..288ffc2 100644
--- a/js/assets.js
+++ b/src/js/assets.js
@@ -57,8 +57,8 @@ var reIsUserPath = /^assets\/user\//;
var lastRepoMetaTimestamp = 0;
var refreshRepoMetaPeriod = 5 * oneHour;
-// TODO: move chrome.i18n.getMessage to XAL
-var errorCantConnectTo = chrome.i18n.getMessage('errorCantConnectTo');
+// TODO: move vAPI.i18n to XAL
+var errorCantConnectTo = vAPI.i18n('errorCantConnectTo');
var exports = {
autoUpdate: true,
@@ -96,10 +96,10 @@ var cachedAssetsManager = (function() {
// Flush cached non-user assets if these are from a prior version.
// https://github.com/gorhill/httpswitchboard/issues/212
var onLastVersionRead = function(store) {
- var currentVersion = chrome.runtime.getManifest().version;
+ var currentVersion = µBlock.version;
var lastVersion = store.extensionLastVersion || '0.0.0.0';
if ( currentVersion !== lastVersion ) {
- chrome.storage.local.set({ 'extensionLastVersion': currentVersion });
+ vAPI.storage.set({ 'extensionLastVersion': currentVersion });
exports.remove(/^assets\/(ublock|thirdparties)\//);
exports.remove('assets/checksums.txt');
}
@@ -107,7 +107,7 @@ var cachedAssetsManager = (function() {
};
var onLoaded = function(bin) {
// https://github.com/gorhill/httpswitchboard/issues/381
- // Maybe the index was requested multiple times and already
+ // Maybe the index was requested multiple times and already
// fetched by one of the occurrences.
if ( entries === null ) {
if ( chrome.runtime.lastError ) {
@@ -118,9 +118,9 @@ var cachedAssetsManager = (function() {
}
entries = bin.cached_asset_entries || {};
}
- chrome.storage.local.get('extensionLastVersion', onLastVersionRead);
+ vAPI.storage.get('extensionLastVersion', onLastVersionRead);
};
- chrome.storage.local.get('cached_asset_entries', onLoaded);
+ vAPI.storage.get('cached_asset_entries', onLoaded);
};
exports.entries = getEntries;
@@ -148,7 +148,7 @@ var cachedAssetsManager = (function() {
cbError(details);
return;
}
- chrome.storage.local.get(cachedContentPath, onLoaded);
+ vAPI.storage.get(cachedContentPath, onLoaded);
};
getEntries(onEntries);
};
@@ -175,7 +175,7 @@ var cachedAssetsManager = (function() {
var onEntries = function(entries) {
entries[path] = Date.now();
bin.cached_asset_entries = entries;
- chrome.storage.local.set(bin, onSaved);
+ vAPI.storage.set(bin, onSaved);
};
getEntries(onEntries);
};
@@ -201,8 +201,8 @@ var cachedAssetsManager = (function() {
delete entries[path];
}
if ( keystoRemove.length ) {
- chrome.storage.local.remove(keystoRemove);
- chrome.storage.local.set({ 'cached_asset_entries': entries });
+ vAPI.storage.remove(keystoRemove);
+ vAPI.storage.set({ 'cached_asset_entries': entries });
}
};
getEntries(onEntries);
@@ -235,12 +235,12 @@ var getTextFileFromURL = function(url, onLoad, onError) {
};
// console.log('µBlock> getTextFileFromURL("%s"):', url);
var xhr = new XMLHttpRequest();
- xhr.responseType = 'text';
+ xhr.open('get', url, true);
xhr.timeout = 15000;
xhr.onload = onResponseReceived;
xhr.onerror = onError;
xhr.ontimeout = onError;
- xhr.open('get', url, true);
+ xhr.responseType = 'text';
xhr.send();
};
@@ -427,7 +427,7 @@ var readLocalFile = function(path, callback) {
reportBack('');
return;
}
- getTextFileFromURL(chrome.runtime.getURL(details.path), onInstallFileLoaded, onInstallFileError);
+ getTextFileFromURL(vAPI.getURL(details.path), onInstallFileLoaded, onInstallFileError);
};
cachedAssetsManager.load(path, onCachedContentLoaded, onCachedContentError);
@@ -480,7 +480,7 @@ var readRepoFile = function(path, callback) {
// An asset from an external source with a copy shipped with the extension:
// Path --> starts with 'assets/(thirdparties|ublock)/', with a home URL
-// External -->
+// External -->
// Repository --> has checksum (to detect need for update only)
// Cache --> has expiration timestamp (in cache)
// Local --> install time version
@@ -525,7 +525,7 @@ var readRepoCopyAsset = function(path, callback) {
var onCachedContentError = function(details) {
//console.log('µBlock> readRepoCopyAsset("%s") / onCacheFileError()', path);
- getTextFileFromURL(chrome.runtime.getURL(details.path), onInstallFileLoaded, onInstallFileError);
+ getTextFileFromURL(vAPI.getURL(details.path), onInstallFileLoaded, onInstallFileError);
};
var repositoryURL = repositoryRoot + path;
@@ -598,7 +598,7 @@ var readRepoCopyAsset = function(path, callback) {
}
// Not in cache
- getTextFileFromURL(chrome.runtime.getURL(path), onInstallFileLoaded, onInstallFileError);
+ getTextFileFromURL(vAPI.getURL(path), onInstallFileLoaded, onInstallFileError);
};
var onRepoMetaReady = function(meta) {
@@ -633,7 +633,7 @@ var readRepoCopyAsset = function(path, callback) {
/******************************************************************************/
-// An important asset shipped with the extension -- typically small, or
+// An important asset shipped with the extension -- typically small, or
// doesn't change often:
// Path --> starts with 'assets/(thirdparties|ublock)/', without a home URL
// Repository --> has checksum (to detect need for update and corruption)
@@ -674,7 +674,7 @@ var readRepoOnlyAsset = function(path, callback) {
var onCachedContentError = function() {
//console.log('µBlock> readRepoOnlyAsset("%s") / onCachedContentError()', path);
- getTextFileFromURL(chrome.runtime.getURL(path), onInstallFileLoaded, onInstallFileError);
+ getTextFileFromURL(vAPI.getURL(path), onInstallFileLoaded, onInstallFileError);
};
var repositoryURL = repositoryRoot + path + '?ublock=' + Date.now();
@@ -783,7 +783,7 @@ var readExternalAsset = function(path, callback) {
var onCacheMetaReady = function(entries) {
// Fetch from remote if:
// - Not in cache OR
- //
+ //
// - Auto-update enabled AND in cache but obsolete
var timestamp = entries[path];
var obsolete = Date.now() - exports.autoUpdateDelay;
@@ -825,7 +825,7 @@ var readUserAsset = function(path, callback) {
//
// A copy of an asset from an external source shipped with the extension:
// Path --> starts with 'assets/(thirdparties|ublock)/', with a home URL
-// External -->
+// External -->
// Repository --> has checksum (to detect obsolescence)
// Cache --> has expiration timestamp (to detect obsolescence)
// Local --> install time version
@@ -839,7 +839,7 @@ var readUserAsset = function(path, callback) {
//
// An external filter list:
// Path --> starts with 'http'
-// External -->
+// External -->
// Cache --> has expiration timestamp (to detect obsolescence)
//
// User data:
@@ -852,7 +852,7 @@ var readUserAsset = function(path, callback) {
// the asset needs to be updated.
//
// If no update required, an asset if first fetched from the cache. If the
-// asset is not cached it is fetched from the closest location: local for
+// asset is not cached it is fetched from the closest location: local for
// an asset shipped with the extension, external for an asset not shipped
// with the extension.
diff --git a/js/async.js b/src/js/async.js
index ab63545..6e64cc3 100644
--- a/js/async.js
+++ b/src/js/async.js
@@ -174,7 +174,7 @@ return asyncJobManager;
µBlock.updateBadgeAsync = (function(){
var µb = µBlock;
- // Cache callback definition, it was a bad idea to define this one inside
+ // Cache callback definition, it was a bad idea to define this one inside
// updateBadgeAsync
var updateBadge = function(tabId) {
var pageStore = µb.pageStoreFromTabId(tabId);
@@ -182,7 +182,7 @@ return asyncJobManager;
pageStore.updateBadge();
return;
}
- µb.XAL.setIcon(
+ vAPI.setIcon(
tabId,
{ '19': 'img/browsericons/icon19-off.png', '38': 'img/browsericons/icon38-off.png' },
''
diff --git a/js/background.js b/src/js/background.js
index a0528fb..b47cc02 100644
--- a/js/background.js
+++ b/src/js/background.js
@@ -49,7 +49,8 @@ var defaultExternalLists = [
/******************************************************************************/
return {
- manifest: chrome.runtime.getManifest(),
+ name: "µBlock",
+ version: "0.7.0",
userSettings: {
autoUpdate: true,
@@ -111,7 +112,7 @@ return {
pageStores: {},
- storageQuota: chrome.storage.local.QUOTA_BYTES,
+ storageQuota: vAPI.storage.QUOTA_BYTES,
storageUsed: 0,
noopFunc: function(){},
diff --git a/js/contentscript-end.js b/src/js/contentscript-end.js
index 1d5b3e1..33efb2e 100644
--- a/js/contentscript-end.js
+++ b/src/js/contentscript-end.js
@@ -19,112 +19,16 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome */
+/* global chrome, vAPI */
// Injected into content pages
-/******************************************************************************/
-/******************************************************************************/
-
-// https://github.com/gorhill/httpswitchboard/issues/345
-
-var uBlockMessaging = (function(name){
- var port = null;
- var requestId = 1;
- var requestIdToCallbackMap = {};
- var listenCallback = null;
-
- var onPortMessage = function(details) {
- if ( typeof details.id !== 'number' ) {
- return;
- }
- // Announcement?
- if ( details.id < 0 ) {
- if ( listenCallback ) {
- listenCallback(details.msg);
- }
- return;
- }
- var callback = requestIdToCallbackMap[details.id];
- if ( !callback ) {
- return;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[details.id];
- callback(details.msg);
- };
-
- var start = function(name) {
- port = chrome.runtime.connect({ name: name });
- port.onMessage.addListener(onPortMessage);
-
- // https://github.com/gorhill/uBlock/issues/193
- port.onDisconnect.addListener(stop);
- };
-
- var stop = function() {
- listenCallback = null;
- port.disconnect();
- port = null;
- flushCallbacks();
- };
-
- if ( typeof name === 'string' && name !== '' ) {
- start(name);
- }
-
- var ask = function(msg, callback) {
- if ( port === null ) {
- if ( typeof callback === 'function' ) {
- callback();
- }
- return;
- }
- if ( callback === undefined ) {
- tell(msg);
- return;
- }
- var id = requestId++;
- port.postMessage({ id: id, msg: msg });
- requestIdToCallbackMap[id] = callback;
- };
-
- var tell = function(msg) {
- if ( port !== null ) {
- port.postMessage({ id: 0, msg: msg });
- }
- };
-
- var listen = function(callback) {
- listenCallback = callback;
- };
-
- var flushCallbacks = function() {
- var callback;
- for ( var id in requestIdToCallbackMap ) {
- if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) {
- continue;
- }
- callback = requestIdToCallbackMap[id];
- if ( !callback ) {
- continue;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[id];
- callback();
- }
- };
+// because Safari
+if (location.protocol !== "http:" && location.protocol !== "https:") {
+ throw "uBlock> contentscript-end.js > Skipping page... " + location.protocol + location.host;
+}
- return {
- start: start,
- stop: stop,
- ask: ask,
- tell: tell,
- listen: listen
- };
-})('contentscript-end.js');
+var messager = vAPI.messaging.channel('contentscript-end.js');
/******************************************************************************/
/******************************************************************************/
@@ -132,7 +36,6 @@ var uBlockMessaging = (function(name){
// ABP cosmetic filters
(function() {
- var messaging = uBlockMessaging;
var queriedSelectors = {};
var injectedSelectors = {};
var classSelectors = null;
@@ -200,7 +103,7 @@ var uBlockMessaging = (function(name){
}
if ( selectors.length > 0 || highGenerics === null ) {
//console.log('µBlock> ABP cosmetic filters: retrieving CSS rules using %d selectors', selectors.length);
- messaging.ask({
+ messager.send({
what: 'retrieveGenericCosmeticSelectors',
pageURL: window.location.href,
selectors: selectors,
@@ -256,7 +159,7 @@ var uBlockMessaging = (function(name){
contextNodes.length = 0;
};
- // Ensure elements matching a set of selectors are visually removed
+ // Ensure elements matching a set of selectors are visually removed
// from the page, by:
// - Modifying the style property on the elements themselves
// - Injecting a style tag
@@ -271,7 +174,7 @@ var uBlockMessaging = (function(name){
if ( parent ) {
parent.appendChild(style);
}
- messaging.tell({
+ messager.send({
what: 'injectedSelectors',
type: 'cosmetic',
hostname: window.location.hostname,
@@ -398,7 +301,7 @@ var uBlockMessaging = (function(name){
}
};
- // High-high generics are *very costly* to process, so we will coalesce
+ // High-high generics are *very costly* to process, so we will coalesce
// requests to process high-high generics into as few requests as possible.
// The gain is *significant* on bloated pages.
@@ -409,7 +312,7 @@ var uBlockMessaging = (function(name){
if ( injectedSelectors['{{highHighGenerics}}'] !== undefined ) { return; }
if ( document.querySelector(highGenerics.hideHigh) === null ) { return; }
injectedSelectors['{{highHighGenerics}}'] = true;
- // We need to filter out possible exception cosmetic filters from
+ // We need to filter out possible exception cosmetic filters from
// high-high generics selectors.
var selectors = highGenerics.hideHigh.split(',\n');
var i = selectors.length;
@@ -508,6 +411,16 @@ var uBlockMessaging = (function(name){
return;
}
+ if (!window.MutationObserver) {
+ // DOMSubtreeModified?
+ if (!window.WebKitMutationObserver) {
+ return;
+ }
+
+ // Safari
+ window.MutationObserver = window.WebKitMutationObserver;
+ }
+
var ignoreTags = {
'link': true,
'LINK': true,
@@ -557,7 +470,7 @@ var uBlockMessaging = (function(name){
}
if ( addedNodeListsTimer === null ) {
// I arbitrarily chose 50 ms for now:
- // I have to compromise between the overhead of processing too few
+ // I have to compromise between the overhead of processing too few
// nodes too often and the delay of many nodes less often.
addedNodeListsTimer = setTimeout(mutationObservedHandler, 75);
}
@@ -577,8 +490,6 @@ var uBlockMessaging = (function(name){
// Permanent
(function() {
- var messaging = uBlockMessaging;
-
// Listeners to mop up whatever is otherwise missed:
// - Future requests not blocked yet
// - Elements dynamically added to the page
@@ -629,7 +540,7 @@ var uBlockMessaging = (function(name){
} else {
target.style.setProperty('visibility', 'hidden', 'important');
}
- messaging.tell({
+ messager.send({
what: 'injectedSelectors',
type: 'net',
hostname: window.location.hostname,
@@ -644,7 +555,7 @@ var uBlockMessaging = (function(name){
pageHostname: window.location.hostname,
pageURL: window.location.href
};
- messaging.ask(details, onAnswerReceived);
+ messager.send(details, onAnswerReceived);
};
var onResourceLoaded = function(ev) {
@@ -669,8 +580,6 @@ var uBlockMessaging = (function(name){
// Executed only once
(function() {
- var messaging = uBlockMessaging;
-
var srcProps = {
'embed': 'src',
'iframe': 'src',
@@ -703,7 +612,7 @@ var uBlockMessaging = (function(name){
selectors.push(request.tagName + '[' + srcProps[request.tagName] + '="' + request.url + '"]');
}
if ( selectors.length !== 0 ) {
- messaging.tell({
+ messager.send({
what: 'injectedSelectors',
type: 'net',
hostname: window.location.hostname,
@@ -747,7 +656,7 @@ var uBlockMessaging = (function(name){
pageHostname: window.location.hostname,
requests: requests
};
- messaging.ask(details, onAnswerReceived);
+ messager.send(details, onAnswerReceived);
})();
/******************************************************************************/
@@ -762,13 +671,14 @@ var uBlockMessaging = (function(name){
(function() {
var onContextMenu = function(ev) {
- uBlockMessaging.tell({
+ messager.send({
what: 'contextMenuEvent',
clientX: ev.clientX,
clientY: ev.clientY
});
};
- document.addEventListener('contextmenu', onContextMenu);
+
+ window.addEventListener('contextmenu', onContextMenu, true);
})();
/******************************************************************************/
diff --git a/js/contentscript-start.js b/src/js/contentscript-start.js
index 3f1e588..39c5926 100644
--- a/js/contentscript-start.js
+++ b/src/js/contentscript-start.js
@@ -33,108 +33,13 @@
(function() {
-/******************************************************************************/
-/******************************************************************************/
-
-// https://github.com/gorhill/httpswitchboard/issues/345
-
-var uBlockMessaging = (function(name){
- var port = null;
- var requestId = 1;
- var requestIdToCallbackMap = {};
- var listenCallback = null;
-
- var onPortMessage = function(details) {
- if ( typeof details.id !== 'number' ) {
- return;
- }
- // Announcement?
- if ( details.id < 0 ) {
- if ( listenCallback ) {
- listenCallback(details.msg);
- }
- return;
- }
- var callback = requestIdToCallbackMap[details.id];
- if ( callback === undefined ) {
- return;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[details.id];
- callback(details.msg);
- };
-
- var start = function(name) {
- port = chrome.runtime.connect({ name: name });
- port.onMessage.addListener(onPortMessage);
-
- // https://github.com/gorhill/uBlock/issues/193
- port.onDisconnect.addListener(stop);
- };
-
- var stop = function() {
- listenCallback = null;
- port.disconnect();
- port = null;
- flushCallbacks();
- };
-
- if ( typeof name === 'string' && name !== '' ) {
- start(name);
- }
+// because Safari
+if (location.protocol !== "http:" && location.protocol !== "https:") {
+ return;
+}
- var ask = function(msg, callback) {
- if ( port === null ) {
- if ( typeof callback === 'function' ) {
- callback();
- }
- return;
- }
- if ( callback === undefined ) {
- tell(msg);
- return;
- }
- var id = requestId++;
- port.postMessage({ id: id, msg: msg });
- requestIdToCallbackMap[id] = callback;
- };
-
- var tell = function(msg) {
- if ( port !== null ) {
- port.postMessage({ id: 0, msg: msg });
- }
- };
-
- var listen = function(callback) {
- listenCallback = callback;
- };
-
- var flushCallbacks = function() {
- var callback;
- for ( var id in requestIdToCallbackMap ) {
- if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) {
- continue;
- }
- callback = requestIdToCallbackMap[id];
- if ( callback === undefined ) {
- continue;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[id];
- callback();
- }
- };
+var localMessager = vAPI.messaging.channel('contentscript-start.js');
- return {
- start: start,
- stop: stop,
- ask: ask,
- tell: tell,
- listen: listen
- };
-})('contentscript-start.js');
/******************************************************************************/
/******************************************************************************/
@@ -176,7 +81,7 @@ var cosmeticFilters = function(details) {
if ( hide.length !== 0 ) {
var text = hide.join(',\n');
hideElements(text);
- // The linefeed before the style block is very important: do no remove!
+ // The linefeed before the style block is very important: do not remove!
style.appendChild(document.createTextNode(text + '\n{display:none !important;}'));
//console.debug('µBlock> "%s" cosmetic filters: injecting %d CSS rules:', details.domain, details.hide.length, hideStyleText);
}
@@ -214,7 +119,7 @@ var filteringHandler = function(details) {
// the browser to flush this script from memory.
}
// Do not close the port before we are done.
- uBlockMessaging.stop();
+ localMessager.close();
};
var hideElements = function(selectors) {
@@ -230,7 +135,7 @@ var hideElements = function(selectors) {
}
};
-uBlockMessaging.ask(
+localMessager.send(
{
what: 'retrieveDomainCosmeticSelectors',
pageURL: window.location.href,
diff --git a/js/contextmenu.js b/src/js/contextmenu.js
index da93b67..519cfc5 100644
--- a/js/contextmenu.js
+++ b/src/js/contextmenu.js
@@ -44,23 +44,23 @@ var onContextMenuClicked = function(details, tab) {
if ( /^https?:\/\//.test(tab.url) === false ) {
return;
}
- var tagName = '';
- var src = '';
- if ( typeof details.frameUrl === 'string' ) {
- tagName = 'iframe';
- src = details.frameUrl;
- } else if ( typeof details.srcUrl === 'string' ) {
- if ( details.mediaType === 'image' ) {
- tagName = 'img';
- } else if ( details.mediaType === 'video' ) {
- tagName = 'video';
- } else if ( details.mediaType === 'audio' ) {
- tagName = 'audio';
+ var tagName = details.tagName || '';
+ var src = details.frameUrl || details.srcUrl || details.linkUrl || '';
+
+ if (!tagName) {
+ if ( typeof details.frameUrl === 'string' ) {
+ tagName = 'iframe';
+ } else if ( typeof details.srcUrl === 'string' ) {
+ if ( details.mediaType === 'image' ) {
+ tagName = 'img';
+ } else if ( details.mediaType === 'video' ) {
+ tagName = 'video';
+ } else if ( details.mediaType === 'audio' ) {
+ tagName = 'audio';
+ }
+ } else if ( typeof details.linkUrl === 'string' ) {
+ tagName = 'a';
}
- src = details.srcUrl;
- } else if ( typeof details.linkUrl === 'string' ) {
- tagName = 'a';
- src = details.linkUrl;
}
µb.elementPickerExec(tab.id, tagName + '\t' + src);
@@ -70,26 +70,24 @@ var onContextMenuClicked = function(details, tab) {
var toggleMenu = function(on) {
// In case the permission for contextMenu was not granted.
- if ( chrome.contextMenus === undefined ) {
- return;
- }
+ // if ( chrome.contextMenus === undefined ) {
+ // return;
+ // }
// This needs to be local scope: we can't reuse it for more than one
// menu creation call.
var menuCreateDetails = {
id: 'blockElement',
- title: chrome.i18n.getMessage('pickerContextMenuEntry'),
+ title: vAPI.i18n('pickerContextMenuEntry'),
contexts: ['page', 'editable', 'frame', 'link', 'image', 'video'],
documentUrlPatterns: ['https://*/*', 'http://*/*']
};
if ( on === true && enabled === false ) {
- chrome.contextMenus.create(menuCreateDetails);
- chrome.contextMenus.onClicked.addListener(onContextMenuClicked);
+ vAPI.contextMenu.create(menuCreateDetails, onContextMenuClicked);
enabled = true;
} else if ( on !== true && enabled === true ) {
- chrome.contextMenus.onClicked.removeListener(onContextMenuClicked);
- chrome.contextMenus.remove(menuCreateDetails.id);
+ vAPI.contextMenu.remove();
enabled = false;
}
};
diff --git a/js/cosmetic-filtering.js b/src/js/cosmetic-filtering.js
index 345837a..1794bbe 100644
--- a/js/cosmetic-filtering.js
+++ b/src/js/cosmetic-filtering.js
@@ -306,7 +306,7 @@ SelectorCacheEntry.prototype.addCosmetic = function(selectors) {
var dict = this.cosmetic;
var i = selectors.length || 0;
while ( i-- ) {
- dict[selectors[i]] = true;
+ dict[selectors[i]] = true;
}
};
@@ -377,9 +377,9 @@ SelectorCacheEntry.prototype.retrieve = function(type, out) {
// Two Unicode characters:
// T0HHHHHHH HHHHHHHHH
-// | | |
-// | | |
-// | | |
+// | | |
+// | | |
+// | | |
// | | +-- bit 8-0 of FNV
// | |
// | +-- bit 15-9 of FNV
@@ -488,7 +488,7 @@ FilterContainer.prototype.reset = function() {
this.highLowGenericDonthide = {};
this.highLowGenericHideCount = 0;
this.highLowGenericDonthideCount = 0;
-
+
// a[href^="http..."]
this.highMediumGenericHide = {};
this.highMediumGenericDonthide = {};
diff --git a/js/dashboard-common.js b/src/js/dashboard-common.js
index 8585012..8585012 100644
--- a/js/dashboard-common.js
+++ b/src/js/dashboard-common.js
diff --git a/js/dashboard.js b/src/js/dashboard.js
index a11b45d..b1e7aa4 100644
--- a/js/dashboard.js
+++ b/src/js/dashboard.js
@@ -38,8 +38,9 @@ var loadDashboardPanel = function(tab, q) {
/******************************************************************************/
-var onTabClickHandler = function() {
+var onTabClickHandler = function(e) {
loadDashboardPanel(uDom(this).attr('data-dashboard-panel-url'));
+ e.preventDefault();
};
/******************************************************************************/
diff --git a/js/element-picker.js b/src/js/element-picker.js
index 136ec70..c9bd620 100644
--- a/js/element-picker.js
+++ b/src/js/element-picker.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global CSS, chrome */
+/* global CSS, chrome, vAPI */
/******************************************************************************/
/******************************************************************************/
@@ -112,107 +112,6 @@
/******************************************************************************/
/******************************************************************************/
-// Cut & pasted here from reference implementation in messaging-client.js
-// because this is an injected script.
-
-var messaging = (function(name){
- var port = null;
- var requestId = 1;
- var requestIdToCallbackMap = {};
- var listenCallback = null;
-
- var onPortMessage = function(details) {
- if ( typeof details.id !== 'number' ) {
- return;
- }
- // Announcement?
- if ( details.id < 0 ) {
- if ( listenCallback ) {
- listenCallback(details.msg);
- }
- return;
- }
- var callback = requestIdToCallbackMap[details.id];
- if ( !callback ) {
- return;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[details.id];
- callback(details.msg);
- };
-
- var start = function(name) {
- port = chrome.runtime.connect({ name: name });
- port.onMessage.addListener(onPortMessage);
-
- // https://github.com/gorhill/uBlock/issues/193
- port.onDisconnect.addListener(stop);
- };
-
- var stop = function() {
- listenCallback = null;
- port.disconnect();
- port = null;
- flushCallbacks();
- };
-
- if ( typeof name === 'string' && name !== '' ) {
- start(name);
- }
-
- var ask = function(msg, callback) {
- if ( port === null ) {
- if ( typeof callback === 'function' ) {
- callback();
- }
- return;
- }
- if ( callback === undefined ) {
- tell(msg);
- return;
- }
- var id = requestId++;
- port.postMessage({ id: id, msg: msg });
- requestIdToCallbackMap[id] = callback;
- };
-
- var tell = function(msg) {
- if ( port !== null ) {
- port.postMessage({ id: 0, msg: msg });
- }
- };
-
- var listen = function(callback) {
- listenCallback = callback;
- };
-
- var flushCallbacks = function() {
- var callback;
- for ( var id in requestIdToCallbackMap ) {
- if ( requestIdToCallbackMap.hasOwnProperty(id) === false ) {
- continue;
- }
- callback = requestIdToCallbackMap[id];
- if ( !callback ) {
- continue;
- }
- // Must be removed before calling client to be sure to not execute
- // callback again if the client stops the messaging service.
- delete requestIdToCallbackMap[id];
- callback();
- }
- };
-
- return {
- start: start,
- stop: stop,
- ask: ask,
- tell: tell,
- listen: listen
- };
-})('element-picker.js');
-
/******************************************************************************/
/******************************************************************************/
@@ -276,6 +175,24 @@ var pickerRootDistance = function(elem) {
/******************************************************************************/
+// https://github.com/gorhill/uBlock/issues/210
+
+// HTMLElement.getBoundingClientRect() is unreliable (or I misunderstand what
+// it does). I will just compute it myself.
+
+var getBoundingClientRect = function(elem, r) {
+ r.w = elem.offsetWidth;
+ r.h = elem.offsetHeight;
+ r.x = elem.offsetLeft - elem.scrollLeft;
+ r.y = elem.offsetTop - elem.scrollTop;
+ while ( elem = elem.offsetParent ) {
+ r.x += elem.offsetLeft - elem.scrollLeft;
+ r.y += elem.offsetTop - elem.scrollTop;
+ }
+};
+
+/******************************************************************************/
+
var highlightElements = function(elems, force) {
// To make mouse move handler more efficient
if ( !force && elems.length === targetElements.length ) {
@@ -584,7 +501,7 @@ var onDialogClicked = function(ev) {
else if ( ev.target.id === 'create' ) {
var filter = userFilterFromCandidate();
if ( filter ) {
- messaging.tell({ what: 'createUserFilter', filters: filter });
+ messager.send({ what: 'createUserFilter', filters: filter });
removeElements(elementsFromFilter(taCandidate.value));
stopPicker();
}
@@ -742,13 +659,13 @@ var stopPicker = function() {
divDialog.removeEventListener('click', onDialogClicked);
svgRoot.removeEventListener('mousemove', onSvgHovered);
svgRoot.removeEventListener('click', onSvgClicked);
- document.documentElement.removeChild(pickerRoot);
- pickerRoot =
- divDialog =
- svgRoot = svgOcean = svgIslands =
- taCandidate =
+ document.body.removeChild(pickerRoot);
+ pickerRoot =
+ divDialog =
+ svgRoot = svgOcean = svgIslands =
+ taCandidate =
urlNormalizer = null;
- messaging.stop();
+ messager.close();
}
targetElements = [];
};
@@ -766,7 +683,7 @@ var startPicker = function() {
var pickerStyle = document.createElement('style');
pickerStyle.setAttribute('scoped', '');
pickerStyle.textContent = [
- '#µBlock, #µBlock * {',
+ '#µBlock, #µBlock * {',
'background: transparent;',
'background-image: none;',
'border: 0;',
@@ -1046,7 +963,7 @@ var startPicker = function() {
}
};
- messaging.ask({ what: 'elementPickerArguments' }, initPicker);
+ messager.send({ what: 'elementPickerArguments' }, initPicker);
};
/******************************************************************************/
diff --git a/js/i18n.js b/src/js/i18n.js
index bfbe3b3..11cc26f 100644
--- a/js/i18n.js
+++ b/src/js/i18n.js
@@ -23,18 +23,18 @@
uDom.onLoad(function() {
uDom('[data-i18n]').forEach(function(elem) {
- elem.html(chrome.i18n.getMessage(elem.attr('data-i18n')));
+ elem.html(vAPI.i18n.getMessage(elem.attr('data-i18n')));
});
uDom('[title]').forEach(function(elem) {
- var title = chrome.i18n.getMessage(elem.attr('title'));
+ var title = vAPI.i18n.getMessage(elem.attr('title'));
if ( title ) {
elem.attr('title', title);
}
});
uDom('[data-i18n-tip]').forEach(function(elem) {
elem.attr(
- 'data-tip',
- chrome.i18n.getMessage(elem.attr('data-i18n-tip')).replace(/<br>/g, '')
+ 'data-tip',
+ vAPI.i18n.getMessage(elem.attr('data-i18n-tip')).replace(/<br>/g, '')
);
});
});
diff --git a/src/js/js-loader.js b/src/js/js-loader.js
new file mode 100644
index 0000000..326801c
--- /dev/null
+++ b/src/js/js-loader.js
@@ -0,0 +1,37 @@
+(function() {
+ document.body.style.display = "none";
+ document.addEventListener("DOMContentLoaded", function onDOMReady(e) {
+ document.removeEventListener(e.type, onDOMReady, false);
+
+ var jsListToLoad = document.querySelector("script[data-jsList]");
+
+ if (jsListToLoad) {
+ jsListToLoad = jsListToLoad.getAttribute("data-jsList").trim().split(/\s+/);
+ }
+
+ if (Array.isArray(jsListToLoad)) {
+ var loadNextJSFile = function() {
+ var script, src = jsListToLoad.shift();
+
+ if (src) {
+ script = document.createElement("script");
+ script.onload = function() {
+ this.onload = null;
+
+ if (jsListToLoad.length) {
+ loadNextJSFile();
+ }
+ else {
+ document.body.style.display = "";
+ jsListToLoad = document.querySelector("script[data-jsList]");
+ jsListToLoad.parentNode.removeChild(jsListToLoad);
+ }
+ };
+ document.body.appendChild(script).src = src;
+ }
+ };
+
+ loadNextJSFile();
+ }
+ }, false);
+})(); \ No newline at end of file
diff --git a/js/liquid-dict.js b/src/js/liquid-dict.js
index cd15a72..08744d7 100644
--- a/js/liquid-dict.js
+++ b/src/js/liquid-dict.js
@@ -101,7 +101,7 @@ LiquidDict.prototype.makeKey = function(word) {
var i4 = len >>> 2;
var i2 = len >>> 1;
- // Be sure the msb is not set, this will guarantee a valid unicode
+ // Be sure the msb is not set, this will guarantee a valid unicode
// character (because 0xD800-0xDFFF).
return String.fromCharCode(
(word.charCodeAt( i8) & 0x01) << 14 |
diff --git a/js/messaging-handlers.js b/src/js/messaging.js
index 3c3f3e7..87b549d 100644
--- a/js/messaging-handlers.js
+++ b/src/js/messaging.js
@@ -19,7 +19,56 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, µBlock, YaMD5 */
+/* global vAPI, µBlock, YaMD5 */
+
+/******************************************************************************/
+
+// message router and default handler
+vAPI.messaging.setup(function(request, sender, callback) {
+ var µb = µBlock;
+
+ switch ( request.what ) {
+ // Async
+ case 'getAssetContent':
+ µb.assets.getLocal(request.url, callback);
+ return;
+
+ case 'loadUbiquitousAllowRules':
+ µb.loadUbiquitousWhitelists();
+ return;
+
+ // Sync
+ case 'contextMenuEvent':
+ µb.contextMenuClientX = request.clientX;
+ µb.contextMenuClientY = request.clientY;
+ break;
+
+ /*case 'forceReloadTab':
+ µb.forceReload(request.pageURL);
+ break;*/
+
+ case 'getUserSettings':
+ callback(µb.userSettings);
+ break;
+
+ case 'gotoURL':
+ vAPI.tabs.open(request.details);
+ break;
+
+ case 'reloadAllFilters':
+ µb.reloadPresetBlacklists(request.switches, request.update);
+ break;
+
+ case 'userSettings':
+ callback(µb.changeUserSettings(request.name, request.value));
+ break;
+
+ default:
+ // if none of the above, then check the channel listeners
+ return null;
+ }
+});
+
/******************************************************************************/
/******************************************************************************/
@@ -46,11 +95,11 @@ var getDynamicFilterResults = function(scope) {
/******************************************************************************/
-var getStats = function(request) {
+var getStats = function(tab) {
var r = {
globalBlockedRequestCount: µb.localSettings.blockedRequestCount,
globalAllowedRequestCount: µb.localSettings.allowedRequestCount,
- tabId: request.tabId,
+ tabId: tab.id,
pageURL: '',
pageBlockedRequestCount: 0,
pageAllowedRequestCount: 0,
@@ -62,7 +111,7 @@ var getStats = function(request) {
'/': getDynamicFilterResults('*')
}
};
- var pageStore = µb.pageStoreFromTabId(request.tabId);
+ var pageStore = µb.pageStoreFromTabId(tab.id);
if ( pageStore ) {
r.pageURL = pageStore.pageURL;
r.pageHostname = pageStore.pageHostname;
@@ -79,6 +128,14 @@ var getStats = function(request) {
var onMessage = function(request, sender, callback) {
// Async
switch ( request.what ) {
+ case 'activeTabStats':
+ vAPI.tabs.get(null, function(tab) {
+ if ( tab ) {
+ callback(getStats(tab));
+ }
+ });
+ return;
+
default:
break;
}
@@ -94,10 +151,6 @@ var onMessage = function(request, sender, callback) {
µb.elementPickerExec(request.tabId);
break;
- case 'stats':
- response = getStats(request);
- break;
-
case 'toggleNetFiltering':
µb.toggleNetFilteringSwitch(
request.url,
@@ -114,15 +167,12 @@ var onMessage = function(request, sender, callback) {
response['.'] = getDynamicFilterResults(request.pageHostname);
}
break;
-
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
}
callback(response);
};
-µb.messaging.listen('popup.js', onMessage);
+vAPI.messaging.listen('popup.js', onMessage);
/******************************************************************************/
@@ -162,15 +212,12 @@ var onMessage = function(request, sender, callback) {
response = µb.cosmeticFilteringEngine.retrieveDomainSelectors(request);
}
break;
-
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
}
callback(response);
};
-µb.messaging.listen('contentscript-start.js', onMessage);
+vAPI.messaging.listen('contentscript-start.js', onMessage);
/******************************************************************************/
@@ -291,15 +338,12 @@ var onMessage = function(details, sender, callback) {
response = filterRequest(pageStore, details);
}
break;
-
- default:
- return µb.messaging.defaultHandler(details, sender, callback);
}
callback(response);
};
-µb.messaging.listen('contentscript-end.js', onMessage);
+vAPI.messaging.listen('contentscript-end.js', onMessage);
/******************************************************************************/
@@ -332,12 +376,12 @@ var onMessage = function(request, sender, callback) {
case 'elementPickerArguments':
response = {
i18n: {
- create: chrome.i18n.getMessage('pickerCreate'),
- pick: chrome.i18n.getMessage('pickerPick'),
- quit: chrome.i18n.getMessage('pickerQuit'),
- netFilters: chrome.i18n.getMessage('pickerNetFilters'),
- cosmeticFilters: chrome.i18n.getMessage('pickerCosmeticFilters'),
- cosmeticFiltersHint: chrome.i18n.getMessage('pickerCosmeticFiltersHint')
+ create: vAPI.i18n('pickerCreate'),
+ pick: vAPI.i18n('pickerPick'),
+ quit: vAPI.i18n('pickerQuit'),
+ netFilters: vAPI.i18n('pickerNetFilters'),
+ cosmeticFilters: vAPI.i18n('pickerCosmeticFilters'),
+ cosmeticFiltersHint: vAPI.i18n('pickerCosmeticFiltersHint')
},
target: µb.contextMenuTarget,
clientX: µb.contextMenuClientX,
@@ -352,14 +396,12 @@ var onMessage = function(request, sender, callback) {
µb.appendUserFilters(request.filters);
break;
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
}
callback(response);
};
-µb.messaging.listen('element-picker.js', onMessage);
+vAPI.messaging.listen('element-picker.js', onMessage);
/******************************************************************************/
@@ -426,14 +468,12 @@ var onMessage = function(request, sender, callback) {
µb.assets.purge(request.path);
break;
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
}
callback(response);
};
-µb.messaging.listen('3p-filters.js', onMessage);
+vAPI.messaging.listen('3p-filters.js', onMessage);
/******************************************************************************/
@@ -469,14 +509,12 @@ var onMessage = function(request, sender, callback) {
var response;
switch ( request.what ) {
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
}
callback(response);
};
-µb.messaging.listen('1p-filters.js', onMessage);
+vAPI.messaging.listen('1p-filters.js', onMessage);
/******************************************************************************/
@@ -515,14 +553,12 @@ var onMessage = function(request, sender, callback) {
µb.saveWhitelist();
break;
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
}
callback(response);
};
-µb.messaging.listen('whitelist.js', onMessage);
+vAPI.messaging.listen('whitelist.js', onMessage);
/******************************************************************************/
@@ -608,14 +644,15 @@ var onMessage = function(request, sender, callback) {
response = getPageDetails(µb, request.tabId);
break;
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
+ case 'getTabForStats':
+ vAPI.tabs.get(request.tabId, callback);
+ return;
}
callback(response);
};
-µb.messaging.listen('stats.js', onMessage);
+vAPI.messaging.listen('stats.js', onMessage);
/******************************************************************************/
@@ -638,7 +675,7 @@ var getUserData = function(callback) {
var onUserFiltersReady = function(details) {
callback({
'timeStamp': Date.now(),
- 'version': µb.manifest.version,
+ 'version': µb.version,
'userSettings': µb.userSettings,
'filterLists': µb.remoteBlacklists,
'netWhitelist': µb.stringFromWhitelist(µb.netWhitelist),
@@ -705,15 +742,12 @@ var onMessage = function(request, sender, callback) {
case 'resetUserData':
resetUserData();
break;
-
- default:
- return µb.messaging.defaultHandler(request, sender, callback);
}
callback(response);
};
-µb.messaging.listen('about.js', onMessage);
+vAPI.messaging.listen('about.js', onMessage);
/******************************************************************************/
diff --git a/js/mirrors.js b/src/js/mirrors.js
index f82072d..14f096c 100644
--- a/js/mirrors.js
+++ b/src/js/mirrors.js
@@ -31,10 +31,10 @@
/******************************************************************************/
// To show keys in local storage from console:
-// chrome.storage.local.get(null, function (data) { console.log(Object.keys(data)) });
+// vAPI.storage.get(null, function (data) { console.log(Object.keys(data)) });
// To cleanup cached items from console:
-// chrome.storage.local.get(null, function (data) { chrome.storage.local.remove(Object.keys(data).filter(function(a){ return a.indexOf('mirrors_item_') === 0; })); });
+// vAPI.storage.get(null, function (data) { vAPI.storage.remove(Object.keys(data).filter(function(a){ return a.indexOf('mirrors_item_') === 0; })); });
var exports = {
@@ -68,10 +68,10 @@ var loaded = false;
/******************************************************************************/
-// Ideally, URL keys and access time would be attached to the data URL entry
-// itself, but then this would mean the need to persist the whole data URL
+// Ideally, URL keys and access time would be attached to the data URL entry
+// itself, but then this would mean the need to persist the whole data URL
// every time a new URL key is added or the data URL is accessed, and given the
-// data URL can be quite large, that would make no sense efficiency-wise to
+// data URL can be quite large, that would make no sense efficiency-wise to
// re-persist the whole thing.
// So, ContentEntry persisted once, MetadataEntry persisted often.
@@ -95,11 +95,11 @@ var getTextFileFromURL = function(url, onLoad, onError) {
onError = onLoad;
}
var xhr = new XMLHttpRequest();
+ xhr.open('get', url, true);
xhr.timeout = 10000;
xhr.onload = onLoad;
xhr.onerror = onError;
xhr.ontimeout = onError;
- xhr.open('get', url, true);
xhr.responseType = 'arraybuffer';
xhr.send();
};
@@ -108,9 +108,9 @@ var getTextFileFromURL = function(url, onLoad, onError) {
// Safe binary-to-base64. Because window.btoa doesn't work for binary data...
//
-// This implementation doesn't require the creation of a full-length
-// intermediate buffer. I expect less short-term memory use will translate in
-// more efficient conversion. Hopefully I will get time to confirm with
+// This implementation doesn't require the creation of a full-length
+// intermediate buffer. I expect less short-term memory use will translate in
+// more efficient conversion. Hopefully I will get time to confirm with
// benchmarks in the future.
var btoaMap = (function(){
@@ -293,7 +293,7 @@ var pruneToSize = function(toSize) {
var updateMetadata = function() {
metadataPersistTimer = null;
- chrome.storage.local.set({ 'mirrors_metadata': metadata });
+ vAPI.storage.set({ 'mirrors_metadata': metadata });
};
/******************************************************************************/
@@ -336,7 +336,7 @@ var addContent = function(hash, dataURL) {
exports.bytesInUse += dataURL.length;
var bin = {};
bin[storageKeyFromHash(hash)] = contentEntry;
- chrome.storage.local.set(bin);
+ vAPI.storage.set(bin);
if ( exports.bytesInUse >= exports.bytesInUseMax + bytesInUseMercy ) {
pruneToSize(exports.bytesInUseMax);
}
@@ -345,7 +345,7 @@ var addContent = function(hash, dataURL) {
/******************************************************************************/
var removeContent = function(what) {
- chrome.storage.local.remove(what);
+ vAPI.storage.remove(what);
};
/******************************************************************************/
@@ -484,7 +484,7 @@ var load = function() {
var ctEntry = hashToContentMap[hash] = bin[binKey];
exports.bytesInUse += ctEntry.dataURL.length;
};
- chrome.storage.local.get(binKey, onContentReady);
+ vAPI.storage.get(binKey, onContentReady);
};
var onMetadataReady = function(bin) {
@@ -511,7 +511,7 @@ var load = function() {
}
};
- chrome.storage.local.get({ 'mirrors_metadata': metadata }, onMetadataReady);
+ vAPI.storage.get({ 'mirrors_metadata': metadata }, onMetadataReady);
µBlock.assets.get('assets/ublock/mirror-candidates.txt', onMirrorCandidatesReady);
};
diff --git a/js/net-filtering.js b/src/js/net-filtering.js
index 342bf4e..70d0d58 100644
--- a/js/net-filtering.js
+++ b/src/js/net-filtering.js
@@ -814,7 +814,7 @@ FilterManyWildcardsHostname.fromSelfie = function(s) {
// Some buckets can grow quite large, and finding a hit in these buckets
// may end up being expensive. After considering various solutions, the one
-// retained is to promote hit filters to a smaller index, so that next time
+// retained is to promote hit filters to a smaller index, so that next time
// they can be looked-up faster.
// key= 10000 ad count=660
@@ -1144,7 +1144,7 @@ FilterParser.prototype.parseOptHostnames = function(raw) {
hostname = hostname.slice(1);
}
// https://github.com/gorhill/uBlock/issues/191
- // Well it doesn't seem to make a whole lot of sense to have both
+ // Well it doesn't seem to make a whole lot of sense to have both
// non-negated hostnames mixed with negated hostnames.
if ( this.hostnames.length !== 0 && not !== this.notHostname ) {
console.error('FilterContainer.parseOptHostnames(): ambiguous filter syntax: "%s"', this.f);
@@ -1826,7 +1826,7 @@ FilterContainer.prototype.dynamicFiltersFromSelfie = function(selfie) {
/******************************************************************************/
-// Since the addition of the `important` evaluation, this means it is now
+// Since the addition of the `important` evaluation, this means it is now
// likely that the url will have to be scanned more than once. So this is
// to ensure we do it once only, and reuse results.
@@ -2035,7 +2035,7 @@ FilterContainer.prototype.matchString = function(pageDetails, requestURL, reques
// as possible the number of filters to test.
//
// Then, because of the order of probabilities, we should test only
- // block filters first, and test allow filters if and only if there is a
+ // block filters first, and test allow filters if and only if there is a
// hit on a block filter. Since there is a high likelihood of no hit,
// testing allow filter by default is likely wasted work, hence allow
// filters are tested *only* if there is a (unlikely) hit on a block
diff --git a/js/pagestore.js b/src/js/pagestore.js
index dce9b89..e740662 100644
--- a/js/pagestore.js
+++ b/src/js/pagestore.js
@@ -319,7 +319,7 @@ PageStore.prototype.init = function(tabId, pageURL) {
/******************************************************************************/
PageStore.prototype.reuse = function(pageURL, context) {
- // If URL changes without a page reload (more and more common), then we
+ // If URL changes without a page reload (more and more common), then we
// need to keep all that we collected for reuse. In particular, not
// doing so was causing a problem in `videos.foxnews.com`: clicking a
// video thumbnail would not work, because the frame hierarchy structure
@@ -352,7 +352,7 @@ PageStore.prototype.dispose = function() {
// sizeable enough chunks (especially requests, through the request URL
// used as a key).
this.pageURL = this.previousPageURL =
- this.pageHostname = this.pageDomain =
+ this.pageHostname = this.pageDomain =
this.rootHostname = this.rootDomain = '';
this.disposeFrameStores();
this.netFilteringCache = this.netFilteringCache.dispose();
@@ -461,7 +461,7 @@ PageStore.prototype.updateBadge = function() {
if ( µb.userSettings.showIconBadge && netFiltering && this.perLoadBlockedRequestCount ) {
iconStr = µb.utils.formatCount(this.perLoadBlockedRequestCount);
}
- µb.XAL.setIcon(this.tabId, iconPaths, iconStr);
+ vAPI.setIcon(this.tabId, iconPaths, iconStr);
};
// https://www.youtube.com/watch?v=drW8p_dTLD4
diff --git a/js/popup.js b/src/js/popup.js
index 8b70c07..08c605d 100644
--- a/js/popup.js
+++ b/src/js/popup.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, messaging, uDom */
+/* global vAPI, uDom */
/******************************************************************************/
/******************************************************************************/
@@ -35,7 +35,8 @@ var reResultParser = /^(@@)?(\*|\|\|([^$^]+)\^)\$(.+)$/;
// https://github.com/gorhill/httpswitchboard/issues/345
-messaging.start('popup.js');
+var messager = vAPI.messaging.channel('popup.js');
+
/******************************************************************************/
@@ -89,7 +90,11 @@ var syncAllDynamicFilters = function() {
/******************************************************************************/
-var renderStats = function() {
+var renderStats = function(details) {
+ if ( details ) {
+ stats = details;
+ }
+
if ( !stats ) {
return;
}
@@ -111,7 +116,7 @@ var renderStats = function() {
isHTTP
);
- var or = chrome.i18n.getMessage('popupOr');
+ var or = vAPI.i18n('popupOr');
var blocked = stats.pageBlockedRequestCount;
var total = stats.pageAllowedRequestCount + blocked;
var html = [];
@@ -152,27 +157,9 @@ var renderStats = function() {
uDom('#dynamicFilteringToggler').toggleClass('on', stats.dynamicFilteringEnabled);
};
-/******************************************************************************/
-
-var onStatsReceived = function(details) {
- stats = details;
- renderStats();
-};
-
-/******************************************************************************/
-
-var onTabsReceived = function(tabs) {
- if ( tabs.length === 0 ) {
- return;
- }
- var q = {
- what: 'stats',
- tabId: tabs[0].id
- };
- messaging.ask( q, onStatsReceived );
-};
-
-chrome.tabs.query({ active: true, currentWindow: true }, onTabsReceived);
+messager.send( {
+ what: 'activeTabStats'
+}, renderStats );
/******************************************************************************/
@@ -181,7 +168,7 @@ var toggleNetFilteringSwitch = function(ev) {
return;
}
var off = uDom(this).toggleClass('off').hasClassName('off');
- messaging.tell({
+ messager.send({
what: 'toggleNetFiltering',
url: stats.pageURL,
scope: ev.ctrlKey || ev.metaKey ? 'page' : '',
@@ -193,25 +180,33 @@ var toggleNetFilteringSwitch = function(ev) {
/******************************************************************************/
var gotoDashboard = function() {
- messaging.tell({
- what: 'gotoExtensionURL',
- url: 'dashboard.html'
+ messager.send({
+ what: 'gotoURL',
+ details: {
+ url: 'dashboard.html',
+ select: true,
+ index: -1
+ }
});
};
/******************************************************************************/
var gotoStats = function() {
- messaging.tell({
- what: 'gotoExtensionURL',
- url: 'dashboard.html?tab=stats&which=' + stats.tabId
+ messager.send({
+ what: 'gotoURL',
+ details: {
+ url: 'dashboard.html?tab=stats&which=' + stats.tabId,
+ select: true,
+ index: -1
+ }
});
};
/******************************************************************************/
var gotoPick = function() {
- messaging.tell({
+ messager.send({
what: 'gotoPick',
tabId: stats.tabId
});
@@ -222,7 +217,7 @@ var gotoPick = function() {
var renderHeader = function() {
var hdr = uDom('#version');
- hdr.html(hdr.html() + 'v' + chrome.runtime.getManifest().version);
+ hdr.html(hdr.html() + 'v'); // + chrome.runtime.getManifest().version);
};
/******************************************************************************/
@@ -235,7 +230,7 @@ var onDynamicFilterClicked = function(ev) {
stats.dynamicFilterResults = details;
syncAllDynamicFilters();
};
- messaging.ask({
+ messager.send({
what: 'toggleDynamicFilter',
hostname: scope,
requestType: elFilter.attr('data-type'),
@@ -255,7 +250,7 @@ var toggleDynamicFiltering = function(ev) {
}
var el = uDom('#dynamicFilteringToggler');
el.toggleClass('on');
- messaging.tell({
+ messager.send({
what: 'userSettings',
name: 'dynamicFilteringEnabled',
value: el.hasClassName('on')
diff --git a/js/profiler.js b/src/js/profiler.js
index 05745d1..5861ac7 100644
--- a/js/profiler.js
+++ b/src/js/profiler.js
@@ -22,7 +22,7 @@
/******************************************************************************/
var quickProfiler = (function() {
- var timer = performance;
+ var timer = typeof performance === "undefined" ? Date : performance;
var time = 0;
var count = 0;
var tstart = 0;
diff --git a/js/settings.js b/src/js/settings.js
index 5b927ce..023e358 100644
--- a/js/settings.js
+++ b/src/js/settings.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global messaging, uDom */
+/* global vAPI, uDom */
/******************************************************************************/
@@ -27,12 +27,12 @@ uDom.onLoad(function() {
/******************************************************************************/
-messaging.start('settings.js');
+var messager = vAPI.messaging.channel('settings.js');
/******************************************************************************/
var changeUserSettings = function(name, value) {
- messaging.tell({
+ messager.send({
what: 'userSettings',
name: name,
value: value
@@ -69,7 +69,7 @@ var onUserSettingsReceived = function(details) {
});
};
-messaging.ask({ what: 'userSettings' }, onUserSettingsReceived);
+messager.send({ what: 'userSettings' }, onUserSettingsReceived);
/******************************************************************************/
diff --git a/js/start.js b/src/js/start.js
index 826303b..826303b 100644
--- a/js/start.js
+++ b/src/js/start.js
diff --git a/js/stats.js b/src/js/stats.js
index 57b777e..5d4eb47 100644
--- a/js/stats.js
+++ b/src/js/stats.js
@@ -20,7 +20,7 @@
*/
/* jshint bitwise: false */
-/* global chrome, uDom, messaging */
+/* global uDom, vAPI */
/******************************************************************************/
@@ -28,12 +28,12 @@
/******************************************************************************/
-messaging.start('stats.js');
+var messager = vAPI.messaging.channel('stats.js');
/******************************************************************************/
var logSettingChanged = function() {
- messaging.tell({
+ messager.send({
what: 'userSettings',
name: 'logRequests',
value: this.checked
@@ -143,7 +143,7 @@ var renderPageDetails = function(tabId) {
html.push(
'<tr class="header ', className, '">',
'<td colspan="4"><h3>',
- chrome.i18n.getMessage(className + (requests.length ? 'RequestsHeader' : 'RequestsEmpty')),
+ vAPI.i18n(className + (requests.length ? 'RequestsHeader' : 'RequestsEmpty')),
'</h3>'
);
var currentDomain = '';
@@ -172,7 +172,7 @@ var renderPageDetails = function(tabId) {
uDom('#requests .tableHeader').insertAfter(htmlBlocked.concat(htmlAllowed).join(''));
};
- messaging.ask({ what: 'getPageDetails', tabId: tabId }, onDataReceived);
+ messager.send({ what: 'getPageDetails', tabId: tabId }, onDataReceived);
};
/******************************************************************************/
@@ -214,13 +214,16 @@ var renderPageSelector = function(targetTabId) {
selectedTabId = pageSelectors[0];
}
for ( var i = 0; i < pageSelectors.length; i++ ) {
- chrome.tabs.get(parseInt(pageSelectors[i], 10), onTabReceived);
+ messager.send({
+ what: 'getTabForStats',
+ tabId: parseInt(pageSelectors[i], 10)
+ }, onTabReceived);
}
if ( pageSelectors.length > 0 ) {
renderPageDetails(selectedTabId);
}
};
- messaging.ask({ what: 'getPageSelectors' }, onDataReceived);
+ messager.send({ what: 'getPageSelectors' }, onDataReceived);
};
/******************************************************************************/
@@ -241,7 +244,7 @@ var onUserSettingsReceived = function(details) {
/******************************************************************************/
uDom.onLoad(function() {
- messaging.ask({ what: 'userSettings' }, onUserSettingsReceived);
+ messager.send({ what: 'userSettings' }, onUserSettingsReceived);
});
/******************************************************************************/
diff --git a/js/storage.js b/src/js/storage.js
index a66a110..196e037 100644
--- a/js/storage.js
+++ b/src/js/storage.js
@@ -27,7 +27,7 @@
var getBytesInUseHandler = function(bytesInUse) {
µBlock.storageUsed = bytesInUse;
};
- chrome.storage.local.getBytesInUse(null, getBytesInUseHandler);
+ vAPI.storage.getBytesInUse(null, getBytesInUseHandler);
};
/******************************************************************************/
@@ -36,7 +36,7 @@
if ( typeof callback !== 'function' ) {
callback = this.noopFunc;
}
- chrome.storage.local.set(this.localSettings, callback);
+ vAPI.storage.set(this.localSettings, callback);
};
/******************************************************************************/
@@ -46,7 +46,7 @@
µBlock.localSettings = store;
};
- chrome.storage.local.get(this.localSettings, settingsLoaded);
+ vAPI.storage.get(this.localSettings, settingsLoaded);
};
/******************************************************************************/
@@ -64,7 +64,7 @@
/******************************************************************************/
µBlock.saveUserSettings = function() {
- chrome.storage.local.set(this.userSettings, function() {
+ vAPI.storage.set(this.userSettings, function() {
µBlock.getBytesInUse();
});
};
@@ -79,7 +79,7 @@
}
};
- chrome.storage.local.get(this.userSettings, settingsLoaded);
+ vAPI.storage.get(this.userSettings, settingsLoaded);
};
/******************************************************************************/
@@ -88,7 +88,7 @@
var bin = {
'netWhitelist': this.stringFromWhitelist(this.netWhitelist)
};
- chrome.storage.local.set(bin, function() {
+ vAPI.storage.set(bin, function() {
µBlock.getBytesInUse();
});
this.netWhitelistModifyTime = Date.now();
@@ -105,10 +105,10 @@
if ( store.netWhitelist === '' ) {
store.netWhitelist = Object.keys(store.netExceptionList).join('\n');
if ( store.netWhitelist !== '' ) {
- chrome.storage.local.set({ 'netWhitelist': store.netWhitelist });
+ vAPI.storage.set({ 'netWhitelist': store.netWhitelist });
}
}
- chrome.storage.local.remove('netExceptionList');
+ vAPI.storage.remove('netExceptionList');
}
µb.netWhitelist = µb.whitelistFromString(store.netWhitelist);
µb.netWhitelistModifyTime = Date.now();
@@ -122,7 +122,7 @@
'netWhitelist': '',
'netExceptionList': ''
};
- chrome.storage.local.get(bin, onWhitelistLoaded);
+ vAPI.storage.get(bin, onWhitelistLoaded);
};
/******************************************************************************/
@@ -227,9 +227,9 @@
}
// Now get user's selection of lists
- chrome.storage.local.get(
+ vAPI.storage.get(
{ 'remoteBlacklists': availableLists },
- onSelectedListsLoaded
+ onSelectedListsLoaded
);
};
@@ -280,8 +280,8 @@
var loadBlacklistsEnd = function() {
µb.netFilteringEngine.freeze();
µb.cosmeticFilteringEngine.freeze();
- chrome.storage.local.set({ 'remoteBlacklists': µb.remoteBlacklists });
- µb.messaging.announce({ what: 'loadUbiquitousBlacklistCompleted' });
+ vAPI.storage.set({ 'remoteBlacklists': µb.remoteBlacklists });
+ vAPI.messaging.broadcast({ what: 'loadUbiquitousBlacklistCompleted' });
µb.toSelfieAsync();
callback();
};
@@ -345,7 +345,7 @@
filterListMeta.entryCount = acceptedCount;
filterListMeta.entryUsedCount = acceptedCount - duplicateCount;
- // Try to extract a human-friendly name (works only for
+ // Try to extract a human-friendly name (works only for
// ABP-compatible filter lists)
if ( filterListMeta.title === '' ) {
var matches = details.content.slice(0, 1024).match(/(?:^|\n)!\s*Title:([^\n]+)/i);
@@ -460,7 +460,7 @@
filterLists[switches[i].location].off = !!switches[i].off;
}
// Save switch states
- chrome.storage.local.set({ 'remoteBlacklists': filterLists }, onFilterListsReady);
+ vAPI.storage.set({ 'remoteBlacklists': filterLists }, onFilterListsReady);
} else {
onFilterListsReady();
}
@@ -523,12 +523,12 @@
netFilteringEngine: this.netFilteringEngine.toSelfie(),
cosmeticFilteringEngine: this.cosmeticFilteringEngine.toSelfie()
};
- chrome.storage.local.set({ selfie: selfie });
+ vAPI.storage.set({ selfie: selfie });
// console.log('µBlock.toSelfie> made a selfie!');
};
// This is to be sure the selfie is generated in a sane manner: the selfie will
-// be generated if the user doesn't change his filter lists selection for
+// be generated if the user doesn't change his filter lists selection for
// some set time.
µBlock.toSelfieAsync = function(after) {
@@ -570,13 +570,13 @@
callback(true);
};
- chrome.storage.local.get('selfie', onSelfieReady);
+ vAPI.storage.get('selfie', onSelfieReady);
};
/******************************************************************************/
µBlock.destroySelfie = function() {
- chrome.storage.local.remove('selfie');
+ vAPI.storage.remove('selfie');
};
/******************************************************************************/
@@ -623,8 +623,11 @@
scriptStart(tab.id);
}
};
- chrome.tabs.query({ url: 'http://*/*' }, bindToTabs);
- chrome.tabs.query({ url: 'https://*/*' }, bindToTabs);
+
+ if (vAPI.chrome) {
+ chrome.tabs.query({ url: 'http://*/*' }, bindToTabs);
+ chrome.tabs.query({ url: 'https://*/*' }, bindToTabs);
+ }
// https://github.com/gorhill/uBlock/issues/184
// If we restored a selfie, check for updates not too far
@@ -654,7 +657,7 @@
µb.loadFilterLists(onFiltersReady);
};
- // If no selfie available, take the long way, i.e. load and parse
+ // If no selfie available, take the long way, i.e. load and parse
// raw data.
var onSelfieReady = function(success) {
if ( success === true ) {
diff --git a/js/tab.js b/src/js/tab.js
index 30d0286..91bfb08 100644
--- a/js/tab.js
+++ b/src/js/tab.js
@@ -19,77 +19,72 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, µBlock */
+/* global µBlock */
/******************************************************************************/
-(function(){
- var µb = µBlock;
+// When the DOM content of root frame is loaded, this means the tab
+// content has changed.
+vAPI.tabs.onNavigation = function(details) {
+ if ( details.frameId !== 0 ) {
+ return;
+ }
+ µBlock.bindTabToPageStats(details.tabId, details.url);
+};
- // When the DOM content of root frame is loaded, this means the tab
- // content has changed.
- var onNavigationCommitted = function(details) {
- if ( details.frameId !== 0 ) {
- return;
- }
- µb.bindTabToPageStats(details.tabId, details.url);
- };
- chrome.webNavigation.onCommitted.addListener(onNavigationCommitted);
-
- // It may happen the URL in the tab changes, while the page's document
- // stays the same (for instance, Google Maps). Without this listener,
- // the extension icon won't be properly refreshed.
- var onTabUpdated = function(tabId, changeInfo, tab) {
- if ( !tab.url || tab.url === '' ) {
- return;
- }
- if ( !changeInfo.url ) {
- return;
- }
- µb.bindTabToPageStats(tabId, changeInfo.url, 'tabUpdated');
- };
- chrome.tabs.onUpdated.addListener(onTabUpdated);
+// It may happen the URL in the tab changes, while the page's document
+// stays the same (for instance, Google Maps). Without this listener,
+// the extension icon won't be properly refreshed.
+vAPI.tabs.onUpdated = function(tabId, changeInfo, tab) {
+ if ( !tab.url || tab.url === '' ) {
+ return;
+ }
+ if ( !changeInfo.url ) {
+ return;
+ }
+ µBlock.bindTabToPageStats(tabId, changeInfo.url, 'tabUpdated');
+};
- var onTabRemoved = function(tabId) {
- if ( tabId < 0 ) {
- return;
- }
- µb.unbindTabFromPageStats(tabId);
- };
- chrome.tabs.onRemoved.addListener(onTabRemoved);
-
- // https://github.com/gorhill/uBlock/issues/297
- var onCreatedNavigationTarget = function(details) {
- var pageStore = µb.pageStoreFromTabId(details.sourceTabId);
- if ( !pageStore ) {
- return;
- }
- var requestURL = details.url;
- var result = '';
+vAPI.tabs.onClosed = function(tabId) {
+ if ( tabId < 0 ) {
+ return;
+ }
+ µBlock.unbindTabFromPageStats(tabId);
+};
- // https://github.com/gorhill/uBlock/issues/323
- // If popup URL is whitelisted, do not block it
- if ( µb.getNetFilteringSwitch(requestURL) ) {
- result = µb.netFilteringEngine.matchStringExactType(pageStore, requestURL, 'popup');
- }
+// https://github.com/gorhill/uBlock/issues/297
+vAPI.tabs.onPopup = function(details) {
+ var pageStore = µBlock.pageStoreFromTabId(details.sourceTabId);
+ if ( !pageStore ) {
+ return;
+ }
+ var requestURL = details.url;
+ var result = '';
+
+ // https://github.com/gorhill/uBlock/issues/323
+ // If popup URL is whitelisted, do not block it
+ if ( µBlock.getNetFilteringSwitch(requestURL) ) {
+ result = µBlock.netFilteringEngine.matchStringExactType(pageStore, requestURL, 'popup');
+ }
- // https://github.com/gorhill/uBlock/issues/91
+ // https://github.com/gorhill/uBlock/issues/91
if ( result !== '' ) {
pageStore.recordResult('popup', requestURL, result);
}
- // Not blocked
- if ( pageStore.boolFromResult(result) === false ) {
- return;
- }
+ // Not blocked
+ if ( pageStore.boolFromResult(result) === false ) {
+ return;
+ }
+
+ // Blocked
+ // It is a popup, block and remove the tab.
+ µBlock.unbindTabFromPageStats(details.tabId);
+ µBlock.XAL.destroyTab(details.tabId);
+};
+
+vAPI.tabs.registerListeners();
- // Blocked
- // It is a popup, block and remove the tab.
- µb.unbindTabFromPageStats(details.tabId);
- µb.XAL.destroyTab(details.tabId);
- };
- chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
-})();
/******************************************************************************/
/******************************************************************************/
@@ -173,9 +168,9 @@
/******************************************************************************/
-µBlock.forceReload = function(pageURL) {
- var tabId = this.tabIdFromPageUrl(pageURL);
- if ( tabId ) {
- chrome.tabs.reload(tabId, { bypassCache: true });
- }
-};
+// µBlock.forceReload = function(pageURL) {
+// var tabId = this.tabIdFromPageUrl(pageURL);
+// if ( tabId ) {
+// chrome.tabs.reload(tabId, { bypassCache: true });
+// }
+// };
diff --git a/js/traffic.js b/src/js/traffic.js
index 19e042a..5ec2691 100644
--- a/js/traffic.js
+++ b/src/js/traffic.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, µBlock */
+/* global µBlock */
/******************************************************************************/
@@ -59,8 +59,8 @@ var onBeforeRequest = function(details) {
// https://github.com/gorhill/uBlock/issues/206
// https://code.google.com/p/chromium/issues/detail?id=410382
// Work around the issue of Chromium not properly setting the type for
- // `object` requests. Unclear whether this issue will be fixed, hence
- // this workaround to prevent torch-and-pitchfork mobs because ads are
+ // `object` requests. Unclear whether this issue will be fixed, hence
+ // this workaround to prevent torch-and-pitchfork mobs because ads are
// no longer blocked in videos.
// https://github.com/gorhill/uBlock/issues/281
// Looks like Chrome 38 (but not 39) doesn't provide the expected request
@@ -136,7 +136,7 @@ var onBeforeRequest = function(details) {
var onBeforeSendHeaders = function(details) {
// TODO: I vaguely remember reading that when pre-fetch is enabled,
// the tab id could be -1, despite the request not really being a
- // behind-the-scene request. If true, the test below would prevent
+ // behind-the-scene request. If true, the test below would prevent
// the popup blocker from working. Need to check this.
// Do not block behind the scene requests.
@@ -276,66 +276,62 @@ var headerValue = function(headers, name) {
/******************************************************************************/
-chrome.webRequest.onBeforeRequest.addListener(
+vAPI.net.onBeforeRequest = {
+ urls: [
+ 'http://*/*',
+ 'https://*/*'
+ ],
+ types: [
+ "main_frame",
+ "sub_frame",
+ 'stylesheet',
+ "script",
+ "image",
+ "object",
+ "xmlhttprequest",
+ "other"
+ ],
+ extra: [ 'blocking' ],
+ callback: onBeforeRequest
//function(details) {
// quickProfiler.start('onBeforeRequest');
// var r = onBeforeRequest(details);
// quickProfiler.stop();
// return r;
//},
- onBeforeRequest,
- {
- "urls": [
- "http://*/*",
- "https://*/*"
- ],
- "types": [
- "main_frame",
- "sub_frame",
- 'stylesheet',
- "script",
- "image",
- "object",
- "xmlhttprequest",
- "other"
- ]
- },
- [ "blocking" ]
-);
-
-chrome.webRequest.onBeforeSendHeaders.addListener(
+};
+
+vAPI.net.onBeforeSendHeaders = {
+ urls: [
+ 'http://*/*',
+ 'https://*/*'
+ ],
+ types: [
+ "main_frame"
+ ],
+ extra: [ 'blocking', 'requestHeaders' ],
+ callback: onBeforeSendHeaders
//function(details) {
// quickProfiler.start('onBeforeSendHeaders');
// var r = onBeforeSendHeaders(details);
// quickProfiler.stop();
// return r;
//},
- onBeforeSendHeaders,
- {
- "urls": [
- "http://*/*",
- "https://*/*"
- ],
- "types": [
- "main_frame"
- ]
- },
- [ "blocking", "requestHeaders" ]
-);
-
-chrome.webRequest.onHeadersReceived.addListener(
- onHeadersReceived,
- {
- "urls": [
- "http://*/*",
- "https://*/*"
- ],
- "types": [
- "main_frame"
- ]
- },
- [ "blocking", "responseHeaders" ]
-);
+};
+
+vAPI.net.onHeadersReceived = {
+ urls: [
+ 'http://*/*',
+ 'https://*/*'
+ ],
+ types: [
+ "main_frame"
+ ],
+ extra: [ 'blocking', 'responseHeaders' ],
+ callback: onHeadersReceived
+};
+
+vAPI.net.registerListeners();
console.log('µBlock> Beginning to intercept net requests at %s', (new Date()).toISOString());
diff --git a/js/ublock.js b/src/js/ublock.js
index 186eb97..c9019c7 100644
--- a/js/ublock.js
+++ b/src/js/ublock.js
@@ -203,7 +203,7 @@
// Pre-change
switch ( name ) {
- default:
+ default:
break;
}
diff --git a/js/udom.js b/src/js/udom.js
index 4e99257..4e99257 100644
--- a/js/udom.js
+++ b/src/js/udom.js
diff --git a/js/uritools.js b/src/js/uritools.js
index 92ab436..7e5ccb4 100644
--- a/js/uritools.js
+++ b/src/js/uritools.js
@@ -33,6 +33,8 @@ Naming convention from https://en.wikipedia.org/wiki/URI_scheme#Examples
// This will inserted as a module in the µBlock object.
+µBlock = typeof µBlock === "undefined" ? {} : µBlock;
+
µBlock.URI = (function() {
/******************************************************************************/
diff --git a/js/utils.js b/src/js/utils.js
index 6dd18cb..96bfc09 100644
--- a/js/utils.js
+++ b/src/js/utils.js
@@ -31,19 +31,10 @@
var exports = {};
-/******************************************************************************/
-
-exports.gotoURL = function(details) {
- if ( details.tabId ) {
- chrome.tabs.update(details.tabId, { url: details.url });
- } else {
- chrome.tabs.create({ url: details.url });
- }
-};
/******************************************************************************/
-exports.gotoExtensionURL = function(url) {
+/*exports.gotoExtensionURL = function(url) {
var hasQuery = function(url) {
return url.indexOf('?') >= 0;
@@ -65,7 +56,7 @@ exports.gotoExtensionURL = function(url) {
};
var tabIndex = 9999;
- var targetUrl = chrome.extension.getURL(url);
+ var targetUrl = vAPI.getURL(url);
var currentWindow = function(tabs) {
var updateProperties = { active: true };
@@ -98,7 +89,7 @@ exports.gotoExtensionURL = function(url) {
// - Otherwise find the current active tab and open in a tab immediately
// to the right of the active tab
chrome.tabs.query({ active: true }, currentTab);
-};
+};*/
/******************************************************************************/
diff --git a/src/js/vapi-background.js b/src/js/vapi-background.js
new file mode 100644
index 0000000..1db13ae
--- /dev/null
+++ b/src/js/vapi-background.js
@@ -0,0 +1,848 @@
+// for background page only
+
+(function() {
+'use strict';
+
+window.vAPI = window.vAPI || {};
+
+if (window.chrome) {
+ var chrome = window.chrome;
+
+ vAPI.chrome = true;
+
+ vAPI.storage = chrome.storage.local;
+
+ vAPI.tabs = {
+ registerListeners: function() {
+ if (typeof this.onNavigation === 'function') {
+ chrome.webNavigation.onCommitted.addListener(this.onNavigation);
+ }
+
+ if (typeof this.onUpdated === 'function') {
+ chrome.tabs.onUpdated.addListener(this.onUpdated);
+ }
+
+ if (typeof this.onClosed === 'function') {
+ chrome.tabs.onRemoved.addListener(this.onClosed);
+ }
+
+ if (typeof this.onPopup === 'function') {
+ chrome.webNavigation.onCreatedNavigationTarget.addListener(this.onPopup);
+ }
+ },
+ get: function(tabId, callback) {
+ if (tabId === null) {
+ chrome.tabs.query(
+ {
+ active: true,
+ currentWindow: true
+ },
+ function(tabs) {
+ callback(tabs[0]);
+ }
+ );
+ }
+ else {
+ chrome.tabs.get(tabId, callback);
+ }
+ },
+ /*open: function(details) {
+ // to keep incognito context?
+ chrome.windows.getCurrent(function(win) {
+ details.windowId = win.windowId;
+ chrome.tabs.create(details);
+ });
+ },*/
+ open: function(details) {
+ if (!details.url) {
+ return null;
+ }
+ // extension pages
+ else if (!details.url.match(/^\w{2,20}:/)) {
+ details.url = vAPI.getURL(details.url);
+ }
+
+ // dealing with Chrome's asynhronous API
+ var wrapper = function() {
+ if (details.active === undefined) {
+ details.active = true;
+ }
+
+ var subWrapper = function() {
+ var _details = {
+ url: details.url,
+ active: !!details.active
+ };
+
+ if (details.tabId) {
+ // update doesn't accept index, must use move
+ chrome.tabs.update(details.tabId, _details, function(tab) {
+ // if the tab doesn't exist
+ if (chrome.runtime.lastError) {
+ chrome.tabs.create(_details);
+ }
+ else if (details.index !== undefined) {
+ chrome.tabs.move(tab.id, {index: details.index});
+ }
+ });
+ }
+ else {
+ if (details.index !== undefined) {
+ _details.index = details.index;
+ }
+
+ chrome.tabs.create(_details);
+ }
+ };
+
+ if (details.index === -1) {
+ vAPI.tabs.get(null, function(tab) {
+ if (tab) {
+ details.index = tab.index + 1;
+ }
+ else {
+ delete details.index;
+ }
+
+ subWrapper();
+ });
+ }
+ else {
+ subWrapper();
+ }
+ };
+
+ if (details.select) {
+ // note that currentWindow may be even the window of Developer Tools
+ // so, test with setTimeout...
+ chrome.tabs.query({currentWindow: true}, function(tabs) {
+ var url = details.url.replace(rgxHash, '');
+ // this is questionable
+ var rgxHash = /#.*/;
+
+ tabs = tabs.some(function(tab) {
+ if (tab.url.replace(rgxHash, '') === url) {
+ chrome.tabs.update(tab.id, {active: true});
+ return true;
+ }
+ });
+
+ if (!tabs) {
+ wrapper();
+ }
+ });
+ }
+ else {
+ wrapper();
+ }
+ },
+ close: chrome.tabs.remove.bind(chrome.tabs)
+ };
+
+ // Must read: https://code.google.com/p/chromium/issues/detail?id=410868#c8
+
+ // https://github.com/gorhill/uBlock/issues/19
+ // https://github.com/gorhill/uBlock/issues/207
+ // Since we may be called asynchronously, the tab id may not exist
+ // anymore, so this ensures it does still exist.
+
+ vAPI.setIcon = function(tabId, img, badge) {
+ var onIconReady = function() {
+ if ( chrome.runtime.lastError ) {
+ return;
+ }
+
+ chrome.browserAction.setBadgeText({ tabId: tabId, text: badge });
+
+ if ( badge !== '' ) {
+ chrome.browserAction.setBadgeBackgroundColor({ tabId: tabId, color: '#666' });
+ }
+ };
+ chrome.browserAction.setIcon({ tabId: tabId, path: img }, onIconReady);
+ };
+
+ vAPI.messaging = {
+ ports: {},
+ listeners: {},
+ listen: function(name, callback) {
+ this.listeners[name] = callback;
+ },
+ setup: function(connector) {
+ if (this.connector) {
+ return;
+ }
+
+ this.connector = function(port) {
+ var onMessage = function(request) {
+ var callback = function(response) {
+ // stfu
+ if (chrome.runtime.lastError) {
+ return;
+ }
+
+ if (request.requestId) {
+ port.postMessage({
+ requestId: request.requestId,
+ portName: request.portName,
+ msg: response
+ });
+ }
+ };
+
+ var listener = connector(request.msg, port.sender, callback);
+
+ if (listener === null) {
+ listener = vAPI.messaging.listeners[request.portName];
+
+ if (typeof listener === 'function') {
+ listener(request.msg, port.sender, callback);
+ } else {
+ console.error('µBlock> messaging > unknown request: %o', request);
+ }
+ }
+ };
+
+ var onDisconnect = function(port) {
+ port.onDisconnect.removeListener(onDisconnect);
+ port.onMessage.removeListener(onMessage);
+ delete vAPI.messaging.ports[port.name];
+ };
+
+ port.onDisconnect.addListener(onDisconnect);
+ port.onMessage.addListener(onMessage);
+ vAPI.messaging.ports[port.name] = port;
+ };
+
+ chrome.runtime.onConnect.addListener(this.connector);
+ },
+ broadcast: function(message) {
+ message = {
+ broadcast: true,
+ msg: message
+ };
+
+ for (var portName in this.ports) {
+ this.ports[portName].postMessage(message);
+ }
+ }
+ };
+
+ vAPI.net = {
+ registerListeners: function() {
+ var listeners = [
+ 'onBeforeRequest',
+ 'onBeforeSendHeaders',
+ 'onHeadersReceived'
+ ];
+
+ for (var i = 0; i < listeners.length; ++i) {
+ chrome.webRequest[listeners[i]].addListener(
+ this[listeners[i]].callback,
+ {
+ 'urls': this[listeners[i]].urls || ['<all_urls>'],
+ 'types': this[listeners[i]].types || []
+ },
+ this[listeners[i]].extra
+ );
+ }
+ }
+ };
+
+ vAPI.contextMenu = {
+ create: function(details, callback) {
+ this.menuId = details.id;
+ this.callback = callback;
+ chrome.contextMenus.create(details);
+ chrome.contextMenus.onClicked.addListener(this.callback);
+ },
+ remove: function() {
+ chrome.contextMenus.onClicked.removeListener(this.callback);
+ chrome.contextMenus.remove(this.menuId);
+ }
+ };
+} else if (window.safari) {
+ vAPI.safari = true;
+
+ 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: 50 * 1024 * 1024,
+ 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,
+ 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
+ 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 onUpdated === 'function') {
+ chrome.tabs.onUpdated.addListener(this.onUpdated);
+ }*/
+
+ // onClosed handled in the main tab-close event
+
+ // maybe intercept window.open on web-pages?
+ /*if (typeof onPopup === 'function') {
+ chrome.webNavigation.onCreatedNavigationTarget.addListener(this.onPopup);
+ }*/
+ },
+ getTabId: function(tab) {
+ for (var i in vAPI.tabs.stack) {
+ if (vAPI.tabs.stack[i] === tab) {
+ return +i;
+ }
+ }
+
+ return -1;
+ },
+ 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
+ });
+ },
+ open: function(details) {
+ if (!details.url) {
+ return null;
+ }
+ // extension pages
+ else if (!details.url.match(/^\w{2,20}:/)) {
+ details.url = vAPI.getURL(details.url);
+ }
+
+ // 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
+
+ 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;
+ },
+ close: function(tab) {
+ if (!(tab instanceof SafariBrowserTab)) {
+ tab = this.stack[tab];
+ }
+
+ if (tab) {
+ tab.close();
+ }
+ }
+ };
+
+
+ // 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 the selected tab has the same ID, then update the badge too,
+ // or always update it when changing tabs ('activate' event)
+ if (tabId === curTabId) {
+ 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: {},
+ listen: function(name, callback) {
+ this.listeners[name] = callback;
+ },
+ setup: function(connector) {
+ if (this.connector) {
+ return;
+ }
+
+ this.connector = function(request) {
+ if (request.name === 'canLoad') {
+ return;
+ }
+
+ var callback = function(response) {
+ if (request.message.requestId) {
+ request.target.page.dispatchMessage(
+ 'message',
+ {
+ requestId: request.message.requestId,
+ portName: request.message.portName,
+ msg: response
+ }
+ );
+ }
+ };
+
+ var sender = {
+ tab: {
+ id: vAPI.tabs.getTabId(request.target)
+ }
+ };
+
+ var listener = connector(request.message.msg, sender, callback);
+
+ if (listener === null) {
+ listener = vAPI.messaging.listeners[request.message.portName];
+
+ if (typeof listener === 'function') {
+ listener(request.message.msg, sender, callback);
+ } else {
+ console.error('µBlock> messaging > unknown request: %o', request.message);
+ }
+ }
+ };
+
+ safari.application.addEventListener('message', this.connector, false);
+ },
+ broadcast: function(message) {
+ message = {
+ broadcast: true,
+ msg: message
+ };
+
+ for (var tabId in vAPI.tabs.stack) {
+ vAPI.tabs.stack[tabId].page.dispatchMessage('message', message);
+ }
+ }
+ };
+
+ vAPI.net = {
+ registerListeners: function() {
+ // onBeforeRequest is used in the messaging above, in the connector method
+ // in order to use only one listener
+ var onBeforeRequest = this.onBeforeRequest;
+
+ if (typeof onBeforeRequest.callback === 'function') {
+ if (!Array.isArray(onBeforeRequest.types)) {
+ onBeforeRequest.types = [];
+ }
+
+ onBeforeRequest = onBeforeRequest.callback;
+ this.onBeforeRequest.callback = function(request) {
+ if (request.name !== 'canLoad') {
+ return;
+ }
+
+ // no stopPropagation if it was called from beforeNavigate event
+ if (request.stopPropagation) {
+ request.stopPropagation();
+ }
+
+ var block = vAPI.net.onBeforeRequest;
+
+ if (block.types.indexOf(request.message.type) < 0) {
+ return;
+ }
+
+ request.message.tabId = vAPI.tabs.getTabId(request.target);
+ block = onBeforeRequest(request.message);
+
+ // truthy return value will allow the request,
+ // except when redirectUrl is present
+ if (block && typeof block === 'object') {
+ if (block.cancel) {
+ request.message = false;
+ }
+ else if (typeof block.redirectUrl === "string") {
+ request.message = block.redirectUrl;
+ }
+ else {
+ request.message = true;
+ }
+ }
+ else {
+ request.message = true;
+ }
+
+ return request.message;
+ };
+ safari.application.addEventListener('message', this.onBeforeRequest.callback, true);
+
+ // 'main_frame' simulation, since this isn't available in beforeload
+ safari.application.addEventListener('beforeNavigate', function(e) {
+ // e.url is not present for local files or data URIs
+ if (!e.url) {
+ return;
+ }
+
+ vAPI.net.onBeforeRequest.callback({
+ name: 'canLoad',
+ target: e.target,
+ message: {
+ url: e.url,
+ type: 'main_frame',
+ frameId: 0,
+ parentFrameId: -1,
+ timeStamp: e.timeStamp
+ }
+ }) || e.preventDefault();
+ }, true);
+ }
+ }
+ };
+
+ 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.onContextMenuCommand = 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.onContextMenuCommand);
+ },
+ remove: function(argument) {
+ safari.application.removeEventListener('contextmenu', this.onContextMenu);
+ safari.application.removeEventListener("command", this.onContextMenuCommand);
+ this.onContextMenu = null;
+ this.onContextMenuCommand = null;
+ }
+ };
+}
+
+if (!window.chrome) {
+ window.chrome = { runtime: { lastError: null } };
+}
+})();
diff --git a/src/js/vapi-client.js b/src/js/vapi-client.js
new file mode 100644
index 0000000..76058e1
--- /dev/null
+++ b/src/js/vapi-client.js
@@ -0,0 +1,335 @@
+// for non background pages
+/* global chrome, Components, safari */
+
+(function() {
+'use strict';
+
+window.vAPI = window.vAPI || {};
+
+// since this is common across vendors
+var messagingConnector = function(response) {
+ var channel, listener;
+
+ if (!response) {
+ return;
+ }
+
+ 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];
+
+ if (!listener) {
+ channel = vAPI.messaging.channels[response.portName];
+ listener = channel && channel.listener;
+ }
+ }
+
+ if (typeof listener === 'function') {
+ delete vAPI.messaging.listeners[response.requestId];
+ delete response.requestId;
+ listener(response.msg);
+ }
+};
+
+if (window.chrome) {
+ vAPI.messaging = {
+ port: null,
+ requestId: 0,
+ listenerId: null,
+ listeners: {},
+ channels: {},
+ connector: messagingConnector,
+ setup: function() {
+ this.listenerId = 'uBlock:' + name + ':' + parseInt(Math.random() * 1e10, 10).toString(36);
+ this.port = chrome.runtime.connect({name: this.listenerId});
+ this.port.onMessage.addListener(this.connector);
+ },
+ close: function() {
+ if (this.port) {
+ this.port.disconnect();
+ this.port.onMessage.removeListener(this.connector);
+ this.channels = this.listeners = this.port = this.listenerId = null;
+ }
+ },
+ channel: function(name, callback) {
+ if (!name) {
+ return;
+ }
+
+ if (!this.listenerId) {
+ this.setup();
+ }
+
+ this.channels[name] = {
+ portName: name,
+ listener: typeof callback === 'function' ? callback : null,
+ send: function(message, callback) {
+ message = {
+ portName: this.portName,
+ msg: message
+ };
+
+ if (callback) {
+ message.requestId = ++vAPI.messaging.requestId;
+ vAPI.messaging.listeners[message.requestId] = callback;
+ }
+
+ vAPI.messaging.port.postMessage(message);
+ },
+ close: function() {
+ delete vAPI.messaging.channels[this.portName];
+ }
+ };
+
+ return this.channels[name];
+ }
+ };
+} else if (window.safari) {
+ 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;
+ details.type = 'xmlhttprequest';
+ }
+ 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';
+ }
+ }
+
+ // tabId is determined in the background script
+ // details.tabId = null;
+ details.frameId = 0;
+ details.parentFrameId = window === window.top ? -1 : 0;
+ details.timeStamp = Date.now();
+
+ var response = safari.self.tab.canLoad(e, details);
+
+ if (!response) {
+ e.preventDefault();
+ return false;
+ }
+ // local mirroring, response is a data: URL here
+ else if (typeof response === 'string') {
+ if (details.type === 'script') {
+ e.preventDefault();
+ return response;
+ }
+ else if (details.type === 'script') {
+ e.preventDefault();
+ details = document.createElement('script');
+ details.textContent = atob(response.slice(35));
+ e.target.parentNode.insertBefore(details, e.target);
+ details.parentNode.removeChild(details);
+ }
+ }
+ };
+
+ // intercepting xhr requests
+ setTimeout(function() {
+ if (location.protocol === "safari-extension:") {
+ return;
+ }
+
+ var randomEventName = parseInt(Math.random() * 1e15, 10).toString(36);
+ var beforeLoadEvent = document.createEvent('Event');
+ beforeLoadEvent.initEvent('beforeload');
+
+ window.addEventListener(randomEventName, function(e) {
+ var result = onBeforeLoad(beforeLoadEvent, e.detail);
+
+ if (onBeforeLoad(beforeLoadEvent, e.detail) === false) {
+ e.detail.url = false;
+ }
+ else if (typeof result === 'string') {
+ e.detail.url = result;
+ }
+ }, true);
+
+ // since the extension context is unable to reach the page context
+ var tempScript = document.createElement('script');
+ tempScript.onload = function() {
+ this.parentNode.removeChild(this);
+ };
+ document.head.appendChild(tempScript).src = "data:application/x-javascript;base64," + btoa(["(function() {",
+ "var xhr_open = XMLHttpRequest.prototype.open;",
+
+ "XMLHttpRequest.prototype.open = function(method, url, async, u, p) {",
+ "var ev = document.createEvent('CustomEvent');",
+ "var detail = {url: url};",
+ "ev.initCustomEvent(",
+ "'" + randomEventName + "',",
+ "false, false,",
+ "detail",
+ ");",
+ "window.dispatchEvent(ev);",
+ "if (detail.url === false) {",
+ "throw Error;",
+ "}",
+ "else if (typeof detail.url === 'string') {",
+ "url = detail.url;",
+ "}",
+ "return xhr_open.call(this, method, url, async, u, p);",
+ "};",
+ "})();"].join(''));
+ }, 0);
+
+ document.addEventListener('beforeload', onBeforeLoad, true);
+
+ // relevant?
+ // https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/MessagesandProxies/MessagesandProxies.html#//apple_ref/doc/uid/TP40009977-CH14-SW12
+ vAPI.messaging = {
+ port: null,
+ requestId: 0,
+ listeners: {},
+ channels: {},
+ connector: messagingConnector,
+ setup: function() {
+ this._connector = function(msg) {
+ vAPI.messaging.connector(msg.message);
+ };
+ safari.self.addEventListener('message', this._connector, false);
+ },
+ close: function() {
+ if (this._connector) {
+ safari.self.removeEventListener('message', this._connector, false);
+ }
+ },
+ channel: function(name, callback) {
+ if (!name) {
+ return;
+ }
+
+ if (!this._connector) {
+ this.setup();
+ }
+
+ this.channels[name] = {
+ portName: name,
+ listener: typeof callback === 'function' ? callback : null,
+ send: function(message, callback) {
+ message = {
+ portName: this.portName,
+ msg: message
+ };
+
+ if (callback) {
+ message.requestId = ++vAPI.messaging.requestId;
+ vAPI.messaging.listeners[message.requestId] = callback;
+ }
+
+ if (safari.extension.globalPage) {
+ // popover content doesn't know messaging...
+ safari.extension.globalPage.contentWindow
+ .vAPI.messaging.connector({
+ name: 'message',
+ message: message,
+ target: {
+ page: {
+ dispatchMessage: function(name, msg) {
+ vAPI.messaging.connector(msg);
+ }
+ }
+ }
+ });
+ }
+ else {
+ safari.self.tab.dispatchMessage('message', message);
+ }
+ },
+ close: function() {
+ delete vAPI.messaging.channels[this.portName];
+ }
+ };
+
+ return this.channels[name];
+ }
+ };
+
+ var onContextMenu = function(e) {
+ var details = {
+ tagName: e.target.tagName.toLowerCase(),
+ pageUrl: window.location.href,
+ insideFrame: window.top !== window
+ };
+
+ 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);
+ };
+
+ window.addEventListener('contextmenu', onContextMenu, true);
+}
+
+})();
diff --git a/src/js/vapi-common.js b/src/js/vapi-common.js
new file mode 100644
index 0000000..2997a11
--- /dev/null
+++ b/src/js/vapi-common.js
@@ -0,0 +1,62 @@
+// only for background and other extension pages
+/* global chrome, Components, BeforeLoadEvent */
+
+(function() {
+'use strict';
+
+window.vAPI = window.vAPI || {};
+
+if (window.chrome) {
+ var chrome = window.chrome;
+
+ vAPI.getURL = function(path) {
+ return chrome.runtime.getURL(path);
+ };
+
+ vAPI.i18n = function(s) {
+ return chrome.i18n.getMessage(s) || s;
+ };
+} else if (window.safari) {
+ vAPI.getURL = function(path) {
+ return safari.extension.baseURI + path;
+ };
+
+ var xhr = new XMLHttpRequest;
+ xhr.overrideMimeType('application/json;charset=utf-8');
+ xhr.open('GET', './locales.json', false);
+ xhr.send();
+ vAPI.i18nData = JSON.parse(xhr.responseText);
+
+ if (vAPI.i18nData[vAPI.i18n = navigator.language.replace('-', '_')]
+ || vAPI.i18nData[vAPI.i18n = vAPI.i18n.slice(0, 2)]) {
+ vAPI.i18nAlpha2 = vAPI.i18n;
+ } else {
+ vAPI.i18nAlpha2 = vAPI.i18nData._;
+ }
+
+ xhr = new XMLHttpRequest;
+ xhr.overrideMimeType('application/json;charset=utf-8');
+ xhr.open('GET', './_locales/' + vAPI.i18nAlpha2 + '/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' && safari.self) {
+ vAPI.updatePopoverSize = function() {
+ safari.self.width = document.body.clientWidth;
+ safari.self.height = document.body.clientHeight;
+ };
+
+ setTimeout(vAPI.updatePopoverSize, 200);
+ }
+}
+
+})(); \ No newline at end of file
diff --git a/js/whitelist.js b/src/js/whitelist.js
index ee306f5..b23b261 100644
--- a/js/whitelist.js
+++ b/src/js/whitelist.js
@@ -19,7 +19,7 @@
Home: https://github.com/gorhill/uBlock
*/
-/* global chrome, messaging, uDom */
+/* global chrome, vAPI, uDom */
/******************************************************************************/
@@ -27,13 +27,13 @@
/******************************************************************************/
-messaging.start('whitelist.js');
+var messager = vAPI.messaging.channel('whitelist.js');
/******************************************************************************/
var cachedWhitelist = '';
-// Could make it more fancy if needed. But speed... It's a compromise.
+// Could make it more fancy if needed. But speed... It's a compromise.
var reUnwantedChars = /[\x00-\x09\x0b\x0c\x0e-\x1f!"#$'()<>{}|\\^\[\]`~]/;
/******************************************************************************/
@@ -55,7 +55,7 @@ var renderWhitelist = function() {
cachedWhitelist = whitelist;
uDom('#whitelist').val(cachedWhitelist);
};
- messaging.ask({ what: 'getWhitelist' }, onRead);
+ messager.send({ what: 'getWhitelist' }, onRead);
};
/******************************************************************************/
@@ -107,7 +107,7 @@ var whitelistApplyHandler = function() {
what: 'setWhitelist',
whitelist: cachedWhitelist
};
- messaging.tell(request);
+ messager.send(request);
whitelistChanged();
};
diff --git a/js/xal.js b/src/js/xal.js
index 3ddc6e4..db474ce 100644
--- a/js/xal.js
+++ b/src/js/xal.js
@@ -32,27 +32,6 @@ var noopFunc = function(){};
/******************************************************************************/
-// Must read: https://code.google.com/p/chromium/issues/detail?id=410868#c8
-
-// https://github.com/gorhill/uBlock/issues/19
-// https://github.com/gorhill/uBlock/issues/207
-// Since we may be called asynchronously, the tab id may not exist
-// anymore, so this ensures it does still exist.
-
-exports.setIcon = function(id, imgDict, overlayStr) {
- var onIconReady = function() {
- if ( chrome.runtime.lastError ) {
- return;
- }
- chrome.browserAction.setBadgeText({ tabId: id, text: overlayStr });
- if ( overlayStr !== '' ) {
- chrome.browserAction.setBadgeBackgroundColor({ tabId: id, color: '#666' });
- }
- };
- chrome.browserAction.setIcon({ tabId: id, path: imgDict }, onIconReady);
-};
-
-/******************************************************************************/
exports.injectScript = function(id, details) {
chrome.tabs.executeScript(id, details);
@@ -63,31 +42,37 @@ exports.injectScript = function(id, details) {
exports.keyvalSetOne = function(key, val, callback) {
var bin = {};
bin[key] = val;
- chrome.storage.local.set(bin, callback || noopFunc);
+ vAPI.storage.set(bin, callback || noopFunc);
};
/******************************************************************************/
exports.keyvalSetMany = function(dict, callback) {
- chrome.storage.local.set(dict, callback || noopFunc);
+ vAPI.storage.set(dict, callback || noopFunc);
};
/******************************************************************************/
exports.keyvalRemoveAll = function(callback) {
- chrome.storage.local.clear(callback || noopFunc);
+ vAPI.storage.clear(callback || noopFunc);
};
/******************************************************************************/
exports.restart = function() {
- chrome.runtime.reload();
+ if (vAPI.chrome) {
+ chrome.runtime.reload();
+ }
+
+ // TODO? for cross-browser solution:
+ // window.location.reload();
+ // plus close all extension tabs
};
/******************************************************************************/
exports.destroyTab = function(tabId) {
- chrome.tabs.remove(tabId, function() {
+ vAPI.tabs.remove(tabId, function() {
// required by chrome API, or else warnings at console (also, mind jshint)
if ( chrome.runtime.lastError ) {
}
diff --git a/lib/publicsuffixlist.min.js b/src/lib/publicsuffixlist.min.js
index e114a8e..e114a8e 100644
--- a/lib/publicsuffixlist.min.js
+++ b/src/lib/publicsuffixlist.min.js
diff --git a/lib/punycode.min.js b/src/lib/punycode.min.js
index 4016a00..4016a00 100644
--- a/lib/punycode.min.js
+++ b/src/lib/punycode.min.js
diff --git a/lib/yamd5.js b/src/lib/yamd5.js
index d4b747a..d4b747a 100644
--- a/lib/yamd5.js
+++ b/src/lib/yamd5.js
diff --git a/src/locales.json b/src/locales.json
new file mode 100644
index 0000000..34fb265
--- /dev/null
+++ b/src/locales.json
@@ -0,0 +1 @@
+{"_": "en", "ar": 1, "cs": 1, "da": 1, "de": 1, "el": 1, "en": 1, "es": 1, "et": 1, "fi": 1, "fr": 1, "he": 1, "hr": 1, "hu": 1, "id": 1, "it": 1, "ja": 1, "nb": 1, "nl": 1, "pl": 1, "pt-BR": 1, "pt-PT": 1, "ro": 1, "ru": 1, "sv": 1, "tr": 1, "uk": 1, "vi": 1, "zh-CN": 1} \ No newline at end of file
diff --git a/manifest.json b/src/manifest.json
index befb99f..38f1938 100644
--- a/manifest.json
+++ b/src/manifest.json
@@ -1,42 +1,24 @@
{
"manifest_version": 2,
- "name": "__MSG_extName__",
- "short_name": "µBlock",
+ "minimum_chrome_version": "22.0",
+ "default_locale": "en",
+ "update_url": "https://clients2.google.com/service/update2/crx",
+
"version": "0.7.0.10",
+ "name": "__MSG_extName__",
"description": "__MSG_extShortDesc__",
+ "homepage_url": "https://github.com/gorhill/uBlock",
+ "author": "Raymond Hill",
+ "developer": {
+ "name": "Raymond Hill",
+ "email": "rhill@raymondhill.net"
+ },
+
"icons": {
"16": "img/icon_16.png",
"128": "img/icon_128.png"
},
- "browser_action": {
- "default_icon": {
- "19": "img/browsericons/icon19-off.png",
- "38": "img/browsericons/icon38-off.png"
- },
- "default_title": "__MSG_extName__",
- "default_popup": "popup.html"
- },
- "author": "Raymond Hill",
- "background": {
- "page": "background.html"
- },
- "content_scripts": [
- {
- "matches": ["http://*/*", "https://*/*"],
- "js": ["js/contentscript-start.js"],
- "run_at": "document_start",
- "all_frames": true
- },
- {
- "matches": ["http://*/*", "https://*/*"],
- "js": ["js/contentscript-end.js"],
- "run_at": "document_end",
- "all_frames": true
- }
- ],
- "default_locale": "en",
- "minimum_chrome_version": "22.0",
- "options_page": "dashboard.html",
+
"permissions": [
"contextMenus",
"downloads",
@@ -48,5 +30,33 @@
"webRequestBlocking",
"http://*/*",
"https://*/*"
- ]
+ ],
+
+ "background": {
+ "page": "background.html"
+ },
+ "options_page": "dashboard.html",
+ "content_scripts": [
+ {
+ "matches": ["http://*/*", "https://*/*"],
+ "js": ["js/vapi-client.js", "js/contentscript-start.js"],
+ "run_at": "document_start",
+ "all_frames": true
+ },
+ {
+ "matches": ["http://*/*", "https://*/*"],
+ "js": ["js/contentscript-end.js"],
+ "run_at": "document_end",
+ "all_frames": true
+ }
+ ],
+
+ "browser_action": {
+ "default_icon": {
+ "19": "img/browsericons/icon19-off.png",
+ "38": "img/browsericons/icon38-off.png"
+ },
+ "default_title": "µBlock",
+ "default_popup": "popup.html"
+ }
}
diff --git a/popup.html b/src/popup.html
index 4759aff..0c2ea30 100644
--- a/popup.html
+++ b/src/popup.html
@@ -52,10 +52,14 @@
<div class="label">&lt;iframe&gt;</div>
</div>
</div>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/popup.js"></script>
+<script src="js/js-loader.js" data-jsList="
+js/vapi-common.js
+js/vapi-client.js
+js/udom.js
+js/i18n.js
+js/popup.js
+"></script>
+
</body>
</html>
diff --git a/settings.html b/src/settings.html
index 4945037..8b80569 100644
--- a/settings.html
+++ b/src/settings.html
@@ -18,18 +18,21 @@ ul {
<body>
<ul>
- <li><input id="collapse-blocked" type="checkbox"> <label data-i18n="settingsCollapseBlockedPrompt" for="collapse-blocked"></label>
- <li><input id="icon-badge" type="checkbox"> <label data-i18n="settingsIconBadgePrompt" for="icon-badge"></label>
+ <li><input id="collapse-blocked" type="checkbox"><label data-i18n="settingsCollapseBlockedPrompt" for="collapse-blocked"></label>
+ <li><input id="icon-badge" type="checkbox"><label data-i18n="settingsIconBadgePrompt" for="icon-badge"></label>
<li><input id="context-menu-enabled" type="checkbox"><label data-i18n="settingsContextMenuPrompt" for="context-menu-enabled"></label>
<li><input id="experimental-enabled" type="checkbox"><label data-i18n="settingsExperimentalPrompt" for="experimental-enabled"></label>
(<a href="https://github.com/gorhill/uBlock/wiki/Experimental-features" style="font-style:italic">Experimental features</a>)
</ul>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/dashboard-common.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/settings.js"></script>
+<script src="js/js-loader.js" data-jsList="
+js/vapi-common.js
+js/vapi-client.js
+js/udom.js
+js/i18n.js
+js/dashboard-common.js
+js/settings.js
+"></script>
</body>
</html>
diff --git a/stats.html b/src/stats.html
index 6ac8483..990cdf3 100644
--- a/stats.html
+++ b/src/stats.html
@@ -113,11 +113,14 @@ tr.logMirrored {
</div>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/dashboard-common.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/stats.js"></script>
+<script src="js/js-loader.js" data-jsList="
+js/vapi-common.js
+js/vapi-client.js
+js/udom.js
+js/i18n.js
+js/dashboard-common.js
+js/stats.js
+"></script>
</body>
</html>
diff --git a/whitelist.html b/src/whitelist.html
index ea79f49..77abe7c 100644
--- a/whitelist.html
+++ b/src/whitelist.html
@@ -18,12 +18,15 @@
<p><button id="whitelistApply" type="button" disabled="true" data-i18n="whitelistApply"></button></p>
</div>
-<script src="lib/punycode.min.js"></script>
-<script src="js/udom.js"></script>
-<script src="js/i18n.js"></script>
-<script src="js/dashboard-common.js"></script>
-<script src="js/messaging-client.js"></script>
-<script src="js/whitelist.js"></script>
+<script src="js/js-loader.js" data-jsList="
+lib/punycode.min.js
+js/vapi-common.js
+js/vapi-client.js
+js/udom.js
+js/i18n.js
+js/dashboard-common.js
+js/whitelist.js
+"></script>
</body>
</html>
diff --git a/tools/build_meta.py b/tools/build_meta.py
new file mode 100644
index 0000000..0701e6a
--- /dev/null
+++ b/tools/build_meta.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+
+import os
+import re
+import json
+from time import strftime
+from datetime import datetime
+from shutil import rmtree as rmt
+from collections import OrderedDict
+from xml.sax.saxutils import escape
+
+osp = os.path
+pj = osp.join
+
+os.chdir('..')
+
+
+def rmtree(path):
+ if osp.exists(path):
+ rmt(path)
+
+
+def mkdirs(path):
+ try:
+ os.makedirs(path)
+ finally:
+ return osp.exists(path)
+
+
+meta_dir = pj('meta')
+src_dir = pj('src')
+
+with open(pj(meta_dir, 'config.json'), encoding='utf-8') as f:
+ config = json.load(f)
+
+vendors = config['vendors']
+del config['vendors']
+
+src_dir = pj('src')
+source_locale_dir = pj('src', '_locales')
+target_locale_dir = pj('src', 'locale')
+descriptions = OrderedDict({})
+
+tmp = datetime.now() - datetime(year=datetime.today().year, month=1, day=1)
+config['build_number'] = strftime('%y' + str(int(tmp.total_seconds() * 65535 / 31536000)).zfill(5))
+
+rmtree(target_locale_dir)
+
+for alpha2 in os.listdir(source_locale_dir):
+ with open(pj(source_locale_dir, alpha2, 'messages.json'), encoding='utf-8') as f:
+ string_data = json.load(f, object_pairs_hook=OrderedDict)
+
+ alpha2 = alpha2.replace('_', '-')
+
+ mkdirs(pj(target_locale_dir, alpha2))
+
+ with open(pj(target_locale_dir, alpha2, 'messages.properties'), 'wt', encoding='utf-8', newline='\n') as f:
+ descriptions[alpha2] = {}
+
+ for string_name in string_data:
+ if string_name == 'extShortDesc':
+ descriptions[alpha2] = string_data[string_name]['message']
+
+ f.write(string_name)
+ f.write('=')
+ f.write(string_data[string_name]['message'].replace('\n', r'\n'))
+ f.write('\n')
+
+
+with open(pj(src_dir, 'locales.json'), 'wt', encoding='utf-8', newline='\n') as f:
+ tmp = {
+ '_': config['def_lang']
+ }
+
+ for alpha2 in descriptions:
+ tmp[alpha2] = 1
+
+ json.dump(tmp, f, sort_keys=True, ensure_ascii=False)
+
+
+with open(pj(src_dir, vendors['crx']['manifest']), 'wt', encoding='utf-8', newline='\n') as f:
+ with open(pj(meta_dir, 'crx', vendors['crx']['manifest']), 'r') as cf:
+ cf_content = cf.read()
+
+ f.write(
+ re.sub(r"\{(?=\W)|(?<=\W)\}", r'\g<0>\g<0>', cf_content).format(**config)
+ )
diff --git a/tools/import-crowdin.sh b/tools/import-crowdin.sh
new file mode 100644
index 0000000..810b06a
--- /dev/null
+++ b/tools/import-crowdin.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+#
+# This script assumes a linux environment
+
+echo "*** uBlock: Importing from Crowdin archive"
+rm -r ~/Downloads/crowdin
+unzip -q ~/Downloads/ublock.zip -d ~/Downloads/crowdin
+cp ~/Downloads/crowdin/ar/messages.json ../src/_locales/ar/messages.json
+cp ~/Downloads/crowdin/cs/messages.json ../src/_locales/cs/messages.json
+cp ~/Downloads/crowdin/da/messages.json ../src/_locales/da/messages.json
+cp ~/Downloads/crowdin/el/messages.json ../src/_locales/el/messages.json
+cp ~/Downloads/crowdin/es-ES/messages.json ../src/_locales/es/messages.json
+cp ~/Downloads/crowdin/et/messages.json ../src/_locales/et/messages.json
+cp ~/Downloads/crowdin/fi/messages.json ../src/_locales/fi/messages.json
+cp ~/Downloads/crowdin/he/messages.json ../src/_locales/he/messages.json
+cp ~/Downloads/crowdin/hi/messages.json ../src/_locales/hi/messages.json
+cp ~/Downloads/crowdin/hr/messages.json ../src/_locales/hr/messages.json
+cp ~/Downloads/crowdin/hu/messages.json ../src/_locales/hu/messages.json
+cp ~/Downloads/crowdin/id/messages.json ../src/_locales/id/messages.json
+cp ~/Downloads/crowdin/it/messages.json ../src/_locales/it/messages.json
+cp ~/Downloads/crowdin/ja/messages.json ../src/_locales/ja/messages.json
+cp ~/Downloads/crowdin/mr/messages.json ../src/_locales/mr/messages.json
+cp ~/Downloads/crowdin/no/messages.json ../src/_locales/nb/messages.json
+cp ~/Downloads/crowdin/nl/messages.json ../src/_locales/nl/messages.json
+cp ~/Downloads/crowdin/pl/messages.json ../src/_locales/pl/messages.json
+cp ~/Downloads/crowdin/pt-BR/messages.json ../src/_locales/pt_BR/messages.json
+cp ~/Downloads/crowdin/pt-PT/messages.json ../src/_locales/pt_PT/messages.json
+cp ~/Downloads/crowdin/ro/messages.json ../src/_locales/ro/messages.json
+cp ~/Downloads/crowdin/ru/messages.json ../src/_locales/ru/messages.json
+cp ~/Downloads/crowdin/sv-SE/messages.json ../src/_locales/sv/messages.json
+cp ~/Downloads/crowdin/tr/messages.json ../src/_locales/tr/messages.json
+cp ~/Downloads/crowdin/uk/messages.json ../src/_locales/uk/messages.json
+cp ~/Downloads/crowdin/vi/messages.json ../src/_locales/vi/messages.json
+cp ~/Downloads/crowdin/zh-CN/messages.json ../src/_locales/zh_CN/messages.json
+
+#
+
+cp ~/Downloads/crowdin/ar/description.txt ../dist/description/description-ar.txt
+cp ~/Downloads/crowdin/cs/description.txt ../dist/description/description-cs.txt
+cp ~/Downloads/crowdin/da/description.txt ../dist/description/description-da.txt
+#cp ~/Downloads/crowdin/el/description.txt ../dist/description/description-el.txt
+cp ~/Downloads/crowdin/es-ES/description.txt ../dist/description/description-es.txt
+cp ~/Downloads/crowdin/et/description.txt ../dist/description/description-et.txt
+cp ~/Downloads/crowdin/fi/description.txt ../dist/description/description-fi.txt
+cp ~/Downloads/crowdin/he/description.txt ../dist/description/description-he.txt
+cp ~/Downloads/crowdin/hr/description.txt ../dist/description/description-hr.txt
+cp ~/Downloads/crowdin/hu/description.txt ../dist/description/description-hu.txt
+cp ~/Downloads/crowdin/id/description.txt ../dist/description/description-id.txt
+cp ~/Downloads/crowdin/it/description.txt ../dist/description/description-it.txt
+#cp ~/Downloads/crowdin/ja/description.txt ../dist/description/description-ja.txt
+cp ~/Downloads/crowdin/no/description.txt ../dist/description/description-no.txt
+cp ~/Downloads/crowdin/nl/description.txt ../dist/description/description-nl.txt
+cp ~/Downloads/crowdin/pl/description.txt ../dist/description/description-pl.txt
+cp ~/Downloads/crowdin/pt-BR/description.txt ../dist/description/description-pt_BR.txt
+cp ~/Downloads/crowdin/pt-PT/description.txt ../dist/description/description-pt_PT.txt
+cp ~/Downloads/crowdin/ro/description.txt ../dist/description/description-ro.txt
+cp ~/Downloads/crowdin/ru/description.txt ../dist/description/description-ru.txt
+cp ~/Downloads/crowdin/sv-SE/description.txt ../dist/description/description-sv.txt
+cp ~/Downloads/crowdin/tr/description.txt ../dist/description/description-tr.txt
+cp ~/Downloads/crowdin/uk/description.txt ../dist/description/description-uk.txt
+#cp ~/Downloads/crowdin/vi/description.txt ../dist/description/description-vi.txt
+cp ~/Downloads/crowdin/zh-CN/description.txt ../dist/description/description-zh_CN.txt
+
+#
+
+rm -r ~/Downloads/crowdin
+echo "*** uBlock: Import done."
diff --git a/tools/make-chrome.sh b/tools/make-chrome.sh
new file mode 100644
index 0000000..93f1625
--- /dev/null
+++ b/tools/make-chrome.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# This script assumes a linux environment
+
+echo "*** uBlock: Creating web store package"
+echo "*** uBlock: Copying files"
+cp -R assets ../dist/ublock/
+rm ../dist/ublock/assets/*.sh
+cp -R css ../dist/ublock/
+cp -R img ../dist/ublock/
+cp -R js ../dist/ublock/
+cp -R lib ../dist/ublock/
+cp -R _locales ../dist/ublock/
+cp *.html ../dist/ublock/
+cp *.txt ../dist/ublock/
+cp manifest.json ../dist/ublock/
+echo "*** uBlock: Package done."
diff --git a/make-clean.sh b/tools/make-clean.sh
index a110926..1b5eb31 100755..100644
--- a/make-clean.sh
+++ b/tools/make-clean.sh
@@ -3,5 +3,5 @@
# This script assumes a linux environment
echo "*** uBlock: Cleaning."
-rm -R dist/ublock/*
+rm -R ../dist/ublock/*
echo "*** uBlock: Cleaned."
diff --git a/tools/make-noassets.sh b/tools/make-noassets.sh
new file mode 100644
index 0000000..ff11b68
--- /dev/null
+++ b/tools/make-noassets.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#
+# This script assumes a linux environment
+
+echo "*** uBlock: Creating web store package"
+echo "*** uBlock: Copying files"
+cp -R css ../dist/ublock/
+cp -R img ../dist/ublock/
+cp -R js ../dist/ublock/
+cp -R lib ../dist/ublock/
+cp -R _locales ../dist/ublock/
+cp *.html ../dist/ublock/
+cp *.txt ../dist/ublock/
+cp manifest.json ../dist/ublock/
+echo "*** uBlock: Package done."
diff --git a/make-opera.sh b/tools/make-opera.sh
index 7eaaddd..f1f5a38 100755
--- a/make-opera.sh
+++ b/tools/make-opera.sh
@@ -4,7 +4,7 @@
echo "*** uBlock: Creating Opera web store package"
./make-chrome.sh
-rm -r dist/ublock/_locales/el
-rm -r dist/ublock/_locales/ja
-rm -r dist/ublock/_locales/vi
+rm -r ../dist/ublock/_locales/el
+rm -r ../dist/ublock/_locales/ja
+rm -r ../dist/ublock/_locales/vi
echo "*** uBlock: Opera package done."