1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-12 22:44:11 +00:00

Improve desktop autofill developer builds (#18334)

* Consolidate references to credential provider feature flag
* Adjust entitlements and build stuff for macOS autofill credential extension
* Reduce signature time for MAS builds
This commit is contained in:
Isaiah Inuwa
2026-01-22 05:58:37 -06:00
committed by GitHub
parent 0433678085
commit d0e3923eb6
8 changed files with 161 additions and 22 deletions

View File

@@ -85,7 +85,8 @@
"signIgnore": [
"MacOS/desktop_proxy",
"MacOS/desktop_proxy.inherit",
"Contents/Plugins/autofill-extension.appex"
"Contents/Plugins/autofill-extension.appex",
"Frameworks/Electron Framework.framework/(Electron Framework|Libraries|Resources|Versions/Current)/.*"
],
"target": ["dmg", "zip"]
},

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>LTZ2PFU5D6.com.bitwarden.desktop</string>
</array>
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
</dict>
</plist>

View File

@@ -256,7 +256,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = D83832AD2D67B9D0003FB9F8 /* ReleaseDeveloper.xcconfig */;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension.entitlements";
CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension_enabled.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
CODE_SIGN_STYLE = Manual;
@@ -409,7 +409,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = D83832AB2D67B9AE003FB9F8 /* Debug.xcconfig */;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension.entitlements";
CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension_enabled.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
CODE_SIGN_STYLE = Manual;

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "2610"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E1DF713B2B342F6900F29026"
BuildableName = "autofill-extension.appex"
BlueprintName = "autofill-extension"
ReferencedContainer = "container:desktop.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
</LaunchAction>
<ProfileAction
buildConfiguration = "ReleaseAppStore"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
askForAppToLaunch = "Yes"
launchAutomaticallySubstyle = "2">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E1DF713B2B342F6900F29026"
BuildableName = "autofill-extension.appex"
BlueprintName = "autofill-extension"
ReferencedContainer = "container:desktop.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "ReleaseAppStore"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -46,7 +46,7 @@
"pack:mac:with-extension": "npm run clean:dist && npm run build:macos-extension:mac && electron-builder --mac --universal -p never",
"pack:mac:arm64": "npm run clean:dist && electron-builder --mac --arm64 -p never",
"pack:mac:mas": "npm run clean:dist && npm run build:macos-extension:mas && electron-builder --mac mas --universal -p never",
"pack:mac:masdev": "npm run clean:dist && npm run build:macos-extension:masdev && electron-builder --mac mas-dev --universal -p never",
"pack:mac:masdev": "npm run clean:dist && electron-builder --mac mas-dev --universal -p never -c.mac.identity=null -c.mas.identity=$CSC_NAME -c.mas.provisioningProfile=bitwarden_desktop_developer_id.provisionprofile -c.mas.entitlements=resources/entitlements.mas.autofill-enabled.plist",
"pack:local:mac": "npm run clean:dist && npm run build:macos-extension:masdev && electron-builder --mac mas-dev --universal -p never -c.mac.provisioningProfile=\"\" -c.mas.provisioningProfile=\"\"",
"pack:win": "npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p never",
"pack:win:beta": "npm run clean:dist && electron-builder --config electron-builder.beta.json --win --x64 --arm64 --ia32 -p never",

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>LTZ2PFU5D6.com.bitwarden.desktop</string>
<key>com.apple.developer.team-identifier</key>
<string>LTZ2PFU5D6</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>LTZ2PFU5D6.com.bitwarden.desktop</string>
</array>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
<array>
<string>/Library/Application Support/Mozilla/NativeMessagingHosts/</string>
<string>/Library/Application Support/Google/Chrome/NativeMessagingHosts/</string>
<string>/Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/</string>
<string>/Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/</string>
<string>/Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/</string>
<string>/Library/Application Support/Chromium/NativeMessagingHosts/</string>
<string>/Library/Application Support/Microsoft Edge/NativeMessagingHosts/</string>
<string>/Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/</string>
<string>/Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/</string>
<string>/Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/</string>
<string>/Library/Application Support/Vivaldi/NativeMessagingHosts/</string>
<string>/Library/Application Support/Zen/NativeMessagingHosts/</string>
<string>/Library/Application Support/net.imput.helium</string>
</array>
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
</dict>
</plist>

View File

@@ -16,7 +16,9 @@ async function run(context) {
const appPath = `${context.appOutDir}/${appName}.app`;
const macBuild = context.electronPlatformName === "darwin";
const copySafariExtension = ["darwin", "mas"].includes(context.electronPlatformName);
const copyAutofillExtension = ["darwin"].includes(context.electronPlatformName); // Disabled for mas builds
const isMasDevBuild =
context.electronPlatformName === "mas" && context.targets.at(0)?.name === "mas-dev";
const copyAutofillExtension = ["darwin"].includes(context.electronPlatformName) || isMasDevBuild;
let shouldResign = false;
@@ -31,7 +33,6 @@ async function run(context) {
fse.mkdirSync(path.join(appPath, "Contents/PlugIns"));
}
fse.copySync(extensionPath, path.join(appPath, "Contents/PlugIns/autofill-extension.appex"));
shouldResign = true;
}
}

View File

@@ -10,6 +10,7 @@ import {
mergeMap,
switchMap,
takeUntil,
tap,
} from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
@@ -52,6 +53,8 @@ import type { NativeWindowObject } from "./desktop-fido2-user-interface.service"
export class DesktopAutofillService implements OnDestroy {
private destroy$ = new Subject<void>();
private registrationRequest: autofill.PasskeyRegistrationRequest;
private featureFlag?: FeatureFlag;
private isEnabled: boolean = false;
constructor(
private logService: LogService,
@@ -60,19 +63,26 @@ export class DesktopAutofillService implements OnDestroy {
private fido2AuthenticatorService: Fido2AuthenticatorServiceAbstraction<NativeWindowObject>,
private accountService: AccountService,
private authService: AuthService,
private platformUtilsService: PlatformUtilsService,
) {}
platformUtilsService: PlatformUtilsService,
) {
const deviceType = platformUtilsService.getDevice();
if (deviceType === DeviceType.MacOsDesktop) {
this.featureFlag = FeatureFlag.MacOsNativeCredentialSync;
}
}
async init() {
// Currently only supported for MacOS
if (this.platformUtilsService.getDevice() !== DeviceType.MacOsDesktop) {
this.isEnabled =
this.featureFlag && (await this.configService.getFeatureFlag(this.featureFlag));
if (!this.isEnabled) {
return;
}
this.configService
.getFeatureFlag$(FeatureFlag.MacOsNativeCredentialSync)
.getFeatureFlag$(this.featureFlag)
.pipe(
distinctUntilChanged(),
tap((enabled) => (this.isEnabled = enabled)),
filter((enabled) => enabled === true), // Only proceed if feature is enabled
switchMap(() => {
return combineLatest([
@@ -199,11 +209,11 @@ export class DesktopAutofillService implements OnDestroy {
listenIpc() {
ipc.autofill.listenPasskeyRegistration(async (clientId, sequenceNumber, request, callback) => {
if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
if (!this.isEnabled) {
this.logService.debug(
"listenPasskeyRegistration: MacOsNativeCredentialSync feature flag is disabled",
`listenPasskeyRegistration: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
callback(new Error("MacOsNativeCredentialSync feature flag is disabled"), null);
callback(new Error("Native credential sync feature flag is disabled"), null);
return;
}
@@ -230,11 +240,11 @@ export class DesktopAutofillService implements OnDestroy {
ipc.autofill.listenPasskeyAssertionWithoutUserInterface(
async (clientId, sequenceNumber, request, callback) => {
if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
if (!this.isEnabled) {
this.logService.debug(
"listenPasskeyAssertionWithoutUserInterface: MacOsNativeCredentialSync feature flag is disabled",
`listenPasskeyAssertionWithoutUserInterface: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
callback(new Error("MacOsNativeCredentialSync feature flag is disabled"), null);
callback(new Error("Native credential sync feature flag is disabled"), null);
return;
}
@@ -297,11 +307,11 @@ export class DesktopAutofillService implements OnDestroy {
);
ipc.autofill.listenPasskeyAssertion(async (clientId, sequenceNumber, request, callback) => {
if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
if (!this.isEnabled) {
this.logService.debug(
"listenPasskeyAssertion: MacOsNativeCredentialSync feature flag is disabled",
`listenPasskeyAssertion: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
callback(new Error("MacOsNativeCredentialSync feature flag is disabled"), null);
callback(new Error("Native credential sync feature flag is disabled"), null);
return;
}
@@ -324,9 +334,9 @@ export class DesktopAutofillService implements OnDestroy {
// Listen for native status messages
ipc.autofill.listenNativeStatus(async (clientId, sequenceNumber, status) => {
if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
if (!this.isEnabled) {
this.logService.debug(
"listenNativeStatus: MacOsNativeCredentialSync feature flag is disabled",
`listenNativeStatus: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
return;
}