| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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_ui_controller.h" | 5 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" |
| 7 #include "chrome/app/chrome_command_ids.h" | 8 #include "chrome/app/chrome_command_ids.h" |
| 8 #include "chrome/browser/browsing_data/browsing_data_helper.h" | 9 #include "chrome/browser/browsing_data/browsing_data_helper.h" |
| 9 #include "chrome/browser/password_manager/chrome_password_manager_client.h" | 10 #include "chrome/browser/password_manager/chrome_password_manager_client.h" |
| 10 #include "chrome/browser/password_manager/password_store_factory.h" | 11 #include "chrome/browser/password_manager/password_store_factory.h" |
| 11 #include "chrome/browser/ui/browser_command_controller.h" | 12 #include "chrome/browser/ui/browser_command_controller.h" |
| 12 #include "chrome/browser/ui/browser_finder.h" | 13 #include "chrome/browser/ui/browser_finder.h" |
| 13 #include "chrome/browser/ui/browser_window.h" | 14 #include "chrome/browser/ui/browser_window.h" |
| 14 #include "chrome/browser/ui/chrome_pages.h" | 15 #include "chrome/browser/ui/chrome_pages.h" |
| 15 #include "chrome/browser/ui/location_bar/location_bar.h" | 16 #include "chrome/browser/ui/location_bar/location_bar.h" |
| 16 #include "chrome/browser/ui/passwords/manage_passwords_icon.h" | 17 #include "chrome/browser/ui/passwords/manage_passwords_icon.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 } | 61 } |
| 61 | 62 |
| 62 } // namespace | 63 } // namespace |
| 63 | 64 |
| 64 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ManagePasswordsUIController); | 65 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ManagePasswordsUIController); |
| 65 | 66 |
| 66 ManagePasswordsUIController::ManagePasswordsUIController( | 67 ManagePasswordsUIController::ManagePasswordsUIController( |
| 67 content::WebContents* web_contents) | 68 content::WebContents* web_contents) |
| 68 : content::WebContentsObserver(web_contents), | 69 : content::WebContentsObserver(web_contents), |
| 69 state_(password_manager::ui::INACTIVE_STATE), | 70 state_(password_manager::ui::INACTIVE_STATE), |
| 70 bubble_shown_(false) { | 71 should_pop_up_bubble_(false) { |
| 71 password_manager::PasswordStore* password_store = | 72 password_manager::PasswordStore* password_store = |
| 72 GetPasswordStore(web_contents); | 73 GetPasswordStore(web_contents); |
| 73 if (password_store) | 74 if (password_store) |
| 74 password_store->AddObserver(this); | 75 password_store->AddObserver(this); |
| 75 } | 76 } |
| 76 | 77 |
| 77 ManagePasswordsUIController::~ManagePasswordsUIController() {} | 78 ManagePasswordsUIController::~ManagePasswordsUIController() {} |
| 78 | 79 |
| 79 void ManagePasswordsUIController::UpdateBubbleAndIconVisibility() { | 80 void ManagePasswordsUIController::UpdateBubbleAndIconVisibility() { |
| 80 bubble_shown_ = false; | |
| 81 // If we're not on a "webby" URL (e.g. "chrome://sign-in"), we shouldn't | 81 // If we're not on a "webby" URL (e.g. "chrome://sign-in"), we shouldn't |
| 82 // display either the bubble or the icon. | 82 // display either the bubble or the icon. |
| 83 if (!BrowsingDataHelper::IsWebScheme( | 83 if (!BrowsingDataHelper::IsWebScheme( |
| 84 web_contents()->GetLastCommittedURL().scheme())) { | 84 web_contents()->GetLastCommittedURL().scheme())) { |
| 85 SetState(password_manager::ui::INACTIVE_STATE); | 85 SetState(password_manager::ui::INACTIVE_STATE); |
| 86 } | 86 } |
| 87 | 87 |
| 88 #if !defined(OS_ANDROID) | 88 #if !defined(OS_ANDROID) |
| 89 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); | 89 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); |
| 90 if (!browser) | 90 if (!browser) |
| 91 return; | 91 return; |
| 92 LocationBar* location_bar = browser->window()->GetLocationBar(); | 92 LocationBar* location_bar = browser->window()->GetLocationBar(); |
| 93 DCHECK(location_bar); | 93 DCHECK(location_bar); |
| 94 location_bar->UpdateManagePasswordsIconAndBubble(); | 94 location_bar->UpdateManagePasswordsIconAndBubble(); |
| 95 #endif | 95 #endif |
| 96 } | 96 } |
| 97 | 97 |
| 98 base::TimeDelta ManagePasswordsUIController::Elapsed() const { | 98 base::TimeDelta ManagePasswordsUIController::Elapsed() const { |
| 99 return timer_ ? timer_->Elapsed() : base::TimeDelta::Max(); | 99 return timer_ ? timer_->Elapsed() : base::TimeDelta::Max(); |
| 100 } | 100 } |
| 101 | 101 |
| 102 void ManagePasswordsUIController::OnAskToReportURL(const GURL& url) { | 102 void ManagePasswordsUIController::OnAskToReportURL(const GURL& url) { |
| 103 origin_ = url; | 103 origin_ = url; |
| 104 SetState(password_manager::ui::ASK_USER_REPORT_URL_STATE); | 104 SetState(password_manager::ui:: |
| 105 ASK_USER_REPORT_URL_BUBBLE_SHOWN_BEFORE_TRANSITION_STATE); |
| 106 base::AutoReset<bool> resetter(&should_pop_up_bubble_, true); |
| 105 UpdateBubbleAndIconVisibility(); | 107 UpdateBubbleAndIconVisibility(); |
| 106 } | 108 } |
| 107 | 109 |
| 108 void ManagePasswordsUIController::OnPasswordSubmitted( | 110 void ManagePasswordsUIController::OnPasswordSubmitted( |
| 109 scoped_ptr<PasswordFormManager> form_manager) { | 111 scoped_ptr<PasswordFormManager> form_manager) { |
| 110 form_manager_ = form_manager.Pass(); | 112 form_manager_ = form_manager.Pass(); |
| 111 password_form_map_ = ConstifyMap(form_manager_->best_matches()); | 113 password_form_map_ = ConstifyMap(form_manager_->best_matches()); |
| 112 origin_ = PendingPassword().origin; | 114 origin_ = PendingPassword().origin; |
| 113 SetState(password_manager::ui::PENDING_PASSWORD_AND_BUBBLE_STATE); | 115 SetState(password_manager::ui::PENDING_PASSWORD_STATE); |
| 114 timer_.reset(new base::ElapsedTimer()); | 116 timer_.reset(new base::ElapsedTimer); |
| 117 base::AutoReset<bool> resetter(&should_pop_up_bubble_, true); |
| 115 UpdateBubbleAndIconVisibility(); | 118 UpdateBubbleAndIconVisibility(); |
| 116 } | 119 } |
| 117 | 120 |
| 118 bool ManagePasswordsUIController::OnChooseCredentials( | 121 bool ManagePasswordsUIController::OnChooseCredentials( |
| 119 ScopedVector<autofill::PasswordForm> local_credentials, | 122 ScopedVector<autofill::PasswordForm> local_credentials, |
| 120 ScopedVector<autofill::PasswordForm> federated_credentials, | 123 ScopedVector<autofill::PasswordForm> federated_credentials, |
| 121 const GURL& origin, | 124 const GURL& origin, |
| 122 base::Callback<void(const password_manager::CredentialInfo&)> callback) { | 125 base::Callback<void(const password_manager::CredentialInfo&)> callback) { |
| 123 DCHECK(!local_credentials.empty() || !federated_credentials.empty()); | 126 DCHECK(!local_credentials.empty() || !federated_credentials.empty()); |
| 124 form_manager_.reset(); | 127 form_manager_.reset(); |
| 125 origin_ = origin; | 128 origin_ = origin; |
| 126 local_credentials_forms_.swap(local_credentials); | 129 local_credentials_forms_.swap(local_credentials); |
| 127 federated_credentials_forms_.swap(federated_credentials); | 130 federated_credentials_forms_.swap(federated_credentials); |
| 128 // The map is useless because usernames may overlap. | 131 // The map is useless because usernames may overlap. |
| 129 password_form_map_.clear(); | 132 password_form_map_.clear(); |
| 130 SetState(password_manager::ui::CREDENTIAL_REQUEST_AND_BUBBLE_STATE); | 133 SetState(password_manager::ui::CREDENTIAL_REQUEST_STATE); |
| 134 base::AutoReset<bool> resetter(&should_pop_up_bubble_, true); |
| 131 UpdateBubbleAndIconVisibility(); | 135 UpdateBubbleAndIconVisibility(); |
| 132 if (bubble_shown_) | 136 if (!should_pop_up_bubble_) { |
| 133 credentials_callback_ = callback; | 137 credentials_callback_ = callback; |
| 134 return bubble_shown_; | 138 return true; |
| 139 } |
| 140 return false; |
| 135 } | 141 } |
| 136 | 142 |
| 137 void ManagePasswordsUIController::OnAutomaticPasswordSave( | 143 void ManagePasswordsUIController::OnAutomaticPasswordSave( |
| 138 scoped_ptr<PasswordFormManager> form_manager) { | 144 scoped_ptr<PasswordFormManager> form_manager) { |
| 139 form_manager_ = form_manager.Pass(); | 145 form_manager_ = form_manager.Pass(); |
| 140 password_form_map_ = ConstifyMap(form_manager_->best_matches()); | 146 password_form_map_ = ConstifyMap(form_manager_->best_matches()); |
| 141 password_form_map_[form_manager_->associated_username()] = | 147 password_form_map_[form_manager_->associated_username()] = |
| 142 &form_manager_->pending_credentials(); | 148 &form_manager_->pending_credentials(); |
| 143 origin_ = form_manager_->pending_credentials().origin; | 149 origin_ = form_manager_->pending_credentials().origin; |
| 144 SetState(password_manager::ui::CONFIRMATION_STATE); | 150 SetState(password_manager::ui::CONFIRMATION_STATE); |
| 151 base::AutoReset<bool> resetter(&should_pop_up_bubble_, true); |
| 145 UpdateBubbleAndIconVisibility(); | 152 UpdateBubbleAndIconVisibility(); |
| 146 } | 153 } |
| 147 | 154 |
| 148 void ManagePasswordsUIController::OnPasswordAutofilled( | 155 void ManagePasswordsUIController::OnPasswordAutofilled( |
| 149 const PasswordFormMap& password_form_map) { | 156 const PasswordFormMap& password_form_map) { |
| 150 DeepCopyMap(password_form_map, &password_form_map_, &new_password_forms_); | 157 DeepCopyMap(password_form_map, &password_form_map_, &new_password_forms_); |
| 151 origin_ = password_form_map_.begin()->second->origin; | 158 origin_ = password_form_map_.begin()->second->origin; |
| 152 // Don't show the UI for PSL matched passwords. They are not stored for this | 159 // Don't show the UI for PSL matched passwords. They are not stored for this |
| 153 // page and cannot be deleted. | 160 // page and cannot be deleted. |
| 154 SetState(password_form_map_.begin()->second->IsPublicSuffixMatch() | 161 SetState(password_form_map_.begin()->second->IsPublicSuffixMatch() |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 void ManagePasswordsUIController::SavePassword() { | 214 void ManagePasswordsUIController::SavePassword() { |
| 208 DCHECK(PasswordPendingUserDecision()); | 215 DCHECK(PasswordPendingUserDecision()); |
| 209 SavePasswordInternal(); | 216 SavePasswordInternal(); |
| 210 SetState(password_manager::ui::MANAGE_STATE); | 217 SetState(password_manager::ui::MANAGE_STATE); |
| 211 UpdateBubbleAndIconVisibility(); | 218 UpdateBubbleAndIconVisibility(); |
| 212 } | 219 } |
| 213 | 220 |
| 214 void ManagePasswordsUIController::ChooseCredential( | 221 void ManagePasswordsUIController::ChooseCredential( |
| 215 const autofill::PasswordForm& form, | 222 const autofill::PasswordForm& form, |
| 216 password_manager::CredentialType credential_type) { | 223 password_manager::CredentialType credential_type) { |
| 217 DCHECK(password_manager::ui::IsCredentialsState(state_)); | 224 DCHECK_EQ(password_manager::ui::CREDENTIAL_REQUEST_STATE, state_); |
| 218 DCHECK(!credentials_callback_.is_null()); | 225 DCHECK(!credentials_callback_.is_null()); |
| 219 | 226 |
| 220 // Here, |credential_type| refers to whether the credential was originally | 227 // Here, |credential_type| refers to whether the credential was originally |
| 221 // passed into ::OnChooseCredentials as part of the |local_credentials| or | 228 // passed into ::OnChooseCredentials as part of the |local_credentials| or |
| 222 // |federated_credentials| lists (e.g. whether it is an existing credential | 229 // |federated_credentials| lists (e.g. whether it is an existing credential |
| 223 // saved for this origin, or whether we should synthesize a new | 230 // saved for this origin, or whether we should synthesize a new |
| 224 // FederatedCredential). | 231 // FederatedCredential). |
| 225 // | 232 // |
| 226 // If |credential_type| is federated, the credential MUST be returned as | 233 // If |credential_type| is federated, the credential MUST be returned as |
| 227 // a FederatedCredential in order to prevent password information leaking | 234 // a FederatedCredential in order to prevent password information leaking |
| (...skipping 12 matching lines...) Expand all Loading... |
| 240 } else if (credential_type == | 247 } else if (credential_type == |
| 241 password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY) { | 248 password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY) { |
| 242 type_to_return = password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY; | 249 type_to_return = password_manager::CredentialType::CREDENTIAL_TYPE_EMPTY; |
| 243 } else { | 250 } else { |
| 244 type_to_return = | 251 type_to_return = |
| 245 password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED; | 252 password_manager::CredentialType::CREDENTIAL_TYPE_FEDERATED; |
| 246 } | 253 } |
| 247 password_manager::CredentialInfo info = | 254 password_manager::CredentialInfo info = |
| 248 password_manager::CredentialInfo(form, type_to_return); | 255 password_manager::CredentialInfo(form, type_to_return); |
| 249 credentials_callback_.Run(info); | 256 credentials_callback_.Run(info); |
| 250 SetState(password_manager::ui::INACTIVE_STATE); | 257 credentials_callback_.Reset(); |
| 251 UpdateBubbleAndIconVisibility(); | |
| 252 } | 258 } |
| 253 | 259 |
| 254 void ManagePasswordsUIController::SavePasswordInternal() { | 260 void ManagePasswordsUIController::SavePasswordInternal() { |
| 255 DCHECK(form_manager_.get()); | 261 DCHECK(form_manager_.get()); |
| 256 form_manager_->Save(); | 262 form_manager_->Save(); |
| 257 } | 263 } |
| 258 | 264 |
| 259 void ManagePasswordsUIController::NeverSavePassword() { | 265 void ManagePasswordsUIController::NeverSavePassword() { |
| 260 DCHECK(PasswordPendingUserDecision()); | 266 DCHECK(PasswordPendingUserDecision()); |
| 261 NeverSavePasswordInternal(); | 267 NeverSavePasswordInternal(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 } | 341 } |
| 336 | 342 |
| 337 const autofill::PasswordForm& ManagePasswordsUIController:: | 343 const autofill::PasswordForm& ManagePasswordsUIController:: |
| 338 PendingPassword() const { | 344 PendingPassword() const { |
| 339 DCHECK(form_manager_); | 345 DCHECK(form_manager_); |
| 340 return form_manager_->pending_credentials(); | 346 return form_manager_->pending_credentials(); |
| 341 } | 347 } |
| 342 | 348 |
| 343 void ManagePasswordsUIController::UpdateIconAndBubbleState( | 349 void ManagePasswordsUIController::UpdateIconAndBubbleState( |
| 344 ManagePasswordsIcon* icon) { | 350 ManagePasswordsIcon* icon) { |
| 345 if (password_manager::ui::IsAutomaticDisplayState(state_)) { | 351 if (should_pop_up_bubble_) { |
| 346 // We must display the icon before showing the bubble, as the bubble would | 352 // We must display the icon before showing the bubble, as the bubble would |
| 347 // be otherwise unanchored. However, we can't change the controller's state | 353 // be otherwise unanchored. |
| 348 // until _after_ the bubble is shown, as our metrics depend on the seeing | 354 icon->SetState(state_); |
| 349 // the original state to determine if the bubble opened automagically or via | |
| 350 // user action. | |
| 351 password_manager::ui::State end_state = | |
| 352 GetEndStateForAutomaticState(state_); | |
| 353 icon->SetState(end_state); | |
| 354 ShowBubbleWithoutUserInteraction(); | 355 ShowBubbleWithoutUserInteraction(); |
| 355 SetState(end_state); | |
| 356 } else { | 356 } else { |
| 357 icon->SetState(state_); | 357 icon->SetState(state_); |
| 358 } | 358 } |
| 359 } | 359 } |
| 360 | 360 |
| 361 void ManagePasswordsUIController::OnBubbleShown() { | 361 void ManagePasswordsUIController::OnBubbleShown() { |
| 362 bubble_shown_ = true; | 362 should_pop_up_bubble_ = false; |
| 363 } |
| 364 |
| 365 void ManagePasswordsUIController::OnBubbleHidden() { |
| 366 password_manager::ui::State next_state = state_; |
| 367 if (state_ == password_manager::ui::CREDENTIAL_REQUEST_STATE) |
| 368 next_state = password_manager::ui::INACTIVE_STATE; |
| 369 else if (state_ == password_manager::ui::CONFIRMATION_STATE) |
| 370 next_state = password_manager::ui::MANAGE_STATE; |
| 371 |
| 372 if (next_state != state_) { |
| 373 SetState(next_state); |
| 374 UpdateBubbleAndIconVisibility(); |
| 375 } |
| 363 } | 376 } |
| 364 | 377 |
| 365 void ManagePasswordsUIController::ShowBubbleWithoutUserInteraction() { | 378 void ManagePasswordsUIController::ShowBubbleWithoutUserInteraction() { |
| 366 DCHECK(password_manager::ui::IsAutomaticDisplayState(state_)); | 379 DCHECK(should_pop_up_bubble_); |
| 367 #if !defined(OS_ANDROID) | 380 #if !defined(OS_ANDROID) |
| 368 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); | 381 Browser* browser = chrome::FindBrowserWithWebContents(web_contents()); |
| 369 if (!browser || browser->toolbar_model()->input_in_progress()) | 382 if (!browser || browser->toolbar_model()->input_in_progress()) |
| 370 return; | 383 return; |
| 371 if (state_ == password_manager::ui::PENDING_PASSWORD_AND_BUBBLE_STATE && | |
| 372 !password_bubble_experiment::ShouldShowBubble( | |
| 373 browser->profile()->GetPrefs())) | |
| 374 return; | |
| 375 CommandUpdater* updater = browser->command_controller()->command_updater(); | 384 CommandUpdater* updater = browser->command_controller()->command_updater(); |
| 376 updater->ExecuteCommand(IDC_MANAGE_PASSWORDS_FOR_PAGE); | 385 updater->ExecuteCommand(IDC_MANAGE_PASSWORDS_FOR_PAGE); |
| 377 #endif | 386 #endif |
| 378 } | 387 } |
| 379 | 388 |
| 380 bool ManagePasswordsUIController::PasswordPendingUserDecision() const { | 389 bool ManagePasswordsUIController::PasswordPendingUserDecision() const { |
| 381 return password_manager::ui::IsPendingState(state_); | 390 return state_ == password_manager::ui::PENDING_PASSWORD_STATE; |
| 382 } | 391 } |
| 383 | 392 |
| 384 void ManagePasswordsUIController::WebContentsDestroyed() { | 393 void ManagePasswordsUIController::WebContentsDestroyed() { |
| 385 password_manager::PasswordStore* password_store = | 394 password_manager::PasswordStore* password_store = |
| 386 GetPasswordStore(web_contents()); | 395 GetPasswordStore(web_contents()); |
| 387 if (password_store) | 396 if (password_store) |
| 388 password_store->RemoveObserver(this); | 397 password_store->RemoveObserver(this); |
| 389 } | 398 } |
| OLD | NEW |