diff --git a/add-on/src/lib/ipfs-companion.js b/add-on/src/lib/ipfs-companion.js index 82a8ab2bd..480975b02 100644 --- a/add-on/src/lib/ipfs-companion.js +++ b/add-on/src/lib/ipfs-companion.js @@ -22,7 +22,7 @@ import { createRequestModifier } from './ipfs-request.js' import createNotifier from './notifier.js' import { runPendingOnInstallTasks } from './on-installed.js' import { guiURLString, migrateOptions, optionDefaults, safeURL, storeMissingOptions } from './options.js' -import { getExtraInfoSpec } from './redirect-handler/blockOrObserve.js' +import { cleanupRules, getExtraInfoSpec } from './redirect-handler/blockOrObserve.js' import createRuntimeChecks from './runtime-checks.js' import { initState, offlinePeerCount } from './state.js' @@ -521,6 +521,7 @@ export default async function init (inQuickImport = false) { try { const oldColor = colorArraytoHex(await browser.action.getBadgeBackgroundColor({})) if (badgeColor !== oldColor) { + await cleanupRules(true) await browser.action.setBadgeBackgroundColor({ color: badgeColor }) await setBrowserActionIcon(badgeIcon) } @@ -577,7 +578,7 @@ export default async function init (inQuickImport = false) { } } - async function onStorageChange (changes, area) { + async function onStorageChange (changes) { let shouldReloadExtension = false let shouldRestartIpfsClient = false let shouldStopIpfsClient = false @@ -696,6 +697,8 @@ export default async function init (inQuickImport = false) { browser.tabs.reload() // async reload of options page to keep it alive await browser.runtime.reload() } + log('storage change processed') + // Post update to Browser Action (if exists) -- this gives UX a snappy feel await sendStatusUpdateToBrowserAction() } diff --git a/add-on/src/lib/redirect-handler/blockOrObserve.ts b/add-on/src/lib/redirect-handler/blockOrObserve.ts index 9c07341fc..f8f23789d 100644 --- a/add-on/src/lib/redirect-handler/blockOrObserve.ts +++ b/add-on/src/lib/redirect-handler/blockOrObserve.ts @@ -12,8 +12,6 @@ const log = debug('ipfs-companion:redirect-handler:blockOrObserve') log.error = debug('ipfs-companion:redirect-handler:blockOrObserve:error') export const DEFAULT_NAMESPACES = new Set(['ipfs', 'ipns']) - -export const GLOBAL_STATE_CHANGE = 'GLOBAL_STATE_CHANGE' export const GLOBAL_STATE_OPTION_CHANGE = 'GLOBAL_STATE_OPTION_CHANGE' export const DELETE_RULE_REQUEST = 'DELETE_RULE_REQUEST' export const DELETE_RULE_REQUEST_SUCCESS = 'DELETE_RULE_REQUEST_SUCCESS' @@ -32,7 +30,7 @@ interface redirectHandlerInput { getPort: (state: CompanionState) => string } -type messageToSelfType = typeof GLOBAL_STATE_CHANGE | typeof GLOBAL_STATE_OPTION_CHANGE | typeof DELETE_RULE_REQUEST +type messageToSelfType = typeof GLOBAL_STATE_OPTION_CHANGE | typeof DELETE_RULE_REQUEST interface messageToSelf { type: messageToSelfType value?: string | Record @@ -50,36 +48,38 @@ export const defaultNSRegexStr = `(${[...DEFAULT_NAMESPACES].join('|')})` export const supportsBlock = (): boolean => !(browser.declarativeNetRequest?.MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES > 0) /** - * Notify self about state change. - * @returns void + * Sends message to self to notify about change. + * + * @param msg */ -export async function notifyStateChange (): Promise { - return await sendMessageToSelf(GLOBAL_STATE_CHANGE) +async function sendMessageToSelf (msg: messageToSelfType, value?: any): Promise { + // this check ensures we don't send messages to ourselves if blocking mode is enabled. + if (!supportsBlock()) { + const message: messageToSelf = { type: msg, value } + // on FF, this call waits for the response from the listener. + // on Chrome, this needs a callback. + await browser.runtime.sendMessage(message) + } } /** * Notify self about option change. + * * @returns void */ export async function notifyOptionChange (): Promise { + log('notifyOptionChange') return await sendMessageToSelf(GLOBAL_STATE_OPTION_CHANGE) } -export async function notifyDeleteRule (id: number): Promise { - return await sendMessageToSelf(DELETE_RULE_REQUEST, id) -} - /** - * Sends message to self to notify about change. + * Notify self about rule deletion. * - * @param msg + * @param id number + * @returns void */ -async function sendMessageToSelf (msg: messageToSelfType, value?: any): Promise { - // this check ensures we don't send messages to ourselves if blocking mode is enabled. - if (!supportsBlock()) { - const message: messageToSelf = { type: msg } - await browser.runtime.sendMessage(message) - } +export async function notifyDeleteRule (id: number): Promise { + return await sendMessageToSelf(DELETE_RULE_REQUEST, id) } const savedRegexFilters: Map = new Map() @@ -205,7 +205,8 @@ async function cleanupRuleById (id: number): Promise { * @param {function} handlerFn */ function setupListeners (handlers: Record Promise>): void { - browser.runtime.onMessage.addListener(async ({ message: { type, value } }: { message: messageToSelf }): Promise => { + browser.runtime.onMessage.addListener(async (message: messageToSelf): Promise => { + const { type, value } = message if (type in handlers) { await handlers[type](value) } @@ -340,6 +341,23 @@ export function generateAddRule ( */ export function addRuleToDynamicRuleSetGenerator ( getState: () => CompanionState): (input: redirectHandlerInput) => Promise { + // setup listeners for the extension. + setupListeners({ + [GLOBAL_STATE_OPTION_CHANGE]: async (): Promise => { + log('GLOBAL_STATE_OPTION_CHANGE') + await cleanupRules(true) + await reconcileRulesAndRemoveOld(getState()) + }, + [DELETE_RULE_REQUEST]: async (value: number): Promise => { + if (value != null) { + await cleanupRuleById(value) + await browser.runtime.sendMessage({ type: DELETE_RULE_REQUEST_SUCCESS }) + } else { + await cleanupRules(true) + } + } + }) + // returning a closure to avoid passing `getState` as an argument to `addRuleToDynamicRuleSet`. return async function ({ originUrl, redirectUrl }: redirectHandlerInput): Promise { // update the rules so that the next request is handled correctly. @@ -378,24 +396,6 @@ export function addRuleToDynamicRuleSetGenerator ( } ) } - - setupListeners({ - [GLOBAL_STATE_CHANGE]: async (): Promise => { - await reconcileRulesAndRemoveOld(getState()) - }, - [GLOBAL_STATE_OPTION_CHANGE]: async (): Promise => { - await cleanupRules(true) - await reconcileRulesAndRemoveOld(getState()) - }, - [DELETE_RULE_REQUEST]: async (value: number): Promise => { - if (value != null) { - await cleanupRuleById(value) - await browser.runtime.sendMessage({ type: DELETE_RULE_REQUEST_SUCCESS }) - } else { - await cleanupRules(true) - } - } - }) // call to reconcile rules and remove old ones. await reconcileRulesAndRemoveOld(state) } diff --git a/add-on/src/lib/redirect-handler/subdomainRedirectRegexFilter.ts b/add-on/src/lib/redirect-handler/subdomainRedirectRegexFilter.ts index 8690d2134..fa73ed24d 100644 --- a/add-on/src/lib/redirect-handler/subdomainRedirectRegexFilter.ts +++ b/add-on/src/lib/redirect-handler/subdomainRedirectRegexFilter.ts @@ -31,7 +31,6 @@ export class SubdomainRedirectRegexFilter extends RegexFilter { const subdomainPart = urlParts.shift() as string // this needs to be computed for every iteration as the staticUrlParts changes const commonStaticUrlEnd = `\\.${escapeURLRegex(staticUrlParts.join('.'))}\\/${RULE_REGEX_ENDING}` - // this does not work for subdomains where namespace is not provided. // e.g. https://helia-identify.on.fleek.co/ // e.g. https://bafybeib3bzis4mejzsnzsb65od3rnv5ffit7vsllratddjkgfgq4wiamqu.on.fleek.co/ diff --git a/add-on/src/options/page.js b/add-on/src/options/page.js index 78b3537d2..dedbe8473 100644 --- a/add-on/src/options/page.js +++ b/add-on/src/options/page.js @@ -43,10 +43,10 @@ export default function optionsPage (state, emit) { // when global toggle is in "suspended" state return html`
- ${globalToggleForm({ - active: state.options.active, - onOptionChange - })} + ${globalToggleForm({ + active: state.options.active, + onOptionChange + })}
` } diff --git a/add-on/src/options/store.js b/add-on/src/options/store.js index c998f5033..961edd72f 100644 --- a/add-on/src/options/store.js +++ b/add-on/src/options/store.js @@ -3,7 +3,7 @@ import browser from 'webextension-polyfill' import { optionDefaults } from '../lib/options.js' -import { DELETE_RULE_REQUEST_SUCCESS, RULE_REGEX_ENDING, notifyDeleteRule, notifyOptionChange, notifyStateChange } from '../lib/redirect-handler/blockOrObserve.js' +import { DELETE_RULE_REQUEST_SUCCESS, RULE_REGEX_ENDING, notifyDeleteRule, notifyOptionChange } from '../lib/redirect-handler/blockOrObserve.js' import createRuntimeChecks from '../lib/runtime-checks.js' // The store contains and mutates the state for the app @@ -49,9 +49,6 @@ export default function optionStore (state, emitter) { emitter.on('optionChange', async ({ key, value }) => { browser.storage.local.set({ [key]: value }) - if (key === 'active') { - await notifyStateChange() - } await notifyOptionChange() }) diff --git a/add-on/src/popup/browser-action/store.js b/add-on/src/popup/browser-action/store.js index de5580cbe..0b7c5f815 100644 --- a/add-on/src/popup/browser-action/store.js +++ b/add-on/src/popup/browser-action/store.js @@ -7,7 +7,7 @@ import { optionsPage, welcomePage } from '../../lib/constants.js' import { contextMenuCopyAddressAtPublicGw, contextMenuCopyCanonicalAddress, contextMenuCopyCidAddress, contextMenuCopyPermalink, contextMenuCopyRawCid, contextMenuViewOnGateway } from '../../lib/context-menus.js' import { browserActionFilesCpImportCurrentTab } from '../../lib/ipfs-import.js' import { ipfsContentPath } from '../../lib/ipfs-path.js' -import { notifyStateChange } from '../../lib/redirect-handler/blockOrObserve.js' +import { notifyOptionChange } from '../../lib/redirect-handler/blockOrObserve.js' import { POSSIBLE_NODE_TYPES } from '../../lib/state.js' // The store contains and mutates the state for the app @@ -179,7 +179,11 @@ export default (state, emitter) => { } // console.dir('toggleSiteIntegrations', state) await browser.storage.local.set({ disabledOn, enabledOn }) - await notifyStateChange() + await notifyOptionChange() + // notifyOptionsChange call is async, sends a message to background and + // waits for it to resolve. However, that doesnt work the + // same way in Chrome and FF. So we need to wait a bit before reloading. + await new Promise(resolve => setTimeout(resolve, 200)) const path = ipfsContentPath(currentTab.url, { keepURIParams: true }) // Reload the current tab to apply updated redirect preference @@ -216,7 +220,7 @@ export default (state, emitter) => { state.swarmPeers = null state.isIpfsOnline = false } - await notifyStateChange() + await notifyOptionChange() await browser.storage.local.set({ active: state.active }) } catch (error) { console.error(`Unable to update global Active flag due to ${error}`)