OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/login_prompt.h" | 5 #include "chrome/browser/login_prompt.h" |
6 | 6 |
7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
8 | 8 |
9 #include "app/l10n_util.h" | 9 #include "app/l10n_util.h" |
10 #include "base/message_loop.h" | 10 #include "chrome/browser/chrome_thread.h" |
11 #include "chrome/browser/gtk/constrained_window_gtk.h" | 11 #include "chrome/browser/gtk/constrained_window_gtk.h" |
12 #include "chrome/browser/login_model.h" | 12 #include "chrome/browser/login_model.h" |
13 #include "chrome/browser/password_manager/password_manager.h" | 13 #include "chrome/browser/password_manager/password_manager.h" |
14 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" | 14 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" |
15 #include "chrome/browser/tab_contents/navigation_controller.h" | 15 #include "chrome/browser/tab_contents/navigation_controller.h" |
16 #include "chrome/browser/tab_contents/tab_contents.h" | 16 #include "chrome/browser/tab_contents/tab_contents.h" |
17 #include "chrome/browser/tab_contents/tab_util.h" | 17 #include "chrome/browser/tab_contents/tab_util.h" |
18 #include "chrome/common/gtk_util.h" | 18 #include "chrome/common/gtk_util.h" |
19 #include "chrome/common/notification_service.h" | 19 #include "chrome/common/notification_service.h" |
20 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" |
21 #include "net/url_request/url_request.h" | 21 #include "net/url_request/url_request.h" |
22 | 22 |
23 using webkit_glue::PasswordForm; | 23 using webkit_glue::PasswordForm; |
24 | 24 |
25 // ---------------------------------------------------------------------------- | 25 // ---------------------------------------------------------------------------- |
26 // LoginHandlerGtk | 26 // LoginHandlerGtk |
27 | 27 |
28 // This class simply forwards the authentication from the LoginView (on | 28 // This class simply forwards the authentication from the LoginView (on |
29 // the UI thread) to the URLRequest (on the I/O thread). | 29 // the UI thread) to the URLRequest (on the I/O thread). |
30 // This class uses ref counting to ensure that it lives until all InvokeLaters | 30 // This class uses ref counting to ensure that it lives until all InvokeLaters |
31 // have been called. | 31 // have been called. |
32 class LoginHandlerGtk : public LoginHandler, | 32 class LoginHandlerGtk : public LoginHandler, |
33 public base::RefCountedThreadSafe<LoginHandlerGtk>, | 33 public base::RefCountedThreadSafe<LoginHandlerGtk>, |
34 public ConstrainedWindowGtkDelegate, | 34 public ConstrainedWindowGtkDelegate, |
35 public LoginModelObserver { | 35 public LoginModelObserver { |
36 public: | 36 public: |
37 LoginHandlerGtk(URLRequest* request, MessageLoop* ui_loop) | 37 LoginHandlerGtk(URLRequest* request) |
38 : handled_auth_(false), | 38 : handled_auth_(false), |
39 dialog_(NULL), | 39 dialog_(NULL), |
40 ui_loop_(ui_loop), | |
41 request_(request), | 40 request_(request), |
42 request_loop_(MessageLoop::current()), | |
43 password_manager_(NULL), | 41 password_manager_(NULL), |
44 login_model_(NULL) { | 42 login_model_(NULL) { |
45 DCHECK(request_) << "LoginHandlerGtk constructed with NULL request"; | 43 DCHECK(request_) << "LoginHandlerGtk constructed with NULL request"; |
46 | 44 |
47 AddRef(); // matched by ReleaseLater. | 45 AddRef(); // matched by ReleaseLater. |
48 if (!ResourceDispatcherHost::RenderViewForRequest(request_, | 46 if (!ResourceDispatcherHost::RenderViewForRequest(request_, |
49 &render_process_host_id_, | 47 &render_process_host_id_, |
50 &tab_contents_id_)) { | 48 &tab_contents_id_)) { |
51 NOTREACHED(); | 49 NOTREACHED(); |
52 } | 50 } |
(...skipping 23 matching lines...) Expand all Loading... |
76 WideToUTF8(username).c_str()); | 74 WideToUTF8(username).c_str()); |
77 gtk_entry_set_text(GTK_ENTRY(password_entry_), | 75 gtk_entry_set_text(GTK_ENTRY(password_entry_), |
78 WideToUTF8(password).c_str()); | 76 WideToUTF8(password).c_str()); |
79 gtk_editable_select_region(GTK_EDITABLE(username_entry_), 0, -1); | 77 gtk_editable_select_region(GTK_EDITABLE(username_entry_), 0, -1); |
80 } | 78 } |
81 } | 79 } |
82 | 80 |
83 // LoginHandler: | 81 // LoginHandler: |
84 virtual void BuildViewForPasswordManager(PasswordManager* manager, | 82 virtual void BuildViewForPasswordManager(PasswordManager* manager, |
85 std::wstring explanation) { | 83 std::wstring explanation) { |
86 DCHECK(MessageLoop::current() == ui_loop_); | 84 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
87 | 85 |
88 root_.Own(gtk_vbox_new(NULL, gtk_util::kContentAreaBorder)); | 86 root_.Own(gtk_vbox_new(NULL, gtk_util::kContentAreaBorder)); |
89 GtkWidget* label = gtk_label_new(WideToUTF8(explanation).c_str()); | 87 GtkWidget* label = gtk_label_new(WideToUTF8(explanation).c_str()); |
90 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | 88 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); |
91 gtk_box_pack_start(GTK_BOX(root_.get()), label, FALSE, FALSE, 0); | 89 gtk_box_pack_start(GTK_BOX(root_.get()), label, FALSE, FALSE, 0); |
92 | 90 |
93 username_entry_ = gtk_entry_new(); | 91 username_entry_ = gtk_entry_new(); |
94 gtk_entry_set_activates_default(GTK_ENTRY(username_entry_), TRUE); | 92 gtk_entry_set_activates_default(GTK_ENTRY(username_entry_), TRUE); |
95 | 93 |
96 password_entry_ = gtk_entry_new(); | 94 password_entry_ = gtk_entry_new(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 | 137 |
140 virtual void SetPasswordForm(const webkit_glue::PasswordForm& form) { | 138 virtual void SetPasswordForm(const webkit_glue::PasswordForm& form) { |
141 password_form_ = form; | 139 password_form_ = form; |
142 } | 140 } |
143 | 141 |
144 virtual void SetPasswordManager(PasswordManager* password_manager) { | 142 virtual void SetPasswordManager(PasswordManager* password_manager) { |
145 password_manager_ = password_manager; | 143 password_manager_ = password_manager; |
146 } | 144 } |
147 | 145 |
148 virtual TabContents* GetTabContentsForLogin() { | 146 virtual TabContents* GetTabContentsForLogin() { |
149 DCHECK(MessageLoop::current() == ui_loop_); | 147 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
150 | 148 |
151 return tab_util::GetTabContentsByID(render_process_host_id_, | 149 return tab_util::GetTabContentsByID(render_process_host_id_, |
152 tab_contents_id_); | 150 tab_contents_id_); |
153 } | 151 } |
154 | 152 |
155 virtual void SetAuth(const std::wstring& username, | 153 virtual void SetAuth(const std::wstring& username, |
156 const std::wstring& password) { | 154 const std::wstring& password) { |
157 if (WasAuthHandled(true)) | 155 if (WasAuthHandled(true)) |
158 return; | 156 return; |
159 | 157 |
160 // Tell the password manager the credentials were submitted / accepted. | 158 // Tell the password manager the credentials were submitted / accepted. |
161 if (password_manager_) { | 159 if (password_manager_) { |
162 password_form_.username_value = WideToUTF16Hack(username); | 160 password_form_.username_value = WideToUTF16Hack(username); |
163 password_form_.password_value = WideToUTF16Hack(password); | 161 password_form_.password_value = WideToUTF16Hack(password); |
164 password_manager_->ProvisionallySavePassword(password_form_); | 162 password_manager_->ProvisionallySavePassword(password_form_); |
165 } | 163 } |
166 | 164 |
167 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 165 ChromeThread::PostTask( |
168 this, &LoginHandlerGtk::CloseContentsDeferred)); | 166 ChromeThread::UI, FROM_HERE, |
169 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 167 NewRunnableMethod(this, &LoginHandlerGtk::CloseContentsDeferred)); |
170 this, &LoginHandlerGtk::SendNotifications)); | 168 ChromeThread::PostTask( |
171 request_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 169 ChromeThread::UI, FROM_HERE, |
172 this, &LoginHandlerGtk::SetAuthDeferred, username, password)); | 170 NewRunnableMethod(this, &LoginHandlerGtk::SendNotifications)); |
| 171 ChromeThread::PostTask( |
| 172 ChromeThread::IO, FROM_HERE, |
| 173 NewRunnableMethod(this, &LoginHandlerGtk::SetAuthDeferred, username, |
| 174 password)); |
173 } | 175 } |
174 | 176 |
175 virtual void CancelAuth() { | 177 virtual void CancelAuth() { |
176 if (WasAuthHandled(true)) | 178 if (WasAuthHandled(true)) |
177 return; | 179 return; |
178 | 180 |
179 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 181 ChromeThread::PostTask( |
180 this, &LoginHandlerGtk::CloseContentsDeferred)); | 182 ChromeThread::UI, FROM_HERE, |
181 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 183 NewRunnableMethod(this, &LoginHandlerGtk::CloseContentsDeferred)); |
182 this, &LoginHandlerGtk::SendNotifications)); | 184 ChromeThread::PostTask( |
183 request_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 185 ChromeThread::UI, FROM_HERE, |
184 this, &LoginHandlerGtk::CancelAuthDeferred)); | 186 NewRunnableMethod(this, &LoginHandlerGtk::SendNotifications)); |
| 187 ChromeThread::PostTask( |
| 188 ChromeThread::IO, FROM_HERE, |
| 189 NewRunnableMethod(this, &LoginHandlerGtk::CancelAuthDeferred)); |
185 } | 190 } |
186 | 191 |
187 virtual void OnRequestCancelled() { | 192 virtual void OnRequestCancelled() { |
188 DCHECK(MessageLoop::current() == request_loop_) << | 193 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)) << |
189 "Why is OnRequestCancelled called from the UI thread?"; | 194 "Why is OnRequestCancelled called from the UI thread?"; |
190 | 195 |
191 // Reference is no longer valid. | 196 // Reference is no longer valid. |
192 request_ = NULL; | 197 request_ = NULL; |
193 | 198 |
194 // Give up on auth if the request was cancelled. | 199 // Give up on auth if the request was cancelled. |
195 CancelAuth(); | 200 CancelAuth(); |
196 } | 201 } |
197 | 202 |
198 // Overridden from ConstrainedWindowGtkDelegate: | 203 // Overridden from ConstrainedWindowGtkDelegate: |
199 virtual GtkWidget* GetWidgetRoot() { | 204 virtual GtkWidget* GetWidgetRoot() { |
200 return root_.get(); | 205 return root_.get(); |
201 } | 206 } |
202 | 207 |
203 virtual void DeleteDelegate() { | 208 virtual void DeleteDelegate() { |
204 if (!WasAuthHandled(true)) { | 209 if (!WasAuthHandled(true)) { |
205 request_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 210 ChromeThread::PostTask( |
206 this, &LoginHandlerGtk::CancelAuthDeferred)); | 211 ChromeThread::IO, FROM_HERE, |
207 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 212 NewRunnableMethod(this, &LoginHandlerGtk::CancelAuthDeferred)); |
208 this, &LoginHandlerGtk::SendNotifications)); | 213 ChromeThread::PostTask( |
| 214 ChromeThread::UI, FROM_HERE, |
| 215 NewRunnableMethod(this, &LoginHandlerGtk::SendNotifications)); |
209 } | 216 } |
210 | 217 |
211 SetModel(NULL); | 218 SetModel(NULL); |
212 | 219 |
213 // Delete this object once all InvokeLaters have been called. | 220 // Delete this object once all InvokeLaters have been called. |
214 request_loop_->ReleaseSoon(FROM_HERE, this); | 221 ChromeThread::ReleaseSoon(ChromeThread::IO, FROM_HERE, this); |
215 } | 222 } |
216 | 223 |
217 private: | 224 private: |
218 friend class LoginPrompt; | 225 friend class LoginPrompt; |
219 | 226 |
220 // Calls SetAuth from the request_loop. | 227 // Calls SetAuth from the IO loop. |
221 void SetAuthDeferred(const std::wstring& username, | 228 void SetAuthDeferred(const std::wstring& username, |
222 const std::wstring& password) { | 229 const std::wstring& password) { |
223 DCHECK(MessageLoop::current() == request_loop_); | 230 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
224 | 231 |
225 if (request_) { | 232 if (request_) { |
226 request_->SetAuth(username, password); | 233 request_->SetAuth(username, password); |
227 ResetLoginHandlerForRequest(request_); | 234 ResetLoginHandlerForRequest(request_); |
228 } | 235 } |
229 } | 236 } |
230 | 237 |
231 // Calls CancelAuth from the request_loop. | 238 // Calls CancelAuth from the IO loop. |
232 void CancelAuthDeferred() { | 239 void CancelAuthDeferred() { |
233 DCHECK(MessageLoop::current() == request_loop_); | 240 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); |
234 | 241 |
235 if (request_) { | 242 if (request_) { |
236 request_->CancelAuth(); | 243 request_->CancelAuth(); |
237 // Verify that CancelAuth does destroy the request via our delegate. | 244 // Verify that CancelAuth does destroy the request via our delegate. |
238 DCHECK(request_ != NULL); | 245 DCHECK(request_ != NULL); |
239 ResetLoginHandlerForRequest(request_); | 246 ResetLoginHandlerForRequest(request_); |
240 } | 247 } |
241 } | 248 } |
242 | 249 |
243 // Closes the view_contents from the UI loop. | 250 // Closes the view_contents from the UI loop. |
244 void CloseContentsDeferred() { | 251 void CloseContentsDeferred() { |
245 DCHECK(MessageLoop::current() == ui_loop_); | 252 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
246 | 253 |
247 // The hosting ConstrainedWindow may have been freed. | 254 // The hosting ConstrainedWindow may have been freed. |
248 if (dialog_) | 255 if (dialog_) |
249 dialog_->CloseConstrainedWindow(); | 256 dialog_->CloseConstrainedWindow(); |
250 } | 257 } |
251 | 258 |
252 // Returns whether authentication had been handled (SetAuth or CancelAuth). | 259 // Returns whether authentication had been handled (SetAuth or CancelAuth). |
253 // If |set_handled| is true, it will mark authentication as handled. | 260 // If |set_handled| is true, it will mark authentication as handled. |
254 bool WasAuthHandled(bool set_handled) { | 261 bool WasAuthHandled(bool set_handled) { |
255 AutoLock lock(handled_auth_lock_); | 262 AutoLock lock(handled_auth_lock_); |
256 bool was_handled = handled_auth_; | 263 bool was_handled = handled_auth_; |
257 if (set_handled) | 264 if (set_handled) |
258 handled_auth_ = true; | 265 handled_auth_ = true; |
259 return was_handled; | 266 return was_handled; |
260 } | 267 } |
261 | 268 |
262 // Notify observers that authentication is needed or received. The automation | 269 // Notify observers that authentication is needed or received. The automation |
263 // proxy uses this for testing. | 270 // proxy uses this for testing. |
264 void SendNotifications() { | 271 void SendNotifications() { |
265 DCHECK(MessageLoop::current() == ui_loop_); | 272 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
266 | 273 |
267 NotificationService* service = NotificationService::current(); | 274 NotificationService* service = NotificationService::current(); |
268 TabContents* requesting_contents = GetTabContentsForLogin(); | 275 TabContents* requesting_contents = GetTabContentsForLogin(); |
269 if (!requesting_contents) | 276 if (!requesting_contents) |
270 return; | 277 return; |
271 | 278 |
272 NavigationController* controller = &requesting_contents->controller(); | 279 NavigationController* controller = &requesting_contents->controller(); |
273 | 280 |
274 if (!WasAuthHandled(false)) { | 281 if (!WasAuthHandled(false)) { |
275 LoginNotificationDetails details(this); | 282 LoginNotificationDetails details(this); |
276 service->Notify(NotificationType::AUTH_NEEDED, | 283 service->Notify(NotificationType::AUTH_NEEDED, |
277 Source<NavigationController>(controller), | 284 Source<NavigationController>(controller), |
278 Details<LoginNotificationDetails>(&details)); | 285 Details<LoginNotificationDetails>(&details)); |
279 } else { | 286 } else { |
280 service->Notify(NotificationType::AUTH_SUPPLIED, | 287 service->Notify(NotificationType::AUTH_SUPPLIED, |
281 Source<NavigationController>(controller), | 288 Source<NavigationController>(controller), |
282 NotificationService::NoDetails()); | 289 NotificationService::NoDetails()); |
283 } | 290 } |
284 } | 291 } |
285 | 292 |
286 static void OnOKClicked(GtkButton *button, LoginHandlerGtk* handler) { | 293 static void OnOKClicked(GtkButton *button, LoginHandlerGtk* handler) { |
287 DCHECK(MessageLoop::current() == handler->ui_loop_); | 294 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
288 | 295 |
289 handler->SetAuth( | 296 handler->SetAuth( |
290 UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(handler->username_entry_))), | 297 UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(handler->username_entry_))), |
291 UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(handler->password_entry_)))); | 298 UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(handler->password_entry_)))); |
292 } | 299 } |
293 | 300 |
294 static void OnCancelClicked(GtkButton *button, LoginHandlerGtk* handler) { | 301 static void OnCancelClicked(GtkButton *button, LoginHandlerGtk* handler) { |
295 DCHECK(MessageLoop::current() == handler->ui_loop_); | 302 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
296 handler->CancelAuth(); | 303 handler->CancelAuth(); |
297 } | 304 } |
298 | 305 |
299 // True if we've handled auth (SetAuth or CancelAuth has been called). | 306 // True if we've handled auth (SetAuth or CancelAuth has been called). |
300 bool handled_auth_; | 307 bool handled_auth_; |
301 Lock handled_auth_lock_; | 308 Lock handled_auth_lock_; |
302 | 309 |
303 // The ConstrainedWindow that is hosting our LoginView. | 310 // The ConstrainedWindow that is hosting our LoginView. |
304 // This should only be accessed on the ui_loop_. | 311 // This should only be accessed on the UI loop. |
305 ConstrainedWindow* dialog_; | 312 ConstrainedWindow* dialog_; |
306 | 313 |
307 // The MessageLoop of the thread that the ChromeViewContents lives in. | |
308 MessageLoop* ui_loop_; | |
309 | |
310 // The request that wants login data. | 314 // The request that wants login data. |
311 // This should only be accessed on the request_loop_. | 315 // This should only be accessed on the IO loop. |
312 URLRequest* request_; | 316 URLRequest* request_; |
313 | 317 |
314 // The MessageLoop of the thread that the URLRequest lives in. | |
315 MessageLoop* request_loop_; | |
316 | |
317 // The PasswordForm sent to the PasswordManager. This is so we can refer to it | 318 // The PasswordForm sent to the PasswordManager. This is so we can refer to it |
318 // when later notifying the password manager if the credentials were accepted | 319 // when later notifying the password manager if the credentials were accepted |
319 // or rejected. | 320 // or rejected. |
320 // This should only be accessed on the ui_loop_. | 321 // This should only be accessed on the UI loop. |
321 PasswordForm password_form_; | 322 PasswordForm password_form_; |
322 | 323 |
323 // Points to the password manager owned by the TabContents requesting auth. | 324 // Points to the password manager owned by the TabContents requesting auth. |
324 // Can be null if the TabContents is not a TabContents. | 325 // Can be null if the TabContents is not a TabContents. |
325 // This should only be accessed on the ui_loop_. | 326 // This should only be accessed on the UI loop. |
326 PasswordManager* password_manager_; | 327 PasswordManager* password_manager_; |
327 | 328 |
328 // Cached from the URLRequest, in case it goes NULL on us. | 329 // Cached from the URLRequest, in case it goes NULL on us. |
329 int render_process_host_id_; | 330 int render_process_host_id_; |
330 int tab_contents_id_; | 331 int tab_contents_id_; |
331 | 332 |
332 // The GtkWidgets that form our visual hierarchy: | 333 // The GtkWidgets that form our visual hierarchy: |
333 // The root container we pass to our parent. | 334 // The root container we pass to our parent. |
334 OwnedWidgetGtk root_; | 335 OwnedWidgetGtk root_; |
335 | 336 |
336 // GtkEntry widgets that the user types into. | 337 // GtkEntry widgets that the user types into. |
337 GtkWidget* username_entry_; | 338 GtkWidget* username_entry_; |
338 GtkWidget* password_entry_; | 339 GtkWidget* password_entry_; |
339 | 340 |
340 // If not null, points to a model we need to notify of our own destruction | 341 // If not null, points to a model we need to notify of our own destruction |
341 // so it doesn't try and access this when its too late. | 342 // so it doesn't try and access this when its too late. |
342 LoginModel* login_model_; | 343 LoginModel* login_model_; |
343 | 344 |
344 DISALLOW_COPY_AND_ASSIGN(LoginHandlerGtk); | 345 DISALLOW_COPY_AND_ASSIGN(LoginHandlerGtk); |
345 }; | 346 }; |
346 | 347 |
347 // static | 348 // static |
348 LoginHandler* LoginHandler::Create(URLRequest* request, MessageLoop* ui_loop) { | 349 LoginHandler* LoginHandler::Create(URLRequest* request) { |
349 return new LoginHandlerGtk(request, ui_loop); | 350 return new LoginHandlerGtk(request); |
350 } | 351 } |
OLD | NEW |