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. 4 5 #ifndef CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_H_ 6 #define CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_H_ 7 8 #include <memory> 9 #include <vector> 10 11 #include "base/macros.h" 12 #include "base/timer/timer.h" 13 #include "chrome/browser/ui/passwords/manage_passwords_state.h" 14 #include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h" 15 #include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate.h" 16 #include "chrome/browser/ui/passwords/passwords_model_delegate.h" 17 #include "chrome/common/buildflags.h" 18 #include "components/password_manager/core/browser/password_manager_client.h" 19 #include "components/password_manager/core/browser/password_store.h" 20 #include "components/password_manager/core/browser/ui/post_save_compromised_helper.h" 21 #include "content/public/browser/web_contents_observer.h" 22 #include "content/public/browser/web_contents_user_data.h" 23 24 namespace base { 25 class TimeDelta; 26 } 27 28 namespace content { 29 class WebContents; 30 } 31 32 namespace password_manager { 33 enum class CredentialType; 34 struct InteractionsStats; 35 class PasswordFeatureManager; 36 class PasswordFormManagerForUI; 37 class PostSaveCompromisedHelper; 38 } // namespace password_manager 39 40 class AccountChooserPrompt; 41 struct AccountInfo; 42 class AutoSigninFirstRunPrompt; 43 class CredentialLeakPrompt; 44 class ManagePasswordsIconView; 45 class CredentialLeakDialogController; 46 class CredentialManagerDialogController; 47 class PasswordBaseDialogController; 48 49 // Per-tab class to control the Omnibox password icon and bubble. 50 class ManagePasswordsUIController 51 : public content::WebContentsObserver, 52 public content::WebContentsUserData<ManagePasswordsUIController>, 53 public password_manager::PasswordStore::Observer, 54 public PasswordsLeakDialogDelegate, 55 public PasswordsModelDelegate, 56 public PasswordsClientUIDelegate { 57 public: 58 ~ManagePasswordsUIController() override; 59 60 #if defined(UNIT_TEST) set_save_fallback_timeout_in_seconds(int timeout)61 static void set_save_fallback_timeout_in_seconds(int timeout) { 62 save_fallback_timeout_in_seconds_ = timeout; 63 } 64 #endif 65 66 // PasswordsClientUIDelegate: 67 void OnPasswordSubmitted( 68 std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager) 69 override; 70 void OnUpdatePasswordSubmitted( 71 std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager) 72 override; 73 void OnShowManualFallbackForSaving( 74 std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager, 75 bool has_generated_password, 76 bool is_update) override; 77 void OnHideManualFallbackForSaving() override; 78 bool OnChooseCredentials( 79 std::vector<std::unique_ptr<password_manager::PasswordForm>> 80 local_credentials, 81 const url::Origin& origin, 82 ManagePasswordsState::CredentialsCallback callback) override; 83 void OnAutoSignin( 84 std::vector<std::unique_ptr<password_manager::PasswordForm>> local_forms, 85 const url::Origin& origin) override; 86 void OnPromptEnableAutoSignin() override; 87 void OnAutomaticPasswordSave( 88 std::unique_ptr<password_manager::PasswordFormManagerForUI> form_manager) 89 override; 90 void OnPasswordAutofilled( 91 const std::vector<const password_manager::PasswordForm*>& password_forms, 92 const url::Origin& origin, 93 const std::vector<const password_manager::PasswordForm*>* 94 federated_matches) override; 95 void OnCredentialLeak(password_manager::CredentialLeakType leak_dialog_type, 96 const GURL& origin) override; 97 void OnShowMoveToAccountBubble( 98 std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_move) 99 override; 100 101 virtual void NotifyUnsyncedCredentialsWillBeDeleted( 102 std::vector<password_manager::PasswordForm> unsynced_credentials); 103 104 // PasswordStore::Observer: 105 void OnLoginsChanged( 106 const password_manager::PasswordStoreChangeList& changes) override; 107 108 // Set the state of the Omnibox icon, and possibly show the associated bubble 109 // without user interaction. 110 virtual void UpdateIconAndBubbleState(ManagePasswordsIconView* icon); 111 112 // True iff the bubble is to be opened automatically. IsAutomaticallyOpeningBubble()113 bool IsAutomaticallyOpeningBubble() const { 114 return bubble_status_ == BubbleStatus::SHOULD_POP_UP; 115 } 116 117 // virtual to be overridden in tests. 118 virtual base::WeakPtr<PasswordsModelDelegate> GetModelDelegateProxy(); 119 120 // PasswordsModelDelegate: 121 content::WebContents* GetWebContents() const override; 122 url::Origin GetOrigin() const override; 123 password_manager::PasswordFormMetricsRecorder* 124 GetPasswordFormMetricsRecorder() override; 125 password_manager::PasswordFeatureManager* GetPasswordFeatureManager() 126 override; 127 password_manager::ui::State GetState() const override; 128 const password_manager::PasswordForm& GetPendingPassword() const override; 129 const std::vector<password_manager::PasswordForm>& GetUnsyncedCredentials() 130 const override; 131 password_manager::metrics_util::CredentialSourceType GetCredentialSource() 132 const override; 133 const std::vector<std::unique_ptr<password_manager::PasswordForm>>& 134 GetCurrentForms() const override; 135 const password_manager::InteractionsStats* GetCurrentInteractionStats() 136 const override; 137 size_t GetTotalNumberCompromisedPasswords() const override; 138 bool DidAuthForAccountStoreOptInFail() const override; 139 bool BubbleIsManualFallbackForSaving() const override; 140 void OnBubbleShown() override; 141 void OnBubbleHidden() override; 142 void OnNoInteraction() override; 143 void OnNopeUpdateClicked() override; 144 void NeverSavePassword() override; 145 void OnPasswordsRevealed() override; 146 void SavePassword(const base::string16& username, 147 const base::string16& password) override; 148 void SaveUnsyncedCredentialsInProfileStore( 149 const std::vector<password_manager::PasswordForm>& selected_credentials) 150 override; 151 void DiscardUnsyncedCredentials() override; 152 void MovePasswordToAccountStore() override; 153 void BlockMovingPasswordToAccountStore() override; 154 void ChooseCredential( 155 const password_manager::PasswordForm& form, 156 password_manager::CredentialType credential_type) override; 157 void NavigateToPasswordManagerAccountDashboard( 158 password_manager::ManagePasswordsReferrer referrer) override; 159 void NavigateToPasswordManagerSettingsPage( 160 password_manager::ManagePasswordsReferrer referrer) override; 161 void EnableSync(const AccountInfo& account) override; 162 void OnDialogHidden() override; 163 bool AuthenticateUser() override; 164 void AuthenticateUserForAccountStoreOptInAndSavePassword( 165 const base::string16& username, 166 const base::string16& password) override; 167 void AuthenticateUserForAccountStoreOptInAndMovePassword() override; 168 bool ArePasswordsRevealedWhenBubbleIsOpened() const override; 169 170 #if defined(UNIT_TEST) 171 // Overwrites the client for |passwords_data_|. set_client(password_manager::PasswordManagerClient * client)172 void set_client(password_manager::PasswordManagerClient* client) { 173 passwords_data_.set_client(client); 174 } 175 #endif // defined(UNIT_TEST) 176 177 protected: 178 explicit ManagePasswordsUIController(content::WebContents* web_contents); 179 180 // Hides the bubble if opened. Mocked in the tests. 181 virtual void HidePasswordBubble(); 182 183 // Called when a PasswordForm is autofilled, when a new PasswordForm is 184 // submitted, or when a navigation occurs to update the visibility of the 185 // manage passwords icon and bubble. 186 virtual void UpdateBubbleAndIconVisibility(); 187 188 // Called to create the account chooser dialog. Mocked in tests. 189 virtual AccountChooserPrompt* CreateAccountChooser( 190 CredentialManagerDialogController* controller); 191 192 // Called to create the account chooser dialog. Mocked in tests. 193 virtual AutoSigninFirstRunPrompt* CreateAutoSigninPrompt( 194 CredentialManagerDialogController* controller); 195 196 // Called to create the credentials leaked dialog. 197 virtual CredentialLeakPrompt* CreateCredentialLeakPrompt( 198 CredentialLeakDialogController* controller); 199 200 // Check if |web_contents()| is attached to some Browser. Mocked in tests. 201 virtual bool HasBrowserWindow() const; 202 203 // True if the bubble is to be opened automatically or after re-auth. ShouldBubblePopUp()204 bool ShouldBubblePopUp() const { 205 return IsAutomaticallyOpeningBubble() || 206 bubble_status_ == BubbleStatus::SHOULD_POP_UP_AFTER_REAUTH; 207 } 208 209 // Returns whether the bubble is currently open. IsShowingBubbleForTest()210 bool IsShowingBubbleForTest() const { return IsShowingBubble(); } 211 212 // content::WebContentsObserver: 213 void DidFinishNavigation( 214 content::NavigationHandle* navigation_handle) override; 215 void OnVisibilityChanged(content::Visibility visibility) override; 216 217 private: 218 friend class content::WebContentsUserData<ManagePasswordsUIController>; 219 220 // PasswordsLeakDialogDelegate: 221 void NavigateToPasswordCheckup( 222 password_manager::PasswordCheckReferrer referrer) override; 223 void OnLeakDialogHidden() override; 224 225 enum class BubbleStatus { 226 NOT_SHOWN, 227 // The bubble is to be popped up in the next call to 228 // UpdateBubbleAndIconVisibility(). 229 SHOULD_POP_UP, 230 // The bubble is to be reopened after re-authentication. 231 SHOULD_POP_UP_AFTER_REAUTH, 232 SHOWN, 233 // Same as SHOWN but the icon is to be updated when the bubble is closed. 234 SHOWN_PENDING_ICON_UPDATE, 235 }; 236 IsShowingBubble()237 bool IsShowingBubble() const { 238 return bubble_status_ == BubbleStatus::SHOWN || 239 bubble_status_ == BubbleStatus::SHOWN_PENDING_ICON_UPDATE; 240 } 241 242 // Returns the timeout for the manual save fallback. 243 static base::TimeDelta GetTimeoutForSaveFallback(); 244 245 // Shows the password bubble without user interaction. 246 void ShowBubbleWithoutUserInteraction(); 247 248 // Resets |bubble_status_| signalling that if the bubble was due to pop up, 249 // it shouldn't anymore. 250 void ClearPopUpFlagForBubble(); 251 252 // Closes the account chooser gracefully so the callback is called. Then sets 253 // the state to MANAGE_STATE. 254 void DestroyAccountChooser(); 255 256 // content::WebContentsObserver: 257 void WebContentsDestroyed() override; 258 259 // Requests authentication and reopens the bubble if the controller still 260 // exists and is in a pending state. 261 void RequestAuthenticationAndReopenBubble(); 262 263 // Re-opens the bubble. The password in the reopened bubble will be revealed 264 // if the authentication was successful. 265 void ReopenBubbleAfterAuth(bool auth_is_successful); 266 267 // Shows an authentication dialog and returns true if auth is successful. 268 virtual bool ShowAuthenticationDialog(); 269 270 // Gets invoked gaia reauth flow is finished. If the reauth was successful, 271 // and the |form_manager| is still the same, |username| and |password| are 272 // saved against the current origin. If the reauth was unsuccessful, it 273 // changes the default destination to profle store and reopens the save 274 // bubble. 275 void FinishSavingPasswordAfterAccountStoreOptInAuth( 276 const url::Origin& origin, 277 password_manager::PasswordFormManagerForUI* form_manager, 278 const base::string16& username, 279 const base::string16& password, 280 password_manager::PasswordManagerClient::ReauthSucceeded 281 reauth_succeeded); 282 283 void OnTriggerPostSaveCompromisedBubble( 284 password_manager::PostSaveCompromisedHelper::BubbleType type, 285 size_t count_compromised_passwords_); 286 287 // Triggered from a reauthentication flow. If |form_manager| is still valid 288 // and the reauth was successful, the password is moved to the account store. 289 void FinishMovingPasswordAfterAccountStoreOptInAuth( 290 password_manager::PasswordFormManagerForUI* form_manager, 291 password_manager::PasswordManagerClient::ReauthSucceeded 292 reauth_succeeded); 293 294 // Timeout in seconds for the manual fallback for saving. 295 static int save_fallback_timeout_in_seconds_; 296 297 // The wrapper around current state and data. 298 ManagePasswordsState passwords_data_; 299 300 // The controller for the blocking dialogs. 301 std::unique_ptr<PasswordBaseDialogController> dialog_controller_; 302 303 // The helper to pop up a reminder about compromised passwords. 304 std::unique_ptr<password_manager::PostSaveCompromisedHelper> 305 post_save_compromised_helper_; 306 307 BubbleStatus bubble_status_ = BubbleStatus::NOT_SHOWN; 308 309 // The timer that controls whether the fallback for saving should be 310 // available. Should be reset once the fallback is not needed (an automatic 311 // popup will be shown or the user saved/updated the password with the 312 // fallback). 313 base::OneShotTimer save_fallback_timer_; 314 315 // True iff bubble should pop up with revealed password value. 316 bool are_passwords_revealed_when_next_bubble_is_opened_; 317 318 // The bubbles of different types can pop up unpredictably superseding each 319 // other. However, closing the bubble may affect the state of 320 // ManagePasswordsUIController internally. This is undesired if 321 // ManagePasswordsUIController is in the process of opening a new bubble. The 322 // situation is worse on Windows where the bubble is destroyed asynchronously. 323 // Thus, OnBubbleHidden() can be called after the new one is shown. By that 324 // time the internal state of ManagePasswordsUIController has nothing to do 325 // with the old bubble. 326 // Invalidating all the weak pointers will detach the current bubble. 327 base::WeakPtrFactory<ManagePasswordsUIController> weak_ptr_factory_{this}; 328 329 WEB_CONTENTS_USER_DATA_KEY_DECL(); 330 331 DISALLOW_COPY_AND_ASSIGN(ManagePasswordsUIController); 332 }; 333 334 #endif // CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_H_ 335