mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
[PM-5617] Re-add setting to turn off browser autofill (#7592)
* [PM-5617] Re-Add Setting to Turn Off Default Browser Autofill * [PM-5617] Re-Add Setting to Turn Off Default Browser Autofill * [PM-5617] Removing the privacy optional permission from Firefox * [PM-5617] Adding jest tests to validate the behavior within BrowserApi * [PM-5617] Adjusting messaging based on feedback from design * [PM-5617] Adjusting messaging based on feedback from design * [PM-5617] Adjusting messaging based on feedback from design * [PM-5617] Removing unnecessary configService dependency
This commit is contained in:
@@ -62,6 +62,9 @@ function distFirefox() {
|
|||||||
return dist("firefox", (manifest) => {
|
return dist("firefox", (manifest) => {
|
||||||
delete manifest.storage;
|
delete manifest.storage;
|
||||||
delete manifest.sandbox;
|
delete manifest.sandbox;
|
||||||
|
manifest.optional_permissions = manifest.optional_permissions.filter(
|
||||||
|
(permission) => permission !== "privacy",
|
||||||
|
);
|
||||||
return manifest;
|
return manifest;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2895,5 +2895,33 @@
|
|||||||
"commonImportFormats": {
|
"commonImportFormats": {
|
||||||
"message": "Common formats",
|
"message": "Common formats",
|
||||||
"description": "Label indicating the most common import formats"
|
"description": "Label indicating the most common import formats"
|
||||||
|
},
|
||||||
|
"overrideDefaultBrowserAutofillTitle": {
|
||||||
|
"message": "Make Bitwarden your default password manager?",
|
||||||
|
"description": "Dialog title facilitating the ability to override a chrome browser's default autofill behavior"
|
||||||
|
},
|
||||||
|
"overrideDefaultBrowserAutofillDescription": {
|
||||||
|
"message": "Ignoring this option may cause conflicts between the Bitwarden auto-fill menu and your browser's.",
|
||||||
|
"description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior"
|
||||||
|
},
|
||||||
|
"overrideDefaultBrowserAutofillPrivacyRequiredDescription": {
|
||||||
|
"message": "This action will restart the Bitwarden extension. Ignoring this option may cause conflicts between the Bitwarden auto-fill menu and your browser's.",
|
||||||
|
"description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior"
|
||||||
|
},
|
||||||
|
"overrideDefaultBrowserAutoFillSettings": {
|
||||||
|
"message": "Make Bitwarden your default password manager",
|
||||||
|
"description": "Label for the setting that allows overriding the default browser autofill settings"
|
||||||
|
},
|
||||||
|
"privacyPermissionAdditionNotGrantedTitle": {
|
||||||
|
"message": "Unable to set Bitwarden as the default password manager",
|
||||||
|
"description": "Title for the dialog that appears when the user has not granted the extension permission to set privacy settings"
|
||||||
|
},
|
||||||
|
"privacyPermissionAdditionNotGrantedDescription": {
|
||||||
|
"message": "You must grant browser privacy permissions to Bitwarden to set it as the default password manager.",
|
||||||
|
"description": "Description for the dialog that appears when the user has not granted the extension permission to set privacy settings"
|
||||||
|
},
|
||||||
|
"makeDefault": {
|
||||||
|
"message": "Make default",
|
||||||
|
"description": "Button text for the setting that allows overriding the default browser autofill settings"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ import {
|
|||||||
settingsServiceFactory,
|
settingsServiceFactory,
|
||||||
SettingsServiceInitOptions,
|
SettingsServiceInitOptions,
|
||||||
} from "../../../background/service-factories/settings-service.factory";
|
} from "../../../background/service-factories/settings-service.factory";
|
||||||
import {
|
|
||||||
configServiceFactory,
|
|
||||||
ConfigServiceInitOptions,
|
|
||||||
} from "../../../platform/background/service-factories/config-service.factory";
|
|
||||||
import {
|
import {
|
||||||
CachedServices,
|
CachedServices,
|
||||||
factory,
|
factory,
|
||||||
@@ -47,8 +43,7 @@ export type AutoFillServiceInitOptions = AutoFillServiceOptions &
|
|||||||
EventCollectionServiceInitOptions &
|
EventCollectionServiceInitOptions &
|
||||||
LogServiceInitOptions &
|
LogServiceInitOptions &
|
||||||
SettingsServiceInitOptions &
|
SettingsServiceInitOptions &
|
||||||
UserVerificationServiceInitOptions &
|
UserVerificationServiceInitOptions;
|
||||||
ConfigServiceInitOptions;
|
|
||||||
|
|
||||||
export function autofillServiceFactory(
|
export function autofillServiceFactory(
|
||||||
cache: { autofillService?: AbstractAutoFillService } & CachedServices,
|
cache: { autofillService?: AbstractAutoFillService } & CachedServices,
|
||||||
@@ -67,7 +62,6 @@ export function autofillServiceFactory(
|
|||||||
await logServiceFactory(cache, opts),
|
await logServiceFactory(cache, opts),
|
||||||
await settingsServiceFactory(cache, opts),
|
await settingsServiceFactory(cache, opts),
|
||||||
await userVerificationServiceFactory(cache, opts),
|
await userVerificationServiceFactory(cache, opts),
|
||||||
await configServiceFactory(cache, opts),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,10 +41,27 @@
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-footer" *ngIf="accountSwitcherEnabled">
|
<div class="box-footer" *ngIf="accountSwitcherEnabled && canOverrideBrowserAutofillSetting">
|
||||||
{{ "showAutoFillMenuOnFormFieldsDescAlt" | i18n }}
|
{{ "showAutoFillMenuOnFormFieldsDescAlt" | i18n }}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-content" *ngIf="canOverrideBrowserAutofillSetting">
|
||||||
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
<label for="overrideBrowserAutofill" class="!tw-mr-0">{{
|
||||||
|
"overrideDefaultBrowserAutoFillSettings" | i18n
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
id="overrideBrowserAutofill"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateDefaultBrowserAutofillDisabled()"
|
||||||
|
[(ngModel)]="defaultBrowserAutofillDisabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="box-footer">
|
<div class="box-footer">
|
||||||
|
<span *ngIf="accountSwitcherEnabled">{{ "showAutoFillMenuOnFormFieldsDescAlt" | i18n }}</span>
|
||||||
{{ "turnOffBrowserBuiltInPasswordManagerSettings" | i18n }}
|
{{ "turnOffBrowserBuiltInPasswordManagerSettings" | i18n }}
|
||||||
<a
|
<a
|
||||||
[attr.href]="disablePasswordManagerLink"
|
[attr.href]="disablePasswordManagerLink"
|
||||||
@@ -56,7 +73,6 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="box tw-mt-4">
|
<div class="box tw-mt-4">
|
||||||
<div class="box-content">
|
<div class="box-content">
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { UriMatchType } from "@bitwarden/common/vault/enums";
|
import { UriMatchType } from "@bitwarden/common/vault/enums";
|
||||||
|
import { DialogService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { BrowserApi } from "../../../platform/browser/browser-api";
|
import { BrowserApi } from "../../../platform/browser/browser-api";
|
||||||
import { enableAccountSwitching } from "../../../platform/flags";
|
import { enableAccountSwitching } from "../../../platform/flags";
|
||||||
@@ -17,6 +18,8 @@ import { AutofillOverlayVisibility } from "../../utils/autofill-overlay.enum";
|
|||||||
templateUrl: "autofill.component.html",
|
templateUrl: "autofill.component.html",
|
||||||
})
|
})
|
||||||
export class AutofillComponent implements OnInit {
|
export class AutofillComponent implements OnInit {
|
||||||
|
protected canOverrideBrowserAutofillSetting = false;
|
||||||
|
protected defaultBrowserAutofillDisabled = false;
|
||||||
protected autoFillOverlayVisibility: number;
|
protected autoFillOverlayVisibility: number;
|
||||||
protected autoFillOverlayVisibilityOptions: any[];
|
protected autoFillOverlayVisibilityOptions: any[];
|
||||||
protected disablePasswordManagerLink: string;
|
protected disablePasswordManagerLink: string;
|
||||||
@@ -35,6 +38,7 @@ export class AutofillComponent implements OnInit {
|
|||||||
private configService: ConfigServiceAbstraction,
|
private configService: ConfigServiceAbstraction,
|
||||||
private settingsService: SettingsService,
|
private settingsService: SettingsService,
|
||||||
private autofillService: AutofillService,
|
private autofillService: AutofillService,
|
||||||
|
private dialogService: DialogService,
|
||||||
) {
|
) {
|
||||||
this.autoFillOverlayVisibilityOptions = [
|
this.autoFillOverlayVisibilityOptions = [
|
||||||
{
|
{
|
||||||
@@ -68,6 +72,14 @@ export class AutofillComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
|
this.canOverrideBrowserAutofillSetting =
|
||||||
|
this.platformUtilsService.isChrome() ||
|
||||||
|
this.platformUtilsService.isEdge() ||
|
||||||
|
this.platformUtilsService.isOpera() ||
|
||||||
|
this.platformUtilsService.isVivaldi();
|
||||||
|
|
||||||
|
this.defaultBrowserAutofillDisabled = await this.browserAutofillSettingCurrentlyOverridden();
|
||||||
|
|
||||||
this.autoFillOverlayVisibility =
|
this.autoFillOverlayVisibility =
|
||||||
(await this.settingsService.getAutoFillOverlayVisibility()) || AutofillOverlayVisibility.Off;
|
(await this.settingsService.getAutoFillOverlayVisibility()) || AutofillOverlayVisibility.Off;
|
||||||
|
|
||||||
@@ -87,6 +99,7 @@ export class AutofillComponent implements OnInit {
|
|||||||
await this.settingsService.getAutoFillOverlayVisibility();
|
await this.settingsService.getAutoFillOverlayVisibility();
|
||||||
await this.settingsService.setAutoFillOverlayVisibility(this.autoFillOverlayVisibility);
|
await this.settingsService.setAutoFillOverlayVisibility(this.autoFillOverlayVisibility);
|
||||||
await this.handleUpdatingAutofillOverlayContentScripts(previousAutoFillOverlayVisibility);
|
await this.handleUpdatingAutofillOverlayContentScripts(previousAutoFillOverlayVisibility);
|
||||||
|
await this.requestPrivacyPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateAutoFillOnPageLoad() {
|
async updateAutoFillOnPageLoad() {
|
||||||
@@ -165,4 +178,73 @@ export class AutofillComponent implements OnInit {
|
|||||||
|
|
||||||
await this.autofillService.reloadAutofillScripts();
|
await this.autofillService.reloadAutofillScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async requestPrivacyPermission() {
|
||||||
|
if (
|
||||||
|
this.autoFillOverlayVisibility === AutofillOverlayVisibility.Off ||
|
||||||
|
!this.canOverrideBrowserAutofillSetting ||
|
||||||
|
(await this.browserAutofillSettingCurrentlyOverridden())
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const permissionGranted = await this.privacyPermissionGranted();
|
||||||
|
const contentKey = permissionGranted
|
||||||
|
? "overrideDefaultBrowserAutofillDescription"
|
||||||
|
: "overrideDefaultBrowserAutofillPrivacyRequiredDescription";
|
||||||
|
await this.dialogService.openSimpleDialog({
|
||||||
|
title: { key: "overrideDefaultBrowserAutofillTitle" },
|
||||||
|
content: { key: contentKey },
|
||||||
|
acceptButtonText: { key: "makeDefault" },
|
||||||
|
acceptAction: async () => await this.handleOverrideDialogAccept(),
|
||||||
|
cancelButtonText: { key: "ignore" },
|
||||||
|
type: "info",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateDefaultBrowserAutofillDisabled() {
|
||||||
|
const privacyPermissionGranted = await this.privacyPermissionGranted();
|
||||||
|
if (!this.defaultBrowserAutofillDisabled && !privacyPermissionGranted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!privacyPermissionGranted &&
|
||||||
|
!(await BrowserApi.requestPermission({ permissions: ["privacy"] }))
|
||||||
|
) {
|
||||||
|
await this.dialogService.openSimpleDialog({
|
||||||
|
title: { key: "privacyPermissionAdditionNotGrantedTitle" },
|
||||||
|
content: { key: "privacyPermissionAdditionNotGrantedDescription" },
|
||||||
|
acceptButtonText: { key: "ok" },
|
||||||
|
cancelButtonText: null,
|
||||||
|
type: "warning",
|
||||||
|
});
|
||||||
|
this.defaultBrowserAutofillDisabled = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserApi.updateDefaultBrowserAutofillSettings(!this.defaultBrowserAutofillDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleOverrideDialogAccept = async () => {
|
||||||
|
this.defaultBrowserAutofillDisabled = true;
|
||||||
|
await this.updateDefaultBrowserAutofillDisabled();
|
||||||
|
};
|
||||||
|
|
||||||
|
async browserAutofillSettingCurrentlyOverridden() {
|
||||||
|
if (!this.canOverrideBrowserAutofillSetting) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await this.privacyPermissionGranted())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await BrowserApi.browserAutofillSettingsOverridden();
|
||||||
|
}
|
||||||
|
|
||||||
|
async privacyPermissionGranted(): Promise<boolean> {
|
||||||
|
return await BrowserApi.permissionsGranted(["privacy"]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { mock, mockReset } from "jest-mock-extended";
|
|||||||
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
|
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/services/config/config.service";
|
|
||||||
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/services/event/event-collection.service";
|
||||||
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
import { SettingsService } from "@bitwarden/common/services/settings.service";
|
||||||
import {
|
import {
|
||||||
@@ -56,7 +55,6 @@ describe("AutofillService", () => {
|
|||||||
const logService = mock<LogService>();
|
const logService = mock<LogService>();
|
||||||
const settingsService = mock<SettingsService>();
|
const settingsService = mock<SettingsService>();
|
||||||
const userVerificationService = mock<UserVerificationService>();
|
const userVerificationService = mock<UserVerificationService>();
|
||||||
const configService = mock<ConfigService>();
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
autofillService = new AutofillService(
|
autofillService = new AutofillService(
|
||||||
@@ -67,7 +65,6 @@ describe("AutofillService", () => {
|
|||||||
logService,
|
logService,
|
||||||
settingsService,
|
settingsService,
|
||||||
userVerificationService,
|
userVerificationService,
|
||||||
configService,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { EventCollectionService } from "@bitwarden/common/abstractions/event/eve
|
|||||||
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
|
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||||
@@ -47,7 +46,6 @@ export default class AutofillService implements AutofillServiceInterface {
|
|||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private settingsService: SettingsService,
|
private settingsService: SettingsService,
|
||||||
private userVerificationService: UserVerificationService,
|
private userVerificationService: UserVerificationService,
|
||||||
private configService: ConfigServiceAbstraction,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -614,7 +614,6 @@ export default class MainBackground {
|
|||||||
this.logService,
|
this.logService,
|
||||||
this.settingsService,
|
this.settingsService,
|
||||||
this.userVerificationService,
|
this.userVerificationService,
|
||||||
this.configService,
|
|
||||||
);
|
);
|
||||||
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
this.auditService = new AuditService(this.cryptoFunctionService, this.apiService);
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
"webRequest",
|
"webRequest",
|
||||||
"webRequestBlocking"
|
"webRequestBlocking"
|
||||||
],
|
],
|
||||||
"optional_permissions": ["nativeMessaging"],
|
"optional_permissions": ["nativeMessaging", "privacy"],
|
||||||
"content_security_policy": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
|
"content_security_policy": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
|
||||||
"sandbox": {
|
"sandbox": {
|
||||||
"pages": ["overlay/button.html", "overlay/list.html"],
|
"pages": ["overlay/button.html", "overlay/list.html"],
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
"alarms",
|
"alarms",
|
||||||
"scripting"
|
"scripting"
|
||||||
],
|
],
|
||||||
"optional_permissions": ["nativeMessaging"],
|
"optional_permissions": ["nativeMessaging", "privacy"],
|
||||||
"host_permissions": ["http://*/*", "https://*/*"],
|
"host_permissions": ["http://*/*", "https://*/*"],
|
||||||
"content_security_policy": {
|
"content_security_policy": {
|
||||||
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
|
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'",
|
||||||
|
|||||||
@@ -136,4 +136,82 @@ describe("BrowserApi", () => {
|
|||||||
expect(result).toEqual(executeScriptResult);
|
expect(result).toEqual(executeScriptResult);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("browserAutofillSettingsOverridden", () => {
|
||||||
|
it("returns true if the browser autofill settings are overridden", async () => {
|
||||||
|
const expectedDetails = {
|
||||||
|
value: false,
|
||||||
|
levelOfControl: "controlled_by_this_extension",
|
||||||
|
} as chrome.types.ChromeSettingGetResultDetails;
|
||||||
|
chrome.privacy.services.autofillAddressEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
chrome.privacy.services.autofillCreditCardEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
chrome.privacy.services.passwordSavingEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await BrowserApi.browserAutofillSettingsOverridden();
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false if the browser autofill settings are not overridden", async () => {
|
||||||
|
const expectedDetails = {
|
||||||
|
value: true,
|
||||||
|
levelOfControl: "controlled_by_this_extension",
|
||||||
|
} as chrome.types.ChromeSettingGetResultDetails;
|
||||||
|
chrome.privacy.services.autofillAddressEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
chrome.privacy.services.autofillCreditCardEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
chrome.privacy.services.passwordSavingEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await BrowserApi.browserAutofillSettingsOverridden();
|
||||||
|
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false if the browser autofill settings are not controlled by the extension", async () => {
|
||||||
|
const expectedDetails = {
|
||||||
|
value: false,
|
||||||
|
levelOfControl: "controlled_by_other_extensions",
|
||||||
|
} as chrome.types.ChromeSettingGetResultDetails;
|
||||||
|
chrome.privacy.services.autofillAddressEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
chrome.privacy.services.autofillCreditCardEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
chrome.privacy.services.passwordSavingEnabled.get = jest.fn((details, callback) =>
|
||||||
|
callback(expectedDetails),
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await BrowserApi.browserAutofillSettingsOverridden();
|
||||||
|
|
||||||
|
expect(result).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("updateDefaultBrowserAutofillSettings", () => {
|
||||||
|
it("updates the default browser autofill settings", async () => {
|
||||||
|
await BrowserApi.updateDefaultBrowserAutofillSettings(false);
|
||||||
|
|
||||||
|
expect(chrome.privacy.services.autofillAddressEnabled.set).toHaveBeenCalledWith({
|
||||||
|
value: false,
|
||||||
|
});
|
||||||
|
expect(chrome.privacy.services.autofillCreditCardEnabled.set).toHaveBeenCalledWith({
|
||||||
|
value: false,
|
||||||
|
});
|
||||||
|
expect(chrome.privacy.services.passwordSavingEnabled.set).toHaveBeenCalledWith({
|
||||||
|
value: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -445,4 +445,43 @@ export class BrowserApi {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies if the browser autofill settings are overridden by the extension.
|
||||||
|
*/
|
||||||
|
static async browserAutofillSettingsOverridden(): Promise<boolean> {
|
||||||
|
const checkOverrideStatus = (details: chrome.types.ChromeSettingGetResultDetails) =>
|
||||||
|
details.levelOfControl === "controlled_by_this_extension" && !details.value;
|
||||||
|
|
||||||
|
const autofillAddressOverridden: boolean = await new Promise((resolve) =>
|
||||||
|
chrome.privacy.services.autofillAddressEnabled.get({}, (details) =>
|
||||||
|
resolve(checkOverrideStatus(details)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const autofillCreditCardOverridden: boolean = await new Promise((resolve) =>
|
||||||
|
chrome.privacy.services.autofillCreditCardEnabled.get({}, (details) =>
|
||||||
|
resolve(checkOverrideStatus(details)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
const passwordSavingOverridden: boolean = await new Promise((resolve) =>
|
||||||
|
chrome.privacy.services.passwordSavingEnabled.get({}, (details) =>
|
||||||
|
resolve(checkOverrideStatus(details)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return autofillAddressOverridden && autofillCreditCardOverridden && passwordSavingOverridden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the browser autofill settings to the given value.
|
||||||
|
*
|
||||||
|
* @param value - Determines whether to enable or disable the autofill settings.
|
||||||
|
*/
|
||||||
|
static updateDefaultBrowserAutofillSettings(value: boolean) {
|
||||||
|
chrome.privacy.services.autofillAddressEnabled.set({ value });
|
||||||
|
chrome.privacy.services.autofillCreditCardEnabled.set({ value });
|
||||||
|
chrome.privacy.services.passwordSavingEnabled.set({ value });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,23 @@ const port = {
|
|||||||
postMessage: jest.fn(),
|
postMessage: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const privacy = {
|
||||||
|
services: {
|
||||||
|
autofillAddressEnabled: {
|
||||||
|
get: jest.fn(),
|
||||||
|
set: jest.fn(),
|
||||||
|
},
|
||||||
|
autofillCreditCardEnabled: {
|
||||||
|
get: jest.fn(),
|
||||||
|
set: jest.fn(),
|
||||||
|
},
|
||||||
|
passwordSavingEnabled: {
|
||||||
|
get: jest.fn(),
|
||||||
|
set: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// set chrome
|
// set chrome
|
||||||
global.chrome = {
|
global.chrome = {
|
||||||
i18n,
|
i18n,
|
||||||
@@ -98,4 +115,5 @@ global.chrome = {
|
|||||||
scripting,
|
scripting,
|
||||||
windows,
|
windows,
|
||||||
port,
|
port,
|
||||||
|
privacy,
|
||||||
} as any;
|
} as any;
|
||||||
|
|||||||
Reference in New Issue
Block a user