Add more checks to investigate SupervisedUserPrefStore crash at startup.
[chromium-blink-merge.git] / chrome / browser / password_manager / chrome_password_manager_client.cc
blob6c58631126f5e102896147af30cb96c5a5eb50bc
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/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/browsing_data/browsing_data_helper.h"
14 #include "chrome/browser/password_manager/password_manager_util.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/chrome_switches.h"
24 #include "chrome/common/chrome_version_info.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/content/common/credential_manager_types.h"
35 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
36 #include "components/password_manager/core/browser/log_receiver.h"
37 #include "components/password_manager/core/browser/password_form_manager.h"
38 #include "components/password_manager/core/browser/password_manager_internals_service.h"
39 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
40 #include "components/password_manager/core/browser/password_manager_url_collection_experiment.h"
41 #include "components/password_manager/core/common/password_manager_switches.h"
42 #include "content/public/browser/navigation_entry.h"
43 #include "content/public/browser/render_view_host.h"
44 #include "content/public/browser/web_contents.h"
45 #include "google_apis/gaia/gaia_urls.h"
46 #include "net/base/url_util.h"
47 #include "third_party/re2/re2/re2.h"
49 #if defined(OS_ANDROID)
50 #include "chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.h"
51 #endif
53 using password_manager::ContentPasswordManagerDriverFactory;
54 using password_manager::PasswordManagerInternalsService;
55 using password_manager::PasswordManagerInternalsServiceFactory;
57 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromePasswordManagerClient);
59 // Shorten the name to spare line breaks. The code provides enough context
60 // already.
61 typedef autofill::SavePasswordProgressLogger Logger;
63 // static
64 void ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
65 content::WebContents* contents,
66 autofill::AutofillClient* autofill_client) {
67 if (FromWebContents(contents))
68 return;
70 contents->SetUserData(
71 UserDataKey(),
72 new ChromePasswordManagerClient(contents, autofill_client));
75 ChromePasswordManagerClient::ChromePasswordManagerClient(
76 content::WebContents* web_contents,
77 autofill::AutofillClient* autofill_client)
78 : content::WebContentsObserver(web_contents),
79 profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
80 password_manager_(this),
81 driver_factory_(nullptr),
82 credential_manager_dispatcher_(web_contents, this),
83 observer_(nullptr),
84 can_use_log_router_(false),
85 autofill_sync_state_(ALLOW_SYNC_CREDENTIALS),
86 sync_credential_was_filtered_(false) {
87 ContentPasswordManagerDriverFactory::CreateForWebContents(web_contents, this,
88 autofill_client);
89 driver_factory_ =
90 ContentPasswordManagerDriverFactory::FromWebContents(web_contents);
92 PasswordManagerInternalsService* service =
93 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
94 if (service)
95 can_use_log_router_ = service->RegisterClient(this);
96 SetUpAutofillSyncState();
99 ChromePasswordManagerClient::~ChromePasswordManagerClient() {
100 PasswordManagerInternalsService* service =
101 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
102 if (service)
103 service->UnregisterClient(this);
106 bool ChromePasswordManagerClient::IsAutomaticPasswordSavingEnabled() const {
107 return base::CommandLine::ForCurrentProcess()->HasSwitch(
108 password_manager::switches::kEnableAutomaticPasswordSaving) &&
109 chrome::VersionInfo::GetChannel() ==
110 chrome::VersionInfo::CHANNEL_UNKNOWN;
113 bool ChromePasswordManagerClient::IsPasswordManagerEnabledForCurrentPage()
114 const {
115 DCHECK(web_contents());
116 content::NavigationEntry* entry =
117 web_contents()->GetController().GetLastCommittedEntry();
118 if (!entry) {
119 // TODO(gcasto): Determine if fix for crbug.com/388246 is relevant here.
120 return true;
123 // Disable the password manager for online password management.
124 if (IsURLPasswordWebsiteReauth(entry->GetURL()))
125 return false;
127 if (EnabledForSyncSignin())
128 return true;
130 // Do not fill nor save password when a user is signing in for sync. This
131 // is because users need to remember their password if they are syncing as
132 // this is effectively their master password.
133 return entry->GetURL().host() != chrome::kChromeUIChromeSigninHost;
136 bool ChromePasswordManagerClient::ShouldAskUserToSubmitURL(const GURL& url) {
137 return url.is_valid() && !url.is_empty() && url.has_host() &&
138 password_manager_.IsSavingEnabledForCurrentPage() &&
139 password_manager::urls_collection_experiment::ShouldShowBubble(
140 GetPrefs());
143 bool ChromePasswordManagerClient::ShouldFilterAutofillResult(
144 const autofill::PasswordForm& form) {
145 if (!IsSyncAccountCredential(base::UTF16ToUTF8(form.username_value),
146 form.signon_realm))
147 return false;
149 if (autofill_sync_state_ == DISALLOW_SYNC_CREDENTIALS) {
150 sync_credential_was_filtered_ = true;
151 return true;
154 if (autofill_sync_state_ == DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH &&
155 LastLoadWasTransactionalReauthPage()) {
156 sync_credential_was_filtered_ = true;
157 return true;
160 return false;
163 std::string ChromePasswordManagerClient::GetSyncUsername() const {
164 return password_manager_sync_metrics::GetSyncUsername(profile_);
167 bool ChromePasswordManagerClient::IsSyncAccountCredential(
168 const std::string& username, const std::string& origin) const {
169 return password_manager_sync_metrics::IsSyncAccountCredential(
170 profile_, username, origin);
173 void ChromePasswordManagerClient::AskUserAndMaybeReportURL(
174 const GURL& url) const {
175 ManagePasswordsUIController* manage_passwords_ui_controller =
176 ManagePasswordsUIController::FromWebContents(web_contents());
177 manage_passwords_ui_controller->OnAskToReportURL(url);
180 void ChromePasswordManagerClient::AutofillResultsComputed() {
181 UMA_HISTOGRAM_BOOLEAN("PasswordManager.SyncCredentialFiltered",
182 sync_credential_was_filtered_);
183 sync_credential_was_filtered_ = false;
186 bool ChromePasswordManagerClient::PromptUserToSavePassword(
187 scoped_ptr<password_manager::PasswordFormManager> form_to_save,
188 password_manager::CredentialSourceType type) {
189 // Save password infobar and the password bubble prompts in case of
190 // "webby" URLs and do not prompt in case of "non-webby" URLS (e.g. file://).
191 if (!BrowsingDataHelper::IsWebScheme(
192 web_contents()->GetLastCommittedURL().scheme())) {
193 return false;
196 if (IsTheHotNewBubbleUIEnabled()) {
197 ManagePasswordsUIController* manage_passwords_ui_controller =
198 ManagePasswordsUIController::FromWebContents(web_contents());
199 manage_passwords_ui_controller->OnPasswordSubmitted(form_to_save.Pass());
200 } else {
201 // TODO(melandory): If type is CREDENTIAL_SOURCE_API then new bubble should
202 // be shown.
203 std::string uma_histogram_suffix(
204 password_manager::metrics_util::GroupIdToString(
205 password_manager::metrics_util::MonitoredDomainGroupId(
206 form_to_save->realm(), GetPrefs())));
207 SavePasswordInfoBarDelegate::Create(
208 web_contents(), form_to_save.Pass(), uma_histogram_suffix);
210 return true;
213 bool ChromePasswordManagerClient::PromptUserToChooseCredentials(
214 ScopedVector<autofill::PasswordForm> local_forms,
215 ScopedVector<autofill::PasswordForm> federated_forms,
216 const GURL& origin,
217 base::Callback<void(const password_manager::CredentialInfo&)> callback) {
218 return ManagePasswordsUIController::FromWebContents(web_contents())->
219 OnChooseCredentials(local_forms.Pass(), federated_forms.Pass(), origin,
220 callback);
223 void ChromePasswordManagerClient::NotifyUserAutoSignin(
224 ScopedVector<autofill::PasswordForm> local_forms) {
225 DCHECK(!local_forms.empty());
226 ManagePasswordsUIController::FromWebContents(web_contents())->
227 OnAutoSignin(local_forms.Pass());
230 void ChromePasswordManagerClient::AutomaticPasswordSave(
231 scoped_ptr<password_manager::PasswordFormManager> saved_form) {
232 #if defined(OS_ANDROID)
233 GeneratedPasswordSavedInfoBarDelegateAndroid::Create(web_contents());
234 #else
235 if (IsTheHotNewBubbleUIEnabled()) {
236 ManagePasswordsUIController* manage_passwords_ui_controller =
237 ManagePasswordsUIController::FromWebContents(web_contents());
238 manage_passwords_ui_controller->OnAutomaticPasswordSave(
239 saved_form.Pass());
241 #endif
244 void ChromePasswordManagerClient::PasswordWasAutofilled(
245 const autofill::PasswordFormMap& best_matches) const {
246 ManagePasswordsUIController* manage_passwords_ui_controller =
247 ManagePasswordsUIController::FromWebContents(web_contents());
248 if (manage_passwords_ui_controller && IsTheHotNewBubbleUIEnabled())
249 manage_passwords_ui_controller->OnPasswordAutofilled(best_matches);
252 void ChromePasswordManagerClient::PasswordAutofillWasBlocked(
253 const autofill::PasswordFormMap& best_matches) const {
254 ManagePasswordsUIController* controller =
255 ManagePasswordsUIController::FromWebContents(web_contents());
256 if (controller && IsTheHotNewBubbleUIEnabled())
257 controller->OnBlacklistBlockedAutofill(best_matches);
260 void ChromePasswordManagerClient::HidePasswordGenerationPopup() {
261 if (popup_controller_)
262 popup_controller_->HideAndDestroy();
265 PrefService* ChromePasswordManagerClient::GetPrefs() {
266 return profile_->GetPrefs();
269 password_manager::PasswordStore*
270 ChromePasswordManagerClient::GetPasswordStore() const {
271 // Always use EXPLICIT_ACCESS as the password manager checks IsOffTheRecord
272 // itself when it shouldn't access the PasswordStore.
273 // TODO(gcasto): Is is safe to change this to
274 // ServiceAccessType::IMPLICIT_ACCESS?
275 return PasswordStoreFactory::GetForProfile(
276 profile_, ServiceAccessType::EXPLICIT_ACCESS).get();
279 base::FieldTrial::Probability
280 ChromePasswordManagerClient::GetProbabilityForExperiment(
281 const std::string& experiment_name) const {
282 base::FieldTrial::Probability enabled_probability = 0;
283 if (experiment_name ==
284 password_manager::PasswordManager::kOtherPossibleUsernamesExperiment) {
285 switch (chrome::VersionInfo::GetChannel()) {
286 case chrome::VersionInfo::CHANNEL_DEV:
287 case chrome::VersionInfo::CHANNEL_BETA:
288 enabled_probability = 50;
289 break;
290 default:
291 break;
294 return enabled_probability;
297 bool ChromePasswordManagerClient::IsPasswordSyncEnabled(
298 password_manager::CustomPassphraseState state) const {
299 ProfileSyncService* sync_service =
300 ProfileSyncServiceFactory::GetForProfile(profile_);
301 if (sync_service && sync_service->HasSyncSetupCompleted() &&
302 sync_service->SyncActive() &&
303 sync_service->GetActiveDataTypes().Has(syncer::PASSWORDS)) {
304 if (sync_service->IsUsingSecondaryPassphrase()) {
305 return state == password_manager::ONLY_CUSTOM_PASSPHRASE;
306 } else {
307 return state == password_manager::WITHOUT_CUSTOM_PASSPHRASE;
310 return false;
313 void ChromePasswordManagerClient::OnLogRouterAvailabilityChanged(
314 bool router_can_be_used) {
315 if (can_use_log_router_ == router_can_be_used)
316 return;
317 can_use_log_router_ = router_can_be_used;
319 NotifyRendererOfLoggingAvailability();
322 void ChromePasswordManagerClient::LogSavePasswordProgress(
323 const std::string& text) const {
324 if (!IsLoggingActive())
325 return;
326 PasswordManagerInternalsService* service =
327 PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
328 if (service)
329 service->ProcessLog(text);
332 bool ChromePasswordManagerClient::IsLoggingActive() const {
333 // WebUI tabs do not need to log password saving progress. In particular, the
334 // internals page itself should not send any logs.
335 return can_use_log_router_ && !web_contents()->GetWebUI();
338 bool ChromePasswordManagerClient::WasLastNavigationHTTPError() const {
339 DCHECK(web_contents());
341 scoped_ptr<password_manager::BrowserSavePasswordProgressLogger> logger;
342 if (IsLoggingActive()) {
343 logger.reset(new password_manager::BrowserSavePasswordProgressLogger(this));
344 logger->LogMessage(
345 Logger::STRING_WAS_LAST_NAVIGATION_HTTP_ERROR_METHOD);
348 content::NavigationEntry* entry =
349 web_contents()->GetController().GetVisibleEntry();
350 if (!entry)
351 return false;
352 int http_status_code = entry->GetHttpStatusCode();
354 if (logger)
355 logger->LogNumber(Logger::STRING_HTTP_STATUS_CODE, http_status_code);
357 if (http_status_code >= 400 && http_status_code < 600)
358 return true;
359 return false;
362 bool ChromePasswordManagerClient::DidLastPageLoadEncounterSSLErrors() const {
363 content::NavigationEntry* entry =
364 web_contents()->GetController().GetLastCommittedEntry();
365 if (!entry)
366 return false;
368 return net::IsCertStatusError(entry->GetSSL().cert_status);
371 bool ChromePasswordManagerClient::IsOffTheRecord() const {
372 return web_contents()->GetBrowserContext()->IsOffTheRecord();
375 password_manager::PasswordManager*
376 ChromePasswordManagerClient::GetPasswordManager() {
377 return &password_manager_;
380 autofill::AutofillManager*
381 ChromePasswordManagerClient::GetAutofillManagerForMainFrame() {
382 autofill::ContentAutofillDriverFactory* factory =
383 autofill::ContentAutofillDriverFactory::FromWebContents(web_contents());
384 return factory
385 ? factory->DriverForFrame(web_contents()->GetMainFrame())
386 ->autofill_manager()
387 : nullptr;
390 void ChromePasswordManagerClient::SetTestObserver(
391 autofill::PasswordGenerationPopupObserver* observer) {
392 observer_ = observer;
395 bool ChromePasswordManagerClient::OnMessageReceived(
396 const IPC::Message& message,
397 content::RenderFrameHost* render_frame_host) {
398 bool handled = true;
399 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ChromePasswordManagerClient, message,
400 render_frame_host)
401 // Autofill messages:
402 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
403 ShowPasswordGenerationPopup)
404 IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordEditingPopup,
405 ShowPasswordEditingPopup)
406 IPC_END_MESSAGE_MAP()
408 IPC_BEGIN_MESSAGE_MAP(ChromePasswordManagerClient, message)
409 IPC_MESSAGE_HANDLER(AutofillHostMsg_HidePasswordGenerationPopup,
410 HidePasswordGenerationPopup)
411 IPC_MESSAGE_HANDLER(AutofillHostMsg_PasswordAutofillAgentConstructed,
412 NotifyRendererOfLoggingAvailability)
413 // Default:
414 IPC_MESSAGE_UNHANDLED(handled = false)
415 IPC_END_MESSAGE_MAP()
417 return handled;
420 gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace(
421 const gfx::RectF& bounds) {
422 gfx::Rect client_area = web_contents()->GetContainerBounds();
423 return bounds + client_area.OffsetFromOrigin();
426 void ChromePasswordManagerClient::ShowPasswordGenerationPopup(
427 content::RenderFrameHost* render_frame_host,
428 const gfx::RectF& bounds,
429 int max_length,
430 const autofill::PasswordForm& form) {
431 // TODO(gcasto): Validate data in PasswordForm.
433 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
435 popup_controller_ =
436 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
437 popup_controller_, element_bounds_in_screen_space, form, max_length,
438 &password_manager_,
439 driver_factory_->GetDriverForFrame(render_frame_host), observer_,
440 web_contents(), web_contents()->GetNativeView());
441 popup_controller_->Show(true /* display_password */);
444 void ChromePasswordManagerClient::ShowPasswordEditingPopup(
445 content::RenderFrameHost* render_frame_host,
446 const gfx::RectF& bounds,
447 const autofill::PasswordForm& form) {
448 gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
449 popup_controller_ =
450 autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
451 popup_controller_, element_bounds_in_screen_space, form,
452 0, // Unspecified max length.
453 &password_manager_,
454 driver_factory_->GetDriverForFrame(render_frame_host), observer_,
455 web_contents(), web_contents()->GetNativeView());
456 popup_controller_->Show(false /* display_password */);
459 void ChromePasswordManagerClient::NotifyRendererOfLoggingAvailability() {
460 if (!web_contents())
461 return;
463 web_contents()->GetRenderViewHost()->Send(new AutofillMsg_SetLoggingState(
464 web_contents()->GetRenderViewHost()->GetRoutingID(),
465 can_use_log_router_));
468 bool ChromePasswordManagerClient::LastLoadWasTransactionalReauthPage() const {
469 DCHECK(web_contents());
470 content::NavigationEntry* entry =
471 web_contents()->GetController().GetLastCommittedEntry();
472 if (!entry)
473 return false;
475 if (entry->GetURL().GetOrigin() !=
476 GaiaUrls::GetInstance()->gaia_url().GetOrigin())
477 return false;
479 // "rart" is the transactional reauth paramter.
480 std::string ignored_value;
481 return net::GetValueForKeyInQuery(entry->GetURL(),
482 "rart",
483 &ignored_value);
486 bool ChromePasswordManagerClient::IsURLPasswordWebsiteReauth(
487 const GURL& url) const {
488 if (url.GetOrigin() != GaiaUrls::GetInstance()->gaia_url().GetOrigin())
489 return false;
491 // "rart" param signals this page is for transactional reauth.
492 std::string param_value;
493 if (!net::GetValueForKeyInQuery(url, "rart", &param_value))
494 return false;
496 // Check the "continue" param to see if this reauth page is for the passwords
497 // website.
498 param_value.clear();
499 if (!net::GetValueForKeyInQuery(url, "continue", &param_value))
500 return false;
502 // All password sites, including test sites, have autofilling disabled.
503 CR_DEFINE_STATIC_LOCAL(RE2, account_dashboard_pattern,
504 ("passwords(-([a-z-]+\\.corp))?\\.google\\.com"));
506 return RE2::FullMatch(GURL(param_value).host(), account_dashboard_pattern);
509 bool ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled() {
510 #if !defined(USE_AURA) && !defined(OS_MACOSX)
511 return false;
512 #endif
513 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
514 if (command_line->HasSwitch(switches::kDisableSavePasswordBubble))
515 return false;
517 if (command_line->HasSwitch(switches::kEnableSavePasswordBubble))
518 return true;
520 std::string group_name =
521 base::FieldTrialList::FindFullName("PasswordManagerUI");
523 // The bubble should be the default case that runs on the bots.
524 return group_name != "Infobar";
527 bool ChromePasswordManagerClient::EnabledForSyncSignin() {
528 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
529 if (command_line->HasSwitch(
530 password_manager::switches::kDisableManagerForSyncSignin))
531 return false;
533 if (command_line->HasSwitch(
534 password_manager::switches::kEnableManagerForSyncSignin))
535 return true;
537 // Default is enabled.
538 std::string group_name =
539 base::FieldTrialList::FindFullName("PasswordManagerStateForSyncSignin");
540 return group_name != "Disabled";
543 void ChromePasswordManagerClient::SetUpAutofillSyncState() {
544 std::string group_name =
545 base::FieldTrialList::FindFullName("AutofillSyncCredential");
547 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
548 if (command_line->HasSwitch(
549 password_manager::switches::kAllowAutofillSyncCredential)) {
550 autofill_sync_state_ = ALLOW_SYNC_CREDENTIALS;
551 return;
553 if (command_line->HasSwitch(
554 password_manager::switches::
555 kDisallowAutofillSyncCredentialForReauth)) {
556 autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH;
557 return;
559 if (command_line->HasSwitch(
560 password_manager::switches::kDisallowAutofillSyncCredential)) {
561 autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS;
562 return;
565 if (group_name == "DisallowSyncCredentialsForReauth") {
566 autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH;
567 } else if (group_name == "DisallowSyncCredentials") {
568 autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS;
569 } else {
570 // Allow by default.
571 autofill_sync_state_ = ALLOW_SYNC_CREDENTIALS;
575 const GURL& ChromePasswordManagerClient::GetMainFrameURL() const {
576 return web_contents()->GetVisibleURL();