| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" | 5 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 const std::vector<std::unique_ptr<autofill::PasswordForm>>& forms) { | 54 const std::vector<std::unique_ptr<autofill::PasswordForm>>& forms) { |
| 55 std::vector<autofill::PasswordForm> result; | 55 std::vector<autofill::PasswordForm> result; |
| 56 result.reserve(forms.size()); | 56 result.reserve(forms.size()); |
| 57 std::transform(forms.begin(), forms.end(), std::back_inserter(result), | 57 std::transform(forms.begin(), forms.end(), std::back_inserter(result), |
| 58 [](const std::unique_ptr<autofill::PasswordForm>& form) { | 58 [](const std::unique_ptr<autofill::PasswordForm>& form) { |
| 59 return *form; | 59 return *form; |
| 60 }); | 60 }); |
| 61 return result; | 61 return result; |
| 62 } | 62 } |
| 63 | 63 |
| 64 bool IsSmartLockUser(Profile* profile) { | 64 password_bubble_experiment::SmartLockBranding GetSmartLockBrandingState( |
| 65 Profile* profile) { |
| 65 const browser_sync::ProfileSyncService* sync_service = | 66 const browser_sync::ProfileSyncService* sync_service = |
| 66 ProfileSyncServiceFactory::GetForProfile(profile); | 67 ProfileSyncServiceFactory::GetForProfile(profile); |
| 67 return password_bubble_experiment::IsSmartLockUser(sync_service); | 68 return password_bubble_experiment::GetSmartLockBrandingState(sync_service); |
| 68 } | 69 } |
| 69 | 70 |
| 70 } // namespace | 71 } // namespace |
| 71 | 72 |
| 72 // Class responsible for collecting and reporting all the runtime interactions | 73 // Class responsible for collecting and reporting all the runtime interactions |
| 73 // with the bubble. | 74 // with the bubble. |
| 74 class ManagePasswordsBubbleModel::InteractionKeeper { | 75 class ManagePasswordsBubbleModel::InteractionKeeper { |
| 75 public: | 76 public: |
| 76 InteractionKeeper( | 77 InteractionKeeper( |
| 77 password_manager::InteractionsStats stats, | 78 password_manager::InteractionsStats stats, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 sign_in_promo_dismissal_reason_(metrics_util::CHROME_SIGNIN_DISMISSED), | 144 sign_in_promo_dismissal_reason_(metrics_util::CHROME_SIGNIN_DISMISSED), |
| 144 interaction_stats_(std::move(stats)), | 145 interaction_stats_(std::move(stats)), |
| 145 clock_(new base::DefaultClock), | 146 clock_(new base::DefaultClock), |
| 146 sign_in_promo_shown_count(0) {} | 147 sign_in_promo_shown_count(0) {} |
| 147 | 148 |
| 148 void ManagePasswordsBubbleModel::InteractionKeeper::ReportInteractions( | 149 void ManagePasswordsBubbleModel::InteractionKeeper::ReportInteractions( |
| 149 const ManagePasswordsBubbleModel* model) { | 150 const ManagePasswordsBubbleModel* model) { |
| 150 if (model->state() == password_manager::ui::PENDING_PASSWORD_STATE) { | 151 if (model->state() == password_manager::ui::PENDING_PASSWORD_STATE) { |
| 151 Profile* profile = model->GetProfile(); | 152 Profile* profile = model->GetProfile(); |
| 152 if (profile) { | 153 if (profile) { |
| 154 if (GetSmartLockBrandingState(profile) == |
| 155 password_bubble_experiment::SmartLockBranding::FULL) { |
| 156 password_bubble_experiment::RecordSavePromptFirstRunExperienceWasShown( |
| 157 profile->GetPrefs()); |
| 158 } |
| 153 if (dismissal_reason_ == metrics_util::NO_DIRECT_INTERACTION && | 159 if (dismissal_reason_ == metrics_util::NO_DIRECT_INTERACTION && |
| 154 display_disposition_ == | 160 display_disposition_ == |
| 155 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING) { | 161 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING) { |
| 156 if (interaction_stats_.dismissal_count < | 162 if (interaction_stats_.dismissal_count < |
| 157 std::numeric_limits<decltype( | 163 std::numeric_limits<decltype( |
| 158 interaction_stats_.dismissal_count)>::max()) | 164 interaction_stats_.dismissal_count)>::max()) |
| 159 interaction_stats_.dismissal_count++; | 165 interaction_stats_.dismissal_count++; |
| 160 interaction_stats_.update_time = clock_->Now(); | 166 interaction_stats_.update_time = clock_->Now(); |
| 161 password_manager::PasswordStore* password_store = | 167 password_manager::PasswordStore* password_store = |
| 162 PasswordStoreFactory::GetForProfile( | 168 PasswordStoreFactory::GetForProfile( |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 } else if (state_ == password_manager::ui::MANAGE_STATE) { | 248 } else if (state_ == password_manager::ui::MANAGE_STATE) { |
| 243 local_credentials_ = DeepCopyForms(delegate_->GetCurrentForms()); | 249 local_credentials_ = DeepCopyForms(delegate_->GetCurrentForms()); |
| 244 UpdateManageStateTitle(); | 250 UpdateManageStateTitle(); |
| 245 manage_link_ = | 251 manage_link_ = |
| 246 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK); | 252 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK); |
| 247 } | 253 } |
| 248 | 254 |
| 249 if (state_ == password_manager::ui::CONFIRMATION_STATE) { | 255 if (state_ == password_manager::ui::CONFIRMATION_STATE) { |
| 250 base::string16 save_confirmation_link = | 256 base::string16 save_confirmation_link = |
| 251 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_LINK); | 257 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_LINK); |
| 258 int confirmation_text_id = IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT; |
| 259 if (GetSmartLockBrandingState(GetProfile()) == |
| 260 password_bubble_experiment::SmartLockBranding::FULL) { |
| 261 std::string management_hostname = |
| 262 GURL(password_manager::kPasswordManagerAccountDashboardURL).host(); |
| 263 save_confirmation_link = base::UTF8ToUTF16(management_hostname); |
| 264 confirmation_text_id = |
| 265 IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_SMART_LOCK_TEXT; |
| 266 } |
| 267 |
| 252 size_t offset; | 268 size_t offset; |
| 253 save_confirmation_text_ = | 269 save_confirmation_text_ = |
| 254 l10n_util::GetStringFUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT, | 270 l10n_util::GetStringFUTF16( |
| 255 save_confirmation_link, &offset); | 271 confirmation_text_id, save_confirmation_link, &offset); |
| 256 save_confirmation_link_range_ = | 272 save_confirmation_link_range_ = |
| 257 gfx::Range(offset, offset + save_confirmation_link.length()); | 273 gfx::Range(offset, offset + save_confirmation_link.length()); |
| 258 } | 274 } |
| 259 | 275 |
| 260 password_manager::metrics_util::UIDisplayDisposition display_disposition = | 276 password_manager::metrics_util::UIDisplayDisposition display_disposition = |
| 261 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING; | 277 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING; |
| 262 if (display_reason == USER_ACTION) { | 278 if (display_reason == USER_ACTION) { |
| 263 switch (state_) { | 279 switch (state_) { |
| 264 case password_manager::ui::PENDING_PASSWORD_STATE: | 280 case password_manager::ui::PENDING_PASSWORD_STATE: |
| 265 display_disposition = metrics_util::MANUAL_WITH_PASSWORD_PENDING; | 281 display_disposition = metrics_util::MANUAL_WITH_PASSWORD_PENDING; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 } | 368 } |
| 353 | 369 |
| 354 // TODO(gcasto): Is it worth having this be separate from OnDoneClicked()? | 370 // TODO(gcasto): Is it worth having this be separate from OnDoneClicked()? |
| 355 // User intent is pretty similar in both cases. | 371 // User intent is pretty similar in both cases. |
| 356 void ManagePasswordsBubbleModel::OnOKClicked() { | 372 void ManagePasswordsBubbleModel::OnOKClicked() { |
| 357 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_OK); | 373 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_OK); |
| 358 } | 374 } |
| 359 | 375 |
| 360 void ManagePasswordsBubbleModel::OnManageLinkClicked() { | 376 void ManagePasswordsBubbleModel::OnManageLinkClicked() { |
| 361 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_MANAGE); | 377 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_MANAGE); |
| 362 delegate_->NavigateToPasswordManagerSettingsPage(); | 378 if (GetSmartLockBrandingState(GetProfile()) == |
| 379 password_bubble_experiment::SmartLockBranding::FULL) { |
| 380 delegate_->NavigateToExternalPasswordManager(); |
| 381 } else { |
| 382 delegate_->NavigateToPasswordManagerSettingsPage(); |
| 383 } |
| 363 } | 384 } |
| 364 | 385 |
| 365 void ManagePasswordsBubbleModel::OnBrandLinkClicked() { | 386 void ManagePasswordsBubbleModel::OnBrandLinkClicked() { |
| 366 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_BRAND_NAME); | 387 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_BRAND_NAME); |
| 367 delegate_->NavigateToSmartLockHelpPage(); | 388 delegate_->NavigateToSmartLockHelpPage(); |
| 368 } | 389 } |
| 369 | 390 |
| 370 void ManagePasswordsBubbleModel::OnAutoSignInToastTimeout() { | 391 void ManagePasswordsBubbleModel::OnAutoSignInToastTimeout() { |
| 371 interaction_keeper_->set_dismissal_reason( | 392 interaction_keeper_->set_dismissal_reason( |
| 372 metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT); | 393 metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 | 430 |
| 410 content::WebContents* ManagePasswordsBubbleModel::GetWebContents() const { | 431 content::WebContents* ManagePasswordsBubbleModel::GetWebContents() const { |
| 411 return delegate_ ? delegate_->GetWebContents() : nullptr; | 432 return delegate_ ? delegate_->GetWebContents() : nullptr; |
| 412 } | 433 } |
| 413 | 434 |
| 414 bool ManagePasswordsBubbleModel::ShouldShowMultipleAccountUpdateUI() const { | 435 bool ManagePasswordsBubbleModel::ShouldShowMultipleAccountUpdateUI() const { |
| 415 return state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE && | 436 return state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE && |
| 416 local_credentials_.size() > 1 && !password_overridden_; | 437 local_credentials_.size() > 1 && !password_overridden_; |
| 417 } | 438 } |
| 418 | 439 |
| 440 bool ManagePasswordsBubbleModel::ShouldShowGoogleSmartLockWelcome() const { |
| 441 Profile* profile = GetProfile(); |
| 442 if (GetSmartLockBrandingState(profile) == |
| 443 password_bubble_experiment::SmartLockBranding::FULL) { |
| 444 PrefService* prefs = profile->GetPrefs(); |
| 445 return !prefs->GetBoolean( |
| 446 password_manager::prefs::kWasSavePrompFirstRunExperienceShown); |
| 447 } |
| 448 return false; |
| 449 } |
| 450 |
| 419 bool ManagePasswordsBubbleModel::ReplaceToShowSignInPromoIfNeeded() { | 451 bool ManagePasswordsBubbleModel::ReplaceToShowSignInPromoIfNeeded() { |
| 420 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); | 452 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); |
| 421 PrefService* prefs = GetProfile()->GetPrefs(); | 453 PrefService* prefs = GetProfile()->GetPrefs(); |
| 422 const browser_sync::ProfileSyncService* sync_service = | 454 const browser_sync::ProfileSyncService* sync_service = |
| 423 ProfileSyncServiceFactory::GetForProfile(GetProfile()); | 455 ProfileSyncServiceFactory::GetForProfile(GetProfile()); |
| 424 if (password_bubble_experiment::ShouldShowChromeSignInPasswordPromo( | 456 if (password_bubble_experiment::ShouldShowChromeSignInPasswordPromo( |
| 425 prefs, sync_service)) { | 457 prefs, sync_service)) { |
| 426 interaction_keeper_->ReportInteractions(this); | 458 interaction_keeper_->ReportInteractions(this); |
| 427 title_brand_link_range_ = gfx::Range(); | 459 title_brand_link_range_ = gfx::Range(); |
| 428 title_ = l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SIGNIN_PROMO_TITLE); | 460 title_ = l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SIGNIN_PROMO_TITLE); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 445 | 477 |
| 446 void ManagePasswordsBubbleModel::UpdatePendingStateTitle() { | 478 void ManagePasswordsBubbleModel::UpdatePendingStateTitle() { |
| 447 title_brand_link_range_ = gfx::Range(); | 479 title_brand_link_range_ = gfx::Range(); |
| 448 PasswordTitleType type = | 480 PasswordTitleType type = |
| 449 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE | 481 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE |
| 450 ? PasswordTitleType::UPDATE_PASSWORD | 482 ? PasswordTitleType::UPDATE_PASSWORD |
| 451 : (pending_password_.federation_origin.unique() | 483 : (pending_password_.federation_origin.unique() |
| 452 ? PasswordTitleType::SAVE_PASSWORD | 484 ? PasswordTitleType::SAVE_PASSWORD |
| 453 : PasswordTitleType::SAVE_ACCOUNT); | 485 : PasswordTitleType::SAVE_ACCOUNT); |
| 454 GetSavePasswordDialogTitleTextAndLinkRange( | 486 GetSavePasswordDialogTitleTextAndLinkRange( |
| 455 GetWebContents()->GetVisibleURL(), origin_, IsSmartLockUser(GetProfile()), | 487 GetWebContents()->GetVisibleURL(), origin_, |
| 488 GetSmartLockBrandingState(GetProfile()) != |
| 489 password_bubble_experiment::SmartLockBranding::NONE, |
| 456 type, &title_, &title_brand_link_range_); | 490 type, &title_, &title_brand_link_range_); |
| 457 } | 491 } |
| 458 | 492 |
| 459 void ManagePasswordsBubbleModel::UpdateManageStateTitle() { | 493 void ManagePasswordsBubbleModel::UpdateManageStateTitle() { |
| 460 GetManagePasswordsDialogTitleText(GetWebContents()->GetVisibleURL(), origin_, | 494 GetManagePasswordsDialogTitleText(GetWebContents()->GetVisibleURL(), origin_, |
| 461 &title_); | 495 &title_); |
| 462 } | 496 } |
| 463 | 497 |
| 464 metrics_util::UpdatePasswordSubmissionEvent | 498 metrics_util::UpdatePasswordSubmissionEvent |
| 465 ManagePasswordsBubbleModel::GetUpdateDismissalReason( | 499 ManagePasswordsBubbleModel::GetUpdateDismissalReason( |
| (...skipping 18 matching lines...) Expand all Loading... |
| 484 return metrics_util::NO_UPDATE_SUBMISSION; | 518 return metrics_util::NO_UPDATE_SUBMISSION; |
| 485 } | 519 } |
| 486 if (state_ != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) | 520 if (state_ != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) |
| 487 return metrics_util::NO_UPDATE_SUBMISSION; | 521 return metrics_util::NO_UPDATE_SUBMISSION; |
| 488 if (password_overridden_) | 522 if (password_overridden_) |
| 489 return update_events[3][behavior]; | 523 return update_events[3][behavior]; |
| 490 if (ShouldShowMultipleAccountUpdateUI()) | 524 if (ShouldShowMultipleAccountUpdateUI()) |
| 491 return update_events[2][behavior]; | 525 return update_events[2][behavior]; |
| 492 return update_events[1][behavior]; | 526 return update_events[1][behavior]; |
| 493 } | 527 } |
| OLD | NEW |