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 "chrome/browser/password_manager/chrome_password_manager_client.h"
7 #include "base/bind_helpers.h"
8 #include "base/command_line.h"
9 #include "base/memory/singleton.h"
10 #include "base/metrics/histogram.h"
11 #include "chrome/browser/password_manager/password_manager_util.h"
12 #include "chrome/browser/password_manager/password_store_factory.h"
13 #include "chrome/browser/password_manager/save_password_infobar_delegate.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/sync/profile_sync_service.h"
16 #include "chrome/browser/sync/profile_sync_service_factory.h"
17 #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
18 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/chrome_version_info.h"
21 #include "components/autofill/content/common/autofill_messages.h"
22 #include "components/autofill/core/browser/password_generator.h"
23 #include "components/autofill/core/common/password_form.h"
24 #include "components/password_manager/core/browser/password_form_manager.h"
25 #include "components/password_manager/core/browser/password_manager.h"
26 #include "components/password_manager/core/browser/password_manager_logger.h"
27 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
28 #include "components/password_manager/core/common/password_manager_switches.h"
29 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/web_contents.h"
32 #if defined(OS_ANDROID)
33 #include "chrome/browser/android/password_authentication_manager.h"
38 bool IsTheHotNewBubbleUIEnabled() {
39 std::string group_name =
40 base::FieldTrialList::FindFullName("PasswordManagerUI");
42 CommandLine* command_line = CommandLine::ForCurrentProcess();
43 if (command_line->HasSwitch(switches::kDisableSavePasswordBubble))
46 if (command_line->HasSwitch(switches::kEnableSavePasswordBubble))
49 return group_name == "Bubble";
54 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromePasswordManagerClient);
58 ChromePasswordManagerClient::CreateForWebContentsWithAutofillManagerDelegate(
59 content::WebContents* contents,
60 autofill::AutofillManagerDelegate* delegate) {
61 if (FromWebContents(contents))
64 contents->SetUserData(UserDataKey(),
65 new ChromePasswordManagerClient(contents, delegate));
68 ChromePasswordManagerClient::ChromePasswordManagerClient(
69 content::WebContents* web_contents,
70 autofill::AutofillManagerDelegate* autofill_manager_delegate)
71 : content::WebContentsObserver(web_contents),
72 driver_(web_contents, this, autofill_manager_delegate),
77 ChromePasswordManagerClient::~ChromePasswordManagerClient() {}
79 bool ChromePasswordManagerClient::IsAutomaticPasswordSavingEnabled() const {
80 return CommandLine::ForCurrentProcess()->HasSwitch(
81 password_manager::switches::kEnableAutomaticPasswordSaving) &&
82 chrome::VersionInfo::GetChannel() ==
83 chrome::VersionInfo::CHANNEL_UNKNOWN;
86 void ChromePasswordManagerClient::PromptUserToSavePassword(
87 password_manager::PasswordFormManager* form_to_save) {
88 if (IsTheHotNewBubbleUIEnabled()) {
89 ManagePasswordsUIController* manage_passwords_ui_controller =
90 ManagePasswordsUIController::FromWebContents(web_contents());
91 if (manage_passwords_ui_controller) {
92 manage_passwords_ui_controller->OnPasswordSubmitted(form_to_save);
97 std::string uma_histogram_suffix(
98 password_manager::metrics_util::GroupIdToString(
99 password_manager::metrics_util::MonitoredDomainGroupId(
100 form_to_save->realm(), GetPrefs())));
101 SavePasswordInfoBarDelegate::Create(
102 web_contents(), form_to_save, uma_histogram_suffix);
106 void ChromePasswordManagerClient::PasswordWasAutofilled(
107 const autofill::PasswordFormMap& best_matches) const {
108 ManagePasswordsUIController* manage_passwords_ui_controller =
109 ManagePasswordsUIController::FromWebContents(web_contents());
110 if (manage_passwords_ui_controller && IsTheHotNewBubbleUIEnabled())
111 manage_passwords_ui_controller->OnPasswordAutofilled(best_matches);
114 void ChromePasswordManagerClient::PasswordAutofillWasBlocked(
115 const autofill::PasswordFormMap& best_matches) const {
116 ManagePasswordsUIController* controller =
117 ManagePasswordsUIController::FromWebContents(web_contents());
118 if (controller && IsTheHotNewBubbleUIEnabled())
119 controller->OnBlacklistBlockedAutofill(best_matches);
122 void ChromePasswordManagerClient::AuthenticateAutofillAndFillForm(
123 scoped_ptr<autofill::PasswordFormFillData> fill_data) {
124 #if defined(OS_ANDROID)
125 PasswordAuthenticationManager::AuthenticatePasswordAutofill(
127 base::Bind(&ChromePasswordManagerClient::CommitFillPasswordForm,
128 weak_factory_.GetWeakPtr(),
129 base::Owned(fill_data.release())));
131 // Additional authentication is currently only available for Android, so all
132 // other plaftorms should just fill the password form directly.
133 CommitFillPasswordForm(fill_data.get());
137 Profile* ChromePasswordManagerClient::GetProfile() {
138 return Profile::FromBrowserContext(web_contents()->GetBrowserContext());
141 void ChromePasswordManagerClient::HidePasswordGenerationPopup() {
142 if (popup_controller_)
143 popup_controller_->HideAndDestroy();
146 PrefService* ChromePasswordManagerClient::GetPrefs() {
147 return GetProfile()->GetPrefs();
150 password_manager::PasswordStore*
151 ChromePasswordManagerClient::GetPasswordStore() {
152 // Always use EXPLICIT_ACCESS as the password manager checks IsOffTheRecord
153 // itself when it shouldn't access the PasswordStore.
154 // TODO(gcasto): Is is safe to change this to Profile::IMPLICIT_ACCESS?
155 return PasswordStoreFactory::GetForProfile(GetProfile(),
156 Profile::EXPLICIT_ACCESS).get();
159 password_manager::PasswordManagerDriver*
160 ChromePasswordManagerClient::GetDriver() {
164 base::FieldTrial::Probability
165 ChromePasswordManagerClient::GetProbabilityForExperiment(
166 const std::string& experiment_name) {
167 base::FieldTrial::Probability enabled_probability = 0;
168 if (experiment_name ==
169 password_manager::PasswordManager::kOtherPossibleUsernamesExperiment) {
170 switch (chrome::VersionInfo::GetChannel()) {
171 case chrome::VersionInfo::CHANNEL_DEV:
172 case chrome::VersionInfo::CHANNEL_BETA:
173 enabled_probability = 50;
179 return enabled_probability;
182 bool ChromePasswordManagerClient::IsPasswordSyncEnabled() {
183 ProfileSyncService* sync_service =
184 ProfileSyncServiceFactory::GetForProfile(GetProfile());
185 // Don't consider sync enabled if the user has a custom passphrase. See
186 // crbug.com/358998 for more details.
188 sync_service->HasSyncSetupCompleted() &&
189 sync_service->sync_initialized() &&
190 !sync_service->IsUsingSecondaryPassphrase()) {
191 return sync_service->GetActiveDataTypes().Has(syncer::PASSWORDS);
196 void ChromePasswordManagerClient::SetLogger(
197 password_manager::PasswordManagerLogger* logger) {
198 // We should never be replacing one logger with a different one, because that
199 // will leave the first without further updates, and the user likely confused.
200 // TODO(vabr): For the reason above, before moving the internals page from
201 // behind the flag, make sure to restrict the number of internals page
202 // instances to 1 in normal profiles, and 0 in incognito.
203 DCHECK(!logger || !logger_);
206 // Also inform the renderer process to start or stop logging.
207 web_contents()->GetRenderViewHost()->Send(new AutofillMsg_ChangeLoggingState(
208 web_contents()->GetRenderViewHost()->GetRoutingID(), logger != NULL));
211 void ChromePasswordManagerClient::LogSavePasswordProgress(
212 const std::string& text) {
213 if (IsLoggingActive())
214 logger_->LogSavePasswordProgress(text);
217 bool ChromePasswordManagerClient::IsLoggingActive() const {
218 return logger_ != NULL;
222 password_manager::PasswordGenerationManager*
223 ChromePasswordManagerClient::GetGenerationManagerFromWebContents(
224 content::WebContents* contents) {
225 ChromePasswordManagerClient* client =
226 ChromePasswordManagerClient::FromWebContents(contents);
229 return client->GetDriver()->GetPasswordGenerationManager();
233 password_manager::PasswordManager*
234 ChromePasswordManagerClient::GetManagerFromWebContents(
235 content::WebContents* contents) {
236 ChromePasswordManagerClient* client =
237 ChromePasswordManagerClient::FromWebContents(contents);
240 return client->GetDriver()->GetPasswordManager();
243 void ChromePasswordManagerClient::SetTestObserver(
244 autofill::PasswordGenerationPopupObserver* observer) {
245 observer_ = observer;
248 bool ChromePasswordManagerClient::OnMessageReceived(
249 const IPC::Message& message) {
251 IPC_BEGIN_MESSAGE_MAP(ChromePasswordManagerClient, message)
252 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
253 ShowPasswordGenerationPopup)
254 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordEditingPopup,
255 ShowPasswordEditingPopup)
256 IPC_MESSAGE_HANDLER(AutofillHostMsg_HidePasswordGenerationPopup,
257 HidePasswordGenerationPopup)
258 IPC_MESSAGE_UNHANDLED(handled = false)
259 IPC_END_MESSAGE_MAP()
263 gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace(
264 const gfx::RectF& bounds) {
265 gfx::Rect client_area = web_contents()->GetContainerBounds();
266 return bounds + client_area.OffsetFromOrigin();
269 void ChromePasswordManagerClient::ShowPasswordGenerationPopup(
270 const gfx::RectF& bounds,
272 const autofill::PasswordForm& form) {
273 // TODO(gcasto): Validate data in PasswordForm.
275 // Only implemented for Aura right now.
276 #if defined(USE_AURA)
277 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
280 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
282 element_bounds_in_screen_space,
285 driver_.GetPasswordManager(),
288 web_contents()->GetNativeView());
289 popup_controller_->Show(true /* display_password */);
290 #endif // #if defined(USE_AURA)
293 void ChromePasswordManagerClient::ShowPasswordEditingPopup(
294 const gfx::RectF& bounds,
295 const autofill::PasswordForm& form) {
296 // Only implemented for Aura right now.
297 #if defined(USE_AURA)
298 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
301 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
303 element_bounds_in_screen_space,
305 0, // Unspecified max length.
306 driver_.GetPasswordManager(),
309 web_contents()->GetNativeView());
310 popup_controller_->Show(false /* display_password */);
311 #endif // #if defined(USE_AURA)
314 void ChromePasswordManagerClient::CommitFillPasswordForm(
315 autofill::PasswordFormFillData* data) {
316 driver_.FillPasswordForm(*data);