Skip to content

Commit

Permalink
Merge branch 'main' into PM-13894
Browse files Browse the repository at this point in the history
  • Loading branch information
cd-bitwarden authored Nov 14, 2024
2 parents a938cbb + e6fce42 commit ccd727d
Show file tree
Hide file tree
Showing 33 changed files with 583 additions and 148 deletions.
20 changes: 5 additions & 15 deletions .github/workflows/build-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1177,21 +1177,6 @@ jobs:
--file $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \
--output none
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name bitwarden_desktop_autofill_app_store_2024.provisionprofile \
--file $HOME/secrets/bitwarden_desktop_autofill_app_store_2024.provisionprofile \
--output none
- name: Set up provisioning profiles
run: |
AUTOFILL_PROFILE_PATH=$HOME/secrets/bitwarden_desktop_autofill_app_store_2024.provisionprofile
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
mkdir -p "$PROFILES_DIR_PATH"
AUTOFILL_UUID=$(grep UUID -A1 -a $AUTOFILL_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
cp $AUTOFILL_PROFILE_PATH "$PROFILES_DIR_PATH/$AUTOFILL_UUID.provisionprofile"
- name: Get certificates
run: |
mkdir -p $HOME/certificates
Expand Down Expand Up @@ -1243,6 +1228,11 @@ jobs:
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Set up provisioning profiles
run: |
cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \
$GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile
- name: Increment version
shell: pwsh
env:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<popup-page>
<popup-page [disablePadding]="true">
<popup-header
slot="header"
[background]="'alt'"
Expand All @@ -19,7 +19,6 @@
[icon]="pageIcon"
[showReadonlyHostname]="showReadonlyHostname"
[hideLogo]="true"
[decreaseTopPadding]="true"
[maxWidth]="maxWidth"
>
<router-outlet></router-outlet>
Expand Down
6 changes: 4 additions & 2 deletions apps/browser/src/background/main.background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ export default class MainBackground {
autoSubmitLoginBackground: AutoSubmitLoginBackground;
sdkService: SdkService;
cipherAuthorizationService: CipherAuthorizationService;
inlineMenuFieldQualificationService: InlineMenuFieldQualificationService;

onUpdatedRan: boolean;
onReplacedRan: boolean;
Expand Down Expand Up @@ -1249,6 +1250,8 @@ export default class MainBackground {
this.collectionService,
this.organizationService,
);

this.inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();
}

async bootstrap() {
Expand Down Expand Up @@ -1630,7 +1633,6 @@ export default class MainBackground {
this.themeStateService,
);
} else {
const inlineMenuFieldQualificationService = new InlineMenuFieldQualificationService();
this.overlayBackground = new OverlayBackground(
this.logService,
this.cipherService,
Expand All @@ -1643,7 +1645,7 @@ export default class MainBackground {
this.platformUtilsService,
this.vaultSettingsService,
this.fido2ActiveRequestManager,
inlineMenuFieldQualificationService,
this.inlineMenuFieldQualificationService,
this.themeStateService,
this.totpService,
() => this.generatePassword(),
Expand Down
2 changes: 2 additions & 0 deletions apps/browser/src/popup/services/services.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ import { ExtensionAnonLayoutWrapperDataService } from "../../auth/popup/extensio
import { ExtensionLoginComponentService } from "../../auth/popup/login/extension-login-component.service";
import { AutofillService as AutofillServiceAbstraction } from "../../autofill/services/abstractions/autofill.service";
import AutofillService from "../../autofill/services/autofill.service";
import { InlineMenuFieldQualificationService } from "../../autofill/services/inline-menu-field-qualification.service";
import { ForegroundBrowserBiometricsService } from "../../key-management/biometrics/foreground-browser-biometrics";
import { BrowserKeyService } from "../../key-management/browser-key.service";
import { BrowserApi } from "../../platform/browser/browser-api";
Expand Down Expand Up @@ -167,6 +168,7 @@ const safeProviders: SafeProvider[] = [
safeProvider(DebounceNavigationService),
safeProvider(DialogService),
safeProvider(PopupCloseWarningService),
safeProvider(InlineMenuFieldQualificationService),
safeProvider({
provide: DEFAULT_VAULT_TIMEOUT,
useValue: VaultTimeoutStringType.OnRestart,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Subject } from "rxjs";

import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { AUTOFILL_ID } from "@bitwarden/common/autofill/constants";
import { EventType } from "@bitwarden/common/enums";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
Expand Down Expand Up @@ -33,6 +34,7 @@ describe("ViewV2Component", () => {
const params$ = new Subject();
const mockNavigate = jest.fn();
const collect = jest.fn().mockResolvedValue(null);
const doAutofill = jest.fn();

const mockCipher = {
id: "122-333-444",
Expand All @@ -41,7 +43,7 @@ describe("ViewV2Component", () => {
};

const mockVaultPopupAutofillService = {
doAutofill: jest.fn(),
doAutofill,
};
const mockUserId = Utils.newGuid() as UserId;
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
Expand All @@ -54,6 +56,7 @@ describe("ViewV2Component", () => {
beforeEach(async () => {
mockNavigate.mockClear();
collect.mockClear();
doAutofill.mockClear();

await TestBed.configureTestingModule({
imports: [ViewV2Component],
Expand Down Expand Up @@ -148,5 +151,13 @@ describe("ViewV2Component", () => {
undefined,
);
}));

it('invokes `doAutofill` when action="AUTOFILL_ID"', fakeAsync(() => {
params$.next({ action: AUTOFILL_ID });

flush(); // Resolve all promises

expect(doAutofill).toHaveBeenCalledOnce();
}));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class ViewV2Component {
switchMap(async (cipher) => {
this.cipher = cipher;
this.headerText = this.setHeader(cipher.type);
if (this.loadAction === AUTOFILL_ID || this.loadAction === SHOW_AUTOFILL_BUTTON) {
if (this.loadAction === AUTOFILL_ID) {
await this.vaultPopupAutofillService.doAutofill(this.cipher);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { BehaviorSubject, of } from "rxjs";

import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
Expand All @@ -19,6 +20,7 @@ import { LoginView } from "@bitwarden/common/vault/models/view/login.view";
import { ToastService } from "@bitwarden/components";
import { PasswordRepromptService } from "@bitwarden/vault";

import { InlineMenuFieldQualificationService } from "../../../../../browser/src/autofill/services/inline-menu-field-qualification.service";
import {
AutoFillOptions,
AutofillService,
Expand Down Expand Up @@ -46,13 +48,21 @@ describe("VaultPopupAutofillService", () => {
const mockPasswordRepromptService = mock<PasswordRepromptService>();
const mockCipherService = mock<CipherService>();
const mockMessagingService = mock<MessagingService>();
const mockInlineMenuFieldQualificationService = mock<InlineMenuFieldQualificationService>();
const mockLogService = mock<LogService>();

const mockUserId = Utils.newGuid() as UserId;
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);

beforeEach(() => {
jest.spyOn(BrowserPopupUtils, "inPopout").mockReturnValue(false);
jest.spyOn(BrowserApi, "getTabFromCurrentWindow").mockResolvedValue(mockCurrentTab);
jest
.spyOn(mockInlineMenuFieldQualificationService, "isFieldForCreditCardForm")
.mockReturnValue(true);
jest
.spyOn(mockInlineMenuFieldQualificationService, "isFieldForIdentityForm")
.mockReturnValue(true);

mockAutofillService.collectPageDetailsFromTab$.mockReturnValue(new BehaviorSubject([]));

Expand All @@ -70,6 +80,14 @@ describe("VaultPopupAutofillService", () => {
provide: AccountService,
useValue: accountService,
},
{
provide: InlineMenuFieldQualificationService,
useValue: mockInlineMenuFieldQualificationService,
},
{
provide: LogService,
useValue: mockLogService,
},
],
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import {
startWith,
Subject,
switchMap,
timeout,
} from "rxjs";

import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
Expand All @@ -23,6 +25,7 @@ import { LoginUriView } from "@bitwarden/common/vault/models/view/login-uri.view
import { ToastService } from "@bitwarden/components";
import { PasswordRepromptService } from "@bitwarden/vault";

import { InlineMenuFieldQualificationService } from "../../../../../browser/src/autofill/services/inline-menu-field-qualification.service";
import {
AutofillService,
PageDetail,
Expand Down Expand Up @@ -72,11 +75,53 @@ export class VaultPopupAutofillService {
if (!tab) {
return of([]);
}
return this.autofillService.collectPageDetailsFromTab$(tab);
return this.autofillService
.collectPageDetailsFromTab$(tab)
.pipe(timeout({ first: 1500, with: () => of([]) }));
}),
shareReplay({ refCount: false, bufferSize: 1 }),
);

nonLoginCipherTypesOnPage$: Observable<{
[CipherType.Card]: boolean;
[CipherType.Identity]: boolean;
}> = this._currentPageDetails$.pipe(
map((pageDetails) => {
let pageHasCardFields = false;
let pageHasIdentityFields = false;

try {
if (!pageDetails) {
throw Error("No page details were provided");
}

for (const details of pageDetails) {
for (const field of details.details.fields) {
if (!pageHasCardFields) {
pageHasCardFields = this.inlineMenuFieldQualificationService.isFieldForCreditCardForm(
field,
details.details,
);
}

if (!pageHasIdentityFields) {
pageHasIdentityFields =
this.inlineMenuFieldQualificationService.isFieldForIdentityForm(
field,
details.details,
);
}
}
}
} catch (error) {
// no-op on failure; do not show extra cipher types
this.logService.warning(error.message);
}

return { [CipherType.Card]: pageHasCardFields, [CipherType.Identity]: pageHasIdentityFields };
}),
);

constructor(
private autofillService: AutofillService,
private i18nService: I18nService,
Expand All @@ -87,6 +132,8 @@ export class VaultPopupAutofillService {
private messagingService: MessagingService,
private route: ActivatedRoute,
private accountService: AccountService,
private logService: LogService,
private inlineMenuFieldQualificationService: InlineMenuFieldQualificationService,
) {
this._currentPageDetails$.subscribe();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault
import { CipherType } from "@bitwarden/common/vault/enums";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";

import { InlineMenuFieldQualificationService } from "../../../../../browser/src/autofill/services/inline-menu-field-qualification.service";
import { BrowserApi } from "../../../platform/browser/browser-api";

import { VaultPopupAutofillService } from "./vault-popup-autofill.service";
Expand All @@ -39,6 +40,7 @@ describe("VaultPopupItemsService", () => {
const collectionService = mock<CollectionService>();
const vaultAutofillServiceMock = mock<VaultPopupAutofillService>();
const syncServiceMock = mock<SyncService>();
const inlineMenuFieldQualificationServiceMock = mock<InlineMenuFieldQualificationService>();

beforeEach(() => {
allCiphers = cipherFactory(10);
Expand Down Expand Up @@ -78,6 +80,11 @@ describe("VaultPopupItemsService", () => {
url: "https://example.com",
} as chrome.tabs.Tab);

vaultAutofillServiceMock.nonLoginCipherTypesOnPage$ = new BehaviorSubject({
[CipherType.Card]: true,
[CipherType.Identity]: true,
});

mockOrg = {
id: "org1",
name: "Organization 1",
Expand Down Expand Up @@ -105,6 +112,10 @@ describe("VaultPopupItemsService", () => {
{ provide: CollectionService, useValue: collectionService },
{ provide: VaultPopupAutofillService, useValue: vaultAutofillServiceMock },
{ provide: SyncService, useValue: syncServiceMock },
{
provide: InlineMenuFieldQualificationService,
useValue: inlineMenuFieldQualificationServiceMock,
},
],
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@ export class VaultPopupItemsService {
private _otherAutoFillTypes$: Observable<CipherType[]> = combineLatest([
this.vaultSettingsService.showCardsCurrentTab$,
this.vaultSettingsService.showIdentitiesCurrentTab$,
this.vaultPopupAutofillService.nonLoginCipherTypesOnPage$,
]).pipe(
map(([showCards, showIdentities]) => {
map(([showCardsSettingEnabled, showIdentitiesSettingEnabled, nonLoginCipherTypesOnPage]) => {
const showCards = showCardsSettingEnabled && nonLoginCipherTypesOnPage[CipherType.Card];
const showIdentities =
showIdentitiesSettingEnabled && nonLoginCipherTypesOnPage[CipherType.Identity];

return [
...(showCards ? [CipherType.Card] : []),
...(showIdentities ? [CipherType.Identity] : []),
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/resources/entitlements.mac.plist
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<!--
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
-->
</dict>
</plist>
2 changes: 2 additions & 0 deletions apps/desktop/resources/entitlements.mas.inherit.plist
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<!--
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
-->
</dict>
</plist>
2 changes: 2 additions & 0 deletions apps/desktop/resources/entitlements.mas.plist
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<!--
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
-->
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
<array>
<string>/Library/Application Support/Mozilla/NativeMessagingHosts/</string>
Expand Down
Loading

0 comments on commit ccd727d

Please sign in to comment.