Elim cr-checkbox
[chromium-blink-merge.git] / chrome / browser / password_manager / chrome_password_manager_client.cc
blob49da307f654d33c083b664ce73dbb383b97fc86f
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.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/memory/singleton.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.h"
13 #include "chrome/browser/browsing_data/browsing_data_helper.h"
14 #include "chrome/browser/password_manager/password_store_factory.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/browser/sync/profile_sync_service.h"
18 #include "chrome/browser/sync/profile_sync_service_factory.h"
19 #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
20 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
21 #include "chrome/common/channel_info.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/url_constants.h"
24 #include "components/autofill/content/browser/content_autofill_driver.h"
25 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
26 #include "components/autofill/content/common/autofill_messages.h"
27 #include "components/autofill/core/browser/password_generator.h"
28 #include "components/autofill/core/common/password_form.h"
29 #include "components/password_manager/content/browser/content_password_manager_driver.h"
30 #include "components/password_manager/content/browser/password_manager_internals_service_factory.h"
31 #include "components/password_manager/content/common/credential_manager_messages.h"
32 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
33 #include "components/password_manager/core/browser/log_receiver.h"
34 #include "components/password_manager/core/browser/password_form_manager.h"
35 #include "components/password_manager/core/browser/password_manager_internals_service.h"
36 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
37 #include "components/password_manager/core/browser/password_manager_settings_migration_experiment.h"
38 #include "components/password_manager/core/browser/password_manager_util.h"
39 #include "components/password_manager/core/common/credential_manager_types.h"
40 #include "components/password_manager/core/common/password_manager_pref_names.h"
41 #include "components/password_manager/core/common/password_manager_switches.h"
42 #include "components/password_manager/sync/browser/password_sync_util.h"
43 #include "components/signin/core/browser/signin_manager.h"
44 #include "components/version_info/version_info.h"
45 #include "content/public/browser/navigation_entry.h"
46 #include "content/public/browser/render_view_host.h"
47 #include "content/public/browser/web_contents.h"
48 #include "google_apis/gaia/gaia_urls.h"
49 #include "net/base/url_util.h"
50 #include "third_party/re2/re2/re2.h"
52 #if defined(OS_MACOSX) || defined(OS_ANDROID)
53 #include "chrome/browser/password_manager/save_password_infobar_delegate.h"
54 #endif
56 #if defined(OS_ANDROID)
57 #include "chrome/browser/android/tab_android.h"
58 #include "chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.h"
59 #include "chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.h"
60 #endif
62 using password_manager::ContentPasswordManagerDriverFactory;
63 using password_manager::PasswordManagerInternalsService;
64 using password_manager::PasswordManagerInternalsServiceFactory;
66 // Shorten the name to spare line breaks. The code provides enough context
67 // already.
68 typedef autofill::SavePasswordProgressLogger Logger;
70 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromePasswordManagerClient);
72 namespace {
74 const sync_driver::SyncService* GetSyncService(Profile* profile) {
75 if (ProfileSyncServiceFactory::HasProfileSyncService(profile))
76 return ProfileSyncServiceFactory::GetForProfile(profile);
77 return nullptr;
80 const SigninManagerBase* GetSigninManager(Profile* profile) {
81 return SigninManagerFactory::GetForProfile(profile);
84 // This routine is called when PasswordManagerClient is constructed.
85 // Currently we report metrics only once at startup. We require
86 // that this is only ever called from a single thread in order to
87 // avoid needing to lock (a static boolean flag is then sufficient to
88 // guarantee running only once).
89 void ReportMetrics(bool password_manager_enabled,
90 password_manager::PasswordManagerClient* client,
91 Profile* profile) {
92 static base::PlatformThreadId initial_thread_id =
93 base::PlatformThread::CurrentId();
94 DCHECK_EQ(base::PlatformThread::CurrentId(), initial_thread_id);
96 static bool ran_once = false;
97 if (ran_once)
98 return;
99 ran_once = true;
101 password_manager::PasswordStore* store = client->GetPasswordStore();
102 // May be null in tests.
103 if (store) {
104 store->ReportMetrics(
105 password_manager::sync_util::GetSyncUsernameIfSyncingPasswords(
106 GetSyncService(profile), GetSigninManager(profile)),
107 client->GetPasswordSyncState() ==
108 password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE);
110 UMA_HISTOGRAM_BOOLEAN("PasswordManager.Enabled", password_manager_enabled);
113 } // namespace
115 // static
116 void ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
117 content::WebContents* contents,
118 autofill::AutofillClient* autofill_client) {
119 if (FromWebContents(contents))
120 return;
122 contents->SetUserData(
123 UserDataKey(),
124 new ChromePasswordManagerClient(contents, autofill_client));
127 ChromePasswordManagerClient::ChromePasswordManagerClient(
128 content::WebContents* web_contents,
129 autofill::AutofillClient* autofill_client)
130 : content::WebContentsObserver(web_contents),
131 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
132 password_manager_(this),
133 driver_factory_(nullptr),
134 credential_manager_dispatcher_(web_contents, this),
135 observer_(nullptr),
136 can_use_log_router_(false),
137 credentials_filter_(this,
138 base::Bind(&GetSyncService, profile_),
139 base::Bind(&GetSigninManager, profile_)) {
140 ContentPasswordManagerDriverFactory::CreateForWebContents(web_contents, this,
141 autofill_client);
142 driver_factory_ =
143 ContentPasswordManagerDriverFactory::FromWebContents(web_contents);
145 PasswordManagerInternalsService* service =
146 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
147 if (service)
148 can_use_log_router_ = service->RegisterClient(this);
149 saving_and_filling_passwords_enabled_.Init(
150 password_manager::prefs::kPasswordManagerSavingEnabled, GetPrefs());
151 ReportMetrics(*saving_and_filling_passwords_enabled_, this, profile_);
154 ChromePasswordManagerClient::~ChromePasswordManagerClient() {
155 PasswordManagerInternalsService* service =
156 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
157 if (service)
158 service->UnregisterClient(this);
161 bool ChromePasswordManagerClient::IsAutomaticPasswordSavingEnabled() const {
162 return base::CommandLine::ForCurrentProcess()->HasSwitch(
163 password_manager::switches::kEnableAutomaticPasswordSaving) &&
164 chrome::GetChannel() == version_info::Channel::UNKNOWN;
167 bool ChromePasswordManagerClient::IsPasswordManagementEnabledForCurrentPage()
168 const {
169 DCHECK(web_contents());
170 content::NavigationEntry* entry =
171 web_contents()->GetController().GetLastCommittedEntry();
172 bool is_enabled = false;
173 if (!entry) {
174 // TODO(gcasto): Determine if fix for crbug.com/388246 is relevant here.
175 is_enabled = true;
176 } else if (IsURLPasswordWebsiteReauth(entry->GetURL())) {
177 // Disable the password manager for online password management.
178 is_enabled = false;
179 } else if (EnabledForSyncSignin()) {
180 is_enabled = true;
181 } else {
182 // Do not fill nor save password when a user is signing in for sync. This
183 // is because users need to remember their password if they are syncing as
184 // this is effectively their master password.
185 is_enabled = entry->GetURL().host() != chrome::kChromeUIChromeSigninHost;
187 if (IsLoggingActive()) {
188 password_manager::BrowserSavePasswordProgressLogger logger(this);
189 logger.LogBoolean(
190 Logger::STRING_PASSWORD_MANAGEMENT_ENABLED_FOR_CURRENT_PAGE,
191 is_enabled);
193 return is_enabled;
196 bool ChromePasswordManagerClient::IsSavingAndFillingEnabledForCurrentPage()
197 const {
198 // TODO(melandory): remove saving_and_filling_passwords_enabled_ check from
199 // here once we decide to switch to new settings behavior for everyone.
200 return *saving_and_filling_passwords_enabled_ && !IsOffTheRecord() &&
201 IsFillingEnabledForCurrentPage();
204 bool ChromePasswordManagerClient::IsFillingEnabledForCurrentPage() const {
205 return (!password_manager::IsSettingsBehaviorChangeActive() ||
206 *saving_and_filling_passwords_enabled_) &&
207 !DidLastPageLoadEncounterSSLErrors() &&
208 IsPasswordManagementEnabledForCurrentPage();
211 bool ChromePasswordManagerClient::PromptUserToSaveOrUpdatePassword(
212 scoped_ptr<password_manager::PasswordFormManager> form_to_save,
213 password_manager::CredentialSourceType type,
214 bool update_password) {
215 // Save password infobar and the password bubble prompts in case of
216 // "webby" URLs and do not prompt in case of "non-webby" URLS (e.g. file://).
217 if (!BrowsingDataHelper::IsWebScheme(
218 web_contents()->GetLastCommittedURL().scheme())) {
219 return false;
222 if (IsTheHotNewBubbleUIEnabled()) {
223 ManagePasswordsUIController* manage_passwords_ui_controller =
224 ManagePasswordsUIController::FromWebContents(web_contents());
225 if (update_password && IsUpdatePasswordUIEnabled()) {
226 manage_passwords_ui_controller->OnUpdatePasswordSubmitted(
227 form_to_save.Pass());
228 } else {
229 manage_passwords_ui_controller->OnPasswordSubmitted(form_to_save.Pass());
231 } else {
232 #if defined(OS_MACOSX) || defined(OS_ANDROID)
233 if (form_to_save->IsBlacklisted())
234 return false;
235 std::string uma_histogram_suffix(
236 password_manager::metrics_util::GroupIdToString(
237 password_manager::metrics_util::MonitoredDomainGroupId(
238 form_to_save->pending_credentials().signon_realm, GetPrefs())));
239 SavePasswordInfoBarDelegate::Create(
240 web_contents(), form_to_save.Pass(), uma_histogram_suffix, type);
241 #else
242 NOTREACHED() << "Aura platforms should always use the bubble";
243 #endif
245 return true;
248 bool ChromePasswordManagerClient::PromptUserToChooseCredentials(
249 ScopedVector<autofill::PasswordForm> local_forms,
250 ScopedVector<autofill::PasswordForm> federated_forms,
251 const GURL& origin,
252 base::Callback<void(const password_manager::CredentialInfo&)> callback) {
253 return ManagePasswordsUIController::FromWebContents(web_contents())->
254 OnChooseCredentials(local_forms.Pass(), federated_forms.Pass(), origin,
255 callback);
258 void ChromePasswordManagerClient::ForceSavePassword() {
259 password_manager::ContentPasswordManagerDriver* driver =
260 driver_factory_->GetDriverForFrame(web_contents()->GetFocusedFrame());
261 driver->ForceSavePassword();
264 void ChromePasswordManagerClient::NotifyUserAutoSignin(
265 ScopedVector<autofill::PasswordForm> local_forms) {
266 DCHECK(!local_forms.empty());
267 #if defined(OS_ANDROID)
268 TabAndroid *tab = TabAndroid::FromWebContents(web_contents());
269 ShowAutoSigninSnackbar(tab, local_forms[0]->username_value);
270 #else
271 ManagePasswordsUIController::FromWebContents(web_contents())->
272 OnAutoSignin(local_forms.Pass());
274 #endif
277 void ChromePasswordManagerClient::AutomaticPasswordSave(
278 scoped_ptr<password_manager::PasswordFormManager> saved_form) {
279 #if defined(OS_ANDROID)
280 GeneratedPasswordSavedInfoBarDelegateAndroid::Create(web_contents());
281 #else
282 if (IsTheHotNewBubbleUIEnabled()) {
283 ManagePasswordsUIController* manage_passwords_ui_controller =
284 ManagePasswordsUIController::FromWebContents(web_contents());
285 manage_passwords_ui_controller->OnAutomaticPasswordSave(
286 saved_form.Pass());
288 #endif
291 void ChromePasswordManagerClient::PasswordWasAutofilled(
292 const autofill::PasswordFormMap& best_matches) const {
293 ManagePasswordsUIController* manage_passwords_ui_controller =
294 ManagePasswordsUIController::FromWebContents(web_contents());
295 if (manage_passwords_ui_controller && IsTheHotNewBubbleUIEnabled())
296 manage_passwords_ui_controller->OnPasswordAutofilled(best_matches);
299 void ChromePasswordManagerClient::PasswordAutofillWasBlocked(
300 const autofill::PasswordFormMap& best_matches) const {
301 ManagePasswordsUIController* controller =
302 ManagePasswordsUIController::FromWebContents(web_contents());
303 if (controller && IsTheHotNewBubbleUIEnabled())
304 controller->OnBlacklistBlockedAutofill(best_matches);
307 void ChromePasswordManagerClient::HidePasswordGenerationPopup() {
308 if (popup_controller_)
309 popup_controller_->HideAndDestroy();
312 PrefService* ChromePasswordManagerClient::GetPrefs() {
313 return profile_->GetPrefs();
316 password_manager::PasswordStore*
317 ChromePasswordManagerClient::GetPasswordStore() const {
318 // Always use EXPLICIT_ACCESS as the password manager checks IsOffTheRecord
319 // itself when it shouldn't access the PasswordStore.
320 // TODO(gcasto): Is is safe to change this to
321 // ServiceAccessType::IMPLICIT_ACCESS?
322 return PasswordStoreFactory::GetForProfile(
323 profile_, ServiceAccessType::EXPLICIT_ACCESS).get();
326 password_manager::PasswordSyncState
327 ChromePasswordManagerClient::GetPasswordSyncState() const {
328 const ProfileSyncService* sync_service =
329 ProfileSyncServiceFactory::GetForProfile(profile_);
330 return password_manager_util::GetPasswordSyncState(sync_service);
333 void ChromePasswordManagerClient::OnLogRouterAvailabilityChanged(
334 bool router_can_be_used) {
335 if (can_use_log_router_ == router_can_be_used)
336 return;
337 can_use_log_router_ = router_can_be_used;
339 NotifyRendererOfLoggingAvailability();
342 void ChromePasswordManagerClient::LogSavePasswordProgress(
343 const std::string& text) const {
344 if (!IsLoggingActive())
345 return;
346 PasswordManagerInternalsService* service =
347 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
348 if (service)
349 service->ProcessLog(text);
352 bool ChromePasswordManagerClient::IsLoggingActive() const {
353 // WebUI tabs do not need to log password saving progress. In particular, the
354 // internals page itself should not send any logs.
355 return can_use_log_router_ && !web_contents()->GetWebUI();
358 bool ChromePasswordManagerClient::WasLastNavigationHTTPError() const {
359 DCHECK(web_contents());
361 scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger;
362 if (IsLoggingActive()) {
363 logger.reset(new password_manager::BrowserSavePasswordProgressLogger(this));
364 logger->LogMessage(
365 Logger::STRING_WAS_LAST_NAVIGATION_HTTP_ERROR_METHOD);
368 content::NavigationEntry* entry =
369 web_contents()->GetController().GetVisibleEntry();
370 if (!entry)
371 return false;
372 int http_status_code = entry->GetHttpStatusCode();
374 if (logger)
375 logger->LogNumber(Logger::STRING_HTTP_STATUS_CODE, http_status_code);
377 if (http_status_code >= 400 && http_status_code < 600)
378 return true;
379 return false;
382 bool ChromePasswordManagerClient::DidLastPageLoadEncounterSSLErrors() const {
383 content::NavigationEntry* entry =
384 web_contents()->GetController().GetLastCommittedEntry();
385 bool ssl_errors = true;
386 if (!entry) {
387 ssl_errors = false;
388 } else {
389 ssl_errors = net::IsCertStatusError(entry->GetSSL().cert_status);
391 if (IsLoggingActive()) {
392 password_manager::BrowserSavePasswordProgressLogger logger(this);
393 logger.LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, ssl_errors);
395 return ssl_errors;
398 bool ChromePasswordManagerClient::IsOffTheRecord() const {
399 return web_contents()->GetBrowserContext()->IsOffTheRecord();
402 password_manager::PasswordManager*
403 ChromePasswordManagerClient::GetPasswordManager() {
404 return &password_manager_;
407 autofill::AutofillManager*
408 ChromePasswordManagerClient::GetAutofillManagerForMainFrame() {
409 autofill::ContentAutofillDriverFactory* factory =
410 autofill::ContentAutofillDriverFactory::FromWebContents(web_contents());
411 return factory
412 ? factory->DriverForFrame(web_contents()->GetMainFrame())
413 ->autofill_manager()
414 : nullptr;
417 void ChromePasswordManagerClient::SetTestObserver(
418 autofill::PasswordGenerationPopupObserver* observer) {
419 observer_ = observer;
422 bool ChromePasswordManagerClient::OnMessageReceived(
423 const IPC::Message& message,
424 content::RenderFrameHost* render_frame_host) {
425 bool handled = true;
426 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ChromePasswordManagerClient, message,
427 render_frame_host)
428 // Autofill messages:
429 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
430 ShowPasswordGenerationPopup)
431 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordEditingPopup,
432 ShowPasswordEditingPopup)
433 IPC_END_MESSAGE_MAP()
435 IPC_BEGIN_MESSAGE_MAP(ChromePasswordManagerClient, message)
436 IPC_MESSAGE_HANDLER(AutofillHostMsg_HidePasswordGenerationPopup,
437 HidePasswordGenerationPopup)
438 IPC_MESSAGE_HANDLER(AutofillHostMsg_GenerationAvailableForForm,
439 GenerationAvailableForForm)
440 IPC_MESSAGE_HANDLER(AutofillHostMsg_PasswordAutofillAgentConstructed,
441 NotifyRendererOfLoggingAvailability)
442 // Default:
443 IPC_MESSAGE_UNHANDLED(handled = false)
444 IPC_END_MESSAGE_MAP()
446 return handled;
449 gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace(
450 const gfx::RectF& bounds) {
451 gfx::Rect client_area = web_contents()->GetContainerBounds();
452 return bounds + client_area.OffsetFromOrigin();
455 void ChromePasswordManagerClient::ShowPasswordGenerationPopup(
456 content::RenderFrameHost* render_frame_host,
457 const gfx::RectF& bounds,
458 int max_length,
459 const autofill::PasswordForm& form) {
460 // TODO(gcasto): Validate data in PasswordForm.
462 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
464 popup_controller_ =
465 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
466 popup_controller_, element_bounds_in_screen_space, form, max_length,
467 &password_manager_,
468 driver_factory_->GetDriverForFrame(render_frame_host), observer_,
469 web_contents(), web_contents()->GetNativeView());
470 popup_controller_->Show(true /* display_password */);
473 void ChromePasswordManagerClient::ShowPasswordEditingPopup(
474 content::RenderFrameHost* render_frame_host,
475 const gfx::RectF& bounds,
476 const autofill::PasswordForm& form) {
477 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
478 popup_controller_ =
479 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
480 popup_controller_, element_bounds_in_screen_space, form,
481 0, // Unspecified max length.
482 &password_manager_,
483 driver_factory_->GetDriverForFrame(render_frame_host), observer_,
484 web_contents(), web_contents()->GetNativeView());
485 popup_controller_->Show(false /* display_password */);
488 void ChromePasswordManagerClient::GenerationAvailableForForm(
489 const autofill::PasswordForm& form) {
490 password_manager_.GenerationAvailableForForm(form);
493 void ChromePasswordManagerClient::NotifyRendererOfLoggingAvailability() {
494 if (!web_contents())
495 return;
497 web_contents()->GetRenderViewHost()->Send(new AutofillMsg_SetLoggingState(
498 web_contents()->GetRenderViewHost()->GetRoutingID(),
499 can_use_log_router_));
502 bool ChromePasswordManagerClient::IsURLPasswordWebsiteReauth(
503 const GURL& url) const {
504 if (url.GetOrigin() != GaiaUrls::GetInstance()->gaia_url().GetOrigin())
505 return false;
507 // "rart" param signals this page is for transactional reauth.
508 std::string param_value;
509 if (!net::GetValueForKeyInQuery(url, "rart", &param_value))
510 return false;
512 // Check the "continue" param to see if this reauth page is for the passwords
513 // website.
514 param_value.clear();
515 if (!net::GetValueForKeyInQuery(url, "continue", &param_value))
516 return false;
518 // All password sites, including test sites, have autofilling disabled.
519 CR_DEFINE_STATIC_LOCAL(RE2, account_dashboard_pattern,
520 ("passwords(-([a-z-]+\\.corp))?\\.google\\.com"));
522 return RE2::FullMatch(GURL(param_value).host(), account_dashboard_pattern);
525 bool ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled() {
526 #if defined(OS_ANDROID)
527 return false;
528 #elif defined(OS_MACOSX)
529 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
530 if (command_line->HasSwitch(switches::kDisableSavePasswordBubble))
531 return false;
533 if (command_line->HasSwitch(switches::kEnableSavePasswordBubble))
534 return true;
536 std::string group_name =
537 base::FieldTrialList::FindFullName("PasswordManagerUI");
539 // The bubble should be the default case that runs on the bots.
540 return group_name != "Infobar";
541 #else
542 // All other platforms use Aura, and therefore always show the bubble.
543 return true;
544 #endif
547 bool ChromePasswordManagerClient::IsUpdatePasswordUIEnabled() const {
548 #if defined(OS_MACOSX)
549 return false;
550 #else
551 return IsTheHotNewBubbleUIEnabled();
552 #endif
555 bool ChromePasswordManagerClient::EnabledForSyncSignin() {
556 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
557 if (command_line->HasSwitch(
558 password_manager::switches::kDisableManagerForSyncSignin))
559 return false;
561 if (command_line->HasSwitch(
562 password_manager::switches::kEnableManagerForSyncSignin))
563 return true;
565 // Default is enabled.
566 std::string group_name =
567 base::FieldTrialList::FindFullName("PasswordManagerStateForSyncSignin");
568 return group_name != "Disabled";
571 const GURL& ChromePasswordManagerClient::GetMainFrameURL() const {
572 return web_contents()->GetVisibleURL();
575 const GURL& ChromePasswordManagerClient::GetLastCommittedEntryURL() const {
576 DCHECK(web_contents());
577 content::NavigationEntry* entry =
578 web_contents()->GetController().GetLastCommittedEntry();
579 if (!entry)
580 return GURL::EmptyGURL();
582 return entry->GetURL();
585 const password_manager::CredentialsFilter*
586 ChromePasswordManagerClient::GetStoreResultFilter() const {
587 return &credentials_filter_;