1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/password_manager/content/browser/credential_manager_dispatcher.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/autofill/core/common/password_form.h"
12 #include "components/password_manager/content/browser/content_password_manager_driver.h"
13 #include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
14 #include "components/password_manager/content/common/credential_manager_messages.h"
15 #include "components/password_manager/core/browser/password_manager_client.h"
16 #include "components/password_manager/core/browser/password_store.h"
17 #include "components/password_manager/core/common/credential_manager_types.h"
18 #include "components/password_manager/core/common/password_manager_pref_names.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/web_contents.h"
21 #include "ipc/ipc_message_macros.h"
23 namespace password_manager
{
25 // CredentialManagerDispatcher -------------------------------------------------
27 CredentialManagerDispatcher::CredentialManagerDispatcher(
28 content::WebContents
* web_contents
,
29 PasswordManagerClient
* client
)
30 : WebContentsObserver(web_contents
), client_(client
) {
32 auto_signin_enabled_
.Init(prefs::kPasswordManagerAutoSignin
,
36 CredentialManagerDispatcher::~CredentialManagerDispatcher() {
39 bool CredentialManagerDispatcher::OnMessageReceived(
40 const IPC::Message
& message
) {
42 IPC_BEGIN_MESSAGE_MAP(CredentialManagerDispatcher
, message
)
43 IPC_MESSAGE_HANDLER(CredentialManagerHostMsg_Store
, OnStore
);
44 IPC_MESSAGE_HANDLER(CredentialManagerHostMsg_RequireUserMediation
,
45 OnRequireUserMediation
);
46 IPC_MESSAGE_HANDLER(CredentialManagerHostMsg_RequestCredential
,
48 IPC_MESSAGE_UNHANDLED(handled
= false)
53 void CredentialManagerDispatcher::OnStore(
55 const password_manager::CredentialInfo
& credential
) {
56 DCHECK(credential
.type
!= CredentialType::CREDENTIAL_TYPE_EMPTY
);
58 web_contents()->GetRenderViewHost()->Send(
59 new CredentialManagerMsg_AcknowledgeStore(
60 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id
));
62 if (!client_
->IsSavingEnabledForCurrentPage())
65 scoped_ptr
<autofill::PasswordForm
> form(CreatePasswordFormFromCredentialInfo(
66 credential
, web_contents()->GetLastCommittedURL().GetOrigin()));
67 form
->skip_zero_click
= !IsZeroClickAllowed();
69 // TODO(mkwst): This is a stub; we should be checking the PasswordStore to
70 // determine whether or not the credential exists, and calling UpdateLogin
72 form_manager_
.reset(new CredentialManagerPasswordFormManager(
73 client_
, GetDriver(), *form
, this));
76 void CredentialManagerDispatcher::OnProvisionalSaveComplete() {
77 DCHECK(form_manager_
);
78 if (client_
->IsSavingEnabledForCurrentPage()) {
79 client_
->PromptUserToSaveOrUpdatePassword(
80 form_manager_
.Pass(), CredentialSourceType::CREDENTIAL_SOURCE_API
,
85 void CredentialManagerDispatcher::OnRequireUserMediation(int request_id
) {
88 PasswordStore
* store
= GetPasswordStore();
90 if (!pending_require_user_mediation_
) {
91 pending_require_user_mediation_
.reset(
92 new CredentialManagerPendingRequireUserMediationTask(
93 this, web_contents()->GetLastCommittedURL().GetOrigin()));
95 // This will result in a callback to
96 // CredentialManagerPendingRequireUserMediationTask::OnGetPasswordStoreResults().
97 store
->GetAutofillableLogins(pending_require_user_mediation_
.get());
99 pending_require_user_mediation_
->AddOrigin(
100 web_contents()->GetLastCommittedURL().GetOrigin());
104 web_contents()->GetRenderViewHost()->Send(
105 new CredentialManagerMsg_AcknowledgeRequireUserMediation(
106 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id
));
109 void CredentialManagerDispatcher::OnRequestCredential(
111 bool zero_click_only
,
112 const std::vector
<GURL
>& federations
) {
114 PasswordStore
* store
= GetPasswordStore();
115 if (pending_request_
|| !store
) {
116 web_contents()->GetRenderViewHost()->Send(
117 new CredentialManagerMsg_RejectCredentialRequest(
118 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id
,
120 ? blink::WebCredentialManagerError::ErrorTypePendingRequest
121 : blink::WebCredentialManagerError::
122 ErrorTypePasswordStoreUnavailable
));
126 if (zero_click_only
&& !IsZeroClickAllowed()) {
127 web_contents()->GetRenderViewHost()->Send(
128 new CredentialManagerMsg_SendCredential(
129 web_contents()->GetRenderViewHost()->GetRoutingID(), request_id
,
134 pending_request_
.reset(new CredentialManagerPendingRequestTask(
135 this, request_id
, zero_click_only
,
136 web_contents()->GetLastCommittedURL().GetOrigin(), federations
));
138 // This will result in a callback to
139 // PendingRequestTask::OnGetPasswordStoreResults().
140 store
->GetAutofillableLogins(pending_request_
.get());
143 PasswordStore
* CredentialManagerDispatcher::GetPasswordStore() {
144 return client_
? client_
->GetPasswordStore() : nullptr;
147 bool CredentialManagerDispatcher::IsZeroClickAllowed() const {
148 return *auto_signin_enabled_
&& !client_
->IsOffTheRecord();
151 GURL
CredentialManagerDispatcher::GetOrigin() const {
152 return web_contents()->GetLastCommittedURL().GetOrigin();
155 base::WeakPtr
<PasswordManagerDriver
> CredentialManagerDispatcher::GetDriver() {
156 ContentPasswordManagerDriverFactory
* driver_factory
=
157 ContentPasswordManagerDriverFactory::FromWebContents(web_contents());
158 DCHECK(driver_factory
);
159 PasswordManagerDriver
* driver
=
160 driver_factory
->GetDriverForFrame(web_contents()->GetMainFrame());
161 return driver
->AsWeakPtr();
164 void CredentialManagerDispatcher::SendCredential(int request_id
,
165 const CredentialInfo
& info
) {
166 DCHECK(pending_request_
);
167 DCHECK_EQ(pending_request_
->id(), request_id
);
169 if (PasswordStore
* store
= GetPasswordStore()) {
170 if (info
.type
!= CredentialType::CREDENTIAL_TYPE_EMPTY
&&
171 IsZeroClickAllowed()) {
172 scoped_ptr
<autofill::PasswordForm
> form(
173 CreatePasswordFormFromCredentialInfo(info
,
174 pending_request_
->origin()));
175 form
->skip_zero_click
= false;
176 store
->UpdateLogin(*form
);
180 web_contents()->GetRenderViewHost()->Send(
181 new CredentialManagerMsg_SendCredential(
182 web_contents()->GetRenderViewHost()->GetRoutingID(),
183 pending_request_
->id(), info
));
184 pending_request_
.reset();
187 PasswordManagerClient
* CredentialManagerDispatcher::client() const {
191 void CredentialManagerDispatcher::DoneRequiringUserMediation() {
192 DCHECK(pending_require_user_mediation_
);
193 pending_require_user_mediation_
.reset();
196 } // namespace password_manager