From d73837e6771469ab81dbc3cc831987fa6c5f5381 Mon Sep 17 00:00:00 2001
From: Graham Langford <30706330+grahamlangford@users.noreply.github.com>
Date: Wed, 29 May 2024 15:25:08 -0500
Subject: [PATCH] Remove mv2 code final (#8523)
* src/background/browserAction
* src/background/sidePanel
* simplify comments, remove unused code paths
* fix tests
* code comments
* cleanup comments
* remove mv2 code from sidebar
* lint and ts fixes
* removes more mv3 checks
* further cleanup
* remove mv2 sessionStorage shim
* fix strictNullChecks issue
* reverts bad deletion
* cleanup
* cleanup
---
src/background/setToolbarBadge.test.ts | 2 -
.../ephemeralForm/formTransformer.test.ts | 1 -
.../browserActionInstantHandler.ts | 21 ---
src/contentScript/contentScriptCore.ts | 20 ---
src/contentScript/sidebarController.tsx | 127 +++------------
src/contentScript/sidebarDomControllerLite.ts | 150 ------------------
.../pages/settings/ExperimentalSettings.tsx | 18 +--
src/mv3/SessionStorage.test.ts | 24 +++
src/mv3/SessionStorage.ts | 25 +--
src/mv3/api.ts | 12 +-
src/sandbox/messenger/api.ts | 49 ++----
.../sidebar/sidebarExtension.test.ts | 13 +-
src/store/settings/settingsTypes.ts | 8 +-
src/tsconfig.strictNullChecks.json | 2 -
src/utils/notify.tsx | 5 -
src/utils/sidePanelUtils.ts | 14 +-
webpack.config.mjs | 1 -
17 files changed, 85 insertions(+), 407 deletions(-)
delete mode 100644 src/contentScript/browserActionInstantHandler.ts
delete mode 100644 src/contentScript/sidebarDomControllerLite.ts
diff --git a/src/background/setToolbarBadge.test.ts b/src/background/setToolbarBadge.test.ts
index 12cd673370..bd65bde251 100644
--- a/src/background/setToolbarBadge.test.ts
+++ b/src/background/setToolbarBadge.test.ts
@@ -27,8 +27,6 @@ jest.mock("@/mv3/api", () => ({
setBadgeBackgroundColor: jest.fn(),
setBadgeText: jest.fn(),
},
- // TODO: Remove when MV2 code is dropped from src/contentScript
- isMV3: jest.fn(() => true),
}));
describe("setToolbarBadge", () => {
diff --git a/src/bricks/transformers/ephemeralForm/formTransformer.test.ts b/src/bricks/transformers/ephemeralForm/formTransformer.test.ts
index 0c2eddf88b..18409714d5 100644
--- a/src/bricks/transformers/ephemeralForm/formTransformer.test.ts
+++ b/src/bricks/transformers/ephemeralForm/formTransformer.test.ts
@@ -27,7 +27,6 @@ import { showModal } from "@/contentScript/modalDom";
jest.mock("@/utils/iframeUtils");
jest.mock("@/contentScript/modalDom");
-jest.mock("@/contentScript/sidebarDomControllerLite");
const showModalMock = jest.mocked(showModal);
diff --git a/src/contentScript/browserActionInstantHandler.ts b/src/contentScript/browserActionInstantHandler.ts
deleted file mode 100644
index 44c3576ca1..0000000000
--- a/src/contentScript/browserActionInstantHandler.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2024 PixieBrix, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-/** @file This file MUST be lightweight and free of any logic and dependencies, it's meant to be instant */
-import { toggleSidebarFrame } from "@/contentScript/sidebarDomControllerLite";
-
-toggleSidebarFrame();
diff --git a/src/contentScript/contentScriptCore.ts b/src/contentScript/contentScriptCore.ts
index 610caa7cc5..9c9c4459bb 100644
--- a/src/contentScript/contentScriptCore.ts
+++ b/src/contentScript/contentScriptCore.ts
@@ -40,13 +40,6 @@ import initFloatingActions from "@/components/floatingActions/initFloatingAction
import { initSidebarActivation } from "@/contentScript/sidebarActivation";
import { initPerformanceMonitoring } from "@/contentScript/performanceMonitoring";
import { initRuntime } from "@/runtime/reducePipeline";
-import { initSidebarFocusEvents } from "./sidebarController";
-import {
- isSidebarFrameVisible,
- removeSidebarFrame,
-} from "@/contentScript/sidebarDomControllerLite";
-import { isMV3 } from "@/mv3/api";
-import { onContextInvalidated } from "webext-events";
import { setPlatform } from "@/platform/platformContext";
import { markDocumentAsFocusableByUser } from "@/utils/focusTracker";
import contentScriptPlatform from "@/contentScript/contentScriptPlatform";
@@ -95,7 +88,6 @@ export async function init(): Promise {
void initNavigation();
- initSidebarFocusEvents();
void initSidebarActivation();
// Let the partner page know
@@ -103,16 +95,4 @@ export async function init(): Promise {
void initFloatingActions();
void initPerformanceMonitoring();
-
- onContextInvalidated.addListener(() => {
- // The sidebar breaks when the context is invalidated, so it's best to close it
- // In MV3, this happens automatically
- if (!isMV3() && isSidebarFrameVisible()) {
- removeSidebarFrame();
- // TODO: Also notify closure in MV3.
- // There it's more complicated to show this message ONLY if the sidebar was open
- // because the sidebar is closed before this listener is called.
- void notifyContextInvalidated();
- }
- });
}
diff --git a/src/contentScript/sidebarController.tsx b/src/contentScript/sidebarController.tsx
index af671b957e..bd8c3b750c 100644
--- a/src/contentScript/sidebarController.tsx
+++ b/src/contentScript/sidebarController.tsx
@@ -23,8 +23,6 @@ import * as contentScriptApi from "@/contentScript/messenger/strict/api";
import { isEmpty, throttle } from "lodash";
import { signalFromEvent } from "abort-utils";
import { SimpleEventTarget } from "@/utils/SimpleEventTarget";
-import * as sidebarMv2 from "@/contentScript/sidebarDomControllerLite";
-import { getSidebarElement } from "@/contentScript/sidebarDomControllerLite";
import { type Except } from "type-fest";
import { type RunArgs, RunReason } from "@/types/runtimeTypes";
import { type UUID } from "@/types/stringTypes";
@@ -42,12 +40,9 @@ import { getTemporaryPanelSidebarEntries } from "@/platform/panels/panelControll
import { getFormPanelSidebarEntries } from "@/platform/forms/formController";
import { memoizeUntilSettled } from "@/utils/promiseUtils";
import { getTimedSequence } from "@/types/helpers";
-import { isMV3 } from "@/mv3/api";
import { focusCaptureDialog } from "@/contentScript/focusCaptureDialog";
import { isLoadedInIframe } from "@/utils/iframeUtils";
import { showMySidePanel } from "@/background/messenger/strict/api";
-import focusController from "@/utils/focusController";
-import selectionController from "@/utils/selectionController";
import { getTopLevelFrame, messenger } from "webext-messenger";
import {
getSidebarTargetForCurrentTab,
@@ -56,8 +51,6 @@ import {
import pRetry from "p-retry";
import { hideNotification, showNotification } from "@/utils/notify";
-const HIDE_SIDEBAR_EVENT_NAME = "pixiebrix:hideSidebar";
-
/**
* Event listeners triggered when the sidebar shows and is ready to receive messages.
*/
@@ -72,7 +65,7 @@ let modActivationPanelEntry: ModActivationPanelEntry | null = null;
* Only one check at a time
* Cannot throttle because subsequent checks need to be able to be made immediately
*/
-const isSidePanelOpenMv3 = memoizeUntilSettled(async () => {
+export const isSidePanelOpen = memoizeUntilSettled(async () => {
try {
await messenger(
"SIDEBAR_PING",
@@ -85,10 +78,6 @@ const isSidePanelOpenMv3 = memoizeUntilSettled(async () => {
}
});
-export const isSidePanelOpen = isMV3()
- ? isSidePanelOpenMv3
- : sidebarMv2.isSidebarFrameVisible;
-
// - Only start one ping at a time
// - Limit to one request every second (if the user closes the sidebar that quickly, we likely see those errors anyway)
// - Throw custom error if the sidebar doesn't respond in time
@@ -155,30 +144,25 @@ export async function showSidebarInTopFrame() {
// We do not await the promise here since we want to show the sidebar as soon as possible to avoid the possibility
// of the user needing to provide another user gesture to open the sidebar.
- const sidebarInitiallyOpenPromise = isSidePanelOpenMv3();
+ const sidebarInitiallyOpenPromise = isSidePanelOpen();
if (isLoadedInIframe()) {
console.warn("showSidebarInTopFrame should not be called in an iframe");
}
- // Defensively handle accidental calls from iframes
- if (isMV3() || isLoadedInIframe()) {
- try {
- await showMySidePanel();
- } catch (error) {
- if (!isUserGestureRequiredError(error)) {
- throw error;
- }
-
- await focusCaptureDialog({
- message: 'Click "Open Sidebar" to open the mod sidebar',
- buttonText: "Open Sidebar",
- signal: signalFromEvent(sidebarShowEvents, sidebarShowEvents.coreEvent),
- });
- await showMySidePanel();
+ try {
+ await showMySidePanel();
+ } catch (error) {
+ if (!isUserGestureRequiredError(error)) {
+ throw error;
}
- } else if (!sidebarMv2.isSidebarFrameVisible()) {
- sidebarMv2.insertSidebarFrame();
+
+ await focusCaptureDialog({
+ message: 'Click "Open Sidebar" to open the mod sidebar',
+ buttonText: "Open Sidebar",
+ signal: signalFromEvent(sidebarShowEvents, sidebarShowEvents.coreEvent),
+ });
+ await showMySidePanel();
}
await pingSidebar();
@@ -587,29 +571,17 @@ export function getReservedPanelEntries(): {
function sidePanelOnCloseSignal(): AbortSignal {
const controller = new AbortController();
expectContext("contentScript");
- if (isMV3()) {
- window.addEventListener(
- "resize",
- async () => {
- // TODO: Replace with official event when available
- // Official event requested in https://github.com/w3c/webextensions/issues/517
- if (!(await isSidePanelOpenMv3())) {
- controller.abort();
- }
- },
- { signal: controller.signal },
- );
- } else {
- window.addEventListener(
- HIDE_SIDEBAR_EVENT_NAME,
- () => {
+ window.addEventListener(
+ "resize",
+ async () => {
+ // TODO: Replace with official event when available
+ // Official event requested in https://github.com/w3c/webextensions/issues/517
+ if (!(await isSidePanelOpen())) {
controller.abort();
- },
- {
- signal: controller.signal,
- },
- );
- }
+ }
+ },
+ { signal: controller.signal },
+ );
return controller.signal;
}
@@ -618,54 +590,3 @@ export function sidePanelOnClose(callback: () => void): void {
const signal = sidePanelOnCloseSignal();
signal.addEventListener("abort", callback, { once: true });
}
-
-export function initSidebarFocusEvents(): void {
- if (!isMV3()) {
- // Add listeners to track keep track of focus with the MV2 sidebar. When the user interacts
- // with the MV2 sidebar, the sidebar gets set as the document.activeElement. Required for brick
- // functionality such as InsertAtCursorEffect
- sidebarShowEvents.add(() => {
- const sidebar = getSidebarElement();
-
- if (!sidebar) {
- // Should always exist because sidebarShowEvents is called on Sidebar App initialization
- return;
- }
-
- // Save focus on initial load, because the user may have `mouseenter`ed the sidebar before the React App
- // fired the sidebarShowEvent event. For example, if the user clicked the browserAction toolbar button and
- // immediately `mouseenter`ed the sidebar (because the top of the sidebar is very close to the top browserAction)
- if (document.activeElement !== sidebar) {
- focusController.save();
- }
-
- const closeSignal = sidePanelOnCloseSignal();
-
- // Can't detect clicks in the sidebar itself. So need to just watch for enter/leave the sidebar element
- sidebar.addEventListener(
- "mouseenter",
- () => {
- // If the user clicks into the sidebar and then leaves the sidebar, don't set the focus to the sidebar
- // when they re-enter the sidebar
- if (document.activeElement !== sidebar) {
- // FIXME: If the user closes the sidebar when these two items are stored,
- // both controllers will be stuck that way until some other .restore()/.clear() call resets it. It will need a "sidebar hide" listener to ensure it doesn't happen
- // https://github.com/pixiebrix/pixiebrix-extension/pull/7842#discussion_r1516015396
- focusController.save();
- selectionController.save();
- }
- },
- { passive: true, capture: true, signal: closeSignal },
- );
-
- sidebar.addEventListener(
- "mouseleave",
- () => {
- focusController.clear();
- selectionController.clear();
- },
- { passive: true, capture: true, signal: closeSignal },
- );
- });
- }
-}
diff --git a/src/contentScript/sidebarDomControllerLite.ts b/src/contentScript/sidebarDomControllerLite.ts
deleted file mode 100644
index b5dac2bf63..0000000000
--- a/src/contentScript/sidebarDomControllerLite.ts
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2024 PixieBrix, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-/**
- * @file This file MUST not have dependencies as it's meant to be tiny and imported by browserActionInstantHandler.ts.
- * Because browserActionInstantHandler.ts is a separate content script, any modules will be duplicated
- * between browserActionInstantHandler and the main content script.
- */
-
-import { MAX_Z_INDEX, PANEL_FRAME_ID } from "@/domConstants";
-import shadowWrap from "@/utils/shadowWrap";
-import { expectContext } from "@/utils/expectContext";
-import { uuidv4 } from "@/types/helpers";
-
-export const SIDEBAR_WIDTH_CSS_PROPERTY = "--pb-sidebar-width";
-const ORIGINAL_MARGIN_CSS_PROPERTY = "--pb-original-margin-right";
-
-const SIDEBAR_WIDTH_PX = 400;
-
-function storeOriginalCSSOnce() {
- const html = document.documentElement;
-
- if (html.style.getPropertyValue(ORIGINAL_MARGIN_CSS_PROPERTY)) {
- return;
- }
-
- // Store the original margin, so it can be reused in future calculations. It must also persist across sessions
- html.style.setProperty(
- ORIGINAL_MARGIN_CSS_PROPERTY,
- getComputedStyle(html).getPropertyValue("margin-right"),
- );
-
- // Make margin dynamic, so it always follows the original margin AND the sidebar width, if open
- html.style.setProperty(
- "margin-right",
- `calc(var(${ORIGINAL_MARGIN_CSS_PROPERTY}) + var(${SIDEBAR_WIDTH_CSS_PROPERTY}))`,
- );
-
- // Some websites like https://www.nespresso.com/us/en/ have `width: 100%` on the HTML.
- // This resets it as it prevents the margin from working (and it's the default already)
- html.style.setProperty("width", "auto");
-}
-
-function setSidebarWidth(pixels: number): void {
- const html = document.documentElement;
- html.style.setProperty(SIDEBAR_WIDTH_CSS_PROPERTY, `${pixels}px`);
-}
-
-/**
- * Returns the sidebar frame if it's in the DOM, or null otherwise. The sidebar might not be initialized yet.
- */
-export function getSidebarElement(): Element | null {
- expectContext("contentScript");
-
- return document.documentElement.querySelector(`#${PANEL_FRAME_ID}`);
-}
-
-/**
- * Return true if the sidebar frame is in the DOM. The sidebar might not be initialized yet.
- */
-export function isSidebarFrameVisible(): boolean {
- return Boolean(getSidebarElement());
-}
-
-/** Removes the element; Returns false if no element was found */
-export function removeSidebarFrame(): boolean {
- const sidebar = getSidebarElement();
- if (sidebar) {
- sidebar.remove();
- setSidebarWidth(0);
- }
-
- return Boolean(sidebar);
-}
-
-/** Inserts the element; Returns false if it already existed */
-export function insertSidebarFrame(): boolean {
- if (isSidebarFrameVisible()) {
- return false;
- }
-
- storeOriginalCSSOnce();
- const nonce = uuidv4();
- const actionUrl = new URL(browser.runtime.getURL("sidebar.html"));
- actionUrl.searchParams.set("nonce", nonce);
-
- setSidebarWidth(SIDEBAR_WIDTH_PX);
-
- const iframe = document.createElement("iframe");
- iframe.src = actionUrl.href;
-
- Object.assign(iframe.style, {
- position: "fixed",
- top: 0,
- right: 0,
- // `-1` keeps it under the QuickBar #4130
- zIndex: MAX_Z_INDEX - 1,
-
- // Note that it can't use the variable because the frame is in the shadow DOM
- width: CSS.px(SIDEBAR_WIDTH_PX),
- height: "100%",
- border: 0,
- borderLeft: "1px solid lightgray",
-
- // Note that it can't use our CSS variables because this element lives on the host
- background: "#f9f8fa",
- });
-
- const wrapper = shadowWrap(iframe);
- wrapper.id = PANEL_FRAME_ID;
- document.documentElement.append(wrapper);
-
- iframe.animate([{ translate: "50%" }, { translate: 0 }], {
- duration: 500,
- easing: "cubic-bezier(0.23, 1, 0.32, 1)",
- });
-
- if (!isSidebarFrameVisible()) {
- console.error(
- "Post-condition failed: isSidebarFrameVisible is false after insertSidebarFrame",
- );
- }
-
- return true;
-}
-
-/**
- * Toggle the sidebar frame. Returns true if the sidebar is now visible, false otherwise.
- */
-export function toggleSidebarFrame(): void {
- if (isSidebarFrameVisible()) {
- removeSidebarFrame();
- } else {
- insertSidebarFrame();
- }
-}
diff --git a/src/extensionConsole/pages/settings/ExperimentalSettings.tsx b/src/extensionConsole/pages/settings/ExperimentalSettings.tsx
index 57db4613ce..b01f5c24b5 100644
--- a/src/extensionConsole/pages/settings/ExperimentalSettings.tsx
+++ b/src/extensionConsole/pages/settings/ExperimentalSettings.tsx
@@ -23,15 +23,10 @@ import { faFlask } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { selectSettings } from "@/store/settings/settingsSelectors";
import SettingToggle from "@/extensionConsole/pages/settings/SettingToggle";
-import { isMV3 } from "@/mv3/api";
const ExperimentalSettings: React.FunctionComponent = () => {
- const {
- suggestElements,
- excludeRandomClasses,
- performanceTracing,
- sandboxedCode,
- } = useSelector(selectSettings);
+ const { suggestElements, excludeRandomClasses, performanceTracing } =
+ useSelector(selectSettings);
return (
@@ -63,15 +58,6 @@ const ExperimentalSettings: React.FunctionComponent = () => {
isEnabled={performanceTracing ?? false}
flag="performanceTracing"
/>
- {!isMV3() && (
-
- )}
diff --git a/src/mv3/SessionStorage.test.ts b/src/mv3/SessionStorage.test.ts
index ff91dd319b..a9fbe64b16 100644
--- a/src/mv3/SessionStorage.test.ts
+++ b/src/mv3/SessionStorage.test.ts
@@ -17,6 +17,30 @@
import { SessionMap, SessionValue } from "./SessionStorage";
+const _map = new Map();
+
+// Workaround until https://github.com/RickyMarou/jest-webextension-mock/issues/6 is resolved
+browser.storage.session = {
+ get: jest.fn(async (key: string) => ({ [key]: _map.get(key) })),
+ set: jest.fn(async (obj) => {
+ _map.set(...Object.entries(obj)[0]!);
+ }),
+ remove: jest.fn(async (key) => {
+ _map.delete(key);
+ }),
+ clear: jest.fn(),
+ onChanged: {
+ addListener: jest.fn(),
+ removeListener: jest.fn(),
+ hasListener: jest.fn(),
+ hasListeners: jest.fn(),
+ },
+};
+
+beforeEach(() => {
+ _map.clear();
+});
+
test("SessionMap", async () => {
const map = new SessionMap("jester", import.meta.url);
await expect(map.get("alpha")).resolves.toBeUndefined();
diff --git a/src/mv3/SessionStorage.ts b/src/mv3/SessionStorage.ts
index 493b6f0211..7cba28b977 100644
--- a/src/mv3/SessionStorage.ts
+++ b/src/mv3/SessionStorage.ts
@@ -28,12 +28,6 @@ import { type ManualStorageKey } from "@/utils/storageUtils";
import { once } from "lodash";
import pMemoize from "p-memoize";
-// Just like chrome.storage.session, this must be "global"
-// eslint-disable-next-line local-rules/persistBackgroundData -- MV2-only
-const storage = new Map();
-
-// eslint-disable-next-line local-rules/persistBackgroundData -- Static
-const hasSession = "session" in chrome.storage;
function validateContext(): void {
expectContext(
"background",
@@ -62,9 +56,6 @@ export class SessionMap {
async has(secondaryKey: string): Promise {
this.validateContext();
const rawStorageKey = this.getRawStorageKey(secondaryKey);
- if (!hasSession) {
- return storage.has(rawStorageKey);
- }
const result = await browser.storage.session.get(rawStorageKey);
// OK to check for undefined because it's not a valid JsonValue. The `set` method calls `delete` if
@@ -76,11 +67,9 @@ export class SessionMap {
async get(secondaryKey: string): Promise {
this.validateContext();
const rawStorageKey = this.getRawStorageKey(secondaryKey);
- if (!hasSession) {
- return storage.get(rawStorageKey) as Value | undefined;
- }
const result = await browser.storage.session.get(rawStorageKey);
+
// eslint-disable-next-line security/detect-object-injection -- `getRawStorageKey` ensures the format
return result[rawStorageKey] as Value | undefined;
}
@@ -96,22 +85,14 @@ export class SessionMap {
}
const rawStorageKey = this.getRawStorageKey(secondaryKey);
- if (hasSession) {
- await browser.storage.session.set({ [rawStorageKey]: value });
- } else {
- storage.set(rawStorageKey, value);
- }
+ await browser.storage.session.set({ [rawStorageKey]: value });
}
async delete(secondaryKey: string): Promise {
this.validateContext();
const rawStorageKey = this.getRawStorageKey(secondaryKey);
- if (hasSession) {
- await browser.storage.session.remove(rawStorageKey);
- } else {
- storage.delete(rawStorageKey);
- }
+ await browser.storage.session.remove(rawStorageKey);
}
}
diff --git a/src/mv3/api.ts b/src/mv3/api.ts
index 10a7729f19..6410f7daab 100644
--- a/src/mv3/api.ts
+++ b/src/mv3/api.ts
@@ -16,18 +16,10 @@
*/
/** @file Temporary helpers useful for the MV3 transition */
+// TODO: Determine if we want to keep this file
import { type Tabs } from "webextension-polyfill";
-import { once } from "lodash";
-
-export const isMV3 = once((): boolean => {
- // https://github.com/pixiebrix/pixiebrix-extension/issues/8273
- if (!chrome.runtime?.getManifest) {
- return false;
- }
-
- return chrome.runtime.getManifest().manifest_version === 3;
-});
export const browserAction = globalThis.chrome?.action;
+// XXX: Not sure if we still need both Tab types
export type Tab = Tabs.Tab | chrome.tabs.Tab;
diff --git a/src/sandbox/messenger/api.ts b/src/sandbox/messenger/api.ts
index f5e8cd5ef8..6d823d2abb 100644
--- a/src/sandbox/messenger/api.ts
+++ b/src/sandbox/messenger/api.ts
@@ -20,11 +20,7 @@
import injectIframe, { hiddenIframeStyle } from "@/utils/injectIframe";
import postMessage from "@/utils/postMessage";
import pMemoize from "p-memoize";
-import * as directApi from "@/sandbox/messenger/executor";
import { type JsonObject } from "type-fest";
-import { getSettingsState } from "@/store/settings/settingsStorage";
-import { once } from "lodash";
-import { isMV3 } from "@/mv3/api";
// Uses pMemoize to allow retries after a failure
const loadSandbox = pMemoize(async () => {
@@ -35,15 +31,6 @@ const loadSandbox = pMemoize(async () => {
return iframe.contentWindow;
});
-const isSandboxed = once(async (): Promise => {
- if (isMV3()) {
- return true;
- }
-
- const { sandboxedCode } = await getSettingsState();
- return Boolean(sandboxedCode);
-});
-
export type TemplateRenderPayload = {
template: string;
context: JsonObject;
@@ -55,37 +42,31 @@ export type TemplateValidatePayload = string;
export async function renderNunjucksTemplate(
payload: TemplateRenderPayload,
): Promise {
- return (await isSandboxed())
- ? postMessage({
- recipient: await loadSandbox(),
- payload,
- type: "RENDER_NUNJUCKS",
- })
- : directApi.renderNunjucksTemplate(payload);
+ return postMessage({
+ recipient: await loadSandbox(),
+ payload,
+ type: "RENDER_NUNJUCKS",
+ });
}
export async function validateNunjucksTemplate(
payload: TemplateValidatePayload,
): Promise {
- return (await isSandboxed())
- ? postMessage({
- recipient: await loadSandbox(),
- payload,
- type: "VALIDATE_NUNJUCKS",
- })
- : directApi.validateNunjucksTemplate(payload);
+ return postMessage({
+ recipient: await loadSandbox(),
+ payload,
+ type: "VALIDATE_NUNJUCKS",
+ });
}
export async function renderHandlebarsTemplate(
payload: TemplateRenderPayload,
): Promise {
- return (await isSandboxed())
- ? postMessage({
- recipient: await loadSandbox(),
- payload,
- type: "RENDER_HANDLEBARS",
- })
- : directApi.renderHandlebarsTemplate(payload);
+ return postMessage({
+ recipient: await loadSandbox(),
+ payload,
+ type: "RENDER_HANDLEBARS",
+ });
}
export type JavaScriptPayload = {
diff --git a/src/starterBricks/sidebar/sidebarExtension.test.ts b/src/starterBricks/sidebar/sidebarExtension.test.ts
index 6a0a50eb72..ea8d05a19c 100644
--- a/src/starterBricks/sidebar/sidebarExtension.test.ts
+++ b/src/starterBricks/sidebar/sidebarExtension.test.ts
@@ -31,10 +31,10 @@ import { RootReader, tick } from "@/starterBricks/starterBrickTestUtils";
import {
getReservedPanelEntries,
sidebarShowEvents,
+ isSidePanelOpen,
} from "@/contentScript/sidebarController";
import { setState } from "@/platform/state/stateController";
import { modMetadataFactory } from "@/testUtils/factories/modComponentFactories";
-import { PANEL_FRAME_ID } from "@/domConstants";
import brickRegistry from "@/bricks/registry";
import { sleep } from "@/utils/timeUtils";
import { getPlatform } from "@/platform/platformContext";
@@ -43,6 +43,12 @@ import {
type SidebarConfig,
} from "@/starterBricks/sidebar/types";
+jest.mock("@/contentScript/sidebarController", () => ({
+ ...jest.requireActual("@/contentScript/sidebarController"),
+ isSidePanelOpen: jest.fn(),
+}));
+const isSidePanelOpenMock = jest.mocked(isSidePanelOpen);
+
const rootReader = new RootReader();
const starterBrickFactory = (definitionOverrides: UnknownObject = {}) =>
@@ -83,6 +89,7 @@ describe("sidebarExtension", () => {
brickRegistry.clear();
brickRegistry.register([rootReader]);
rootReader.readCount = 0;
+ isSidePanelOpenMock.mockResolvedValue(false);
});
it("reserves panel on load", async () => {
@@ -189,7 +196,7 @@ describe("sidebarExtension", () => {
expect(rootReader.readCount).toBe(0);
// Fake the sidebar being added to the page
- $(document.body).append(``);
+ isSidePanelOpenMock.mockResolvedValue(true);
sidebarShowEvents.emit({ reason: RunReason.MANUAL });
await tick();
@@ -251,7 +258,7 @@ describe("sidebarExtension", () => {
await extensionPoint.install();
// Fake the sidebar being added to the page
- $(document.body).append(``);
+ isSidePanelOpenMock.mockResolvedValue(true);
sidebarShowEvents.emit({ reason: RunReason.MANUAL });
await tick();
diff --git a/src/store/settings/settingsTypes.ts b/src/store/settings/settingsTypes.ts
index 09f2479179..f841c8e319 100644
--- a/src/store/settings/settingsTypes.ts
+++ b/src/store/settings/settingsTypes.ts
@@ -41,11 +41,6 @@ export type SkunkworksSettingsFlags = {
* Experimental setting to track runtime performance
*/
performanceTracing?: boolean;
-
- /**
- * Experimental setting to run some code in a sandbox
- */
- sandboxedCode?: boolean;
};
export type GeneralSettingsFlags = {
@@ -167,6 +162,9 @@ export type SettingsStateV3 = SettingsStateV2 & {
varAutosuggest: boolean;
};
+/**
+ * @deprecated - Do not use versioned state types directly
+ */
export type SettingsStateV4 = SettingsStateV3 & {
/**
* @since 1.8.11 SettingsStateV4 makes textSelectionMenu and snippetShortcutMenu required
diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json
index 14e0bfc83a..16b9ae21a0 100644
--- a/src/tsconfig.strictNullChecks.json
+++ b/src/tsconfig.strictNullChecks.json
@@ -427,7 +427,6 @@
"./components/walkthroughModal/WalkthroughModalApp.tsx",
"./components/walkthroughModal/showWalkthroughModal.ts",
"./contentScript/activationConstants.ts",
- "./contentScript/browserActionInstantHandler.ts",
"./contentScript/contentScriptPlatform.ts",
"./contentScript/context.ts",
"./contentScript/contextMenus.ts",
@@ -468,7 +467,6 @@
"./contentScript/ready.ts",
"./contentScript/setExtensionIdInApp.ts",
"./contentScript/sidebarController.tsx",
- "./contentScript/sidebarDomControllerLite.ts",
"./contentScript/snippetShortcutMenu/SnippetShortcutMenu.stories.tsx",
"./contentScript/snippetShortcutMenu/SnippetShortcutMenu.test.tsx",
"./contentScript/snippetShortcutMenu/SnippetShortcutMenu.tsx",
diff --git a/src/utils/notify.tsx b/src/utils/notify.tsx
index 78a071a7d3..341234a1b5 100644
--- a/src/utils/notify.tsx
+++ b/src/utils/notify.tsx
@@ -25,9 +25,6 @@ import reportError from "@/telemetry/reportError";
import { type Except, type RequireAtLeastOne } from "type-fest";
import { getErrorMessage } from "@/errors/errorHelpers";
import { merge, truncate } from "lodash";
-/* eslint-disable-next-line local-rules/noCrossBoundaryImports -- While correct, the `sidebarDomControllerLite` name
-implies that it's a small, pure module, and it's unlikely to cause issues */
-import { SIDEBAR_WIDTH_CSS_PROPERTY } from "@/contentScript/sidebarDomControllerLite";
import ErrorIcon from "@/icons/error.svg?loadAsComponent";
import WarningIcon from "@/icons/warning.svg?loadAsComponent";
import type { Notification, NotificationType } from "@/utils/notificationTypes";
@@ -145,8 +142,6 @@ export function showNotification({
const options: ToastOptions = {
id,
duration,
- // Keep the notification centered on the document even when the sidebar is open
- style: { marginLeft: `calc(var(${SIDEBAR_WIDTH_CSS_PROPERTY}, 0) * -1)` },
};
const component = ;
diff --git a/src/utils/sidePanelUtils.ts b/src/utils/sidePanelUtils.ts
index ac2d838c88..3d81d77892 100644
--- a/src/utils/sidePanelUtils.ts
+++ b/src/utils/sidePanelUtils.ts
@@ -18,11 +18,9 @@
/** @file This file contains utilities to deal with the sidePanel from other contexts */
import { getErrorMessage } from "@/errors/errorHelpers";
-import { isMV3 } from "@/mv3/api";
import { forbidContext, isBrowserSidebarTopFrame } from "@/utils/expectContext";
import { type PageTarget, messenger, getThisFrame } from "webext-messenger";
import { isContentScript } from "webext-detect-page";
-import { showSidebar } from "@/contentScript/messenger/strict/api";
/**
* Returns true if an error showing sidebar is due to a missing user gesture.
@@ -44,14 +42,10 @@ export async function openSidePanel(tabId: number): Promise {
"The content script doesn't have direct access to the `sidePanel` API. Call `showMySidePanel` instead",
);
- if (isMV3()) {
- await openSidePanelMv3(tabId);
- } else {
- await showSidebar({ tabId });
- }
+ await _openSidePanel(tabId);
}
-async function openSidePanelMv3(tabId: number): Promise {
+async function _openSidePanel(tabId: number): Promise {
// Simultaneously enable and open the side panel.
// If we wait too long before calling .open(), we will lose the "user gesture" permission
// There is no way to know whether the side panel is open yet, so we call it regardless.
@@ -97,10 +91,6 @@ export function getSidebarPath(tabId: number): string {
}
export function getSidebarTarget(tabId: number): PageTarget {
- if (!isMV3()) {
- return { tabId, page: "/sidebar.html" };
- }
-
return {
page: getSidebarPath(tabId),
};
diff --git a/webpack.config.mjs b/webpack.config.mjs
index b6284a3f65..ea1b4e8807 100644
--- a/webpack.config.mjs
+++ b/webpack.config.mjs
@@ -117,7 +117,6 @@ const createConfig = (env, options) =>
"contentScript/contentScript",
"contentScript/loadActivationEnhancements",
- "contentScript/browserActionInstantHandler",
"contentScript/setExtensionIdInApp",
"pageEditor/pageEditor",