diff --git a/README.md b/README.md index d573395a5..7e9681459 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ * [Release History](#release-history) * [Wiki](https://github.com/gorhill/uBlock/wiki) -# ![Build](https://travis-ci.org/gorhill/uBlock.svg?branch=master) +# [![Build Status](https://travis-ci.org/gorhill/uBlock.svg?branch=master)](https://travis-ci.org/gorhill/uBlock) ## Philosophy @@ -91,13 +91,9 @@ Install from [Firefox Add-ons homepage](https://addons.mozilla.org/en-US/firefox #### Safari -##### 8.0 or newer only +Install the latest µBlock for Safari [from its homepage](https://chrismatic.io/ublock/), or a potentially-outdated version from the [Safari Extension Gallery](https://extensions.apple.com/details/?id=net.gorhill.uBlock-96G4BAKDQ9). -You can get and install the latest µBlock for Safari **[right here](https://chrismatic.io/ublock/)**. - -µBlock is also available on the [Safari Extension Gallery](https://extensions.apple.com/details/?id=net.gorhill.uBlock-96G4BAKDQ9), although that's not guaranteed to be the latest version. - -Safari versions prior to 8.0 have a bug triggering a crash during µBlock installation. It's not recommended that you attempt to install µBlock on them (*if you must, do it at your own risk*). +Safari 6.1 and later (developed on Safari 8/Yosemite; tested on 6.1/Mountain Lion and 7/Mavericks). #### Note for all browsers diff --git a/assets/checksums.txt b/assets/checksums.txt index 56753b91a..36b93abe5 100644 --- a/assets/checksums.txt +++ b/assets/checksums.txt @@ -1,5 +1,5 @@ 59371e23b383053da7cd2e8d31d4ccf7 assets/ublock/privacy.txt -227044014eb0d8f40ab1be72538c68fd assets/ublock/filters.txt +42a552919bf86d9e73a963c401b18423 assets/ublock/filters.txt dcf3e05bae803343c9d632f0baf8bedd assets/ublock/mirror-candidates.txt 96e088c2dbb8759e046d2a44ed375000 assets/ublock/filter-lists.json 132b3ecc9da8a68c3faf740c00af734b assets/thirdparties/adblock-plus-japanese-filter.googlecode.com/hg/abp_jp.txt diff --git a/assets/ublock/filters.txt b/assets/ublock/filters.txt index 92898aa4a..f32d92574 100644 --- a/assets/ublock/filters.txt +++ b/assets/ublock/filters.txt @@ -303,8 +303,9 @@ deviantart.com##.dp-ad-chrome.dp-ad-visible @@||2o7.net^$domain=totaljobs.com # https://github.com/gorhill/uBlock/issues/822 +# https://github.com/gorhill/uBlock/issues/940 # To counter `google-analytics.com` in Dan Pollock's, hpHosts, MVPS, Peter Lowe's -@@||google-analytics.com^$domain=musixmatch.com +@@||google-analytics.com^$domain=musixmatch.com|bikstok.sonymusicshop.dk # https://github.com/gorhill/uBlock/issues/841 # To counter `quantcast.com` in hpHosts, Peter Lowe's @@ -313,3 +314,21 @@ deviantart.com##.dp-ad-chrome.dp-ad-visible # Chrome store feedback: "on gaana.com it blocks the site" # To counter `_social_tracking.` in EasyPrivacy @@||css5.gaanacdn.com/minify-*/min/?$script + +# http://support.getadblock.com/discussions/problems/73955-specific-web-site-causes-thousands-infinite-blocks-locks-up-chrome +||www.notempire.com/js/gridview$script + +# https://github.com/gorhill/uBlock/issues/919 +@@||s.youtube.com/api/stats/playback?$image,object-subrequest + +# https://twitter.com/Urre/status/572742363069714432 +# To counter `/keen.min.js` in EasyPrivacy +@@||keen.github.io/*/keen.min.js$domain=keen.github.io + +# Feedback from Chrome store: "videos dont work on this site" +# http://www.okgoals.com/match-highlights-1425491618---41 +# To counter `intergi.com` in Peter Lowe's +@@||cdn.phoenix.intergi.com^$domain=okgoals.com + +# https://github.com/gorhill/uBlock/issues/951 +answers.yahoo.com###ya-center-rail > [id^="ya-q-"][id$="-textads"] diff --git a/dist/description/description-da.txt b/dist/description/description-da.txt index 665f8932f..b7537f70c 100644 --- a/dist/description/description-da.txt +++ b/dist/description/description-da.txt @@ -1,21 +1,21 @@ -En effektiv blocker: let på hukommelse og CPU fodaftryk, og endnu kan indlæse og håndhæve tusindvis flere filtre end andre populære blokkere derude. +En effektiv blocker: let på hukommelse og CPU forbrug,. Kan indlæse og anvende tusindvis af flere filtre end andre populære blockere derude. -Illustreret oversigt over dens effektivitet: https://github.com/gorhill/uBlock/wiki/%C2%B5Block-vs.-ABP :-Efficiency-compared +Illustreret oversigt over effektiviteten: https://github.com/gorhill/uBlock/wiki/%C2%B5Block-vs.-ABP :-Efficiency-compared -Brug: Den Store power knap i pop-up-vinduet er til permanent deaktivere/aktivere µBlock for det aktuelle websted. Det gælder kun for det aktuelle websted , det er ikke en global afbryderknap. +Anvendelse: Den Store power knap i pop-up-vinduet kan permanent deaktivere/aktivere µBlock på det aktuelle websted. Dette gælder kun for det aktuelle websted, det er ikke en global afbryderknap. *** -Fleksibel, det er mere end en "ad blocker": det kan også læse og oprette filtre fra hosts-filer. +Fleksibel, det er mere end en "ad blocker": den kan også læse og oprette filtre fra hosts-filer. -Ud af boksen, er disse lister over filtre indlæses og håndhævet: +Fra starten af er disse lister over filtre indlæst og anvendt: - EasyList - Peter Lowe’s Ad server list - EasyPrivacy - Malware domains -Flere lister er tilgængelige for dig at vælge når du ønsker det: +Flere lister er tilgængelige hvis du ønsker det: - Fanboy’s Enhanced Tracking List - Dan Pollock’s hosts file @@ -24,26 +24,26 @@ Flere lister er tilgængelige for dig at vælge når du ønsker det: - Spam404 - Osv. -Selvfølgelig, jo flere aktive filtre mere jo højere hukommelse fodtryk. Endnu, selv efter at tilføje Fanboys to ekstra lister, Hphosts's annonce og tracking servere, µBlock stadig har en ringere hukommelse footprint end andre meget populære blokkere derude. +Selvfølgelig vil flere aktive filtre betyde højere hukommelsesforbrug. Selv efter tilføjelse af Fanboys to ekstra lister, og hpHosts’s Ad and tracking server, har µBlock stadig et lavere hukommelsesforbrug end andre blockere derude. -Desuden være opmærksom på at vælge nogle af disse ekstra lister kan føre til højere sandsynlighed for webstedet brud - især de lister, der normalt anvendes som host-filel. +Vær desuden opmærksom på, at hvis du vælger nogle af disse ekstra lister kan det føre til højere sandsynlighed for, at webstedet bliver vist forkert - især de lister der normalt anvendes som hosts-fil. *** -Uden de forudindstillede lister over filtre er denne udvidelse intet. Så hvis du nogensinde virkelig ønsker at bidrage med noget, tænk på de mennesker, der arbejder hårdt for at vedligeholde filterlister, du bruger, som blev stillet til rådighed til brug af alle gratis. +Uden de forudindstillede lister med filtre er denne udvidelse intet. Hvis du nogensinde virkelig ønsker at bidrage med noget, så tænk på de mennesker der arbejder hårdt for at vedligeholde de filterlister du bruger, som alle blev stillet gratis til rådighed for alle. *** Gratis. -Open source med offentlige licens (GPLv3) -For brugere af brugere. +Open source med offentlig licens (GPLv3) +For brugere, af brugere. Bidragydere @ Github: https://github.com/gorhill/uBlock/graphs/contributors Bidragydere @ Crowdin: https://crowdin.net/project/ublock *** -Det er ganske en tidlig version, holde dette i tankerne, når du gennemser. +Dette er en tidlig version. Hav dette i tankerne når du skriver en anmeldelse. -Projekt Ændringslog: +Projekt changelog: https://github.com/gorhill/uBlock/releases \ No newline at end of file diff --git a/dist/description/description-sv.txt b/dist/description/description-sv.txt index 3e321836c..3d61f692f 100644 --- a/dist/description/description-sv.txt +++ b/dist/description/description-sv.txt @@ -23,7 +23,7 @@ Fler filterlistor finns tillgängliga att använda om du vill: - hpHosts’s Ad and tracking servers - MVPS HOSTS - Spam404 -- m.fl. +- med flera Ju fler aktiverade filter, desto högre minnesanvändning. Men även efter att ha lagt till Fanboys två extra filterlistor och hpHosts' Ad and tracking servers så använder µBlock mindre minne än andra väldigt populära blockerare. diff --git a/doc/img/rlogger-01.png b/doc/img/rlogger-01.png new file mode 100644 index 000000000..b25e7b126 Binary files /dev/null and b/doc/img/rlogger-01.png differ diff --git a/doc/img/rlogger-02.png b/doc/img/rlogger-02.png new file mode 100644 index 000000000..8e6a1fc98 Binary files /dev/null and b/doc/img/rlogger-02.png differ diff --git a/doc/img/rlogger-03.png b/doc/img/rlogger-03.png new file mode 100644 index 000000000..fde49f26f Binary files /dev/null and b/doc/img/rlogger-03.png differ diff --git a/doc/img/rlogger-04.png b/doc/img/rlogger-04.png new file mode 100644 index 000000000..f27db5283 Binary files /dev/null and b/doc/img/rlogger-04.png differ diff --git a/doc/img/rlogger-05.png b/doc/img/rlogger-05.png new file mode 100644 index 000000000..de66d0a40 Binary files /dev/null and b/doc/img/rlogger-05.png differ diff --git a/doc/img/rlogger-06.png b/doc/img/rlogger-06.png new file mode 100644 index 000000000..cce3aaeea Binary files /dev/null and b/doc/img/rlogger-06.png differ diff --git a/platform/chromium/manifest.json b/platform/chromium/manifest.json index 51bf2e590..358c372c7 100644 --- a/platform/chromium/manifest.json +++ b/platform/chromium/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "µBlock", - "version": "0.8.9.2", + "version": "0.9.0.0", "default_locale": "en", "description": "__MSG_extShortDesc__", diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index 730ed3c1c..47d80fd26 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -738,12 +738,7 @@ vAPI.tabs.reload = function(tabId) { return; } - if ( vAPI.fennec ) { - tab.browser.reload(); - return; - } - - getOwnerWindow(tab).gBrowser.reloadTab(tab); + getBrowserForTab(tab).webNavigation.reload(0); }; /******************************************************************************/ diff --git a/platform/opera/manifest.json b/platform/opera/manifest.json index a9308a163..b87317761 100644 --- a/platform/opera/manifest.json +++ b/platform/opera/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "µBlock", - "version": "0.8.8.2", + "version": "0.8.9.1", "default_locale": "en", "description": "__MSG_extShortDesc__", diff --git a/platform/safari/vapi-background.js b/platform/safari/vapi-background.js index a1d6c0d25..6b34892af 100644 --- a/platform/safari/vapi-background.js +++ b/platform/safari/vapi-background.js @@ -42,6 +42,29 @@ /******************************************************************************/ + if(navigator.userAgent.indexOf("Safari/6") === -1) { // If we're not on at least Safari 8 + var _open = XMLHttpRequest.prototype.open; + XMLHttpRequest.prototype.open = function(m, u) { + if(u.lastIndexOf("safari-extension:", 0) === 0) { + var i = u.length, seeDot = false; + while(i --) { + if(u[i] === ".") { + seeDot = true; + } + else if(u[i] === "/") { + break; + } + } + if(seeDot === false) { + throw 'InvalidAccessError'; // Avoid crash + return; + } + } + _open.apply(this, arguments); + }; + } + /******************************************************************************/ + vAPI.app.restart = function() {}; /******************************************************************************/ diff --git a/src/_locales/ar/messages.json b/src/_locales/ar/messages.json index ac3cc935a..08692c3ba 100644 --- a/src/_locales/ar/messages.json +++ b/src/_locales/ar/messages.json @@ -235,6 +235,18 @@ "message":"تفعيل الخصائص التجريبية (حول<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"الذاكرة المستخدمة: {{value}} بايت", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"آخر استيراد:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"آخر تصدير:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} من فلاتر الشبكه + {{cosmeticFilterCount}} فلاتر تجميليه:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -352,7 +364,7 @@ "description":"This will remove all temporary rules" }, "rulesCommit":{ - "message":"حفظ", + "message":"تعليق", "description":"This will persist temporary rules" }, "rulesEdit":{ @@ -451,6 +463,14 @@ "message":"خلف الكواليس", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"فلتر سجل الإدخالات", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"العدد الأقصى للإدخالات في السجلات", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"سجل التغيير", "description":"English: Change log" diff --git a/src/_locales/bg/messages.json b/src/_locales/bg/messages.json index 75a49b107..4239d2b25 100644 --- a/src/_locales/bg/messages.json +++ b/src/_locales/bg/messages.json @@ -192,11 +192,11 @@ "description":"English: Create" }, "pickerPick":{ - "message":"Избиране", + "message":"Нов избор", "description":"English: Pick" }, "pickerQuit":{ - "message":"Изход", + "message":"Отказ", "description":"English: Quit" }, "pickerNetFilters":{ @@ -235,6 +235,18 @@ "message":"Разрешаване на експериментални функции ( за<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Използвани за съхранение: {{value}} байта", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Последно възстановяване:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Последно резервно копие:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} мрежови филтри + {{cosmeticFilterCount}} козметични филтри от:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Скрити", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"филтриране на записи", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Максимален брой записи в дневника", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Списък с промени", "description":"English: Change log" diff --git a/src/_locales/ca/messages.json b/src/_locales/ca/messages.json index d08bc30f1..b004cfbd2 100644 --- a/src/_locales/ca/messages.json +++ b/src/_locales/ca/messages.json @@ -235,6 +235,18 @@ "message":"Habilitar funcions experimentals (Quant a<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtres de xarxa + {{cosmeticFilterCount}} filtres cosmètics de:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Peticions ocultes", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrar entrades del registre", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Nombre màxim d'entrades del registre", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Registre de canvis", "description":"English: Change log" diff --git a/src/_locales/cs/messages.json b/src/_locales/cs/messages.json index c65f2b804..484ef841b 100644 --- a/src/_locales/cs/messages.json +++ b/src/_locales/cs/messages.json @@ -235,6 +235,18 @@ "message":"Povolit experimentální funkce (co to je?<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Prostoru využito: {{value}} bajtů", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Poslední obnova:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Poslední záloha:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} síťových filtrů + {{cosmeticFilterCount}} kosmetických filtrů z:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Za oponou", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrovat záznamy", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximální počet záznamů", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Change log", "description":"English: Change log" diff --git a/src/_locales/da/messages.json b/src/_locales/da/messages.json index 0c819ae7d..45237ea7c 100644 --- a/src/_locales/da/messages.json +++ b/src/_locales/da/messages.json @@ -180,7 +180,7 @@ "description":"" }, "popupHitDomainCountPrompt":{ - "message":"Tilsluttede domæner", + "message":"Forbundne domæner", "description":"appears in popup" }, "popupHitDomainCount":{ @@ -235,6 +235,18 @@ "message":"Slå eksperimentielle funktioner til (Om<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} netværksfiltre + {{cosmeticFilterCount}} kosmetiske filtre fra:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -380,7 +392,7 @@ "description":"default file name to use" }, "rulesHint":{ - "message":"Liste af dine dynamiske filtreringsregler.", + "message":"Liste over dine dynamiske filtreringsregler.", "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ @@ -451,6 +463,14 @@ "message":"Bag kulisserne", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"Filtrér elementer i log", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maksimalt antal elementer i log", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Changelog", "description":"English: Change log" diff --git a/src/_locales/de/messages.json b/src/_locales/de/messages.json index 65d54500c..bfdf08990 100644 --- a/src/_locales/de/messages.json +++ b/src/_locales/de/messages.json @@ -235,6 +235,18 @@ "message":"Aktiviere experimentelle Features (About<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Verwendeter Speicherplatz: {{value}} Bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Letzte Wiederherstellung:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Letztes Backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} Netzwerkfilter + {{cosmeticFilterCount}} kosmetische Filter von:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Hintergrundanfragen", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"Protokoll-Einträge filtern", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximale Anzahl an Protokoll-Einträgen", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Änderungsprotokoll", "description":"English: Change log" diff --git a/src/_locales/el/messages.json b/src/_locales/el/messages.json index d64787fd1..fa6bf1663 100644 --- a/src/_locales/el/messages.json +++ b/src/_locales/el/messages.json @@ -235,6 +235,18 @@ "message":"Ενεργοποιήση πειραματικών χαρακτηριστικών (Πληροφορίες<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} φίλτρα δικτύου+ {{cosmeticFilterCount}} κοσμητικά φίλτρα από:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filter log entries", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Change log", "description":"English: Change log" diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 4c8e6a015..cd559e4ae 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -35,10 +35,6 @@ "message":"µBlock — Network request log", "description":"Title for the network request log window" }, - "statsFilterPrompt":{ - "message":"filter log entries", - "description": "English: filter log entries" - }, "aboutPageName":{ "message":"About", "description":"appears as tab name in dashboard" @@ -239,6 +235,18 @@ "message":"Enable experimental features (About<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -455,6 +463,14 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filter log entries", + "description": "English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Change log", "description":"English: Change log" diff --git a/src/_locales/es/messages.json b/src/_locales/es/messages.json index e54bd66b6..e62f3797a 100644 --- a/src/_locales/es/messages.json +++ b/src/_locales/es/messages.json @@ -235,6 +235,18 @@ "message":"Habilitar funciones experimentales (Acerca de<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Almacenamiento usado: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Última restauración:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Último respaldo:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtros de red y {{cosmeticFilterCount}} filtros cosméticos de:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,8 +463,16 @@ "message":"Peticiones ocultas", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrar entradas del registro", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Cantidad máxima de entradas del registro", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ - "message":"Cambios", + "message":"Registro de cambios", "description":"English: Change log" }, "aboutWiki":{ @@ -484,7 +504,7 @@ "description":"English: Reset to default settings..." }, "aboutRestoreDataConfirm":{ - "message":"Toda la configuración se sobrescribirá utilizando datos respaldados {{time}} y µBlock se reiniciará. \n\n¿Sobrescribir toda la configuración existente utilizando datos de la copia de seguridad?", + "message":"Toda la configuración se sobrescribirá utilizando datos respaldados en {{time}} y µBlock se reiniciará. \n\n¿Sobrescribir toda la configuración existente utilizando datos de la copia de seguridad?", "description":"Message asking user to confirm restore" }, "aboutRestoreDataError":{ diff --git a/src/_locales/et/messages.json b/src/_locales/et/messages.json index 791bda083..9c4573d16 100644 --- a/src/_locales/et/messages.json +++ b/src/_locales/et/messages.json @@ -235,6 +235,18 @@ "message":"Luba katselised funktsioonid (teave<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Mahtu kasutatud: {{value}} baiti", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Viimane taastus:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Viimane varundus:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} võrgufiltrit + {{cosmeticFilterCount}} ilufiltrit:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Telgitagus", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtreeri logikirjeid", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maksimaalne logikirjete arv", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Muudatuste logi", "description":"English: Change log" diff --git a/src/_locales/fa/messages.json b/src/_locales/fa/messages.json index de410d373..be66762b2 100644 --- a/src/_locales/fa/messages.json +++ b/src/_locales/fa/messages.json @@ -235,6 +235,18 @@ "message":"فعال کردن ویژگی های آزمایشی ( درباره<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"فضای مصرفی: {{value}} بایت", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"آخرین بازیابی:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"آخرین پشتیبانی:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} فیلتر های شبکه + {{cosmeticFilterCount}} فرم های فیلتر انتخابی:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"پشت صحنه", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"فیلتر کردن مطالب لاگ", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"بیشترین تعداد مطالب لاگ", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"تغییرات اخیر", "description":"English: Change log" @@ -500,7 +520,7 @@ "description":"English: Network error: unable to connect to {{url}}" }, "dummy":{ - "message":"This entry must be the last one", + "message":"این باید آخرین مطلب باشد", "description":"so we dont need to deal with comma for last entry" } } \ No newline at end of file diff --git a/src/_locales/fi/messages.json b/src/_locales/fi/messages.json index 51e26f6e6..8f99a5590 100644 --- a/src/_locales/fi/messages.json +++ b/src/_locales/fi/messages.json @@ -235,6 +235,18 @@ "message":"Salli kokeilulliset toiminnot (Tietoa<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filter log entries", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Muutosloki", "description":"English: Change log" diff --git a/src/_locales/fil/messages.json b/src/_locales/fil/messages.json index c82f6afbb..fd255a4d6 100644 --- a/src/_locales/fil/messages.json +++ b/src/_locales/fil/messages.json @@ -235,6 +235,18 @@ "message":"Enable experimental features (About<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filter log entries", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Change log", "description":"English: Change log" diff --git a/src/_locales/fr/messages.json b/src/_locales/fr/messages.json index bad46620c..8ca19b006 100644 --- a/src/_locales/fr/messages.json +++ b/src/_locales/fr/messages.json @@ -235,6 +235,18 @@ "message":"Activer les fonctionnalités expérimentales (En savoir plus<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Stockage utilisé : {{value}} octet(s)", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Date de la dernière restauration :", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Date de la dernière sauvegarde :", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtre(s) réseau et {{cosmeticFilterCount}} filtre(s) esthétique(s) actuellement en action :", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Requêtes en coulisses", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"Filtrer les entrées du journal", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Nombre maximum d'entrées à conserver dans le journal", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Journal des changements (en Anglais)", "description":"English: Change log" diff --git a/src/_locales/he/messages.json b/src/_locales/he/messages.json index 750e9ebee..977dc3fcb 100644 --- a/src/_locales/he/messages.json +++ b/src/_locales/he/messages.json @@ -235,6 +235,18 @@ "message":"אפשר תכונות ניסיוניות (אודות<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"אחסון בשימוש: {{value}} בתים", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"שחזור אחרון:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"גיבוי אחרון:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} מסנני רשת + {{cosmeticFilterCount}} מסננים קוסמטיים מתוך:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"מאחורי הקלעים", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"סנן רשומות", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"מספר רשומות מקסימליות", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"רשימת שינויים", "description":"English: Change log" diff --git a/src/_locales/hi/messages.json b/src/_locales/hi/messages.json index a76f54cc5..2dc5f2958 100644 --- a/src/_locales/hi/messages.json +++ b/src/_locales/hi/messages.json @@ -235,6 +235,18 @@ "message":"Enable experimental features (About<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"पर्दे के पीछे", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filter log entries", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Change log", "description":"English: Change log" diff --git a/src/_locales/hr/messages.json b/src/_locales/hr/messages.json index 51c30fa79..570c78d13 100644 --- a/src/_locales/hr/messages.json +++ b/src/_locales/hr/messages.json @@ -235,6 +235,18 @@ "message":"Omogućiti eksperimentalne mogućnosti (O mogućnostima<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Korišteno prostora: {{value}} bajtova", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Posljednji povratak na prijašnje:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Posljednja sigurnosna kopija:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} mrežni\/ih filter\/a + {{cosmeticFilterCount}} estetski\/ih filter\/a iz:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Iza scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrirajte zabilješke", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Makismalan broj zabilješki", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Popis promjena", "description":"English: Change log" diff --git a/src/_locales/hu/messages.json b/src/_locales/hu/messages.json index 097e606b8..667ce208b 100644 --- a/src/_locales/hu/messages.json +++ b/src/_locales/hu/messages.json @@ -184,7 +184,7 @@ "description":"appears in popup" }, "popupHitDomainCount":{ - "message":"{{count}} a(z) {{total}}-böl", + "message":"{{count}}, összesen: {{total}}", "description":"appears in popup" }, "pickerCreate":{ @@ -235,6 +235,18 @@ "message":"Kísérleti funkciók engedélyezése", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Tárolóhely használva: {{value}} byte", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Utolsó biztonsági mentés visszaállitása:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Utolsó biztonsági mentés:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} net-szűrők + {{cosmeticFilterCount}} kozmetikai szűrők:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Hálózati forgalom a háttérben", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"Naplóbejegyzések szűrése", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum naplóbejegyzések száma", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Változások listája", "description":"English: Change log" diff --git a/src/_locales/id/messages.json b/src/_locales/id/messages.json index 68b56d8ca..e44b00d5c 100644 --- a/src/_locales/id/messages.json +++ b/src/_locales/id/messages.json @@ -235,6 +235,18 @@ "message":"Aktifkan fitur eksperimental (Tentang<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filter jaringan + {{cosmeticFilterCount}} filter tampilan dari:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Di balik layar", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"saring entri catatan", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Jumlah maximum entri catatan", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Catatan perubahan", "description":"English: Change log" diff --git a/src/_locales/it/messages.json b/src/_locales/it/messages.json index 906fbdc60..b4751b010 100644 --- a/src/_locales/it/messages.json +++ b/src/_locales/it/messages.json @@ -235,6 +235,18 @@ "message":"Attiva funzionalità sperimentali (Informazioni<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Spazio utilizzato: {{value}} byte", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Ultimo ripristino:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Ultimo backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtri di rete + {{cosmeticFilterCount}} filtri cosmetici da:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Dietro le quinte", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtra voci del registro", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Numero massimo di voci del registro", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Change log", "description":"English: Change log" diff --git a/src/_locales/ja/messages.json b/src/_locales/ja/messages.json index 33b35e4a0..e6ba7f93e 100644 --- a/src/_locales/ja/messages.json +++ b/src/_locales/ja/messages.json @@ -235,6 +235,18 @@ "message":"実験的な機能を有効にする (About<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"使用中のストレージ: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"最後の復元:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"最後のバックアップ:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}}ネットワークフィルタ+{{cosmeticFilterCount}}コスメチックフィルタ:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"絞り込み", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"バージョン更新履歴 (Change log)", "description":"English: Change log" diff --git a/src/_locales/ko/messages.json b/src/_locales/ko/messages.json index 5d6a8845c..ef8bc6e8f 100644 --- a/src/_locales/ko/messages.json +++ b/src/_locales/ko/messages.json @@ -235,6 +235,18 @@ "message":"실험 기능 활성화 (자세히<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"스토리지 사용량: {{value}} 바이트", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"최근 복원:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"최근 백업:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} 네트워크 필터 + {{cosmeticFilterCount}} 시각적 필터:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"숨겨진 구성 요소", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"필터 로그 항목", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"로그 항목의 최대 갯수", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"변경사항", "description":"English: Change log" diff --git a/src/_locales/lv/messages.json b/src/_locales/lv/messages.json index 22227c578..77dd13e2f 100644 --- a/src/_locales/lv/messages.json +++ b/src/_locales/lv/messages.json @@ -235,6 +235,18 @@ "message":"Iespējot eksperimentālas iespējas (Sīkāk šeit<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} tīkla filtri + {{cosmeticFilterCount}} kosmētikas filtri no:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Aizkulisēs", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"žurnāla ierakstu filtrs", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Žurnāla ierakstu maksimālais skaits", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Izmaiņu žurnāls", "description":"English: Change log" diff --git a/src/_locales/mr/messages.json b/src/_locales/mr/messages.json index 45ee80ee8..63e98c10b 100644 --- a/src/_locales/mr/messages.json +++ b/src/_locales/mr/messages.json @@ -235,6 +235,18 @@ "message":"प्रायोगिक वैशिष्ट्ये सक्षम करा", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} नेटवर्क फिल्टर + {{cosmeticFilterCount}} उटणे फिल्टर :", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filter log entries", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"बदल नोंदी", "description":"English: Change log" diff --git a/src/_locales/nb/messages.json b/src/_locales/nb/messages.json index b02ce3e7a..12c2498d5 100644 --- a/src/_locales/nb/messages.json +++ b/src/_locales/nb/messages.json @@ -235,6 +235,18 @@ "message":"Aktiver eksperimentelle funksjoner (Info<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} nettverksfiltre + {{cosmeticFilterCount}} kosmetiske filtre fra:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Bak kulissene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filter log entries", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum number of log entries", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Endringslogg", "description":"English: Change log" diff --git a/src/_locales/nl/messages.json b/src/_locales/nl/messages.json index 2a0359173..83ad9cf29 100644 --- a/src/_locales/nl/messages.json +++ b/src/_locales/nl/messages.json @@ -32,7 +32,7 @@ "description":"appears as tab name in dashboard" }, "statsPageName":{ - "message":"µBlock — Log van netwerkverzoeken", + "message":"µBlock — Logboek van netwerkverzoeken", "description":"Title for the network request log window" }, "aboutPageName":{ @@ -68,7 +68,7 @@ "description":"English: Enter element picker mode" }, "popupTipLog":{ - "message":"Ga naar verzoekenlog", + "message":"Naar verzoekenlogboek gaan", "description":"English: Go to request log" }, "popupSiteInlineScriptEnabled":{ @@ -235,6 +235,18 @@ "message":"Experimentele functies inschakelen (Over<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Gebruikte opslagruimte: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Laatste herstel:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Laatste back-up:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} netwerkfilters + {{cosmeticFilterCount}} cosmetische filters van:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Achter de schermen", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"logboekitems filteren", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximum aantal logboekitems", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Veranderingenlogboek", "description":"English: Change log" diff --git a/src/_locales/pl/messages.json b/src/_locales/pl/messages.json index 6fa04b2bf..25660479a 100644 --- a/src/_locales/pl/messages.json +++ b/src/_locales/pl/messages.json @@ -235,6 +235,18 @@ "message":"Włącz funkcje eksperymentalne (Więcej<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Użycie pamięci masowej: {{value}} bajtów", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Ostatnie przywrócenie:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Ostatnia kopia zapasowa:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtry sieciowe + {{cosmeticFilterCount}} filtry kosmetyczne z:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Za kulisami", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtruj wpisy w logu", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maksymalna liczba wpisów do wyświetlenia", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Dziennik zmian", "description":"English: Change log" diff --git a/src/_locales/pt_BR/messages.json b/src/_locales/pt_BR/messages.json index c83a80cf9..43fe76e59 100644 --- a/src/_locales/pt_BR/messages.json +++ b/src/_locales/pt_BR/messages.json @@ -235,6 +235,18 @@ "message":"Ativar os recursos experimentais (Sobre<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Armazenamento usado: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Última restauração:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Último backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtros de rede + {{cosmeticFilterCount}} filtros cosméticos de:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Por trás da cena", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrar entradas de registro", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Número máximo de entradas de registro", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Registro de alterações", "description":"English: Change log" diff --git a/src/_locales/pt_PT/messages.json b/src/_locales/pt_PT/messages.json index 512288ccc..f0e45279d 100644 --- a/src/_locales/pt_PT/messages.json +++ b/src/_locales/pt_PT/messages.json @@ -8,7 +8,7 @@ "description":"this will be in the chrome web store: must be 132 characters or less" }, "dashboardName":{ - "message":"µBlock — Painel de Controlo", + "message":"µBlock — Painel de controlo", "description":"English: µBlock — Dashboard" }, "settingsPageName":{ @@ -40,7 +40,7 @@ "description":"appears as tab name in dashboard" }, "popupPowerSwitchInfo":{ - "message":"Clique: desativar\/ativar o µBlock para este site.\n\nCtrl+clique: desativar o µBlock apenas nesta página.", + "message":"Clique: desativar\/ativar o µBlock para este sítio web.\n\nCtrl+clique: desativar o µBlock apenas nesta página.", "description":"English: Click: disable\/enable µBlock for this site.\n\nCtrl+click: disable µBlock only on this page." }, "popupBlockedRequestPrompt":{ @@ -216,7 +216,7 @@ "description":"English: Block element" }, "settingsCollapseBlockedPrompt":{ - "message":"Ocultar espaços ocupados de elementos bloqueados", + "message":"Ocultar espaços ocupados por elementos bloqueados", "description":"English: Hide placeholders of blocked elements" }, "settingsIconBadgePrompt":{ @@ -235,6 +235,18 @@ "message":"Ativar funções experimentais (Sobre<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Armazenamento utilizado: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Último restauro:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Último backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtros de rede + {{cosmeticFilterCount}} filtros cosméticos a partir de:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Bastidores", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrar entradas de registo", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Número máximo de entradas de registo", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Registo de alterações", "description":"English: Change log" diff --git a/src/_locales/ro/messages.json b/src/_locales/ro/messages.json index 52c7e1d33..1503d120d 100644 --- a/src/_locales/ro/messages.json +++ b/src/_locales/ro/messages.json @@ -235,6 +235,18 @@ "message":"Activează funcțiile experimentale (Despre<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Spațiu de stocare utilizat: {{value}} octeți", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Ultima restaurare:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Ultima copie de siguranță:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtre rețea + {{cosmeticFilterCount}} filtre vizuale din:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"În spatele scenei", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrează intrările din jurnal", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Numărul maxim de intrări în jurnal", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Jurnalul de modificări", "description":"English: Change log" diff --git a/src/_locales/ru/messages.json b/src/_locales/ru/messages.json index 9fefe1a2b..6580fde73 100644 --- a/src/_locales/ru/messages.json +++ b/src/_locales/ru/messages.json @@ -235,6 +235,18 @@ "message":"Включить экспериментальные возможности (Подробнее<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Используется {{value}} байт", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Последнее восстановление:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Последняя резервная копия:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} сетевых фильтров + {{cosmeticFilterCount}} косметических фильтров из:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"За кулисами", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"фильтр записей в журнале", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Максимальное количество записей в журнале", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Список изменений", "description":"English: Change log" diff --git a/src/_locales/sq/messages.json b/src/_locales/sq/messages.json index 843662992..5314020d4 100644 --- a/src/_locales/sq/messages.json +++ b/src/_locales/sq/messages.json @@ -235,6 +235,18 @@ "message":"Aktivizoj veçoritë eksperimentale (Info<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Hapësira e përdorur: {{value}} bajt", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Rindërtimi i fundit:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Kopjimi i fundit:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} filtra të rrjetit + {{cosmeticFilterCount}} filtra kozmetikë nga:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Në prapaskenë", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtroni elementet e ditarit", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Numri maksimal i elementeve të ditarit", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Ditari i ndryshimeve", "description":"English: Change log" diff --git a/src/_locales/sv/messages.json b/src/_locales/sv/messages.json index 33ce3dfbe..d73294c16 100644 --- a/src/_locales/sv/messages.json +++ b/src/_locales/sv/messages.json @@ -160,7 +160,7 @@ "description":"" }, "popup3pAnyRulePrompt":{ - "message":"Tredjeparts", + "message":"Tredjepart", "description":"" }, "popupInlineScriptRulePrompt":{ @@ -232,9 +232,21 @@ "description":"English: " }, "settingsExperimentalPrompt":{ - "message":"Aktivera experimentella funktioner", + "message":"Aktivera experimentella funktioner (Om<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Använt utrymme: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Senaste återställning:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Senaste säkerhetskopia:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} nätverksfilter + {{cosmeticFilterCount}} kosmetiska filter från:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -372,7 +384,7 @@ "description":"" }, "rulesExport":{ - "message":"Exportera till fil...", + "message":"Exportera till fil", "description":"" }, "rulesDefaultFileName":{ @@ -451,6 +463,14 @@ "message":"Under huven", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"filtrera loggposter", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maximalt antal loggposter", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Ändringslogg", "description":"English: Change log" diff --git a/src/_locales/tr/messages.json b/src/_locales/tr/messages.json index 966c3c177..5ce6bdfe0 100644 --- a/src/_locales/tr/messages.json +++ b/src/_locales/tr/messages.json @@ -235,6 +235,18 @@ "message":"Test aşamasındaki özellikleri etkinleştir (Hakkında<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Storage used: {{value}} bytes", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Last restore:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Last backup:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} ağ filtresi + {{cosmeticFilterCount}} kozmetik filtre:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Sahne arkası", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"Log kayıtlarını filtrele", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Maksimum log kayıt sayısı", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Değişiklikler", "description":"English: Change log" diff --git a/src/_locales/uk/messages.json b/src/_locales/uk/messages.json index 8e5bcf272..378910a8c 100644 --- a/src/_locales/uk/messages.json +++ b/src/_locales/uk/messages.json @@ -235,6 +235,18 @@ "message":"Ввімкнути експериментальні функції (Детальніше тут<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Використано: {{value}} байт", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Востаннє відновлено:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Остання резервна копія:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} мережевих фільтрів + {{cosmeticFilterCount}} косметичних фільтрів з:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -348,7 +360,7 @@ "description":"header" }, "rulesRevert":{ - "message":"скасувати зміни", + "message":"Скасувати зміни", "description":"This will remove all temporary rules" }, "rulesCommit":{ @@ -451,6 +463,14 @@ "message":"За лаштунками", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"фільтр журналу записів", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Максимальна кількість записів в журналі", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Журнал змін", "description":"English: Change log" diff --git a/src/_locales/vi/messages.json b/src/_locales/vi/messages.json index 9fff30687..d4a42f29f 100644 --- a/src/_locales/vi/messages.json +++ b/src/_locales/vi/messages.json @@ -180,7 +180,7 @@ "description":"" }, "popupHitDomainCountPrompt":{ - "message":"tên miền", + "message":"tên miền đã kết nối", "description":"appears in popup" }, "popupHitDomainCount":{ @@ -235,6 +235,18 @@ "message":"Kích hoạt các tính năng thử nghiệm (Thông tin<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"Bộ nhớ đã dùng: {{value}} byte", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"Lần phục hồi trước:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"Lần sao lưu trước:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"{{netFilterCount}} bộ lọc mạng + {{cosmeticFilterCount}} bộ lọc phần tử ẩn từ:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"lọc mục ghi nhận", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"Số mục ghi nhận tối đa", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"Thay đổi", "description":"English: Change log" diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json index e76353f41..fed02fd0f 100644 --- a/src/_locales/zh_CN/messages.json +++ b/src/_locales/zh_CN/messages.json @@ -235,6 +235,18 @@ "message":"启用实验功能(关于<\/a>)", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"已用空间:{{value}} 字节", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"上次恢复:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"上次备份:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"当前使用了 {{netFilterCount}} 个 URL 过滤规则和 {{cosmeticFilterCount}} 个元素过滤规则:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -451,6 +463,14 @@ "message":"后台", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"过滤日志条目", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"日志条目最大数量", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"更新日志", "description":"English: Change log" diff --git a/src/_locales/zh_TW/messages.json b/src/_locales/zh_TW/messages.json index 8ee47cf4d..3f1d3f61e 100644 --- a/src/_locales/zh_TW/messages.json +++ b/src/_locales/zh_TW/messages.json @@ -235,6 +235,18 @@ "message":"啟用實驗性功能", "description":"English: Enable experimental features" }, + "settingsStorageUsed":{ + "message":"已使用的儲存: {{value}} 位元組", + "description":"English: Storage used: {{}} bytes" + }, + "settingsLastRestorePrompt":{ + "message":"最後的還原:", + "description":"English: Last restore:" + }, + "settingsLastBackupPrompt":{ + "message":"最後的備份:", + "description":"English: Last backup:" + }, "3pListsOfBlockedHostsPrompt":{ "message":"目前使用{{netFilterCount}} 網址過濾和{{cosmeticFilterCount}} 元素過濾規則:", "description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:" @@ -332,7 +344,7 @@ "description":"English: Export" }, "1pExportFilename":{ - "message":"ublock-自訂過濾_{{datetime}}.txt", + "message":"我的-ublock-自訂過濾_{{datetime}}.txt", "description":"English: my-ublock-static-filters_{{datetime}}.txt" }, "1pApplyChanges":{ @@ -376,7 +388,7 @@ "description":"" }, "rulesDefaultFileName":{ - "message":"ublock-自訂動態規則_{{datetime}}.txt", + "message":"我的-ublock-自訂動態規則_{{datetime}}.txt", "description":"default file name to use" }, "rulesHint":{ @@ -384,7 +396,7 @@ "description":"English: List of your dynamic filtering rules." }, "rulesFormatHint":{ - "message":"規則語法: 來源主機名稱 目標主機名稱 需求類型 行為<\/code> (說明文件<\/a>)。", + "message":"規則語法:來源主機名稱 目標主機名稱 連線請求類型 操作<\/code>(完整說明<\/a>)。", "description":"English: dynamic rule syntax and full documentation." }, "whitelistPrompt":{ @@ -400,7 +412,7 @@ "description":"English: Export" }, "whitelistExportFilename":{ - "message":"ublock-白名單_{{datetime}}.txt", + "message":"我的-ublock-白名單_{{datetime}}.txt", "description":"English: my-ublock-whitelist_{{datetime}}.txt" }, "whitelistApply":{ @@ -451,6 +463,14 @@ "message":"幕後", "description":"Pretty name for behind-the-scene network requests" }, + "logFilterPrompt":{ + "message":"過濾日誌條目", + "description":"English: filter log entries" + }, + "logMaxEntriesTip":{ + "message":"最大日誌條目數量", + "description":"Tooltip informaing that the input field is to set the maximum number of entries in the log" + }, "aboutChangelog":{ "message":"更新日誌", "description":"English: Change log" @@ -472,7 +492,7 @@ "description":"English: Backup to file" }, "aboutBackupFilename":{ - "message":"ublock-備份_{{datetime}}.txt", + "message":"我的-ublock-備份_{{datetime}}.txt", "description":"English: my-ublock-backup_{{datetime}}.txt" }, "aboutRestoreDataButton":{ diff --git a/src/css/1p-filters.css b/src/css/1p-filters.css index 267c067a3..5f71e1e66 100644 --- a/src/css/1p-filters.css +++ b/src/css/1p-filters.css @@ -8,7 +8,8 @@ div > p:last-child { box-sizing: border-box; font-size: small; height: 60vh; + text-align: left; white-space: pre; width: 100%; - text-align: left; + word-wrap: normal; } diff --git a/src/css/3p-filters.css b/src/css/3p-filters.css index 4af551674..509931a61 100644 --- a/src/css/3p-filters.css +++ b/src/css/3p-filters.css @@ -122,6 +122,7 @@ body[dir=rtl] #externalListsDiv { height: 10em; white-space: pre; width: 100%; + word-wrap: normal; } body #busyOverlay { position: fixed; diff --git a/src/css/devtool-log.css b/src/css/devtool-log.css index 5f269284f..d3ea119ab 100644 --- a/src/css/devtool-log.css +++ b/src/css/devtool-log.css @@ -37,6 +37,15 @@ body { body.filterOff #toolbar #filterButton { opacity: 0.25; } +#filterExpression.bad { + background-color: #fee; + } +#maxEntries { + margin-left: 3em; + } +input:focus { + background-color: #ffe; + } #content { margin-top: 36px; } @@ -70,6 +79,7 @@ body:not(.filterOff) #content table tr.hidden { padding: 3px 0; text-align: center; white-space: pre; + width: 1em; } #content table tr td:nth-of-type(2) { white-space: normal; diff --git a/src/css/devtools.css b/src/css/devtools.css index 4f29fb19f..44a5892fc 100644 --- a/src/css/devtools.css +++ b/src/css/devtools.css @@ -27,6 +27,9 @@ body { margin: 0 0 0 1em; vertical-align: middle; } +#pageSelector { + max-width: 80%; + } #toolbar #refresh { margin-left: 4px; } diff --git a/src/devtool-log.html b/src/devtool-log.html index 8733ee939..cd6ae644c 100644 --- a/src/devtool-log.html +++ b/src/devtool-log.html @@ -10,7 +10,8 @@
- + +
diff --git a/src/epicker.html b/src/epicker.html index 29a098f64..0d51f2690 100644 --- a/src/epicker.html +++ b/src/epicker.html @@ -121,7 +121,7 @@ svg > path:first-child { svg > path + path { stroke: #F00; stroke-width: 0.5px; - fill: rgba(255,0,0,0.25); + fill: rgba(255,31,31,0.25); } aside { background-color: rgba(255,255,255,0.9); diff --git a/src/js/background.js b/src/js/background.js index c640a3cb2..1419a43b7 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -63,6 +63,7 @@ return { externalLists: defaultExternalLists, firewallPaneMinimized: true, parseAllABPHideFilters: true, + requestLogMaxEntries: 0, showIconBadge: true }, @@ -80,15 +81,24 @@ return { localSettings: { blockedRequestCount: 0, - allowedRequestCount: 0 + allowedRequestCount: 0, }, + localSettingsModifyTime: 0, + localSettingsSaveTime: 0, // read-only systemSettings: { - compiledMagic: 'shztbfhkfjit', + compiledMagic: 'wcuwrlodqyee', selfieMagic: 'spqmeuaftfra' }, + restoreBackupSettings: { + lastRestoreFile: '', + lastRestoreTime: 0, + lastBackupFile: '', + lastBackupTime: 0 + }, + // EasyList, EasyPrivacy and many others have an 4-day update period, // as per list headers. updateAssetsEvery: 97 * oneHour, diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index 5efbeb797..3812fc478 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -364,7 +364,7 @@ var messager = vAPI.messaging.channel('contentscript-end.js'); // so we will just skip them from now on. if ( processHighHighGenericsMisses === 0 ) { injectedSelectors['{{highHighGenerics}}'] = true; - console.debug('high-high generic: apparently not needed...'); + //console.debug('high-high generic: apparently not needed...'); } return; } diff --git a/src/js/contentscript-start.js b/src/js/contentscript-start.js index e2eb6f0a2..6fba5730c 100644 --- a/src/js/contentscript-start.js +++ b/src/js/contentscript-start.js @@ -156,11 +156,12 @@ var hideElements = function(selectors) { } }; +var url = window.location.href; localMessager.send( { what: 'retrieveDomainCosmeticSelectors', - pageURL: window.location.href, - locationURL: window.location.href + pageURL: url, + locationURL: url }, filteringHandler ); diff --git a/src/js/devtool-log.js b/src/js/devtool-log.js index 621e504e1..6f2bd1918 100644 --- a/src/js/devtool-log.js +++ b/src/js/devtool-log.js @@ -37,6 +37,15 @@ var body = doc.body; var tbody = doc.querySelector('#content tbody'); var rowJunkyard = []; var reFilter = null; +var filterTargetTestResult = true; +var maxEntries = 0; + +var prettyRequestTypes = { + 'main_frame': 'doc', + 'stylesheet': 'css', + 'sub_frame': 'frame', + 'xmlhttprequest': 'xhr' +}; /******************************************************************************/ @@ -102,7 +111,7 @@ var renderLogEntry = function(entry) { var tr = createRow(); if ( entry.result.charAt(1) === 'b' ) { tr.classList.add('blocked'); - tr.cells[0].textContent = ' \u2212\u00A0'; + tr.cells[0].textContent = ' -\u00A0'; } else if ( entry.result.charAt(1) === 'a' ) { tr.classList.add('allowed'); if ( entry.result.charAt(0) === 'm' ) { @@ -110,7 +119,7 @@ var renderLogEntry = function(entry) { } tr.cells[0].textContent = ' +\u00A0'; } else { - tr.cells[0].textContent = ' '; + tr.cells[0].textContent = ''; } if ( entry.type === 'main_frame' ) { tr.classList.add('maindoc'); @@ -119,8 +128,8 @@ var renderLogEntry = function(entry) { if ( entry.result.lastIndexOf('sa', 0) === 0 ) { filterText = '@@' + filterText; } - tr.cells[1].textContent = filterText + ' '; - tr.cells[2].textContent = entry.type + ' '; + tr.cells[1].textContent = filterText + '\t'; + tr.cells[2].textContent = (prettyRequestTypes[entry.type] || entry.type) + '\t'; vAPI.insertHTML(tr.cells[3], renderURL(entry.url, entry.result)); applyFilterToRow(tr); tbody.insertBefore(tr, tbody.firstChild); @@ -141,6 +150,11 @@ var renderLogBuffer = function(buffer) { renderLogEntry(buffer[i]); } + // Prevent logger from growing infinitely and eating all memory. For + // instance someone could forget that it is left opened for some + // dynamically refreshed pages. + truncateLog(maxEntries); + var yDelta = tbody.offsetHeight - height; if ( yDelta === 0 ) { return; @@ -165,6 +179,18 @@ var renderLogBuffer = function(buffer) { /******************************************************************************/ +var truncateLog = function(size) { + if ( size === 0 ) { + size = 25000; + } + size = Math.min(size, 25000); + while ( tbody.childElementCount > size ) { + rowJunkyard.push(tbody.removeChild(tbody.lastElementChild)); + } +}; + +/******************************************************************************/ + var onBufferRead = function(buffer) { if ( Array.isArray(buffer) ) { renderLogBuffer(buffer); @@ -200,7 +226,7 @@ var reloadTab = function() { var applyFilterToRow = function(row) { var re = reFilter; - if ( re === null || re.test(row.textContent) ) { + if ( re === null || re.test(row.textContent) === filterTargetTestResult ) { row.classList.remove('hidden'); } else { row.classList.add('hidden'); @@ -219,8 +245,9 @@ var applyFilter = function() { return; } var re = reFilter; + var target = filterTargetTestResult; while ( row !== null ) { - if ( re.test(row.textContent) ) { + if ( re.test(row.textContent) === target ) { row.classList.remove('hidden'); } else { row.classList.add('hidden'); @@ -251,25 +278,45 @@ var onFilterButton = function() { /******************************************************************************/ var onFilterChanged = function() { - var filterRaw = uDom('#filterExpression').val().trim(); + var filterExpression = uDom('#filterExpression'); + var filterRaw = filterExpression.val().trim(); + // Assume good filter expression + filterExpression.removeClass('bad'); + + // Invert resultset? + filterTargetTestResult = filterRaw.charAt(0) !== '!'; + if ( filterTargetTestResult === false ) { + filterRaw = filterRaw.slice(1); + } + + // No filter if ( filterRaw === '') { reFilter = null; - unapplyFilter(); return; } + // Regex? + if ( filterRaw.length > 1 && filterRaw.charAt(0) === '/' && filterRaw.slice(-1) === '/' ) { + try { + reFilter = new RegExp(filterRaw.slice(1, -1)); + } catch (e) { + reFilter = null; + filterExpression.addClass('bad'); + } + return; + } + + // Plain filtering var filterParts = filterRaw - .replace(/^\s*-(\s+|$)/, '−\xA0') - .replace(/^\s*\\+(\s+|$)/, '\\+\xA0') - .split(/\s+/); + .replace(/^\s*-(\s+|$)/, '-\xA0 ') + .replace(/^\s*\\+(\s+|$)/, '+\xA0 ') + .split(/[ \f\n\r\t\v​]+/); var n = filterParts.length; for ( var i = 0; i < n; i++ ) { filterParts[i] = filterParts[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } reFilter = new RegExp(filterParts.join('.*\\s+.*')); - - applyFilter(); }; /******************************************************************************/ @@ -280,6 +327,7 @@ var onFilterChangedAsync = (function() { var commit = function() { timer = null; onFilterChanged(); + applyFilter(); }; var changed = function() { @@ -294,6 +342,28 @@ var onFilterChangedAsync = (function() { /******************************************************************************/ +var onMaxEntriesChanged = function() { + var raw = uDom(this).val(); + try { + maxEntries = parseInt(raw, 10); + if ( isNaN(maxEntries) ) { + maxEntries = 0; + } + } catch (e) { + maxEntries = 0; + } + + messager.send({ + what: 'userSettings', + name: 'requestLogMaxEntries', + value: maxEntries + }); + + truncateLog(maxEntries); +}; + +/******************************************************************************/ + uDom.onLoad(function() { // Extract the tab id of the page we need to pull the log var matches = window.location.search.match(/[\?&]tabId=([^&]+)/); @@ -301,12 +371,19 @@ uDom.onLoad(function() { inspectedTabId = matches[1]; } + var onSettingsReady = function(settings) { + maxEntries = settings.requestLogMaxEntries || 0; + uDom('#maxEntries').val(maxEntries || ''); + }; + messager.send({ what: 'getUserSettings' }, onSettingsReady); + readLogBuffer(); uDom('#reload').on('click', reloadTab); uDom('#clear').on('click', clearBuffer); uDom('#filterButton').on('click', onFilterButton); uDom('#filterExpression').on('input', onFilterChangedAsync); + uDom('#maxEntries').on('change', onMaxEntriesChanged); }); /******************************************************************************/ diff --git a/src/js/dynamic-net-filtering.js b/src/js/dynamic-net-filtering.js index 312cb322c..a64a44a8a 100644 --- a/src/js/dynamic-net-filtering.js +++ b/src/js/dynamic-net-filtering.js @@ -26,6 +26,8 @@ µBlock.Firewall = (function() { +'use strict'; + /******************************************************************************/ var magicId = 'chmdgxwtetgu'; @@ -148,11 +150,22 @@ Matrix.prototype.assign = function(other) { Matrix.prototype.copyRules = function(other, srcHostname, desHostnames) { var thisRules = this.rules; var otherRules = other.rules; + var ruleKey, ruleValue; // Specific types - thisRules['* *'] = otherRules['* *']; - var ruleKey = srcHostname + ' *'; - thisRules[ruleKey] = otherRules[ruleKey]; + ruleValue = otherRules['* *'] || 0; + if ( ruleValue !== 0 ) { + thisRules['* *'] = ruleValue; + } else { + delete thisRules['* *']; + } + ruleKey = srcHostname + ' *'; + ruleValue = otherRules[ruleKey] || 0; + if ( ruleValue !== 0 ) { + thisRules[ruleKey] = ruleValue; + } else { + delete thisRules[ruleKey]; + } // Specific destinations for ( var desHostname in desHostnames ) { @@ -160,9 +173,19 @@ Matrix.prototype.copyRules = function(other, srcHostname, desHostnames) { continue; } ruleKey = '* ' + desHostname; - thisRules[ruleKey] = otherRules[ruleKey]; + ruleValue = otherRules[ruleKey] || 0; + if ( ruleValue !== 0 ) { + thisRules[ruleKey] = ruleValue; + } else { + delete thisRules[ruleKey]; + } ruleKey = srcHostname + ' ' + desHostname ; - thisRules[ruleKey] = otherRules[ruleKey]; + ruleValue = otherRules[ruleKey] || 0; + if ( ruleValue !== 0 ) { + thisRules[ruleKey] = ruleValue; + } else { + delete thisRules[ruleKey]; + } } return true; diff --git a/src/js/element-picker.js b/src/js/element-picker.js index b3be0ffb4..a5f35a480 100644 --- a/src/js/element-picker.js +++ b/src/js/element-picker.js @@ -412,9 +412,9 @@ var elementsFromFilter = function(filter) { // One idea is to normalize all a[href] on the page, but for now I will // wait and see, as I prefer to refrain from tampering with the page // content if I can avoid it. - if ( filter.slice(0, 2) === '##' ) { + if ( filter.lastIndexOf('##', 0) === 0 ) { try { - out = document.querySelectorAll(filter.replace('##', '')); + out = document.querySelectorAll(filter.slice(2)); } catch (e) { } @@ -423,16 +423,47 @@ var elementsFromFilter = function(filter) { // Net filters: we need to lookup manually -- translating into a // foolproof CSS selector is just not possible - if ( filter.slice(0, 2) === '||' ) { - filter = filter.replace('||', ''); + + // https://github.com/gorhill/uBlock/issues/945 + // Transform into a regular expression, this allows the user to edit and + // insert wildcard(s) into the proposed filter + var reStr = ''; + if ( filter.length > 1 && filter.charAt(0) === '/' && filter.slice(-1) === '/' ) { + reStr = filter.slice(1, -1); } - var elems = document.querySelectorAll('iframe, img, object, embed'); + else { + var rePrefix = '', reSuffix = ''; + if ( filter.slice(0, 2) === '||' ) { + filter = filter.replace('||', ''); + } else { + if ( filter.charAt(0) === '|' ) { + rePrefix = '^'; + filter = filter.slice(1); + } + } + if ( filter.slice(-1) === '|' ) { + reSuffix = '$'; + filter = filter.slice(0, -1); + } + reStr = rePrefix + + filter.replace(/[.+?${}()|[\]\\]/g, '\\$&').replace(/[\*^]+/g, '.*') + + reSuffix; + } + var reFilter = null; + try { + reFilter = new RegExp(reStr); + } catch (e) { + return out; + } + + var props = netFilterSources; + var elems = document.querySelectorAll(Object.keys(props).join()); var i = elems.length; var elem, src; while ( i-- ) { elem = elems[i]; - src = elem[netFilterSources[elem.tagName.toLowerCase()]]; - if ( src && src.indexOf(filter) !== -1 ) { + src = elem[props[elem.tagName.toLowerCase()]]; + if ( src && reFilter.test(src) ) { out.push(elem); } } @@ -452,14 +483,15 @@ var userFilterFromCandidate = function() { } // Cosmetic filter? - if ( v.slice(0, 2) === '##' ) { + if ( v.lastIndexOf('##', 0) === 0 ) { return window.location.hostname + v; } // If domain included in filter, no need for domain option - if ( v.slice(0, 2) === '||' ) { + if ( v.lastIndexOf('||', 0) === 0 ) { return v; } + // Assume net filter return v + '$domain=' + window.location.hostname; }; @@ -529,7 +561,11 @@ var onDialogClicked = function(ev) { else if ( ev.target.id === 'create' ) { var filter = userFilterFromCandidate(); if ( filter ) { - localMessager.send({ what: 'createUserFilter', filters: filter }); + var d = new Date(); + localMessager.send({ + what: 'createUserFilter', + filters: '! ' + d.toLocaleString() + ' ' + window.location.href + '\n' + filter, + }); removeElements(elementsFromFilter(taCandidate.value)); stopPicker(); } diff --git a/src/js/i18n.js b/src/js/i18n.js index 95304f51d..231a1dbf5 100644 --- a/src/js/i18n.js +++ b/src/js/i18n.js @@ -37,10 +37,7 @@ uDom.onLoad(function() { } }); uDom('[placeholder]').forEach(function(elem) { - var placeholder = vAPI.i18n(elem.attr('placeholder')); - if ( placeholder ) { - elem.attr('placeholder', placeholder); - } + elem.attr('placeholder', vAPI.i18n(elem.attr('placeholder'))); }); uDom('[data-i18n-tip]').forEach(function(elem) { elem.attr( diff --git a/src/js/messaging.js b/src/js/messaging.js index 3f5f73598..ff811b42b 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -961,24 +961,58 @@ var µb = µBlock; /******************************************************************************/ -var getUserData = function(callback) { - var onUserFiltersReady = function(details) { +var getLocalData = function(callback) { + var onStorageInfoReady = function(bytesInUse) { + var o = µb.restoreBackupSettings; callback({ - 'timeStamp': Date.now(), - 'version': vAPI.app.version, - 'userSettings': µb.userSettings, - 'filterLists': µb.remoteBlacklists, - 'netWhitelist': µb.stringFromWhitelist(µb.netWhitelist), - 'userFilters': details.content + storageUsed: bytesInUse, + lastRestoreFile: o.lastRestoreFile, + lastRestoreTime: o.lastRestoreTime, + lastBackupFile: o.lastBackupFile, + lastBackupTime: o.lastBackupTime }); }; + + µb.getBytesInUse(onStorageInfoReady); +}; + +/******************************************************************************/ + +var backupUserData = function(callback) { + var onUserFiltersReady = function(details) { + var userData = { + timeStamp: Date.now(), + version: vAPI.app.version, + userSettings: µb.userSettings, + filterLists: µb.remoteBlacklists, + netWhitelist: µb.stringFromWhitelist(µb.netWhitelist), + userFilters: details.content + }; + var now = new Date(); + var filename = vAPI.i18n('aboutBackupFilename') + .replace('{{datetime}}', now.toLocaleString()) + .replace(/ +/g, '_'); + + vAPI.download({ + 'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userData, null, ' ')), + 'filename': filename + }); + + µb.restoreBackupSettings.lastBackupFile = filename; + µb.restoreBackupSettings.lastBackupTime = Date.now(); + µb.XAL.keyvalSetMany(µb.restoreBackupSettings); + + getLocalData(callback); + }; + µb.assets.get('assets/user/filters.txt', onUserFiltersReady); }; /******************************************************************************/ -var restoreUserData = function(userData) { - var countdown = 5; +var restoreUserData = function(request) { + var userData = request.userData; + var countdown = 6; var onCountdown = function() { countdown -= 1; if ( countdown === 0 ) { @@ -994,6 +1028,13 @@ var restoreUserData = function(userData) { µb.XAL.keyvalSetOne('remoteBlacklists', userData.filterLists, onCountdown); µb.XAL.keyvalSetOne('netWhitelist', userData.netWhitelist, onCountdown); µb.assets.put('assets/user/filters.txt', userData.userFilters, onCountdown); + + µb.XAL.keyvalSetMany({ + lastRestoreFile: request.file || '', + lastRestoreTime: Date.now(), + lastBackupFile: '', + lastBackupTime: 0 + }, onCountdown); }; // If we are going to restore all, might as well wipe out clean local @@ -1006,7 +1047,7 @@ var restoreUserData = function(userData) { var resetUserData = function() { µb.XAL.keyvalRemoveAll(); // Keep global counts, people can become quite attached to numbers - µBlock.saveLocalSettings(); + µb.saveLocalSettings(); vAPI.app.restart(); }; @@ -1015,8 +1056,11 @@ var resetUserData = function() { var onMessage = function(request, sender, callback) { // Async switch ( request.what ) { - case 'getUserData': - return getUserData(callback); + case 'backupUserData': + return backupUserData(callback); + + case 'getLocalData': + return getLocalData(callback); default: break; @@ -1027,7 +1071,7 @@ var onMessage = function(request, sender, callback) { switch ( request.what ) { case 'restoreUserData': - restoreUserData(request.userData); + restoreUserData(request); break; case 'resetUserData': diff --git a/src/js/pagestore.js b/src/js/pagestore.js index a8cb32dbd..d1c642e45 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -713,9 +713,10 @@ PageStore.prototype.logRequest = function(context, result) { if ( requestHostname === '' ) { requestHostname = context.pageHostname; } + var now = Date.now(); if ( this.hostnameToCountMap.hasOwnProperty(requestHostname) === false ) { this.hostnameToCountMap[requestHostname] = 0; - this.contentLastModified = Date.now(); + this.contentLastModified = now; } var c = result.charAt(1); if ( c === '' || c === 'a' ) { @@ -727,6 +728,7 @@ PageStore.prototype.logRequest = function(context, result) { this.perLoadBlockedRequestCount++; µb.localSettings.blockedRequestCount++; } + µb.localSettingsModifyTime = now; this.logBuffer.writeOne(context, result); }; diff --git a/src/js/settings.js b/src/js/settings.js index cf9981b2f..ae10d2067 100644 --- a/src/js/settings.js +++ b/src/js/settings.js @@ -33,27 +33,16 @@ var messager = vAPI.messaging.channel('settings.js'); /******************************************************************************/ -var exportToFile = function() { - var onUserDataReady = function(userData) { - if (!userData) { - return; - } - var now = new Date(); - var filename = vAPI.i18n('aboutBackupFilename') - .replace('{{datetime}}', now.toLocaleString()) - .replace(/ +/g, '_'); - vAPI.download({ - 'url': 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(userData, null, ' ')), - 'filename': filename - }); - }; - - messager.send({ what: 'getUserData' }, onUserDataReady); -}; - -/******************************************************************************/ - var handleImportFilePicker = function() { + var file = this.files[0]; + if ( file === undefined || file.name === '' ) { + return; + } + if ( file.type.indexOf('text') !== 0 ) { + return; + } + var filename = file.name; + var fileReaderOnLoadHandler = function() { var userData; try { @@ -80,20 +69,17 @@ var handleImportFilePicker = function() { } var time = new Date(userData.timeStamp); var msg = vAPI.i18n('aboutRestoreDataConfirm') - .replace('{{time}}', time.toLocaleString()); + .replace('{{time}}', time.toLocaleString()); var proceed = window.confirm(msg); if ( proceed ) { - messager.send({ what: 'restoreUserData', userData: userData }); + messager.send({ + what: 'restoreUserData', + userData: userData, + file: filename + }); } }; - var file = this.files[0]; - if ( file === undefined || file.name === '' ) { - return; - } - if ( file.type.indexOf('text') !== 0 ) { - return; - } var fr = new FileReader(); fr.onload = fileReaderOnLoadHandler; fr.readAsText(file); @@ -112,6 +98,47 @@ var startImportFilePicker = function() { /******************************************************************************/ +var exportToFile = function() { + messager.send({ what: 'backupUserData' }, onLocalDataReceived); +}; + +/******************************************************************************/ + +var onLocalDataReceived = function(details) { + uDom('#localData > ul > li:nth-of-type(1)').text( + vAPI.i18n('settingsStorageUsed').replace('{{value}}', details.storageUsed.toLocaleString()) + ); + + var elem, dt; + var timeOptions = { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + timeZoneName: 'short' + }; + var lastBackupFile = details.lastBackupFile || ''; + if ( lastBackupFile !== '' ) { + dt = new Date(details.lastBackupTime); + uDom('#localData > ul > li:nth-of-type(2) > ul > li:nth-of-type(1)').text(dt.toLocaleString('fullwide', timeOptions)); + //uDom('#localData > ul > li:nth-of-type(2) > ul > li:nth-of-type(2)').text(lastBackupFile); + uDom('#localData > ul > li:nth-of-type(2)').css('display', ''); + } + + var lastRestoreFile = details.lastRestoreFile || ''; + elem = uDom('#localData > p:nth-of-type(3)'); + if ( lastRestoreFile !== '' ) { + dt = new Date(details.lastRestoreTime); + uDom('#localData > ul > li:nth-of-type(3) > ul > li:nth-of-type(1)').text(dt.toLocaleString('fullwide', timeOptions)); + uDom('#localData > ul > li:nth-of-type(3) > ul > li:nth-of-type(2)').text(lastRestoreFile); + uDom('#localData > ul > li:nth-of-type(3)').css('display', ''); + } +}; + +/******************************************************************************/ + var resetUserData = function() { var msg = vAPI.i18n('aboutResetDataConfirm'); var proceed = window.confirm(msg); @@ -175,6 +202,7 @@ var onUserSettingsReceived = function(details) { uDom.onLoad(function() { messager.send({ what: 'userSettings' }, onUserSettingsReceived); + messager.send({ what: 'getLocalData' }, onLocalDataReceived); }); /******************************************************************************/ diff --git a/src/js/start.js b/src/js/start.js index bca966bb0..b1c82f84a 100644 --- a/src/js/start.js +++ b/src/js/start.js @@ -143,12 +143,6 @@ var onUserSettingsReady = function(fetched) { /******************************************************************************/ -var onLocalSettingsReady = function(fetched) { - fromFetch(µb.localSettings, fetched); -}; - -/******************************************************************************/ - // Housekeeping, as per system setting changes var onSystemSettingsReady = function(fetched) { @@ -170,11 +164,11 @@ var onSystemSettingsReady = function(fetched) { /******************************************************************************/ var onFirstFetchReady = function(fetched) { - // Order is important -- do not change: onSystemSettingsReady(fetched); - onLocalSettingsReady(fetched); + fromFetch(µb.localSettings, fetched); onUserSettingsReady(fetched); + fromFetch(µb.restoreBackupSettings, fetched); onNetWhitelistReady(fetched.netWhitelist); onVersionReady(fetched.version); @@ -191,6 +185,10 @@ var onFirstFetchReady = function(fetched) { var fetchableProps = { 'compiledMagic': '', + 'lastRestoreFile': '', + 'lastRestoreTime': 0, + 'lastBackupFile': '', + 'lastBackupTime': 0, 'netWhitelist': '', 'selfie': null, 'selfieMagic': '', @@ -222,6 +220,7 @@ var fromFetch = function(to, fetched) { toFetch(µb.localSettings, fetchableProps); toFetch(µb.userSettings, fetchableProps); +toFetch(µb.restoreBackupSettings, fetchableProps); vAPI.storage.get(fetchableProps, onFirstFetchReady); diff --git a/src/js/static-net-filtering.js b/src/js/static-net-filtering.js index 85c3a31cf..cf92cce3c 100644 --- a/src/js/static-net-filtering.js +++ b/src/js/static-net-filtering.js @@ -22,13 +22,12 @@ /* jshint bitwise: false, esnext: true, boss: true */ /* global punycode, µBlock */ -// Older Safari throws an exception for const when it's used with 'use strict'. -// 'use strict'; - /******************************************************************************/ µBlock.staticNetFilteringEngine = (function(){ +'use strict'; + /******************************************************************************/ var µb = µBlock; @@ -45,17 +44,17 @@ var µb = µBlock; // | +---- bit 8-15: unused // +---- bit 15: never use! (to ensure valid unicode character) -const BlockAction = 0 << 0; -const AllowAction = 1 << 0; -const ToggleAction = BlockAction ^ AllowAction; +var BlockAction = 0 << 0; +var AllowAction = 1 << 0; +var ToggleAction = BlockAction ^ AllowAction; -const Important = 1 << 1; +var Important = 1 << 1; -const AnyParty = 0 << 2; -const FirstParty = 1 << 2; -const ThirdParty = 2 << 2; +var AnyParty = 0 << 2; +var FirstParty = 1 << 2; +var ThirdParty = 2 << 2; -const AnyType = 1 << 4; +var AnyType = 1 << 4; var typeNameToTypeValue = { 'stylesheet': 2 << 4, 'image': 3 << 4, @@ -80,13 +79,13 @@ var typeOtherValue = typeNameToTypeValue.other; // The 2 lsb *must* be zeroed var allNetRequestTypesBitmap = (1 << (typeOtherValue >>> 4) + 2) - 4; -const BlockAnyTypeAnyParty = BlockAction | AnyType | AnyParty; -const BlockAnyType = BlockAction | AnyType; -const BlockAnyParty = BlockAction | AnyParty; +var BlockAnyTypeAnyParty = BlockAction | AnyType | AnyParty; +var BlockAnyType = BlockAction | AnyType; +var BlockAnyParty = BlockAction | AnyParty; -const AllowAnyTypeAnyParty = AllowAction | AnyType | AnyParty; -const AllowAnyType = AllowAction | AnyType; -const AllowAnyParty = AllowAction | AnyParty; +var AllowAnyTypeAnyParty = AllowAction | AnyType | AnyParty; +var AllowAnyType = AllowAction | AnyType; +var AllowAnyParty = AllowAction | AnyParty; var reHostnameRule = /^[0-9a-z][0-9a-z.-]*[0-9a-z]$/; var reURLPostHostnameAnchors = /[\/?#]/; @@ -166,10 +165,18 @@ var isFirstParty = function(firstPartyDomain, hostname) { return c === '.' || c === ''; }; -var strToRegex = function(prefix, s) { - var reStr = s.replace(/([.+?^=!:${}()|\[\]\/\\])/g, '\\$1') +// https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions + +var strToRegex = function(s, anchor) { + var reStr = s.replace(/[.+?^${}()|[\]\\]/g, '\\$&') .replace(/\*/g, '.*'); - return new RegExp(prefix + reStr); + if ( anchor < 0 ) { + reStr = '^' + reStr; + } else if ( anchor > 0 ) { + reStr += reStr + '$'; + } + //console.debug('µBlock.staticNetFilteringEngine: created RegExp("%s")', reStr); + return new RegExp(reStr); }; /******************************************************************************* @@ -190,33 +197,13 @@ Filters family tree: - no hostname - specific hostname (not implemented) -- one wildcard - - anywhere - - no hostname - - specific hostname - - anchored at start - - no hostname - - specific hostname - - anchored at end - - no hostname - - specific hostname +- with wildcard(s) - anchored within hostname - - no hostname (not implemented) - - specific hostname (not implemented) - -- more than one wildcard - - anywhere - no hostname - specific hostname - - anchored at start + - all else - no hostname - specific hostname - - anchored at end - - no hostname - - specific hostname - - anchored within hostname - - no hostname (not implemented) - - specific hostname (not implemented) */ @@ -546,7 +533,7 @@ FilterPlainHnAnchored.prototype.match = function(url, tokenBeg) { reURLPostHostnameAnchors.test(url.slice(pos + 3, tokenBeg)) === false; }; -FilterPlainHnAnchored.fid = FilterPlainHnAnchored.prototype.fid = 'h|a'; +FilterPlainHnAnchored.fid = FilterPlainHnAnchored.prototype.fid = '||a'; FilterPlainHnAnchored.prototype.toString = function() { return '||' + this.s; @@ -568,310 +555,81 @@ FilterPlainHnAnchored.fromSelfie = function(s) { /******************************************************************************/ -// With a single wildcard, regex is not optimal. -// See: -// http://jsperf.com/regexp-vs-indexof-abp-miss/5 -// http://jsperf.com/regexp-vs-indexof-abp-hit/4 +// Generic filter -var FilterSingleWildcard = function(lSegment, rSegment, tokenBeg) { - this.tokenBeg = tokenBeg; - this.lSegment = lSegment; - this.rSegment = rSegment; +var FilterGeneric = function(s, anchor) { + this.s = s; + this.anchor = anchor; + this.re = null; }; -FilterSingleWildcard.prototype.match = function(url, tokenBeg) { - tokenBeg -= this.tokenBeg; - return url.substr(tokenBeg, this.lSegment.length) === this.lSegment && - url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0; +FilterGeneric.prototype.match = function(url) { + if ( this.re === null ) { + this.re = strToRegex(this.s, this.anchor); + } + return this.re.test(url); }; -FilterSingleWildcard.fid = FilterSingleWildcard.prototype.fid = '*'; +FilterGeneric.fid = FilterGeneric.prototype.fid = '_'; -FilterSingleWildcard.prototype.toString = function() { - return this.lSegment + '*' + this.rSegment; +FilterGeneric.prototype.toString = function() { + if ( this.anchor === 0 ) { + return this.s; + } + if ( this.anchor < 0 ) { + return '|' + this.s; + } + return this.s + '|'; }; -FilterSingleWildcard.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment + '\t' + - this.tokenBeg; +FilterGeneric.prototype.toSelfie = function() { + return this.s + '\t' + this.anchor; }; -FilterSingleWildcard.compile = function(details) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + - s.slice(pos + 1) + '\t' + - details.tokenBeg; +FilterGeneric.compile = function(details) { + return details.f + '\t' + details.anchor; }; -FilterSingleWildcard.fromSelfie = function(s) { - var args = s.split('\t'); - return new FilterSingleWildcard(args[0], args[1], atoi(args[2])); -}; - -/******************************************************************************/ - -var FilterSingleWildcardHostname = function(lSegment, rSegment, tokenBeg, hostname) { - this.tokenBeg = tokenBeg; - this.lSegment = lSegment; - this.rSegment = rSegment; - this.hostname = hostname; -}; - -FilterSingleWildcardHostname.prototype.match = function(url, tokenBeg) { - tokenBeg -= this.tokenBeg; - return pageHostnameRegister.slice(-this.hostname.length) === this.hostname && - url.substr(tokenBeg, this.lSegment.length) === this.lSegment && - url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0; -}; - -FilterSingleWildcardHostname.fid = FilterSingleWildcardHostname.prototype.fid = '*h'; - -FilterSingleWildcardHostname.prototype.toString = function() { - return this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname; -}; - -FilterSingleWildcardHostname.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment + '\t' + - this.tokenBeg + '\t' + - this.hostname; -}; - -FilterSingleWildcardHostname.compile = function(details, hostname) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + - s.slice(pos + 1) + '\t' + - details.tokenBeg + '\t' + - hostname; -}; - -FilterSingleWildcardHostname.fromSelfie = function(s) { - var args = s.split('\t'); - return new FilterSingleWildcardHostname(args[0], args[1], atoi(args[2]), args[3]); -}; - -/******************************************************************************/ - -var FilterSingleWildcardPrefix0 = function(lSegment, rSegment) { - this.lSegment = lSegment; - this.rSegment = rSegment; -}; - -FilterSingleWildcardPrefix0.prototype.match = function(url, tokenBeg) { - return url.substr(tokenBeg, this.lSegment.length) === this.lSegment && - url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0; -}; - -FilterSingleWildcardPrefix0.fid = FilterSingleWildcardPrefix0.prototype.fid = '0*'; - -FilterSingleWildcardPrefix0.prototype.toString = function() { - return this.lSegment + '*' + this.rSegment; -}; - -FilterSingleWildcardPrefix0.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment; -}; - -FilterSingleWildcardPrefix0.compile = function(details) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + s.slice(pos + 1); -}; - -FilterSingleWildcardPrefix0.fromSelfie = function(s) { +FilterGeneric.fromSelfie = function(s) { var pos = s.indexOf('\t'); - return new FilterSingleWildcardPrefix0(s.slice(0, pos), s.slice(pos + 1)); + return new FilterGeneric(s.slice(0, pos), parseInt(s.slice(pos + 1), 10)); }; /******************************************************************************/ -var FilterSingleWildcardPrefix0Hostname = function(lSegment, rSegment, hostname) { - this.lSegment = lSegment; - this.rSegment = rSegment; +// Generic filter + +var FilterGenericHostname = function(s, anchor, hostname) { + FilterGeneric.call(this, s, anchor); this.hostname = hostname; }; +FilterGenericHostname.prototype = Object.create(FilterGeneric.prototype); +FilterGenericHostname.prototype.constructor = FilterGenericHostname; -FilterSingleWildcardPrefix0Hostname.prototype.match = function(url, tokenBeg) { - return pageHostnameRegister.slice(-this.hostname.length) === this.hostname && - url.substr(tokenBeg, this.lSegment.length) === this.lSegment && - url.indexOf(this.rSegment, tokenBeg + this.lSegment.length) > 0; +FilterGenericHostname.prototype.match = function(url) { + if ( pageHostnameRegister.slice(-this.hostname.length) !== this.hostname ) { + return false; + } + return FilterGeneric.prototype.match.call(this, url); }; -FilterSingleWildcardPrefix0Hostname.fid = FilterSingleWildcardPrefix0Hostname.prototype.fid = '0*h'; +FilterGenericHostname.fid = FilterGenericHostname.prototype.fid = '_h'; -FilterSingleWildcardPrefix0Hostname.prototype.toString = function() { - return this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname; +FilterGenericHostname.prototype.toString = function() { + return FilterGeneric.prototype.toString.call(this) + '$domain=' + this.hostname; }; -FilterSingleWildcardPrefix0Hostname.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment + '\t' + - this.hostname; +FilterGenericHostname.prototype.toSelfie = function() { + return FilterGeneric.prototype.toSelfie.call(this) + '\t' + this.hostname; }; -FilterSingleWildcardPrefix0Hostname.compile = function(details, hostname) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + - s.slice(pos + 1) + '\t' + - hostname; +FilterGenericHostname.compile = function(details, hostname) { + return FilterGeneric.compile(details) + '\t' + hostname; }; -FilterSingleWildcardPrefix0Hostname.fromSelfie = function(s) { - var args = s.split('\t'); - return new FilterSingleWildcardPrefix0Hostname(args[0], args[1], args[2]); -}; - -/******************************************************************************/ - -var FilterSingleWildcardLeftAnchored = function(lSegment, rSegment) { - this.lSegment = lSegment; - this.rSegment = rSegment; -}; - -FilterSingleWildcardLeftAnchored.prototype.match = function(url) { - return url.slice(0, this.lSegment.length) === this.lSegment && - url.indexOf(this.rSegment, this.lSegment.length) > 0; -}; - -FilterSingleWildcardLeftAnchored.fid = FilterSingleWildcardLeftAnchored.prototype.fid = '|*'; - -FilterSingleWildcardLeftAnchored.prototype.toString = function() { - return '|' + this.lSegment + '*' + this.rSegment; -}; - -FilterSingleWildcardLeftAnchored.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment; -}; - -FilterSingleWildcardLeftAnchored.compile = function(details) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + - s.slice(pos + 1); -}; - -FilterSingleWildcardLeftAnchored.fromSelfie = function(s) { - var pos = s.indexOf('\t'); - return new FilterSingleWildcardLeftAnchored(s.slice(0, pos), s.slice(pos + 1)); -}; - -/******************************************************************************/ - -var FilterSingleWildcardLeftAnchoredHostname = function(lSegment, rSegment, hostname) { - this.lSegment = lSegment; - this.rSegment = rSegment; - this.hostname = hostname; -}; - -FilterSingleWildcardLeftAnchoredHostname.prototype.match = function(url) { - return pageHostnameRegister.slice(-this.hostname.length) === this.hostname && - url.slice(0, this.lSegment.length) === this.lSegment && - url.indexOf(this.rSegment, this.lSegment.length) > 0; -}; - -FilterSingleWildcardLeftAnchoredHostname.fid = FilterSingleWildcardLeftAnchoredHostname.prototype.fid = '|*h'; - -FilterSingleWildcardLeftAnchoredHostname.prototype.toString = function() { - return '|' + this.lSegment + '*' + this.rSegment + '$domain=' + this.hostname; -}; - -FilterSingleWildcardLeftAnchoredHostname.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment + '\t' + - this.hostname; -}; - -FilterSingleWildcardLeftAnchoredHostname.compile = function(details, hostname) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + - s.slice(pos + 1) + '\t' + - hostname; -}; - -FilterSingleWildcardLeftAnchoredHostname.fromSelfie = function(s) { - var args = s.split('\t'); - return new FilterSingleWildcardLeftAnchoredHostname(args[0], args[1], args[2]); -}; - -/******************************************************************************/ - -var FilterSingleWildcardRightAnchored = function(lSegment, rSegment) { - this.lSegment = lSegment; - this.rSegment = rSegment; -}; - -FilterSingleWildcardRightAnchored.prototype.match = function(url) { - return url.slice(-this.rSegment.length) === this.rSegment && - url.lastIndexOf(this.lSegment, url.length - this.rSegment.length - this.lSegment.length) >= 0; -}; - -FilterSingleWildcardRightAnchored.fid = FilterSingleWildcardRightAnchored.prototype.fid = '*|'; - -FilterSingleWildcardRightAnchored.prototype.toString = function() { - return this.lSegment + '*' + this.rSegment + '|'; -}; - -FilterSingleWildcardRightAnchored.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment; -}; - -FilterSingleWildcardRightAnchored.compile = function(details) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + - s.slice(pos + 1); -}; - -FilterSingleWildcardRightAnchored.fromSelfie = function(s) { - var pos = s.indexOf('\t'); - return new FilterSingleWildcardRightAnchored(s.slice(0, pos), s.slice(pos + 1)); -}; - -/******************************************************************************/ - -var FilterSingleWildcardRightAnchoredHostname = function(lSegment, rSegment, hostname) { - this.lSegment = lSegment; - this.rSegment = rSegment; - this.hostname = hostname; -}; - -FilterSingleWildcardRightAnchoredHostname.prototype.match = function(url) { - return pageHostnameRegister.slice(-this.hostname.length) === this.hostname && - url.slice(-this.rSegment.length) === this.rSegment && - url.lastIndexOf(this.lSegment, url.length - this.rSegment.length - this.lSegment.length) >= 0; -}; - -FilterSingleWildcardRightAnchoredHostname.fid = FilterSingleWildcardRightAnchoredHostname.prototype.fid = '*|h'; - -FilterSingleWildcardRightAnchoredHostname.prototype.toString = function() { - return this.lSegment + '*' + this.rSegment + '|$domain=' + this.hostname; -}; - -FilterSingleWildcardRightAnchoredHostname.prototype.toSelfie = function() { - return this.lSegment + '\t' + - this.rSegment + '\t' + - this.hostname; -}; - -FilterSingleWildcardRightAnchoredHostname.compile = function(details, hostname) { - var s = details.f; - var pos = s.indexOf('*'); - return s.slice(0, pos) + '\t' + - s.slice(pos + 1) + '\t' + - hostname; -}; - -FilterSingleWildcardRightAnchoredHostname.fromSelfie = function(s) { - var args = s.split('\t'); - return new FilterSingleWildcardRightAnchoredHostname(args[0], args[1], args[2]); +FilterGenericHostname.fromSelfie = function(s) { + var fields = s.split('\t'); + return new FilterGenericHostname(fields[0], parseInt(fields[1], 10), fields[2]); }; /******************************************************************************/ @@ -887,7 +645,7 @@ var FilterGenericHnAnchored = function(s) { FilterGenericHnAnchored.prototype.match = function(url) { if ( this.re === null ) { - this.re = strToRegex('', this.s); + this.re = strToRegex(this.s, 0); } // Quick test first if ( this.re.test(url) === false ) { @@ -926,12 +684,13 @@ var FilterGenericHnAnchoredHostname = function(s, hostname) { this.hostname = hostname; }; FilterGenericHnAnchoredHostname.prototype = Object.create(FilterGenericHnAnchored.prototype); +FilterGenericHnAnchoredHostname.prototype.constructor = FilterGenericHnAnchoredHostname; FilterGenericHnAnchoredHostname.prototype.match = function(url) { if ( pageHostnameRegister.slice(-this.hostname.length) !== this.hostname ) { return false; } - return FilterGenericHnAnchored.prototype.match.call(this. url); + return FilterGenericHnAnchored.prototype.match.call(this, url); }; FilterGenericHnAnchoredHostname.fid = FilterGenericHnAnchoredHostname.prototype.fid = '||_h'; @@ -955,88 +714,6 @@ FilterGenericHnAnchoredHostname.fromSelfie = function(s) { /******************************************************************************/ -// With many wildcards, a regex is best. - -// Ref: regex escaper taken from: -// https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions -// modified for the purpose here. - -var FilterManyWildcards = function(s, tokenBeg) { - this.s = s; - this.tokenBeg = tokenBeg; - this.re = null; -}; - -FilterManyWildcards.prototype.match = function(url, tokenBeg) { - if ( this.re === null ) { - this.re = strToRegex('^', this.s); - } - return this.re.test(url.slice(tokenBeg - this.tokenBeg)); -}; - -FilterManyWildcards.fid = FilterManyWildcards.prototype.fid = '*+'; - -FilterManyWildcards.prototype.toString = function() { - return this.s; -}; - -FilterManyWildcards.prototype.toSelfie = function() { - return this.s + '\t' + this.tokenBeg; -}; - -FilterManyWildcards.compile = function(details) { - return details.f + '\t' + details.tokenBeg; -}; - -FilterManyWildcards.fromSelfie = function(s) { - var pos = s.indexOf('\t'); - return new FilterManyWildcards(s.slice(0, pos), atoi(s.slice(pos + 1))); -}; - -/******************************************************************************/ - -var FilterManyWildcardsHostname = function(s, tokenBeg, hostname) { - this.s = s; - this.tokenBeg = tokenBeg; - this.re = null; - this.hostname = hostname; -}; - -FilterManyWildcardsHostname.prototype.match = function(url, tokenBeg) { - if ( pageHostnameRegister.slice(-this.hostname.length) !== this.hostname ) { - return false; - } - if ( this.re === null ) { - this.re = strToRegex('^', this.s); - } - return this.re.test(url.slice(tokenBeg - this.tokenBeg)); -}; - -FilterManyWildcardsHostname.fid = FilterManyWildcardsHostname.prototype.fid = '*+h'; - -FilterManyWildcardsHostname.prototype.toString = function() { - return this.s + '$domain=' + this.hostname; -}; - -FilterManyWildcardsHostname.prototype.toSelfie = function() { - return this.s + '\t' + - this.tokenBeg + '\t' + - this.hostname; -}; - -FilterManyWildcardsHostname.compile = function(details, hostname) { - return details.f + '\t' + - details.tokenBeg + '\t' + - hostname; -}; - -FilterManyWildcardsHostname.fromSelfie = function(s) { - var args = s.split('\t'); - return new FilterManyWildcardsHostname(args[0], atoi(args[1]), args[2]); -}; - -/******************************************************************************/ - // Regex-based filters var FilterRegex = function(s) { @@ -1405,24 +1082,11 @@ var getFilterClass = function(details) { return FilterRegex; } var s = details.f; - var wcOffset = s.indexOf('*'); - if ( wcOffset !== -1 ) { + if ( s.indexOf('*') !== -1 ) { if ( details.hostnameAnchored ) { return FilterGenericHnAnchored; } - if ( s.indexOf('*', wcOffset + 1) !== -1 ) { - return details.anchor === 0 ? FilterManyWildcards : null; - } - if ( details.anchor < 0 ) { - return FilterSingleWildcardLeftAnchored; - } - if ( details.anchor > 0 ) { - return FilterSingleWildcardRightAnchored; - } - if ( details.tokenBeg === 0 ) { - return FilterSingleWildcardPrefix0; - } - return FilterSingleWildcard; + return FilterGeneric; } if ( details.anchor < 0 ) { return FilterPlainLeftAnchored; @@ -1449,24 +1113,11 @@ var getHostnameBasedFilterClass = function(details) { return FilterRegexHostname; } var s = details.f; - var wcOffset = s.indexOf('*'); - if ( wcOffset !== -1 ) { + if ( s.indexOf('*') !== -1 ) { if ( details.hostnameAnchored ) { return FilterGenericHnAnchoredHostname; } - if ( s.indexOf('*', wcOffset + 1) !== -1 ) { - return details.anchor === 0 ? FilterManyWildcardsHostname : null; - } - if ( details.anchor < 0 ) { - return FilterSingleWildcardLeftAnchoredHostname; - } - if ( details.anchor > 0 ) { - return FilterSingleWildcardRightAnchoredHostname; - } - if ( details.tokenBeg === 0 ) { - return FilterSingleWildcardPrefix0Hostname; - } - return FilterSingleWildcardHostname; + return FilterGenericHostname; } if ( details.anchor < 0 ) { return FilterPlainLeftAnchoredHostname; @@ -1860,6 +1511,7 @@ FilterContainer.prototype.reset = function() { this.duplicateBuster = {}; this.categories = Object.create(null); this.filterParser.reset(); + this.filterCounts = {}; }; /******************************************************************************/ @@ -1895,20 +1547,12 @@ FilterContainer.prototype.factories = { '|ah': FilterPlainLeftAnchoredHostname, 'a|': FilterPlainRightAnchored, 'a|h': FilterPlainRightAnchoredHostname, - 'h|a': FilterPlainHnAnchored, - '*': FilterSingleWildcard, - '*h': FilterSingleWildcardHostname, - '0*': FilterSingleWildcardPrefix0, - '0*h': FilterSingleWildcardPrefix0Hostname, - '|*': FilterSingleWildcardLeftAnchored, - '|*h': FilterSingleWildcardLeftAnchoredHostname, - '*|': FilterSingleWildcardRightAnchored, - '*|h': FilterSingleWildcardRightAnchoredHostname, - '*+': FilterManyWildcards, - '*+h': FilterManyWildcardsHostname, + '||a': FilterPlainHnAnchored, '//': FilterRegex, '//h': FilterRegexHostname, '{h}': FilterHostnameDict, + '_': FilterGeneric, + '_h': FilterGenericHostname, '||_': FilterGenericHnAnchored, '||_h': FilterGenericHnAnchoredHostname }; @@ -2240,6 +1884,14 @@ FilterContainer.prototype.fromCompiledContent = function(text, lineBeg) { this.duplicateBuster[line] = true; factory = this.factories[fields[2]]; + + // For development purpose + //if ( this.filterCounts.hasOwnProperty(fields[2]) === false ) { + // this.filterCounts[fields[2]] = 1; + //} else { + // this.filterCounts[fields[2]]++; + //} + filter = factory.fromSelfie(fields[3]); if ( entry === undefined ) { bucket[fields[1]] = filter; diff --git a/src/js/storage.js b/src/js/storage.js index beb3edeed..478f3a200 100644 --- a/src/js/storage.js +++ b/src/js/storage.js @@ -25,9 +25,13 @@ /******************************************************************************/ -µBlock.getBytesInUse = function() { +µBlock.getBytesInUse = function(callback) { + if ( typeof callback !== 'function' ) { + callback = this.noopFunc; + } var getBytesInUseHandler = function(bytesInUse) { µBlock.storageUsed = bytesInUse; + callback(bytesInUse); }; vAPI.storage.getBytesInUse(null, getBytesInUseHandler); }; @@ -38,6 +42,11 @@ if ( typeof callback !== 'function' ) { callback = this.noopFunc; } + if ( this.localSettingsModifyTime <= this.localSettingsSaveTime ) { + callback(); + return; + } + this.localSettingsSaveTime = Date.now(); vAPI.storage.set(this.localSettings, callback); }; @@ -124,7 +133,7 @@ if ( details.content.indexOf(content.trim()) !== -1 ) { return; } - µb.saveUserFilters(details.content.trim() + '\n' + content.trim(), onSaved); + µb.saveUserFilters(details.content.trim() + '\n\n' + content.trim(), onSaved); }; this.loadUserFilters(onLoaded); diff --git a/src/settings.html b/src/settings.html index fe376538c..17fea4963 100644 --- a/src/settings.html +++ b/src/settings.html @@ -7,9 +7,21 @@