Make sure the win_chromium_gn_x64_dbg bot is using symbol_level=1
[chromium-blink-merge.git] / chrome / browser / password_manager / chrome_password_manager_client.cc
blob8d54e929d08645656196ffadc6dd05ae80317cd6
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 "base/prefs/pref_service.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/browsing_data/browsing_data_helper.h"
15 #include "chrome/browser/password_manager/password_store_factory.h"
16 #include "chrome/browser/password_manager/save_password_infobar_delegate.h"
17 #include "chrome/browser/password_manager/sync_metrics.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/sync/profile_sync_service.h"
20 #include "chrome/browser/sync/profile_sync_service_factory.h"
21 #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
22 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
23 #include "chrome/common/channel_info.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/url_constants.h"
26 #include "components/autofill/content/browser/content_autofill_driver.h"
27 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
28 #include "components/autofill/content/common/autofill_messages.h"
29 #include "components/autofill/core/browser/password_generator.h"
30 #include "components/autofill/core/common/password_form.h"
31 #include "components/password_manager/content/browser/content_password_manager_driver.h"
32 #include "components/password_manager/content/browser/password_manager_internals_service_factory.h"
33 #include "components/password_manager/content/common/credential_manager_messages.h"
34 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
35 #include "components/password_manager/core/browser/log_receiver.h"
36 #include "components/password_manager/core/browser/password_form_manager.h"
37 #include "components/password_manager/core/browser/password_manager_internals_service.h"
38 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
39 #include "components/password_manager/core/browser/password_manager_util.h"
40 #include "components/password_manager/core/common/credential_manager_types.h"
41 #include "components/password_manager/core/common/password_manager_pref_names.h"
42 #include "components/password_manager/core/common/password_manager_switches.h"
43 #include "components/password_manager/sync/browser/sync_store_result_filter.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_ANDROID)
53 #include "chrome/browser/android/tab_android.h"
54 #include "chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.h"
55 #include "chrome/browser/ui/android/snackbars/auto_signin_snackbar_controller.h"
56 #endif
58 using password_manager::ContentPasswordManagerDriverFactory;
59 using password_manager::PasswordManagerInternalsService;
60 using password_manager::PasswordManagerInternalsServiceFactory;
62 // Shorten the name to spare line breaks. The code provides enough context
63 // already.
64 typedef autofill::SavePasswordProgressLogger Logger;
66 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromePasswordManagerClient);
68 namespace {
69 // This routine is called when PasswordManagerClient is constructed.
70 // Currently we report metrics only once at startup. We require
71 // that this is only ever called from a single thread in order to
72 // avoid needing to lock (a static boolean flag is then sufficient to
73 // guarantee running only once).
74 void ReportMetrics(bool password_manager_enabled,
75 password_manager::PasswordManagerClient* client) {
76 static base::PlatformThreadId initial_thread_id =
77 base::PlatformThread::CurrentId();
78 DCHECK_EQ(base::PlatformThread::CurrentId(), initial_thread_id);
80 static bool ran_once = false;
81 if (ran_once)
82 return;
83 ran_once = true;
85 password_manager::PasswordStore* store = client->GetPasswordStore();
86 // May be null in tests.
87 if (store) {
88 store->ReportMetrics(client->GetSyncUsername(),
89 client->GetPasswordSyncState() ==
90 password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE);
92 UMA_HISTOGRAM_BOOLEAN("PasswordManager.Enabled", password_manager_enabled);
95 } // namespace
97 // static
98 void ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
99 content::WebContents* contents,
100 autofill::AutofillClient* autofill_client) {
101 if (FromWebContents(contents))
102 return;
104 contents->SetUserData(
105 UserDataKey(),
106 new ChromePasswordManagerClient(contents, autofill_client));
109 ChromePasswordManagerClient::ChromePasswordManagerClient(
110 content::WebContents* web_contents,
111 autofill::AutofillClient* autofill_client)
112 : content::WebContentsObserver(web_contents),
113 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
114 password_manager_(this),
115 driver_factory_(nullptr),
116 credential_manager_dispatcher_(web_contents, this),
117 observer_(nullptr),
118 can_use_log_router_(false) {
119 ContentPasswordManagerDriverFactory::CreateForWebContents(web_contents, this,
120 autofill_client);
121 driver_factory_ =
122 ContentPasswordManagerDriverFactory::FromWebContents(web_contents);
124 PasswordManagerInternalsService* service =
125 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
126 if (service)
127 can_use_log_router_ = service->RegisterClient(this);
128 saving_passwords_enabled_.Init(
129 password_manager::prefs::kPasswordManagerSavingEnabled, GetPrefs());
130 ReportMetrics(*saving_passwords_enabled_, this);
133 ChromePasswordManagerClient::~ChromePasswordManagerClient() {
134 PasswordManagerInternalsService* service =
135 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
136 if (service)
137 service->UnregisterClient(this);
140 bool ChromePasswordManagerClient::IsAutomaticPasswordSavingEnabled() const {
141 return base::CommandLine::ForCurrentProcess()->HasSwitch(
142 password_manager::switches::kEnableAutomaticPasswordSaving) &&
143 chrome::GetChannel() == version_info::Channel::UNKNOWN;
146 bool ChromePasswordManagerClient::IsPasswordManagementEnabledForCurrentPage()
147 const {
148 DCHECK(web_contents());
149 content::NavigationEntry* entry =
150 web_contents()->GetController().GetLastCommittedEntry();
151 bool is_enabled = false;
152 if (!entry) {
153 // TODO(gcasto): Determine if fix for crbug.com/388246 is relevant here.
154 is_enabled = true;
155 } else if (IsURLPasswordWebsiteReauth(entry->GetURL())) {
156 // Disable the password manager for online password management.
157 is_enabled = false;
158 } else if (EnabledForSyncSignin()) {
159 is_enabled = true;
160 } else {
161 // Do not fill nor save password when a user is signing in for sync. This
162 // is because users need to remember their password if they are syncing as
163 // this is effectively their master password.
164 is_enabled = entry->GetURL().host() != chrome::kChromeUIChromeSigninHost;
166 if (IsLoggingActive()) {
167 password_manager::BrowserSavePasswordProgressLogger logger(this);
168 logger.LogBoolean(
169 Logger::STRING_PASSWORD_MANAGEMENT_ENABLED_FOR_CURRENT_PAGE,
170 is_enabled);
172 return is_enabled;
175 bool ChromePasswordManagerClient::IsSavingEnabledForCurrentPage() const {
176 return *saving_passwords_enabled_ && !IsOffTheRecord() &&
177 !DidLastPageLoadEncounterSSLErrors() &&
178 IsPasswordManagementEnabledForCurrentPage();
181 std::string ChromePasswordManagerClient::GetSyncUsername() const {
182 return password_manager_sync_metrics::GetSyncUsername(profile_);
185 bool ChromePasswordManagerClient::IsSyncAccountCredential(
186 const std::string& username,
187 const std::string& realm) const {
188 return password_manager_sync_metrics::IsSyncAccountCredential(
189 profile_, username, realm);
192 bool ChromePasswordManagerClient::PromptUserToSaveOrUpdatePassword(
193 scoped_ptr<password_manager::PasswordFormManager> form_to_save,
194 password_manager::CredentialSourceType type,
195 bool update_password) {
196 // Save password infobar and the password bubble prompts in case of
197 // "webby" URLs and do not prompt in case of "non-webby" URLS (e.g. file://).
198 if (!BrowsingDataHelper::IsWebScheme(
199 web_contents()->GetLastCommittedURL().scheme())) {
200 return false;
203 if (IsTheHotNewBubbleUIEnabled()) {
204 ManagePasswordsUIController* manage_passwords_ui_controller =
205 ManagePasswordsUIController::FromWebContents(web_contents());
206 if (update_password && IsUpdatePasswordUIEnabled()) {
207 manage_passwords_ui_controller->OnUpdatePasswordSubmitted(
208 form_to_save.Pass());
209 } else {
210 manage_passwords_ui_controller->OnPasswordSubmitted(form_to_save.Pass());
212 } else {
213 if (form_to_save->IsBlacklisted())
214 return false;
215 std::string uma_histogram_suffix(
216 password_manager::metrics_util::GroupIdToString(
217 password_manager::metrics_util::MonitoredDomainGroupId(
218 form_to_save->pending_credentials().signon_realm, GetPrefs())));
219 SavePasswordInfoBarDelegate::Create(
220 web_contents(), form_to_save.Pass(), uma_histogram_suffix, type);
222 return true;
225 bool ChromePasswordManagerClient::PromptUserToChooseCredentials(
226 ScopedVector<autofill::PasswordForm> local_forms,
227 ScopedVector<autofill::PasswordForm> federated_forms,
228 const GURL& origin,
229 base::Callback<void(const password_manager::CredentialInfo&)> callback) {
230 return ManagePasswordsUIController::FromWebContents(web_contents())->
231 OnChooseCredentials(local_forms.Pass(), federated_forms.Pass(), origin,
232 callback);
235 void ChromePasswordManagerClient::ForceSavePassword() {
236 password_manager::ContentPasswordManagerDriver* driver =
237 driver_factory_->GetDriverForFrame(web_contents()->GetFocusedFrame());
238 driver->ForceSavePassword();
241 void ChromePasswordManagerClient::NotifyUserAutoSignin(
242 ScopedVector<autofill::PasswordForm> local_forms) {
243 DCHECK(!local_forms.empty());
244 #if defined(OS_ANDROID)
245 TabAndroid *tab = TabAndroid::FromWebContents(web_contents());
246 ShowAutoSigninSnackbar(tab, local_forms[0]->username_value);
247 #else
248 ManagePasswordsUIController::FromWebContents(web_contents())->
249 OnAutoSignin(local_forms.Pass());
251 #endif
254 void ChromePasswordManagerClient::AutomaticPasswordSave(
255 scoped_ptr<password_manager::PasswordFormManager> saved_form) {
256 #if defined(OS_ANDROID)
257 GeneratedPasswordSavedInfoBarDelegateAndroid::Create(web_contents());
258 #else
259 if (IsTheHotNewBubbleUIEnabled()) {
260 ManagePasswordsUIController* manage_passwords_ui_controller =
261 ManagePasswordsUIController::FromWebContents(web_contents());
262 manage_passwords_ui_controller->OnAutomaticPasswordSave(
263 saved_form.Pass());
265 #endif
268 void ChromePasswordManagerClient::PasswordWasAutofilled(
269 const autofill::PasswordFormMap& best_matches) const {
270 ManagePasswordsUIController* manage_passwords_ui_controller =
271 ManagePasswordsUIController::FromWebContents(web_contents());
272 if (manage_passwords_ui_controller && IsTheHotNewBubbleUIEnabled())
273 manage_passwords_ui_controller->OnPasswordAutofilled(best_matches);
276 void ChromePasswordManagerClient::PasswordAutofillWasBlocked(
277 const autofill::PasswordFormMap& best_matches) const {
278 ManagePasswordsUIController* controller =
279 ManagePasswordsUIController::FromWebContents(web_contents());
280 if (controller && IsTheHotNewBubbleUIEnabled())
281 controller->OnBlacklistBlockedAutofill(best_matches);
284 void ChromePasswordManagerClient::HidePasswordGenerationPopup() {
285 if (popup_controller_)
286 popup_controller_->HideAndDestroy();
289 PrefService* ChromePasswordManagerClient::GetPrefs() {
290 return profile_->GetPrefs();
293 password_manager::PasswordStore*
294 ChromePasswordManagerClient::GetPasswordStore() const {
295 // Always use EXPLICIT_ACCESS as the password manager checks IsOffTheRecord
296 // itself when it shouldn't access the PasswordStore.
297 // TODO(gcasto): Is is safe to change this to
298 // ServiceAccessType::IMPLICIT_ACCESS?
299 return PasswordStoreFactory::GetForProfile(
300 profile_, ServiceAccessType::EXPLICIT_ACCESS).get();
303 password_manager::PasswordSyncState
304 ChromePasswordManagerClient::GetPasswordSyncState() const {
305 const ProfileSyncService* sync_service =
306 ProfileSyncServiceFactory::GetForProfile(profile_);
307 return password_manager_util::GetPasswordSyncState(sync_service);
310 void ChromePasswordManagerClient::OnLogRouterAvailabilityChanged(
311 bool router_can_be_used) {
312 if (can_use_log_router_ == router_can_be_used)
313 return;
314 can_use_log_router_ = router_can_be_used;
316 NotifyRendererOfLoggingAvailability();
319 void ChromePasswordManagerClient::LogSavePasswordProgress(
320 const std::string& text) const {
321 if (!IsLoggingActive())
322 return;
323 PasswordManagerInternalsService* service =
324 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
325 if (service)
326 service->ProcessLog(text);
329 bool ChromePasswordManagerClient::IsLoggingActive() const {
330 // WebUI tabs do not need to log password saving progress. In particular, the
331 // internals page itself should not send any logs.
332 return can_use_log_router_ && !web_contents()->GetWebUI();
335 bool ChromePasswordManagerClient::WasLastNavigationHTTPError() const {
336 DCHECK(web_contents());
338 scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger;
339 if (IsLoggingActive()) {
340 logger.reset(new password_manager::BrowserSavePasswordProgressLogger(this));
341 logger->LogMessage(
342 Logger::STRING_WAS_LAST_NAVIGATION_HTTP_ERROR_METHOD);
345 content::NavigationEntry* entry =
346 web_contents()->GetController().GetVisibleEntry();
347 if (!entry)
348 return false;
349 int http_status_code = entry->GetHttpStatusCode();
351 if (logger)
352 logger->LogNumber(Logger::STRING_HTTP_STATUS_CODE, http_status_code);
354 if (http_status_code >= 400 && http_status_code < 600)
355 return true;
356 return false;
359 bool ChromePasswordManagerClient::DidLastPageLoadEncounterSSLErrors() const {
360 content::NavigationEntry* entry =
361 web_contents()->GetController().GetLastCommittedEntry();
362 bool ssl_errors = true;
363 if (!entry) {
364 ssl_errors = false;
365 } else {
366 ssl_errors = net::IsCertStatusError(entry->GetSSL().cert_status);
368 if (IsLoggingActive()) {
369 password_manager::BrowserSavePasswordProgressLogger logger(this);
370 logger.LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, ssl_errors);
372 return ssl_errors;
375 bool ChromePasswordManagerClient::IsOffTheRecord() const {
376 return web_contents()->GetBrowserContext()->IsOffTheRecord();
379 password_manager::PasswordManager*
380 ChromePasswordManagerClient::GetPasswordManager() {
381 return &password_manager_;
384 autofill::AutofillManager*
385 ChromePasswordManagerClient::GetAutofillManagerForMainFrame() {
386 autofill::ContentAutofillDriverFactory* factory =
387 autofill::ContentAutofillDriverFactory::FromWebContents(web_contents());
388 return factory
389 ? factory->DriverForFrame(web_contents()->GetMainFrame())
390 ->autofill_manager()
391 : nullptr;
394 void ChromePasswordManagerClient::SetTestObserver(
395 autofill::PasswordGenerationPopupObserver* observer) {
396 observer_ = observer;
399 bool ChromePasswordManagerClient::OnMessageReceived(
400 const IPC::Message& message,
401 content::RenderFrameHost* render_frame_host) {
402 bool handled = true;
403 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ChromePasswordManagerClient, message,
404 render_frame_host)
405 // Autofill messages:
406 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
407 ShowPasswordGenerationPopup)
408 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordEditingPopup,
409 ShowPasswordEditingPopup)
410 IPC_END_MESSAGE_MAP()
412 IPC_BEGIN_MESSAGE_MAP(ChromePasswordManagerClient, message)
413 IPC_MESSAGE_HANDLER(AutofillHostMsg_HidePasswordGenerationPopup,
414 HidePasswordGenerationPopup)
415 IPC_MESSAGE_HANDLER(AutofillHostMsg_GenerationAvailableForForm,
416 GenerationAvailableForForm)
417 IPC_MESSAGE_HANDLER(AutofillHostMsg_PasswordAutofillAgentConstructed,
418 NotifyRendererOfLoggingAvailability)
419 // Default:
420 IPC_MESSAGE_UNHANDLED(handled = false)
421 IPC_END_MESSAGE_MAP()
423 return handled;
426 gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace(
427 const gfx::RectF& bounds) {
428 gfx::Rect client_area = web_contents()->GetContainerBounds();
429 return bounds + client_area.OffsetFromOrigin();
432 void ChromePasswordManagerClient::ShowPasswordGenerationPopup(
433 content::RenderFrameHost* render_frame_host,
434 const gfx::RectF& bounds,
435 int max_length,
436 const autofill::PasswordForm& form) {
437 // TODO(gcasto): Validate data in PasswordForm.
439 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
441 popup_controller_ =
442 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
443 popup_controller_, element_bounds_in_screen_space, form, max_length,
444 &password_manager_,
445 driver_factory_->GetDriverForFrame(render_frame_host), observer_,
446 web_contents(), web_contents()->GetNativeView());
447 popup_controller_->Show(true /* display_password */);
450 void ChromePasswordManagerClient::ShowPasswordEditingPopup(
451 content::RenderFrameHost* render_frame_host,
452 const gfx::RectF& bounds,
453 const autofill::PasswordForm& form) {
454 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
455 popup_controller_ =
456 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
457 popup_controller_, element_bounds_in_screen_space, form,
458 0, // Unspecified max length.
459 &password_manager_,
460 driver_factory_->GetDriverForFrame(render_frame_host), observer_,
461 web_contents(), web_contents()->GetNativeView());
462 popup_controller_->Show(false /* display_password */);
465 void ChromePasswordManagerClient::GenerationAvailableForForm(
466 const autofill::PasswordForm& form) {
467 password_manager_.GenerationAvailableForForm(form);
470 void ChromePasswordManagerClient::NotifyRendererOfLoggingAvailability() {
471 if (!web_contents())
472 return;
474 web_contents()->GetRenderViewHost()->Send(new AutofillMsg_SetLoggingState(
475 web_contents()->GetRenderViewHost()->GetRoutingID(),
476 can_use_log_router_));
479 bool ChromePasswordManagerClient::IsURLPasswordWebsiteReauth(
480 const GURL& url) const {
481 if (url.GetOrigin() != GaiaUrls::GetInstance()->gaia_url().GetOrigin())
482 return false;
484 // "rart" param signals this page is for transactional reauth.
485 std::string param_value;
486 if (!net::GetValueForKeyInQuery(url, "rart", &param_value))
487 return false;
489 // Check the "continue" param to see if this reauth page is for the passwords
490 // website.
491 param_value.clear();
492 if (!net::GetValueForKeyInQuery(url, "continue", &param_value))
493 return false;
495 // All password sites, including test sites, have autofilling disabled.
496 CR_DEFINE_STATIC_LOCAL(RE2, account_dashboard_pattern,
497 ("passwords(-([a-z-]+\\.corp))?\\.google\\.com"));
499 return RE2::FullMatch(GURL(param_value).host(), account_dashboard_pattern);
502 bool ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled() {
503 #if !defined(USE_AURA) && !defined(OS_MACOSX)
504 return false;
505 #endif
506 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
507 if (command_line->HasSwitch(switches::kDisableSavePasswordBubble))
508 return false;
510 if (command_line->HasSwitch(switches::kEnableSavePasswordBubble))
511 return true;
513 std::string group_name =
514 base::FieldTrialList::FindFullName("PasswordManagerUI");
516 // The bubble should be the default case that runs on the bots.
517 return group_name != "Infobar";
520 bool ChromePasswordManagerClient::IsUpdatePasswordUIEnabled() const {
521 #if defined(OS_MACOSX)
522 return false;
523 #else
524 return IsTheHotNewBubbleUIEnabled();
525 #endif
528 bool ChromePasswordManagerClient::EnabledForSyncSignin() {
529 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
530 if (command_line->HasSwitch(
531 password_manager::switches::kDisableManagerForSyncSignin))
532 return false;
534 if (command_line->HasSwitch(
535 password_manager::switches::kEnableManagerForSyncSignin))
536 return true;
538 // Default is enabled.
539 std::string group_name =
540 base::FieldTrialList::FindFullName("PasswordManagerStateForSyncSignin");
541 return group_name != "Disabled";
544 const GURL& ChromePasswordManagerClient::GetMainFrameURL() const {
545 return web_contents()->GetVisibleURL();
548 const GURL& ChromePasswordManagerClient::GetLastCommittedEntryURL() const {
549 DCHECK(web_contents());
550 content::NavigationEntry* entry =
551 web_contents()->GetController().GetLastCommittedEntry();
552 if (!entry)
553 return GURL::EmptyGURL();
555 return entry->GetURL();
558 scoped_ptr<password_manager::CredentialsFilter>
559 ChromePasswordManagerClient::CreateStoreResultFilter() const {
560 return make_scoped_ptr(new password_manager::SyncStoreResultFilter(this));