File: third_party_credential_manager_impl.cc

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (151 lines) | stat: -rw-r--r-- 5,793 bytes parent folder | download | duplicates (3)
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
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/credential_management/android/third_party_credential_manager_impl.h"

#include "base/android/jni_callback.h"
#include "base/check_deref.h"
#include "base/functional/bind.h"
#include "base/notimplemented.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/ssl_status.h"

namespace credential_management {

ThirdPartyCredentialManagerImpl::ThirdPartyCredentialManagerImpl(
    content::WebContents* web_contents)
    : bridge_(std::make_unique<ThirdPartyCredentialManagerBridge>()),
      web_contents_(CHECK_DEREF(web_contents)) {}

ThirdPartyCredentialManagerImpl::ThirdPartyCredentialManagerImpl(
    base::PassKey<class ThirdPartyCredentialManagerImplTest>,
    content::WebContents* web_contents,
    std::unique_ptr<CredentialManagerBridge> bridge)
    : bridge_(std::move(bridge)), web_contents_(CHECK_DEREF(web_contents)) {}

ThirdPartyCredentialManagerImpl::~ThirdPartyCredentialManagerImpl() = default;

void ThirdPartyCredentialManagerImpl::Store(
    const password_manager::CredentialInfo& credential,
    StoreCallback callback) {
  // Don't store empty credentials.
  if (credential.type ==
      password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY) {
    return;
  }

  std::u16string username = credential.id.value_or(u"");
  std::u16string password = credential.password.value_or(u"");
  bridge_->Store(username, password,
                 web_contents_->GetPrimaryMainFrame()
                     ->GetLastCommittedOrigin()
                     .Serialize(),
                 std::move(callback));
}

void ThirdPartyCredentialManagerImpl::PreventSilentAccess(
    PreventSilentAccessCallback callback) {
  // Send acknowledge response back.
  // We're currently preventing silent access for every get request by default
  // in 3rd party mode so there is nothing more to do here for now.
  std::move(callback).Run();
}

// This method decides if credential picker should be shown.

// Credential mediation can be silent, optional, conditional or
// required.

// Silent mediation should not show a credential picker even if there
// are multiple credentials available and return null.
// Silent mediation can't be implemented here, because the Android API
// doesn't support it. We'd have to know the amount of available credentials
// already before calling get.

// By default, the GetCredentialRequest will have optional
// mediation: if there's more than one matching credential, the system
// will show the credential picker UI to the user.

// Required mediation will show the credential picker, no matter the amount
// of choices.

// Conditional mediation allows the user to pick a credential from the
// picker or avoid selecting a credential without any user-visible error
// condition. That type of mediotion is also not supported in the Android
// API.

bool ShouldAllowAutoSelect(
    password_manager::CredentialMediationRequirement mediation) {
  switch (mediation) {
    case password_manager::CredentialMediationRequirement::kOptional:
      return true;
    case password_manager::CredentialMediationRequirement::kRequired:
      return false;
    case password_manager::CredentialMediationRequirement::kSilent:
    case password_manager::CredentialMediationRequirement::kConditional:
      NOTIMPLEMENTED();
  }
  return false;
}

net::CertStatus ThirdPartyCredentialManagerImpl::GetMainFrameCertStatus()
    const {
  content::NavigationEntry* entry =
      web_contents_->GetController().GetLastCommittedEntry();
  if (!entry) {
    return 0;
  }
  return entry->GetSSL().cert_status;
}

void ThirdPartyCredentialManagerImpl::Get(
    password_manager::CredentialMediationRequirement mediation,
    bool include_passwords,
    const std::vector<GURL>& federations,
    GetCallback callback) {
  // Return an empty credential if the current page has SSL errors.
  if (net::IsCertStatusError(GetMainFrameCertStatus())) {
    std::move(callback).Run(password_manager::CredentialManagerError::SUCCESS,
                            password_manager::CredentialInfo());
    return;
  }

  // Return an empty credential for incognito mode.
  if (IsOffTheRecord()) {
    // Callback with empty credential info.
    std::move(callback).Run(password_manager::CredentialManagerError::SUCCESS,
                            password_manager::CredentialInfo());
    return;
  }

  // Silent mediation is not supported because the list of origins that prevent
  // silent access can't be persisted.
  // Conditional mediation is only for passkeys, not for passwords that are
  // currently the only supported credential type.
  // Return an empty credential in these cases.
  if (mediation == password_manager::CredentialMediationRequirement::kSilent ||
      mediation ==
          password_manager::CredentialMediationRequirement::kConditional) {
    std::move(callback).Run(password_manager::CredentialManagerError::SUCCESS,
                            password_manager::CredentialInfo());
    return;
  }

  bridge_->Get(ShouldAllowAutoSelect(mediation), include_passwords, federations,
               web_contents_->GetPrimaryMainFrame()
                   ->GetLastCommittedOrigin()
                   .Serialize(),
               std::move(callback));
}

void ThirdPartyCredentialManagerImpl::ResetAfterDisconnecting() {
  // There is currently nothing to do upon disconnecting for this implementation
  // of CredentialManagerInterface.
}

bool ThirdPartyCredentialManagerImpl::IsOffTheRecord() const {
  return web_contents_->GetBrowserContext()->IsOffTheRecord();
}

}  // namespace credential_management