Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
570 changes: 431 additions & 139 deletions packages/fxa-settings/src/components/App/index.tsx

Large diffs are not rendered by default.

27 changes: 23 additions & 4 deletions packages/fxa-settings/src/lib/hooks/useFxAStatus/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ describe('useFxAStatus', () => {
});
});

it('returns supportsKeysOptionalLogin: true when Relay or SmartWindow service', async () => {
it('reports browserSupportsKeysOptional: true when the browser advertises keys_optional', async () => {
const integration = {
type: IntegrationType.OAuthNative,
isSync: () => false,
Expand All @@ -131,10 +131,13 @@ describe('useFxAStatus', () => {
);

await waitForNextUpdate();
expect(result.current.supportsKeysOptionalLogin).toBe(true);
expect(result.current.browserSupportsKeysOptional).toBe(true);
});

it('returns supportsKeysOptionalLogin: false for Sync', async () => {
// The hook reports the raw browser capability regardless of integration
// type; whether a Sync login may use it is decided on the integration
// model (see Integration.supportsKeylessLogin), not here.
it('reports browserSupportsKeysOptional: true for Sync when the browser advertises it', async () => {
const integration = {
type: IntegrationType.OAuthNative,
isSync: () => true,
Expand All @@ -144,7 +147,23 @@ describe('useFxAStatus', () => {
useFxAStatus(integration)
);
await waitForNextUpdate();
expect(result.current.supportsKeysOptionalLogin).toBe(false);
expect(result.current.browserSupportsKeysOptional).toBe(true);
});

it('reports browserSupportsKeysOptional: false when the browser omits keys_optional', async () => {
(firefox.fxaStatus as jest.Mock).mockResolvedValue({
capabilities: { engines: [] },
});
const integration = {
type: IntegrationType.OAuthNative,
isSync: () => false,
isFirefoxNonSync: () => true,
};
const { result, waitForNextUpdate } = renderHook(() =>
useFxAStatus(integration)
);
await waitForNextUpdate();
expect(result.current.browserSupportsKeysOptional).toBe(false);
});
});
});
Expand Down
22 changes: 8 additions & 14 deletions packages/fxa-settings/src/lib/hooks/useFxAStatus/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ export function useFxAStatus(integration: FxAStatusIntegration) {
typeof syncEngineConfigs | undefined
>();
const [declinedSyncEngines, setDeclinedSyncEngines] = useState<string[]>([]);
const [supportsKeysOptionalLogin, setSupportsKeysOptionalLogin] =
useState<boolean>(false);
// Raw browser `keys_optional` capability. Per-integration policy (whether a
// given login may skip keys) lives on the Integration model, not here.
const [browserSupportsKeysOptional, setBrowserSupportsKeysOptional] =
useState(false);
const [supportsCanLinkAccountUid, setSupportsCanLinkAccountUid] = useState<
boolean | undefined
>(undefined);
Expand Down Expand Up @@ -77,17 +79,9 @@ export function useFxAStatus(integration: FxAStatusIntegration) {
setWebChannelEngines(capabilities.engines);
}
}
// Check if third party auth (passwordless) log in to the browser is supported,
// currently only Firefox desktop 147+ as of Q1 2026
if (
capabilities.keys_optional &&
isOAuthNative &&
integration.isFirefoxNonSync()
) {
setSupportsKeysOptionalLogin(true);
} else {
setSupportsKeysOptionalLogin(false);
}
// Report the raw browser `keys_optional` capability (Fx desktop 147+ as
// of Q1 2026). Consumers decide per-integration whether it applies.
setBrowserSupportsKeysOptional(!!capabilities.keys_optional);
if (capabilities.can_link_account_uid) {
setSupportsCanLinkAccountUid(true);
} else {
Expand Down Expand Up @@ -154,7 +148,7 @@ export function useFxAStatus(integration: FxAStatusIntegration) {
offeredSyncEngineConfigs,
declinedSyncEngines,
selectedEnginesForGlean,
supportsKeysOptionalLogin,
browserSupportsKeysOptional,
supportsCanLinkAccountUid,
};
}
Expand Down
6 changes: 3 additions & 3 deletions packages/fxa-settings/src/lib/hooks/useFxAStatus/mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import type { UseFxAStatusResult } from '.';

export function mockUseFxAStatus({
offeredSyncEnginesOverride,
supportsKeysOptionalLogin = false,
browserSupportsKeysOptional = false,
supportsCanLinkAccountUid,
}: {
offeredSyncEnginesOverride?: ReturnType<typeof getSyncEngineIds>;
supportsKeysOptionalLogin?: boolean;
browserSupportsKeysOptional?: boolean;
supportsCanLinkAccountUid?: boolean | undefined;
} = {}) {
const offeredSyncEngineConfigs = syncEngineConfigs;
Expand All @@ -35,7 +35,7 @@ export function mockUseFxAStatus({
offeredSyncEngineConfigs,
declinedSyncEngines,
selectedEnginesForGlean,
supportsKeysOptionalLogin,
browserSupportsKeysOptional,
supportsCanLinkAccountUid,
} satisfies UseFxAStatusResult;
}
Expand Down
Loading
Loading