diff --git a/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts b/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts index 38a4ff41015b..2d590928b1b2 100644 --- a/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts +++ b/components/brave_extension/extension/brave_extension/actions/shieldsPanelActions.ts @@ -138,6 +138,23 @@ export const shieldsReady: actions.ShieldsReady = () => { } } +export const generateClassIdStylesheet = (tabId: number, classes: string[], ids: string[]) => { + return { + type: types.GENERATE_CLASS_ID_STYLESHEET, + tabId, + classes, + ids + } +} + +export const cosmeticFilterRuleExceptions = (tabId: number, exceptions: string[]) => { + return { + type: types.COSMETIC_FILTER_RULE_EXCEPTIONS, + tabId, + exceptions + } +} + export const contentScriptsLoaded: actions.ContentScriptsLoaded = (tabId: number, url: string) => { return { type: types.CONTENT_SCRIPTS_LOADED, diff --git a/components/brave_extension/extension/brave_extension/background/api/cosmeticFilterAPI.ts b/components/brave_extension/extension/brave_extension/background/api/cosmeticFilterAPI.ts index 3065539b993d..1ee5d0efeeb7 100644 --- a/components/brave_extension/extension/brave_extension/background/api/cosmeticFilterAPI.ts +++ b/components/brave_extension/extension/brave_extension/background/api/cosmeticFilterAPI.ts @@ -2,6 +2,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +import shieldsPanelActions from '../actions/shieldsPanelActions' + const generateCosmeticBlockingStylesheet = (hideSelectors: string[], styleSelectors: any) => { let stylesheet = '' if (hideSelectors.length > 0) { @@ -18,6 +20,16 @@ const generateCosmeticBlockingStylesheet = (hideSelectors: string[], styleSelect return stylesheet } +export const injectClassIdStylesheet = (tabId: number, classes: string[], ids: string[], exceptions: string[]) => { + chrome.braveShields.classIdStylesheet(classes, ids, exceptions, stylesheet => { + chrome.tabs.insertCSS(tabId, { + code: stylesheet, + cssOrigin: 'user', + runAt: 'document_start' + }) + }) +} + export const addSiteCosmeticFilter = async (origin: string, cssfilter: string) => { chrome.storage.local.get('cosmeticFilterList', (storeData = {}) => { let storeList = Object.assign({}, storeData.cosmeticFilterList) @@ -54,17 +66,14 @@ export const applyAdblockCosmeticFilters = (tabId: number, hostname: string) => }) } - chrome.tabs.sendMessage(tabId, { - type: 'cosmeticFilterGenericExceptions', - exceptions: resources.exceptions - }) - if (resources.injected_script) { chrome.tabs.executeScript(tabId, { code: resources.injected_script, runAt: 'document_start' }) } + + shieldsPanelActions.cosmeticFilterRuleExceptions(tabId, resources.exceptions) }) } diff --git a/components/brave_extension/extension/brave_extension/background/events/cosmeticFilterEvents.ts b/components/brave_extension/extension/brave_extension/background/events/cosmeticFilterEvents.ts index aba2a7670395..99b92f25eed9 100644 --- a/components/brave_extension/extension/brave_extension/background/events/cosmeticFilterEvents.ts +++ b/components/brave_extension/extension/brave_extension/background/events/cosmeticFilterEvents.ts @@ -51,13 +51,15 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { break } case 'classIdStylesheet': { - chrome.braveShields.classIdStylesheet(msg.classes, msg.ids, msg.exceptions, stylesheet => { - chrome.tabs.insertCSS({ - code: stylesheet, - cssOrigin: 'user', - runAt: 'document_start' - }) - }) + const tab = sender.tab + if (tab === undefined) { + break + } + const tabId = tab.id + if (tabId === undefined) { + break + } + shieldsPanelActions.generateClassIdStylesheet(tabId, msg.classes, msg.ids) break } case 'contentScriptsLoaded': { diff --git a/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts b/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts index 6c676c7a32e4..8db43e0c2cfa 100644 --- a/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts +++ b/components/brave_extension/extension/brave_extension/background/reducers/shieldsPanelReducer.ts @@ -34,6 +34,7 @@ import { } from '../api/shieldsAPI' import { reloadTab } from '../api/tabsAPI' import { + injectClassIdStylesheet, applyAdblockCosmeticFilters, applyCSSCosmeticFilters } from '../api/cosmeticFilterAPI' @@ -346,6 +347,31 @@ export default function shieldsPanelReducer ( }) break } + case shieldsPanelTypes.GENERATE_CLASS_ID_STYLESHEET: { + const tabData = state.tabs[action.tabId] + if (!tabData) { + console.error('Active tab not found') + break + } + const exceptions = tabData.cosmeticFilters.ruleExceptions + + // setTimeout is used to prevent injectClassIdStylesheet from calling + // another Redux function immediately + setTimeout(() => injectClassIdStylesheet(action.tabId, action.classes, action.ids, exceptions), 0) + break + } + case shieldsPanelTypes.COSMETIC_FILTER_RULE_EXCEPTIONS: { + const tabData = state.tabs[action.tabId] + if (!tabData) { + console.error('Active tab not found') + break + } + state = shieldsPanelState.saveCosmeticFilterRuleExceptions(state, action.tabId, action.exceptions) + chrome.tabs.sendMessage(action.tabId, { + type: 'cosmeticFilterGenericExceptions' + }) + break + } case shieldsPanelTypes.CONTENT_SCRIPTS_LOADED: { const tabData = state.tabs[action.tabId] if (!tabData) { diff --git a/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts b/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts index 5f760968c983..faea8d578819 100644 --- a/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts +++ b/components/brave_extension/extension/brave_extension/constants/shieldsPanelTypes.ts @@ -20,4 +20,6 @@ export const SET_FINAL_SCRIPTS_BLOCKED_ONCE_STATE = 'SET_FINAL_SCRIPTS_BLOCKED_O export const SET_ADVANCED_VIEW_FIRST_ACCESS = 'SET_ADVANCED_VIEW_FIRST_ACCESS' export const TOGGLE_ADVANCED_VIEW = 'TOGGLE_ADVANCED_VIEW' export const SHIELDS_READY = 'SHIELDS_READY' +export const GENERATE_CLASS_ID_STYLESHEET = 'GENERATE_CLASS_ID_STYLESHEET' +export const COSMETIC_FILTER_RULE_EXCEPTIONS = 'COSMETIC_FILTER_RULE_EXCEPTIONS' export const CONTENT_SCRIPTS_LOADED = 'CONTENT_SCRIPTS_LOADED' diff --git a/components/brave_extension/extension/brave_extension/content_cosmetic.ts b/components/brave_extension/extension/brave_extension/content_cosmetic.ts index 8b9de5bb6a59..9e95a141cba8 100644 --- a/components/brave_extension/extension/brave_extension/content_cosmetic.ts +++ b/components/brave_extension/extension/brave_extension/content_cosmetic.ts @@ -1,5 +1,3 @@ -let genericExceptions: Array | undefined = undefined - const queriedIds = new Set() const queriedClasses = new Set() const regexWhitespace = /\s/ @@ -45,8 +43,7 @@ const handleNewNodes = (newNodes: Element[]) => { chrome.runtime.sendMessage({ type: 'classIdStylesheet', classes, - ids, - exceptions: genericExceptions + ids }) } @@ -72,8 +69,6 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { const action = typeof msg === 'string' ? msg : msg.type switch (action) { case 'cosmeticFilterGenericExceptions': { - genericExceptions = msg.exceptions - let allNodes = Array.from(document.querySelectorAll('[id],[class]')) handleNewNodes(allNodes) applyCosmeticFilterMutationObserver() diff --git a/components/brave_extension/extension/brave_extension/state/shieldsPanelState.ts b/components/brave_extension/extension/brave_extension/state/shieldsPanelState.ts index 7ffedd1f8f16..aa1ef65323bb 100644 --- a/components/brave_extension/extension/brave_extension/state/shieldsPanelState.ts +++ b/components/brave_extension/extension/brave_extension/state/shieldsPanelState.ts @@ -112,6 +112,12 @@ export const updateResourceBlocked: shieldState.UpdateResourceBlocked = (state, return { ...state, tabs } } +export const saveCosmeticFilterRuleExceptions: shieldState.SaveCosmeticFilterRuleExceptions = (state, tabId, exceptions) => { + const tabs: shieldState.Tabs = { ...state.tabs } + tabs[tabId] = { ...tabs[tabId], ...{ cosmeticFilters: { ...tabs[tabId].cosmeticFilters, ruleExceptions: exceptions } } } + return { ...state, tabs } +} + export const resetBlockingStats: shieldState.ResetBlockingStats = (state, tabId) => { const tabs: shieldState.Tabs = { ...state.tabs } tabs[tabId] = { ...tabs[tabId], ...{ adsBlocked: 0, trackersBlocked: 0, httpsRedirected: 0, javascriptBlocked: 0, fingerprintingBlocked: 0 } } diff --git a/components/brave_extension/extension/brave_extension/types/actions/shieldsPanelActions.ts b/components/brave_extension/extension/brave_extension/types/actions/shieldsPanelActions.ts index 8a736b190678..3aa6f3a29e2d 100644 --- a/components/brave_extension/extension/brave_extension/types/actions/shieldsPanelActions.ts +++ b/components/brave_extension/extension/brave_extension/types/actions/shieldsPanelActions.ts @@ -173,6 +173,27 @@ export interface ShieldsReady { (): ShieldsReadyReturn } +interface GenerateClassIdStylesheetReturn { + type: types.GENERATE_CLASS_ID_STYLESHEET, + tabId: number, + classes: string[], + ids: string[] +} + +export interface GenerateClassIdStylesheet { + (tabId: number, classes: string[], ids: string[]): GenerateClassIdStylesheetReturn +} + +interface CosmeticFilterRuleExceptionsReturn { + type: types.COSMETIC_FILTER_RULE_EXCEPTIONS, + tabId: number, + exceptions: string[] +} + +export interface CosmeticFilterRuleExceptions { + (tabId: number, exceptions: string[]): CosmeticFilterRuleExceptionsReturn +} + interface ContentScriptsLoadedReturn { type: types.CONTENT_SCRIPTS_LOADED, tabId: number, @@ -201,4 +222,6 @@ export type shieldPanelActions = SetFinalScriptsBlockedStateReturn | SetAdvancedViewFirstAccessReturn | ShieldsReadyReturn | + GenerateClassIdStylesheetReturn | + CosmeticFilterRuleExceptionsReturn | ContentScriptsLoadedReturn diff --git a/components/brave_extension/extension/brave_extension/types/adblock/adblockTypes.ts b/components/brave_extension/extension/brave_extension/types/adblock/adblockTypes.ts index 3503d66c956e..d8ab3dca6cf0 100644 --- a/components/brave_extension/extension/brave_extension/types/adblock/adblockTypes.ts +++ b/components/brave_extension/extension/brave_extension/types/adblock/adblockTypes.ts @@ -6,3 +6,7 @@ export type BlockTypes = 'ads' | 'trackers' | 'httpUpgradableResources' | 'javas export type BlockOptions = 'allow' | 'block' export type BlockFPOptions = 'allow' | 'block' | 'block_third_party' export type BlockCookiesOptions = 'allow' | 'block' | 'block_third_party' + +export interface CosmeticFilteringState { + ruleExceptions: Array +} diff --git a/components/brave_extension/extension/brave_extension/types/constants/shieldsPanelTypes.ts b/components/brave_extension/extension/brave_extension/types/constants/shieldsPanelTypes.ts index fec88c90ae92..05c2568a3cbb 100644 --- a/components/brave_extension/extension/brave_extension/types/constants/shieldsPanelTypes.ts +++ b/components/brave_extension/extension/brave_extension/types/constants/shieldsPanelTypes.ts @@ -22,4 +22,6 @@ export type SET_FINAL_SCRIPTS_BLOCKED_ONCE_STATE = typeof types.SET_FINAL_SCRIPT export type SET_ADVANCED_VIEW_FIRST_ACCESS = typeof types.SET_ADVANCED_VIEW_FIRST_ACCESS export type TOGGLE_ADVANCED_VIEW = typeof types.TOGGLE_ADVANCED_VIEW export type SHIELDS_READY = typeof types.SHIELDS_READY +export type GENERATE_CLASS_ID_STYLESHEET = typeof types.GENERATE_CLASS_ID_STYLESHEET +export type COSMETIC_FILTER_RULE_EXCEPTIONS = typeof types.COSMETIC_FILTER_RULE_EXCEPTIONS export type CONTENT_SCRIPTS_LOADED = typeof types.CONTENT_SCRIPTS_LOADED diff --git a/components/brave_extension/extension/brave_extension/types/state/shieldsPannelState.ts b/components/brave_extension/extension/brave_extension/types/state/shieldsPannelState.ts index 9f6f51f626e5..2738c15456b2 100644 --- a/components/brave_extension/extension/brave_extension/types/state/shieldsPannelState.ts +++ b/components/brave_extension/extension/brave_extension/types/state/shieldsPannelState.ts @@ -3,6 +3,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ import { BlockOptions, BlockTypes, BlockFPOptions, BlockCookiesOptions } from '../other/blockTypes' +import { CosmeticFilteringState } from '../adblock/adblockTypes' import { NoScriptInfo } from '../other/noScriptInfo' export interface Tab { @@ -29,6 +30,7 @@ export interface Tab { trackersBlockedResources: Array httpsRedirectedResources: Array fingerprintingBlockedResources: Array + cosmeticFilters: CosmeticFilteringState } export interface Tabs { @@ -86,6 +88,10 @@ export interface UpdateResourceBlocked { (state: State, tabId: number, blockType: BlockTypes, subresource: string): State } +export interface SaveCosmeticFilterRuleExceptions { + (state: State, tabId: number, exceptions: Array): State +} + export interface ResetBlockingStats { (state: State, tabId: number): State }