1 // Copyright (c) 2012 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_LOGIN_LOGIN_PROMPT_H_ 6 #define CHROME_BROWSER_UI_LOGIN_LOGIN_PROMPT_H_ 7 8 #include <string> 9 10 #include "base/basictypes.h" 11 #include "base/synchronization/lock.h" 12 #include "chrome/browser/password_manager/password_manager.h" 13 #include "content/public/browser/notification_observer.h" 14 #include "content/public/browser/resource_dispatcher_host_login_delegate.h" 15 16 class GURL; 17 18 namespace content { 19 class RenderViewHostDelegate; 20 class NotificationRegistrar; 21 } // namespace content 22 23 namespace net { 24 class AuthChallengeInfo; 25 class HttpNetworkSession; 26 class URLRequest; 27 } // namespace net 28 29 // This is the base implementation for the OS-specific classes that route 30 // authentication info to the net::URLRequest that needs it. These functions 31 // must be implemented in a thread safe manner. 32 class LoginHandler : public content::ResourceDispatcherHostLoginDelegate, 33 public LoginModelObserver, 34 public content::NotificationObserver { 35 public: 36 LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request); 37 38 // Builds the platform specific LoginHandler. Used from within 39 // CreateLoginPrompt() which creates tasks. 40 static LoginHandler* Create(net::AuthChallengeInfo* auth_info, 41 net::URLRequest* request); 42 43 // ResourceDispatcherHostLoginDelegate implementation: 44 virtual void OnRequestCancelled() OVERRIDE; 45 46 // Initializes the underlying platform specific view. 47 virtual void BuildViewForPasswordManager(PasswordManager* manager, 48 const string16& explanation) = 0; 49 50 // Sets information about the authentication type (|form|) and the 51 // |password_manager| for this profile. 52 void SetPasswordForm(const content::PasswordForm& form); 53 void SetPasswordManager(PasswordManager* password_manager); 54 55 // Returns the WebContents that needs authentication. 56 content::WebContents* GetWebContentsForLogin() const; 57 58 // Resend the request with authentication credentials. 59 // This function can be called from either thread. 60 void SetAuth(const string16& username, const string16& password); 61 62 // Display the error page without asking for credentials again. 63 // This function can be called from either thread. 64 void CancelAuth(); 65 66 // Implements the content::NotificationObserver interface. 67 // Listens for AUTH_SUPPLIED and AUTH_CANCELLED notifications from other 68 // LoginHandlers so that this LoginHandler has the chance to dismiss itself 69 // if it was waiting for the same authentication. 70 virtual void Observe(int type, 71 const content::NotificationSource& source, 72 const content::NotificationDetails& details) OVERRIDE; 73 74 // Who/where/what asked for the authentication. 75 const net::AuthChallengeInfo* auth_info() const { return auth_info_.get(); } 76 77 // Returns whether authentication had been handled (SetAuth or CancelAuth). 78 bool WasAuthHandled() const; 79 80 protected: 81 virtual ~LoginHandler(); 82 83 void SetModel(LoginModel* model); 84 85 // Notify observers that authentication is needed. 86 void NotifyAuthNeeded(); 87 88 // Performs necessary cleanup before deletion. 89 void ReleaseSoon(); 90 91 // Closes the native dialog. 92 virtual void CloseDialog() = 0; 93 94 private: 95 // Starts observing notifications from other LoginHandlers. 96 void AddObservers(); 97 98 // Stops observing notifications from other LoginHandlers. 99 void RemoveObservers(); 100 101 // Notify observers that authentication is supplied. 102 void NotifyAuthSupplied(const string16& username, 103 const string16& password); 104 105 // Notify observers that authentication is cancelled. 106 void NotifyAuthCancelled(); 107 108 // Marks authentication as handled and returns the previous handled 109 // state. 110 bool TestAndSetAuthHandled(); 111 112 // Calls SetAuth from the IO loop. 113 void SetAuthDeferred(const string16& username, 114 const string16& password); 115 116 // Calls CancelAuth from the IO loop. 117 void CancelAuthDeferred(); 118 119 // Closes the view_contents from the UI loop. 120 void CloseContentsDeferred(); 121 122 // True if we've handled auth (SetAuth or CancelAuth has been called). 123 bool handled_auth_; 124 mutable base::Lock handled_auth_lock_; 125 126 // Who/where/what asked for the authentication. 127 scoped_refptr<net::AuthChallengeInfo> auth_info_; 128 129 // The request that wants login data. 130 // This should only be accessed on the IO loop. 131 net::URLRequest* request_; 132 133 // The HttpNetworkSession |request_| is associated with. 134 const net::HttpNetworkSession* http_network_session_; 135 136 // The PasswordForm sent to the PasswordManager. This is so we can refer to it 137 // when later notifying the password manager if the credentials were accepted 138 // or rejected. 139 // This should only be accessed on the UI loop. 140 content::PasswordForm password_form_; 141 142 // Points to the password manager owned by the WebContents requesting auth. 143 // This should only be accessed on the UI loop. 144 PasswordManager* password_manager_; 145 146 // Cached from the net::URLRequest, in case it goes NULL on us. 147 int render_process_host_id_; 148 int tab_contents_id_; 149 150 // If not null, points to a model we need to notify of our own destruction 151 // so it doesn't try and access this when its too late. 152 LoginModel* login_model_; 153 154 // Observes other login handlers so this login handler can respond. 155 // This is only accessed on the UI thread. 156 scoped_ptr<content::NotificationRegistrar> registrar_; 157 }; 158 159 // Details to provide the content::NotificationObserver. Used by the automation 160 // proxy for testing. 161 class LoginNotificationDetails { 162 public: 163 explicit LoginNotificationDetails(LoginHandler* handler) 164 : handler_(handler) {} 165 LoginHandler* handler() const { return handler_; } 166 167 private: 168 LoginNotificationDetails() {} 169 170 LoginHandler* handler_; // Where to send the response. 171 172 DISALLOW_COPY_AND_ASSIGN(LoginNotificationDetails); 173 }; 174 175 // Details to provide the NotificationObserver. Used by the automation proxy 176 // for testing and by other LoginHandlers to dismiss themselves when an 177 // identical auth is supplied. 178 class AuthSuppliedLoginNotificationDetails : public LoginNotificationDetails { 179 public: 180 AuthSuppliedLoginNotificationDetails(LoginHandler* handler, 181 const string16& username, 182 const string16& password) 183 : LoginNotificationDetails(handler), 184 username_(username), 185 password_(password) {} 186 const string16& username() const { return username_; } 187 const string16& password() const { return password_; } 188 189 private: 190 // The username that was used for the authentication. 191 const string16 username_; 192 193 // The password that was used for the authentication. 194 const string16 password_; 195 196 DISALLOW_COPY_AND_ASSIGN(AuthSuppliedLoginNotificationDetails); 197 }; 198 199 // Prompts the user for their username and password. This is designed to 200 // be called on the background (I/O) thread, in response to 201 // net::URLRequest::Delegate::OnAuthRequired. The prompt will be created 202 // on the main UI thread via a call to UI loop's InvokeLater, and will send the 203 // credentials back to the net::URLRequest on the calling thread. 204 // A LoginHandler object (which lives on the calling thread) is returned, 205 // which can be used to set or cancel authentication programmatically. The 206 // caller must invoke OnRequestCancelled() on this LoginHandler before 207 // destroying the net::URLRequest. 208 LoginHandler* CreateLoginPrompt(net::AuthChallengeInfo* auth_info, 209 net::URLRequest* request); 210 211 // Helper to remove the ref from an net::URLRequest to the LoginHandler. 212 // Should only be called from the IO thread, since it accesses an 213 // net::URLRequest. 214 void ResetLoginHandlerForRequest(net::URLRequest* request); 215 216 // Get the signon_realm under which the identity should be saved. 217 std::string GetSignonRealm(const GURL& url, 218 const net::AuthChallengeInfo& auth_info); 219 220 #endif // CHROME_BROWSER_UI_LOGIN_LOGIN_PROMPT_H_ 221