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