| 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 |