1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
content / browser / webid / federated_auth_request_impl.h [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_WEBID_FEDERATED_AUTH_REQUEST_IMPL_H_
#define CONTENT_BROWSER_WEBID_FEDERATED_AUTH_REQUEST_IMPL_H_
#include <memory>
#include <string>
#include <vector>
#include "base/containers/queue.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "content/browser/webid/fedcm_metrics.h"
#include "content/browser/webid/federated_provider_fetcher.h"
#include "content/browser/webid/identity_registry.h"
#include "content/browser/webid/idp_network_request_manager.h"
#include "content/common/content_export.h"
#include "content/public/browser/document_service.h"
#include "content/public/browser/federated_identity_api_permission_context_delegate.h"
#include "content/public/browser/federated_identity_modal_dialog_view_delegate.h"
#include "content/public/browser/federated_identity_permission_context_delegate.h"
#include "content/public/browser/identity_request_dialog_controller.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/credentialmanagement/credential_manager.mojom.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"
#include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h"
#include "url/gurl.h"
namespace gfx {
class Image;
}
namespace content {
class FederatedAuthDisconnectRequest;
class FederatedAuthUserInfoRequest;
class FederatedIdentityApiPermissionContextDelegate;
class FederatedIdentityAutoReauthnPermissionContextDelegate;
class FederatedIdentityPermissionContextDelegate;
class RenderFrameHost;
using IdentityProviderDataPtr = scoped_refptr<content::IdentityProviderData>;
using IdentityRequestAccountPtr =
scoped_refptr<content::IdentityRequestAccount>;
using MediationRequirement = ::password_manager::CredentialMediationRequirement;
using RpMode = blink::mojom::RpMode;
using TokenError = IdentityCredentialTokenError;
// FederatedAuthRequestImpl handles mojo connections from the renderer to
// fulfill WebID-related requests.
//
// In practice, it is owned and managed by a RenderFrameHost. It accomplishes
// that via subclassing DocumentService, which observes the lifecycle of a
// RenderFrameHost and manages its own memory.
// Create() creates a self-managed instance of FederatedAuthRequestImpl and
// binds it to the receiver.
class CONTENT_EXPORT FederatedAuthRequestImpl
: public DocumentService<blink::mojom::FederatedAuthRequest>,
public FederatedIdentityPermissionContextDelegate::
IdpSigninStatusObserver,
public content::FederatedIdentityModalDialogViewDelegate {
public:
static constexpr char kWildcardDomainHint[] = "any";
static void Create(RenderFrameHost*,
mojo::PendingReceiver<blink::mojom::FederatedAuthRequest>);
static FederatedAuthRequestImpl& CreateForTesting(
RenderFrameHost&,
FederatedIdentityApiPermissionContextDelegate*,
FederatedIdentityAutoReauthnPermissionContextDelegate*,
FederatedIdentityPermissionContextDelegate*,
IdentityRegistry*,
mojo::PendingReceiver<blink::mojom::FederatedAuthRequest>);
FederatedAuthRequestImpl(const FederatedAuthRequestImpl&) = delete;
FederatedAuthRequestImpl& operator=(const FederatedAuthRequestImpl&) = delete;
~FederatedAuthRequestImpl() override;
// blink::mojom::FederatedAuthRequest:
void RequestToken(std::vector<blink::mojom::IdentityProviderGetParametersPtr>
idp_get_params_ptrs,
MediationRequirement requirement,
RequestTokenCallback) override;
void RequestUserInfo(blink::mojom::IdentityProviderConfigPtr provider,
RequestUserInfoCallback) override;
void CancelTokenRequest() override;
void ResolveTokenRequest(const std::optional<std::string>& account_id,
const std::string& token,
ResolveTokenRequestCallback callback) override;
void SetIdpSigninStatus(const url::Origin& origin,
blink::mojom::IdpSigninStatus status) override;
void RegisterIdP(const ::GURL& idp, RegisterIdPCallback) override;
void UnregisterIdP(const ::GURL& idp, UnregisterIdPCallback) override;
void CloseModalDialogView() override;
void PreventSilentAccess(PreventSilentAccessCallback callback) override;
void Disconnect(blink::mojom::IdentityCredentialDisconnectOptionsPtr options,
DisconnectCallback) override;
// FederatedIdentityPermissionContextDelegate::IdpSigninStatusObserver:
void OnIdpSigninStatusReceived(const url::Origin& idp_config_origin,
bool idp_signin_status) override;
void SetNetworkManagerForTests(
std::unique_ptr<IdpNetworkRequestManager> manager);
void SetDialogControllerForTests(
std::unique_ptr<IdentityRequestDialogController> controller);
// content::FederatedIdentityModalDialogViewDelegate:
void OnClose() override;
bool OnResolve(GURL idp_config_url,
const std::optional<std::string>& account_id,
const std::string& token) override;
// To be called on the FederatedAuthRequest object corresponding to a
// popup opened by ShowModalDialog, specifically for the case when
// ShowModalDialog returned null (particularly Android). In that case,
// we can only set up the IdentityRegistry object when we get a call
// from the popup context.
// Returns false when no identity registry could be created (e.g. this
// is not in a context created by ShowModalDialog).
bool SetupIdentityRegistryFromPopup();
// Rejects the pending request if it has not been resolved naturally yet.
void OnRejectRequest();
// Returns whether the API is enabled or not.
FederatedIdentityApiPermissionContextDelegate::PermissionStatus
GetApiPermissionStatus();
struct IdentityProviderGetInfo {
IdentityProviderGetInfo(blink::mojom::IdentityProviderRequestOptionsPtr,
blink::mojom::RpContext rp_context,
blink::mojom::RpMode rp_mode);
~IdentityProviderGetInfo();
IdentityProviderGetInfo(const IdentityProviderGetInfo&);
IdentityProviderGetInfo& operator=(const IdentityProviderGetInfo& other);
blink::mojom::IdentityProviderRequestOptionsPtr provider;
blink::mojom::RpContext rp_context{blink::mojom::RpContext::kSignIn};
blink::mojom::RpMode rp_mode{blink::mojom::RpMode::kPassive};
};
struct IdentityProviderInfo {
IdentityProviderInfo(const blink::mojom::IdentityProviderRequestOptionsPtr&,
IdpNetworkRequestManager::Endpoints,
IdentityProviderMetadata,
blink::mojom::RpContext rp_context,
blink::mojom::RpMode rp_mode);
~IdentityProviderInfo();
IdentityProviderInfo(const IdentityProviderInfo&);
blink::mojom::IdentityProviderRequestOptionsPtr provider;
IdpNetworkRequestManager::Endpoints endpoints;
IdentityProviderMetadata metadata;
bool has_failing_idp_signin_status{false};
blink::mojom::RpContext rp_context{blink::mojom::RpContext::kSignIn};
blink::mojom::RpMode rp_mode{blink::mojom::RpMode::kPassive};
IdentityProviderDataPtr data;
};
struct IdentityProviderLoginUrlInfo {
std::string login_hint;
std::string domain_hint;
};
// For use by the devtools protocol for browser automation.
IdentityRequestDialogController* GetDialogController() {
return request_dialog_controller_.get();
}
const std::vector<IdentityProviderDataPtr>& GetSortedIdpData() const {
return idp_data_for_display_;
}
const std::vector<IdentityRequestAccountPtr>& GetAccounts() const {
return accounts_;
}
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum DialogType {
kNone = 0,
kSelectAccount = 1,
kAutoReauth = 2,
kConfirmIdpLogin = 3,
kError = 4,
// Popups are not technically dialogs in the strict sense, but because they
// are mutually exclusive with browser UI dialogs we use this enum for them
// as well.
kLoginToIdpPopup = 5,
kContinueOnPopup = 6,
kErrorUrlPopup = 7,
kMaxValue = kErrorUrlPopup
};
DialogType GetDialogType() const { return dialog_type_; }
enum IdentitySelectionType { kExplicit, kAutoPassive, kAutoActive };
bool ShouldNotifyDevtoolsForDialogType(DialogType type);
void AcceptAccountsDialogForDevtools(const GURL& config_url,
const IdentityRequestAccount& account);
void DismissAccountsDialogForDevtools(bool should_embargo);
void AcceptConfirmIdpLoginDialogForDevtools();
void DismissConfirmIdpLoginDialogForDevtools();
bool UseAnotherAccountForDevtools(const IdentityProviderData& provider);
bool HasMoreDetailsButtonForDevtools();
void ClickErrorDialogGotItForDevtools();
void ClickErrorDialogMoreDetailsForDevtools();
void DismissErrorDialogForDevtools();
// Returns a list of fields that we should mediate authorization for. If
// empty, we should not show a permission request dialog.
std::vector<IdentityRequestDialogDisclosureField> GetDisclosureFields(
const blink::mojom::IdentityProviderRequestOptions& provider);
// Whether we can show the continue_on popup (not using mediation: silent,
// etc.)
bool CanShowContinueOnPopup() const;
private:
friend class FederatedAuthRequestImplTest;
struct FetchData {
FetchData();
~FetchData();
// Set of config URLs of IDPs that have yet to be processed.
std::set<GURL> pending_idps;
// Whether accounts endpoint fetch succeeded for at least one IdP.
bool did_succeed_for_at_least_one_idp{false};
// Whether the fetch was triggered by an IdP sign-in status update.
bool for_idp_signin{false};
};
FederatedAuthRequestImpl(
RenderFrameHost&,
FederatedIdentityApiPermissionContextDelegate*,
FederatedIdentityAutoReauthnPermissionContextDelegate*,
FederatedIdentityPermissionContextDelegate*,
IdentityRegistry*,
mojo::PendingReceiver<blink::mojom::FederatedAuthRequest>);
bool HasPendingRequest() const;
// Fetch well-known, config, accounts and client metadata endpoints for
// passed-in IdPs. Uses parameters from `token_request_get_infos_`.
// `for_idp_signin` indicates whether the fetch is as a result of an IdP
// sign-in status update.
void FetchEndpointsForIdps(const std::set<GURL>& idp_config_urls,
bool for_idp_signin);
void OnAllConfigAndWellKnownFetched(
std::vector<FederatedProviderFetcher::FetchResult> fetch_results);
void OnClientMetadataResponseReceived(
std::unique_ptr<IdentityProviderInfo> idp_info,
std::vector<IdentityRequestAccountPtr>&& accounts,
IdpNetworkRequestManager::FetchStatus status,
IdpNetworkRequestManager::ClientMetadata client_metadata);
// Called when all of the data needed to display the FedCM prompt has been
// fetched for `idp_info`.
void OnFetchDataForIdpSucceeded(
std::unique_ptr<IdentityProviderInfo> idp_info,
std::vector<IdentityRequestAccountPtr>&& accounts,
const IdpNetworkRequestManager::ClientMetadata& client_metadata);
// Called when there is an error in fetching information to show the prompt
// for a given IDP - `idp_info`, but we do not need to show failure UI for the
// IDP.
void OnFetchDataForIdpFailed(
std::unique_ptr<IdentityProviderInfo> idp_info,
blink::mojom::FederatedAuthRequestResult result,
std::optional<content::FedCmRequestIdTokenStatus> token_status,
bool should_delay_callback);
// Called when there is an error fetching information to show the prompt for a
// given IDP, and because of the mismatch this IDP must be present in the
// dialog we show to the user.
void OnIdpMismatch(std::unique_ptr<IdentityProviderInfo> idp_info);
std::vector<blink::mojom::IdentityProviderRequestOptionsPtr>
MaybeAddRegisteredProviders(
std::vector<blink::mojom::IdentityProviderRequestOptionsPtr>& providers);
void MaybeShowAccountsDialog();
void ShowModalDialog(DialogType dialog_type,
const GURL& idp_config_url,
const GURL& url_to_show);
void ShowErrorDialog(const GURL& idp_config_url,
IdpNetworkRequestManager::FetchStatus status,
std::optional<TokenError> error);
// Called when we should show a failure dialog in the case where a single IDP
// account fetch resulted in a mismatch with its login status.
void ShowSingleIdpFailureDialog();
void OnAccountsDisplayed();
// Updates the IdpSigninStatus in case of accounts fetch failure and shows a
// failure UI if applicable.
void HandleAccountsFetchFailure(
std::unique_ptr<IdentityProviderInfo> idp_info,
std::optional<bool> old_idp_signin_status,
blink::mojom::FederatedAuthRequestResult result,
std::optional<content::FedCmRequestIdTokenStatus> token_status);
void OnAccountsResponseReceived(
std::unique_ptr<IdentityProviderInfo> idp_info,
IdpNetworkRequestManager::FetchStatus status,
std::vector<IdentityRequestAccountPtr> accounts);
// Fetches the account pictures for |accounts| and calls
// OnFetchDataForIdpSucceeded when done.
void FetchAccountPictures(
std::unique_ptr<IdentityProviderInfo> idp_info,
const std::vector<IdentityRequestAccountPtr>& accounts,
const IdpNetworkRequestManager::ClientMetadata& client_metadata);
void OnAccountPictureReceived(base::RepeatingClosure cb,
GURL url,
const gfx::Image& image);
void OnAllAccountPicturesReceived(
std::unique_ptr<IdentityProviderInfo> idp_info,
std::vector<IdentityRequestAccountPtr>&& accounts,
const IdpNetworkRequestManager::ClientMetadata& client_metadata);
void OnAccountSelected(const GURL& idp_config_url,
const std::string& account_id,
bool is_sign_in);
void OnDismissFailureDialog(
IdentityRequestDialogController::DismissReason dismiss_reason);
void OnDismissErrorDialog(
const GURL& idp_config_url,
IdpNetworkRequestManager::FetchStatus status,
std::optional<TokenError> token_error,
IdentityRequestDialogController::DismissReason dismiss_reason);
void OnDialogDismissed(
IdentityRequestDialogController::DismissReason dismiss_reason);
void CompleteTokenRequest(const GURL& idp_config_url,
IdpNetworkRequestManager::FetchStatus status,
std::optional<std::string> token,
std::optional<TokenError> token_error,
bool should_delay_callback);
void OnTokenResponseReceived(
blink::mojom::IdentityProviderRequestOptionsPtr idp,
IdpNetworkRequestManager::FetchStatus status,
IdpNetworkRequestManager::TokenResult result);
void OnContinueOnResponseReceived(
blink::mojom::IdentityProviderRequestOptionsPtr idp,
IdpNetworkRequestManager::FetchStatus status,
const GURL& url);
// Called after we get at token (either from the ID assertion endpoint or
// from IdentityProvider.resolve) to update our various permissions.
void MarkUserAsSignedIn(const GURL& idp_config_url,
const std::string& account_id);
void CompleteRequestWithError(
blink::mojom::FederatedAuthRequestResult result,
std::optional<content::FedCmRequestIdTokenStatus> token_status,
std::optional<TokenError> token_error,
bool should_delay_callback);
// Completes request. Displays a dialog if there is an error and the error is
// during a fetch triggered by an IdP sign-in status change.
void CompleteRequest(
blink::mojom::FederatedAuthRequestResult result,
std::optional<content::FedCmRequestIdTokenStatus> token_status,
std::optional<TokenError> token_error,
const std::optional<GURL>& selected_idp_config_url,
const std::string& token,
bool should_delay_callback);
void CompleteUserInfoRequest(
FederatedAuthUserInfoRequest* request,
RequestUserInfoCallback callback,
blink::mojom::RequestUserInfoStatus status,
std::optional<std::vector<blink::mojom::IdentityUserInfoPtr>> user_info);
// Notifies metrics endpoint that either the user did not select the IDP in
// the prompt or that there was an error in fetching data for the IDP.
void SendFailedTokenRequestMetrics(
const GURL& metrics_endpoint,
blink::mojom::FederatedAuthRequestResult result);
void SendSuccessfulTokenRequestMetrics(const GURL& idp_config_url);
void CleanUp();
std::unique_ptr<IdpNetworkRequestManager> CreateNetworkManager();
std::unique_ptr<IdentityRequestDialogController> CreateDialogController();
// Creates an inspector issue related to a federated authentication request to
// the Issues panel in DevTools.
void AddDevToolsIssue(blink::mojom::FederatedAuthRequestResult result);
// Adds a console error message related to a federated authentication request
// issue. The Issues panel is preferred, but for now we also surface console
// error messages since it is much simpler to add.
void AddConsoleErrorMessage(blink::mojom::FederatedAuthRequestResult result);
void MaybeAddResponseCodeToConsole(const char* fetch_description,
int response_code);
// Computes the login state of accounts. It uses the IDP-provided signal, if
// it had been populated. Otherwise, it uses the browser knowledge on which
// accounts are returning and which are not.
void ComputeLoginStates(const GURL& idp_config_url,
std::vector<IdentityRequestAccountPtr>& accounts);
url::Origin GetEmbeddingOrigin() const;
// Returns true and the `IdentityProviderData` + `IdentityRequestAccount` for
// the only returning account. Returns false if there are multiple returning
// accounts or no returning account.
bool GetAccountForAutoReauthn(IdentityProviderDataPtr* out_idp_data,
IdentityRequestAccountPtr* out_account);
// Check if auto re-authn is available so we can skip fetching accounts if the
// auto re-authn flow is guaranteed to fail.
bool ShouldFailBeforeFetchingAccounts(const GURL& config_url);
// Check if the site requires user mediation due to a previous
// `preventSilentAccess` call.
bool RequiresUserMediation();
void SetRequiresUserMediation(bool requires_user_mediation,
base::OnceClosure callback);
// Trigger a dialog to prompt the user to login to the IdP. `can_append_hints`
// is true if the caller allows the login url to be augmented with login and
// domain hints.
void LoginToIdP(bool can_append_hints,
const GURL& idp_config_url,
GURL login_url);
void MaybeShowActiveModeModalDialog(const GURL& idp_config_url,
const GURL& idp_login_url);
void CompleteDisconnectRequest(DisconnectCallback callback,
blink::mojom::DisconnectStatus status);
void RecordErrorMetrics(
blink::mojom::IdentityProviderRequestOptionsPtr idp,
IdpNetworkRequestManager::FedCmTokenResponseType token_response_type,
std::optional<IdpNetworkRequestManager::FedCmErrorDialogType>
error_dialog_type,
std::optional<IdpNetworkRequestManager::FedCmErrorUrlType>
error_url_type);
void OnRegisterIdPPermissionResponse(RegisterIdPCallback callback,
const GURL& idp,
bool accepted);
void MaybeCreateFedCmMetrics();
bool IsNewlyLoggedIn(const IdentityRequestAccount& account);
// Returns whether there are accounts remaining after applying the account
// label filter.
bool FilterAccountsWithLabel(
const std::string& label,
std::vector<IdentityRequestAccountPtr>& accounts);
// Returns whether there are accounts remaining after applying the login hint
// filter.
bool FilterAccountsWithLoginHint(
const std::string& login_hint,
std::vector<IdentityRequestAccountPtr>& accounts);
// Returns whether there are accounts remaining after applying the domain hint
// filter.
bool FilterAccountsWithDomainHint(
const std::string& domain_hint,
std::vector<IdentityRequestAccountPtr>& accounts);
RpMode GetRpMode() const { return rp_mode_; }
std::unique_ptr<IdpNetworkRequestManager> network_manager_;
std::unique_ptr<IdentityRequestDialogController> request_dialog_controller_;
// Replacements for testing.
std::unique_ptr<IdpNetworkRequestManager> mock_network_manager_;
std::unique_ptr<IdentityRequestDialogController> mock_dialog_controller_;
// Helper that records FedCM UMA and UKM metrics. Initialized in the
// RequestToken() method, so all metrics must be recorded after that.
std::unique_ptr<FedCmMetrics> fedcm_metrics_;
// Populated in OnAllConfigAndWellKnownFetched().
base::flat_map<GURL, GURL> metrics_endpoints_;
// Populated by OnFetchDataForIdpSucceeded() and OnIdpMismatch().
base::flat_map<GURL, std::unique_ptr<IdentityProviderInfo>> idp_infos_;
// Populated by MaybeShowAccountsDialog().
std::vector<IdentityProviderDataPtr> idp_data_for_display_;
// Populated by OnFetchDataForIdpSucceeded(). Contains the accounts of each
// IDP. Used to later set accounts_ in the order in which the IDPs are
// requested.
base::flat_map<GURL, std::vector<IdentityRequestAccountPtr>> idp_accounts_;
// The accounts to be displayed by the UI.
std::vector<IdentityRequestAccountPtr> accounts_;
// The newly logged in accounts, to be prioritized by the UI. Subset of
// `accounts_`.
std::vector<IdentityRequestAccountPtr> new_accounts_;
// Contains the set of account IDs of an IDP before a login URL is displayed
// to the user. Used to compute the account ID of the account that the user
// logs in to. Populated by LoginToIdP().
base::flat_set<std::string> account_ids_before_login_;
// Maps the login URL to the info that may be added as query parameters to
// that URL. Populated by OnAllConfigAndWellKnownFetched().
base::flat_map<GURL, IdentityProviderLoginUrlInfo> idp_login_infos_;
// The downloaded image data.
std::map<GURL, gfx::Image> downloaded_images_;
raw_ptr<FederatedIdentityApiPermissionContextDelegate>
api_permission_delegate_ = nullptr;
raw_ptr<FederatedIdentityAutoReauthnPermissionContextDelegate>
auto_reauthn_permission_delegate_ = nullptr;
raw_ptr<FederatedIdentityPermissionContextDelegate> permission_delegate_ =
nullptr;
raw_ptr<IdentityRegistry> identity_registry_ = nullptr;
// The account that was selected by the user. This is only applicable to the
// mediation flow.
std::string account_id_;
base::TimeTicks start_time_;
base::TimeTicks well_known_and_config_fetched_time_;
base::TimeTicks accounts_fetched_time_;
base::TimeTicks client_metadata_fetched_time_;
base::TimeTicks ready_to_display_accounts_dialog_time_;
base::TimeTicks accounts_dialog_display_time_;
base::TimeTicks select_account_time_;
base::TimeTicks id_assertion_response_time_;
bool errors_logged_to_console_{false};
// This gets set at the beginning of a request. It indicates whether we
// should bypass the delay to notify the renderer, for use in automated
// tests when the delay is irrelevant to the test but slows it down
// unncessarily.
bool should_complete_request_immediately_{false};
// While there could be both token request and user info request when a user
// visits a site, it's worth noting that they must be from different render
// frames. e.g. one top frame rp.example and one iframe idp.example.
// Therefore,
// 1. if one of the requests exists, the other one shouldn't. e.g. if the
// iframe requests user info, it cannot request token at the same time.
// 2. the user info request should not set "HasPendingRequest" on the page
// (multiple per page). It's OK to have multiple concurrent user info requests
// since there's no browser UI involved. e.g. rp.example embeds
// iframe1.example and iframe2.example. Both iframes can request user info
// simultaneously.
RequestTokenCallback auth_request_token_callback_;
std::unique_ptr<FederatedProviderFetcher> provider_fetcher_;
// Set of pending user info requests.
base::flat_set<std::unique_ptr<FederatedAuthUserInfoRequest>>
user_info_requests_;
// Pending disconnect request.
std::unique_ptr<FederatedAuthDisconnectRequest> disconnect_request_;
// TODO(crbug.com/40238075): Refactor these member variables introduced
// through the multi IDP prototype implementation to make them less confusing.
// Parameters passed to RequestToken().
base::flat_map<GURL, IdentityProviderGetInfo> token_request_get_infos_;
// Data related to in-progress FetchEndpointsForIdps() fetch.
FetchData fetch_data_;
// List of config URLs of IDPs in the same order as the providers specified in
// the navigator.credentials.get call.
std::vector<GURL> idp_order_;
// If dialog_type_ is kConfirmIdpLogin, this is the login URL for the IDP. If
// LoginToIdp() is called, this is the login URL for the IDP.
GURL login_url_;
// If dialog_type_ is kError or a popup is open, this is the config URL for
// the IDP.
GURL config_url_;
// If dialog_type_ is kError, this is the fetch status of the token request.
IdpNetworkRequestManager::FetchStatus token_request_status_;
// If dialog_type_ is kError, this is the token error.
std::optional<TokenError> token_error_;
DialogType dialog_type_ = kNone;
MediationRequirement mediation_requirement_;
IdentitySelectionType identity_selection_type_ = kExplicit;
RpMode rp_mode_{RpMode::kPassive};
// Time when the accounts dialog is last shown for metrics purposes.
std::optional<base::TimeTicks> accounts_dialog_shown_time_;
// Time when the mismatch dialog is last shown for metrics purposes.
std::optional<base::TimeTicks> mismatch_dialog_shown_time_;
// Whether a mismatch dialog has been shown for the current request.
bool has_shown_mismatch_{false};
// Type of error URL for metrics and devtools issue purposes.
std::optional<IdpNetworkRequestManager::FedCmErrorUrlType> error_url_type_;
// Number of navigator.credentials.get() requests made for metrics purposes.
// Requests made when there is a pending FedCM request or for the purpose of
// Wallets or multi-IDP are not counted.
int num_requests_{0};
// The active flow requires user activation to be kicked off. We'd also need
// this information along the way. e.g. showing pop-up window when accounts
// fetch is failed. However, the function `HasTransientUserActivation` may
// return false at that time because the network requests may be very slow
// such that the previous user gesture is expired. Therefore we store the
// information to use it during the entire the active flow.
bool had_transient_user_activation_{false};
base::WeakPtrFactory<FederatedAuthRequestImpl> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WEBID_FEDERATED_AUTH_REQUEST_IMPL_H_