mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-22 11:45:59 +01:00
[PS-2455] Catch and log contextmenu errors (#4699)
* Set initRunning to true initRunning was checked and at the end set to false, but it never got set to true * Catch and log contextmenu errors
This commit is contained in:
parent
9a20bda169
commit
db202f9e9e
@ -1,6 +1,7 @@
|
|||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
@ -12,6 +13,7 @@ import { MainContextMenuHandler } from "./main-context-menu-handler";
|
|||||||
describe("context-menu", () => {
|
describe("context-menu", () => {
|
||||||
let stateService: MockProxy<BrowserStateService>;
|
let stateService: MockProxy<BrowserStateService>;
|
||||||
let i18nService: MockProxy<I18nService>;
|
let i18nService: MockProxy<I18nService>;
|
||||||
|
let logService: MockProxy<LogService>;
|
||||||
|
|
||||||
let removeAllSpy: jest.SpyInstance<void, [callback?: () => void]>;
|
let removeAllSpy: jest.SpyInstance<void, [callback?: () => void]>;
|
||||||
let createSpy: jest.SpyInstance<
|
let createSpy: jest.SpyInstance<
|
||||||
@ -24,6 +26,7 @@ describe("context-menu", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
stateService = mock();
|
stateService = mock();
|
||||||
i18nService = mock();
|
i18nService = mock();
|
||||||
|
logService = mock();
|
||||||
|
|
||||||
removeAllSpy = jest
|
removeAllSpy = jest
|
||||||
.spyOn(chrome.contextMenus, "removeAll")
|
.spyOn(chrome.contextMenus, "removeAll")
|
||||||
@ -36,7 +39,7 @@ describe("context-menu", () => {
|
|||||||
return props.id;
|
return props.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
sut = new MainContextMenuHandler(stateService, i18nService);
|
sut = new MainContextMenuHandler(stateService, i18nService, logService);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => jest.resetAllMocks());
|
afterEach(() => jest.resetAllMocks());
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
|
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
|
||||||
import { Utils } from "@bitwarden/common/misc/utils";
|
import { Utils } from "@bitwarden/common/misc/utils";
|
||||||
import { GlobalState } from "@bitwarden/common/models/domain/global-state";
|
import { GlobalState } from "@bitwarden/common/models/domain/global-state";
|
||||||
@ -10,6 +11,10 @@ import {
|
|||||||
i18nServiceFactory,
|
i18nServiceFactory,
|
||||||
I18nServiceInitOptions,
|
I18nServiceInitOptions,
|
||||||
} from "../../background/service_factories/i18n-service.factory";
|
} from "../../background/service_factories/i18n-service.factory";
|
||||||
|
import {
|
||||||
|
logServiceFactory,
|
||||||
|
LogServiceInitOptions,
|
||||||
|
} from "../../background/service_factories/log-service.factory";
|
||||||
import {
|
import {
|
||||||
stateServiceFactory,
|
stateServiceFactory,
|
||||||
StateServiceInitOptions,
|
StateServiceInitOptions,
|
||||||
@ -36,7 +41,11 @@ export class MainContextMenuHandler {
|
|||||||
|
|
||||||
create: (options: chrome.contextMenus.CreateProperties) => Promise<void>;
|
create: (options: chrome.contextMenus.CreateProperties) => Promise<void>;
|
||||||
|
|
||||||
constructor(private stateService: BrowserStateService, private i18nService: I18nService) {
|
constructor(
|
||||||
|
private stateService: BrowserStateService,
|
||||||
|
private i18nService: I18nService,
|
||||||
|
private logService: LogService
|
||||||
|
) {
|
||||||
if (chrome.contextMenus) {
|
if (chrome.contextMenus) {
|
||||||
this.create = (options) => {
|
this.create = (options) => {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
@ -56,30 +65,32 @@ export class MainContextMenuHandler {
|
|||||||
|
|
||||||
static async mv3Create(cachedServices: CachedServices) {
|
static async mv3Create(cachedServices: CachedServices) {
|
||||||
const stateFactory = new StateFactory(GlobalState, Account);
|
const stateFactory = new StateFactory(GlobalState, Account);
|
||||||
const serviceOptions: StateServiceInitOptions & I18nServiceInitOptions = {
|
const serviceOptions: StateServiceInitOptions & I18nServiceInitOptions & LogServiceInitOptions =
|
||||||
cryptoFunctionServiceOptions: {
|
{
|
||||||
win: self,
|
cryptoFunctionServiceOptions: {
|
||||||
},
|
win: self,
|
||||||
encryptServiceOptions: {
|
},
|
||||||
logMacFailures: false,
|
encryptServiceOptions: {
|
||||||
},
|
logMacFailures: false,
|
||||||
i18nServiceOptions: {
|
},
|
||||||
systemLanguage: chrome.i18n.getUILanguage(),
|
i18nServiceOptions: {
|
||||||
},
|
systemLanguage: chrome.i18n.getUILanguage(),
|
||||||
logServiceOptions: {
|
},
|
||||||
isDev: false,
|
logServiceOptions: {
|
||||||
},
|
isDev: false,
|
||||||
stateMigrationServiceOptions: {
|
},
|
||||||
stateFactory: stateFactory,
|
stateMigrationServiceOptions: {
|
||||||
},
|
stateFactory: stateFactory,
|
||||||
stateServiceOptions: {
|
},
|
||||||
stateFactory: stateFactory,
|
stateServiceOptions: {
|
||||||
},
|
stateFactory: stateFactory,
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return new MainContextMenuHandler(
|
return new MainContextMenuHandler(
|
||||||
await stateServiceFactory(cachedServices, serviceOptions),
|
await stateServiceFactory(cachedServices, serviceOptions),
|
||||||
await i18nServiceFactory(cachedServices, serviceOptions)
|
await i18nServiceFactory(cachedServices, serviceOptions),
|
||||||
|
await logServiceFactory(cachedServices, serviceOptions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,17 +100,17 @@ export class MainContextMenuHandler {
|
|||||||
*/
|
*/
|
||||||
async init(): Promise<boolean> {
|
async init(): Promise<boolean> {
|
||||||
const menuDisabled = await this.stateService.getDisableContextMenuItem();
|
const menuDisabled = await this.stateService.getDisableContextMenuItem();
|
||||||
|
if (menuDisabled) {
|
||||||
if (this.initRunning) {
|
await MainContextMenuHandler.removeAll();
|
||||||
return menuDisabled;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (this.initRunning) {
|
||||||
if (menuDisabled) {
|
return true;
|
||||||
await MainContextMenuHandler.removeAll();
|
}
|
||||||
return false;
|
this.initRunning = true;
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
const create = async (options: Omit<chrome.contextMenus.CreateProperties, "contexts">) => {
|
const create = async (options: Omit<chrome.contextMenus.CreateProperties, "contexts">) => {
|
||||||
await this.create({ ...options, contexts: ["all"] });
|
await this.create({ ...options, contexts: ["all"] });
|
||||||
};
|
};
|
||||||
@ -152,11 +163,12 @@ export class MainContextMenuHandler {
|
|||||||
parentId: ROOT_ID,
|
parentId: ROOT_ID,
|
||||||
title: this.i18nService.t("copyElementIdentifier"),
|
title: this.i18nService.t("copyElementIdentifier"),
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
return true;
|
this.logService.warning(error.message);
|
||||||
} finally {
|
} finally {
|
||||||
this.initRunning = false;
|
this.initRunning = false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async removeAll() {
|
static async removeAll() {
|
||||||
@ -190,33 +202,37 @@ export class MainContextMenuHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sanitizedTitle = MainContextMenuHandler.sanitizeContextMenuTitle(title);
|
try {
|
||||||
|
const sanitizedTitle = MainContextMenuHandler.sanitizeContextMenuTitle(title);
|
||||||
|
|
||||||
const createChildItem = async (parent: string) => {
|
const createChildItem = async (parent: string) => {
|
||||||
const menuItemId = `${parent}_${id}`;
|
const menuItemId = `${parent}_${id}`;
|
||||||
return await this.create({
|
return await this.create({
|
||||||
type: "normal",
|
type: "normal",
|
||||||
id: menuItemId,
|
id: menuItemId,
|
||||||
parentId: parent,
|
parentId: parent,
|
||||||
title: sanitizedTitle,
|
title: sanitizedTitle,
|
||||||
contexts: ["all"],
|
contexts: ["all"],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cipher == null || !Utils.isNullOrEmpty(cipher.login.password)) {
|
if (cipher == null || !Utils.isNullOrEmpty(cipher.login.password)) {
|
||||||
await createChildItem(AUTOFILL_ID);
|
await createChildItem(AUTOFILL_ID);
|
||||||
if (cipher?.viewPassword ?? true) {
|
if (cipher?.viewPassword ?? true) {
|
||||||
await createChildItem(COPY_PASSWORD_ID);
|
await createChildItem(COPY_PASSWORD_ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (cipher == null || !Utils.isNullOrEmpty(cipher.login.username)) {
|
if (cipher == null || !Utils.isNullOrEmpty(cipher.login.username)) {
|
||||||
await createChildItem(COPY_USERNAME_ID);
|
await createChildItem(COPY_USERNAME_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const canAccessPremium = await this.stateService.getCanAccessPremium();
|
const canAccessPremium = await this.stateService.getCanAccessPremium();
|
||||||
if (canAccessPremium && (cipher == null || !Utils.isNullOrEmpty(cipher.login.totp))) {
|
if (canAccessPremium && (cipher == null || !Utils.isNullOrEmpty(cipher.login.totp))) {
|
||||||
await createChildItem(COPY_VERIFICATIONCODE_ID);
|
await createChildItem(COPY_VERIFICATIONCODE_ID);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.logService.warning(error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,7 +573,11 @@ export default class MainBackground {
|
|||||||
this.avatarUpdateService = new AvatarUpdateService(this.apiService, this.stateService);
|
this.avatarUpdateService = new AvatarUpdateService(this.apiService, this.stateService);
|
||||||
|
|
||||||
if (!this.popupOnlyContext) {
|
if (!this.popupOnlyContext) {
|
||||||
this.mainContextMenuHandler = new MainContextMenuHandler(this.stateService, this.i18nService);
|
this.mainContextMenuHandler = new MainContextMenuHandler(
|
||||||
|
this.stateService,
|
||||||
|
this.i18nService,
|
||||||
|
this.logService
|
||||||
|
);
|
||||||
|
|
||||||
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
this.cipherContextMenuHandler = new CipherContextMenuHandler(
|
||||||
this.mainContextMenuHandler,
|
this.mainContextMenuHandler,
|
||||||
|
Loading…
Reference in New Issue
Block a user