From 294a49924b7cdda67f8ae3684b6be8468e25c4bb Mon Sep 17 00:00:00 2001 From: Slava Leleka Date: Fri, 28 Jun 2024 11:10:10 +0300 Subject: [PATCH 1/4] fix linter Squashed commit of the following: commit d892fca33be9aa152cac3719df2d3055b9a1fd02 Author: Slava Leleka Date: Thu Jun 27 19:08:08 2024 +0300 fix linter --- .../rules-limits/rules-limits-service-mv3.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts b/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts index b9a4403400..1f6e176f41 100644 --- a/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts +++ b/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts @@ -208,7 +208,7 @@ export class RulesLimitsService { * @returns Limitation error. */ private static getRegexpRulesLimitExceedErr = (result: ConfigurationResult): LimitationError | undefined => { - return result.dynamicRules.limitations + return result.dynamicRules?.limitations .find((e) => e instanceof TooManyRegexpRulesError); }; @@ -219,7 +219,7 @@ export class RulesLimitsService { * @returns Too many rules error. */ private static getRulesLimitExceedErr = (result: ConfigurationResult): LimitationError | undefined => { - return result.dynamicRules.limitations + return result.dynamicRules?.limitations .find((e) => e instanceof TooManyRulesError); }; @@ -231,8 +231,8 @@ export class RulesLimitsService { */ private static getDynamicRulesEnabledCount(result: ConfigurationResult): number { const rulesLimitExceedErr = RulesLimitsService.getRulesLimitExceedErr(result); - const declarativeRulesCount = result.dynamicRules.ruleSet.getRulesCount(); - return rulesLimitExceedErr?.numberOfMaximumRules || declarativeRulesCount; + const declarativeRulesCount = result.dynamicRules?.ruleSet.getRulesCount(); + return rulesLimitExceedErr?.numberOfMaximumRules || declarativeRulesCount || 0; } /** @@ -265,8 +265,8 @@ export class RulesLimitsService { */ private static getDynamicRulesRegexpsEnabledCount(result: ConfigurationResult): number { const regexpRulesLimitExceedErr = RulesLimitsService.getRegexpRulesLimitExceedErr(result); - const regexpsCount = result.dynamicRules.ruleSet.getRegexpRulesCount(); - return regexpsCount + (regexpRulesLimitExceedErr?.excludedRulesIds.length || 0); + const regexpsCount = result.dynamicRules?.ruleSet.getRegexpRulesCount(); + return (regexpsCount || 0) + (regexpRulesLimitExceedErr?.excludedRulesIds.length || 0); } /** From 654c59dd47fd34300c8178250907685ac08afd80 Mon Sep 17 00:00:00 2001 From: Slava Leleka Date: Mon, 1 Jul 2024 12:29:44 +0300 Subject: [PATCH 2/4] fix popup styles. AG-33925 Squashed commit of the following: commit 696d4b066f6efac1f3494892f39b767bdf75f804 Merge: ad6a30011 294a49924 Author: Slava Leleka Date: Fri Jun 28 11:10:50 2024 +0300 Merge branch 'v5.0' into fix/AG-33925 commit ad6a300114f4b8c2e8d01755f375051c15de9bf2 Author: Slava Leleka Date: Thu Jun 27 19:08:08 2024 +0300 fix linter commit 33a2709c844a54056af1ded6224eb03fbf4b9986 Author: Slava Leleka Date: Thu Jun 27 19:03:52 2024 +0300 fix popup select list background-color for light commit 44cbccdccec03052c79b1782f3a11a257c52e480 Author: Slava Leleka Date: Thu Jun 27 19:02:02 2024 +0300 fix popup current site and cta link styles commit de43b195faa749dbf0fa07944a7838f659d76c64 Author: Slava Leleka Date: Thu Jun 27 18:53:36 2024 +0300 fix popup background-color for dark --- .../common/components/ui/Select/select.pcss | 17 ++++++++++ .../popup/components/Actions/actions.pcss | 8 ++--- .../pages/popup/components/Header/header.pcss | 4 +-- .../src/pages/popup/components/Main/main.pcss | 33 ++++++++++++++----- Extension/src/pages/popup/styles/common.pcss | 16 ++++----- 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/Extension/src/pages/common/components/ui/Select/select.pcss b/Extension/src/pages/common/components/ui/Select/select.pcss index 674edf5479..672288a8c1 100644 --- a/Extension/src/pages/common/components/ui/Select/select.pcss +++ b/Extension/src/pages/common/components/ui/Select/select.pcss @@ -116,6 +116,11 @@ left: 0; right: initial; margin-top: 20px; + background-color: var(--white); + + @media (prefers-color-scheme: dark) { + background-color: var(--gray1f); + } } } } @@ -138,6 +143,12 @@ color: var(--gray900); } } + + &.popup-modification { + .select__list { + background-color: var(--white); + } + } } } @@ -158,5 +169,11 @@ background-color: var(--gray900); } } + + &.popup-modification { + .select__list { + background-color: var(--gray1f); + } + } } } diff --git a/Extension/src/pages/popup/components/Actions/actions.pcss b/Extension/src/pages/popup/components/Actions/actions.pcss index 2f8b638b19..0ded12e7b1 100644 --- a/Extension/src/pages/popup/components/Actions/actions.pcss +++ b/Extension/src/pages/popup/components/Actions/actions.pcss @@ -10,7 +10,7 @@ max-width: 320px; @media (prefers-color-scheme: dark) { - background-color: var(--black); + background-color: var(--gray1f); } &--mv3 { @@ -31,7 +31,7 @@ background-color: var(--gray100); @media (prefers-color-scheme: dark) { - background-color: var(--grayDark); + background-color: var(--gray3d); } } @@ -80,11 +80,11 @@ .dark-mode { & .actions { - background-color: var(--black); + background-color: var(--gray1f); .action { &:hover { - background-color: var(--grayDark); + background-color: var(--gray3d); } &__title { diff --git a/Extension/src/pages/popup/components/Header/header.pcss b/Extension/src/pages/popup/components/Header/header.pcss index 604c05611f..332546822e 100644 --- a/Extension/src/pages/popup/components/Header/header.pcss +++ b/Extension/src/pages/popup/components/Header/header.pcss @@ -6,7 +6,7 @@ padding: 0 16px 0 24px; @media (prefers-color-scheme: dark) { - background-color: var(--black); + background-color: var(--gray1f); } &__buttons { @@ -53,7 +53,7 @@ .dark-mode { .popup-header { - background-color: var(--black); + background-color: var(--gray1f); &__button { color: var(--grayc0); diff --git a/Extension/src/pages/popup/components/Main/main.pcss b/Extension/src/pages/popup/components/Main/main.pcss index 2a84de97a7..b6e4f0b842 100644 --- a/Extension/src/pages/popup/components/Main/main.pcss +++ b/Extension/src/pages/popup/components/Main/main.pcss @@ -244,12 +244,21 @@ .main { color: var(--gray900); - &__cta-link { - color: var(--gray700); + &__header { + &--current-site { + color: var(--gray7f); + } + } - &:hover { - color: var(--gray900); + &__cta { + &--link { + color: var(--gray7f); + + &:hover { + color: var(--gray3d); + } } + } } @@ -266,11 +275,19 @@ .main { color: var(--gray300); - &__cta-link { - color: var(--gray400); + &__header { + &--current-site { + color: var(--grayc0); + } + } + + &__cta { + &--link { + color: var(--grayc0); - &:hover { - color: var(--gray100); + &:hover { + color: var(--graye4); + } } } } diff --git a/Extension/src/pages/popup/styles/common.pcss b/Extension/src/pages/popup/styles/common.pcss index 08e4fa4d7c..e32b0e9d89 100644 --- a/Extension/src/pages/popup/styles/common.pcss +++ b/Extension/src/pages/popup/styles/common.pcss @@ -15,19 +15,19 @@ body, min-height: 100%; width: auto; min-width: 320px; - background-color: var(--width); + background-color: var(--white); @media (prefers-color-scheme: dark) { - background-color: var(--black); + background-color: var(--gray1f); } } html { font-size: 10px; - background-color: var(--width); + background-color: var(--white); @media (prefers-color-scheme: dark) { - background-color: var(--black); + background-color: var(--gray1f); } } @@ -69,20 +69,20 @@ select { .light-mode { color-scheme: light; - background-color: var(--width); + background-color: var(--white); body, #root { - background-color: var(--width); + background-color: var(--white); } } .dark-mode { color-scheme: dark; - background-color: var(--black); + background-color: var(--gray1f); body, #root { - background-color: var(--black); + background-color: var(--gray1f); } } From aa4891f77d4372ccc1cc19b7f9ab59c824c0791a Mon Sep 17 00:00:00 2001 From: Dmitry Seregin Date: Mon, 1 Jul 2024 14:18:07 +0300 Subject: [PATCH 3/4] AG-33794: proper usage of settings.filteringEnabled Merge in EXTENSIONS/browser-extension from fix/AG-33794 to v5.0 Squashed commit of the following: commit 25631e84c898606d6f2eb1af8c87f2f42b107ddb Merge: ccf4bb628 654c59dd4 Author: Dmitriy Seregin Date: Mon Jul 1 14:09:09 2024 +0300 Merge branch 'v5.0' into fix/AG-33794 commit ccf4bb6289321b0a8cb0a4959f720c8f5b19677a Merge: 0f711dc88 294a49924 Author: Dmitriy Seregin Date: Sun Jun 30 20:31:01 2024 +0300 Merge branch 'v5.0' into fix/AG-33794 commit 0f711dc886e0ef982e9a73a553f18c39ff4b1c53 Author: Dmitriy Seregin Date: Sun Jun 30 20:26:12 2024 +0300 fixes commit 01908468aed1b4e4c65cb3a83bd669c7fe004148 Author: Dmitriy Seregin Date: Wed Jun 26 19:06:40 2024 +0300 fixes commit ceda9224a65b8c61a8d5d4b49834aaa7932645a8 Merge: 2f3c60e79 da26e4696 Author: Dmitriy Seregin Date: Wed Jun 26 19:05:35 2024 +0300 Merge branch v5.0 into fix/AG-33794 commit 2f3c60e797d3a98f10cadcb423915dbc4e7d04a4 Author: Dmitriy Seregin Date: Wed Jun 26 19:01:59 2024 +0300 update deps commit cfd49b661336c3d3fd2038ea7b10d0756dc1d050 Author: Dmitriy Seregin Date: Wed Jun 26 17:37:48 2024 +0300 AG-33794: proper usage of settings.filteringEnabled --- Extension/src/background/api/filters/main.ts | 7 +- Extension/src/background/api/ui/icons.ts | 2 +- Extension/src/background/app/app-mv3.ts | 2 +- Extension/src/background/engine/engine-mv3.ts | 36 ++--- .../src/background/schema/settings/main.ts | 5 +- .../src/background/services/locale-detect.ts | 4 +- .../rules-limits/rules-limits-service-mv3.ts | 145 ++++++++++-------- Extension/src/background/services/settings.ts | 4 +- Extension/src/background/services/ui/popup.ts | 2 +- .../src/background/utils/arrays-are-equal.ts | 34 ++++ .../src/background/utils/string-storage.ts | 2 + .../components/RulesLimits/RulesLimits.tsx | 2 + 12 files changed, 151 insertions(+), 94 deletions(-) create mode 100644 Extension/src/background/utils/arrays-are-equal.ts diff --git a/Extension/src/background/api/filters/main.ts b/Extension/src/background/api/filters/main.ts index 6b63c9138b..0b6a847483 100644 --- a/Extension/src/background/api/filters/main.ts +++ b/Extension/src/background/api/filters/main.ts @@ -359,11 +359,8 @@ export class FiltersApi { * @returns Enabled filters metadata array. */ public static getEnabledFiltersWithMetadata(): FilterMetadata[] { - const filters = FiltersApi.getEnabledFilters(); - return filters - .map(f => { - return FiltersApi.getFilterMetadata(f); - }) + return FiltersApi.getEnabledFilters() + .map(f => FiltersApi.getFilterMetadata(f)) .filter((f): f is FilterMetadata => f !== undefined); } diff --git a/Extension/src/background/api/ui/icons.ts b/Extension/src/background/api/ui/icons.ts index 2b0424d0c8..faf4ca1e9c 100644 --- a/Extension/src/background/api/ui/icons.ts +++ b/Extension/src/background/api/ui/icons.ts @@ -67,7 +67,7 @@ export class IconsApi { } const isMv3LimitsExceeded = __IS_MV3__ - ? RulesLimitsService.areFilterLimitsExceeded() + ? await RulesLimitsService.areFilterLimitsExceeded() : false; try { diff --git a/Extension/src/background/app/app-mv3.ts b/Extension/src/background/app/app-mv3.ts index cfafc261d3..3ebdc2dd97 100644 --- a/Extension/src/background/app/app-mv3.ts +++ b/Extension/src/background/app/app-mv3.ts @@ -137,7 +137,7 @@ export class App { // Initializes Settings storage data await SettingsApi.init(); - rulesLimitsService.init(); + await rulesLimitsService.init(); // TODO mv3 uses other way to inject scripts. AG-33507 // /** diff --git a/Extension/src/background/engine/engine-mv3.ts b/Extension/src/background/engine/engine-mv3.ts index 002e399783..405847bf9e 100644 --- a/Extension/src/background/engine/engine-mv3.ts +++ b/Extension/src/background/engine/engine-mv3.ts @@ -104,24 +104,11 @@ export class Engine implements TsWebExtensionEngine { await RulesLimitsService.checkFiltersLimitsChange(this.update.bind(this)); - if (RulesLimitsService.areFilterLimitsExceeded()) { + if (await RulesLimitsService.areFilterLimitsExceeded()) { toasts.showRuleLimitsAlert(); } } - /** - * Stops the tswebextension and updates the counter of active rules. - */ - async stop(): Promise { - logger.info('Stop tswebextension...'); - await this.api.stop(); - - const rulesCount = this.api.getRulesCount(); - logger.info(`tswebextension is stopped. Rules count: ${rulesCount}`); - // TODO: remove after frontend refactoring - listeners.notifyListeners(listeners.RequestFilterUpdated); - } - /** * Updates tswebextension configuration and after that updates the counter * of active rules. @@ -132,6 +119,9 @@ export class Engine implements TsWebExtensionEngine { const configuration = await Engine.getConfiguration(); logger.info('Update tswebextension configuration...'); + if (skipLimitsCheck) { + logger.info('With skip limits check.'); + } const result = await this.api.configure(configuration); rulesLimitsService.set(result); @@ -143,6 +133,10 @@ export class Engine implements TsWebExtensionEngine { if (!skipLimitsCheck) { await RulesLimitsService.checkFiltersLimitsChange(this.update.bind(this)); } + + if (await RulesLimitsService.areFilterLimitsExceeded()) { + toasts.showRuleLimitsAlert(); + } } /** @@ -210,12 +204,16 @@ export class Engine implements TsWebExtensionEngine { * Sets the filtering state. * * @param isFilteringEnabled - The filtering state. + * + * Note: we do not pass the parameter to engine because we suppose that + * settings already changed and tswebextension will generate configuration + * itself based on the current settings. */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars public async setFilteringState(isFilteringEnabled: boolean): Promise { - if (isFilteringEnabled) { - await this.stop(); - } else { - await this.start(); - } + // Configure tswebextension with the new settings without checking limits + // if we paused filtering. + const skipCheck = isFilteringEnabled === false; + await this.update(skipCheck); } } diff --git a/Extension/src/background/schema/settings/main.ts b/Extension/src/background/schema/settings/main.ts index 9a58eed360..065fda230b 100644 --- a/Extension/src/background/schema/settings/main.ts +++ b/Extension/src/background/schema/settings/main.ts @@ -26,6 +26,8 @@ export enum SettingOption { DisableDetectFilters = 'detect-filters-disabled', DisableSafebrowsing = 'safebrowsing-disabled', FiltersUpdatePeriod = 'filters-update-period', + // Is filtering disabled or not. + DisableFiltering = 'adguard-disabled', // Extension specific settings. UseOptimizedFilters = 'use-optimized-filters', @@ -65,9 +67,6 @@ export enum SettingOption { Metadata = 'filters-metadata', I18nMetadata = 'filters-i18n-metadata', CustomFilters = 'custom-filters', - - // Allowlist domains. - DisableFiltering = 'adguard-disabled', } // Setting options may be stringified, use preprocessors for correct type casting diff --git a/Extension/src/background/services/locale-detect.ts b/Extension/src/background/services/locale-detect.ts index b71a9b0cf1..ef11587b12 100644 --- a/Extension/src/background/services/locale-detect.ts +++ b/Extension/src/background/services/locale-detect.ts @@ -216,7 +216,7 @@ export class LocaleDetect { changeInfo: Tabs.OnUpdatedChangeInfoType, tab: Tabs.Tab, ): Promise { - if (tab.status === 'complete') { + if (tab.status === 'complete' && !__IS_MV3__) { await this.detectTabLanguage(tab); } } @@ -331,6 +331,8 @@ export class LocaleDetect { const disabledFiltersIds = filterIds.filter(filterId => !FiltersApi.isFilterEnabled(filterId)); + // TODO: Check, do we really need always enable language group, + // even if user disabled it manually? // Always enable language filters group. groupStateStorage.enableGroups([AntibannerGroupsId.LanguageFiltersGroupId]); diff --git a/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts b/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts index 1f6e176f41..63f95ead45 100644 --- a/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts +++ b/Extension/src/background/services/rules-limits/rules-limits-service-mv3.ts @@ -17,7 +17,6 @@ */ import browser from 'webextension-polyfill'; -import { isEqual } from 'lodash-es'; import { TooManyRegexpRulesError, @@ -38,7 +37,7 @@ import { type FilterMetadata, FiltersApi, } from '../../api'; -import { filterStateStorage } from '../../storages'; +import { filterStateStorage, settingsStorage } from '../../storages'; import { rulesLimitsStorage } from '../../storages/rules-limits'; import { rulesLimitsStorageDataValidator } from '../../schema/rules-limits'; import { logger } from '../../../common/logger'; @@ -46,6 +45,8 @@ import { canEnableStaticFilterSchema, canEnableStaticGroupSchema } from '../../. // Note: due to circular dependencies, import message-handler.ts after all // other imports. import { messageHandler } from '../../message-handler'; +import { arraysAreEqual } from '../../utils/arrays-are-equal'; +import { SettingOption } from '../../schema/settings/main'; import type { StaticLimitsCheckResult, @@ -85,7 +86,7 @@ export class RulesLimitsService { /** * Subscribes to messages from the options' page. */ - public init(): void { + public async init(): Promise { // Rules limits page overall status with all counters. messageHandler.addListener(MessageType.GetRulesLimitsCountersMv3, this.onGetRulesLimitsCounters.bind(this)); @@ -101,6 +102,9 @@ export class RulesLimitsService { MessageType.ClearRulesLimitsWarningMv3, RulesLimitsService.cleanExpectedEnabledFilters, ); + + // First read from storage and set data to cache. + await RulesLimitsService.initStorage(); } /** @@ -231,8 +235,8 @@ export class RulesLimitsService { */ private static getDynamicRulesEnabledCount(result: ConfigurationResult): number { const rulesLimitExceedErr = RulesLimitsService.getRulesLimitExceedErr(result); - const declarativeRulesCount = result.dynamicRules?.ruleSet.getRulesCount(); - return rulesLimitExceedErr?.numberOfMaximumRules || declarativeRulesCount || 0; + const declarativeRulesCount = result.dynamicRules?.ruleSet.getRulesCount() || 0; + return rulesLimitExceedErr?.numberOfMaximumRules || declarativeRulesCount; } /** @@ -265,8 +269,8 @@ export class RulesLimitsService { */ private static getDynamicRulesRegexpsEnabledCount(result: ConfigurationResult): number { const regexpRulesLimitExceedErr = RulesLimitsService.getRegexpRulesLimitExceedErr(result); - const regexpsCount = result.dynamicRules?.ruleSet.getRegexpRulesCount(); - return (regexpsCount || 0) + (regexpRulesLimitExceedErr?.excludedRulesIds.length || 0); + const regexpsCount = result.dynamicRules?.ruleSet.getRegexpRulesCount() || 0; + return regexpsCount + (regexpRulesLimitExceedErr?.excludedRulesIds.length || 0); } /** @@ -281,14 +285,27 @@ export class RulesLimitsService { } /** - * Returns actually enabled filters. + * Returns filters which marked as enabled in storage. * - * @returns Actually enabled filters. + * @returns Filters which marked as enabled in storage. */ - private static getActuallyEnabledFilters(): number[] { + public static getExpectedEnabledFilters(): number[] { return FiltersApi.getEnabledFiltersWithMetadata() + // Ignore custom filters because they are user-defined and conversion + // of them is going via dynamic part of DNR rules. .filter((f) => !CustomFilterApi.isCustomFilter(f.filterId)) - .map((f) => f.filterId); + .map((filter) => filter.filterId); + } + + /** + * Returns filters which rulesets (we have 1 to 1 relation) actually enabled. + * + * @returns Filters which rulesets (we have 1 to 1 relation) actually enabled. + */ + private static async getActuallyEnabledFilters(): Promise { + const enabledRuleSetsIds = await chrome.declarativeNetRequest.getEnabledRulesets(); + + return enabledRuleSetsIds.map((id) => Number.parseInt(id.slice(RULE_SET_NAME_PREFIX.length), 10)); } /** @@ -319,9 +336,9 @@ export class RulesLimitsService { staticRulesMaximumCount, staticRulesRegexpsEnabledCount: RulesLimitsService.getStaticRulesRegexpsCount(result, filters), staticRulesRegexpsMaxCount: MAX_NUMBER_OF_REGEX_RULES, - actuallyEnabledFilters: RulesLimitsService.getActuallyEnabledFilters(), - expectedEnabledFilters: rulesLimitsStorage.getData(), - areFilterLimitsExceeded: RulesLimitsService.areFilterLimitsExceeded(), + actuallyEnabledFilters: await RulesLimitsService.getActuallyEnabledFilters(), + expectedEnabledFilters: RulesLimitsService.getExpectedEnabledFilters(), + areFilterLimitsExceeded: await RulesLimitsService.areFilterLimitsExceeded(), }; } @@ -330,14 +347,31 @@ export class RulesLimitsService { * * @returns True if the filter limits are exceeded, false otherwise. */ - public static areFilterLimitsExceeded(): boolean { - const actuallyEnabledFilters = RulesLimitsService.getActuallyEnabledFilters().length; - const expectedEnabledFilters = RulesLimitsService.getExpectedEnabledFilters().length; - - // limits are exceeded if the number of actually enabled filters is fewer - // than the number of filters that should be enabled (expected enabled filters) - // and everything in manifest is disabled - return actuallyEnabledFilters < expectedEnabledFilters; + public static async areFilterLimitsExceeded(): Promise { + const cachedEnabledFilters = rulesLimitsStorage.getData(); + const actuallyEnabledFilters = await RulesLimitsService.getActuallyEnabledFilters(); + + const filteringDisabled = settingsStorage.get(SettingOption.DisableFiltering); + if (actuallyEnabledFilters.length === 0 && filteringDisabled) { + return false; + } + + // If there are some filters in storage - it means, that last used + // configuration is damaged and we should notify user about them until + // he will fix configuration or turn off this notification. + // This case needed to save warning if service worker will restart and + // after successful configuration update we will not notify user about + // changed configuration or user paused and resumed protection. + if (cachedEnabledFilters.length > 0 && !arraysAreEqual(actuallyEnabledFilters, cachedEnabledFilters)) { + return true; + } + + // Else we do a full check of the current configuration: if filters from + // configuration are not same as enabled filters - it means that browser + // declined update of the configuration and we should notify user about it. + const expectedEnabledFilters = RulesLimitsService.getExpectedEnabledFilters(); + + return !arraysAreEqual(actuallyEnabledFilters, expectedEnabledFilters); } /** @@ -352,35 +386,34 @@ export class RulesLimitsService { /** * Check if filters limits have changed and update filters state if needed. * - * @param update Function to update filters state. + * @param update Function to update filters state and configure tswebextension. */ public static async checkFiltersLimitsChange(update: (skipCheck: boolean) => Promise): Promise { - const expectedEnabledFilters = FiltersApi.getEnabledFiltersWithMetadata() - .filter((f) => !CustomFilterApi.isCustomFilter(f.filterId)) - .map((filter) => filter.filterId) - .sort((a, b) => a - b); - - const actuallyEnabledFilters = (await chrome.declarativeNetRequest.getEnabledRulesets()) - .map((s) => Number.parseInt(s.slice(RULE_SET_NAME_PREFIX.length), 10)) - .sort((a, b) => a - b); - - const isStateBroken = !isEqual(expectedEnabledFilters, actuallyEnabledFilters); + const isStateBroken = await RulesLimitsService.areFilterLimitsExceeded(); - const filtersToDisable = expectedEnabledFilters.filter((id) => !actuallyEnabledFilters.includes(id)); + // If state is broken - disable filters that were expected to be enabled + // and configure tswebextension without them to activate minimal possible + // defense. + if (isStateBroken) { + const expectedEnabledFilters = RulesLimitsService.getExpectedEnabledFilters(); + const actuallyEnabledFilters = await RulesLimitsService.getActuallyEnabledFilters(); - // Save last expected to be enabled filters to notify UI. + const filtersToDisable = expectedEnabledFilters.filter((id) => !actuallyEnabledFilters.includes(id)); - if (isStateBroken) { + // Save last expected to be enabled filters to notify UI about them. await rulesLimitsStorage.setData(expectedEnabledFilters); + filterStateStorage.enableFilters(actuallyEnabledFilters); filterStateStorage.disableFilters(filtersToDisable); + // Update tswebextension configuration without check limitations to + // skip recursion. await update(true); } else { - const prevExpectedEnabledFilters = await RulesLimitsService.getFromStorage(); // If state is not broken - clear list of "broken" filters + const prevExpectedEnabledFilters = rulesLimitsStorage.getData(); if (prevExpectedEnabledFilters.length > 0) { - await rulesLimitsStorage.setData([]); + await this.cleanExpectedEnabledFilters(); } } } @@ -393,37 +426,25 @@ export class RulesLimitsService { } /** - * Returns an array of previously set filter ids from storage. + * Read stringified domains array from specified allowlist storage, + * parse it and set memory cache. * - * @returns An array of previously set filter ids. + * If data is not exist, set default data. */ - private static async getFromStorage(): Promise { - let data: number[] = []; + private static async initStorage(): Promise { try { const storageData = await rulesLimitsStorage.read(); if (typeof storageData === 'string') { - data = rulesLimitsStorageDataValidator.parse(JSON.parse(storageData)); - rulesLimitsStorage.setCache(data); + const validatedData = rulesLimitsStorageDataValidator.parse(JSON.parse(storageData)); + rulesLimitsStorage.setCache(validatedData); } else { - data = []; - await rulesLimitsStorage.setData(data); + await this.cleanExpectedEnabledFilters(); } } catch (e) { // eslint-disable-next-line max-len logger.warn(`Cannot parse data from "${rulesLimitsStorage.key}" storage, set default states. Origin error: `, e); - data = []; - await rulesLimitsStorage.setData(data); + await this.cleanExpectedEnabledFilters(); } - return data; - } - - /** - * Returns previously enabled filters. - * - * @returns Previously enabled filters. - */ - public static getExpectedEnabledFilters(): number[] { - return rulesLimitsStorage.getData(); } /** @@ -448,7 +469,7 @@ export class RulesLimitsService { * * @returns Promise that resolves with possible limitations. */ - private static getStaticFiltersLimitations(): StaticLimitsCheckResult { + private static async getStaticFiltersLimitations(): Promise { const enabledFiltersCount = RulesLimitsService.getStaticEnabledFiltersCount(); if (enabledFiltersCount === MAX_NUMBER_OF_ENABLED_STATIC_RULESETS) { return { @@ -463,13 +484,15 @@ export class RulesLimitsService { }; } - if (RulesLimitsService.areFilterLimitsExceeded()) { + const areFilterLimitsExceeded = await RulesLimitsService.areFilterLimitsExceeded(); + if (areFilterLimitsExceeded) { + const actuallyEnabledFilters = await RulesLimitsService.getActuallyEnabledFilters(); return { ok: false, data: { type: 'static', filtersCount: { - current: RulesLimitsService.getActuallyEnabledFilters().length, + current: actuallyEnabledFilters.length, expected: RulesLimitsService.getExpectedEnabledFilters().length, }, }, diff --git a/Extension/src/background/services/settings.ts b/Extension/src/background/services/settings.ts index 84d0aef23b..69b9c4fadd 100644 --- a/Extension/src/background/services/settings.ts +++ b/Extension/src/background/services/settings.ts @@ -138,9 +138,9 @@ export class SettingsService { * * @returns Item of {@link GetOptionsDataResponse}. */ - static getOptionsData(): GetOptionsDataResponse { + static async getOptionsData(): Promise { const areFilterLimitsExceeded = __IS_MV3__ - ? RulesLimitsService.areFilterLimitsExceeded() + ? await RulesLimitsService.areFilterLimitsExceeded() : false; return { diff --git a/Extension/src/background/services/ui/popup.ts b/Extension/src/background/services/ui/popup.ts index a3aace1c48..29c825bc55 100644 --- a/Extension/src/background/services/ui/popup.ts +++ b/Extension/src/background/services/ui/popup.ts @@ -91,7 +91,7 @@ export class PopupService { const hasUserRulesToReset = await UserRulesApi.hasRulesForUrl(tabContext.info.url); const areFilterLimitsExceeded = __IS_MV3__ - ? RulesLimitsService.areFilterLimitsExceeded() + ? await RulesLimitsService.areFilterLimitsExceeded() : false; return { diff --git a/Extension/src/background/utils/arrays-are-equal.ts b/Extension/src/background/utils/arrays-are-equal.ts new file mode 100644 index 0000000000..bc76fe4a99 --- /dev/null +++ b/Extension/src/background/utils/arrays-are-equal.ts @@ -0,0 +1,34 @@ +/** + * @file + * This file is part of AdGuard Browser Extension (https://github.com/AdguardTeam/AdguardBrowserExtension). + * + * AdGuard Browser Extension is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AdGuard Browser Extension is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AdGuard Browser Extension. If not, see . + */ + +import { isEqual } from 'lodash'; + +/** + * Compare two arrays and return true if they are equal. + * + * @param arrA Array A. + * @param arrB Array B. + * + * @returns True if arrays are equal. + */ +export const arraysAreEqual = (arrA: number[], arrB: number[]): boolean => { + return isEqual( + arrA.sort((a, b) => a - b), + arrB.sort((a, b) => a - b), + ); +}; diff --git a/Extension/src/background/utils/string-storage.ts b/Extension/src/background/utils/string-storage.ts index be92a215cc..fa0d60ce8e 100644 --- a/Extension/src/background/utils/string-storage.ts +++ b/Extension/src/background/utils/string-storage.ts @@ -19,6 +19,8 @@ import { StorageInterface } from '../../common/storage'; /** * Class for managing data that is persisted as string in another key value storage. + * + * TODO: Add init method to read data from storage and set it to cache. */ export class StringStorage { // parent storage key diff --git a/Extension/src/pages/options/components/RulesLimits/RulesLimits.tsx b/Extension/src/pages/options/components/RulesLimits/RulesLimits.tsx index e71a3e27c9..a567d129b0 100644 --- a/Extension/src/pages/options/components/RulesLimits/RulesLimits.tsx +++ b/Extension/src/pages/options/components/RulesLimits/RulesLimits.tsx @@ -39,6 +39,8 @@ import { Warning } from './Warning'; import './rules-limits.pcss'; +// TODO: We can add an one additional possible step to remove warning: try to +// enable some filter and if configuration will success - warning will be removed. export const RulesLimits = observer(() => { /** * Threshold for highlighting the number of enabled rules. From 8514ced79b3f6dce4f00a973bc80eff8c5d1c0ae Mon Sep 17 00:00:00 2001 From: Slava Leleka Date: Mon, 1 Jul 2024 16:56:02 +0300 Subject: [PATCH 4/4] fix rule limits warning no filters text Squashed commit of the following: commit 6b3d3c083815ee4b5ee72c9ae0cae53748ec4762 Merge: 0d5e2c30b aa4891f77 Author: Slava Leleka Date: Mon Jul 1 16:39:04 2024 +0300 Merge branch 'v5.0' into fix/rule-limits-warning-subheading-01 commit 0d5e2c30b8cc4b6fcce84389b756206f6c686835 Author: Slava Leleka Date: Mon Jul 1 16:08:23 2024 +0300 fix rule limits warning no filters text --- Extension/_locales/en/messages.json | 3 --- .../options/components/RulesLimits/Warning/Warning.tsx | 10 +++++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Extension/_locales/en/messages.json b/Extension/_locales/en/messages.json index 63f03d23a9..c8564d0627 100644 --- a/Extension/_locales/en/messages.json +++ b/Extension/_locales/en/messages.json @@ -770,9 +770,6 @@ "options_rule_limits_warning_list_enabled_now_title": { "message": "Filters enabled now" }, - "options_rule_limits_warning_nothing_enabled_now_title": { - "message": "No filters enabled now" - }, "options_rule_limits_warning_actions_title": { "message": "Your possible actions" }, diff --git a/Extension/src/pages/options/components/RulesLimits/Warning/Warning.tsx b/Extension/src/pages/options/components/RulesLimits/Warning/Warning.tsx index 588e882705..e188820bf4 100644 --- a/Extension/src/pages/options/components/RulesLimits/Warning/Warning.tsx +++ b/Extension/src/pages/options/components/RulesLimits/Warning/Warning.tsx @@ -105,15 +105,15 @@ export const Warning = ({
+ {translator.getMessage('options_rule_limits_warning_list_enabled_now_title')} +
+
{ actuallyEnabledFilterNames.trim().length === 0 - ? translator.getMessage('options_rule_limits_warning_nothing_enabled_now_title') - : translator.getMessage('options_rule_limits_warning_list_enabled_now_title') + ? translator.getMessage('options_filters_no_enabled') + : actuallyEnabledFilterNames }
-
- {actuallyEnabledFilterNames} -