From 57048d57b26c3ff516f70b64329babc17bfa932a Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 6 Oct 2020 12:39:05 -0400 Subject: [PATCH 01/73] Reject improper use of procedural operator in selector list Related feedback: - https://github.com/uBlockOrigin/uBlock-issues/issues/382#issuecomment-703725346 --- src/js/static-filtering-parser.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/js/static-filtering-parser.js b/src/js/static-filtering-parser.js index a2860465f5009..4df8f7c6fde51 100644 --- a/src/js/static-filtering-parser.js +++ b/src/js/static-filtering-parser.js @@ -1372,9 +1372,9 @@ Parser.prototype.SelectorCompiler = class { return { name: name, value: regexDetails }; } + // https://github.com/AdguardTeam/ExtendedCss/issues/31#issuecomment-302391277 + // Prepend `:scope ` if needed. compileConditionalSelector(s) { - // https://github.com/AdguardTeam/ExtendedCss/issues/31#issuecomment-302391277 - // Prepend `:scope ` if needed. if ( this.reNeedScope.test(s) ) { s = `:scope ${s}`; } @@ -1388,11 +1388,11 @@ Parser.prototype.SelectorCompiler = class { return n; } + // https://github.com/uBlockOrigin/uBlock-issues/issues/341#issuecomment-447603588 + // Reject instances of :not() filters for which the argument is + // a valid CSS selector, otherwise we would be adversely + // changing the behavior of CSS4's :not(). compileNotSelector(s) { - // https://github.com/uBlockOrigin/uBlock-issues/issues/341#issuecomment-447603588 - // Reject instances of :not() filters for which the argument is - // a valid CSS selector, otherwise we would be adversely - // changing the behavior of CSS4's :not(). if ( this.cssSelectorType(s) === 0 ) { return this.compileConditionalSelector(s); } @@ -1408,8 +1408,10 @@ Parser.prototype.SelectorCompiler = class { if ( s === '' ) { return s; } } + // https://github.com/uBlockOrigin/uBlock-issues/issues/382#issuecomment-703725346 + // Prepend `*` only when it can be deemed implicit. compileSpathExpression(s) { - if ( this.cssSelectorType('*' + s) === 1 ) { + if ( this.cssSelectorType(/^\s*[+:>~]/.test(s) ? '*' + s : s) === 1 ) { return s; } } From 778338fce865a54a29d284e3eba01278c5c94f8f Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 6 Oct 2020 17:26:28 -0400 Subject: [PATCH 02/73] Fix picker generating overly long candidate cosmetic filters Related feedback: - https://www.reddit.com/r/uBlockOrigin/comments/j5tx8x/understand_the_element_blocker_and_feedback/g7wf2q9/ Regression from: - https://github.com/gorhill/uBlock/commit/9eb455ab5eb2 --- src/css/epicker-ui.css | 2 +- src/js/epicker-ui.js | 36 +++++++++++++++++++++++++++++------- src/js/scriptlets/epicker.js | 23 +++++++++++++++++++++++ 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/css/epicker-ui.css b/src/css/epicker-ui.css index efe685f76620b..68f33ad1b04cd 100644 --- a/src/css/epicker-ui.css +++ b/src/css/epicker-ui.css @@ -116,7 +116,7 @@ html#ublock0-epicker, justify-content: space-evenly; } #resultsetModifiers.hide > * { - display: none; + visibility: hidden; } .resultsetModifier { border: 0; diff --git a/src/js/epicker-ui.js b/src/js/epicker-ui.js index 7ab87c35f8926..abb9d86edfe50 100644 --- a/src/js/epicker-ui.js +++ b/src/js/epicker-ui.js @@ -230,13 +230,24 @@ const candidateFromFilterChoice = function(filterChoice) { paths.unshift('body > '); } - computedCandidate = `##${paths.join('')}`; + if ( paths.length === 0 ) { return ''; } - $id('resultsetModifiers').classList.remove('hide'); renderRange('resultsetDepth', slot, true); renderRange('resultsetSpecificity'); - return computedCandidate; + vAPI.MessagingConnection.sendTo(epickerConnectionId, { + what: 'optimizeCandidate', + paths, + }); +}; + +/******************************************************************************/ + +const onCandidateOptimized = function(details) { + $id('resultsetModifiers').classList.remove('hide'); + computedCandidate = details.filter; + taCandidate.value = computedCandidate; + onCandidateChanged(); }; /******************************************************************************/ @@ -437,10 +448,12 @@ const onDepthChanged = function() { const input = $stor('#resultsetDepth input'); const max = parseInt(input.max, 10); const value = parseInt(input.value, 10); - taCandidate.value = candidateFromFilterChoice({ + const text = candidateFromFilterChoice({ filters: cosmeticFilterCandidates, slot: max - value, }); + if ( text === undefined ) { return; } + taCandidate.value = text; onCandidateChanged(); }; @@ -448,10 +461,12 @@ const onDepthChanged = function() { const onSpecificityChanged = function() { if ( taCandidate.value !== computedCandidate ) { return; } - taCandidate.value = candidateFromFilterChoice({ + const text = candidateFromFilterChoice({ filters: cosmeticFilterCandidates, slot: computedCandidateSlot, }); + if ( text === undefined ) { return; } + taCandidate.value = text; onCandidateChanged(); }; @@ -470,7 +485,9 @@ const onCandidateClicked = function(ev) { li = li.previousElementSibling; choice.slot += 1; } - taCandidate.value = candidateFromFilterChoice(choice); + const text = candidateFromFilterChoice(choice); + if ( text === undefined ) { return; } + taCandidate.value = text; onCandidateChanged(); }; @@ -692,7 +709,9 @@ const showDialog = function(details) { slot: filter.slot, }; - taCandidate.value = candidateFromFilterChoice(filterChoice); + const text = candidateFromFilterChoice(filterChoice); + if ( text === undefined ) { return; } + taCandidate.value = text; onCandidateChanged(); }; @@ -751,6 +770,9 @@ const quitPicker = function() { const onPickerMessage = function(msg) { switch ( msg.what ) { + case 'candidateOptimized': + onCandidateOptimized(msg); + break; case 'showDialog': showDialog(msg); break; diff --git a/src/js/scriptlets/epicker.js b/src/js/scriptlets/epicker.js index 943e5b7b04e53..311c226f312ba 100644 --- a/src/js/scriptlets/epicker.js +++ b/src/js/scriptlets/epicker.js @@ -820,6 +820,26 @@ const filterToDOMInterface = (( ) => { /******************************************************************************/ +const onOptmizeCandidate = function(details) { + const { paths } = details; + let count = Number.MAX_SAFE_INTEGER; + let selector = ''; + for ( let i = 0, n = paths.length; i < n; i++ ) { + const s = paths.slice(n - i - 1).join(''); + const elems = document.querySelectorAll(s); + if ( elems.length < count ) { + selector = s; + count = elems.length; + } + } + vAPI.MessagingConnection.sendTo(epickerConnectionId, { + what: 'candidateOptimized', + filter: `##${selector}`, + }); +}; + +/******************************************************************************/ + const showDialog = function(options) { vAPI.MessagingConnection.sendTo(epickerConnectionId, { what: 'showDialog', @@ -1044,6 +1064,9 @@ const onDialogMessage = function(msg) { highlightElements([], true); } break; + case 'optimizeCandidate': + onOptmizeCandidate(msg); + break; case 'dialogCreate': filterToDOMInterface.queryAll(msg); filterToDOMInterface.preview(true, true); From 956544661bb86d7d4e969a8e93e7bbd1384a8ebc Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 6 Oct 2020 17:30:03 -0400 Subject: [PATCH 03/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 0b5c5068be376..2eb7bf41f2464 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.1.5 +1.30.1.6 From e2e51c4df6c2d37c0a9f5486f1293e960d6426f1 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 6 Oct 2020 17:36:08 -0400 Subject: [PATCH 04/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index ad223b30089b3..58f9b9307218a 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.1.5", + "version": "1.30.1.6", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.1b5", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.1b5/uBlock0_1.30.1b5.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.1b6", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.1b6/uBlock0_1.30.1b6.firefox.signed.xpi" } ] } From 04b11b431146926718d5ab4308601bba4ea2ab6d Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 6 Oct 2020 21:02:51 -0400 Subject: [PATCH 05/73] Fix restore backup feature Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1282 --- src/js/messaging.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/messaging.js b/src/js/messaging.js index d6327e6a86c3b..89d1b2c960d32 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -938,8 +938,8 @@ const restoreUserData = async function(request) { // Discard unknown setting or setting with default value. for ( const key in hiddenSettings ) { if ( - this.hiddenSettingsDefault.hasOwnProperty(key) === false || - hiddenSettings[key] === this.hiddenSettingsDefault[key] + µb.hiddenSettingsDefault.hasOwnProperty(key) === false || + hiddenSettings[key] === µb.hiddenSettingsDefault[key] ) { delete hiddenSettings[key]; } From 80ca6dad85afc7960181015cd29fd3b0088d61fc Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 6 Oct 2020 21:03:57 -0400 Subject: [PATCH 06/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 2eb7bf41f2464..c674d00863ab8 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.1.6 +1.30.1.7 From df604b414bcf104ed5ee76e108fa41ec88a5461e Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 6 Oct 2020 21:11:00 -0400 Subject: [PATCH 07/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 58f9b9307218a..80e4019250abf 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.1.6", + "version": "1.30.1.7", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.1b6", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.1b6/uBlock0_1.30.1b6.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.1b7", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.1b7/uBlock0_1.30.1b7.firefox.signed.xpi" } ] } From bfe5e2daa1bc3ccea3734166d9c7f4970f963877 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 7 Oct 2020 11:04:16 -0400 Subject: [PATCH 08/73] Limit width of picker dialog in large viewport --- src/css/epicker-ui.css | 5 +++-- src/css/themes/default.css | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/css/epicker-ui.css b/src/css/epicker-ui.css index 68f33ad1b04cd..e45b935dd0913 100644 --- a/src/css/epicker-ui.css +++ b/src/css/epicker-ui.css @@ -14,12 +14,13 @@ html#ublock0-epicker, } #ublock0-epicker aside { background-color: var(--default-surface); - border: 1px solid #aaa; + border: 1px solid var(--default-surface-border); bottom: 4px; box-sizing: border-box; cursor: default; display: none; - min-width: 24em; + max-width: 36rem; + min-width: 24rem; padding: 4px; position: fixed; right: 4px; diff --git a/src/css/themes/default.css b/src/css/themes/default.css index c0eb567895c23..8ba229500a0a5 100644 --- a/src/css/themes/default.css +++ b/src/css/themes/default.css @@ -78,6 +78,7 @@ --default-ink-a4: var(--ink-80-a4); --default-ink-a50: var(--ink-80-a50); --default-surface: var(--light-gray-10); + --default-surface-border: var(--light-gray-70); --default-surface-hover: var(--light-gray-30-a50); --bg-1: hsla(240, 20%, 98%, 1); From 46ec9694115d79ef3b380f366a8332ead267ef49 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 7 Oct 2020 11:52:38 -0400 Subject: [PATCH 09/73] Add ability to use full URL in auto-generated comment Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1281 New supported placeholder: `{{url}}`, which will be replaced by the full URL of the page for which a filter is created. --- src/js/epicker-ui.js | 21 ++++++++------------- src/js/logger-ui.js | 9 +++++---- src/js/scriptlets/epicker.js | 3 +-- src/js/storage.js | 15 +++++++++------ 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/js/epicker-ui.js b/src/js/epicker-ui.js index abb9d86edfe50..2242ec538c761 100644 --- a/src/js/epicker-ui.js +++ b/src/js/epicker-ui.js @@ -53,9 +53,9 @@ const epickerId = (( ) => { })(); if ( epickerId === null ) { return; } +const docURL = new URL(vAPI.getURL('')); + let epickerConnectionId; -let filterHostname = ''; -let filterOrigin = ''; let resultsetOpt; let netFilterCandidates = []; @@ -102,9 +102,11 @@ const renderRange = function(id, value, invert = false) { const userFilterFromCandidate = function(filter) { if ( filter === '' || filter === '!' ) { return; } + const hn = vAPI.hostnameFromURI(docURL.href); + // Cosmetic filter? if ( filter.startsWith('##') ) { - return filterHostname + filter; + return hn + filter; } // Assume net filter @@ -112,7 +114,7 @@ const userFilterFromCandidate = function(filter) { // If no domain included in filter, we need domain option if ( filter.startsWith('||') === false ) { - opts.push(`domain=${filterHostname}`); + opts.push(`domain=${hn}`); } if ( resultsetOpt !== undefined ) { @@ -416,8 +418,7 @@ const onCreateClicked = function() { what: 'createUserFilter', autoComment: true, filters: filter, - origin: filterOrigin, - pageDomain: filterHostname, + docURL: docURL.href, killCache: /^#[$?]?#/.test(candidate) === false, }); } @@ -672,13 +673,7 @@ const showDialog = function(details) { } cosmeticFilterCandidates = cosmeticFilters; - // https://github.com/gorhill/uBlock/issues/738 - // Trim dots. - filterHostname = details.hostname; - if ( filterHostname.slice(-1) === '.' ) { - filterHostname = filterHostname.slice(0, -1); - } - filterOrigin = details.origin; + docURL.href = details.url; populateCandidates(netFilters, '#netFilters'); populateCandidates(cosmeticFilters, '#cosmeticFilters'); diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js index 939ff672095d5..cfd9ed4be2450 100644 --- a/src/js/logger-ui.js +++ b/src/js/logger-ui.js @@ -1263,13 +1263,16 @@ const reloadTab = function(ev) { // Avoid duplicates if ( createdStaticFilters.hasOwnProperty(value) ) { return; } createdStaticFilters[value] = true; + // https://github.com/uBlockOrigin/uBlock-issues/issues/1281#issuecomment-704217175 + // TODO: + // Figure a way to use the actual document URL. Currently using + // a synthetic URL derived from the document hostname. if ( value !== '' ) { messaging.send('loggerUI', { what: 'createUserFilter', autoComment: true, filters: value, - origin: targetPageDomain, - pageDomain: targetPageDomain, + docURL: `https://${targetFrameHostname}/`, }); } updateWidgets(); @@ -1872,8 +1875,6 @@ const reloadTab = function(ev) { ); })(); -// https://www.youtube.com/watch?v=XyNYrmmdUd4 - /******************************************************************************/ /******************************************************************************/ diff --git a/src/js/scriptlets/epicker.js b/src/js/scriptlets/epicker.js index 311c226f312ba..c249de68c688c 100644 --- a/src/js/scriptlets/epicker.js +++ b/src/js/scriptlets/epicker.js @@ -843,8 +843,7 @@ const onOptmizeCandidate = function(details) { const showDialog = function(options) { vAPI.MessagingConnection.sendTo(epickerConnectionId, { what: 'showDialog', - hostname: self.location.hostname, - origin: self.location.origin, + url: self.location.href, netFilters: netFilterCandidates, cosmeticFilters: cosmeticFilterCandidates, filter: bestCandidateFilter, diff --git a/src/js/storage.js b/src/js/storage.js index 79ea86051e49e..4fc5457de7590 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -399,12 +399,15 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { // Date in YYYY-MM-DD format - https://stackoverflow.com/a/50130338 const ISO8061Date = new Date(d.getTime() + (d.getTimezoneOffset()*60000)).toISOString().split('T')[0]; + const url = new URL(options.docURL); comment = '! ' + this.hiddenSettings.autoCommentFilterTemplate .replace('{{date}}', ISO8061Date) .replace('{{time}}', d.toLocaleTimeString()) - .replace('{{origin}}', options.origin); + .replace('{{hostname}}', url.hostname) + .replace('{{origin}}', url.origin) + .replace('{{url}}', url.href); } const details = await this.loadUserFilters(); @@ -414,10 +417,7 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { // from the last comment found in the user filter list. if ( comment !== '' ) { const pos = details.content.lastIndexOf(comment); - if ( - pos === -1 || - details.content.indexOf('\n!', pos + 1) !== -1 - ) { + if ( pos === -1 || details.content.indexOf('\n!', pos + 1) !== -1 ) { filters = '\n' + comment + '\n' + filters; } } @@ -462,7 +462,10 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { µBlock.createUserFilters = function(details) { this.appendUserFilters(details.filters, details); // https://github.com/gorhill/uBlock/issues/1786 - this.cosmeticFilteringEngine.removeFromSelectorCache(details.pageDomain); + if ( details.docURL === undefined ) { return; } + this.cosmeticFilteringEngine.removeFromSelectorCache( + vAPI.hostnameFromURI(details.docURL) + ); }; /******************************************************************************/ From a2ff2097cef79c7b58aab013177f0f6693bd428b Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 7 Oct 2020 11:54:40 -0400 Subject: [PATCH 10/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index c674d00863ab8..98aa8ba26e45f 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.1.7 +1.30.1.8 From 5a956d4d5d4bcedcacff902afb647f13141b8bdb Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 7 Oct 2020 11:55:08 -0400 Subject: [PATCH 11/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 98aa8ba26e45f..6d142b10474c8 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.1.8 +1.30.3.0 From d84bfd3f355cd6e537b0d08af45b1b5594d241bf Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 7 Oct 2020 12:15:52 -0400 Subject: [PATCH 12/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 80e4019250abf..66501d8aca81e 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.1.7", + "version": "1.30.3.0", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.1b7", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.1b7/uBlock0_1.30.1b7.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b0", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b0/uBlock0_1.30.3b0.firefox.signed.xpi" } ] } From 4f00c08f6b5f707faa428aecded2901c4a65dd2a Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 7 Oct 2020 14:23:57 -0400 Subject: [PATCH 13/73] Fix detection of already present comment Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1281 Related feedback: - https://github.com/uBlockOrigin/uBlock-issues/issues/1281#issuecomment-705081202 --- src/js/storage.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/js/storage.js b/src/js/storage.js index 4fc5457de7590..cef46fcd25b5b 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -416,8 +416,13 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { // The comment, if any, will be applied if and only if it is different // from the last comment found in the user filter list. if ( comment !== '' ) { - const pos = details.content.lastIndexOf(comment); - if ( pos === -1 || details.content.indexOf('\n!', pos + 1) !== -1 ) { + const beg = details.content.lastIndexOf(comment); + const end = beg === -1 ? -1 : beg + comment.length; + if ( + end === -1 || + details.content.startsWith('\n', end) === false || + details.content.includes('\n!', end) + ) { filters = '\n' + comment + '\n' + filters; } } @@ -428,10 +433,9 @@ self.addEventListener('hiddenSettingsChanged', ( ) => { // duplicates at this point may lead to more issues. await this.saveUserFilters(details.content.trim() + '\n' + filters); - const compiledFilters = this.compileFilters( - filters, - { assetKey: this.userFiltersPath } - ); + const compiledFilters = this.compileFilters(filters, { + assetKey: this.userFiltersPath + }); const snfe = this.staticNetFilteringEngine; const cfe = this.cosmeticFilteringEngine; const acceptedCount = snfe.acceptedCount + cfe.acceptedCount; From 11b9f88b382ee9b918ad66b6c8b3bd11a9c785c5 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 8 Oct 2020 07:25:15 -0400 Subject: [PATCH 14/73] Update urlhaus-filter URL Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1285 --- assets/assets.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/assets.json b/assets/assets.json index 37e42df92fa22..3e0fbc39a871c 100644 --- a/assets/assets.json +++ b/assets/assets.json @@ -147,7 +147,7 @@ "group": "malware", "title": "Online Malicious URL Blocklist", "contentURL": [ - "https://gitlab.com/curben/urlhaus-filter/raw/master/urlhaus-filter-online.txt", + "https://curben.gitlab.io/malware-filter/urlhaus-filter-online.txt", "https://raw.githubusercontent.com/curbengh/urlhaus-filter/master/urlhaus-filter-online.txt", "assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt" ], @@ -156,7 +156,7 @@ "https://gitcdn.xyz/repo/curbengh/urlhaus-filter/master/urlhaus-filter-online.txt", "https://cdn.jsdelivr.net/gh/curbengh/urlhaus-filter/urlhaus-filter-online.txt", "https://raw.githubusercontent.com/curbengh/urlhaus-filter/master/urlhaus-filter-online.txt", - "https://gitlab.com/curben/urlhaus-filter/raw/master/urlhaus-filter-online.txt" + "https://curben.gitlab.io/malware-filter/urlhaus-filter-online.txt" ], "supportURL": "https://gitlab.com/curben/urlhaus-filter#urlhaus-malicious-url-blocklist" }, From c3f267db8fe1c3a7ed98662a31ddb7172a166e10 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 8 Oct 2020 09:49:35 -0400 Subject: [PATCH 15/73] Improve bad filter detection in element picker Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1280 --- src/js/epicker-ui.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/js/epicker-ui.js b/src/js/epicker-ui.js index 2242ec538c761..15eefafe0e6c8 100644 --- a/src/js/epicker-ui.js +++ b/src/js/epicker-ui.js @@ -71,9 +71,17 @@ const filterFromTextarea = function() { if ( s === '' ) { return ''; } const pos = s.indexOf('\n'); const filter = pos === -1 ? s.trim() : s.slice(0, pos).trim(); - staticFilteringParser.analyze(filter); - staticFilteringParser.analyzeExtra(); - return staticFilteringParser.shouldDiscard() ? '!' : filter; + const sfp = staticFilteringParser; + sfp.analyze(filter); + sfp.analyzeExtra(); + if ( + sfp.category !== sfp.CATStaticExtFilter && + sfp.category !== sfp.CATStaticNetFilter || + sfp.shouldDiscard() + ) { + return '!'; + } + return filter; }; /******************************************************************************/ From e1bf3c84c24c5eec3a9e5eacc3873503d418f636 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 8 Oct 2020 09:52:14 -0400 Subject: [PATCH 16/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 6d142b10474c8..bfd5567b63219 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.0 +1.30.3.1 From 2d1d7e193e8cf0a29d50a2fbade6782f137bb8f2 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 8 Oct 2020 09:55:44 -0400 Subject: [PATCH 17/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 66501d8aca81e..7f89161e6132b 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.3.0", + "version": "1.30.3.1", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b0", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b0/uBlock0_1.30.3b0.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b1", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b1/uBlock0_1.30.3b1.firefox.signed.xpi" } ] } From ba0b62ec97a5ce1fdd71f8ba97d83d83bf84eaf6 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Thu, 8 Oct 2020 10:15:33 -0400 Subject: [PATCH 18/73] Update to more accurate explanation --- src/web_accessible_resources/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web_accessible_resources/README.txt b/src/web_accessible_resources/README.txt index 6b0a4c41aa4a7..f9ab5c3a11d5b 100644 --- a/src/web_accessible_resources/README.txt +++ b/src/web_accessible_resources/README.txt @@ -1,7 +1,7 @@ IMPORTANT Content of this folder cannot be accessed without the internal secret token -created each time uBlock Origin is launched. +created for each request to any of the "web accessible resources". Any fetch operation made without uBlock Origin's internal secret will result in failure. This means that despite the content of the folder here declared as From 59169209850c54c31d94990f0c956281fe43eb03 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 9 Oct 2020 13:50:54 -0400 Subject: [PATCH 19/73] Add support for click-to-load of embedded frames Additionally, as a requirement to support click-to-load feature, redirected resources will from now on no longer be collapsed. Related issues: - https://github.com/gorhill/uBlock/issues/2688 - https://github.com/gorhill/uBlock/issues/3619 - https://github.com/gorhill/uBlock/issues/1899 This new feature should considered in its draft stage and it needs to be fine-tuned as per feedback. Important: Only embedded frames can be converted into click-to-load widgets, as only these can be properly shieded from access by page content. Examples of usage: ||youtube.com/embed/$3p,frame,redirect=clicktoload ||scribd.com/embeds/$3p,frame,redirect=clicktoload ||player.vimeo.com/video/$3p,frame,redirect=clicktoload --- src/css/click-to-load.css | 48 +++++++++++++ src/css/themes/default.css | 2 + src/js/click-to-load.js | 63 +++++++++++++++++ src/js/filtering-context.js | 16 +++-- src/js/messaging.js | 15 +++- src/js/pagestore.js | 69 +++++++++++++++---- src/js/redirect-engine.js | 17 ++++- src/js/traffic.js | 5 +- .../click-to-load.html | 25 +++++++ 9 files changed, 238 insertions(+), 22 deletions(-) create mode 100644 src/css/click-to-load.css create mode 100644 src/js/click-to-load.js create mode 100644 src/web_accessible_resources/click-to-load.html diff --git a/src/css/click-to-load.css b/src/css/click-to-load.css new file mode 100644 index 0000000000000..e6e4d77fdd41f --- /dev/null +++ b/src/css/click-to-load.css @@ -0,0 +1,48 @@ +/** + uBlock Origin - a browser extension to block requests. + Copyright (C) 2014-present 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 +*/ + +body { + align-items: center; + background-color: var(--default-surface); + border: 1px solid var(--ubo-red); + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: space-evenly; + position: relative; + } + +.logo { + left: 0; + padding: 2px; + position: absolute; + top: 0; + } + +#frameURL { + font-family: monospace; + font-size: 90%; + overflow: hidden; + word-break: break-all; + } + +#clickToLoad { + cursor: default; + } diff --git a/src/css/themes/default.css b/src/css/themes/default.css index 8ba229500a0a5..00a2d10100213 100644 --- a/src/css/themes/default.css +++ b/src/css/themes/default.css @@ -74,6 +74,8 @@ :root { --font-size: 14px; + --ubo-red: #800000; + --default-ink: var(--ink-80); --default-ink-a4: var(--ink-80-a4); --default-ink-a50: var(--ink-80-a50); diff --git a/src/js/click-to-load.js b/src/js/click-to-load.js new file mode 100644 index 0000000000000..b43e5cdb1d31f --- /dev/null +++ b/src/js/click-to-load.js @@ -0,0 +1,63 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2014-present 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 +*/ + +'use strict'; + +/******************************************************************************/ +/******************************************************************************/ + +(( ) => { + +/******************************************************************************/ + +if ( typeof vAPI !== 'object' ) { return; } + +const url = new URL(self.location.href); +const frameURL = url.searchParams.get('url'); +const frameURLElem = document.getElementById('frameURL'); + +frameURLElem.textContent = frameURL; + +const onWindowResize = function() { + document.body.style.width = `${self.innerWidth}px`; + document.body.style.height = `${self.innerHeight}px`; +}; + +onWindowResize(); + +self.addEventListener('resize', onWindowResize); + +document.body.addEventListener('click', ev => { + if ( ev.isTrusted === false ) { return; } + //if ( ev.target === frameURLElem ) { return; } + vAPI.messaging.send('default', { + what: 'clickToLoad', + frameURL, + }).then(ok => { + if ( ok ) { + self.location.replace(frameURL); + } + }); +}); + +/******************************************************************************/ + +})(); diff --git a/src/js/filtering-context.js b/src/js/filtering-context.js index 9623723059ea8..17f46b1226be3 100644 --- a/src/js/filtering-context.js +++ b/src/js/filtering-context.js @@ -35,7 +35,8 @@ this.aliasURL = undefined; this.hostname = undefined; this.domain = undefined; - this.docId = undefined; + this.docId = -1; + this.frameId = -1; this.docOrigin = undefined; this.docHostname = undefined; this.docDomain = undefined; @@ -69,9 +70,13 @@ this.type = details.type; this.setURL(details.url); this.aliasURL = details.aliasURL || undefined; - this.docId = details.type !== 'sub_frame' - ? details.frameId - : details.parentFrameId; + if ( details.type !== 'sub_frame' ) { + this.docId = details.frameId; + this.frameId = -1; + } else { + this.docId = details.parentFrameId; + this.frameId = details.frameId; + } if ( this.tabId > 0 ) { if ( this.docId === 0 ) { this.docOrigin = this.tabOrigin; @@ -81,7 +86,7 @@ this.setDocOriginFromURL(details.documentUrl); } else { const pageStore = µBlock.pageStoreFromTabId(this.tabId); - const docStore = pageStore && pageStore.getFrame(this.docId); + const docStore = pageStore && pageStore.getFrameStore(this.docId); if ( docStore ) { this.setDocOriginFromURL(docStore.rawURL); } else { @@ -109,6 +114,7 @@ this.hostname = other.hostname; this.domain = other.domain; this.docId = other.docId; + this.frameId = other.frameId; this.docOrigin = other.docOrigin; this.docHostname = other.docHostname; this.docDomain = other.docDomain; diff --git a/src/js/messaging.js b/src/js/messaging.js index 89d1b2c960d32..44c4e810fdfdc 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -41,6 +41,15 @@ const µb = µBlock; +const clickToLoad = function(request, sender) { + const { tabId, frameId } = µb.getMessageSenderDetails(sender); + if ( tabId === undefined || frameId === undefined ) { return false; } + const pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore === null ) { return false; } + pageStore.clickToLoad(frameId, request.frameURL); + return true; +}; + const getDomainNames = function(targets) { const µburi = µb.URI; return targets.map(target => { @@ -93,13 +102,17 @@ const onMessage = function(request, sender, callback) { } // Sync - var response; + let response; switch ( request.what ) { case 'applyFilterListSelection': response = µb.applyFilterListSelection(request); break; + case 'clickToLoad': + response = clickToLoad(request, sender); + break; + case 'createUserFilter': µb.createUserFilters(request); break; diff --git a/src/js/pagestore.js b/src/js/pagestore.js index c086352bee82d..f5cd7dd9c1675 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -84,6 +84,12 @@ const NetFilteringResultCache = class { this.hash = now; } + forgetResult(fctxt) { + const key = `${fctxt.getDocHostname()} ${fctxt.type} ${fctxt.url}`; + this.results.delete(key); + this.blocked.delete(key); + } + empty() { this.blocked.clear(); this.results.clear(); @@ -165,6 +171,7 @@ const FrameStore = class { init(frameURL) { this.t0 = Date.now(); this.exceptCname = undefined; + this.clickToLoad = 0; this.rawURL = frameURL; if ( frameURL !== undefined ) { this.hostname = vAPI.hostnameFromURI(frameURL); @@ -253,7 +260,7 @@ const PageStore = class { this.frameAddCount = 0; this.frames = new Map(); - this.setFrame(0, tabContext.rawURL); + this.setFrameURL(0, tabContext.rawURL); // The current filtering context is cloned because: // - We may be called with or without the current context having been @@ -308,7 +315,7 @@ const PageStore = class { // As part of https://github.com/chrisaljoudi/uBlock/issues/405 // URL changed, force a re-evaluation of filtering switch this.rawURL = tabContext.rawURL; - this.setFrame(0, this.rawURL); + this.setFrameURL(0, this.rawURL); return this; } @@ -353,20 +360,23 @@ const PageStore = class { this.frames.clear(); } - getFrame(frameId) { + getFrameStore(frameId) { return this.frames.get(frameId) || null; } - setFrame(frameId, frameURL) { - const frameStore = this.frames.get(frameId); + setFrameURL(frameId, frameURL) { + let frameStore = this.frames.get(frameId); if ( frameStore !== undefined ) { frameStore.init(frameURL); - return; + } else { + frameStore = FrameStore.factory(frameURL); + this.frames.set(frameId, frameStore); + this.frameAddCount += 1; + if ( (this.frameAddCount & 0b111111) === 0 ) { + this.pruneFrames(); + } } - this.frames.set(frameId, FrameStore.factory(frameURL)); - this.frameAddCount += 1; - if ( (this.frameAddCount & 0b111111) !== 0 ) { return; } - this.pruneFrames(); + return frameStore; } // There is no event to tell us a specific subframe has been removed from @@ -597,6 +607,22 @@ const PageStore = class { } } + // Click-to-load: + // When frameId is not -1, the resource is always sub_frame. + if ( result === 1 && fctxt.frameId !== -1 ) { + const docStore = this.getFrameStore(fctxt.frameId); + if ( docStore !== null && docStore.clickToLoad !== 0 ) { + result = 2; + if ( µb.logger.enabled ) { + fctxt.setFilter({ + result, + source: 'network', + raw: 'click-to-load', + }); + } + } + } + if ( cacheableResult ) { this.netFilteringCache.rememberResult(fctxt, result); } else if ( @@ -696,11 +722,19 @@ const PageStore = class { return 1; } + clickToLoad(frameId, frameURL) { + let frameStore = this.getFrameStore(frameId); + if ( frameStore === null ) { + frameStore = this.setFrameURL(frameId, frameURL); + } + frameStore.clickToLoad = Date.now(); + } + shouldExceptCname(fctxt) { let exceptCname; let frameStore; if ( fctxt.docId !== undefined ) { - frameStore = this.getFrame(fctxt.docId); + frameStore = this.getFrameStore(fctxt.docId); if ( frameStore instanceof Object ) { exceptCname = frameStore.exceptCname; } @@ -742,10 +776,12 @@ const PageStore = class { // content script-side (i.e. `iframes` -- unlike `img`). if ( Array.isArray(resources) && resources.length !== 0 ) { for ( const resource of resources ) { - this.filterRequest( - fctxt.setType(resource.type) - .setURL(resource.url) + const result = this.filterRequest( + fctxt.setType(resource.type).setURL(resource.url) ); + if ( result === 1 && µb.redirectEngine.toURL(fctxt) ) { + this.forgetBlockedResource(fctxt); + } } } if ( this.netFilteringCache.hash === response.hash ) { return; } @@ -753,6 +789,11 @@ const PageStore = class { response.blockedResources = this.netFilteringCache.lookupAllBlocked(fctxt.getDocHostname()); } + + forgetBlockedResource(fctxt) { + if ( this.collapsibleResources.has(fctxt.type) === false ) { return; } + this.netFilteringCache.forgetResult(fctxt); + } }; PageStore.prototype.cacheableResults = new Set([ diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js index fa3f26db02dd2..71ac4b0aa7602 100644 --- a/src/js/redirect-engine.js +++ b/src/js/redirect-engine.js @@ -67,6 +67,10 @@ const redirectableResources = new Map([ [ 'chartbeat.js', { alias: 'static.chartbeat.com/chartbeat.js', } ], + [ 'click-to-load.html', { + alias: 'clicktoload', + params: [ 'url' ], + } ], [ 'doubleclick_instream_ad_status.js', { alias: 'doubleclick.net/instream/ad_status.js', } ], @@ -191,6 +195,7 @@ const RedirectEntry = class { this.mime = ''; this.data = ''; this.warURL = undefined; + this.params = undefined; } // Prevent redirection to web accessible resources when the request is @@ -208,7 +213,15 @@ const RedirectEntry = class { fctxt instanceof Object && fctxt.type !== 'xmlhttprequest' ) { - return `${this.warURL}${vAPI.warSecret()}`; + let url = `${this.warURL}${vAPI.warSecret()}`; + if ( this.params !== undefined ) { + for ( const name of this.params ) { + const value = fctxt[name]; + if ( value === undefined ) { continue; } + url += `&${name}=${encodeURIComponent(value)}`; + } + } + return url; } if ( this.data === undefined ) { return; } // https://github.com/uBlockOrigin/uBlock-issues/issues/701 @@ -251,6 +264,7 @@ const RedirectEntry = class { r.mime = selfie.mime; r.data = selfie.data; r.warURL = selfie.warURL; + r.params = selfie.params; return r; } }; @@ -721,6 +735,7 @@ RedirectEngine.prototype.loadBuiltinResources = function() { mime: mimeFromName(name), data, warURL: vAPI.getURL(`/web_accessible_resources/${name}`), + params: details.params, }); this.resources.set(name, entry); if ( details.alias !== undefined ) { diff --git a/src/js/traffic.js b/src/js/traffic.js index 7079c3efb2264..fb1a4071bbb13 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -101,7 +101,7 @@ const onBeforeRequest = function(details) { details.type === 'sub_frame' && details.aliasURL === undefined ) { - pageStore.setFrame(details.frameId, details.url); + pageStore.setFrameURL(details.frameId, details.url); } if ( result === 2 ) { return { cancel: false }; @@ -113,10 +113,13 @@ const onBeforeRequest = function(details) { // https://github.com/gorhill/uBlock/issues/949 // Redirect blocked request? + // https://github.com/gorhill/uBlock/issues/3619 + // Don't collapse redirected resources if ( µb.hiddenSettings.ignoreRedirectFilters !== true ) { const url = µb.redirectEngine.toURL(fctxt); if ( url !== undefined ) { pageStore.internalRedirectionCount += 1; + pageStore.forgetBlockedResource(fctxt); if ( µb.logger.enabled ) { fctxt.setRealm('redirect') .setFilter({ source: 'redirect', raw: µb.redirectEngine.resourceNameRegister }) diff --git a/src/web_accessible_resources/click-to-load.html b/src/web_accessible_resources/click-to-load.html new file mode 100644 index 0000000000000..f8cfa99b0983a --- /dev/null +++ b/src/web_accessible_resources/click-to-load.html @@ -0,0 +1,25 @@ + + + + + +uBlock Origin Click-to-Load + + + + + + + + +Click to load +
+ + + + + + + + + From f3012341e01f37036cc526fae9d5c329143ac7cc Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 9 Oct 2020 14:04:19 -0400 Subject: [PATCH 20/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index bfd5567b63219..c8838d6cf04b9 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.1 +1.30.3.2 From c54fb03414034399d9e0532018a250344e31bbc0 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 9 Oct 2020 14:10:33 -0400 Subject: [PATCH 21/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 7f89161e6132b..1d25b5b1d55fe 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.3.1", + "version": "1.30.3.2", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b1", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b1/uBlock0_1.30.3b1.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b2", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b2/uBlock0_1.30.3b2.firefox.signed.xpi" } ] } From 2e5d32e96798dd55f3fae66d7091645ff7ad3784 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 10 Oct 2020 08:36:30 -0400 Subject: [PATCH 22/73] Fine tune code related to click-to-load feature The redirectable resource has been renamed `click2load.html`, so as to avoid uses of dash characters and to also allow for future different click-to-load resources. --- src/_locales/en/messages.json | 4 ++ src/css/{click-to-load.css => click2load.css} | 0 src/js/{click-to-load.js => click2load.js} | 0 src/js/filtering-context.js | 3 + src/js/pagestore.js | 59 +++++++++++-------- src/js/redirect-engine.js | 3 +- src/js/traffic.js | 25 +++----- .../{click-to-load.html => click2load.html} | 4 +- 8 files changed, 52 insertions(+), 46 deletions(-) rename src/css/{click-to-load.css => click2load.css} (100%) rename src/js/{click-to-load.js => click2load.js} (100%) rename src/web_accessible_resources/{click-to-load.html => click2load.html} (84%) diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 79dea09037e3b..54170c36a381e 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message use in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/css/click-to-load.css b/src/css/click2load.css similarity index 100% rename from src/css/click-to-load.css rename to src/css/click2load.css diff --git a/src/js/click-to-load.js b/src/js/click2load.js similarity index 100% rename from src/js/click-to-load.js rename to src/js/click2load.js diff --git a/src/js/filtering-context.js b/src/js/filtering-context.js index 17f46b1226be3..cad4e16844ba6 100644 --- a/src/js/filtering-context.js +++ b/src/js/filtering-context.js @@ -44,6 +44,7 @@ this.tabOrigin = undefined; this.tabHostname = undefined; this.tabDomain = undefined; + this.redirectURL = undefined; this.filter = undefined; }; @@ -104,6 +105,7 @@ } else { this.setDocOrigin(this.tabOrigin); } + this.redirectURL = undefined; this.filter = undefined; return this; }, @@ -122,6 +124,7 @@ this.tabOrigin = other.tabOrigin; this.tabHostname = other.tabHostname; this.tabDomain = other.tabDomain; + this.redirectURL = other.redirectURL; this.filter = undefined; return this; }, diff --git a/src/js/pagestore.js b/src/js/pagestore.js index f5cd7dd9c1675..7301f992b16c8 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -54,18 +54,21 @@ const NetFilteringResultCache = class { return this; } + // https://github.com/gorhill/uBlock/issues/3619 + // Don't collapse redirected resources rememberResult(fctxt, result) { if ( fctxt.tabId <= 0 ) { return; } if ( this.results.size === 0 ) { this.pruneAsync(); } - const key = fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url; + const key = `${fctxt.getDocHostname()} ${fctxt.type} ${fctxt.url}`; this.results.set(key, { - result: result, + result, + redirectURL: fctxt.redirectURL, logData: fctxt.filter, tstamp: Date.now() }); - if ( result !== 1 ) { return; } + if ( result !== 1 || fctxt.redirectURL !== undefined ) { return; } const now = Date.now(); this.blocked.set(key, now); this.hash = now; @@ -76,16 +79,17 @@ const NetFilteringResultCache = class { if ( this.blocked.size === 0 ) { this.pruneAsync(); } + if ( fctxt.redirectURL !== undefined ) { return; } const now = Date.now(); this.blocked.set( - fctxt.getDocHostname() + ' ' + fctxt.type + ' ' + fctxt.url, + `${fctxt.getDocHostname()} ${fctxt.type} ${fctxt.url}`, now ); this.hash = now; } - forgetResult(fctxt) { - const key = `${fctxt.getDocHostname()} ${fctxt.type} ${fctxt.url}`; + forgetResult(docHostname, type, url) { + const key = `${docHostname} ${type} ${url}`; this.results.delete(key); this.blocked.delete(key); } @@ -171,7 +175,7 @@ const FrameStore = class { init(frameURL) { this.t0 = Date.now(); this.exceptCname = undefined; - this.clickToLoad = 0; + this.clickToLoad = false; this.rawURL = frameURL; if ( frameURL !== undefined ) { this.hostname = vAPI.hostnameFromURI(frameURL); @@ -559,6 +563,7 @@ const PageStore = class { if ( cacheableResult ) { const entry = this.netFilteringCache.lookupResult(fctxt); if ( entry !== undefined ) { + fctxt.redirectURL = entry.redirectURL; fctxt.filter = entry.logData; return entry.result; } @@ -607,11 +612,11 @@ const PageStore = class { } } - // Click-to-load: + // Click-to-load? // When frameId is not -1, the resource is always sub_frame. if ( result === 1 && fctxt.frameId !== -1 ) { - const docStore = this.getFrameStore(fctxt.frameId); - if ( docStore !== null && docStore.clickToLoad !== 0 ) { + const frameStore = this.getFrameStore(fctxt.frameId); + if ( frameStore !== null && frameStore.clickToLoad ) { result = 2; if ( µb.logger.enabled ) { fctxt.setFilter({ @@ -623,13 +628,20 @@ const PageStore = class { } } + // https://github.com/gorhill/uBlock/issues/949 + // Redirect blocked request? + if ( result === 1 && µb.hiddenSettings.ignoreRedirectFilters !== true ) { + const redirectURL = µb.redirectEngine.toURL(fctxt); + if ( redirectURL !== undefined ) { + fctxt.redirectURL = redirectURL; + this.internalRedirectionCount += 1; + } + } + if ( cacheableResult ) { this.netFilteringCache.rememberResult(fctxt, result); - } else if ( - result === 1 && - this.collapsibleResources.has(requestType) - ) { - this.netFilteringCache.rememberBlock(fctxt, true); + } else if ( result === 1 && this.collapsibleResources.has(requestType) ) { + this.netFilteringCache.rememberBlock(fctxt); } return result; @@ -727,7 +739,12 @@ const PageStore = class { if ( frameStore === null ) { frameStore = this.setFrameURL(frameId, frameURL); } - frameStore.clickToLoad = Date.now(); + this.netFilteringCache.forgetResult( + this.tabHostname, + 'sub_frame', + frameURL + ); + frameStore.clickToLoad = true; } shouldExceptCname(fctxt) { @@ -776,12 +793,9 @@ const PageStore = class { // content script-side (i.e. `iframes` -- unlike `img`). if ( Array.isArray(resources) && resources.length !== 0 ) { for ( const resource of resources ) { - const result = this.filterRequest( + this.filterRequest( fctxt.setType(resource.type).setURL(resource.url) ); - if ( result === 1 && µb.redirectEngine.toURL(fctxt) ) { - this.forgetBlockedResource(fctxt); - } } } if ( this.netFilteringCache.hash === response.hash ) { return; } @@ -789,11 +803,6 @@ const PageStore = class { response.blockedResources = this.netFilteringCache.lookupAllBlocked(fctxt.getDocHostname()); } - - forgetBlockedResource(fctxt) { - if ( this.collapsibleResources.has(fctxt.type) === false ) { return; } - this.netFilteringCache.forgetResult(fctxt); - } }; PageStore.prototype.cacheableResults = new Set([ diff --git a/src/js/redirect-engine.js b/src/js/redirect-engine.js index 71ac4b0aa7602..378183f6dd90d 100644 --- a/src/js/redirect-engine.js +++ b/src/js/redirect-engine.js @@ -67,8 +67,7 @@ const redirectableResources = new Map([ [ 'chartbeat.js', { alias: 'static.chartbeat.com/chartbeat.js', } ], - [ 'click-to-load.html', { - alias: 'clicktoload', + [ 'click2load.html', { params: [ 'url' ], } ], [ 'doubleclick_instream_ad_status.js', { diff --git a/src/js/traffic.js b/src/js/traffic.js index fb1a4071bbb13..481cd8916473e 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -111,25 +111,16 @@ const onBeforeRequest = function(details) { // Blocked - // https://github.com/gorhill/uBlock/issues/949 - // Redirect blocked request? - // https://github.com/gorhill/uBlock/issues/3619 - // Don't collapse redirected resources - if ( µb.hiddenSettings.ignoreRedirectFilters !== true ) { - const url = µb.redirectEngine.toURL(fctxt); - if ( url !== undefined ) { - pageStore.internalRedirectionCount += 1; - pageStore.forgetBlockedResource(fctxt); - if ( µb.logger.enabled ) { - fctxt.setRealm('redirect') - .setFilter({ source: 'redirect', raw: µb.redirectEngine.resourceNameRegister }) - .toLogger(); - } - return { redirectUrl: url }; - } + if ( fctxt.redirectURL === undefined ) { + return { cancel: true }; } - return { cancel: true }; + if ( µb.logger.enabled ) { + fctxt.setRealm('redirect') + .setFilter({ source: 'redirect', raw: µb.redirectEngine.resourceNameRegister }) + .toLogger(); + } + return { redirectUrl: fctxt.redirectURL }; }; /******************************************************************************/ diff --git a/src/web_accessible_resources/click-to-load.html b/src/web_accessible_resources/click2load.html similarity index 84% rename from src/web_accessible_resources/click-to-load.html rename to src/web_accessible_resources/click2load.html index f8cfa99b0983a..57c806869c774 100644 --- a/src/web_accessible_resources/click-to-load.html +++ b/src/web_accessible_resources/click2load.html @@ -6,7 +6,7 @@ uBlock Origin Click-to-Load - + @@ -19,7 +19,7 @@ - + From 9144fe9cbb0eba6790d138cbe243bae8af393cc5 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 10 Oct 2020 08:40:20 -0400 Subject: [PATCH 23/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index c8838d6cf04b9..9833ba923398e 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.2 +1.30.3.3 From 7b2a64db2b8815dba3c2d36ec12b31b6165def73 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 10 Oct 2020 08:45:28 -0400 Subject: [PATCH 24/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 1d25b5b1d55fe..3d2f3efdaacce 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.3.2", + "version": "1.30.3.3", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b2", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b2/uBlock0_1.30.3b2.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b3", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b3/uBlock0_1.30.3b3.firefox.signed.xpi" } ] } From 03596439caf28c09f11ff3a710637e90682ddae3 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 10 Oct 2020 14:18:19 -0400 Subject: [PATCH 25/73] Remove obsolete code to import content of localStorage Months ago, usage of synchronous localStorage was replaced with asynchronous extension storage. There was code for the conversion to be seamless by importing the content of now obsolete localStorage. This code is no longer needed as majority of users are assumed to use versions of uBO above 1.25.0. Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/899 --- platform/chromium/vapi-background.js | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 2f47248bba25c..569dd9e5af400 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -1435,27 +1435,10 @@ vAPI.localStorage = { if ( this.cache instanceof Promise ) { return this.cache; } if ( this.cache instanceof Object ) { return this.cache; } this.cache = webext.storage.local.get('localStorage').then(bin => { - this.cache = undefined; - try { - if ( - bin instanceof Object === false || - bin.localStorage instanceof Object === false - ) { - this.cache = {}; - const ls = self.localStorage; - for ( let i = 0; i < ls.length; i++ ) { - const key = ls.key(i); - this.cache[key] = ls.getItem(key); - } - webext.storage.local.set({ localStorage: this.cache }); - } else { - this.cache = bin.localStorage; - } - } catch(ex) { - } - if ( this.cache instanceof Object === false ) { - this.cache = {}; - } + this.cache = bin instanceof Object && + bin.localStorage instanceof Object + ? bin.localStorage + : {}; }); return this.cache; }, From 376ef4645fd2bb92b20240d8c7f2f45a8ec9100c Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 11 Oct 2020 07:45:16 -0400 Subject: [PATCH 26/73] Fine tune click-to-load visual --- src/css/click2load.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/css/click2load.css b/src/css/click2load.css index e6e4d77fdd41f..efd35aef3164c 100644 --- a/src/css/click2load.css +++ b/src/css/click2load.css @@ -25,7 +25,6 @@ body { box-sizing: border-box; display: flex; flex-direction: column; - justify-content: space-evenly; position: relative; } @@ -45,4 +44,5 @@ body { #clickToLoad { cursor: default; + margin-bottom: 1em; } From 6ff72af4aae9f7c53f7d478983d3667ee6da1dad Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 11 Oct 2020 07:45:58 -0400 Subject: [PATCH 27/73] Only URLs in comments can be selected through double-click --- src/js/codemirror/ubo-static-filtering.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js index 7f6299dfe1ca0..656aaa0c147f9 100644 --- a/src/js/codemirror/ubo-static-filtering.js +++ b/src/js/codemirror/ubo-static-filtering.js @@ -578,16 +578,24 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { return Pass; } } + const s = cm.getLine(line); + const token = cm.getTokenTypeAt(pos); + let lmatch, rmatch; + let select = false; - // Select URL - let lmatch = /\bhttps?:\/\/\S+$/.exec(s.slice(0, ch)); - let rmatch = /^\S+/.exec(s.slice(ch)); + // Select URL in comments + if ( token === 'comment link' ) { + lmatch = /\S+$/.exec(s.slice(0, ch)); + rmatch = /^\S+/.exec(s.slice(ch)); + select = lmatch !== null && rmatch !== null && + /^https?:\/\//.test(s.slice(lmatch.index)); + } // TODO: add more convenient word-matching cases here - // if ( lmatch === null || rmatch === null ) { ... } + // if ( select === false ) { ... } - if ( lmatch === null || rmatch === null ) { return Pass; } + if ( select === false ) { return Pass; } cm.setSelection( { line, ch: lmatch.index }, { line, ch: ch + rmatch.index + rmatch[0].length } From 1727585faa55715b8987b3f2afb34238aba902a3 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 11 Oct 2020 08:59:44 -0400 Subject: [PATCH 28/73] Hightlight to warn about unknown redirect tokens Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1134 --- src/js/codemirror/ubo-static-filtering.js | 68 +++++++++++++++++------ 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js index 656aaa0c147f9..1c268647a6b98 100644 --- a/src/js/codemirror/ubo-static-filtering.js +++ b/src/js/codemirror/ubo-static-filtering.js @@ -177,6 +177,56 @@ CodeMirror.defineMode('ubo-static-filtering', function() { return null; }; + const colorNetOptionValueSpan = function(stream, bits) { + const { pos, string } = stream; + let style; + // Warn about unknown redirect tokens. + if ( + string.charCodeAt(pos - 1) === 0x3D /* '=' */ && + /[$,]redirect(-rule)?=$/.test(string.slice(0, pos)) + ) { + style = 'value'; + let end = parser.skipUntil( + parserSlot, + parser.commentSpan.i, + parser.BITComma + ); + const token = parser.strFromSlices(parserSlot, end - 3); + if ( redirectNames.has(token) === false ) { + style += ' warning'; + } + stream.pos += token.length; + parserSlot = end; + return style; + } + if ( (bits & parser.BITTilde) !== 0 ) { + style = 'keyword strong'; + } else if ( (bits & parser.BITPipe) !== 0 ) { + style = 'def'; + } + stream.pos += parser.slices[parserSlot+2]; + parserSlot += 3; + return style || 'value'; + }; + + const colorNetOptionSpan = function(stream) { + const bits = parser.slices[parserSlot]; + let style; + if ( (bits & parser.BITComma) !== 0 ) { + style = 'def strong'; + netOptionValueMode = false; + } else if ( netOptionValueMode ) { + return colorNetOptionValueSpan(stream, bits); + } else if ( (bits & parser.BITTilde) !== 0 ) { + style = 'keyword strong'; + } else if ( (bits & parser.BITEqual) !== 0 ) { + netOptionValueMode = true; + } + stream.pos += parser.slices[parserSlot+2]; + parserSlot += 3; + return style || 'def'; + }; + const colorNetSpan = function(stream) { if ( parserSlot < parser.exceptionSpan.i ) { stream.pos += parser.slices[parserSlot+2]; @@ -236,23 +286,7 @@ CodeMirror.defineMode('ubo-static-filtering', function() { parserSlot >= parser.optionsSpan.i && parserSlot < parser.commentSpan.i ) { - const bits = parser.slices[parserSlot]; - let style; - if ( (bits & parser.BITComma) !== 0 ) { - style = 'def strong'; - netOptionValueMode = false; - } else if ( (bits & parser.BITTilde) !== 0 ) { - style = 'keyword strong'; - } else if ( (bits & parser.BITPipe) !== 0 ) { - style = 'def'; - } else if ( netOptionValueMode ) { - style = 'value'; - } else if ( (bits & parser.BITEqual) !== 0 ) { - netOptionValueMode = true; - } - stream.pos += parser.slices[parserSlot+2]; - parserSlot += 3; - return style || 'def'; + return colorNetOptionSpan(stream); } if ( parserSlot >= parser.commentSpan.i && From 80effe605484f8078e1cdb9b6f98715e809ffe1e Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 11 Oct 2020 09:07:19 -0400 Subject: [PATCH 29/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 9833ba923398e..a099b2b6ff34a 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.3 +1.30.3.4 From 422e3f676ff37325d6c7745127b99885748dbd4a Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 11 Oct 2020 09:16:14 -0400 Subject: [PATCH 30/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 3d2f3efdaacce..6ce6bc1c86f69 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.3.3", + "version": "1.30.3.4", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b3", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b3/uBlock0_1.30.3b3.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b4", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b4/uBlock0_1.30.3b4.firefox.signed.xpi" } ] } From 6e010ecc0f9471818733e40ee37cd69336faddeb Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 12 Oct 2020 10:08:51 -0400 Subject: [PATCH 31/73] Prevent set-constant properties from being overtaken Related feedback: - https://github.com/uBlockOrigin/uBlock-issues/issues/156#issuecomment-707095193 Additionally, while investigating the issue I removed code which is no longer needed since content scripts are now injected in `about:blank` frames since 1.29.0. --- assets/resources/scriptlets.js | 2 +- src/js/scriptlet-filtering.js | 64 ++-------------------------------- 2 files changed, 4 insertions(+), 62 deletions(-) diff --git a/assets/resources/scriptlets.js b/assets/resources/scriptlets.js index 9901d3f64a373..570e72cf45438 100644 --- a/assets/resources/scriptlets.js +++ b/assets/resources/scriptlets.js @@ -754,7 +754,7 @@ } } Object.defineProperty(owner, prop, { - configurable: true, + configurable: false, get() { if ( prevGetter !== undefined ) { prevGetter(); diff --git a/src/js/scriptlet-filtering.js b/src/js/scriptlet-filtering.js index 3317bef1d80dd..3edb53b423069 100644 --- a/src/js/scriptlet-filtering.js +++ b/src/js/scriptlet-filtering.js @@ -94,64 +94,6 @@ } }; injectScriptlets(document); - const processIFrame = function(iframe) { - const src = iframe.src; - if ( /^https?:\/\//.test(src) === false ) { - injectScriptlets(iframe.contentDocument); - } - }; - let observerTimer, - observerLists = []; - const observerAsync = function() { - for ( const nodelist of observerLists ) { - for ( const node of nodelist ) { - if ( node.nodeType !== 1 ) { continue; } - if ( node.parentElement === null ) { continue; } - if ( node.localName === 'iframe' ) { - processIFrame(node); - } - if ( node.childElementCount === 0 ) { continue; } - let iframes = node.querySelectorAll('iframe'); - for ( const iframe of iframes ) { - processIFrame(iframe); - } - } - } - observerLists = []; - observerTimer = undefined; - }; - const ready = function(ev) { - if ( ev !== undefined ) { - window.removeEventListener(ev.type, ready); - } - const iframes = document.getElementsByTagName('iframe'); - if ( iframes.length !== 0 ) { - observerLists.push(iframes); - observerTimer = setTimeout(observerAsync, 1); - } - const observer = new MutationObserver(function(mutations) { - for ( const mutation of mutations ) { - if ( mutation.addedNodes.length !== 0 ) { - observerLists.push(mutation.addedNodes); - } - } - if ( - observerLists.length !== 0 && - observerTimer === undefined - ) { - observerTimer = setTimeout(observerAsync, 1); - } - }); - observer.observe( - document.documentElement, - { childList: true, subtree: true } - ); - }; - if ( document.readyState === 'loading' ) { - window.addEventListener('DOMContentLoaded', ready); - } else { - ready(); - } }.toString(), ')(', '"', 'hostname-slot', '", ', @@ -457,10 +399,10 @@ code = 'debugger;\n' + code; } vAPI.tabs.executeScript(details.tabId, { - code: code, + code, frameId: details.frameId, - matchAboutBlank: false, - runAt: 'document_start' + matchAboutBlank: true, + runAt: 'document_start', }); }; From 6c7fb059e152cfd4150b155346878fa0bdd2700b Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 12 Oct 2020 10:42:10 -0400 Subject: [PATCH 32/73] Import translation work from https://crowdin.com/project/ublock --- dist/description/description-de.txt | 4 +-- src/_locales/ar/messages.json | 2 +- src/_locales/de/messages.json | 38 ++++++++++++++--------------- src/_locales/he/messages.json | 14 +++++------ 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/dist/description/description-de.txt b/dist/description/description-de.txt index 6ee8b523c1212..7d9fa2b478c5a 100644 --- a/dist/description/description-de.txt +++ b/dist/description/description-de.txt @@ -1,4 +1,4 @@ -Ein effizienter Blocker: Geringer Speicherbedarf und niedrige CPU-Belastung - und dennoch werden Tausende an Filtern mehr angewendet als bei anderen populären Blockern. +Ein effizienter Blocker: Geringer Speicherbedarf und niedrige CPU-Belastung - und dennoch werden tausende Filter mehr angewendet als bei anderen beliebten Blockern. Ein illustrierter Überblick über seine Effizienz: https://github.com/gorhill/uBlock/wiki/uBlock-vs.-ABP:-efficiency-compared @@ -30,7 +30,7 @@ Bedenke allerdings, dass durch die Wahl zusätzlicher Listen die Wahrscheinlichk - Wenn du etwas beitragen möchtest, dann denke an die Menschen, die hart dafür arbeiten, die von dir benutzten Filterlisten zu pflegen, und diese für uns alle frei verfügbar gemacht haben. + Wenn du etwas beitragen möchtest, dann denke an die Menschen, die hart dafür arbeiten, die von dir benutzten Filterlisten zu pflegen und diese für uns alle frei verfügbar gemacht haben. diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index 24d0b628de37e..acd598e9abc7b 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -648,7 +648,7 @@ "description": "Tooltip for the row filterer button in the logger page" }, "logFilterPrompt": { - "message": "فلتر سجل الإدخالات", + "message": "رشّح محتوى السجل", "description": "Placeholder string for logger output filtering input field" }, "loggerRowFiltererBuiltinTip": { diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json index dfd9ea11e0d99..b036750b962c8 100644 --- a/src/_locales/de/messages.json +++ b/src/_locales/de/messages.json @@ -12,7 +12,7 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Achtung! Du hast deine Änderungen nicht gespeichert", + "message": "Warnung! Nicht gespeicherte Änderungen", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { @@ -108,7 +108,7 @@ "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { - "message": "Klicken, um das Dashboard zu öffnen", + "message": "Klicken, um die Übersicht zu öffnen", "description": "English: Click to open the dashboard" }, "popupTipZapper": { @@ -116,7 +116,7 @@ "description": "Tooltip for the element-zapper icon in the popup panel" }, "popupTipPicker": { - "message": "Öffne den Element-Picker-Modus", + "message": "Element-Auswahl öffnen", "description": "English: Enter element picker mode" }, "popupTipLog": { @@ -124,27 +124,27 @@ "description": "Tooltip used for the logger icon in the panel" }, "popupTipNoPopups": { - "message": "Blockieren von Popups für diese Seite an-/ausschalten", + "message": "Pop-ups auf dieser Seite blockieren/zulassen", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { - "message": "Hier klicken, um alle Popups auf dieser Seite zu blockieren", + "message": "Hier klicken, um alle Popups auf dieser Website zu blockieren", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups2": { - "message": "Hier klicken, um Popups auf dieser Seite nicht mehr zu blockieren", + "message": "Hier klicken, um Popups auf dieser Website nicht mehr zu blockieren", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "Das Blockieren großer Medienelemente auf dieser Seite an-/ausschalten", + "message": "Große Medienelemente dieser Seite anzeigen/sperren", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { - "message": "Hier klicken, um große Medienelemente auf dieser Seite zu blockieren", + "message": "Hier klicken, um große Medienelemente auf dieser Website zu blockieren", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia2": { - "message": "Hier klicken, um große Medienelemente auf dieser Seite nicht mehr zu blockieren", + "message": "Hier klicken, um große Medienelemente auf dieser Website nicht mehr zu blockieren", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoCosmeticFiltering": { @@ -152,11 +152,11 @@ "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering1": { - "message": "Hier klicken, um Kosmetische Filter auf dieser Seite zu deaktivieren", + "message": "Hier klicken, um kosmetische Filter auf dieser Seite zu deaktivieren", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoCosmeticFiltering2": { - "message": "Hier klicken, um Kosmetische Filter auf dieser Seite zu aktivieren", + "message": "Hier klicken, um kosmetische Filter auf dieser Seite zu aktivieren", "description": "Tooltip for the no-cosmetic-filtering per-site switch" }, "popupTipNoRemoteFonts": { @@ -300,7 +300,7 @@ "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { - "message": "Verstecke die Platzhalter für blockierte Elemente", + "message": "Platzhalter für blockierte Elemente ausblenden", "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { @@ -396,7 +396,7 @@ "description": "A button in the in the _3rd-party filters_ pane" }, "3pPurgeAll": { - "message": "Leere alle Cache-Speicher", + "message": "Alle Cache-Speicher leeren", "description": "A button in the in the _3rd-party filters_ pane" }, "3pParseAllABPHideFiltersPrompt1": { @@ -496,7 +496,7 @@ "description": "English: Export" }, "1pExportFilename": { - "message": "my-ublock-custom-filters_{{datetime}}.txt", + "message": "ublock-statische-filter_{{datetime}}.txt", "description": "English: my-ublock-static-filters_{{datetime}}.txt" }, "1pApplyChanges": { @@ -736,11 +736,11 @@ "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartBlock": { - "message": "Blockiere", + "message": "Blockieren", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartAllow": { - "message": "Erlaube", + "message": "Erlauben", "description": "Used in the static filtering wizard" }, "loggerStaticFilteringSentencePartType": { @@ -876,7 +876,7 @@ "description": "Text for button to create a backup of all settings" }, "aboutBackupFilename": { - "message": "my-ublock-backup_{{datetime}}.txt", + "message": "ublock-sicherung_{{datetime}}.txt", "description": "English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton": { @@ -888,7 +888,7 @@ "description": "English: Reset to default settings..." }, "aboutRestoreDataConfirm": { - "message": "Alle Einstellungen werden überschrieben und auf den Stand von {{time}} gebracht. Anschließend wird uBlock neu gestartet.\n\nSollen die aktuellen Einstellungen durch das Backup ersetzt werden?", + "message": "Alle Einstellungen werden überschrieben und auf den Stand von {{time}} gebracht. Anschließend wird uBlock neu gestartet.\n\nSollen die aktuellen Einstellungen durch die Sicherung ersetzt werden?", "description": "Message asking user to confirm restore" }, "aboutRestoreDataError": { @@ -968,7 +968,7 @@ "description": "English: Go back" }, "docblockedClose": { - "message": "Schließe dieses Fenster", + "message": "Dieses Fenster schließen", "description": "English: Close this window" }, "docblockedProceed": { diff --git a/src/_locales/he/messages.json b/src/_locales/he/messages.json index 66548b3eb3e93..da30c8039b7e7 100644 --- a/src/_locales/he/messages.json +++ b/src/_locales/he/messages.json @@ -40,7 +40,7 @@ "description": "appears as tab name in dashboard" }, "whitelistPageName": { - "message": "רשימה לבנה", + "message": "אתרים מהימנים", "description": "appears as tab name in dashboard" }, "shortcutsPageName": { @@ -484,7 +484,7 @@ "description": "used as a tooltip for error icon beside a list" }, "1pFormatHint": { - "message": "מסנן אחד לשורה. המסנן יכול להיות שם מארח פשוט, או מסנן תואם EasyList. שורות עם קידומת ! ייתקלו בהתעלמות.", + "message": "מסנן אחד לכל שורה. המסנן יכול להיות דומיין פשוט, או מסנן התואם ל- EasyList. שורות עם קידומת ! לא יפורשו.", "description": "Short information about how to create custom filters" }, "1pImport": { @@ -552,11 +552,11 @@ "description": "English: dynamic rule syntax and full documentation." }, "rulesSort": { - "message": "מיון:", + "message": "מיין לפי:", "description": "English: label for sort option." }, "rulesSortByType": { - "message": "סוג כלל", + "message": "סוג הרשומה", "description": "English: a sort option for list of rules." }, "rulesSortBySource": { @@ -568,7 +568,7 @@ "description": "English: a sort option for list of rules." }, "whitelistPrompt": { - "message": "הכוונות האתר המהימן מכתיבות באילו דפי רשת uBlock Origin צריך להיות מושבת. כניסה אחת לשורה. הכוונות בלתי תקפות ייתקלו בהתעלמות בשקט ויקבלו הערה.", + "message": "הרשומות באתרים המהימנים מציינות באילו דפי אינטרנט uBlock Origin לא יהיה פעיל. רשומה אחת בכל שורה. רשומות לא חוקיות תתעלמנה בשקט ויסומנו כהערות.", "description": "The name of the trusted sites pane." }, "whitelistImport": { @@ -580,7 +580,7 @@ "description": "English: Export" }, "whitelistExportFilename": { - "message": "my-ublock-whitelist_{{datetime}}.txt", + "message": "my-ublock-trusted-sites_{{datetime}}.txt", "description": "The default filename to use for import/export purpose" }, "whitelistApply": { @@ -904,7 +904,7 @@ "description": "English: Network error: {{msg}}" }, "subscriberConfirm": { - "message": "uBlock₀: הוסף את הכתובת הבאה לרשימת הפילטרים המותאמים אישית שלך?\n\nכותרת: \"{{title}}\"\nכתובת URL: {{url}}", + "message": "הוסף את הכתובת הבאה לרשימת הפילטרים המותאמים אישית שלך?\n\nכותרת: \"{{title}}\"\nכתובת URL: {{url}}", "description": "No longer used" }, "subscribeButton": { From 8a50bfcedfa9def6b4d4308a835bd3548529fcdc Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 12 Oct 2020 10:43:17 -0400 Subject: [PATCH 33/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index a099b2b6ff34a..6e6c75b96c20c 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.4 +1.30.3.5 From b38f7b9899e33ae6ee84ad852a68a515d739a78d Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 12 Oct 2020 10:50:41 -0400 Subject: [PATCH 34/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 6ce6bc1c86f69..ad659cfd067fd 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.3.4", + "version": "1.30.3.5", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b4", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b4/uBlock0_1.30.3b4.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b5", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b5/uBlock0_1.30.3b5.firefox.signed.xpi" } ] } From a08f33e09db55438a8cef1cb333eaeb511645db1 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 12 Oct 2020 11:00:30 -0400 Subject: [PATCH 35/73] Prevent only target (leaf) property from being overtaken Related discussion: - https://github.com/uBlockOrigin/uBlock-issues/issues/156#issuecomment-707095193 Related commit: - https://github.com/gorhill/uBlock/commit/6e010ecc0f9471818733e40ee37cd69336faddeb --- assets/resources/scriptlets.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/resources/scriptlets.js b/assets/resources/scriptlets.js index 570e72cf45438..78ae17cd7e20f 100644 --- a/assets/resources/scriptlets.js +++ b/assets/resources/scriptlets.js @@ -741,7 +741,7 @@ }; // https://github.com/uBlockOrigin/uBlock-issues/issues/156 // Support multiple trappers for the same property. - const trapProp = function(owner, prop, handler) { + const trapProp = function(owner, prop, configurable, handler) { if ( handler.init(owner[prop]) === false ) { return; } const odesc = Object.getOwnPropertyDescriptor(owner, prop); let prevGetter, prevSetter; @@ -754,7 +754,7 @@ } } Object.defineProperty(owner, prop, { - configurable: false, + configurable, get() { if ( prevGetter !== undefined ) { prevGetter(); @@ -772,7 +772,7 @@ const trapChain = function(owner, chain) { const pos = chain.indexOf('.'); if ( pos === -1 ) { - trapProp(owner, chain, { + trapProp(owner, chain, false, { v: undefined, init: function(v) { if ( mustAbort(v) ) { return false; } @@ -798,7 +798,7 @@ trapChain(v, chain); return; } - trapProp(owner, prop, { + trapProp(owner, prop, true, { v: undefined, init: function(v) { this.v = v; From 5c18133369e09d0ddfce1c54a5fb9d180ee0c2dd Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 12 Oct 2020 11:02:23 -0400 Subject: [PATCH 36/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 6e6c75b96c20c..57a049a855eb9 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.5 +1.30.3.6 From a42c49d855a24ad01ab1d4e405025e735bc20985 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Mon, 12 Oct 2020 12:21:02 -0400 Subject: [PATCH 37/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index ad659cfd067fd..6ddf890335790 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.3.5", + "version": "1.30.3.6", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b5", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b5/uBlock0_1.30.3b5.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b6", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b6/uBlock0_1.30.3b6.firefox.signed.xpi" } ] } From 3da97673d9a34940a582560f376fc7b1a4265f9c Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 07:19:06 -0400 Subject: [PATCH 38/73] Remove more remnants of obsolete pseudo user styles code Related commit: - https://github.com/gorhill/uBlock/commit/5c68867b92735931a791dfedf4ef9608cc364862 --- src/js/contentscript.js | 53 +++++++----------------------------- src/js/scriptlets/epicker.js | 3 +- 2 files changed, 12 insertions(+), 44 deletions(-) diff --git a/src/js/contentscript.js b/src/js/contentscript.js index b80431879ee78..f3226a72d1797 100644 --- a/src/js/contentscript.js +++ b/src/js/contentscript.js @@ -851,7 +851,7 @@ vAPI.injectScriptlet = function(doc, text) { this.domFilterer.addCSSRule( `[${this.masterToken}][${styleToken}]`, style, - { silent: true } + { silent: true, mustInject: true } ); return styleToken; } @@ -908,7 +908,6 @@ vAPI.injectScriptlet = function(doc, text) { this.disabled = false; this.listeners = []; this.filterset = new Set(); - this.addedCSSRules = new Set(); this.exceptedCSSRules = []; this.exceptions = []; this.proceduralFilterer = null; @@ -929,22 +928,11 @@ vAPI.injectScriptlet = function(doc, text) { addCSSRule(selectors, declarations, details = {}) { if ( selectors === undefined ) { return; } const selectorsStr = Array.isArray(selectors) - ? selectors.join(',\n') - : selectors; + ? selectors.join(',\n') + : selectors; if ( selectorsStr.length === 0 ) { return; } - const entry = { - selectors: selectorsStr, - declarations, - lazy: details.lazy === true, - injected: details.injected === true - }; - this.addedCSSRules.add(entry); - this.filterset.add(entry); - if ( - this.disabled === false && - entry.lazy !== true && - entry.injected !== true - ) { + this.filterset.add({ selectors: selectorsStr, declarations }); + if ( details.mustInject && this.disabled === false ) { vAPI.userStylesheet.add(`${selectorsStr}\n{${declarations}}`); } this.commit(); @@ -1012,20 +1000,7 @@ vAPI.injectScriptlet = function(doc, text) { commitNow() { this.commitTimer.clear(); if ( vAPI instanceof Object === false ) { return; } - const userStylesheet = vAPI.userStylesheet; - for ( const entry of this.addedCSSRules ) { - if ( - this.disabled === false && - entry.lazy && - entry.injected === false - ) { - userStylesheet.add( - `${entry.selectors}\n{${entry.declarations}}` - ); - } - } - this.addedCSSRules.clear(); - userStylesheet.apply(); + vAPI.userStylesheet.apply(); if ( this.proceduralFilterer instanceof Object ) { this.proceduralFilterer.commitNow(); } @@ -1059,11 +1034,11 @@ vAPI.injectScriptlet = function(doc, text) { o.action[0] === ':style' && o.tasks === undefined ) { - this.addCSSRule(o.selector, o.action[1]); + this.addCSSRule(o.selector, o.action[1], { mustInject: true }); continue; } if ( o.pseudo !== undefined ) { - this.addCSSRule(o.selector, vAPI.hideStyle); + this.addCSSRule(o.selector, vAPI.hideStyle, { mustInject: true }); continue; } procedurals.push(o); @@ -1550,11 +1525,7 @@ vAPI.injectScriptlet = function(doc, text) { if ( result ) { let selectors = result.injected; if ( typeof selectors === 'string' && selectors.length !== 0 ) { - domFilterer.addCSSRule( - selectors, - vAPI.hideStyle, - { injected: true } - ); + domFilterer.addCSSRule(selectors, vAPI.hideStyle); mustCommit = true; } selectors = result.excepted; @@ -1722,11 +1693,7 @@ vAPI.injectScriptlet = function(doc, text) { vAPI.domSurveyor = null; } domFilterer.exceptions = cfeDetails.exceptionFilters; - domFilterer.addCSSRule( - cfeDetails.injectedHideFilters, - vAPI.hideStyle, - { injected: true } - ); + domFilterer.addCSSRule(cfeDetails.injectedHideFilters, vAPI.hideStyle); domFilterer.addProceduralSelectors(cfeDetails.proceduralFilters); domFilterer.exceptCSSRules(cfeDetails.exceptedFilters); } diff --git a/src/js/scriptlets/epicker.js b/src/js/scriptlets/epicker.js index c249de68c688c..2b4b98d98e264 100644 --- a/src/js/scriptlets/epicker.js +++ b/src/js/scriptlets/epicker.js @@ -805,7 +805,8 @@ const filterToDOMInterface = (( ) => { if ( cssSelectors.size !== 0 ) { vAPI.domFilterer.addCSSRule( Array.from(cssSelectors), - vAPI.hideStyle + vAPI.hideStyle, + { mustInject: true } ); } if ( proceduralSelectors.size !== 0 ) { From a211f5ef50085f0c80740ee7f052a1ebcac80896 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 07:30:24 -0400 Subject: [PATCH 39/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 57a049a855eb9..51bc16f2d88cc 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.6 +1.30.3.7 From 0082ac5069a4f921087aa556d39c6ae074295c11 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 08:20:56 -0400 Subject: [PATCH 40/73] Import translation work from https://crowdin.com/project/ublock --- src/_locales/ar/messages.json | 4 +++ src/_locales/az/messages.json | 48 +++++++++++++++++--------------- src/_locales/bg/messages.json | 4 +++ src/_locales/bn/messages.json | 4 +++ src/_locales/bs/messages.json | 4 +++ src/_locales/ca/messages.json | 4 +++ src/_locales/cs/messages.json | 4 +++ src/_locales/cv/messages.json | 4 +++ src/_locales/da/messages.json | 4 +++ src/_locales/de/messages.json | 4 +++ src/_locales/el/messages.json | 4 +++ src/_locales/en/messages.json | 2 +- src/_locales/en_GB/messages.json | 4 +++ src/_locales/eo/messages.json | 4 +++ src/_locales/es/messages.json | 4 +++ src/_locales/et/messages.json | 4 +++ src/_locales/eu/messages.json | 4 +++ src/_locales/fa/messages.json | 4 +++ src/_locales/fi/messages.json | 4 +++ src/_locales/fil/messages.json | 4 +++ src/_locales/fr/messages.json | 4 +++ src/_locales/fy/messages.json | 4 +++ src/_locales/gl/messages.json | 4 +++ src/_locales/he/messages.json | 4 +++ src/_locales/hi/messages.json | 4 +++ src/_locales/hr/messages.json | 4 +++ src/_locales/hu/messages.json | 4 +++ src/_locales/hy/messages.json | 4 +++ src/_locales/id/messages.json | 4 +++ src/_locales/it/messages.json | 4 +++ src/_locales/ja/messages.json | 4 +++ src/_locales/ka/messages.json | 4 +++ src/_locales/kk/messages.json | 4 +++ src/_locales/kn/messages.json | 4 +++ src/_locales/ko/messages.json | 4 +++ src/_locales/lt/messages.json | 4 +++ src/_locales/lv/messages.json | 4 +++ src/_locales/ml/messages.json | 4 +++ src/_locales/mr/messages.json | 4 +++ src/_locales/ms/messages.json | 4 +++ src/_locales/nb/messages.json | 4 +++ src/_locales/nl/messages.json | 8 ++++-- src/_locales/oc/messages.json | 4 +++ src/_locales/pl/messages.json | 4 +++ src/_locales/pt_BR/messages.json | 4 +++ src/_locales/pt_PT/messages.json | 4 +++ src/_locales/ro/messages.json | 4 +++ src/_locales/ru/messages.json | 4 +++ src/_locales/sk/messages.json | 4 +++ src/_locales/sl/messages.json | 4 +++ src/_locales/sq/messages.json | 14 ++++++---- src/_locales/sr/messages.json | 4 +++ src/_locales/sv/messages.json | 4 +++ src/_locales/ta/messages.json | 4 +++ src/_locales/te/messages.json | 4 +++ src/_locales/th/messages.json | 8 ++++-- src/_locales/tr/messages.json | 4 +++ src/_locales/uk/messages.json | 4 +++ src/_locales/ur/messages.json | 4 +++ src/_locales/vi/messages.json | 4 +++ src/_locales/zh_CN/messages.json | 4 +++ src/_locales/zh_TW/messages.json | 4 +++ 62 files changed, 276 insertions(+), 32 deletions(-) diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index acd598e9abc7b..581d8ab2bff11 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -1063,6 +1063,10 @@ "message": "جيغا بايت", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "يجب أن يكون هذا الإدخال آخر واحد", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/az/messages.json b/src/_locales/az/messages.json index 938b5c5b69a6e..80e133dad9b38 100644 --- a/src/_locales/az/messages.json +++ b/src/_locales/az/messages.json @@ -12,7 +12,7 @@ "description": "English: uBlock₀ — Dashboard" }, "dashboardUnsavedWarning": { - "message": "Diqqət! Yadda saxlamadığınız dəyişikliklər var", + "message": "Xəbərdarlıq! Saxlamadığınız dəyişikliklər var", "description": "A warning in the dashboard when navigating away from unsaved changes" }, "dashboardUnsavedWarningStay": { @@ -20,7 +20,7 @@ "description": "Label for button to prevent navigating away from unsaved changes" }, "dashboardUnsavedWarningIgnore": { - "message": "Nəzərə alma", + "message": "Əhəmiyyət vermə", "description": "Label for button to ignore unsaved changes" }, "settingsPageName": { @@ -40,7 +40,7 @@ "description": "appears as tab name in dashboard" }, "whitelistPageName": { - "message": "İstisnalar", + "message": "Etibarlı saytlar", "description": "appears as tab name in dashboard" }, "shortcutsPageName": { @@ -48,7 +48,7 @@ "description": "appears as tab name in dashboard" }, "statsPageName": { - "message": "uBlock₀ — Qeydiyyatçı", + "message": "uBlock₀ — Jurnal", "description": "Title for the logger window" }, "aboutPageName": { @@ -60,19 +60,19 @@ "description": "Title for the asset viewer page" }, "advancedSettingsPageName": { - "message": "Əlavə parametrlər", + "message": "Qabaqcıl tənzimləmələr", "description": "Title for the advanced settings page" }, "popupPowerSwitchInfo": { - "message": "Klik: Bu saytda uBlock₀-u işə sal/dayandır.\n\nCtrl+klik: Yalnız bu səhifədə uBlock₀-u dayandır.", + "message": "Klikləmə: Bu sayt üçün uBlock₀-u fəallaşdır/sıradan çıxart.\n\nCtrl+klikləmə: Yalnız bu səhifə üçün uBlock₀-u sıradan çıxart.", "description": "English: Click: disable/enable uBlock₀ for this site.\n\nCtrl+click: disable uBlock₀ only on this page." }, "popupPowerSwitchInfo1": { - "message": "Bu saytda uBlock₀-u dayandırmaq üçün düyməyə basın.\n\nYalnız bu səhifədə uBlock₀-u dayandırmaq üçün Ctrl və düyməyə basın.", + "message": "Bu sayt üçün uBlock₀-u sıradan çıxartmaq üçün klikləyin.\n\nYalnız bu səhifə üçün uBlock₀-u sıradan çıxartmaq üçün Ctrl+klikləyin.", "description": "Message to be read by screen readers" }, "popupPowerSwitchInfo2": { - "message": "Bu saytda uBlock₀-u işə salmaq üçün düyməyə basın.", + "message": "Bu saytda uBlock₀-u fəallaşdırmaq üçün klikləyin.", "description": "Message to be read by screen readers" }, "popupBlockedRequestPrompt": { @@ -92,7 +92,7 @@ "description": "English: since install" }, "popupOr": { - "message": "yaxud", + "message": "və ya", "description": "English: or" }, "popupBlockedOnThisPage_v2": { @@ -104,7 +104,7 @@ "description": "For the new mobile-friendly popup design" }, "popupDomainsConnected_v2": { - "message": "Qoşulmuş domenlər", + "message": "Bağlantı qurulmuş domenlər", "description": "For the new mobile-friendly popup design" }, "popupTipDashboard": { @@ -120,23 +120,23 @@ "description": "English: Enter element picker mode" }, "popupTipLog": { - "message": "Loggeri aç", + "message": "Jurnalı aç", "description": "Tooltip used for the logger icon in the panel" }, "popupTipNoPopups": { - "message": "Bu saytda peyda olan bütün pəncərələrin əngəllənməsini işə sal/dayandır", + "message": "Bu sayt üçün bütün açılan pəncələri aç/bağla", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups1": { - "message": "Bu saytda peyda olan bütün pəncərələri əngəlləmək üçün düyməyə basın", + "message": "Bu saytda bütün açılan pəncərələri əngəlləmək üçün kliklə", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoPopups2": { - "message": "Bu saytda peyda olan bütün pəncərələri daha əngəlləməmək üçün düyməyə basın", + "message": "Bu saytdakı bütün açılan pəncələri artıq əngəlləməmək üçün kliklə", "description": "Tooltip for the no-popups per-site switch" }, "popupTipNoLargeMedia": { - "message": "Bu saytda böyük media elemetlərinin əngəllənməsini işə sal/dayandır", + "message": "Bu saytda böyük media elemetlərini əngəlləməyi aç/bağla", "description": "Tooltip for the no-large-media per-site switch" }, "popupTipNoLargeMedia1": { @@ -172,7 +172,7 @@ "description": "Tooltip for the no-remote-fonts per-site switch" }, "popupTipNoScripting1": { - "message": "Bu saytda JavaScript-i əngəlləmək üçün düyməyə basın", + "message": "Bu saytda JavaScript-i sıradan çıxartmaq üçün kliklə", "description": "Tooltip for the no-scripting per-site switch" }, "popupTipNoScripting2": { @@ -216,7 +216,7 @@ "description": "Tooltip when hovering the top-most cell of the local-rules column." }, "popupTipSaveRules": { - "message": "Dəyişiklikləri daimi etmək üçün düyməyə basın.", + "message": "Dəyişiklikləri daimi etmək üçün klikləyin.", "description": "Tooltip when hovering over the padlock in the dynamic filtering pane." }, "popupTipRevertRules": { @@ -908,7 +908,7 @@ "description": "No longer used" }, "subscribeButton": { - "message": "Subscribe", + "message": "Abunə ol", "description": "For the button used to subscribe to a filter list" }, "elapsedOneMinuteAgo": { @@ -1036,19 +1036,19 @@ "description": "Tooltip for the button used to lock scrolling between the views in the 'My rules' pane" }, "genericCopyToClipboard": { - "message": "Mübadilə buferinə kopyala", + "message": "Lövhəyə kopyala", "description": "Label for buttons used to copy something to the clipboard" }, "toggleBlockingProfile": { - "message": "Əngəlləmə profilini işə sal/söndür", + "message": "Əngəlləmə profilini aç/bağla", "description": "Label for keyboard shortcut used to toggle blocking profile" }, "relaxBlockingMode": { - "message": "Zəif əngəlləmə rejimi", + "message": "Əngəlləmə rejimini yüngülləşdir", "description": "Label for keyboard shortcut used to relax blocking mode (meant to replace 'Toggle blocking profile')" }, "storageUsed": { - "message": "İstifadə olunan yer: {{value}} {{unit}}", + "message": "İstifadə olunan anbar: {{value}} {{unit}}", "description": " In Setting pane, renders as (example): Storage used: 13.2 MB" }, "KB": { @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Yükləmək üçün kliklə", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/bg/messages.json b/src/_locales/bg/messages.json index 5c23ff52aad07..1fed8a8c9821e 100644 --- a/src/_locales/bg/messages.json +++ b/src/_locales/bg/messages.json @@ -1063,6 +1063,10 @@ "message": "ГБ", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Щракнете, за да се зареди", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Това поле трябва да бъде последното", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/bn/messages.json b/src/_locales/bn/messages.json index da56838043d5f..490b95b65d846 100644 --- a/src/_locales/bn/messages.json +++ b/src/_locales/bn/messages.json @@ -1063,6 +1063,10 @@ "message": "গিগাবাইট", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/bs/messages.json b/src/_locales/bs/messages.json index 5b66addba637b..cad18c0ca00e9 100644 --- a/src/_locales/bs/messages.json +++ b/src/_locales/bs/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ca/messages.json b/src/_locales/ca/messages.json index 600ec6ef5ae46..9c8b4efe4a6e9 100644 --- a/src/_locales/ca/messages.json +++ b/src/_locales/ca/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Clic per carregar", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Aquesta entrada ha de ser l'última", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/cs/messages.json b/src/_locales/cs/messages.json index b592077527daf..4786dfe88ae2e 100644 --- a/src/_locales/cs/messages.json +++ b/src/_locales/cs/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/cv/messages.json b/src/_locales/cv/messages.json index 4442361046cc7..f0d7290c834d8 100644 --- a/src/_locales/cv/messages.json +++ b/src/_locales/cv/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Ку ҫыру юлашки пулмалла", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/da/messages.json b/src/_locales/da/messages.json index 61d3b45659dab..5635fca2afe56 100644 --- a/src/_locales/da/messages.json +++ b/src/_locales/da/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Klik for at indlæse", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Denne post skal være den sidste", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json index b036750b962c8..599787bd2d2c9 100644 --- a/src/_locales/de/messages.json +++ b/src/_locales/de/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Zum Laden anklicken", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Dieser Eintrag muss der letzte sein", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/el/messages.json b/src/_locales/el/messages.json index b6513ada30b7b..1cdf04f0f27e0 100644 --- a/src/_locales/el/messages.json +++ b/src/_locales/el/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Αυτή η καταχώρηση θα πρέπει να είναι τελευταία", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 54170c36a381e..865de36685684 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -1065,7 +1065,7 @@ }, "clickToLoad": { "message": "Click to load", - "description": "Message use in frame placeholders" + "description": "Message used in frame placeholders" }, "dummy": { "message": "This entry must be the last one", diff --git a/src/_locales/en_GB/messages.json b/src/_locales/en_GB/messages.json index 3c4f5e0e21a25..a2ca0978d7985 100644 --- a/src/_locales/en_GB/messages.json +++ b/src/_locales/en_GB/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/eo/messages.json b/src/_locales/eo/messages.json index 989b20aa9ad76..9780aa1d4ce61 100644 --- a/src/_locales/eo/messages.json +++ b/src/_locales/eo/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/es/messages.json b/src/_locales/es/messages.json index 49f4cdf9230de..aa7acdb2dc8ff 100644 --- a/src/_locales/es/messages.json +++ b/src/_locales/es/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Clic para cargar", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Esta entrada debe ser la última", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/et/messages.json b/src/_locales/et/messages.json index 863272cbc2bb7..1b6c814b30444 100644 --- a/src/_locales/et/messages.json +++ b/src/_locales/et/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Klõpsa laadimiseks", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "See sisestus peab olema viimane", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/eu/messages.json b/src/_locales/eu/messages.json index 2423dae3120cf..5a35dd475e123 100644 --- a/src/_locales/eu/messages.json +++ b/src/_locales/eu/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/fa/messages.json b/src/_locales/fa/messages.json index f6d5c26c9e7b4..28554c287f85b 100644 --- a/src/_locales/fa/messages.json +++ b/src/_locales/fa/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "این باید آخرین مطلب باشد", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/fi/messages.json b/src/_locales/fi/messages.json index 2eca76c6a9c47..c237a6cf5980e 100644 --- a/src/_locales/fi/messages.json +++ b/src/_locales/fi/messages.json @@ -1063,6 +1063,10 @@ "message": "Gt", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/fil/messages.json b/src/_locales/fil/messages.json index 97394462347fb..98d1458254adb 100644 --- a/src/_locales/fil/messages.json +++ b/src/_locales/fil/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/fr/messages.json b/src/_locales/fr/messages.json index 82352c4d641cf..7c4be2fe2d235 100644 --- a/src/_locales/fr/messages.json +++ b/src/_locales/fr/messages.json @@ -1063,6 +1063,10 @@ "message": "Go", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Cliquez pour charger", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/fy/messages.json b/src/_locales/fy/messages.json index 37a04e2c36096..43308013c5cff 100644 --- a/src/_locales/fy/messages.json +++ b/src/_locales/fy/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/gl/messages.json b/src/_locales/gl/messages.json index f36de8d58edbf..efeb6d684d75a 100644 --- a/src/_locales/gl/messages.json +++ b/src/_locales/gl/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Esta ten que ser a derradeira entrada", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/he/messages.json b/src/_locales/he/messages.json index da30c8039b7e7..7a113e593cc18 100644 --- a/src/_locales/he/messages.json +++ b/src/_locales/he/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "ערך זה חייב להיות האחרון", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/hi/messages.json b/src/_locales/hi/messages.json index d4a0fbd220f31..510354b7945ab 100644 --- a/src/_locales/hi/messages.json +++ b/src/_locales/hi/messages.json @@ -1063,6 +1063,10 @@ "message": "जीबी", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/hr/messages.json b/src/_locales/hr/messages.json index 677247c7bf0c0..6c4ad4c53807e 100644 --- a/src/_locales/hr/messages.json +++ b/src/_locales/hr/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Kliknite za pokretanje", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Ova stavka mora biti posljednja", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/hu/messages.json b/src/_locales/hu/messages.json index f2ea627b63d76..2f64c25b86d78 100644 --- a/src/_locales/hu/messages.json +++ b/src/_locales/hu/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Kattints a betöltéshez", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Ez a bejegyzés utolsó kell hogy legyen", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/hy/messages.json b/src/_locales/hy/messages.json index 3a1ed2dd6c010..29b343099c412 100644 --- a/src/_locales/hy/messages.json +++ b/src/_locales/hy/messages.json @@ -1063,6 +1063,10 @@ "message": "ԳԲ", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/id/messages.json b/src/_locales/id/messages.json index 530ea678b1a1f..c7560e3082f14 100644 --- a/src/_locales/id/messages.json +++ b/src/_locales/id/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Klik untuk memuat", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Entri ini harus menjadi yang terakhir", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/it/messages.json b/src/_locales/it/messages.json index bb331cb56cae6..6ae363ba1756d 100644 --- a/src/_locales/it/messages.json +++ b/src/_locales/it/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Clicca per caricare", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ja/messages.json b/src/_locales/ja/messages.json index f10ef7998d7e2..b50a06062b1b5 100644 --- a/src/_locales/ja/messages.json +++ b/src/_locales/ja/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "クリックで、ロードする", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "これは最後のエントリである必要があります", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ka/messages.json b/src/_locales/ka/messages.json index c39d4f879d941..26558c4df7562 100644 --- a/src/_locales/ka/messages.json +++ b/src/_locales/ka/messages.json @@ -1063,6 +1063,10 @@ "message": "გბ", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "დაწკაპეთ ჩასატვირთად", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/kk/messages.json b/src/_locales/kk/messages.json index 2b9a4f2af7201..daac564c00a9b 100644 --- a/src/_locales/kk/messages.json +++ b/src/_locales/kk/messages.json @@ -1063,6 +1063,10 @@ "message": "ГБ", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/kn/messages.json b/src/_locales/kn/messages.json index 9f5f4c9ab0ed6..0ad5d21aa349f 100644 --- a/src/_locales/kn/messages.json +++ b/src/_locales/kn/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ko/messages.json b/src/_locales/ko/messages.json index c7202fc91ff8d..49242dda14145 100644 --- a/src/_locales/ko/messages.json +++ b/src/_locales/ko/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/lt/messages.json b/src/_locales/lt/messages.json index a5b2859d76b47..3638e32ef1da6 100644 --- a/src/_locales/lt/messages.json +++ b/src/_locales/lt/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/lv/messages.json b/src/_locales/lv/messages.json index e324b7d7e55c9..3bd731d83f011 100644 --- a/src/_locales/lv/messages.json +++ b/src/_locales/lv/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Šim ierakstam ir jābūt pēdējam", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ml/messages.json b/src/_locales/ml/messages.json index 0ea53ebf21dad..b2c9a941481fd 100644 --- a/src/_locales/ml/messages.json +++ b/src/_locales/ml/messages.json @@ -1063,6 +1063,10 @@ "message": "ജി.ബി.", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "ലോഡുചെയ്യാൻ ക്ലിക്കുചെയ്യുക", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/mr/messages.json b/src/_locales/mr/messages.json index 0ecb204596d8b..3c9c379f77c93 100644 --- a/src/_locales/mr/messages.json +++ b/src/_locales/mr/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ms/messages.json b/src/_locales/ms/messages.json index 55ccde99d04f3..bed7f87a29153 100644 --- a/src/_locales/ms/messages.json +++ b/src/_locales/ms/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Klik untuk memuatkan", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/nb/messages.json b/src/_locales/nb/messages.json index 779be73930a0e..00fc8a5893362 100644 --- a/src/_locales/nb/messages.json +++ b/src/_locales/nb/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/nl/messages.json b/src/_locales/nl/messages.json index 9864039f8dc83..aefcf58000718 100644 --- a/src/_locales/nl/messages.json +++ b/src/_locales/nl/messages.json @@ -300,7 +300,7 @@ "description": "An entry in the browser's contextual menu" }, "settingsCollapseBlockedPrompt": { - "message": "Tijdelijke aanduidingen van geblokkeerde elementen verbergen", + "message": "Aanduidingen van geblokkeerde elementen verbergen", "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { @@ -312,7 +312,7 @@ "description": "A checkbox in the Settings pane" }, "settingsContextMenuPrompt": { - "message": "Waar mogelijk gebruikmaken van het contextmenu", + "message": "Contextmenu gebruiken waar mogelijk", "description": "English: Make use of context menu where appropriate" }, "settingsColorBlindPrompt": { @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Klik om te laden", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/oc/messages.json b/src/_locales/oc/messages.json index 61e2d225d31a4..804eff9cafb7b 100644 --- a/src/_locales/oc/messages.json +++ b/src/_locales/oc/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/pl/messages.json b/src/_locales/pl/messages.json index 9bdf0cbaa876c..89b96528f00b1 100644 --- a/src/_locales/pl/messages.json +++ b/src/_locales/pl/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Kliknij, aby załadować", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Ten wpis musi być ostatni", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/pt_BR/messages.json b/src/_locales/pt_BR/messages.json index fd0a5673c4987..b155e6d9d1ea4 100644 --- a/src/_locales/pt_BR/messages.json +++ b/src/_locales/pt_BR/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Clique para carregar", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Esta entrada deve ser a última", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/pt_PT/messages.json b/src/_locales/pt_PT/messages.json index e5e2057fbb194..c1e194b5ab946 100644 --- a/src/_locales/pt_PT/messages.json +++ b/src/_locales/pt_PT/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Clique para carregar", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Esta entrada deve ser a última", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ro/messages.json b/src/_locales/ro/messages.json index 895d046067206..34711f184bb81 100644 --- a/src/_locales/ro/messages.json +++ b/src/_locales/ro/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Apasă pentru a încărca", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Aceasta intrare trebuie sa fie ultima", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ru/messages.json b/src/_locales/ru/messages.json index 703a546617bdf..52ab5beb2b4cd 100644 --- a/src/_locales/ru/messages.json +++ b/src/_locales/ru/messages.json @@ -1063,6 +1063,10 @@ "message": "ГБ", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Нажмите, чтобы загрузить", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Эта запись должна быть последней", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/sk/messages.json b/src/_locales/sk/messages.json index 0e233f770cb9c..ac7c08c13d270 100644 --- a/src/_locales/sk/messages.json +++ b/src/_locales/sk/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Kliknite pre načítanie", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/sl/messages.json b/src/_locales/sl/messages.json index 8f567fcb21e86..a1ca0d2909fd6 100644 --- a/src/_locales/sl/messages.json +++ b/src/_locales/sl/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Kliknite za prikaz", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/sq/messages.json b/src/_locales/sq/messages.json index 13710fdba4131..f29c0104bb9d7 100644 --- a/src/_locales/sq/messages.json +++ b/src/_locales/sq/messages.json @@ -304,7 +304,7 @@ "description": "English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt": { - "message": "Tregoj te ikona numrin e kërkesave të refuzuara", + "message": "Shfaq te ikona numrin e kërkesave të refuzuara", "description": "English: Show the number of blocked requests on the icon" }, "settingsTooltipsPrompt": { @@ -484,7 +484,7 @@ "description": "used as a tooltip for error icon beside a list" }, "1pFormatHint": { - "message": "Një filtër për rresht. Filtri mund të jetë thjesht emri i një hosti ose i ngjashëm me ata që përdor Adblock Plus. Nuk do të merren parasysh rreshtat që fillojnë me !.", + "message": "Një filtër për rresht. Filtri mund të jetë thjesht emri i një hosti ose i ngjashëm me ata që përdor EasyList. Nuk do të merren parasysh rreshtat që fillojnë me !.", "description": "Short information about how to create custom filters" }, "1pImport": { @@ -556,7 +556,7 @@ "description": "English: label for sort option." }, "rulesSortByType": { - "message": "Tipi i rregullit", + "message": "Lloji i rregullit", "description": "English: a sort option for list of rules." }, "rulesSortBySource": { @@ -904,11 +904,11 @@ "description": "English: Network error: {{msg}}" }, "subscriberConfirm": { - "message": "uBlock₀: Të shtohet adresa në listën e filtrave tuaj?\n\nTitulli: \"{{title}}\"\nURL: {{url}}", + "message": "Të shtohet adresa në listën e personalizuar të filtrave?\n\nTitulli: \"{{title}}\"\nURL: {{url}}", "description": "No longer used" }, "subscribeButton": { - "message": "Subscribe", + "message": "Abonohem", "description": "For the button used to subscribe to a filter list" }, "elapsedOneMinuteAgo": { @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Klikoni për ta hapur", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/sr/messages.json b/src/_locales/sr/messages.json index 2f47b84eb7444..114433d18dc7e 100644 --- a/src/_locales/sr/messages.json +++ b/src/_locales/sr/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Кликните за учитавање", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/sv/messages.json b/src/_locales/sv/messages.json index 3e1ec8192730a..5d33d38bae8ec 100644 --- a/src/_locales/sv/messages.json +++ b/src/_locales/sv/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Klicka för att ladda", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ta/messages.json b/src/_locales/ta/messages.json index 1359e299d055d..e21727e27adec 100644 --- a/src/_locales/ta/messages.json +++ b/src/_locales/ta/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "ஏற்ற கிளிக் செய்க", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/te/messages.json b/src/_locales/te/messages.json index 1b15f5ebd705e..e040ea0565771 100644 --- a/src/_locales/te/messages.json +++ b/src/_locales/te/messages.json @@ -1063,6 +1063,10 @@ "message": "జీబీ", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "లోడ్ చేయడానికి క్లిక్ చేయండి", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "ఇది అంతిమంగా వుండాల్సిన నమోదు", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/th/messages.json b/src/_locales/th/messages.json index b9e944112706e..f1259b07106aa 100644 --- a/src/_locales/th/messages.json +++ b/src/_locales/th/messages.json @@ -852,7 +852,7 @@ "description": "English: Source code (GPLv3)" }, "aboutContributors": { - "message": "Contributors", + "message": "ผู้มีส่วนร่วม", "description": "English: Contributors" }, "aboutSourceCode": { @@ -860,7 +860,7 @@ "description": "Link text to source code repo" }, "aboutTranslations": { - "message": "Translations", + "message": "การแปลภาษา", "description": "Link text to translations repo" }, "aboutFilterLists": { @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "คลิกเพื่อโหลด", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/tr/messages.json b/src/_locales/tr/messages.json index 358170239fcb2..753e52cbadede 100644 --- a/src/_locales/tr/messages.json +++ b/src/_locales/tr/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Yüklemek için tıkla", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Bu girdi en sonda olmalıdır", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/uk/messages.json b/src/_locales/uk/messages.json index 93bd63c1ffdc7..57bef79800572 100644 --- a/src/_locales/uk/messages.json +++ b/src/_locales/uk/messages.json @@ -1063,6 +1063,10 @@ "message": "ГБ", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Цей запис має бути останнім", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/ur/messages.json b/src/_locales/ur/messages.json index 9844284ee65dc..7349b64451938 100644 --- a/src/_locales/ur/messages.json +++ b/src/_locales/ur/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "This entry must be the last one", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/vi/messages.json b/src/_locales/vi/messages.json index e78b56da57512..3a8074ec46cdd 100644 --- a/src/_locales/vi/messages.json +++ b/src/_locales/vi/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "Click to load", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "Đây là mục cuối", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json index 42d917cc60e97..333df16167007 100644 --- a/src/_locales/zh_CN/messages.json +++ b/src/_locales/zh_CN/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "单击以加载", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "此条目必须是最后一个", "description": "so we dont need to deal with comma for last entry" diff --git a/src/_locales/zh_TW/messages.json b/src/_locales/zh_TW/messages.json index dc824f24262a1..ce4160f478d28 100644 --- a/src/_locales/zh_TW/messages.json +++ b/src/_locales/zh_TW/messages.json @@ -1063,6 +1063,10 @@ "message": "GB", "description": "short for 'gigabytes'" }, + "clickToLoad": { + "message": "點擊以載入", + "description": "Message used in frame placeholders" + }, "dummy": { "message": "此條目須為最後一個", "description": "so we dont need to deal with comma for last entry" From 734456feca8a90b6bcbceea71461201d676a1405 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 08:23:56 -0400 Subject: [PATCH 41/73] Use i18n for click-to-load placeholder --- src/web_accessible_resources/click2load.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web_accessible_resources/click2load.html b/src/web_accessible_resources/click2load.html index 57c806869c774..dbf7f3d6fe771 100644 --- a/src/web_accessible_resources/click2load.html +++ b/src/web_accessible_resources/click2load.html @@ -12,7 +12,7 @@ -Click to load +
From 415a3fa572ab8db1d540cc52e521e421685a7999 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 08:26:09 -0400 Subject: [PATCH 42/73] Ne wrevision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 51bc16f2d88cc..9f0bc2897fa42 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.3.7 +1.30.5.0 From 62c985fe4c090648f2e9865bab12c650dfcf73bc Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 08:35:22 -0400 Subject: [PATCH 43/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 6ddf890335790..9bb4ae9c2b574 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.3.6", + "version": "1.30.5.0", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.3b6", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.3b6/uBlock0_1.30.3b6.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.5b0", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.5b0/uBlock0_1.30.5b0.firefox.signed.xpi" } ] } From 30c38de9bc9d6e7d4502a5c627aa4b3a63b612bf Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 18:53:11 -0400 Subject: [PATCH 44/73] Fix local Google Analytics replacement script Related issue: - https://github.com/uBlockOrigin/uAssets/pull/4115 --- src/web_accessible_resources/google-analytics_analytics.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/web_accessible_resources/google-analytics_analytics.js b/src/web_accessible_resources/google-analytics_analytics.js index 5d6a087c88b6b..87704a2828ae1 100644 --- a/src/web_accessible_resources/google-analytics_analytics.js +++ b/src/web_accessible_resources/google-analytics_analytics.js @@ -38,6 +38,7 @@ const w = window; const gaName = w.GoogleAnalyticsObject || 'ga'; const gaQueue = w[gaName]; + // https://github.com/uBlockOrigin/uAssets/pull/4115 const ga = function() { const len = arguments.length; if ( len === 0 ) { return; } @@ -46,6 +47,8 @@ let a = args[len-1]; if ( a instanceof Object && a.hitCallback instanceof Function ) { fn = a.hitCallback; + } else if ( a instanceof Function ) { + fn = ( ) => { a(ga.create()); }; } else { const pos = args.indexOf('hitCallback'); if ( pos !== -1 && args[pos+1] instanceof Function ) { @@ -54,7 +57,7 @@ } if ( fn instanceof Function === false ) { return; } try { - fn(); + setTimeout(fn, 1); } catch (ex) { } }; From 9994033629f4dee8c07866c19164249d09e9cd55 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Tue, 13 Oct 2020 19:02:37 -0400 Subject: [PATCH 45/73] On second thought, keep what has been working Related commit: - https://github.com/gorhill/uBlock/commit/30c38de9bc9d6e7d4502a5c627aa4b3a63b612bf --- src/web_accessible_resources/google-analytics_analytics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web_accessible_resources/google-analytics_analytics.js b/src/web_accessible_resources/google-analytics_analytics.js index 87704a2828ae1..a3203e2be1c40 100644 --- a/src/web_accessible_resources/google-analytics_analytics.js +++ b/src/web_accessible_resources/google-analytics_analytics.js @@ -57,7 +57,7 @@ } if ( fn instanceof Function === false ) { return; } try { - setTimeout(fn, 1); + fn(); } catch (ex) { } }; From a095b8325046e725c7d3e58943660ac3848d910a Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 14 Oct 2020 10:21:30 -0400 Subject: [PATCH 46/73] Use a CodeMirror editor instance in element picker This allows to bring in all the benefits of syntax highlighting and enhanced editing features in the element picker, like auto- completion, etc. This is also a necessary step to possibly solve the following issue: - https://github.com/gorhill/uBlock/issues/2035 Additionally, incrementally improved the behavior of uBO's custom CodeMirror static filtering syntax mode when double-clicking somewhere in a static extended filter: - on a class/id string will cause the whole class/id string to be selected, including the prepending `.`/`#`. - somewhere in a hostname/entity will cause all the labels from the cursor position to the right-most label to be selected (subject to change/fine-tune as per feedback of filter list maintainers). Related feedback: - https://github.com/uBlockOrigin/uBlock-issues/issues/1134#issuecomment-679421316 --- src/css/epicker-ui.css | 38 +++++------- src/js/1p-filters.js | 4 +- src/js/asset-viewer.js | 4 +- src/js/codemirror/ubo-static-filtering.js | 56 ++++++++++++----- src/js/epicker-ui.js | 65 +++++++++++++++----- src/web_accessible_resources/epicker-ui.html | 17 ++++- 6 files changed, 126 insertions(+), 58 deletions(-) diff --git a/src/css/epicker-ui.css b/src/css/epicker-ui.css index e45b935dd0913..8cb75747c61cc 100644 --- a/src/css/epicker-ui.css +++ b/src/css/epicker-ui.css @@ -29,11 +29,6 @@ html#ublock0-epicker, #ublock0-epicker.paused:not(.zap) aside { display: block; } -#ublock0-epicker ul, -#ublock0-epicker li, -#ublock0-epicker div { - display: block; -} #ublock0-epicker #toolbar { cursor: grab; display: flex; @@ -79,36 +74,31 @@ html#ublock0-epicker, width: 100%; } #ublock0-epicker section > div:first-child { - border: 1px solid #aaa; + border: 1px solid var(--default-surface-border); margin: 0; position: relative; } #ublock0-epicker section.invalidFilter > div:first-child { border-color: red; } -#ublock0-epicker section textarea { - background-color: var(--default-surface); +#ublock0-epicker section .codeMirrorContainer { border: none; box-sizing: border-box; - color: var(--default-ink); font: 11px monospace; height: 8em; - margin: 0; - overflow: hidden; - overflow-y: auto; - padding: 2px 2px 1.2em 2px; - resize: none; + padding: 2px; width: 100%; - word-break: break-all; -} -#ublock0-epicker section textarea + div { - background-color: transparent; - bottom: 0; + } +.CodeMirror-lines, +.CodeMirror pre { + padding: 0; + } +.CodeMirror-vscrollbar { + z-index: 0; + } + +#ublock0-epicker section .resultsetWidgets { display: flex; - left: 0; - pointer-events: none; - position: absolute; - right: 0; } #resultsetModifiers { align-items: flex-end; @@ -196,7 +186,7 @@ html#ublock0-epicker, overflow: hidden; } #ublock0-epicker #candidateFilters { - max-height: 16em; + max-height: 14em; overflow-y: auto; } #ublock0-epicker #candidateFilters > li:first-of-type { diff --git a/src/js/1p-filters.js b/src/js/1p-filters.js index 859fe72336006..b99faf1c79dae 100644 --- a/src/js/1p-filters.js +++ b/src/js/1p-filters.js @@ -42,7 +42,9 @@ const cmEditor = new CodeMirror(document.getElementById('userFilters'), { lineWrapping: true, matchBrackets: true, maxScanLines: 1, - styleActiveLine: true, + styleActiveLine: { + nonEmpty: true, + }, }); uBlockDashboard.patchCodeMirrorEditor(cmEditor); diff --git a/src/js/asset-viewer.js b/src/js/asset-viewer.js index 1e03771c76659..ecdef01c24c29 100644 --- a/src/js/asset-viewer.js +++ b/src/js/asset-viewer.js @@ -53,7 +53,9 @@ matchBrackets: true, maxScanLines: 1, readOnly: true, - styleActiveLine: true, + styleActiveLine: { + nonEmpty: true, + }, }); uBlockDashboard.patchCodeMirrorEditor(cmEditor); diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js index 1c268647a6b98..5821af7c4243c 100644 --- a/src/js/codemirror/ubo-static-filtering.js +++ b/src/js/codemirror/ubo-static-filtering.js @@ -318,10 +318,12 @@ CodeMirror.defineMode('ubo-static-filtering', function() { return 'comment'; } if ( parser.category === parser.CATStaticExtFilter ) { - return colorExtSpan(stream); + const style = colorExtSpan(stream); + return style ? `ext ${style}` : 'ext'; } if ( parser.category === parser.CATStaticNetFilter ) { - return colorNetSpan(stream); + const style = colorNetSpan(stream); + return style ? `net ${style}` : 'net'; } stream.skipToEnd(); return null; @@ -330,13 +332,14 @@ CodeMirror.defineMode('ubo-static-filtering', function() { return { lineComment: '!', token: function(stream) { + let style = ''; if ( stream.sol() ) { parser.analyze(stream.string); parser.analyzeExtra(); parserSlot = 0; netOptionValueMode = false; } - let style = colorSpan(stream) || ''; + style += colorSpan(stream) || ''; if ( (parser.flavorBits & parser.BITFlavorError) !== 0 ) { style += ' line-background-error'; } @@ -615,24 +618,49 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { const s = cm.getLine(line); const token = cm.getTokenTypeAt(pos); - let lmatch, rmatch; - let select = false; + let beg, end; // Select URL in comments - if ( token === 'comment link' ) { - lmatch = /\S+$/.exec(s.slice(0, ch)); - rmatch = /^\S+/.exec(s.slice(ch)); - select = lmatch !== null && rmatch !== null && - /^https?:\/\//.test(s.slice(lmatch.index)); + if ( /\bcomment\b/.test(token) && /\blink\b/.test(token) ) { + const l = /\S+$/.exec(s.slice(0, ch)); + if ( l && /^https?:\/\//.test(s.slice(l.index)) ) { + const r = /^\S+/.exec(s.slice(ch)); + if ( r ) { + beg = l.index; + end = ch + r[0].length; + } + } + } + + // Better word selection for cosmetic filters + if ( /\bext\b/.test(token) ) { + if ( /\bvalue\b/.test(token) ) { + const l = /[^,.]*$/i.exec(s.slice(0, ch)); + const r = /^[^#,]*/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + } + } + if ( /\bvariable\b/.test(token) ) { + const l = /[#.]?[a-z0-9_-]+$/i.exec(s.slice(0, ch)); + const r = /^[a-z0-9_-]+/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + if ( /\bdef\b/.test(cm.getTokenTypeAt({ line, ch: beg + 1 })) ) { + beg += 1; + } + } + } } // TODO: add more convenient word-matching cases here - // if ( select === false ) { ... } - if ( select === false ) { return Pass; } + if ( beg === undefined ) { return Pass; } cm.setSelection( - { line, ch: lmatch.index }, - { line, ch: ch + rmatch.index + rmatch[0].length } + { line, ch: beg }, + { line, ch: end } ); }; diff --git a/src/js/epicker-ui.js b/src/js/epicker-ui.js index 15eefafe0e6c8..bc81e9e728666 100644 --- a/src/js/epicker-ui.js +++ b/src/js/epicker-ui.js @@ -19,6 +19,8 @@ Home: https://github.com/gorhill/uBlock */ +/* global CodeMirror */ + 'use strict'; /******************************************************************************/ @@ -36,7 +38,6 @@ const $storAll = selector => document.querySelectorAll(selector); const pickerRoot = document.documentElement; const dialog = $stor('aside'); -const taCandidate = $stor('textarea'); let staticFilteringParser; const svgRoot = $stor('svg'); @@ -66,11 +67,40 @@ let needBody = false; /******************************************************************************/ +const cmEditor = new CodeMirror(document.querySelector('.codeMirrorContainer'), { + autoCloseBrackets: true, + autofocus: true, + extraKeys: { + 'Ctrl-Space': 'autocomplete', + }, + lineWrapping: true, + matchBrackets: true, + maxScanLines: 1, +}); + +vAPI.messaging.send('dashboard', { + what: 'getAutoCompleteDetails' +}).then(response => { + if ( response instanceof Object === false ) { return; } + const mode = cmEditor.getMode(); + if ( mode.setHints instanceof Function ) { + mode.setHints(response); + } +}); + +/******************************************************************************/ + +const rawFilterFromTextarea = function() { + const text = cmEditor.getValue(); + const pos = text.indexOf('\n'); + return pos === -1 ? text : text.slice(0, pos); +}; + +/******************************************************************************/ + const filterFromTextarea = function() { - const s = taCandidate.value.trim(); - if ( s === '' ) { return ''; } - const pos = s.indexOf('\n'); - const filter = pos === -1 ? s.trim() : s.slice(0, pos).trim(); + const filter = rawFilterFromTextarea(); + if ( filter === '' ) { return ''; } const sfp = staticFilteringParser; sfp.analyze(filter); sfp.analyzeExtra(); @@ -256,7 +286,8 @@ const candidateFromFilterChoice = function(filterChoice) { const onCandidateOptimized = function(details) { $id('resultsetModifiers').classList.remove('hide'); computedCandidate = details.filter; - taCandidate.value = computedCandidate; + cmEditor.setValue(computedCandidate); + cmEditor.clearHistory(); onCandidateChanged(); }; @@ -393,9 +424,9 @@ const onCandidateChanged = function() { $id('resultsetCount').textContent = 'E'; $id('create').setAttribute('disabled', ''); } + const text = rawFilterFromTextarea(); $id('resultsetModifiers').classList.toggle( - 'hide', - taCandidate.value === '' || taCandidate.value !== computedCandidate + 'hide', text === '' || text !== computedCandidate ); vAPI.MessagingConnection.sendTo(epickerConnectionId, { what: 'dialogSetFilter', @@ -462,20 +493,22 @@ const onDepthChanged = function() { slot: max - value, }); if ( text === undefined ) { return; } - taCandidate.value = text; + cmEditor.setValue(text); + cmEditor.clearHistory(); onCandidateChanged(); }; /******************************************************************************/ const onSpecificityChanged = function() { - if ( taCandidate.value !== computedCandidate ) { return; } + if ( rawFilterFromTextarea() !== computedCandidate ) { return; } const text = candidateFromFilterChoice({ filters: cosmeticFilterCandidates, slot: computedCandidateSlot, }); if ( text === undefined ) { return; } - taCandidate.value = text; + cmEditor.setValue(text); + cmEditor.clearHistory(); onCandidateChanged(); }; @@ -496,7 +529,8 @@ const onCandidateClicked = function(ev) { } const text = candidateFromFilterChoice(choice); if ( text === undefined ) { return; } - taCandidate.value = text; + cmEditor.setValue(text); + cmEditor.clearHistory(); onCandidateChanged(); }; @@ -703,7 +737,7 @@ const showDialog = function(details) { // This is an issue which surfaced when the element picker code was // revisited to isolate the picker dialog DOM from the page DOM. if ( typeof filter !== 'object' || filter === null ) { - taCandidate.value = ''; + cmEditor.setValue(''); return; } @@ -714,7 +748,7 @@ const showDialog = function(details) { const text = candidateFromFilterChoice(filterChoice); if ( text === undefined ) { return; } - taCandidate.value = text; + cmEditor.setValue(text); onCandidateChanged(); }; @@ -749,7 +783,8 @@ const startPicker = function() { if ( pickerRoot.classList.contains('zap') ) { return; } - taCandidate.addEventListener('input', onCandidateChanged); + cmEditor.on('changes', onCandidateChanged); + $id('preview').addEventListener('click', onPreviewClicked); $id('create').addEventListener('click', onCreateClicked); $id('pick').addEventListener('click', onPickClicked); diff --git a/src/web_accessible_resources/epicker-ui.html b/src/web_accessible_resources/epicker-ui.html index 7f72300a9886a..24ee865959967 100644 --- a/src/web_accessible_resources/epicker-ui.html +++ b/src/web_accessible_resources/epicker-ui.html @@ -4,16 +4,20 @@ uBlock Origin Element Picker + + + + + + + + + + + - + From 319d1954444575b54b0de0eede5362446cc1b472 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 14 Oct 2020 10:52:32 -0400 Subject: [PATCH 47/73] Import translation work from https://crowdin.com/project/ublock --- src/_locales/ar/messages.json | 2 +- src/_locales/fy/messages.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index 581d8ab2bff11..69a4a643ee134 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -1064,7 +1064,7 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "اضغط للتحميل", "description": "Message used in frame placeholders" }, "dummy": { diff --git a/src/_locales/fy/messages.json b/src/_locales/fy/messages.json index 43308013c5cff..fa9831c4de68d 100644 --- a/src/_locales/fy/messages.json +++ b/src/_locales/fy/messages.json @@ -1064,7 +1064,7 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "Klik om te laden", "description": "Message used in frame placeholders" }, "dummy": { From 72cb4fcf7a081c934ab1541cf716ea68175483c7 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 14 Oct 2020 11:13:52 -0400 Subject: [PATCH 48/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index 9f0bc2897fa42..c4814e59b4b03 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.5.0 +1.30.5.1 From c227b8bd0c0c77afbbc51f3b42adc9bd22011d62 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 14 Oct 2020 11:45:53 -0400 Subject: [PATCH 49/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 9bb4ae9c2b574..65d44521131ed 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.5.0", + "version": "1.30.5.1", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.5b0", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.5b0/uBlock0_1.30.5b0.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.5b1", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.5b1/uBlock0_1.30.5b1.firefox.signed.xpi" } ] } From 3059db77c4a4e8a9a44931b0aa1989c272b07dc4 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Wed, 14 Oct 2020 13:37:09 -0400 Subject: [PATCH 50/73] Use proxy detection code path only on Firefox 79 and less Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/911 This was fixed in Firefox 80: - https://bugzilla.mozilla.org/show_bug.cgi?id=1618271 --- platform/firefox/vapi-webrequest.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/platform/firefox/vapi-webrequest.js b/platform/firefox/vapi-webrequest.js index a7c14c24c79ab..eaa74b34f64fc 100644 --- a/platform/firefox/vapi-webrequest.js +++ b/platform/firefox/vapi-webrequest.js @@ -125,19 +125,21 @@ this.cnameFlushTime = Date.now() + this.cnameMaxTTL * 60000; // https://github.com/uBlockOrigin/uBlock-issues/issues/911 // Install/remove proxy detector. - const wrohr = browser.webRequest.onHeadersReceived; - if ( cnameUncloak === false || cnameUncloakProxied ) { - if ( wrohr.hasListener(proxyDetector) ) { - wrohr.removeListener(proxyDetector); + if ( vAPI.webextFlavor.major < 80 ) { + const wrohr = browser.webRequest.onHeadersReceived; + if ( cnameUncloak === false || cnameUncloakProxied ) { + if ( wrohr.hasListener(proxyDetector) ) { + wrohr.removeListener(proxyDetector); + } + } else if ( wrohr.hasListener(proxyDetector) === false ) { + wrohr.addListener( + proxyDetector, + { urls: [ '*://*/*' ] }, + [ 'blocking' ] + ); } - } else if ( wrohr.hasListener(proxyDetector) === false ) { - wrohr.addListener( - proxyDetector, - { urls: [ '*://*/*' ] }, - [ 'blocking' ] - ); + proxyDetectorTryCount = 32; } - proxyDetectorTryCount = 32; } normalizeDetails(details) { if ( mustPunycode && !reAsciiHostname.test(details.url) ) { From 38e1bbbe68586d88f8d385d93b4c45b086c1eea0 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 16 Oct 2020 10:06:00 -0400 Subject: [PATCH 51/73] Better word selection for static network filters Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1134 Double-clicking on... ... a filter option will cause the option to be wholly selected, including `=[value]` if present; ... a value assigned to a filter option will cause the value to be wholly selected, except when the value is a hostname/entity, in which case all the labels from the cursor position to the right-most label will be selected. --- src/js/codemirror/ubo-static-filtering.js | 24 +++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js index 5821af7c4243c..3e3f583c3fe79 100644 --- a/src/js/codemirror/ubo-static-filtering.js +++ b/src/js/codemirror/ubo-static-filtering.js @@ -633,7 +633,7 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { } // Better word selection for cosmetic filters - if ( /\bext\b/.test(token) ) { + else if ( /\bext\b/.test(token) ) { if ( /\bvalue\b/.test(token) ) { const l = /[^,.]*$/i.exec(s.slice(0, ch)); const r = /^[^#,]*/i.exec(s.slice(ch)); @@ -641,8 +641,7 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { beg = l.index; end = ch + r[0].length; } - } - if ( /\bvariable\b/.test(token) ) { + } else if ( /\bvariable\b/.test(token) ) { const l = /[#.]?[a-z0-9_-]+$/i.exec(s.slice(0, ch)); const r = /^[a-z0-9_-]+/i.exec(s.slice(ch)); if ( l && r ) { @@ -655,7 +654,24 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { } } - // TODO: add more convenient word-matching cases here + // Better word selection for network filters + else if ( /\bnet\b/.test(token) ) { + if ( /\bvalue\b/.test(token) ) { + const l = /[^,.=|]*$/i.exec(s.slice(0, ch)); + const r = /^[^#,|]*/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + } + } else if ( /\bdef\b/.test(token) ) { + const l = /[a-z0-9-]+$/i.exec(s.slice(0, ch)); + const r = /^[^,]*=[^,]+/i.exec(s.slice(ch)); + if ( l && r ) { + beg = l.index; + end = ch + r[0].length; + } + } + } if ( beg === undefined ) { return Pass; } cm.setSelection( From a9ef8634875d0f46b9db75b4dfd52a7e63aa884f Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 16 Oct 2020 10:24:04 -0400 Subject: [PATCH 52/73] Import translation work from https://crowdin.com/project/ublock --- src/_locales/nb/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_locales/nb/messages.json b/src/_locales/nb/messages.json index 00fc8a5893362..4ac8fa7451ee2 100644 --- a/src/_locales/nb/messages.json +++ b/src/_locales/nb/messages.json @@ -1064,7 +1064,7 @@ "description": "short for 'gigabytes'" }, "clickToLoad": { - "message": "Click to load", + "message": "Klikk for å laste", "description": "Message used in frame placeholders" }, "dummy": { From 0cc0792ed70e249b22732d6a9af313e7a0a794c8 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 16 Oct 2020 10:24:58 -0400 Subject: [PATCH 53/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index c4814e59b4b03..e02b96de375aa 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.5.1 +1.30.5.2 From 97bff4713109e644db5b2644b360b14d0d89fa78 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 16 Oct 2020 10:30:51 -0400 Subject: [PATCH 54/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index 65d44521131ed..fcabf6d7bca52 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.5.1", + "version": "1.30.5.2", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.5b1", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.5b1/uBlock0_1.30.5b1.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.5b2", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.5b2/uBlock0_1.30.5b2.firefox.signed.xpi" } ] } From 4c5197322f7f4c74412f01747e7e0c5e2a023677 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 16 Oct 2020 17:12:22 -0400 Subject: [PATCH 55/73] Improve specificity slider in element picker The specificity slider will now be more intuitive by ordering candidates by match count from highest match count to the left to the lowest match count to the right. Candidates with same match counts will be discarded and replaced with the shortest candidate. --- src/js/epicker-ui.js | 158 +++++++++++++++++++---------------- src/js/scriptlets/epicker.js | 48 +++++++---- 2 files changed, 121 insertions(+), 85 deletions(-) diff --git a/src/js/epicker-ui.js b/src/js/epicker-ui.js index bc81e9e728666..2d1767a0b7125 100644 --- a/src/js/epicker-ui.js +++ b/src/js/epicker-ui.js @@ -63,6 +63,7 @@ let netFilterCandidates = []; let cosmeticFilterCandidates = []; let computedCandidateSlot = 0; let computedCandidate = ''; +let computedSpecificityCandidates = []; let needBody = false; /******************************************************************************/ @@ -194,7 +195,13 @@ const candidateFromFilterChoice = function(filterChoice) { $stor(`#cosmeticFilters li:nth-of-type(${slot+1})`) .classList.add('active'); - const specificity = [ + return cosmeticCandidatesFromFilterChoice(filterChoice); +}; + +/******************************************************************************/ + +const cosmeticCandidatesFromFilterChoice = function(filterChoice) { + const specificities = [ 0b0000, // remove hierarchy; remove id, nth-of-type, attribute values 0b0010, // remove hierarchy; remove id, nth-of-type 0b0011, // remove hierarchy @@ -203,89 +210,100 @@ const candidateFromFilterChoice = function(filterChoice) { 0b1100, // remove id, nth-of-type, attribute values 0b1110, // remove id, nth-of-type 0b1111, // keep all = most specific - ][ parseInt($stor('#resultsetSpecificity input').value, 10) ]; - - // Return path: the target element, then all siblings prepended - const paths = []; - for ( let i = slot; i < filters.length; i++ ) { - filter = filters[i].slice(2); - // Remove id, nth-of-type - // https://github.com/uBlockOrigin/uBlock-issues/issues/162 - // Mind escaped periods: they do not denote a class identifier. - if ( (specificity & 0b0001) === 0 ) { - filter = filter.replace(/:nth-of-type\(\d+\)/, ''); - if ( - filter.charAt(0) === '#' && ( - (specificity & 0b1000) === 0 || i === slot - ) - ) { - const pos = filter.search(/[^\\]\./); - if ( pos !== -1 ) { - filter = filter.slice(pos + 1); + ]; + + const candidates = []; + + let { slot, filters } = filterChoice; + let filter = filters[slot]; + + for ( const specificity of specificities ) { + // Return path: the target element, then all siblings prepended + const paths = []; + for ( let i = slot; i < filters.length; i++ ) { + filter = filters[i].slice(2); + // Remove id, nth-of-type + // https://github.com/uBlockOrigin/uBlock-issues/issues/162 + // Mind escaped periods: they do not denote a class identifier. + if ( (specificity & 0b0001) === 0 ) { + filter = filter.replace(/:nth-of-type\(\d+\)/, ''); + if ( + filter.charAt(0) === '#' && ( + (specificity & 0b1000) === 0 || i === slot + ) + ) { + const pos = filter.search(/[^\\]\./); + if ( pos !== -1 ) { + filter = filter.slice(pos + 1); + } } } - } - // Remove attribute values. - if ( (specificity & 0b0010) === 0 ) { - const match = /^\[([^^=]+)\^?=.+\]$/.exec(filter); - if ( match !== null ) { - filter = `[${match[1]}]`; + // Remove attribute values. + if ( (specificity & 0b0010) === 0 ) { + const match = /^\[([^^=]+)\^?=.+\]$/.exec(filter); + if ( match !== null ) { + filter = `[${match[1]}]`; + } + } + // Remove all classes when an id exists. + // https://github.com/uBlockOrigin/uBlock-issues/issues/162 + // Mind escaped periods: they do not denote a class identifier. + if ( filter.charAt(0) === '#' ) { + filter = filter.replace(/([^\\])\..+$/, '$1'); + } + if ( paths.length !== 0 ) { + filter += ' > '; + } + paths.unshift(filter); + // Stop at any element with an id: these are unique in a web page + if ( (specificity & 0b1000) === 0 || filter.startsWith('#') ) { + break; } } - // Remove all classes when an id exists. - // https://github.com/uBlockOrigin/uBlock-issues/issues/162 - // Mind escaped periods: they do not denote a class identifier. - if ( filter.charAt(0) === '#' ) { - filter = filter.replace(/([^\\])\..+$/, '$1'); - } - if ( paths.length !== 0 ) { - filter += ' > '; - } - paths.unshift(filter); - // Stop at any element with an id: these are unique in a web page - if ( (specificity & 0b1000) === 0 || filter.startsWith('#') ) { break; } - } - // Trim hierarchy: remove generic elements from path - if ( (specificity & 0b1100) === 0b1000 ) { - let i = 0; - while ( i < paths.length - 1 ) { - if ( /^[a-z0-9]+ > $/.test(paths[i+1]) ) { - if ( paths[i].endsWith(' > ') ) { - paths[i] = paths[i].slice(0, -2); + // Trim hierarchy: remove generic elements from path + if ( (specificity & 0b1100) === 0b1000 ) { + let i = 0; + while ( i < paths.length - 1 ) { + if ( /^[a-z0-9]+ > $/.test(paths[i+1]) ) { + if ( paths[i].endsWith(' > ') ) { + paths[i] = paths[i].slice(0, -2); + } + paths.splice(i + 1, 1); + } else { + i += 1; } - paths.splice(i + 1, 1); - } else { - i += 1; } } - } - if ( - needBody && - paths.length !== 0 && - paths[0].startsWith('#') === false && - (specificity & 0b1100) !== 0 - ) { - paths.unshift('body > '); - } + if ( + needBody && + paths.length !== 0 && + paths[0].startsWith('#') === false && + (specificity & 0b1100) !== 0 + ) { + paths.unshift('body > '); + } - if ( paths.length === 0 ) { return ''; } + candidates.push(paths); + } renderRange('resultsetDepth', slot, true); renderRange('resultsetSpecificity'); vAPI.MessagingConnection.sendTo(epickerConnectionId, { - what: 'optimizeCandidate', - paths, + what: 'optimizeCandidates', + candidates, }); }; /******************************************************************************/ -const onCandidateOptimized = function(details) { +const onCandidatesOptimized = function(details) { $id('resultsetModifiers').classList.remove('hide'); - computedCandidate = details.filter; + const i = parseInt($stor('#resultsetSpecificity input').value, 10); + computedSpecificityCandidates = details.candidates; + computedCandidate = computedSpecificityCandidates[i]; cmEditor.setValue(computedCandidate); cmEditor.clearHistory(); onCandidateChanged(); @@ -501,13 +519,11 @@ const onDepthChanged = function() { /******************************************************************************/ const onSpecificityChanged = function() { + renderRange('resultsetSpecificity'); if ( rawFilterFromTextarea() !== computedCandidate ) { return; } - const text = candidateFromFilterChoice({ - filters: cosmeticFilterCandidates, - slot: computedCandidateSlot, - }); - if ( text === undefined ) { return; } - cmEditor.setValue(text); + const i = parseInt($stor('#resultsetSpecificity input').value, 10); + computedCandidate = computedSpecificityCandidates[i]; + cmEditor.setValue(computedCandidate); cmEditor.clearHistory(); onCandidateChanged(); }; @@ -808,8 +824,8 @@ const quitPicker = function() { const onPickerMessage = function(msg) { switch ( msg.what ) { - case 'candidateOptimized': - onCandidateOptimized(msg); + case 'candidatesOptimized': + onCandidatesOptimized(msg); break; case 'showDialog': showDialog(msg); diff --git a/src/js/scriptlets/epicker.js b/src/js/scriptlets/epicker.js index 2b4b98d98e264..4571ebba33f78 100644 --- a/src/js/scriptlets/epicker.js +++ b/src/js/scriptlets/epicker.js @@ -821,21 +821,41 @@ const filterToDOMInterface = (( ) => { /******************************************************************************/ -const onOptmizeCandidate = function(details) { - const { paths } = details; - let count = Number.MAX_SAFE_INTEGER; - let selector = ''; - for ( let i = 0, n = paths.length; i < n; i++ ) { - const s = paths.slice(n - i - 1).join(''); - const elems = document.querySelectorAll(s); - if ( elems.length < count ) { - selector = s; - count = elems.length; +const onOptmizeCandidates = function(details) { + const { candidates } = details; + const results = []; + for ( const paths of candidates ) { + let count = Number.MAX_SAFE_INTEGER; + let selector = ''; + for ( let i = 0, n = paths.length; i < n; i++ ) { + const s = paths.slice(n - i - 1).join(''); + const elems = document.querySelectorAll(s); + if ( elems.length < count ) { + selector = s; + count = elems.length; + } } + results.push({ selector: `##${selector}`, count }); + } + // Sort by most match count and shortest selector to least match count and + // longest selector. + results.sort((a, b) => { + const r = b.count - a.count; + if ( r !== 0 ) { return r; } + return a.selector.length - b.selector.length; + }); + // Discard selectors with same match count as shorter ones. + for ( let i = 0; i < results.length - 1; i++ ) { + const a = results[i+0]; + const b = results[i+1]; + if ( b.count !== a.count ) { continue; } + if ( b.selector.length === a.selector.length ) { continue; } + b.selector = a.selector; + b.count = a.count; } vAPI.MessagingConnection.sendTo(epickerConnectionId, { - what: 'candidateOptimized', - filter: `##${selector}`, + what: 'candidatesOptimized', + candidates: results.map(a => a.selector), }); }; @@ -1064,8 +1084,8 @@ const onDialogMessage = function(msg) { highlightElements([], true); } break; - case 'optimizeCandidate': - onOptmizeCandidate(msg); + case 'optimizeCandidates': + onOptmizeCandidates(msg); break; case 'dialogCreate': filterToDOMInterface.queryAll(msg); From 32b08dc7322c32d25ce3cf65c105ca44c2d9886f Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Fri, 16 Oct 2020 17:13:55 -0400 Subject: [PATCH 56/73] Mind whitespaces when double-clicking to select filter option value --- src/js/codemirror/ubo-static-filtering.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/codemirror/ubo-static-filtering.js b/src/js/codemirror/ubo-static-filtering.js index 3e3f583c3fe79..25ecd31872494 100644 --- a/src/js/codemirror/ubo-static-filtering.js +++ b/src/js/codemirror/ubo-static-filtering.js @@ -657,8 +657,8 @@ CodeMirror.registerHelper('fold', 'ubo-static-filtering', (( ) => { // Better word selection for network filters else if ( /\bnet\b/.test(token) ) { if ( /\bvalue\b/.test(token) ) { - const l = /[^,.=|]*$/i.exec(s.slice(0, ch)); - const r = /^[^#,|]*/i.exec(s.slice(ch)); + const l = /[^ ,.=|]*$/i.exec(s.slice(0, ch)); + const r = /^[^ #,|]*/i.exec(s.slice(ch)); if ( l && r ) { beg = l.index; end = ch + r[0].length; From 6a10319f2100b0b8c8e8863fa4508a26a34780d4 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 17 Oct 2020 12:05:03 -0400 Subject: [PATCH 57/73] Fix broken advanced property uiStyles Related commit: - https://github.com/gorhill/uBlock/commit/e3a6d8465f19f4ef5d84ceddb9570644cf4fc0a3 --- src/js/udom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/udom.js b/src/js/udom.js index baf78a6b4d1b1..66bf2d42387d6 100644 --- a/src/js/udom.js +++ b/src/js/udom.js @@ -105,7 +105,7 @@ DOMListFactory.nodeFromSelector = function(selector) { } } if ( response.uiStyles !== 'unset' ) { - document.body.style.cssText = response; + document.body.style.cssText = response.uiStyles; } }); From cd5e1b93c7570a7861e947d6d8cc84a097637964 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 17 Oct 2020 12:07:56 -0400 Subject: [PATCH 58/73] New revision for dev build --- dist/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/version b/dist/version index e02b96de375aa..4e16a771d2149 100644 --- a/dist/version +++ b/dist/version @@ -1 +1 @@ -1.30.5.2 +1.30.5.4 From d83af0d0e8169a1dcb683b3e5cb1cdd09b647621 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 17 Oct 2020 12:25:44 -0400 Subject: [PATCH 59/73] Make Firefox dev build auto-update --- dist/firefox/updates.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dist/firefox/updates.json b/dist/firefox/updates.json index fcabf6d7bca52..729c812f6ecf0 100644 --- a/dist/firefox/updates.json +++ b/dist/firefox/updates.json @@ -3,10 +3,10 @@ "uBlock0@raymondhill.net": { "updates": [ { - "version": "1.30.5.2", + "version": "1.30.5.4", "browser_specific_settings": { "gecko": { "strict_min_version": "55" } }, - "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.5b2", - "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.5b2/uBlock0_1.30.5b2.firefox.signed.xpi" + "update_info_url": "https://github.com/gorhill/uBlock/releases/tag/1.30.5b4", + "update_link": "https://github.com/gorhill/uBlock/releases/download/1.30.5b4/uBlock0_1.30.5b4.firefox.signed.xpi" } ] } From 3bce80a7b632e7033b754e08f9d323354c94d936 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 18 Oct 2020 09:58:44 -0400 Subject: [PATCH 60/73] Update link to uBO on Crowdin The site changed it's main domain from crowdin.net to crowdin.com. --- src/about.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/about.html b/src/about.html index a7861e66b99be..13c40ced497a7 100644 --- a/src/about.html +++ b/src/about.html @@ -28,7 +28,7 @@
 
-
+
 
From 9947fcf4d56f5997e8b681bd69c9a56b329e4b76 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 18 Oct 2020 10:00:55 -0400 Subject: [PATCH 61/73] Improve layout of popup panel when rendered in a tab This brings back the ability to screenshot the whole list of domains when the popup panel is opened in a tab. --- src/css/popup-fenix.css | 8 ++++++++ src/js/popup-fenix.js | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/css/popup-fenix.css b/src/css/popup-fenix.css index 15d9cbbd01a64..7af6d9420c715 100644 --- a/src/css/popup-fenix.css +++ b/src/css/popup-fenix.css @@ -553,6 +553,14 @@ body:not([data-more~="e"]) [data-more="e"] { display: none; } +/* popup-in-tab mode, useful for screenshots */ +:root.desktop.intab body { + overflow: auto; + } +:root.desktop.intab #firewall { + max-height: none; + } + /* horizontally-constrained viewport */ :root.portrait body { overflow-y: auto; diff --git a/src/js/popup-fenix.js b/src/js/popup-fenix.js index c8f543c58dd5e..37e02846547b3 100644 --- a/src/js/popup-fenix.js +++ b/src/js/popup-fenix.js @@ -1027,7 +1027,7 @@ uDom('[data-i18n="popupAnyRulePrompt"]').on('click', ev => { messaging.send('popupPanel', { what: 'gotoURL', details: { - url: `popup-fenix.html?tabId=${popupData.tabId}`, + url: `popup-fenix.html?tabId=${popupData.tabId}&intab=1`, select: true, index: -1, }, @@ -1260,6 +1260,9 @@ const getPopupData = async function(tabId) { panes.prepend(sticky); } } + if ( selfURL.searchParams.get('intab') !== null ) { + root.classList.add('intab'); + } await nextFrames(1); document.body.classList.remove('loading'); }; From 53dd339d78dbd765e24783b9aa52cf0d29935598 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sun, 18 Oct 2020 10:07:46 -0400 Subject: [PATCH 62/73] Improve interactivity for blocked large media elements Related issues: - https://github.com/gorhill/uBlock/issues/1390 - https://github.com/gorhill/uBlock/issues/2334 The deadline to interactively load a specific media element has been extended from 2sec to 5sec. Clicking over a blocked large media element will cause uBO to lookup and handle all potentially blocked large elements at the cursor position. This should take care of being able to unblock media elements hidden under other DOM object. The CSS style applied to blocked large media elements has been fine tuned to improve interactivity. uBO will now remember the specific media elements which were unblocked and keep them exempted from being further blocked. This would be an issue when unblocking a video and then a bit later seeking to another point in the video, in which case uBO would again block network requests for that video. --- src/js/messaging.js | 2 +- src/js/pagestore.js | 30 ++++- src/js/scriptlets/load-large-media-all.js | 36 ++---- .../load-large-media-interactive.js | 121 +++++++++++------- src/js/traffic.js | 2 +- 5 files changed, 114 insertions(+), 77 deletions(-) diff --git a/src/js/messaging.js b/src/js/messaging.js index 44c4e810fdfdc..806845c7cf4be 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -1641,7 +1641,7 @@ const onMessage = function(request, sender, callback) { case 'temporarilyAllowLargeMediaElement': if ( pageStore !== null ) { - pageStore.allowLargeMediaElementsUntil = Date.now() + 2000; + pageStore.allowLargeMediaElementsUntil = Date.now() + 5000; } break; diff --git a/src/js/pagestore.js b/src/js/pagestore.js index 7301f992b16c8..ad80d1ae06045 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -244,7 +244,7 @@ const PageStore = class { typeof this.allowLargeMediaElementsUntil !== 'number' || tabContext.rootHostname !== this.tabHostname ) { - this.allowLargeMediaElementsUntil = 0; + this.allowLargeMediaElementsUntil = Date.now(); } this.tabHostname = tabContext.rootHostname; @@ -260,6 +260,7 @@ const PageStore = class { this.largeMediaCount = 0; this.largeMediaTimer = null; this.internalRedirectionCount = 0; + this.allowLargeMediaElementsRegex = undefined; this.extraData.clear(); this.frameAddCount = 0; @@ -339,7 +340,8 @@ const PageStore = class { this.rawURL = ''; this.hostnameToCountMap = null; this.netFilteringCache.empty(); - this.allowLargeMediaElementsUntil = 0; + this.allowLargeMediaElementsUntil = Date.now(); + this.allowLargeMediaElementsRegex = undefined; if ( this.largeMediaTimer !== null ) { clearTimeout(this.largeMediaTimer); this.largeMediaTimer = null; @@ -438,7 +440,12 @@ const PageStore = class { temporarilyAllowLargeMediaElements(state) { this.largeMediaCount = 0; µb.contextMenu.update(this.tabId); - this.allowLargeMediaElementsUntil = state ? Date.now() + 86400000 : 0; + if ( state ) { + this.allowLargeMediaElementsUntil = 0; + this.allowLargeMediaElementsRegex = undefined; + } else { + this.allowLargeMediaElementsUntil = Date.now(); + } µb.scriptlets.injectDeep(this.tabId, 'load-large-media-all'); } @@ -704,7 +711,23 @@ const PageStore = class { filterLargeMediaElement(fctxt, size) { fctxt.filter = undefined; + if ( this.allowLargeMediaElementsUntil === 0 ) { + return 0; + } + // Disregard large media elements previously allowed: for example, to + // seek inside a previously allowed audio/video. + if ( + this.allowLargeMediaElementsRegex instanceof RegExp && + this.allowLargeMediaElementsRegex.test(fctxt.url) + ) { + return 0; + } if ( Date.now() < this.allowLargeMediaElementsUntil ) { + const sources = this.allowLargeMediaElementsRegex instanceof RegExp + ? [ this.allowLargeMediaElementsRegex.source ] + : []; + sources.push('^' + µb.escapeRegex(fctxt.url)); + this.allowLargeMediaElementsRegex = new RegExp(sources.join('|')); return 0; } if ( @@ -713,6 +736,7 @@ const PageStore = class { fctxt.getTabHostname() ) !== true ) { + this.allowLargeMediaElementsUntil = 0; return 0; } if ( (size >>> 10) < µb.userSettings.largeMediaSize ) { diff --git a/src/js/scriptlets/load-large-media-all.js b/src/js/scriptlets/load-large-media-all.js index a6d71734ae873..943706d28fc46 100644 --- a/src/js/scriptlets/load-large-media-all.js +++ b/src/js/scriptlets/load-large-media-all.js @@ -19,48 +19,36 @@ Home: https://github.com/gorhill/uBlock */ +'use strict'; + /******************************************************************************/ -(function() { - -'use strict'; +(( ) => { /******************************************************************************/ // For all media resources which have failed to load, trigger a reload. -var elems, i, elem, src; - //