Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(436)

Side by Side Diff: chrome/browser/ui/passwords/manage_passwords_bubble_model.cc

Issue 2036323002: Implement the UI logic behind the Sign In promo in the password bubble (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
11 #include <string> 11 #include <string>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
15 #include "base/time/default_clock.h" 16 #include "base/time/default_clock.h"
16 #include "chrome/browser/password_manager/password_store_factory.h" 17 #include "chrome/browser/password_manager/password_store_factory.h"
17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/sync/profile_sync_service_factory.h" 19 #include "chrome/browser/sync/profile_sync_service_factory.h"
19 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" 20 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
20 #include "chrome/browser/ui/passwords/passwords_model_delegate.h" 21 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
21 #include "chrome/grit/chromium_strings.h" 22 #include "chrome/grit/chromium_strings.h"
22 #include "chrome/grit/generated_resources.h" 23 #include "chrome/grit/generated_resources.h"
23 #include "components/browser_sync/browser/profile_sync_service.h" 24 #include "components/browser_sync/browser/profile_sync_service.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 void set_dismissal_reason( 90 void set_dismissal_reason(
90 password_manager::metrics_util::UIDismissalReason reason) { 91 password_manager::metrics_util::UIDismissalReason reason) {
91 dismissal_reason_ = reason; 92 dismissal_reason_ = reason;
92 } 93 }
93 94
94 void set_update_password_submission_event( 95 void set_update_password_submission_event(
95 password_manager::metrics_util::UpdatePasswordSubmissionEvent event) { 96 password_manager::metrics_util::UpdatePasswordSubmissionEvent event) {
96 update_password_submission_event_ = event; 97 update_password_submission_event_ = event;
97 } 98 }
98 99
100 void set_sign_in_promo_dismissal_reason(
101 password_manager::metrics_util::SyncSignInUserAction reason) {
102 sign_in_promo_dismissal_reason_ = reason;
103 }
104
99 void SetClockForTesting(std::unique_ptr<base::Clock> clock) { 105 void SetClockForTesting(std::unique_ptr<base::Clock> clock) {
100 clock_ = std::move(clock); 106 clock_ = std::move(clock);
101 } 107 }
102 108
103 private: 109 private:
104 // The way the bubble appeared. 110 // The way the bubble appeared.
105 const password_manager::metrics_util::UIDisplayDisposition 111 const password_manager::metrics_util::UIDisplayDisposition
106 display_disposition_; 112 display_disposition_;
107 113
108 // Dismissal reason for a bubble. 114 // Dismissal reason for a bubble.
109 password_manager::metrics_util::UIDismissalReason dismissal_reason_; 115 password_manager::metrics_util::UIDismissalReason dismissal_reason_;
110 116
111 // Dismissal reason for the update bubble. 117 // Dismissal reason for the update bubble.
112 password_manager::metrics_util::UpdatePasswordSubmissionEvent 118 password_manager::metrics_util::UpdatePasswordSubmissionEvent
113 update_password_submission_event_; 119 update_password_submission_event_;
114 120
121 // Dismissal reason for the Chrome Sign in bubble.
122 password_manager::metrics_util::SyncSignInUserAction
123 sign_in_promo_dismissal_reason_;
124
115 // Current statistics for the save password bubble; 125 // Current statistics for the save password bubble;
116 password_manager::InteractionsStats interaction_stats_; 126 password_manager::InteractionsStats interaction_stats_;
117 127
118 // Used to retrieve the current time, in base::Time units. 128 // Used to retrieve the current time, in base::Time units.
119 std::unique_ptr<base::Clock> clock_; 129 std::unique_ptr<base::Clock> clock_;
120 130
121 DISALLOW_COPY_AND_ASSIGN(InteractionKeeper); 131 DISALLOW_COPY_AND_ASSIGN(InteractionKeeper);
122 }; 132 };
123 133
124 ManagePasswordsBubbleModel::InteractionKeeper::InteractionKeeper( 134 ManagePasswordsBubbleModel::InteractionKeeper::InteractionKeeper(
125 password_manager::InteractionsStats stats, 135 password_manager::InteractionsStats stats,
126 password_manager::metrics_util::UIDisplayDisposition display_disposition) 136 password_manager::metrics_util::UIDisplayDisposition display_disposition)
127 : display_disposition_(display_disposition), 137 : display_disposition_(display_disposition),
128 dismissal_reason_(metrics_util::NO_DIRECT_INTERACTION), 138 dismissal_reason_(metrics_util::NO_DIRECT_INTERACTION),
129 update_password_submission_event_(metrics_util::NO_UPDATE_SUBMISSION), 139 update_password_submission_event_(metrics_util::NO_UPDATE_SUBMISSION),
140 sign_in_promo_dismissal_reason_(metrics_util::CHROME_SIGNIN_DISMISSED),
130 interaction_stats_(std::move(stats)), 141 interaction_stats_(std::move(stats)),
131 clock_(new base::DefaultClock) { 142 clock_(new base::DefaultClock) {}
132 }
133 143
134 void ManagePasswordsBubbleModel::InteractionKeeper::ReportInteractions( 144 void ManagePasswordsBubbleModel::InteractionKeeper::ReportInteractions(
135 const ManagePasswordsBubbleModel* model) { 145 const ManagePasswordsBubbleModel* model) {
136 if (model->state() == password_manager::ui::PENDING_PASSWORD_STATE) { 146 if (model->state() == password_manager::ui::PENDING_PASSWORD_STATE) {
137 Profile* profile = model->GetProfile(); 147 Profile* profile = model->GetProfile();
138 if (profile) { 148 if (profile) {
139 if (GetSmartLockBrandingState(profile) == 149 if (GetSmartLockBrandingState(profile) ==
140 password_bubble_experiment::SmartLockBranding::FULL) { 150 password_bubble_experiment::SmartLockBranding::FULL) {
141 password_bubble_experiment::RecordSavePromptFirstRunExperienceWasShown( 151 password_bubble_experiment::RecordSavePromptFirstRunExperienceWasShown(
142 profile->GetPrefs()); 152 profile->GetPrefs());
143 } 153 }
144 if (dismissal_reason_ == metrics_util::NO_DIRECT_INTERACTION && 154 if (dismissal_reason_ == metrics_util::NO_DIRECT_INTERACTION &&
145 display_disposition_ == 155 display_disposition_ ==
146 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING) { 156 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING) {
147 if (interaction_stats_.dismissal_count < 157 if (interaction_stats_.dismissal_count <
148 std::numeric_limits<decltype( 158 std::numeric_limits<decltype(
149 interaction_stats_.dismissal_count)>::max()) 159 interaction_stats_.dismissal_count)>::max())
150 interaction_stats_.dismissal_count++; 160 interaction_stats_.dismissal_count++;
151 interaction_stats_.update_time = clock_->Now(); 161 interaction_stats_.update_time = clock_->Now();
152 password_manager::PasswordStore* password_store = 162 password_manager::PasswordStore* password_store =
153 PasswordStoreFactory::GetForProfile( 163 PasswordStoreFactory::GetForProfile(
154 profile, ServiceAccessType::IMPLICIT_ACCESS).get(); 164 profile, ServiceAccessType::IMPLICIT_ACCESS).get();
155 password_store->AddSiteStats(interaction_stats_); 165 password_store->AddSiteStats(interaction_stats_);
156 } 166 }
157 } 167 }
158 } 168 }
159 169
160 if (model->state() != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { 170 if (model->state() == password_manager::ui::CHROME_SIGN_IN_PROMO_STATE) {
171 metrics_util::LogAutoSigninPromoUserAction(sign_in_promo_dismissal_reason_);
172 if (sign_in_promo_dismissal_reason_ ==
173 password_manager::metrics_util::CHROME_SIGNIN_OK ||
174 sign_in_promo_dismissal_reason_ ==
175 password_manager::metrics_util::CHROME_SIGNIN_CANCEL) {
176 DCHECK(model->web_contents());
177 int show_count = model->GetProfile()->GetPrefs()->GetInteger(
178 password_manager::prefs::kNumberSignInPasswordPromoShown);
179 UMA_HISTOGRAM_COUNTS_100("PasswordManager.SignInPromoCountTilClick",
180 show_count);
181 }
182 } else if (model->state() !=
183 password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) {
161 // We have separate metrics for the Update bubble so do not record dismissal 184 // We have separate metrics for the Update bubble so do not record dismissal
162 // reason for it. 185 // reason for it.
163 metrics_util::LogUIDismissalReason(dismissal_reason_); 186 metrics_util::LogUIDismissalReason(dismissal_reason_);
164 } 187 }
165 188
166 PasswordsModelDelegate* delegate = model->web_contents() 189 if (model->state() == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE ||
167 ? PasswordsModelDelegateFromWebContents(model->web_contents()) 190 model->state() == password_manager::ui::PENDING_PASSWORD_STATE) {
168 : nullptr; 191 if (update_password_submission_event_ ==
169 // Check if this was update password and record update statistics. 192 metrics_util::NO_UPDATE_SUBMISSION) {
170 if (update_password_submission_event_ == metrics_util::NO_UPDATE_SUBMISSION && 193 update_password_submission_event_ =
171 (model->state() == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE || 194 model->GetUpdateDismissalReason(NO_INTERACTION);
172 model->state() == password_manager::ui::PENDING_PASSWORD_STATE)) { 195 PasswordsModelDelegate* delegate =
173 update_password_submission_event_ = 196 model->web_contents()
174 model->GetUpdateDismissalReason(NO_INTERACTION); 197 ? PasswordsModelDelegateFromWebContents(model->web_contents())
175 if (model->state() == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE && 198 : nullptr;
176 delegate) 199 if (delegate &&
177 delegate->OnNoInteractionOnUpdate(); 200 model->state() == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE)
201 delegate->OnNoInteractionOnUpdate();
202 }
203
204 if (update_password_submission_event_ != metrics_util::NO_UPDATE_SUBMISSION)
205 LogUpdatePasswordSubmissionEvent(update_password_submission_event_);
178 } 206 }
179 if (update_password_submission_event_ != metrics_util::NO_UPDATE_SUBMISSION)
180 LogUpdatePasswordSubmissionEvent(update_password_submission_event_);
181 } 207 }
182 208
183 ManagePasswordsBubbleModel::ManagePasswordsBubbleModel( 209 ManagePasswordsBubbleModel::ManagePasswordsBubbleModel(
184 content::WebContents* web_contents, 210 content::WebContents* web_contents,
185 DisplayReason display_reason) 211 DisplayReason display_reason)
186 : content::WebContentsObserver(web_contents), 212 : content::WebContentsObserver(web_contents),
187 password_overridden_(false) { 213 password_overridden_(false) {
188 PasswordsModelDelegate* delegate = 214 PasswordsModelDelegate* delegate =
189 PasswordsModelDelegateFromWebContents(web_contents); 215 PasswordsModelDelegateFromWebContents(web_contents);
190 216
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 PasswordStoreFactory::GetForProfile( 415 PasswordStoreFactory::GetForProfile(
390 profile, ServiceAccessType::EXPLICIT_ACCESS).get(); 416 profile, ServiceAccessType::EXPLICIT_ACCESS).get();
391 DCHECK(password_store); 417 DCHECK(password_store);
392 if (action == REMOVE_PASSWORD) 418 if (action == REMOVE_PASSWORD)
393 password_store->RemoveLogin(password_form); 419 password_store->RemoveLogin(password_form);
394 else 420 else
395 password_store->AddLogin(password_form); 421 password_store->AddLogin(password_form);
396 } 422 }
397 423
398 void ManagePasswordsBubbleModel::OnSignInToChromeClicked() { 424 void ManagePasswordsBubbleModel::OnSignInToChromeClicked() {
399 425 interaction_keeper_->set_sign_in_promo_dismissal_reason(
426 metrics_util::CHROME_SIGNIN_OK);
427 GetProfile()->GetPrefs()->SetBoolean(
428 password_manager::prefs::kWasSignInPasswordPromoClicked, true);
429 PasswordsModelDelegateFromWebContents(web_contents())
430 ->NavigateToChromeSignIn();
400 } 431 }
401 432
402 void ManagePasswordsBubbleModel::OnSkipSignInClicked() { 433 void ManagePasswordsBubbleModel::OnSkipSignInClicked() {
403 434 interaction_keeper_->set_sign_in_promo_dismissal_reason(
435 metrics_util::CHROME_SIGNIN_CANCEL);
436 GetProfile()->GetPrefs()->SetBoolean(
437 password_manager::prefs::kWasSignInPasswordPromoClicked, true);
404 } 438 }
405 439
406 Profile* ManagePasswordsBubbleModel::GetProfile() const { 440 Profile* ManagePasswordsBubbleModel::GetProfile() const {
407 return GetProfileFromWebContents(web_contents()); 441 return GetProfileFromWebContents(web_contents());
408 } 442 }
409 443
410 bool ManagePasswordsBubbleModel::ShouldShowMultipleAccountUpdateUI() const { 444 bool ManagePasswordsBubbleModel::ShouldShowMultipleAccountUpdateUI() const {
411 return state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE && 445 return state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE &&
412 local_credentials_.size() > 1 && !password_overridden_; 446 local_credentials_.size() > 1 && !password_overridden_;
413 } 447 }
414 448
415 bool ManagePasswordsBubbleModel::ShouldShowGoogleSmartLockWelcome() const { 449 bool ManagePasswordsBubbleModel::ShouldShowGoogleSmartLockWelcome() const {
416 Profile* profile = GetProfile(); 450 Profile* profile = GetProfile();
417 if (GetSmartLockBrandingState(profile) == 451 if (GetSmartLockBrandingState(profile) ==
418 password_bubble_experiment::SmartLockBranding::FULL) { 452 password_bubble_experiment::SmartLockBranding::FULL) {
419 PrefService* prefs = profile->GetPrefs(); 453 PrefService* prefs = profile->GetPrefs();
420 return !prefs->GetBoolean( 454 return !prefs->GetBoolean(
421 password_manager::prefs::kWasSavePrompFirstRunExperienceShown); 455 password_manager::prefs::kWasSavePrompFirstRunExperienceShown);
422 } 456 }
423 return false; 457 return false;
424 } 458 }
425 459
426 bool ManagePasswordsBubbleModel::ReplaceToShowSignInPromoIfNeeded() { 460 bool ManagePasswordsBubbleModel::ReplaceToShowSignInPromoIfNeeded() {
427 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); 461 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_);
428 if (false /*TODO(crbug.com/615825): there will be a real condition soon*/) { 462 PrefService* prefs = GetProfile()->GetPrefs();
463 if (password_bubble_experiment::ShouldShowChromeSignInPasswordPromo(prefs)) {
464 interaction_keeper_->ReportInteractions(this);
429 title_brand_link_range_ = gfx::Range(); 465 title_brand_link_range_ = gfx::Range();
430 title_ = l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SIGNIN_PROMO_TITLE); 466 title_ = l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_SIGNIN_PROMO_TITLE);
431 state_ = password_manager::ui::CHROME_SIGN_IN_PROMO_STATE; 467 state_ = password_manager::ui::CHROME_SIGN_IN_PROMO_STATE;
468 int show_count = prefs->GetInteger(
469 password_manager::prefs::kNumberSignInPasswordPromoShown);
470 prefs->SetInteger(password_manager::prefs::kNumberSignInPasswordPromoShown,
471 show_count + 1);
432 return true; 472 return true;
433 } 473 }
434 return false; 474 return false;
435 } 475 }
436 476
437 void ManagePasswordsBubbleModel::SetClockForTesting( 477 void ManagePasswordsBubbleModel::SetClockForTesting(
438 std::unique_ptr<base::Clock> clock) { 478 std::unique_ptr<base::Clock> clock) {
439 interaction_keeper_->SetClockForTesting(std::move(clock)); 479 interaction_keeper_->SetClockForTesting(std::move(clock));
440 } 480 }
441 481
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 return metrics_util::NO_UPDATE_SUBMISSION; 522 return metrics_util::NO_UPDATE_SUBMISSION;
483 } 523 }
484 if (state_ != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) 524 if (state_ != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE)
485 return metrics_util::NO_UPDATE_SUBMISSION; 525 return metrics_util::NO_UPDATE_SUBMISSION;
486 if (password_overridden_) 526 if (password_overridden_)
487 return update_events[3][behavior]; 527 return update_events[3][behavior];
488 if (ShouldShowMultipleAccountUpdateUI()) 528 if (ShouldShowMultipleAccountUpdateUI())
489 return update_events[2][behavior]; 529 return update_events[2][behavior];
490 return update_events[1][behavior]; 530 return update_events[1][behavior];
491 } 531 }
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/ui/passwords/manage_passwords_bubble_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698