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 "base/gtest_prod_util.h" 9 #include "base/memory/scoped_vector.h" 10 #include "base/timer/elapsed_timer.h" 11 #include "components/autofill/core/common/password_form.h" 12 #include "components/password_manager/core/browser/password_form_manager.h" 13 #include "components/password_manager/core/browser/password_store.h" 14 #include "components/password_manager/core/browser/password_store_change.h" 15 #include "components/password_manager/core/common/password_manager_ui.h" 16 #include "content/public/browser/navigation_details.h" 17 #include "content/public/browser/web_contents_observer.h" 18 #include "content/public/browser/web_contents_user_data.h" 19 20 namespace content { 21 class WebContents; 22 } 23 24 class ManagePasswordsIcon; 25 26 // Per-tab class to control the Omnibox password icon and bubble. 27 class ManagePasswordsUIController 28 : public content::WebContentsObserver, 29 public content::WebContentsUserData<ManagePasswordsUIController>, 30 public password_manager::PasswordStore::Observer { 31 public: 32 virtual ~ManagePasswordsUIController(); 33 34 // Called when the user submits a form containing login information, so we 35 // can handle later requests to save or blacklist that login information. 36 // This stores the provided object in form_manager_ and triggers the UI to 37 // prompt the user about whether they would like to save the password. 38 void OnPasswordSubmitted( 39 scoped_ptr<password_manager::PasswordFormManager> form_manager); 40 41 // Called when the password will be saved automatically, but we still wish to 42 // visually inform the user that the save has occured. 43 void OnAutomaticPasswordSave( 44 scoped_ptr<password_manager::PasswordFormManager> form_manager); 45 46 // Called when a form is autofilled with login information, so we can manage 47 // password credentials for the current site which are stored in 48 // |password_form_map|. This stores a copy of |password_form_map| and shows 49 // the manage password icon. 50 void OnPasswordAutofilled(const autofill::PasswordFormMap& password_form_map); 51 52 // Called when a form is _not_ autofilled due to user blacklisting. This 53 // stores a copy of |password_form_map| so that we can offer the user the 54 // ability to reenable the manager for this form. 55 void OnBlacklistBlockedAutofill( 56 const autofill::PasswordFormMap& password_form_map); 57 58 // PasswordStore::Observer implementation. 59 virtual void OnLoginsChanged( 60 const password_manager::PasswordStoreChangeList& changes) OVERRIDE; 61 62 // Called from the model when the user chooses to save a password; passes the 63 // action off to the FormManager. The controller MUST be in a pending state, 64 // and WILL be in MANAGE_STATE after this method executes. 65 virtual void SavePassword(); 66 67 // Called from the model when the user chooses to never save passwords; passes 68 // the action off to the FormManager. The controller MUST be in a pending 69 // state, and WILL be in BLACKLIST_STATE after this method executes. 70 virtual void NeverSavePassword(); 71 72 // Called from the model when the user chooses to unblacklist the site. The 73 // controller MUST be in BLACKLIST_STATE, and WILL be in MANAGE_STATE after 74 // this method executes. 75 virtual void UnblacklistSite(); 76 77 // Open a new tab, pointing to the password manager settings page. 78 virtual void NavigateToPasswordManagerSettingsPage(); 79 80 virtual const autofill::PasswordForm& PendingCredentials() const; 81 82 // Set the state of the Omnibox icon, and possibly show the associated bubble 83 // without user interaction. 84 virtual void UpdateIconAndBubbleState(ManagePasswordsIcon* icon); 85 state()86 password_manager::ui::State state() const { return state_; } 87 88 // True if a password is sitting around, waiting for a user to decide whether 89 // or not to save it. 90 bool PasswordPendingUserDecision() const; 91 best_matches()92 const autofill::ConstPasswordFormMap& best_matches() const { 93 return password_form_map_; 94 } 95 origin()96 const GURL& origin() const { return origin_; } 97 98 protected: 99 explicit ManagePasswordsUIController( 100 content::WebContents* web_contents); 101 102 // The pieces of saving and blacklisting passwords that interact with 103 // FormManager, split off into internal functions for testing/mocking. 104 virtual void SavePasswordInternal(); 105 virtual void NeverSavePasswordInternal(); 106 107 // content::WebContentsObserver: 108 virtual void DidNavigateMainFrame( 109 const content::LoadCommittedDetails& details, 110 const content::FrameNavigateParams& params) OVERRIDE; 111 virtual void WasHidden() OVERRIDE; 112 113 // We create copies of PasswordForm objects that come in with unclear lifetime 114 // and store them in this vector as well as in |password_form_map_| to ensure 115 // that we destroy them correctly. If |new_password_forms_| gets cleared then 116 // |password_form_map_| is to be cleared too. 117 ScopedVector<autofill::PasswordForm> new_password_forms_; 118 119 // All previously stored credentials for a specific site. 120 // Protected, not private, so we can mess with the value in 121 // ManagePasswordsUIControllerMock. 122 autofill::ConstPasswordFormMap password_form_map_; 123 124 // The current state of the password manager. Protected so we can manipulate 125 // the value in tests. 126 password_manager::ui::State state_; 127 128 // Used to measure the amount of time on a page; if it's less than some 129 // reasonable limit, then don't close the bubble upon navigation. We create 130 // (and destroy) the timer in DidNavigateMainFrame. 131 scoped_ptr<base::ElapsedTimer> timer_; 132 133 private: 134 friend class content::WebContentsUserData<ManagePasswordsUIController>; 135 136 // Shows the password bubble without user interaction. The controller MUST 137 // be in PENDING_PASSWORD_AND_BUBBLE_STATE. 138 void ShowBubbleWithoutUserInteraction(); 139 140 // Called when a passwordform is autofilled, when a new passwordform is 141 // submitted, or when a navigation occurs to update the visibility of the 142 // manage passwords icon and bubble. 143 void UpdateBubbleAndIconVisibility(); 144 145 // content::WebContentsObserver: 146 virtual void WebContentsDestroyed() OVERRIDE; 147 148 // Set by OnPasswordSubmitted() when the user submits a form containing login 149 // information. If the user responds to a subsequent "Do you want to save 150 // this password?" prompt, we ask this object to save or blacklist the 151 // associated login information in Chrome's password store. 152 scoped_ptr<password_manager::PasswordFormManager> form_manager_; 153 154 // Stores whether autofill was blocked due to a user's decision to blacklist 155 // the current site ("Never save passwords for this site"). 156 bool autofill_blocked_; 157 158 // The origin of the form we're currently dealing with; we'll use this to 159 // determine which PasswordStore changes we should care about when updating 160 // |password_form_map_|. 161 GURL origin_; 162 163 DISALLOW_COPY_AND_ASSIGN(ManagePasswordsUIController); 164 }; 165 166 #endif // CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_H_ 167