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(password_manager::PasswordFormManager* form_manager); 39 40 // Called when a form is autofilled with login information, so we can manage 41 // password credentials for the current site which are stored in 42 // |password_form_map|. This stores a copy of |password_form_map| and shows 43 // the manage password icon. 44 void OnPasswordAutofilled(const autofill::PasswordFormMap& password_form_map); 45 46 // Called when a form is _not_ autofilled due to user blacklisting. This 47 // stores a copy of |password_form_map| so that we can offer the user the 48 // ability to reenable the manager for this form. 49 void OnBlacklistBlockedAutofill( 50 const autofill::PasswordFormMap& password_form_map); 51 52 // PasswordStore::Observer implementation. 53 virtual void OnLoginsChanged( 54 const password_manager::PasswordStoreChangeList& changes) OVERRIDE; 55 56 // Called from the model when the user chooses to save a password; passes the 57 // action off to the FormManager. The controller MUST be in a pending state, 58 // and WILL be in MANAGE_STATE after this method executes. 59 virtual void SavePassword(); 60 61 // Called from the model when the user chooses to never save passwords; passes 62 // the action off to the FormManager. The controller MUST be in a pending 63 // state, and WILL be in BLACKLIST_STATE after this method executes. 64 virtual void NeverSavePassword(); 65 66 // Called from the model when the user chooses to unblacklist the site. The 67 // controller MUST be in BLACKLIST_STATE, and WILL be in MANAGE_STATE after 68 // this method executes. 69 virtual void UnblacklistSite(); 70 71 // Open a new tab, pointing to the password manager settings page. 72 virtual void NavigateToPasswordManagerSettingsPage(); 73 74 virtual const autofill::PasswordForm& PendingCredentials() const; 75 76 // Set the state of the Omnibox icon, and possibly show the associated bubble 77 // without user interaction. 78 virtual void UpdateIconAndBubbleState(ManagePasswordsIcon* icon); 79 80 password_manager::ui::State state() const { return state_; } 81 82 // True if a password is sitting around, waiting for a user to decide whether 83 // or not to save it. 84 bool PasswordPendingUserDecision() const; 85 86 const autofill::PasswordFormMap best_matches() const { 87 return password_form_map_; 88 } 89 90 const GURL& origin() const { return origin_; } 91 92 protected: 93 explicit ManagePasswordsUIController( 94 content::WebContents* web_contents); 95 96 // content::WebContentsObserver: 97 virtual void DidNavigateMainFrame( 98 const content::LoadCommittedDetails& details, 99 const content::FrameNavigateParams& params) OVERRIDE; 100 101 // All previously stored credentials for a specific site. Set by 102 // OnPasswordSubmitted(), OnPasswordAutofilled(), or 103 // OnBlacklistBlockedAutofill(). Protected, not private, so we can mess with 104 // the value in ManagePasswordsUIControllerMock. 105 autofill::PasswordFormMap password_form_map_; 106 107 // We create copies of PasswordForm objects that come in via OnLoginsChanged() 108 // and store them in this vector as well as in |password_form_map_| to ensure 109 // that we destroy them correctly. 110 ScopedVector<autofill::PasswordForm> new_password_forms_; 111 112 // The current state of the password manager. Protected so we can manipulate 113 // the value in tests. 114 password_manager::ui::State state_; 115 116 // Used to measure the amount of time on a page; if it's less than some 117 // reasonable limit, then don't close the bubble upon navigation. We create 118 // (and destroy) the timer in DidNavigateMainFrame. 119 scoped_ptr<base::ElapsedTimer> timer_; 120 121 private: 122 friend class content::WebContentsUserData<ManagePasswordsUIController>; 123 124 // Shows the password bubble without user interaction. The controller MUST 125 // be in PENDING_PASSWORD_AND_BUBBLE_STATE. 126 void ShowBubbleWithoutUserInteraction(); 127 128 // Called when a passwordform is autofilled, when a new passwordform is 129 // submitted, or when a navigation occurs to update the visibility of the 130 // manage passwords icon and bubble. 131 void UpdateBubbleAndIconVisibility(); 132 133 // content::WebContentsObserver: 134 virtual void WebContentsDestroyed() OVERRIDE; 135 136 // Set by OnPasswordSubmitted() when the user submits a form containing login 137 // information. If the user responds to a subsequent "Do you want to save 138 // this password?" prompt, we ask this object to save or blacklist the 139 // associated login information in Chrome's password store. 140 scoped_ptr<password_manager::PasswordFormManager> form_manager_; 141 142 // Stores whether autofill was blocked due to a user's decision to blacklist 143 // the current site ("Never save passwords for this site"). 144 bool autofill_blocked_; 145 146 // The origin of the form we're currently dealing with; we'll use this to 147 // determine which PasswordStore changes we should care about when updating 148 // |password_form_map_|. 149 GURL origin_; 150 151 DISALLOW_COPY_AND_ASSIGN(ManagePasswordsUIController); 152 }; 153 154 #endif // CHROME_BROWSER_UI_PASSWORDS_MANAGE_PASSWORDS_UI_CONTROLLER_H_ 155