diff --git a/dist/description/description-da.txt b/dist/description/description-da.txt index 320a7bb9a460f..0eb6f46f4ba62 100644 --- a/dist/description/description-da.txt +++ b/dist/description/description-da.txt @@ -1,8 +1,8 @@ En effektiv blocker: let på hukommelse og CPU forbrug,. Kan indlæse og anvende tusindvis af flere filtre end andre populære blockere derude. -Illustreret oversigt over effektiviteten: https://github.com/gorhill/uBlock/wiki/uBlock-vs.-ABP :-Efficiency-compared +Illustreret oversigt over effektiviteten: https://github.com/gorhill/uBlock/wiki/uBlock-vs.-ABP:-Efficiency-compared -Anvendelse: Den Store power knap i pop-up-vinduet kan permanent deaktivere/aktivere uBlock på det aktuelle websted. Dette gælder kun for det aktuelle websted, det er ikke en global afbryderknap. +Anvendelse: Den store tænd-sluk-knap i pop op-vinduet bruges til permanent at deaktivere/aktivere uBlock på det aktuelle websted. Dette gælder kun for det aktuelle websted, det er ikke en global afbryderknap. *** @@ -24,7 +24,7 @@ Flere lister er tilgængelige hvis du ønsker det: - Spam404 - Osv. -Selvfølgelig vil flere aktive filtre betyde højere hukommelsesforbrug. Selv efter tilføjelse af Fanboys to ekstra lister, og hpHosts’s Ad and tracking servers, har uBlock₀ stadig et lavere hukommelsesforbrug end andre blokere derude. +Selvfølgelig vil flere aktive filtre betyde højere hukommelsesforbrug. Men selv efter tilføjelse af Fanboys to ekstra lister, samt hpHosts’s Ad and tracking servers, har uBlock stadig et lavere hukommelsesforbrug end andre meget populære blockere derude. Vær desuden opmærksom på, at hvis du vælger nogle af disse ekstra lister kan det føre til højere sandsynlighed for, at webstedet bliver vist forkert - især de lister der normalt anvendes som hosts-fil. diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index b6f4067097a5a..277e007b23804 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "uBlock Origin", - "version": "1.11.1.0", + "version": "1.11.3.1", "default_locale": "en", "description": "__MSG_extShortDesc__", @@ -55,7 +55,9 @@ "webRequest", "webRequestBlocking", "http://*/*", - "https://*/*" + "https://*/*", + "ws://*/*", + "wss://*/*" ], "short_name": "uBlock₀", "storage": { diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 63290d47b6ab0..2032ba2c1b165 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.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 @@ -859,26 +859,36 @@ vAPI.net = {}; /******************************************************************************/ vAPI.net.registerListeners = function() { - var µb = µBlock; - var µburi = µb.URI; + var µb = µBlock, + µburi = µb.URI, + wrApi = chrome.webRequest; // https://bugs.chromium.org/p/chromium/issues/detail?id=410382 // Between Chromium 38-48, plug-ins' network requests were reported as // type "other" instead of "object". - var is_v38_48 = /\bChrom[a-z]+\/(?:3[89]|4[0-8])\.[\d.]+\b/.test(navigator.userAgent), - is_v49_55 = /\bChrom[a-z]+\/(?:49|5[012345])\b/.test(navigator.userAgent); - - // Chromium-based browsers understand only these network request types. - var validTypes = [ - 'main_frame', - 'sub_frame', - 'stylesheet', - 'script', - 'image', - 'object', - 'xmlhttprequest', - 'other' - ]; + var is_v38_48 = /\bChrom[a-z]+\/(?:3[89]|4[0-8])\.[\d.]+\b/.test(navigator.userAgent); + + // legacy Chromium understands only these network request types. + var validTypes = { + main_frame: true, + sub_frame: true, + stylesheet: true, + script: true, + image: true, + object: true, + xmlhttprequest: true, + other: true + }; + // modern Chromium/WebExtensions: more types available. + if ( wrApi.ResourceType ) { + (function() { + for ( var typeKey in wrApi.ResourceType ) { + if ( wrApi.ResourceType.hasOwnProperty(typeKey) ) { + validTypes[wrApi.ResourceType[typeKey]] = true; + } + } + })(); + } var extToTypeMap = new Map([ ['eot','font'],['otf','font'],['svg','font'],['ttf','font'],['woff','font'],['woff2','font'], @@ -888,7 +898,7 @@ vAPI.net.registerListeners = function() { var denormalizeTypes = function(aa) { if ( aa.length === 0 ) { - return validTypes; + return Object.keys(validTypes); } var out = []; var i = aa.length, @@ -896,7 +906,7 @@ vAPI.net.registerListeners = function() { needOther = true; while ( i-- ) { type = aa[i]; - if ( validTypes.indexOf(type) !== -1 ) { + if ( validTypes[type] ) { out.push(type); } if ( type === 'other' ) { @@ -922,23 +932,29 @@ vAPI.net.registerListeners = function() { var normalizeRequestDetails = function(details) { details.tabId = details.tabId.toString(); + var type = details.type; + // https://github.com/gorhill/uBlock/issues/1493 - // Chromium 49+ support a new request type: `ping`, which is fired as - // a result of using `navigator.sendBeacon`. - if ( details.type === 'ping' ) { + // Chromium 49+/WebExtensions support a new request type: `ping`, + // which is fired as a result of using `navigator.sendBeacon`. + if ( type === 'ping' ) { details.type = 'beacon'; return; } + if ( type === 'imageset' ) { + details.type = 'image'; + return; + } + // The rest of the function code is to normalize type - if ( details.type !== 'other' ) { + if ( type !== 'other' ) { return; } // Try to map known "extension" part of URL to request type. var path = µburi.pathFromURI(details.url), - pos = path.indexOf('.', path.length - 6), - type; + pos = path.indexOf('.', path.length - 6); if ( pos !== -1 && (type = extToTypeMap.get(path.slice(pos + 1))) ) { details.type = type; return; @@ -976,16 +992,23 @@ vAPI.net.registerListeners = function() { // logger, etc. // Counterpart of following block of code is found in "vapi-client.js" -- // search for "https://github.com/gorhill/uBlock/issues/1497". + // + // Once uBO 1.11.1 and uBO-Extra 2.12 are widespread, the image-based + // handling code can be removed. var onBeforeWebsocketRequest = function(details) { + if ( (details.type !== 'image') && + (details.method !== 'HEAD' || details.type !== 'xmlhttprequest') + ) { + return; + } + var requestURL = details.url, + matches = /[?&]u(?:rl)?=([^&]+)/.exec(requestURL); + if ( matches === null ) { return; } details.type = 'websocket'; - var requestURL = details.url; - var matches = /[?&]url=([^&]+)/.exec(requestURL); details.url = decodeURIComponent(matches[1]); var r = onBeforeRequestClient(details); - // Blocked? if ( r && r.cancel ) { return r; } - // Try to redirect to the URL of an image already present in the - // document, or a 1x1 data: URL if none is present. + // Redirect to the provided URL, or a 1x1 data: URI if none provided. matches = /[?&]r=([^&]+)/.exec(requestURL); return { redirectUrl: matches !== null ? @@ -995,109 +1018,126 @@ vAPI.net.registerListeners = function() { }; var onBeforeRequestClient = this.onBeforeRequest.callback; - var onBeforeRequest = function(details) { - // https://github.com/gorhill/uBlock/issues/1497 - if ( - details.type === 'image' && - details.url.endsWith('ubofix=f41665f3028c7fd10eecf573336216d3') - ) { - return onBeforeWebsocketRequest(details); + var onBeforeRequest = validTypes.websocket + // modern Chromium/WebExtensions: type 'websocket' is supported + ? function(details) { + normalizeRequestDetails(details); + return onBeforeRequestClient(details); } - - normalizeRequestDetails(details); - return onBeforeRequestClient(details); - }; + // legacy Chromium + : function(details) { + // https://github.com/gorhill/uBlock/issues/1497 + if ( details.url.endsWith('ubofix=f41665f3028c7fd10eecf573336216d3') ) { + var r = onBeforeWebsocketRequest(details); + if ( r !== undefined ) { return r; } + } + normalizeRequestDetails(details); + return onBeforeRequestClient(details); + }; // This is needed for Chromium 49-55. - var onBeforeSendHeaders = function(details) { - if ( details.type !== 'ping' || details.method !== 'POST' ) { return; } - var type = headerValue(details.requestHeaders, 'content-type'); - if ( type === '' ) { return; } - if ( type.endsWith('/csp-report') ) { - details.type = 'csp_report'; - return onBeforeRequestClient(details); - } - }; + var onBeforeSendHeaders = validTypes.csp_report + // modern Chromium/WebExtensions: type 'csp_report' is supported + ? null + // legacy Chromium + : function(details) { + if ( details.type !== 'ping' || details.method !== 'POST' ) { return; } + var type = headerValue(details.requestHeaders, 'content-type'); + if ( type === '' ) { return; } + if ( type.endsWith('/csp-report') ) { + details.type = 'csp_report'; + return onBeforeRequestClient(details); + } + }; var onHeadersReceivedClient = this.onHeadersReceived.callback, onHeadersReceivedClientTypes = this.onHeadersReceived.types.slice(0), onHeadersReceivedTypes = denormalizeTypes(onHeadersReceivedClientTypes); - var onHeadersReceived = function(details) { - normalizeRequestDetails(details); - // Hack to work around Chromium API limitations, where requests of - // type `font` are returned as `other`. For example, our normalization - // fail at transposing `other` into `font` for URLs which are outside - // what is expected. At least when headers are received we can check - // for content type `font/*`. Blocking at onHeadersReceived time is - // less worse than not blocking at all. Also, due to Chromium bug, - // `other` always becomes `object` when it can't be normalized into - // something else. Test case for "unfriendly" font URLs: - // https://www.google.com/fonts - if ( details.type === 'font' ) { - var r = onBeforeRequestClient(details); - if ( typeof r === 'object' && r.cancel === true ) { - return { cancel: true }; + var onHeadersReceived = validTypes.font + // modern Chromium/WebExtensions: type 'font' is supported + ? function(details) { + normalizeRequestDetails(details); + if ( + onHeadersReceivedClientTypes.length !== 0 && + onHeadersReceivedClientTypes.indexOf(details.type) === -1 + ) { + return; } - } - if ( - onHeadersReceivedClientTypes.length !== 0 && - onHeadersReceivedClientTypes.indexOf(details.type) === -1 - ) { - return; - } - return onHeadersReceivedClient(details); - }; - - var installListeners = (function() { - var crapi = chrome.webRequest; - - //listener = function(details) { - // quickProfiler.start('onBeforeRequest'); - // var r = onBeforeRequest(details); - // quickProfiler.stop(); - // return r; - //}; - if ( crapi.onBeforeRequest.hasListener(onBeforeRequest) === false ) { - crapi.onBeforeRequest.addListener( - onBeforeRequest, - { - 'urls': this.onBeforeRequest.urls || [''], - 'types': this.onBeforeRequest.types || undefined - }, - this.onBeforeRequest.extra - ); - } + return onHeadersReceivedClient(details); + } + // legacy Chromium + : function(details) { + normalizeRequestDetails(details); + // Hack to work around Chromium API limitations, where requests of + // type `font` are returned as `other`. For example, our normalization + // fail at transposing `other` into `font` for URLs which are outside + // what is expected. At least when headers are received we can check + // for content type `font/*`. Blocking at onHeadersReceived time is + // less worse than not blocking at all. Also, due to Chromium bug, + // `other` always becomes `object` when it can't be normalized into + // something else. Test case for "unfriendly" font URLs: + // https://www.google.com/fonts + if ( details.type === 'font' ) { + var r = onBeforeRequestClient(details); + if ( typeof r === 'object' && r.cancel === true ) { + return { cancel: true }; + } + } + if ( + onHeadersReceivedClientTypes.length !== 0 && + onHeadersReceivedClientTypes.indexOf(details.type) === -1 + ) { + return; + } + return onHeadersReceivedClient(details); + }; - // Chromium 48 and lower does not support `ping` type. - // Chromium 56 and higher does support `csp_report` stype. - if ( is_v49_55 && crapi.onBeforeSendHeaders.hasListener(onBeforeSendHeaders) === false ) { - crapi.onBeforeSendHeaders.addListener( - onBeforeSendHeaders, - { - 'urls': [ '' ], - 'types': [ 'ping' ] - }, - [ 'blocking', 'requestHeaders' ] - ); - } + var urls, types; - if ( crapi.onHeadersReceived.hasListener(onHeadersReceived) === false ) { - crapi.onHeadersReceived.addListener( - onHeadersReceived, - { - 'urls': this.onHeadersReceived.urls || [''], - 'types': onHeadersReceivedTypes - }, - this.onHeadersReceived.extra - ); + if ( onBeforeRequest ) { + urls = this.onBeforeRequest.urls || ['']; + types = this.onBeforeRequest.types || undefined; + if ( + (validTypes.websocket) && + (types === undefined || types.indexOf('websocket') !== -1) && + (urls.indexOf('') === -1) + ) { + if ( urls.indexOf('ws://*/*') === -1 ) { + urls.push('ws://*/*'); + } + if ( urls.indexOf('wss://*/*') === -1 ) { + urls.push('wss://*/*'); + } } + wrApi.onBeforeRequest.addListener( + onBeforeRequest, + { urls: urls, types: types }, + this.onBeforeRequest.extra + ); + } - // https://github.com/gorhill/uBlock/issues/675 - // Experimental: keep polling to be sure our listeners are still installed. - //setTimeout(installListeners, 20000); - }).bind(this); + // Chromium 48 and lower does not support `ping` type. + // Chromium 56 and higher does support `csp_report` stype. + if ( onBeforeSendHeaders ) { + wrApi.onBeforeSendHeaders.addListener( + onBeforeSendHeaders, + { + 'urls': [ '' ], + 'types': [ 'ping' ] + }, + [ 'blocking', 'requestHeaders' ] + ); + } - installListeners(); + if ( onHeadersReceived ) { + urls = this.onHeadersReceived.urls || ['']; + types = onHeadersReceivedTypes; + wrApi.onHeadersReceived.addListener( + onHeadersReceived, + { urls: urls, types: types }, + this.onHeadersReceived.extra + ); + } }; /******************************************************************************/ @@ -1260,10 +1300,13 @@ vAPI.cloud = (function() { var maxChunkCountPerItem = Math.floor(512 * 0.75) & ~(chunkCountPerFetch - 1); // Mind chrome.storage.sync.QUOTA_BYTES_PER_ITEM (8192 at time of writing) - var maxChunkSize = Math.floor(chrome.storage.sync.QUOTA_BYTES_PER_ITEM * 0.75); + var maxChunkSize = Math.floor(chrome.storage.sync.QUOTA_BYTES_PER_ITEM * 0.75 || 6144); // Mind chrome.storage.sync.QUOTA_BYTES (128 kB at time of writing) - var maxStorageSize = chrome.storage.sync.QUOTA_BYTES; + // Firefox: + // https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/sync + // > You can store up to 100KB of data using this API/ + var maxStorageSize = chrome.storage.sync.QUOTA_BYTES || 102400; var options = { defaultDeviceName: window.navigator.platform, diff --git a/platform/webext/background.html b/platform/webext/background.html new file mode 100644 index 0000000000000..1abcdc511a3e8 --- /dev/null +++ b/platform/webext/background.html @@ -0,0 +1,37 @@ + + + + +uBlock Origin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/webext/bootstrap.js b/platform/webext/bootstrap.js new file mode 100644 index 0000000000000..69f6fc7ddda47 --- /dev/null +++ b/platform/webext/bootstrap.js @@ -0,0 +1,280 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + 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 + 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 +*/ + +/* exported startup, shutdown, install, uninstall */ + +'use strict'; + +/******************************************************************************/ + +const hostName = 'ublock0'; + +/******************************************************************************/ + +function startup({ webExtension }) { + webExtension.startup().then(api => { + let { browser } = api, + storageMigrator; + let onMessage = function(message, sender, callback) { + if ( message.what === 'webext:storageMigrateNext' ) { + storageMigrator = storageMigrator || getStorageMigrator(); + storageMigrator.getNext((key, value) => { + if ( key === undefined ) { + storageMigrator.markAsDone(); + storageMigrator = undefined; + browser.runtime.onMessage.removeListener(onMessage); + } + callback({ key: key, value: JSON.stringify(value) }); + }); + return true; + } + if ( typeof callback === 'function' ) { + callback(); + } + }; + browser.runtime.onMessage.addListener(onMessage); + }); +} + +function shutdown() { +} + +function install() { +} + +function uninstall() { +} + +/******************************************************************************/ + +var getStorageMigrator = function() { + var db = null; + var dbOpenError = ''; + + var close = function() { + if ( db !== null ) { + db.asyncClose(); + } + db = null; + }; + + var open = function() { + if ( db !== null ) { + return db; + } + + // Create path + var { Services } = Components.utils.import('resource://gre/modules/Services.jsm', null), + path = Services.dirsvc.get('ProfD', Components.interfaces.nsIFile); + path.append('extension-data'); + path.append(hostName + '.sqlite'); + if ( !path.exists() || !path.isFile() ) { + return null; + } + + // Open database. + try { + db = Services.storage.openDatabase(path); + if ( db.connectionReady === false ) { + db.asyncClose(); + db = null; + } + } catch (ex) { + if ( dbOpenError === '' ) { + dbOpenError = ex.name; + if ( ex.name === 'NS_ERROR_FILE_CORRUPTED' ) { + close(); + } + } + } + + if ( db === null ) { + return null; + } + + // Since database could be opened successfully, reset error flag (its + // purpose is to avoid spamming console with error messages). + dbOpenError = ''; + + return db; + }; + + // Execute a query + var runStatement = function(stmt, callback) { + var result = {}; + + stmt.executeAsync({ + handleResult: function(rows) { + if ( !rows || typeof callback !== 'function' ) { + return; + } + + var row; + + while ( (row = rows.getNextRow()) ) { + // we assume that there will be two columns, since we're + // using it only for preferences + result[row.getResultByIndex(0)] = row.getResultByIndex(1); + } + }, + handleCompletion: function(reason) { + if ( typeof callback === 'function' && reason === 0 ) { + callback(result); + } + result = null; + }, + handleError: function(error) { + // Caller expects an answer regardless of failure. + if ( typeof callback === 'function' ) { + callback({}); + } + result = null; + // https://github.com/gorhill/uBlock/issues/1768 + // Error cases which warrant a removal of the SQL file, so far: + // - SQLLite error 11 database disk image is malformed + // Can't find doc on MDN about the type of error.result, so I + // force a string comparison. + if ( error.result.toString() === '11' ) { + close(); + } + } + }); + }; + + var bindNames = function(stmt, names) { + if ( Array.isArray(names) === false || names.length === 0 ) { + return; + } + var params = stmt.newBindingParamsArray(); + var i = names.length, bp; + while ( i-- ) { + bp = params.newBindingParams(); + bp.bindByName('name', names[i]); + params.addParams(bp); + } + stmt.bindParameters(params); + }; + + var read = function(details, callback) { + if ( typeof callback !== 'function' ) { + return; + } + + var prepareResult = function(result) { + var key; + for ( key in result ) { + if ( result.hasOwnProperty(key) === false ) { + continue; + } + result[key] = JSON.parse(result[key]); + } + if ( typeof details === 'object' && details !== null ) { + for ( key in details ) { + if ( result.hasOwnProperty(key) === false ) { + result[key] = details[key]; + } + } + } + callback(result); + }; + + if ( open() === null ) { + prepareResult({}); + return; + } + + var names = []; + if ( details !== null ) { + if ( Array.isArray(details) ) { + names = details; + } else if ( typeof details === 'object' ) { + names = Object.keys(details); + } else { + names = [details.toString()]; + } + } + + var stmt; + if ( names.length === 0 ) { + stmt = db.createAsyncStatement('SELECT * FROM "settings"'); + } else { + stmt = db.createAsyncStatement('SELECT * FROM "settings" WHERE "name" = :name'); + bindNames(stmt, names); + } + + runStatement(stmt, prepareResult); + }; + + let allKeys; + + let readNext = function(key, callback) { + if ( key === undefined ) { + callback(); + return; + } + read(key, bin => { + if ( bin instanceof Object && bin.hasOwnProperty(key) ) { + callback(key, bin[key]); + } else { + callback(key); + } + }); + }; + + let getNext = function(callback) { + if ( Array.isArray(allKeys) ) { + readNext(allKeys.pop(), callback); + return; + } + if ( open() === null ) { + callback(); + return; + } + let stmt = db.createAsyncStatement('SELECT "name",\'dummy\' FROM "settings"'); + runStatement(stmt, result => { + allKeys = []; + for ( let key in result ) { + if ( result.hasOwnProperty(key) ) { + allKeys.push(key); + } + } + readNext(allKeys.pop(), callback); + }); + }; + + let markAsDone = function() { + close(); + let { Services } = Components.utils.import('resource://gre/modules/Services.jsm', null), + path = Services.dirsvc.get('ProfD', Components.interfaces.nsIFile); + path.append('extension-data'); + path.append(hostName + '.sqlite'); + if ( path.exists() && path.isFile() ) { + path.renameTo(null, hostName + '.migrated.sqlite'); + } + }; + + return { + getNext: getNext, + markAsDone: markAsDone, + }; +}; + +/******************************************************************************/ diff --git a/platform/webext/chrome.manifest b/platform/webext/chrome.manifest new file mode 100644 index 0000000000000..75781cd6f3b2f --- /dev/null +++ b/platform/webext/chrome.manifest @@ -0,0 +1 @@ +content ublock0 ./ diff --git a/platform/webext/from-legacy.js b/platform/webext/from-legacy.js new file mode 100644 index 0000000000000..456086536b618 --- /dev/null +++ b/platform/webext/from-legacy.js @@ -0,0 +1,61 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2017 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 +*/ + +// For background page + +'use strict'; + +/******************************************************************************/ + +(function() { + let µb = µBlock; + + let migrateAll = function(callback) { + let mustRestart = false; + + let migrateKeyValue = function(details, callback) { + let bin = {}; + bin[details.key] = JSON.parse(details.value); + self.browser.storage.local.set(bin, callback); + mustRestart = true; + }; + + let migrateNext = function() { + self.browser.runtime.sendMessage({ what: 'webext:storageMigrateNext' }, response => { + if ( response.key === undefined ) { + if ( mustRestart ) { + self.browser.runtime.reload(); + } else { + callback(); + } + return; + } + migrateKeyValue(response, migrateNext); + }); + }; + + migrateNext(); + }; + + µb.onBeforeStartQueue.push(migrateAll); +})(); + +/******************************************************************************/ diff --git a/platform/webext/install.rdf b/platform/webext/install.rdf new file mode 100644 index 0000000000000..35a548e72d574 --- /dev/null +++ b/platform/webext/install.rdf @@ -0,0 +1,28 @@ + + + + uBlock0@raymondhill.net + {version} + {name} + {description} + https://github.com/gorhill/uBlock + {author} + Deathamns + Alex Vallat + Manuel Reimer + 2 + true + true + true +{localized} + + + + + {{ec8030f7-c20a-464f-9b0e-13a3a9e97384}} + 52.0a1 + * + + + + diff --git a/platform/webext/manifest.json b/platform/webext/manifest.json index ebbbf36b1ef09..2579d659ae2b8 100644 --- a/platform/webext/manifest.json +++ b/platform/webext/manifest.json @@ -52,6 +52,7 @@ }, "permissions": [ "contextMenus", + "privacy", "storage", "tabs", "webNavigation", diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index 60d07103528cb..be51d8b82bc55 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -208,7 +208,7 @@ "description":"" }, "settingsAdvancedUserPrompt":{ - "message":"أنا مستخدم متقدم (قراءة إجبارية<\/a>)", + "message":"أنا مستخدم ذو خبرة (قراءة إجبارية<\/a>)", "description":"" }, "settingsAdvancedUserSettings":{ diff --git a/src/_locales/da/messages.json b/src/_locales/da/messages.json index b4cb45f624373..7189df5698b18 100644 --- a/src/_locales/da/messages.json +++ b/src/_locales/da/messages.json @@ -224,7 +224,7 @@ "description":"English: " }, "settingsWebRTCIPAddressHiddenPrompt":{ - "message":"Forhindre WebRTC i at lække lokale IP-adresser", + "message":"Forhindr WebRTC i at lække lokale IP-adresser", "description":"English: " }, "settingPerSiteSwitchGroup":{ @@ -232,7 +232,7 @@ "description":"" }, "settingPerSiteSwitchGroupSynopsis":{ - "message":"Disse standardindstillinger kan overskrives på en per-side basis", + "message":"Disse standardindstillinger kan tilsidesættes for hver enkelt websted", "description":"" }, "settingsNoCosmeticFilteringPrompt":{ @@ -240,7 +240,7 @@ "description":"" }, "settingsNoLargeMediaPrompt":{ - "message":"Bloker medieelementer større end {{input: nummer}} kB", + "message":"Bloker medieelementer større end {{input:number}} kB", "description":"" }, "settingsNoRemoteFontsPrompt":{ diff --git a/src/_locales/eo/messages.json b/src/_locales/eo/messages.json index 2c85a00160c1c..38e346efdea93 100644 --- a/src/_locales/eo/messages.json +++ b/src/_locales/eo/messages.json @@ -40,7 +40,7 @@ "description":"appears as tab name in dashboard" }, "advancedSettingsPageName":{ - "message":"Advanced settings", + "message":"Altgradaj agordoj", "description":"Title for the advanced settings page" }, "popupPowerSwitchInfo":{ @@ -212,7 +212,7 @@ "description":"" }, "settingsAdvancedUserSettings":{ - "message":"advanced settings", + "message":"altgradaj agordoj", "description":"For the tooltip of a link which gives access to advanced settings" }, "settingsPrefetchingDisabledPrompt":{ diff --git a/src/_locales/he/messages.json b/src/_locales/he/messages.json index 6efb8f457bed5..3b3b5a19e318f 100644 --- a/src/_locales/he/messages.json +++ b/src/_locales/he/messages.json @@ -424,7 +424,7 @@ "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ - "message":"רשימת שמות המתחם שלך בהם uBlock₀ לא יהיה פעיל. רשומה אחת בכל שורה. שמות מתחם לא חוקיים לא יפורשו ולא תהיה התראה לכך.", + "message":"הרשומות ברשימה הלבנה מציינות באילו דפי אינטרנט uBlock Origin לא יהיה פעיל. רשומה אחת בכל שורה. רשומות לא חוקיות תתעלמנה בשקט ויסומנו כהערות.", "description":"English: An overview of the content of the dashboard's Whitelist pane." }, "whitelistImport":{ diff --git a/src/_locales/pt_BR/messages.json b/src/_locales/pt_BR/messages.json index 1d8961fe5fd12..8fd70338719b7 100644 --- a/src/_locales/pt_BR/messages.json +++ b/src/_locales/pt_BR/messages.json @@ -200,7 +200,7 @@ "description":"English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt":{ - "message":"Modo Daltonismo", + "message":"Modo daltonismo", "description":"English: Color-blind friendly" }, "settingsCloudStorageEnabledPrompt":{ diff --git a/src/_locales/pt_PT/messages.json b/src/_locales/pt_PT/messages.json index e824fb2cb458d..80b866180d310 100644 --- a/src/_locales/pt_PT/messages.json +++ b/src/_locales/pt_PT/messages.json @@ -560,7 +560,7 @@ "description":"English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton":{ - "message":"Restaurar por um ficheiro...", + "message":"Restaurar a partir de um ficheiro...", "description":"English: Restore from file..." }, "aboutResetDataButton":{ @@ -568,7 +568,7 @@ "description":"English: Reset to default settings..." }, "aboutRestoreDataConfirm":{ - "message":"Todas as suas definições serão substituídas utilizando os dados da cópia de segurança de {{time}}, e uBlock₀ irá reiniciar.\n\nSubstituir todas as definições existentes utilizando os dados da cópia de segurança?", + "message":"Todas as suas definições serão substituídas utilizando os dados da cópia de segurança de {{time}}, e o uBlock₀ irá reiniciar.\n\nSubstituir todas as definições existentes utilizando os dados da cópia de segurança?", "description":"Message asking user to confirm restore" }, "aboutRestoreDataError":{ diff --git a/src/_locales/sv/messages.json b/src/_locales/sv/messages.json index 5694fa423c4a6..4febe47c8da29 100644 --- a/src/_locales/sv/messages.json +++ b/src/_locales/sv/messages.json @@ -76,7 +76,7 @@ "description":"English: Enter element picker mode" }, "popupTipLog":{ - "message":"Öppna loggaren", + "message":"Öppna loggen", "description":"Tooltip used for the logger icon in the panel" }, "popupTipNoPopups":{ diff --git a/src/epicker.html b/src/epicker.html index fc1f34e520a3a..42df6414195b6 100644 --- a/src/epicker.html +++ b/src/epicker.html @@ -78,7 +78,7 @@ resize: none; width: 100%; } -section > div:first-child > textarea + div { +#resultsetCount { background-color: #aaa; bottom: 0; color: white; @@ -86,7 +86,7 @@ position: absolute; right: 0; } -section.invalidFilter > div:first-child > textarea + div { +section.invalidFilter #resultsetCount { background-color: red; } section > div:first-child + div { @@ -183,7 +183,7 @@
-
+