diff --git a/.travis.yml b/.travis.yml index 43c8d42cd17ec..bf2a42cc89bc5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,6 @@ script: ./tools/make-${BROWSER}.sh all deploy: provider: releases prerelease: true - # https://github.com/travis-ci/travis-ci/issues/6772 - edge: - branch: releases-fix api_key: secure: EnAMNsPbnS2I0JDkCWiY/6WLERsUbE2Ni5j9ap8YbZt4+sJv7aSoufWZ+0TZvSwr/w5MKCCDKhwXaPfbUwvqrI+eZv6LBXhwajK9Zla25FVjtdGCwKXQ3ZU85PHgL+5FYtuSGACmQj/ruAdSgrI7PgS08e5lqSgEk6lY4y3/6fE= file: dist/build/uBlock0.${BROWSER}.${EXT} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b3ef10f656f5c..ad12233853dd5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Submitting issues -For **support/discussions**, there is [Mozilla Discourse](https://discourse.mozilla-community.org/t/support-ublock-origin/6746). +For **support/discussions/help**, there is [/r/uBlockOrigin](https://www.reddit.com/r/uBlockOrigin/) on Reddit -- this is where I see the most activity for people helping each other regarding uBlock Origin. For **filter-related issues**, report on the respective filter list support site, or at [uBlockOrigin/uAssets](https://github.com/uBlockOrigin/uAssets/issues). Use [the logger](https://github.com/gorhill/uBlock/wiki/The-logger) to diagnose/confirm filter-related issues. If something does not work properly with uBO enabled, the **first step** is to rule out filter-related issues. diff --git a/assets/assets.json b/assets/assets.json index 53a7596d3f4c8..9d2140b5a66fc 100644 --- a/assets/assets.json +++ b/assets/assets.json @@ -78,10 +78,10 @@ "content": "filters", "group": "ads", "off": true, - "title": "Adblock Protector List", - "contentURL": "https://raw.githubusercontent.com/jspenguin2017/AdBlockProtector/master/AdBlockProtectorList.txt", - "supportURL": "https://github.com/jspenguin2017/AdBlockProtector", - "instructionURL": "https://jspenguin2017.github.io/AdBlockProtector/" + "title": "uBlock Protector List", + "contentURL": "https://raw.githubusercontent.com/jspenguin2017/uBlockProtector/master/uBlockProtectorList.txt", + "supportURL": "https://github.com/jspenguin2017/uBlockProtector/blob/master/CONTRIBUTING.MD", + "instructionURL": "https://jspenguin2017.github.io/uBlockProtector/" }, "awrl-0": { "content": "filters", @@ -258,7 +258,10 @@ "updateAfter": 11, "off": true, "title": "hpHosts’ Ad and tracking servers", - "contentURL": "https://hosts-file.net/.%5Cad_servers.txt", + "contentURL": [ + "https://hosts-file.net/.%5Cad_servers.txt", + "http://hosts-file.net/.%5Cad_servers.txt" + ], "supportURL": "https://hosts-file.net/" }, "mvps-0": { @@ -566,7 +569,7 @@ "group": "regions", "off": true, "title": "RUS: Adguard Russian Filter", - "contentURL": "https://filters.adtidy.org/extension/chromium/filters/1.txt", + "contentURL": "https://filters.adtidy.org/extension/ublock/filters/1.txt", "supportURL": "https://forum.adguard.com/forumdisplay.php?69-%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80%D1%8B-Adguard" }, "spa-0": { @@ -602,7 +605,7 @@ "off": true, "title": "TUR: Adguard Turkish Filter", "lang": "tr", - "contentURL": "https://filters.adtidy.org/extension/chromium/filters/13.txt", + "contentURL": "https://filters.adtidy.org/extension/ublock/filters/13.txt", "supportURL": "https://forum.adguard.com/forumdisplay.php?51-Filter-Rules" }, "VIE-0": { diff --git a/dist/README.md b/dist/README.md index 9832fd3a3ee18..94cd0f8d26ebd 100644 --- a/dist/README.md +++ b/dist/README.md @@ -30,3 +30,16 @@ Your uBlock Origin settings are kept intact even after you uninstall the addon. On Linux, the settings are saved in a SQlite file located at `~/.mozilla/firefox/[profile name]/extension-data/ublock0.sqlite`. On Windows, the settings are saved in a SQlite file located at `%APPDATA%\Mozilla\Firefox\Profiles\[profile name]\extension-data\ublock0.sqlite`. + +#### Build instructions (for developers) + +- Clone [uBlock](https://github.com/gorhill/uBlock) and [uAssets](https://github.com/uBlockOrigin/uAssets) repositories in the same parent directory +- Set path to uBlock: `cd uBlock` +- Optional: Select the version to build: `git checkout ` +- Build the plugin: + - Chromium: `./tools/make-chromium.sh` + - Firefox: `./tools/make-firefox.sh all` +- Load the result of the build into your browser: + - Chromium: load the unpacked extension folder `/uBlock/dist/build/uBlock0.chromium/` in Chromium to use the extension. + - Firefox: drag-and-drop `/uBlock/dist/build/uBlock0.firefox.xpi` into Firefox. + diff --git a/dist/description/description-ca.txt b/dist/description/description-ca.txt index dd83d6d98ae6d..5966fd2b4bdad 100644 --- a/dist/description/description-ca.txt +++ b/dist/description/description-ca.txt @@ -1,4 +1,4 @@ -Un bloquejador eficient: el consum de memòria i de processador és baix però, no obstant això, pot carregar i aplicar milers de filtres més que altres bloquejadors coneguts. +Un blocador eficient: Amb un consum discret de memòria i de processador, pot carregar i aplicar milers de filtres més que altres aplicacions semblants. Gràfic de l'eficiència: https://github.com/gorhill/uBlock/wiki/uBlock-vs.-ABP:-efficiency-compared diff --git a/dist/description/description-sv.txt b/dist/description/description-sv.txt index 3014304db201e..d24811632e901 100644 --- a/dist/description/description-sv.txt +++ b/dist/description/description-sv.txt @@ -3,16 +3,16 @@ En effektiv blockerare: lätt på minne och CPU-fotavtryck, som ändå kan ladda Illustrerad översikt av dess effektivitet: https://github.com/gorhill/uBlock/wiki/uBlock-vs.-ABP:-efficiency-compared -Användning: Den stora strömbrytarikonen i popuprutan är till för att avaktivera/aktivera uBlock₀ på den aktuella webbplatsen permanent. Detta gäller enbart för den aktuella webbplatsen, det är inte en global strömbrytare. +Användning: Den stora strömbrytarikonen i poppupprutan är till för att avaktivera/aktivera uBlock₀ på den aktuella webbplatsen permanent. Detta gäller enbart för den aktuella webbplatsen, det är inte en global strömbrytare. *** -Flexibel. uBlock₀ är inte enbart en "reklamblockerare": den kan också läsa och skapa filter från hosts-filer. +Flexibel, uBlock₀ är inte enbart en "reklamblockerare": den kan också läsa och skapa filter från hosts-filer. -Som standard är följande filterlistor laddade och applicerade: +Som standard är följande filterlistor laddade och tillämpade: - EasyList -- Peter Lowe’s Ad server list +- Peter Lowes reklamserverlista - EasyPrivacy - Malware domains @@ -20,18 +20,18 @@ Fler filterlistor finns tillgängliga att använda om du vill: - Fanboy’s Enhanced Tracking List - Dan Pollock’s hosts file -- hpHosts’s Ad and tracking servers +- hpHosts reklam- och spårarservrar - MVPS HOSTS - Spam404 - med flera -Ju fler aktiverade filter, desto högre minnesanvändning. Men även efter att ha lagt till Fanboys två extra filterlistor och hpHosts' Ad and tracking servers så använder uBlock₀ mindre minne än andra väldigt populära blockerare. +Ju fler aktiverade filter, desto högre minnesfotavtryck. Men även efter att ha lagt till Fanboys två extra filterlistor och hpHosts reklam- och språrarservrar, använder uBlock₀ mindre minnesfotavtryck än andra populära blockare. Tänk på att genom att aktivera vissa av dessa extra filterlistor finns det större risk att webbplatser går sönder - särskilt de listor som i normala fall används som hosts-filer. *** -uBlock₀ vore ingenting utan filterlistorna. Så om du vill bidra med någonting, tänk på människorna som arbetar hårt med att upprätthålla de filterlistor du använder, vilka är fritt tillgängliga för allas användning. +Utan de förinställda filterlistorna är detta tillägg ingenting. Så om du vill bidra med någonting, tänk på personerna som arbetar hårt med att upprätthålla de filterlistor du använder, vilka är fritt tillgängliga för allas användning. *** diff --git a/dist/description/description-tr.txt b/dist/description/description-tr.txt index ce9b49b4b2df6..b0debbe30fd45 100644 --- a/dist/description/description-tr.txt +++ b/dist/description/description-tr.txt @@ -1,13 +1,13 @@ -Etkili bir engelleyici: Belleği ve işlemciyi yormaz, yine de diğer popüler engelleyicilere göre binlerce daha fazla süzgeci yükleyip uygulayabilir. +Etkili bir engelleyici: Belleği ve işlemciyi yormaz, yine de diğer popüler engelleyicilere göre binlerce daha çok süzgeci yükleyip uygulayabilir. Verimliliğine örneklendirilmiş genel bakış: https://github.com/gorhill/uBlock/wiki/uBlock-vs.-ABP:-efficiency-compared -Kullanımı: Arayüzdeki büyük güç düğmesi mevcut web sitesinde uBlock'u kalıcı olarak etkisiz/etkin kılmak içindir. Bu yalnızca mevcut web sitesine uygulanır, evrensel bir güç düğmesi değildir. +Kullanımı: Arayüzdeki büyük güç düğmesi o anki web sitesinde, uBlock'u kalıcı olarak devre dışı bırakmak/etkinleştirmek içindir. Bu yalnızca o anki web sitesine uygulanır, evrensel bir güç düğmesi değildir. *** -Esnek, bir "reklam engelleyici"den daha fazlası: Alan adları dosyalarınızdan süzgeçleri okuyabilir ve oluşturabilir. +Esnek, bir "reklam engelleyici"den daha fazlası: Ayrıca alan adları dosyalarınızdan süzgeçleri okuyabilir ve oluşturabilir. Hazır olarak şu süzgeç listeleri yüklüdür ve uygulanır: @@ -23,21 +23,21 @@ Hazır olarak şu süzgeç listeleri yüklüdür ve uygulanır: - hpHosts'un Reklam ve izleyici sunucuları - MVPS HOSTS - Spam404 -- Ve daha birçoğu +- Ve daha başkaları -Tabii ki, daha fazla süzgeç etkinleştirildikçe, bellek kullanımı da yükselir. Ama, Fanboy'un iki ekstra listesi, hpHosts'un reklam ve izleyici sunucuları ekledikten sonra dahi uBlock diğer oldukça popüler olan engelleyicilere göre daha az bellek kullanır. +Elbette, daha çok süzgeç etkinleştirildikçe, bellek kullanımı da artar. Yine de, Fanboy'un iki ekstra listesi, hpHosts'un reklam ve izleyici sunucuları ekledikten sonra bile uBlock diğer oldukça popüler engelleyicilere göre daha az bellek kullanır. Ayrıca, bazı ekstra listelerin seçilmesinin web sitelerinin bozulması olasılığını artırabileceğini unutmayın -- özellikle normalde alan adları dosyası olarak kullanılan listelerin. *** -Ön yüklü gelen süzgeç listeleri olmadan, bu eklenti hiçbir işe yaramaz. Eğer gerçekten bir şekilde katkıda bulunmak isterseniz, herkes tarafından özgürce kullanıma imkan veren, kullandığınız süzgeç listelerini oluşturmak için uğraşan insanları düşünün. +Ön yüklü gelen süzgeç listeleri olmadan, bu eklenti bir işe yaramaz. Bu yüzden, gerçekten bir şekilde katkıda bulunmak isterseniz, herkesin özgürce kullanması için sunulan kullandığınız süzgeç listelerini oluşturmak için uğraşan insanları düşünün. *** Özgür. Açık kaynak kamu lisanslı (GPLv3) -Kullanıcılar tarafından kullanıcılar için. +Kullanıcılardan kullanıcılara. Katkıda bulunanlar @ Github: https://github.com/gorhill/uBlock/graphs/contributors Katkıda bulunanlar @ Crowdin: https://crowdin.net/project/ublock diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index 6b6371c5d502d..4d272891e9b3f 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -2,8 +2,19 @@ "manifest_version": 2, "name": "uBlock Origin", - "version": "1.12.4", + "version": "1.13.8", + "commands": { + "launch-element-zapper": { + "description": "__MSG_popupTipZapper__" + }, + "launch-element-picker": { + "description": "__MSG_popupTipPicker__" + }, + "launch-logger": { + "description": "__MSG_popupTipLog__" + } + }, "default_locale": "en", "description": "__MSG_extShortDesc__", "icons": { @@ -39,7 +50,7 @@ } ], "incognito": "split", - "minimum_chrome_version": "26.0", + "minimum_chrome_version": "38.0", "optional_permissions": [ "file:///*" ], "options_page": "dashboard.html", "options_ui": { diff --git a/platform/chromium/polyfill.js b/platform/chromium/polyfill.js index a21e130e1446c..9530968dc6100 100644 --- a/platform/chromium/polyfill.js +++ b/platform/chromium/polyfill.js @@ -1,7 +1,7 @@ /******************************************************************************* uBlock Origin - a browser extension to block requests. - Copyright (C) 2014-2016 The uBlock Origin authors + Copyright (C) 2014-2017 The uBlock Origin authors This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -72,159 +72,3 @@ var objectAssign = Object.assign || function(target, source) { }; /******************************************************************************/ - -// https://github.com/gorhill/uBlock/issues/1070 -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility -// This polyfill is designed to fulfill *only* what uBlock Origin needs -- this -// is not an accurate API of the real Set() type. - -if ( self.Set instanceof Function === false ) { - self.Set = function(iter) { - this.clear(); - if ( Array.isArray(iter) ) { - for ( var i = 0, n = iter.length; i < n; i++ ) { - this.add(iter[i]); - } - return; - } - }; - - self.Set.polyfill = true; - - self.Set.prototype.clear = function() { - this._set = Object.create(null); - this.size = 0; - // Iterator stuff - this._values = undefined; - this._i = undefined; - this.value = undefined; - this.done = true; - }; - - self.Set.prototype.add = function(k) { - if ( this._set[k] === undefined ) { - this._set[k] = true; - this.size += 1; - } - return this; - }; - - self.Set.prototype.delete = function(k) { - if ( this._set[k] !== undefined ) { - delete this._set[k]; - this.size -= 1; - return true; - } - return false; - }; - - self.Set.prototype.has = function(k) { - return this._set[k] !== undefined; - }; - - self.Set.prototype.next = function() { - if ( this._i < this.size ) { - this.value = this._values[this._i++]; - } else { - this._values = undefined; - this.value = undefined; - this.done = true; - } - return this; - }; - - self.Set.prototype.values = function() { - this._values = Object.keys(this._set); - this._i = 0; - this.value = undefined; - this.done = false; - return this; - }; -} - -/******************************************************************************/ - -// https://github.com/gorhill/uBlock/issues/1070 -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility -// This polyfill is designed to fulfill *only* what uBlock Origin needs -- this -// is not an accurate API of the real Map() type. - -if ( self.Map instanceof Function === false ) { - self.Map = function(iter) { - this.clear(); - if ( Array.isArray(iter) ) { - for ( var i = 0, n = iter.length, entry; i < n; i++ ) { - entry = iter[i]; - this.set(entry[0], entry[1]); - } - return; - } - }; - - self.Map.polyfill = true; - - self.Map.prototype.clear = function() { - this._map = Object.create(null); - this.size = 0; - // Iterator stuff - this._keys = undefined; - this._i = undefined; - this.value = undefined; - this.done = true; - }; - - self.Map.prototype.delete = function(k) { - if ( this._map[k] !== undefined ) { - delete this._map[k]; - this.size -= 1; - return true; - } - return false; - }; - - self.Map.prototype.entries = function() { - this._keys = Object.keys(this._map); - this._i = 0; - this.value = [ undefined, undefined ]; - this.done = false; - return this; - }; - - self.Map.prototype.get = function(k) { - return this._map[k]; - }; - - self.Map.prototype.has = function(k) { - return this._map[k] !== undefined; - }; - - self.Map.prototype.next = function() { - if ( this._i < this.size ) { - var key = this._keys[this._i++]; - this.value[0] = key; - this.value[1] = this._map[key]; - } else { - this._keys = undefined; - this.value = undefined; - this.done = true; - } - return this; - }; - - self.Map.prototype.set = function(k, v) { - if ( v !== undefined ) { - if ( this._map[k] === undefined ) { - this.size += 1; - } - this._map[k] = v; - } else { - if ( this._map[k] !== undefined ) { - this.size -= 1; - } - delete this._map[k]; - } - return this; - }; -} - -/******************************************************************************/ diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 8e3cc9e791498..34e8d1c1218e9 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -35,7 +35,13 @@ var chrome = self.chrome; var manifest = chrome.runtime.getManifest(); vAPI.chrome = true; -vAPI.cantWebsocket = true; +vAPI.chromiumVersion = (function(){ + var matches = /\bChrom(?:e|ium)\/(\d+)\b/.exec(navigator.userAgent); + return matches !== null ? parseInt(matches[1], 10) : NaN; + })(); +vAPI.cantWebsocket = + chrome.webRequest.ResourceType instanceof Object === false || + chrome.webRequest.ResourceType.WEBSOCKET !== 'websocket'; var noopFunc = function(){}; @@ -472,12 +478,12 @@ vAPI.tabs.open = function(details) { var targetURLWithoutHash = pos === -1 ? targetURL : targetURL.slice(0, pos); chrome.tabs.query({ url: targetURLWithoutHash }, function(tabs) { - var tab = tabs[0]; + if ( chrome.runtime.lastError ) { /* noop */ } + var tab = Array.isArray(tabs) && tabs[0]; if ( !tab ) { wrapper(); return; } - var _details = { active: true, url: undefined @@ -1186,6 +1192,11 @@ vAPI.contextMenu = { /******************************************************************************/ /******************************************************************************/ +vAPI.commands = chrome.commands; + +/******************************************************************************/ +/******************************************************************************/ + vAPI.lastError = function() { return chrome.runtime.lastError; }; diff --git a/platform/chromium/vapi-client.js b/platform/chromium/vapi-client.js index 8e659499d24b9..39768c15f582c 100644 --- a/platform/chromium/vapi-client.js +++ b/platform/chromium/vapi-client.js @@ -72,114 +72,6 @@ if ( vAPI.sessionId ) { /******************************************************************************/ -// Support minimally working Set() for legacy Chromium. - -if ( self.Set instanceof Function ) { - self.createSet = function() { - return new Set(); - }; -} else { - self.createSet = (function() { - //console.log('Polyfilling for ES6-like Set().'); - var PrimitiveSet = function() { - this.clear(); - }; - PrimitiveSet.prototype = { - add: function(k) { - if ( this._set[k] === undefined ) { - this._set[k] = true; - this.size += 1; - } - return this; - }, - clear: function() { - this._set = Object.create(null); - this.size = 0; - this._values = undefined; - this._i = undefined; - this.value = undefined; - this.done = true; - }, - delete: function(k) { - if ( this._set[k] === undefined ) { return false; } - delete this._set[k]; - this.size -= 1; - return true; - }, - has: function(k) { - return this._set[k] !== undefined; - }, - next: function() { - if ( this._i < this.size ) { - this.value = this._values[this._i++]; - } else { - this._values = undefined; - this.value = undefined; - this.done = true; - } - return this; - }, - polyfill: true, - values: function() { - this._values = Object.keys(this._set); - this._i = 0; - this.value = undefined; - this.done = false; - return this; - } - }; - var ReferenceSet = function() { - this.clear(); - }; - ReferenceSet.prototype = { - add: function(k) { - if ( this._set.indexOf(k) === -1 ) { - this._set.push(k); - } - }, - clear: function() { - this._set = []; - this._i = 0; - this.value = undefined; - this.done = true; - }, - delete: function(k) { - var pos = this._set.indexOf(k); - if ( pos === -1 ) { return false; } - this._set.splice(pos, 1); - return true; - }, - has: function(k) { - return this._set.indexOf(k) !== -1; - }, - next: function() { - if ( this._i === this._set.length ) { - this.value = undefined; - this.done = true; - } else { - this.value = this._set[this._i]; - this._i += 1; - } - return this; - }, - polyfill: true, - values: function() { - this._i = 0; - this.done = false; - return this; - } - }; - Object.defineProperty(ReferenceSet.prototype, 'size', { - get: function() { return this._set.length; } - }); - return function(type) { - return type === 'object' ? new ReferenceSet() : new PrimitiveSet(); - }; - })(); -} - -/******************************************************************************/ - var referenceCounter = 0; vAPI.lock = function() { diff --git a/platform/edge/manifest.json b/platform/edge/manifest.json index 0db4d95b4ff1b..8f7e388f15b28 100644 --- a/platform/edge/manifest.json +++ b/platform/edge/manifest.json @@ -2,7 +2,19 @@ "manifest_version": 2, "name": "uBlock Origin", - "version": "1.12.4", + "version": "1.13.8", + + "commands": { + "launch-element-zapper": { + "description": "__MSG_popupTipZapper__" + }, + "launch-element-picker": { + "description": "__MSG_popupTipPicker__" + }, + "launch-logger": { + "description": "__MSG_popupTipLog__" + } + }, "default_locale": "en", "description": "__MSG_extShortDesc__", @@ -40,7 +52,7 @@ } ], "incognito": "split", - "minimum_edge_version": "38.14393", + "minimum_edge_version": "40.15063", "optional_permissions": [ "file:///*" ], "options_page": "dashboard.html", "options_ui": { diff --git a/platform/edge/polyfill.js b/platform/edge/polyfill.js index 81eedb9bcedab..b68f5f96086fd 100644 --- a/platform/edge/polyfill.js +++ b/platform/edge/polyfill.js @@ -1,7 +1,7 @@ /******************************************************************************* uBlock Origin - a browser extension to block requests. - Copyright (C) 2014-2016 The uBlock Origin authors + Copyright (C) 2014-2017 The uBlock Origin authors This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -70,159 +70,3 @@ var objectAssign = Object.assign || function(target, source) { }; /******************************************************************************/ - -// https://github.com/gorhill/uBlock/issues/1070 -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility -// This polyfill is designed to fulfill *only* what uBlock Origin needs -- this -// is not an accurate API of the real Set() type. - -if ( self.Set instanceof Function === false ) { - self.Set = function(iter) { - this.clear(); - if ( Array.isArray(iter) ) { - for ( var i = 0, n = iter.length; i < n; i++ ) { - this.add(iter[i]); - } - return; - } - }; - - self.Set.polyfill = true; - - self.Set.prototype.clear = function() { - this._set = Object.create(null); - this.size = 0; - // Iterator stuff - this._values = undefined; - this._i = undefined; - this.value = undefined; - this.done = true; - }; - - self.Set.prototype.add = function(k) { - if ( this._set[k] === undefined ) { - this._set[k] = true; - this.size += 1; - } - return this; - }; - - self.Set.prototype.delete = function(k) { - if ( this._set[k] !== undefined ) { - delete this._set[k]; - this.size -= 1; - return true; - } - return false; - }; - - self.Set.prototype.has = function(k) { - return this._set[k] !== undefined; - }; - - self.Set.prototype.next = function() { - if ( this._i < this.size ) { - this.value = this._values[this._i++]; - } else { - this._values = undefined; - this.value = undefined; - this.done = true; - } - return this; - }; - - self.Set.prototype.values = function() { - this._values = Object.keys(this._set); - this._i = 0; - this.value = undefined; - this.done = false; - return this; - }; -} - -/******************************************************************************/ - -// https://github.com/gorhill/uBlock/issues/1070 -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility -// This polyfill is designed to fulfill *only* what uBlock Origin needs -- this -// is not an accurate API of the real Map() type. - -if ( self.Map instanceof Function === false ) { - self.Map = function(iter) { - this.clear(); - if ( Array.isArray(iter) ) { - for ( var i = 0, n = iter.length, entry; i < n; i++ ) { - entry = iter[i]; - this.set(entry[0], entry[1]); - } - return; - } - }; - - self.Map.polyfill = true; - - self.Map.prototype.clear = function() { - this._map = Object.create(null); - this.size = 0; - // Iterator stuff - this._keys = undefined; - this._i = undefined; - this.value = undefined; - this.done = true; - }; - - self.Map.prototype.delete = function(k) { - if ( this._map[k] !== undefined ) { - delete this._map[k]; - this.size -= 1; - return true; - } - return false; - }; - - self.Map.prototype.entries = function() { - this._keys = Object.keys(this._map); - this._i = 0; - this.value = [ undefined, undefined ]; - this.done = false; - return this; - }; - - self.Map.prototype.get = function(k) { - return this._map[k]; - }; - - self.Map.prototype.has = function(k) { - return this._map[k] !== undefined; - }; - - self.Map.prototype.next = function() { - if ( this._i < this.size ) { - var key = this._keys[this._i++]; - this.value[0] = key; - this.value[1] = this._map[key]; - } else { - this._keys = undefined; - this.value = undefined; - this.done = true; - } - return this; - }; - - self.Map.prototype.set = function(k, v) { - if ( v !== undefined ) { - if ( this._map[k] === undefined ) { - this.size += 1; - } - this._map[k] = v; - } else { - if ( this._map[k] !== undefined ) { - this.size -= 1; - } - delete this._map[k]; - } - return this; - }; -} - -/******************************************************************************/ \ No newline at end of file diff --git a/platform/edge/vapi-background.js b/platform/edge/vapi-background.js index f2a0180f07f67..5d3e0f71d1acd 100644 --- a/platform/edge/vapi-background.js +++ b/platform/edge/vapi-background.js @@ -35,7 +35,13 @@ var browser = self.browser; var manifest = browser.runtime.getManifest(); vAPI.edge = true; -vAPI.cantWebsocket = true; +vAPI.edgeVersion = (function(){ + var matches = /\bEdge\/(\d+\.\d+)\b/.exec(navigator.userAgent); + return matches !== null ? parseInt(matches[1], 10) : NaN; +})(); +vAPI.cantWebsocket = + browser.webRequest.ResourceType instanceof Object === false || + browser.webRequest.ResourceType.WEBSOCKET !== 'websocket'; var noopFunc = function(){}; @@ -622,12 +628,12 @@ vAPI.tabs.open = function(details) { var targetURLWithoutHash = pos === -1 ? targetURL : targetURL.slice(0, pos); browser.tabs.query({ url: targetURLWithoutHash }, function(tabs) { - var tab = tabs[0]; + if ( browser.runtime.lastError ) { /* noop */ } + var tab = Array.isArray(tabs) && tabs[0]; if ( !tab ) { wrapper(); return; } - var _details = { active: true, url: undefined @@ -1342,6 +1348,11 @@ vAPI.contextMenu = { /******************************************************************************/ /******************************************************************************/ +vAPI.commands = browser.commands; + +/******************************************************************************/ +/******************************************************************************/ + vAPI.lastError = function() { return browser.runtime.lastError; }; diff --git a/platform/edge/vapi-client.js b/platform/edge/vapi-client.js index 8d519e46701f6..0e4e266b92f57 100644 --- a/platform/edge/vapi-client.js +++ b/platform/edge/vapi-client.js @@ -72,114 +72,6 @@ if ( vAPI.sessionId ) { /******************************************************************************/ -// Support minimally working Set() for legacy Chromium. - -if ( self.Set instanceof Function ) { - self.createSet = function() { - return new Set(); - }; -} else { - self.createSet = (function() { - //console.log('Polyfilling for ES6-like Set().'); - var PrimitiveSet = function() { - this.clear(); - }; - PrimitiveSet.prototype = { - add: function(k) { - if ( this._set[k] === undefined ) { - this._set[k] = true; - this.size += 1; - } - return this; - }, - clear: function() { - this._set = Object.create(null); - this.size = 0; - this._values = undefined; - this._i = undefined; - this.value = undefined; - this.done = true; - }, - delete: function(k) { - if ( this._set[k] === undefined ) { return false; } - delete this._set[k]; - this.size -= 1; - return true; - }, - has: function(k) { - return this._set[k] !== undefined; - }, - next: function() { - if ( this._i < this.size ) { - this.value = this._values[this._i++]; - } else { - this._values = undefined; - this.value = undefined; - this.done = true; - } - return this; - }, - polyfill: true, - values: function() { - this._values = Object.keys(this._set); - this._i = 0; - this.value = undefined; - this.done = false; - return this; - } - }; - var ReferenceSet = function() { - this.clear(); - }; - ReferenceSet.prototype = { - add: function(k) { - if ( this._set.indexOf(k) === -1 ) { - this._set.push(k); - } - }, - clear: function() { - this._set = []; - this._i = 0; - this.value = undefined; - this.done = true; - }, - delete: function(k) { - var pos = this._set.indexOf(k); - if ( pos === -1 ) { return false; } - this._set.splice(pos, 1); - return true; - }, - has: function(k) { - return this._set.indexOf(k) !== -1; - }, - next: function() { - if ( this._i === this._set.length ) { - this.value = undefined; - this.done = true; - } else { - this.value = this._set[this._i]; - this._i += 1; - } - return this; - }, - polyfill: true, - values: function() { - this._i = 0; - this.done = false; - return this; - } - }; - Object.defineProperty(ReferenceSet.prototype, 'size', { - get: function() { return this._set.length; } - }); - return function(type) { - return type === 'object' ? new ReferenceSet() : new PrimitiveSet(); - }; - })(); -} - -/******************************************************************************/ - var referenceCounter = 0; vAPI.lock = function() { diff --git a/platform/firefox/polyfill.js b/platform/firefox/polyfill.js index 6daf9fd466cc7..6b03d565b36ca 100644 --- a/platform/firefox/polyfill.js +++ b/platform/firefox/polyfill.js @@ -1,7 +1,7 @@ /******************************************************************************* uBlock Origin - a browser extension to block requests. - Copyright (C) 2016 The uBlock Origin authors + Copyright (C) 2016-2017 The uBlock Origin authors This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,51 +41,3 @@ var objectAssign = Object.assign || function(target, source) { }; /******************************************************************************/ - -// Patching for Pale Moon which does not implement ES6 Set/Map. -// Test for non-ES6 Set/Map: check if property `iterator` is present. -// The code is strictly to satisfy uBO's core, not to be an accurate -// implementation of ES6. - -if ( self.Set.prototype.iterator instanceof Function ) { - //console.log('Patching non-ES6 Set() to be more ES6-like.'); - self.Set.prototype._values = self.Set.prototype.values; - self.Set.prototype.values = function() { - this._valueIter = this._values(); - this.value = undefined; - this.done = false; - return this; - }; - self.Set.prototype.next = function() { - try { - this.value = this._valueIter.next(); - } catch (ex) { - this._valueIter = undefined; - this.value = undefined; - this.done = true; - } - return this; - }; -} - -if ( self.Map.prototype.iterator instanceof Function ) { - //console.log('Patching non-ES6 Map() to be more ES6-like.'); - self.Map.prototype._entries = self.Map.prototype.entries; - self.Map.prototype.entries = function() { - this._entryIter = this._entries(); - this.value = undefined; - this.done = false; - return this; - }; - self.Map.prototype.next = function() { - try { - this.value = this._entryIter.next(); - } catch (ex) { - this._entryIter = undefined; - this.value = undefined; - this.done = true; - } - return this; - }; -} - diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index f9d5fd2530038..7a85730ff6e4f 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -53,9 +53,9 @@ var deferUntil = function(testFn, mainFn, details) { details = {}; } - var now = 0; - var next = details.next || 200; - var until = details.until || 2000; + var now = 0, + next = details.next || 200, + until = details.until || 12800; var check = function() { if ( testFn() === true || now >= until ) { @@ -69,7 +69,7 @@ var deferUntil = function(testFn, mainFn, details) { if ( 'sync' in details && details.sync === true ) { check(); } else { - vAPI.setTimeout(check, 1); + vAPI.setTimeout(check, details.first || 1); } }; @@ -1369,6 +1369,7 @@ var tabWatcher = (function() { } else if ( tabBrowser.tabContainer ) { // Firefox tabContainer = tabBrowser.tabContainer; vAPI.contextMenu.register(window); + vAPI.commands.register(window); } // https://github.com/gorhill/uBlock/issues/697 @@ -1413,6 +1414,7 @@ var tabWatcher = (function() { var onWindowUnload = function(win) { vAPI.contextMenu.unregister(win); + vAPI.commands.unregister(win); var tabBrowser = getTabBrowser(win); if ( tabBrowser === null ) { @@ -3106,6 +3108,9 @@ vAPI.toolbarButton = { CustomizableUI.addListener(CUIEvents); + // https://github.com/gorhill/uBlock/issues/2696 + // https://github.com/gorhill/uBlock/issues/2709 + var style = [ '#' + this.id + '.off {', 'list-style-image: url(', @@ -3119,9 +3124,12 @@ vAPI.toolbarButton = { '}', '#' + this.viewId + ',', '#' + this.viewId + ' > iframe {', - 'width: 160px;', 'height: 290px;', + 'max-width: none !important;', + 'min-width: 0 !important;', 'overflow: hidden !important;', + 'padding: 0 !important;', + 'width: 160px;', '}' ]; @@ -3340,7 +3348,8 @@ vAPI.contextMenu = (function() { } deferUntil( canRegister.bind(null, win), - register.bind(null, win) + register.bind(null, win), + { first: 4000 } ); }; @@ -3378,6 +3387,111 @@ vAPI.contextMenu = (function() { /******************************************************************************/ /******************************************************************************/ +// Keyboard shortcuts have to be hardcoded, as they are declaratively created +// in the manifest.json file on webext API, and only a listener has to be +// installed with the browser.commands API. +// +// Assuming only one client listener is installed. + +// Shortcuts can be customized in `about:config` using +// extensions.ublock0.shortcuts.[command id] => modifier-key +// To disable a shortcut, set it to `-`: +// extensions.ublock0.shortcuts.[command id] => - + +vAPI.commands = (function() { + if ( vAPI.fennec || vAPI.thunderbird ) { return; } + + var commands = [ + { id: 'launch-element-zapper' }, + { id: 'launch-element-picker' }, + { id: 'launch-logger' } + ]; + var clientListener; + + var commandHandler = function(ev) { + if ( typeof clientListener !== 'function' ) { return; } + var match = /^uBlock0Key-([a-z-]+)$/.exec(ev.target.id); + if ( match === null ) { return; } + clientListener(match[1]); + }; + + var canRegister = function(win) { + return win && win.document.readyState === 'complete'; + }; + + var register = function(window) { + if ( canRegister(window) !== true ) { return; } + + var doc = window.document, + myKeyset = doc.getElementById('uBlock0Keyset'); + // Already registered? + if ( myKeyset !== null ) { return; } + + var mainKeyset = doc.getElementById('mainKeyset'), + keysetHolder = mainKeyset && mainKeyset.parentNode; + if ( keysetHolder === null ) { return; } + + myKeyset = doc.createElement('keyset'); + myKeyset.setAttribute('id', 'uBlock0Keyset'); + + var myKey, shortcut, parts, modifiers, key; + for ( var command of commands ) { + modifiers = key = ''; + shortcut = vAPI.localStorage.getItem('shortcuts.' + command.id); + if ( shortcut === null ) { + vAPI.localStorage.setItem('shortcuts.' + command.id, ''); + } else if ( (parts = /^((?:[a-z]+-){1,})?(\w)$/.exec(shortcut)) !== null ) { + modifiers = (parts[1] || '').slice(0, -1).replace(/-/g, ','); + key = parts[2] || ''; + } + myKey = doc.createElement('key'); + myKey.setAttribute('id', 'uBlock0Key-' + command.id); + if ( modifiers !== '' ) { + myKey.setAttribute('modifiers', modifiers); + } + myKey.setAttribute('key', key); + // https://stackoverflow.com/a/16786770 + myKey.setAttribute('oncommand', ';'); + myKeyset.appendChild(myKey); + } + + keysetHolder.addEventListener('command', commandHandler); + keysetHolder.appendChild(myKeyset); + }; + + var registerAsync = function(win) { + if ( vAPI.fennec ) { return; } + deferUntil( + canRegister.bind(null, win), + register.bind(null, win), + { first: 4000 } + ); + }; + + var unregister = function(window) { + var doc = window.document, + myKeyset = doc.getElementById('uBlock0Keyset'); + if ( myKeyset === null ) { return; } + myKeyset.removeEventListener('command', commandHandler); + myKeyset.parentNode.removeChild(myKeyset); + }; + + var addListener = function(callback) { + clientListener = callback; + }; + + return { + register: registerAsync, + unregister: unregister, + onCommand: { + addListener: addListener + } + }; +})(); + +/******************************************************************************/ +/******************************************************************************/ + var optionsObserver = (function() { var addonId = 'uBlock0@raymondhill.net'; @@ -3448,7 +3562,7 @@ var optionsObserver = (function() { var register = function() { Services.obs.addObserver(observer, 'addon-options-displayed', false); cleanupTasks.push(unregister); - deferUntil(canInit, init, { next: 463 }); + deferUntil(canInit, init, { first: 4000 }); }; return { diff --git a/platform/firefox/vapi-client.js b/platform/firefox/vapi-client.js index 606f36f12b2eb..5ec47c0ebf525 100644 --- a/platform/firefox/vapi-client.js +++ b/platform/firefox/vapi-client.js @@ -54,46 +54,6 @@ var vAPI = self.vAPI; /******************************************************************************/ -// Support minimally working Set() for legacy Firefox: iterator for legacy -// Set() does not work like the one for standard ES6 Set(). - -if ( self.Set.prototype.iterator instanceof Function === false ) { - self.createSet = function() { - return new Set(); - }; -} else { - self.createSet = (function() { - //console.log('Patching non-ES6 Set() to be more ES6-like.'); - var values = function() { - this._valueIter = this.prototype.values(); - this.value = undefined; - this.done = false; - return this; - }; - var next = function() { - try { - this.value = this._valueIter.next(); - } catch (ex) { - this._valueIter = undefined; - this.value = undefined; - this.done = true; - } - return this; - }; - return function() { - var r = new Set(); - r._valueIter = undefined; - r.value = undefined; - r.done = false; - r.values = values.bind(r); - r.next = next.bind(r); - return r; - }; - })(); -} - -/******************************************************************************/ - var referenceCounter = 0; vAPI.lock = function() { diff --git a/platform/opera/manifest.json b/platform/opera/manifest.json index 7ee9749857c85..3f54dcdb8d5d8 100644 --- a/platform/opera/manifest.json +++ b/platform/opera/manifest.json @@ -1,16 +1,5 @@ { - "manifest_version": 2, - - "name": "uBlock Origin", - "version": "1.9.15.101", - - "default_locale": "en", - "description": "__MSG_extShortDesc__", - "icons": { - "16": "img/icon_16.png", - "128": "img/icon_128.png" - }, - + "author": "All uBlock Origin contributors", "browser_action": { "default_icon": { "19": "img/browsericons/icon19.png", @@ -19,11 +8,20 @@ "default_title": "uBlock Origin", "default_popup": "popup.html" }, - - "author": "All uBlock Origin contributors", "background": { "page": "background.html" }, + "commands": { + "launch-element-zapper": { + "description": "__MSG_popupTipZapper__" + }, + "launch-element-picker": { + "description": "__MSG_popupTipPicker__" + }, + "launch-logger": { + "description": "__MSG_popupTipLog__" + } + }, "content_scripts": [ { "matches": ["http://*/*", "https://*/*"], @@ -38,8 +36,16 @@ "all_frames": false } ], + "default_locale": "en", + "description": "__MSG_extShortDesc__", + "icons": { + "16": "img/icon_16.png", + "128": "img/icon_128.png" + }, "incognito": "split", - "minimum_chrome_version": "26.0", + "manifest_version": 2, + "minimum_chrome_version": "38.0", + "name": "uBlock Origin", "optional_permissions": [ "file:///*" ], "options_page": "dashboard.html", "permissions": [ @@ -51,8 +57,8 @@ "webNavigation", "webRequest", "webRequestBlocking", - "http://*/*", - "https://*/*" + "" ], - "short_name": "uBlock₀" + "short_name": "uBlock₀", + "version": "1.9.15.101" } diff --git a/platform/webext/background.html b/platform/webext/background.html index 1abcdc511a3e8..659797740adbe 100644 --- a/platform/webext/background.html +++ b/platform/webext/background.html @@ -33,5 +33,6 @@ + diff --git a/platform/webext/install.rdf b/platform/webext/install.rdf index 0d0e9b3bf24f2..48ba61afcf7f1 100644 --- a/platform/webext/install.rdf +++ b/platform/webext/install.rdf @@ -25,5 +25,14 @@ + + + + {{aa3c5121-dab2-40e2-81ca-7ea25febc110}} + 54.0 + * + + + diff --git a/platform/webext/manifest.json b/platform/webext/manifest.json index 2579d659ae2b8..e44cb2aef474c 100644 --- a/platform/webext/manifest.json +++ b/platform/webext/manifest.json @@ -11,6 +11,23 @@ } }, + "commands": { + "launch-element-zapper": { + "suggested_key": { + }, + "description": "__MSG_popupTipZapper__" + }, + "launch-element-picker": { + "suggested_key": { + }, + "description": "__MSG_popupTipPicker__" + }, + "launch-logger": { + "suggested_key": { + }, + "description": "__MSG_popupTipLog__" + } + }, "default_locale": "en", "description": "__MSG_extShortDesc__", "icons": { @@ -58,8 +75,7 @@ "webNavigation", "webRequest", "webRequestBlocking", - "http://*/*", - "https://*/*" + "" ], "short_name": "uBlock₀" } diff --git a/src/3p-filters.html b/src/3p-filters.html index 714052ece53c9..062b24fabe7e3 100644 --- a/src/3p-filters.html +++ b/src/3p-filters.html @@ -45,7 +45,7 @@