mirror of
https://github.com/bitwarden/browser
synced 2025-12-06 00:13:28 +00:00
Delete everything related to misc-utils (#13395)
This commit is contained in:
@@ -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",
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
});
|
||||
};
|
||||
@@ -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<PasswordGenerationServiceAbstraction>;
|
||||
let autofillSettingsService: MockProxy<AutofillSettingsService>;
|
||||
let browserTaskSchedulerService: MockProxy<BrowserTaskSchedulerService>;
|
||||
|
||||
let sut: GeneratePasswordToClipboardCommand;
|
||||
|
||||
beforeEach(() => {
|
||||
passwordGenerationService = mock<PasswordGenerationServiceAbstraction>();
|
||||
autofillSettingsService = mock<AutofillSettingsService>();
|
||||
browserTaskSchedulerService = mock<BrowserTaskSchedulerService>({
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from "./clear-clipboard";
|
||||
export * from "./copy-to-clipboard-command";
|
||||
export * from "./generate-password-to-clipboard-command";
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user