| 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 <string> | 11 #include <string> |
| 11 #include <vector> | 12 #include <vector> |
| 12 | 13 |
| 13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/time/default_clock.h" | 15 #include "base/time/default_clock.h" |
| 15 #include "chrome/browser/password_manager/password_store_factory.h" | 16 #include "chrome/browser/password_manager/password_store_factory.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/sync/profile_sync_service_factory.h" | 18 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 18 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" | 19 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" |
| 19 #include "chrome/browser/ui/passwords/passwords_model_delegate.h" | 20 #include "chrome/browser/ui/passwords/passwords_model_delegate.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 39 return Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 40 return Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 40 } | 41 } |
| 41 | 42 |
| 42 void CleanStatisticsForSite(content::WebContents* web_contents, | 43 void CleanStatisticsForSite(content::WebContents* web_contents, |
| 43 const GURL& origin) { | 44 const GURL& origin) { |
| 44 DCHECK(web_contents); | 45 DCHECK(web_contents); |
| 45 Profile* profile = | 46 Profile* profile = |
| 46 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 47 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 47 password_manager::PasswordStore* password_store = | 48 password_manager::PasswordStore* password_store = |
| 48 PasswordStoreFactory::GetForProfile(profile, | 49 PasswordStoreFactory::GetForProfile(profile, |
| 49 ServiceAccessType::EXPLICIT_ACCESS) | 50 ServiceAccessType::IMPLICIT_ACCESS) |
| 50 .get(); | 51 .get(); |
| 51 password_store->RemoveSiteStats(origin.GetOrigin()); | 52 password_store->RemoveSiteStats(origin.GetOrigin()); |
| 52 } | 53 } |
| 53 | 54 |
| 54 ScopedVector<const autofill::PasswordForm> DeepCopyForms( | 55 ScopedVector<const autofill::PasswordForm> DeepCopyForms( |
| 55 const std::vector<const autofill::PasswordForm*>& forms) { | 56 const std::vector<const autofill::PasswordForm*>& forms) { |
| 56 ScopedVector<const autofill::PasswordForm> result; | 57 ScopedVector<const autofill::PasswordForm> result; |
| 57 result.reserve(forms.size()); | 58 result.reserve(forms.size()); |
| 58 std::transform(forms.begin(), forms.end(), std::back_inserter(result), | 59 std::transform(forms.begin(), forms.end(), std::back_inserter(result), |
| 59 [](const autofill::PasswordForm* form) { | 60 [](const autofill::PasswordForm* form) { |
| 60 return new autofill::PasswordForm(*form); | 61 return new autofill::PasswordForm(*form); |
| 61 }); | 62 }); |
| 62 return result; | 63 return result; |
| 63 } | 64 } |
| 64 | 65 |
| 65 password_bubble_experiment::SmartLockBranding GetSmartLockBrandingState( | 66 password_bubble_experiment::SmartLockBranding GetSmartLockBrandingState( |
| 66 Profile* profile) { | 67 Profile* profile) { |
| 67 const ProfileSyncService* sync_service = | 68 const ProfileSyncService* sync_service = |
| 68 ProfileSyncServiceFactory::GetForProfile(profile); | 69 ProfileSyncServiceFactory::GetForProfile(profile); |
| 69 return password_bubble_experiment::GetSmartLockBrandingState(sync_service); | 70 return password_bubble_experiment::GetSmartLockBrandingState(sync_service); |
| 70 } | 71 } |
| 71 | 72 |
| 72 } // namespace | 73 } // namespace |
| 73 | 74 |
| 75 // Class responsible for collecting and reporting all the runtime interactions |
| 76 // with the bubble. |
| 77 class ManagePasswordsBubbleModel::InteractionKeeper { |
| 78 public: |
| 79 InteractionKeeper( |
| 80 password_manager::InteractionsStats stats, |
| 81 password_manager::metrics_util::UIDisplayDisposition display_disposition); |
| 82 |
| 83 ~InteractionKeeper() = default; |
| 84 |
| 85 // Records UMA events and updates the interaction statistics when the bubble |
| 86 // is closed. |
| 87 void ReportInteractions(const ManagePasswordsBubbleModel* model); |
| 88 |
| 89 void set_dismissal_reason( |
| 90 password_manager::metrics_util::UIDismissalReason reason) { |
| 91 dismissal_reason_ = reason; |
| 92 } |
| 93 |
| 94 void set_update_password_submission_event( |
| 95 password_manager::metrics_util::UpdatePasswordSubmissionEvent event) { |
| 96 update_password_submission_event_ = event; |
| 97 } |
| 98 |
| 99 void SetClockForTesting(std::unique_ptr<base::Clock> clock) { |
| 100 clock_ = std::move(clock); |
| 101 } |
| 102 |
| 103 private: |
| 104 // The way the bubble appeared. |
| 105 const password_manager::metrics_util::UIDisplayDisposition |
| 106 display_disposition_; |
| 107 |
| 108 // Dismissal reason for a bubble. |
| 109 password_manager::metrics_util::UIDismissalReason dismissal_reason_; |
| 110 |
| 111 // Dismissal reason for the update bubble. |
| 112 password_manager::metrics_util::UpdatePasswordSubmissionEvent |
| 113 update_password_submission_event_; |
| 114 |
| 115 // Current statistics for the save password bubble; |
| 116 password_manager::InteractionsStats interaction_stats_; |
| 117 |
| 118 // Used to retrieve the current time, in base::Time units. |
| 119 std::unique_ptr<base::Clock> clock_; |
| 120 |
| 121 DISALLOW_COPY_AND_ASSIGN(InteractionKeeper); |
| 122 }; |
| 123 |
| 124 ManagePasswordsBubbleModel::InteractionKeeper::InteractionKeeper( |
| 125 password_manager::InteractionsStats stats, |
| 126 password_manager::metrics_util::UIDisplayDisposition display_disposition) |
| 127 : display_disposition_(display_disposition), |
| 128 dismissal_reason_(metrics_util::NO_DIRECT_INTERACTION), |
| 129 update_password_submission_event_(metrics_util::NO_UPDATE_SUBMISSION), |
| 130 interaction_stats_(std::move(stats)), |
| 131 clock_(new base::DefaultClock) { |
| 132 } |
| 133 |
| 134 void ManagePasswordsBubbleModel::InteractionKeeper::ReportInteractions( |
| 135 const ManagePasswordsBubbleModel* model) { |
| 136 if (model->state() == password_manager::ui::PENDING_PASSWORD_STATE) { |
| 137 Profile* profile = model->GetProfile(); |
| 138 if (profile) { |
| 139 if (GetSmartLockBrandingState(profile) == |
| 140 password_bubble_experiment::SmartLockBranding::FULL) { |
| 141 password_bubble_experiment::RecordSavePromptFirstRunExperienceWasShown( |
| 142 profile->GetPrefs()); |
| 143 } |
| 144 if (dismissal_reason_ == metrics_util::NO_DIRECT_INTERACTION && |
| 145 display_disposition_ == |
| 146 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING) { |
| 147 if (interaction_stats_.dismissal_count < |
| 148 std::numeric_limits<decltype( |
| 149 interaction_stats_.dismissal_count)>::max()) |
| 150 interaction_stats_.dismissal_count++; |
| 151 interaction_stats_.update_time = clock_->Now(); |
| 152 password_manager::PasswordStore* password_store = |
| 153 PasswordStoreFactory::GetForProfile( |
| 154 profile, ServiceAccessType::IMPLICIT_ACCESS).get(); |
| 155 password_store->AddSiteStats(interaction_stats_); |
| 156 } |
| 157 } |
| 158 } |
| 159 |
| 160 if (model->state() != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { |
| 161 // We have separate metrics for the Update bubble so do not record dismissal |
| 162 // reason for it. |
| 163 metrics_util::LogUIDismissalReason(dismissal_reason_); |
| 164 } |
| 165 |
| 166 PasswordsModelDelegate* delegate = model->web_contents() |
| 167 ? PasswordsModelDelegateFromWebContents(model->web_contents()) |
| 168 : nullptr; |
| 169 // Check if this was update password and record update statistics. |
| 170 if (update_password_submission_event_ == metrics_util::NO_UPDATE_SUBMISSION && |
| 171 (model->state() == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE || |
| 172 model->state() == password_manager::ui::PENDING_PASSWORD_STATE)) { |
| 173 update_password_submission_event_ = |
| 174 model->GetUpdateDismissalReason(NO_INTERACTION); |
| 175 if (model->state() == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE && |
| 176 delegate) |
| 177 delegate->OnNoInteractionOnUpdate(); |
| 178 } |
| 179 if (update_password_submission_event_ != metrics_util::NO_UPDATE_SUBMISSION) |
| 180 LogUpdatePasswordSubmissionEvent(update_password_submission_event_); |
| 181 } |
| 182 |
| 74 ManagePasswordsBubbleModel::ManagePasswordsBubbleModel( | 183 ManagePasswordsBubbleModel::ManagePasswordsBubbleModel( |
| 75 content::WebContents* web_contents, | 184 content::WebContents* web_contents, |
| 76 DisplayReason display_reason) | 185 DisplayReason display_reason) |
| 77 : content::WebContentsObserver(web_contents), | 186 : content::WebContentsObserver(web_contents), |
| 78 password_overridden_(false), | 187 password_overridden_(false) { |
| 79 display_disposition_(metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING), | |
| 80 dismissal_reason_(metrics_util::NO_DIRECT_INTERACTION), | |
| 81 update_password_submission_event_(metrics_util::NO_UPDATE_SUBMISSION), | |
| 82 clock_(new base::DefaultClock) { | |
| 83 PasswordsModelDelegate* delegate = | 188 PasswordsModelDelegate* delegate = |
| 84 PasswordsModelDelegateFromWebContents(web_contents); | 189 PasswordsModelDelegateFromWebContents(web_contents); |
| 85 | 190 |
| 86 origin_ = delegate->GetOrigin(); | 191 origin_ = delegate->GetOrigin(); |
| 87 state_ = delegate->GetState(); | 192 state_ = delegate->GetState(); |
| 88 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE || | 193 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE || |
| 89 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { | 194 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { |
| 90 pending_password_ = delegate->GetPendingPassword(); | 195 pending_password_ = delegate->GetPendingPassword(); |
| 91 local_credentials_ = DeepCopyForms(delegate->GetCurrentForms()); | 196 local_credentials_ = DeepCopyForms(delegate->GetCurrentForms()); |
| 92 } else if (state_ == password_manager::ui::CONFIRMATION_STATE) { | 197 } else if (state_ == password_manager::ui::CONFIRMATION_STATE) { |
| 93 // We don't need anything. | 198 // We don't need anything. |
| 94 } else if (state_ == password_manager::ui::AUTO_SIGNIN_STATE) { | 199 } else if (state_ == password_manager::ui::AUTO_SIGNIN_STATE) { |
| 95 pending_password_ = delegate->GetPendingPassword(); | 200 pending_password_ = delegate->GetPendingPassword(); |
| 96 } else { | 201 } else { |
| 97 local_credentials_ = DeepCopyForms(delegate->GetCurrentForms()); | 202 local_credentials_ = DeepCopyForms(delegate->GetCurrentForms()); |
| 98 } | 203 } |
| 99 | 204 |
| 100 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE || | 205 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE || |
| 101 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { | 206 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { |
| 102 UpdatePendingStateTitle(); | 207 UpdatePendingStateTitle(); |
| 103 } else if (state_ == password_manager::ui::CONFIRMATION_STATE) { | 208 } else if (state_ == password_manager::ui::CONFIRMATION_STATE) { |
| 104 title_ = | 209 title_ = |
| 105 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TITLE); | 210 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TITLE); |
| 106 } else if (state_ == password_manager::ui::AUTO_SIGNIN_STATE) { | 211 } else if (state_ == password_manager::ui::AUTO_SIGNIN_STATE) { |
| 107 // There is no title. | 212 // There is no title. |
| 108 } else if (state_ == password_manager::ui::MANAGE_STATE) { | 213 } else if (state_ == password_manager::ui::MANAGE_STATE) { |
| 109 UpdateManageStateTitle(); | 214 UpdateManageStateTitle(); |
| 110 } | 215 } |
| 111 | 216 |
| 217 password_manager::InteractionsStats interaction_stats; |
| 112 if (state_ == password_manager::ui::CONFIRMATION_STATE) { | 218 if (state_ == password_manager::ui::CONFIRMATION_STATE) { |
| 113 base::string16 save_confirmation_link = | 219 base::string16 save_confirmation_link = |
| 114 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_LINK); | 220 l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_LINK); |
| 115 int confirmation_text_id = IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT; | 221 int confirmation_text_id = IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_TEXT; |
| 116 if (GetSmartLockBrandingState(GetProfile()) == | 222 if (GetSmartLockBrandingState(GetProfile()) == |
| 117 password_bubble_experiment::SmartLockBranding::FULL) { | 223 password_bubble_experiment::SmartLockBranding::FULL) { |
| 118 std::string management_hostname = | 224 std::string management_hostname = |
| 119 GURL(password_manager::kPasswordManagerAccountDashboardURL).host(); | 225 GURL(password_manager::kPasswordManagerAccountDashboardURL).host(); |
| 120 save_confirmation_link = base::UTF8ToUTF16(management_hostname); | 226 save_confirmation_link = base::UTF8ToUTF16(management_hostname); |
| 121 confirmation_text_id = | 227 confirmation_text_id = |
| 122 IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_SMART_LOCK_TEXT; | 228 IDS_MANAGE_PASSWORDS_CONFIRM_GENERATED_SMART_LOCK_TEXT; |
| 123 } | 229 } |
| 124 | 230 |
| 125 size_t offset; | 231 size_t offset; |
| 126 save_confirmation_text_ = | 232 save_confirmation_text_ = |
| 127 l10n_util::GetStringFUTF16( | 233 l10n_util::GetStringFUTF16( |
| 128 confirmation_text_id, save_confirmation_link, &offset); | 234 confirmation_text_id, save_confirmation_link, &offset); |
| 129 save_confirmation_link_range_ = | 235 save_confirmation_link_range_ = |
| 130 gfx::Range(offset, offset + save_confirmation_link.length()); | 236 gfx::Range(offset, offset + save_confirmation_link.length()); |
| 131 } else if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) { | 237 } else if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) { |
| 132 interaction_stats_.origin_domain = origin_.GetOrigin(); | 238 interaction_stats.origin_domain = origin_.GetOrigin(); |
| 133 interaction_stats_.username_value = pending_password_.username_value; | 239 interaction_stats.username_value = pending_password_.username_value; |
| 134 password_manager::InteractionsStats* stats = | 240 password_manager::InteractionsStats* stats = |
| 135 delegate->GetCurrentInteractionStats(); | 241 delegate->GetCurrentInteractionStats(); |
| 136 if (stats) { | 242 if (stats) { |
| 137 DCHECK_EQ(interaction_stats_.username_value, stats->username_value); | 243 DCHECK_EQ(interaction_stats.username_value, stats->username_value); |
| 138 DCHECK_EQ(interaction_stats_.origin_domain, stats->origin_domain); | 244 DCHECK_EQ(interaction_stats.origin_domain, stats->origin_domain); |
| 139 interaction_stats_.dismissal_count = stats->dismissal_count; | 245 interaction_stats.dismissal_count = stats->dismissal_count; |
| 140 } | 246 } |
| 141 } else if (state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { | 247 } else if (state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { |
| 142 password_overridden_ = delegate->IsPasswordOverridden(); | 248 password_overridden_ = delegate->IsPasswordOverridden(); |
| 143 } | 249 } |
| 144 | 250 |
| 145 manage_link_ = | 251 manage_link_ = |
| 146 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK); | 252 l10n_util::GetStringUTF16(IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS_LINK); |
| 147 | 253 |
| 254 password_manager::metrics_util::UIDisplayDisposition display_disposition = |
| 255 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING; |
| 148 if (display_reason == USER_ACTION) { | 256 if (display_reason == USER_ACTION) { |
| 149 switch (state_) { | 257 switch (state_) { |
| 150 case password_manager::ui::PENDING_PASSWORD_STATE: | 258 case password_manager::ui::PENDING_PASSWORD_STATE: |
| 151 display_disposition_ = metrics_util::MANUAL_WITH_PASSWORD_PENDING; | 259 display_disposition = metrics_util::MANUAL_WITH_PASSWORD_PENDING; |
| 152 break; | 260 break; |
| 153 case password_manager::ui::PENDING_PASSWORD_UPDATE_STATE: | 261 case password_manager::ui::PENDING_PASSWORD_UPDATE_STATE: |
| 154 display_disposition_ = | 262 display_disposition = |
| 155 metrics_util::MANUAL_WITH_PASSWORD_PENDING_UPDATE; | 263 metrics_util::MANUAL_WITH_PASSWORD_PENDING_UPDATE; |
| 156 break; | 264 break; |
| 157 case password_manager::ui::MANAGE_STATE: | 265 case password_manager::ui::MANAGE_STATE: |
| 158 display_disposition_ = metrics_util::MANUAL_MANAGE_PASSWORDS; | 266 display_disposition = metrics_util::MANUAL_MANAGE_PASSWORDS; |
| 159 break; | 267 break; |
| 160 case password_manager::ui::CONFIRMATION_STATE: | 268 case password_manager::ui::CONFIRMATION_STATE: |
| 161 case password_manager::ui::CREDENTIAL_REQUEST_STATE: | 269 case password_manager::ui::CREDENTIAL_REQUEST_STATE: |
| 162 case password_manager::ui::AUTO_SIGNIN_STATE: | 270 case password_manager::ui::AUTO_SIGNIN_STATE: |
| 163 case password_manager::ui::INACTIVE_STATE: | 271 case password_manager::ui::INACTIVE_STATE: |
| 164 NOTREACHED(); | 272 NOTREACHED(); |
| 165 break; | 273 break; |
| 166 } | 274 } |
| 167 } else { | 275 } else { |
| 168 switch (state_) { | 276 switch (state_) { |
| 169 case password_manager::ui::PENDING_PASSWORD_STATE: | 277 case password_manager::ui::PENDING_PASSWORD_STATE: |
| 170 display_disposition_ = metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING; | 278 display_disposition = metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING; |
| 171 break; | 279 break; |
| 172 case password_manager::ui::PENDING_PASSWORD_UPDATE_STATE: | 280 case password_manager::ui::PENDING_PASSWORD_UPDATE_STATE: |
| 173 display_disposition_ = | 281 display_disposition = |
| 174 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING_UPDATE; | 282 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING_UPDATE; |
| 175 break; | 283 break; |
| 176 case password_manager::ui::CONFIRMATION_STATE: | 284 case password_manager::ui::CONFIRMATION_STATE: |
| 177 display_disposition_ = | 285 display_disposition = |
| 178 metrics_util::AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION; | 286 metrics_util::AUTOMATIC_GENERATED_PASSWORD_CONFIRMATION; |
| 179 break; | 287 break; |
| 180 case password_manager::ui::AUTO_SIGNIN_STATE: | 288 case password_manager::ui::AUTO_SIGNIN_STATE: |
| 181 display_disposition_ = metrics_util::AUTOMATIC_SIGNIN_TOAST; | 289 display_disposition = metrics_util::AUTOMATIC_SIGNIN_TOAST; |
| 182 break; | 290 break; |
| 183 case password_manager::ui::MANAGE_STATE: | 291 case password_manager::ui::MANAGE_STATE: |
| 184 case password_manager::ui::CREDENTIAL_REQUEST_STATE: | 292 case password_manager::ui::CREDENTIAL_REQUEST_STATE: |
| 185 case password_manager::ui::INACTIVE_STATE: | 293 case password_manager::ui::INACTIVE_STATE: |
| 186 NOTREACHED(); | 294 NOTREACHED(); |
| 187 break; | 295 break; |
| 188 } | 296 } |
| 189 } | 297 } |
| 190 metrics_util::LogUIDisplayDisposition(display_disposition_); | 298 metrics_util::LogUIDisplayDisposition(display_disposition); |
| 299 interaction_keeper_.reset(new InteractionKeeper(std::move(interaction_stats), |
| 300 display_disposition)); |
| 191 | 301 |
| 192 delegate->OnBubbleShown(); | 302 delegate->OnBubbleShown(); |
| 193 } | 303 } |
| 194 | 304 |
| 195 ManagePasswordsBubbleModel::~ManagePasswordsBubbleModel() { | 305 ManagePasswordsBubbleModel::~ManagePasswordsBubbleModel() { |
| 196 if (state_ == password_manager::ui::PENDING_PASSWORD_STATE) { | 306 interaction_keeper_->ReportInteractions(this); |
| 197 Profile* profile = GetProfile(); | 307 // web_contents() is nullptr if the tab is closing. |
| 198 if (profile) { | |
| 199 if (GetSmartLockBrandingState(profile) == | |
| 200 password_bubble_experiment::SmartLockBranding::FULL) { | |
| 201 password_bubble_experiment::RecordSavePromptFirstRunExperienceWasShown( | |
| 202 profile->GetPrefs()); | |
| 203 } | |
| 204 if (dismissal_reason_ == metrics_util::NO_DIRECT_INTERACTION && | |
| 205 display_disposition_ == | |
| 206 metrics_util::AUTOMATIC_WITH_PASSWORD_PENDING) { | |
| 207 if (interaction_stats_.dismissal_count < | |
| 208 std::numeric_limits<decltype( | |
| 209 interaction_stats_.dismissal_count)>::max()) | |
| 210 interaction_stats_.dismissal_count++; | |
| 211 interaction_stats_.update_time = clock_->Now(); | |
| 212 password_manager::PasswordStore* password_store = | |
| 213 PasswordStoreFactory::GetForProfile( | |
| 214 profile, ServiceAccessType::EXPLICIT_ACCESS) | |
| 215 .get(); | |
| 216 password_store->AddSiteStats(interaction_stats_); | |
| 217 } | |
| 218 } | |
| 219 } | |
| 220 PasswordsModelDelegate* delegate = | 308 PasswordsModelDelegate* delegate = |
| 221 web_contents() ? PasswordsModelDelegateFromWebContents(web_contents()) | 309 web_contents() ? PasswordsModelDelegateFromWebContents(web_contents()) |
| 222 : nullptr; | 310 : nullptr; |
| 223 if (delegate) | 311 if (delegate) |
| 224 delegate->OnBubbleHidden(); | 312 delegate->OnBubbleHidden(); |
| 225 if (dismissal_reason_ == metrics_util::NOT_DISPLAYED) | |
| 226 return; | |
| 227 | |
| 228 if (state_ != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) { | |
| 229 // We have separate metrics for the Update bubble so do not record dismissal | |
| 230 // reason for it. | |
| 231 metrics_util::LogUIDismissalReason(dismissal_reason_); | |
| 232 } | |
| 233 // Check if this was update password and record update statistics. | |
| 234 if (update_password_submission_event_ == metrics_util::NO_UPDATE_SUBMISSION && | |
| 235 (state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE || | |
| 236 state_ == password_manager::ui::PENDING_PASSWORD_STATE)) { | |
| 237 update_password_submission_event_ = | |
| 238 GetUpdateDismissalReason(NO_INTERACTION); | |
| 239 if (state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE && | |
| 240 delegate) | |
| 241 delegate->OnNoInteractionOnUpdate(); | |
| 242 } | |
| 243 if (update_password_submission_event_ != metrics_util::NO_UPDATE_SUBMISSION) | |
| 244 LogUpdatePasswordSubmissionEvent(update_password_submission_event_); | |
| 245 } | 313 } |
| 246 | 314 |
| 247 void ManagePasswordsBubbleModel::OnNeverForThisSiteClicked() { | 315 void ManagePasswordsBubbleModel::OnNeverForThisSiteClicked() { |
| 248 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); | 316 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); |
| 249 dismissal_reason_ = metrics_util::CLICKED_NEVER; | 317 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_NEVER); |
| 250 update_password_submission_event_ = GetUpdateDismissalReason(NOPE_CLICKED); | 318 interaction_keeper_->set_update_password_submission_event( |
| 319 GetUpdateDismissalReason(NOPE_CLICKED)); |
| 251 CleanStatisticsForSite(web_contents(), origin_); | 320 CleanStatisticsForSite(web_contents(), origin_); |
| 252 PasswordsModelDelegateFromWebContents(web_contents())->NeverSavePassword(); | 321 PasswordsModelDelegateFromWebContents(web_contents())->NeverSavePassword(); |
| 253 } | 322 } |
| 254 | 323 |
| 255 void ManagePasswordsBubbleModel::OnSaveClicked() { | 324 void ManagePasswordsBubbleModel::OnSaveClicked() { |
| 256 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); | 325 DCHECK_EQ(password_manager::ui::PENDING_PASSWORD_STATE, state_); |
| 257 dismissal_reason_ = metrics_util::CLICKED_SAVE; | 326 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_SAVE); |
| 258 update_password_submission_event_ = GetUpdateDismissalReason(UPDATE_CLICKED); | 327 interaction_keeper_->set_update_password_submission_event( |
| 328 GetUpdateDismissalReason(UPDATE_CLICKED)); |
| 259 CleanStatisticsForSite(web_contents(), origin_); | 329 CleanStatisticsForSite(web_contents(), origin_); |
| 260 PasswordsModelDelegateFromWebContents(web_contents())->SavePassword(); | 330 PasswordsModelDelegateFromWebContents(web_contents())->SavePassword(); |
| 261 } | 331 } |
| 262 | 332 |
| 263 void ManagePasswordsBubbleModel::OnNopeUpdateClicked() { | 333 void ManagePasswordsBubbleModel::OnNopeUpdateClicked() { |
| 264 update_password_submission_event_ = GetUpdateDismissalReason(NOPE_CLICKED); | 334 interaction_keeper_->set_update_password_submission_event( |
| 335 GetUpdateDismissalReason(NOPE_CLICKED)); |
| 265 PasswordsModelDelegateFromWebContents(web_contents())->OnNopeUpdateClicked(); | 336 PasswordsModelDelegateFromWebContents(web_contents())->OnNopeUpdateClicked(); |
| 266 } | 337 } |
| 267 | 338 |
| 268 void ManagePasswordsBubbleModel::OnUpdateClicked( | 339 void ManagePasswordsBubbleModel::OnUpdateClicked( |
| 269 const autofill::PasswordForm& password_form) { | 340 const autofill::PasswordForm& password_form) { |
| 270 update_password_submission_event_ = GetUpdateDismissalReason(UPDATE_CLICKED); | 341 interaction_keeper_->set_update_password_submission_event( |
| 342 GetUpdateDismissalReason(UPDATE_CLICKED)); |
| 271 PasswordsModelDelegateFromWebContents(web_contents())->UpdatePassword( | 343 PasswordsModelDelegateFromWebContents(web_contents())->UpdatePassword( |
| 272 password_form); | 344 password_form); |
| 273 } | 345 } |
| 274 | 346 |
| 275 void ManagePasswordsBubbleModel::OnDoneClicked() { | 347 void ManagePasswordsBubbleModel::OnDoneClicked() { |
| 276 dismissal_reason_ = metrics_util::CLICKED_DONE; | 348 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_DONE); |
| 277 } | 349 } |
| 278 | 350 |
| 279 // TODO(gcasto): Is it worth having this be separate from OnDoneClicked()? | 351 // TODO(gcasto): Is it worth having this be separate from OnDoneClicked()? |
| 280 // User intent is pretty similar in both cases. | 352 // User intent is pretty similar in both cases. |
| 281 void ManagePasswordsBubbleModel::OnOKClicked() { | 353 void ManagePasswordsBubbleModel::OnOKClicked() { |
| 282 dismissal_reason_ = metrics_util::CLICKED_OK; | 354 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_OK); |
| 283 } | 355 } |
| 284 | 356 |
| 285 void ManagePasswordsBubbleModel::OnManageLinkClicked() { | 357 void ManagePasswordsBubbleModel::OnManageLinkClicked() { |
| 286 dismissal_reason_ = metrics_util::CLICKED_MANAGE; | 358 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_MANAGE); |
| 287 if (GetSmartLockBrandingState(GetProfile()) == | 359 if (GetSmartLockBrandingState(GetProfile()) == |
| 288 password_bubble_experiment::SmartLockBranding::FULL) { | 360 password_bubble_experiment::SmartLockBranding::FULL) { |
| 289 PasswordsModelDelegateFromWebContents(web_contents()) | 361 PasswordsModelDelegateFromWebContents(web_contents()) |
| 290 ->NavigateToExternalPasswordManager(); | 362 ->NavigateToExternalPasswordManager(); |
| 291 } else { | 363 } else { |
| 292 PasswordsModelDelegateFromWebContents(web_contents()) | 364 PasswordsModelDelegateFromWebContents(web_contents()) |
| 293 ->NavigateToPasswordManagerSettingsPage(); | 365 ->NavigateToPasswordManagerSettingsPage(); |
| 294 } | 366 } |
| 295 } | 367 } |
| 296 | 368 |
| 297 void ManagePasswordsBubbleModel::OnBrandLinkClicked() { | 369 void ManagePasswordsBubbleModel::OnBrandLinkClicked() { |
| 298 dismissal_reason_ = metrics_util::CLICKED_BRAND_NAME; | 370 interaction_keeper_->set_dismissal_reason(metrics_util::CLICKED_BRAND_NAME); |
| 299 PasswordsModelDelegateFromWebContents(web_contents()) | 371 PasswordsModelDelegateFromWebContents(web_contents()) |
| 300 ->NavigateToSmartLockHelpPage(); | 372 ->NavigateToSmartLockHelpPage(); |
| 301 } | 373 } |
| 302 | 374 |
| 303 void ManagePasswordsBubbleModel::OnAutoSignInToastTimeout() { | 375 void ManagePasswordsBubbleModel::OnAutoSignInToastTimeout() { |
| 304 dismissal_reason_ = metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT; | 376 interaction_keeper_->set_dismissal_reason( |
| 377 metrics_util::AUTO_SIGNIN_TOAST_TIMEOUT); |
| 305 } | 378 } |
| 306 | 379 |
| 307 void ManagePasswordsBubbleModel::OnPasswordAction( | 380 void ManagePasswordsBubbleModel::OnPasswordAction( |
| 308 const autofill::PasswordForm& password_form, | 381 const autofill::PasswordForm& password_form, |
| 309 PasswordAction action) { | 382 PasswordAction action) { |
| 310 if (!web_contents()) | 383 Profile* profile = GetProfile(); |
| 384 if (!profile) |
| 311 return; | 385 return; |
| 312 Profile* profile = | |
| 313 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); | |
| 314 password_manager::PasswordStore* password_store = | 386 password_manager::PasswordStore* password_store = |
| 315 PasswordStoreFactory::GetForProfile( | 387 PasswordStoreFactory::GetForProfile( |
| 316 profile, ServiceAccessType::EXPLICIT_ACCESS).get(); | 388 profile, ServiceAccessType::EXPLICIT_ACCESS).get(); |
| 317 DCHECK(password_store); | 389 DCHECK(password_store); |
| 318 if (action == REMOVE_PASSWORD) | 390 if (action == REMOVE_PASSWORD) |
| 319 password_store->RemoveLogin(password_form); | 391 password_store->RemoveLogin(password_form); |
| 320 else | 392 else |
| 321 password_store->AddLogin(password_form); | 393 password_store->AddLogin(password_form); |
| 322 } | 394 } |
| 323 | 395 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 334 Profile* profile = GetProfile(); | 406 Profile* profile = GetProfile(); |
| 335 if (GetSmartLockBrandingState(profile) == | 407 if (GetSmartLockBrandingState(profile) == |
| 336 password_bubble_experiment::SmartLockBranding::FULL) { | 408 password_bubble_experiment::SmartLockBranding::FULL) { |
| 337 PrefService* prefs = profile->GetPrefs(); | 409 PrefService* prefs = profile->GetPrefs(); |
| 338 return !prefs->GetBoolean( | 410 return !prefs->GetBoolean( |
| 339 password_manager::prefs::kWasSavePrompFirstRunExperienceShown); | 411 password_manager::prefs::kWasSavePrompFirstRunExperienceShown); |
| 340 } | 412 } |
| 341 return false; | 413 return false; |
| 342 } | 414 } |
| 343 | 415 |
| 416 void ManagePasswordsBubbleModel::SetClockForTesting( |
| 417 std::unique_ptr<base::Clock> clock) { |
| 418 interaction_keeper_->SetClockForTesting(std::move(clock)); |
| 419 } |
| 420 |
| 344 void ManagePasswordsBubbleModel::UpdatePendingStateTitle() { | 421 void ManagePasswordsBubbleModel::UpdatePendingStateTitle() { |
| 345 title_brand_link_range_ = gfx::Range(); | 422 title_brand_link_range_ = gfx::Range(); |
| 346 PasswordTittleType type = | 423 PasswordTittleType type = |
| 347 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE | 424 state_ == password_manager::ui::PENDING_PASSWORD_UPDATE_STATE |
| 348 ? PasswordTittleType::UPDATE_PASSWORD | 425 ? PasswordTittleType::UPDATE_PASSWORD |
| 349 : (pending_password_.federation_origin.unique() | 426 : (pending_password_.federation_origin.unique() |
| 350 ? PasswordTittleType::SAVE_PASSWORD | 427 ? PasswordTittleType::SAVE_PASSWORD |
| 351 : PasswordTittleType::SAVE_ACCOUNT); | 428 : PasswordTittleType::SAVE_ACCOUNT); |
| 352 GetSavePasswordDialogTitleTextAndLinkRange( | 429 GetSavePasswordDialogTitleTextAndLinkRange( |
| 353 web_contents()->GetVisibleURL(), origin_, | 430 web_contents()->GetVisibleURL(), origin_, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 384 return metrics_util::NO_UPDATE_SUBMISSION; | 461 return metrics_util::NO_UPDATE_SUBMISSION; |
| 385 } | 462 } |
| 386 if (state_ != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) | 463 if (state_ != password_manager::ui::PENDING_PASSWORD_UPDATE_STATE) |
| 387 return metrics_util::NO_UPDATE_SUBMISSION; | 464 return metrics_util::NO_UPDATE_SUBMISSION; |
| 388 if (password_overridden_) | 465 if (password_overridden_) |
| 389 return update_events[3][behavior]; | 466 return update_events[3][behavior]; |
| 390 if (ShouldShowMultipleAccountUpdateUI()) | 467 if (ShouldShowMultipleAccountUpdateUI()) |
| 391 return update_events[2][behavior]; | 468 return update_events[2][behavior]; |
| 392 return update_events[1][behavior]; | 469 return update_events[1][behavior]; |
| 393 } | 470 } |
| OLD | NEW |