1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 13:53:34 +00:00

[PM-24748][PM-24072] Chromium importer (#16100)

* Add importer dummy lib, add cargo deps for win/mac

* Add Chromium importer source from bitwarden/password-access

* Mod crypto is no more

* Expose some Chromium importer functions via NAPI, replace home with home_dir crate

* Add Chromium importer to the main <-> renderer IPC, export all functions from Rust

* Add password and notes fields to the imported logins

* Fix windows to use homedir instead of home

* Return success/failure results

* Import from account logins and join

* Linux v10 support

* Use mod util on Windows

* Use mod util on macOS

* Refactor to move shared code into chromium.rs

* Fix windows

* Fix Linux as well

* Linux v11 support for Chrome/Gnome, everything is async now

* Support multiple browsers on Linux v11

* Move oo7 to Linux

* Fix Windows

* Fix macOS

* Add support for Brave browser in Linux configuration

* Add support for Opera browser in Linux configuration

* Fix Edge and add Arc on macOS

* Add Opera on macOS

* Add support for Vivaldi browser in macOS configuration

* Add support for Chromium browser in macOS configuration

* Fix Edge on Windows

* Add Opera on Windows

* Add Vivaldi on windows

* Add Chromium to supported browsers on Windows

* stub out UI options for chromium direct import

* call IPC funcs from import-desktop

* add notes to chrome csv importer

* remove (csv) from import tool names and format item names as hostnames

* Add ABE/v20 encryption support

* ABE/v20 architecture description

* Add a build step to produce admin.exe and service.exe

* Add Windows v20/ABE configuration functionality to specify the full path to the admin.exe and service.exe. Use ipc.platform.chromiumImporter.configureWindowsCryptoService to configure the Chromium importer on Windows.

* rename ARCHITECTURE.md to README.md

* aligns with guidance from architecture re: in-repository documentation.
* also fixes a failing lint.

* cargo fmt

* cargo clippy fix

* Declare feature flag for using chromium importer

* Linter fix after executing npm run prettier

* Use feature flag to guard the use of the chromium importer

* Added temporary logging to further debug, why the Angular change detection isn't working as expected

* introduce importer metadata; host metadata from service; includes tests

* fix cli build

* Register autotype module in lib.rs
introduce by a bad merge

* Fix web build

* Fix issue with loaders being undefined and the feature flag turned off

* Add missing Chromium support when selecting chromecsv

* debugging

* remove chromium support from chromecsv metadata

* fix default loader selection

* [PM-24753] cargo lib file (#16090)

* Add new modules

* Fix chromium importer

* Fix compile bugs for toolchain

* remove importer folder

* remove IPC code

* undo setting change

* clippy fixes

* cargo fmt

* clippy fixes

* clippy fixes

* clippy fixes

* clippy fixes

* lint fix

* fix release build

* Add files in CODEOWNERS

* Create tools owned preload.ts

* Move chromium-importer.service under tools-ownership

* Fix typeError
When accessing the Chromium direct import options the file button is hidden, so trying to access it's values will fail

* Fix tools owned preload

* Remove dead code and redundant truncation

* Remove configureWindowsCryptoService function/methods

* Clean up cargo files

* Fix unused async

* Update apps/desktop/desktop_native/bitwarden_chromium_importer/Cargo.toml

Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>

* Fix napi deps

* fix lints

* format

* fix linux lint

* fix windows lints

* format

* fix missing `?`

* fix a different missing `?`

---------

Co-authored-by: Dmitry Yakimenko <detunized@gmail.com>
Co-authored-by: Kyle Spearrin <kyle.spearrin@gmail.com>
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
Co-authored-by:  Audrey  <ajensen@bitwarden.com>
Co-authored-by:  Audrey  <audrey@audreyality.com>
Co-authored-by: adudek-bw <adudek@bitwarden.com>
Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>
This commit is contained in:
Daniel James Smith
2025-09-04 11:21:57 +02:00
committed by GitHub
parent b957a0c28f
commit 66f5700a75
46 changed files with 2436 additions and 90 deletions

View File

@@ -37,6 +37,7 @@ export enum FeatureFlag {
/* Tools */
DesktopSendUIRefresh = "desktop-send-ui-refresh",
UseSdkPasswordGenerators = "pm-19976-use-sdk-password-generators",
UseChromiumImporter = "pm-23982-chromium-importer",
/* DIRT */
EventBasedOrganizationIntegrations = "event-based-organization-integrations",
@@ -79,6 +80,7 @@ export const DefaultFeatureFlagValue = {
/* Tools */
[FeatureFlag.DesktopSendUIRefresh]: FALSE,
[FeatureFlag.UseSdkPasswordGenerators]: FALSE,
[FeatureFlag.UseChromiumImporter]: FALSE,
/* DIRT */
[FeatureFlag.EventBasedOrganizationIntegrations]: FALSE,

View File

@@ -0,0 +1,178 @@
import { mock, MockProxy } from "jest-mock-extended";
import { PolicyService } from "../admin-console/abstractions/policy/policy.service.abstraction";
import { ConfigService } from "../platform/abstractions/config/config.service";
import { LogService } from "../platform/abstractions/log.service";
import { PlatformUtilsService } from "../platform/abstractions/platform-utils.service";
import { StateProvider } from "../platform/state";
import { LegacyEncryptorProvider } from "./cryptography/legacy-encryptor-provider";
import { ExtensionRegistry } from "./extension/extension-registry.abstraction";
import { ExtensionService } from "./extension/extension.service";
import { disabledSemanticLoggerProvider } from "./log";
import { createSystemServiceProvider } from "./providers";
describe("SystemServiceProvider", () => {
let mockEncryptor: LegacyEncryptorProvider;
let mockState: StateProvider;
let mockPolicy: PolicyService;
let mockRegistry: ExtensionRegistry;
let mockLogger: LogService;
let mockEnvironment: MockProxy<PlatformUtilsService>;
let mockConfigService: ConfigService;
beforeEach(() => {
jest.resetAllMocks();
mockEncryptor = mock<LegacyEncryptorProvider>();
mockState = mock<StateProvider>();
mockPolicy = mock<PolicyService>();
mockRegistry = mock<ExtensionRegistry>();
mockLogger = mock<LogService>();
mockEnvironment = mock<PlatformUtilsService>();
mockConfigService = mock<ConfigService>();
});
describe("createSystemServiceProvider", () => {
it("returns object with all required services when called with valid parameters", () => {
mockEnvironment.isDev.mockReturnValue(false);
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(result).toHaveProperty("policy", mockPolicy);
expect(result).toHaveProperty("extension");
expect(result).toHaveProperty("log");
expect(result).toHaveProperty("configService", mockConfigService);
expect(result).toHaveProperty("environment", mockEnvironment);
expect(result.extension).toBeInstanceOf(ExtensionService);
});
it("creates ExtensionService with correct dependencies when called", () => {
mockEnvironment.isDev.mockReturnValue(true);
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(result.extension).toBeInstanceOf(ExtensionService);
});
describe("given development environment", () => {
it("uses enableLogForTypes when environment.isDev() returns true", () => {
mockEnvironment.isDev.mockReturnValue(true);
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(mockEnvironment.isDev).toHaveBeenCalledTimes(1);
expect(result.log).not.toBe(disabledSemanticLoggerProvider);
});
});
describe("given production environment", () => {
it("uses disabledSemanticLoggerProvider when environment.isDev() returns false", () => {
mockEnvironment.isDev.mockReturnValue(false);
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(mockEnvironment.isDev).toHaveBeenCalledTimes(1);
expect(result.log).toBe(disabledSemanticLoggerProvider);
});
});
it("configures ExtensionService with encryptor, state, log provider, and now function when called", () => {
mockEnvironment.isDev.mockReturnValue(false);
const dateSpy = jest.spyOn(Date, "now");
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(result.extension).toBeInstanceOf(ExtensionService);
expect(dateSpy).not.toHaveBeenCalled();
});
it("passes through policy service correctly when called", () => {
mockEnvironment.isDev.mockReturnValue(false);
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(result.policy).toBe(mockPolicy);
});
it("passes through configService correctly when called", () => {
mockEnvironment.isDev.mockReturnValue(false);
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(result.configService).toBe(mockConfigService);
});
it("passes through environment service correctly when called", () => {
mockEnvironment.isDev.mockReturnValue(false);
const result = createSystemServiceProvider(
mockEncryptor,
mockState,
mockPolicy,
mockRegistry,
mockLogger,
mockEnvironment,
mockConfigService,
);
expect(result.environment).toBe(mockEnvironment);
});
});
});

View File

@@ -1,10 +1,15 @@
import { LogService } from "@bitwarden/logging";
import { BitwardenClient } from "@bitwarden/sdk-internal";
import { StateProvider } from "@bitwarden/state";
import { PolicyService } from "../admin-console/abstractions/policy/policy.service.abstraction";
import { ConfigService } from "../platform/abstractions/config/config.service";
import { PlatformUtilsService } from "../platform/abstractions/platform-utils.service";
import { LegacyEncryptorProvider } from "./cryptography/legacy-encryptor-provider";
import { ExtensionRegistry } from "./extension/extension-registry.abstraction";
import { ExtensionService } from "./extension/extension.service";
import { LogProvider } from "./log";
import { disabledSemanticLoggerProvider, enableLogForTypes, LogProvider } from "./log";
/** Provides access to commonly-used cross-cutting services. */
export type SystemServiceProvider = {
@@ -20,6 +25,42 @@ export type SystemServiceProvider = {
/** Config Service to determine flag features */
readonly configService: ConfigService;
/** Platform Service to inspect runtime environment */
readonly environment: PlatformUtilsService;
/** SDK Service */
readonly sdk: BitwardenClient;
readonly sdk?: BitwardenClient;
};
/** Constructs a system service provider. */
export function createSystemServiceProvider(
encryptor: LegacyEncryptorProvider,
state: StateProvider,
policy: PolicyService,
registry: ExtensionRegistry,
logger: LogService,
environment: PlatformUtilsService,
configService: ConfigService,
): SystemServiceProvider {
let log: LogProvider;
if (environment.isDev()) {
log = enableLogForTypes(logger, []);
} else {
log = disabledSemanticLoggerProvider;
}
const extension = new ExtensionService(registry, {
encryptor,
state,
log,
now: Date.now,
});
return {
policy,
extension,
log,
configService,
environment,
};
}