From 8d8c4eb29b7ace86a301fc40546960519974b432 Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Fri, 14 Feb 2025 15:59:14 -0500 Subject: [PATCH] Delete everything related to `misc-utils` (#13395) --- .../clipboard/clear-clipboard.spec.ts | 39 -------- .../src/autofill/clipboard/clear-clipboard.ts | 22 ----- .../clipboard/copy-to-clipboard-command.ts | 17 ---- ...rate-password-to-clipboard-command.spec.ts | 97 ------------------- .../generate-password-to-clipboard-command.ts | 48 --------- apps/browser/src/autofill/clipboard/index.ts | 3 - .../src/autofill/content/misc-utils.ts | 23 ----- apps/browser/src/manifest.v3.json | 2 +- apps/browser/webpack.config.js | 3 - 9 files changed, 1 insertion(+), 253 deletions(-) delete mode 100644 apps/browser/src/autofill/clipboard/clear-clipboard.spec.ts delete mode 100644 apps/browser/src/autofill/clipboard/clear-clipboard.ts delete mode 100644 apps/browser/src/autofill/clipboard/copy-to-clipboard-command.ts delete mode 100644 apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.spec.ts delete mode 100644 apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.ts delete mode 100644 apps/browser/src/autofill/clipboard/index.ts delete mode 100644 apps/browser/src/autofill/content/misc-utils.ts diff --git a/apps/browser/src/autofill/clipboard/clear-clipboard.spec.ts b/apps/browser/src/autofill/clipboard/clear-clipboard.spec.ts deleted file mode 100644 index 7bfe7934046..00000000000 --- a/apps/browser/src/autofill/clipboard/clear-clipboard.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { BrowserApi } from "../../platform/browser/browser-api"; - -import { ClearClipboard } from "./clear-clipboard"; - -describe("clearClipboard", () => { - describe("run", () => { - it("Does not clear clipboard when no active tabs are retrieved", async () => { - jest.spyOn(BrowserApi, "getActiveTabs").mockResolvedValue([] as any); - - jest.spyOn(BrowserApi, "sendTabsMessage").mockReturnValue(); - - await ClearClipboard.run(); - - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).not.toHaveBeenCalled(); - - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).not.toHaveBeenCalledWith(1, { - command: "clearClipboard", - }); - }); - - it("Sends a message to the content script to clear the clipboard", async () => { - jest.spyOn(BrowserApi, "getActiveTabs").mockResolvedValue([ - { - id: 1, - }, - ] as any); - - jest.spyOn(BrowserApi, "sendTabsMessage").mockReturnValue(); - - await ClearClipboard.run(); - - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).toHaveBeenCalledTimes(1); - - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).toHaveBeenCalledWith(1, { - command: "clearClipboard", - }); - }); - }); -}); diff --git a/apps/browser/src/autofill/clipboard/clear-clipboard.ts b/apps/browser/src/autofill/clipboard/clear-clipboard.ts deleted file mode 100644 index 93674df0ad9..00000000000 --- a/apps/browser/src/autofill/clipboard/clear-clipboard.ts +++ /dev/null @@ -1,22 +0,0 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { BrowserApi } from "../../platform/browser/browser-api"; - -export class ClearClipboard { - /** - We currently rely on an active tab with an injected content script (`../content/misc-utils.ts`) to clear the clipboard via `window.navigator.clipboard.writeText(text)` - - With https://bugs.chromium.org/p/chromium/issues/detail?id=1160302 it was said that service workers, - would have access to the clipboard api and then we could migrate to a simpler solution - */ - static async run() { - const activeTabs = await BrowserApi.getActiveTabs(); - if (!activeTabs || activeTabs.length === 0) { - return; - } - - BrowserApi.sendTabsMessage(activeTabs[0].id, { - command: "clearClipboard", - }); - } -} diff --git a/apps/browser/src/autofill/clipboard/copy-to-clipboard-command.ts b/apps/browser/src/autofill/clipboard/copy-to-clipboard-command.ts deleted file mode 100644 index 92d35e70e57..00000000000 --- a/apps/browser/src/autofill/clipboard/copy-to-clipboard-command.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { BrowserApi } from "../../platform/browser/browser-api"; - -/** - * Copies text to the clipboard in a MV3 safe way. - * @param tab - The tab that the text will be sent to so that it can be copied to the users clipboard this needs to be an active tab or the DOM won't be able to be used to do the action. The tab sent in here should be from a user started action or queried for active tabs. - * @param text - The text that you want added to the users clipboard. - */ -export const copyToClipboard = async (tab: chrome.tabs.Tab, text: string) => { - if (tab.id == null) { - throw new Error("Cannot copy text to clipboard with a tab that does not have an id."); - } - - BrowserApi.sendTabsMessage(tab.id, { - command: "copyText", - text: text, - }); -}; diff --git a/apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.spec.ts b/apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.spec.ts deleted file mode 100644 index d0d42cc06f7..00000000000 --- a/apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.spec.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { mock, MockProxy } from "jest-mock-extended"; -import { firstValueFrom, Subscription } from "rxjs"; - -import { AutofillSettingsService } from "@bitwarden/common/autofill/services/autofill-settings.service"; -import { ScheduledTaskNames } from "@bitwarden/common/platform/scheduling"; -import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; - -import { BrowserApi } from "../../platform/browser/browser-api"; -import { BrowserTaskSchedulerService } from "../../platform/services/abstractions/browser-task-scheduler.service"; - -import { ClearClipboard } from "./clear-clipboard"; -import { GeneratePasswordToClipboardCommand } from "./generate-password-to-clipboard-command"; - -jest.mock("rxjs", () => { - const actual = jest.requireActual("rxjs"); - return { - ...actual, - firstValueFrom: jest.fn(), - }; -}); - -describe("GeneratePasswordToClipboardCommand", () => { - let passwordGenerationService: MockProxy; - let autofillSettingsService: MockProxy; - let browserTaskSchedulerService: MockProxy; - - let sut: GeneratePasswordToClipboardCommand; - - beforeEach(() => { - passwordGenerationService = mock(); - autofillSettingsService = mock(); - browserTaskSchedulerService = mock({ - setTimeout: jest.fn((taskName, timeoutInMs) => { - const timeoutHandle = setTimeout(() => { - if (taskName === ScheduledTaskNames.generatePasswordClearClipboardTimeout) { - void ClearClipboard.run(); - } - }, timeoutInMs); - - return new Subscription(() => clearTimeout(timeoutHandle)); - }), - }); - - passwordGenerationService.getOptions.mockResolvedValue([{ length: 8 }, {} as any]); - - passwordGenerationService.generatePassword.mockResolvedValue("PASSWORD"); - - jest.spyOn(BrowserApi, "sendTabsMessage").mockReturnValue(); - - sut = new GeneratePasswordToClipboardCommand( - passwordGenerationService, - autofillSettingsService, - browserTaskSchedulerService, - ); - }); - - afterEach(() => { - jest.resetAllMocks(); - }); - - describe("generatePasswordToClipboard", () => { - it("has clear clipboard value", async () => { - jest.useFakeTimers(); - jest.spyOn(ClearClipboard, "run"); - (firstValueFrom as jest.Mock).mockResolvedValue(2 * 60); // 2 minutes - - await sut.generatePasswordToClipboard({ id: 1 } as any); - jest.advanceTimersByTime(2 * 60 * 1000); - - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).toHaveBeenCalledTimes(1); - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).toHaveBeenCalledWith(1, { - command: "copyText", - text: "PASSWORD", - }); - expect(browserTaskSchedulerService.setTimeout).toHaveBeenCalledTimes(1); - expect(browserTaskSchedulerService.setTimeout).toHaveBeenCalledWith( - ScheduledTaskNames.generatePasswordClearClipboardTimeout, - expect.any(Number), - ); - expect(ClearClipboard.run).toHaveBeenCalledTimes(1); - }); - - it("does not have clear clipboard value", async () => { - jest.spyOn(sut as any, "getClearClipboard").mockImplementation(() => null); - - await sut.generatePasswordToClipboard({ id: 1 } as any); - - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).toHaveBeenCalledTimes(1); - - expect(jest.spyOn(BrowserApi, "sendTabsMessage")).toHaveBeenCalledWith(1, { - command: "copyText", - text: "PASSWORD", - }); - expect(browserTaskSchedulerService.setTimeout).not.toHaveBeenCalled(); - }); - }); -}); diff --git a/apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.ts b/apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.ts deleted file mode 100644 index 5fb6e8667a4..00000000000 --- a/apps/browser/src/autofill/clipboard/generate-password-to-clipboard-command.ts +++ /dev/null @@ -1,48 +0,0 @@ -// FIXME: Update this file to be type safe and remove this and next line -// @ts-strict-ignore -import { firstValueFrom, Subscription } from "rxjs"; - -import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service"; -import { TaskSchedulerService, ScheduledTaskNames } from "@bitwarden/common/platform/scheduling"; -import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy"; - -import { ClearClipboard } from "./clear-clipboard"; -import { copyToClipboard } from "./copy-to-clipboard-command"; - -export class GeneratePasswordToClipboardCommand { - private clearClipboardSubscription: Subscription; - - constructor( - private passwordGenerationService: PasswordGenerationServiceAbstraction, - private autofillSettingsService: AutofillSettingsServiceAbstraction, - private taskSchedulerService: TaskSchedulerService, - ) { - this.taskSchedulerService.registerTaskHandler( - ScheduledTaskNames.generatePasswordClearClipboardTimeout, - () => ClearClipboard.run(), - ); - } - - async getClearClipboard() { - return await firstValueFrom(this.autofillSettingsService.clearClipboardDelay$); - } - - async generatePasswordToClipboard(tab: chrome.tabs.Tab) { - const [options] = await this.passwordGenerationService.getOptions(); - const password = await this.passwordGenerationService.generatePassword(options); - - await copyToClipboard(tab, password); - - const clearClipboardDelayInSeconds = await this.getClearClipboard(); - if (!clearClipboardDelayInSeconds) { - return; - } - - const timeoutInMs = clearClipboardDelayInSeconds * 1000; - this.clearClipboardSubscription?.unsubscribe(); - this.clearClipboardSubscription = this.taskSchedulerService.setTimeout( - ScheduledTaskNames.generatePasswordClearClipboardTimeout, - timeoutInMs, - ); - } -} diff --git a/apps/browser/src/autofill/clipboard/index.ts b/apps/browser/src/autofill/clipboard/index.ts deleted file mode 100644 index 3682afd5054..00000000000 --- a/apps/browser/src/autofill/clipboard/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./clear-clipboard"; -export * from "./copy-to-clipboard-command"; -export * from "./generate-password-to-clipboard-command"; diff --git a/apps/browser/src/autofill/content/misc-utils.ts b/apps/browser/src/autofill/content/misc-utils.ts deleted file mode 100644 index 7fe884f1d51..00000000000 --- a/apps/browser/src/autofill/content/misc-utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { TabMessage } from "../../types/tab-messages"; - -async function copyText(text: string) { - await window.navigator.clipboard.writeText(text); -} - -async function onMessageListener( - msg: TabMessage, - sender: chrome.runtime.MessageSender, - responseCallback: (response: unknown) => void, -) { - switch (msg.command) { - case "copyText": - await copyText(msg.text); - break; - case "clearClipboard": - await copyText("\u0000"); - break; - default: - } -} - -chrome.runtime.onMessage.addListener(onMessageListener); diff --git a/apps/browser/src/manifest.v3.json b/apps/browser/src/manifest.v3.json index fe3aad37cf4..a093aa42d9d 100644 --- a/apps/browser/src/manifest.v3.json +++ b/apps/browser/src/manifest.v3.json @@ -26,7 +26,7 @@ { "all_frames": true, "css": ["content/autofill.css"], - "js": ["content/trigger-autofill-script-injection.js", "content/misc-utils.js"], + "js": ["content/trigger-autofill-script-injection.js"], "matches": ["*://*/*", "file:///*"], "exclude_matches": ["*://*/*.xml*", "file:///*.xml*"], "run_at": "document_start" diff --git a/apps/browser/webpack.config.js b/apps/browser/webpack.config.js index d077e54bb73..b6e8a147a50 100644 --- a/apps/browser/webpack.config.js +++ b/apps/browser/webpack.config.js @@ -319,9 +319,6 @@ if (manifestVersion == 2) { } else { // Firefox does not use the offscreen API if (browser !== "firefox") { - // Manifest v3 needs an extra helper for utilities in the content script. - // The javascript output of this should be added to manifest.v3.json - mainConfig.entry["content/misc-utils"] = "./src/autofill/content/misc-utils.ts"; mainConfig.entry["offscreen-document/offscreen-document"] = "./src/platform/offscreen-document/offscreen-document.ts";