login_prompt_views.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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#include "chrome/browser/ui/login/login_prompt.h" 6 7#include "base/strings/string16.h" 8#include "base/strings/utf_string_conversions.h" 9#include "chrome/browser/password_manager/password_manager.h" 10#include "chrome/browser/tab_contents/tab_util.h" 11#include "chrome/browser/ui/views/constrained_window_views.h" 12#include "chrome/browser/ui/views/login_view.h" 13#include "chrome/common/chrome_switches.h" 14#include "components/web_modal/web_contents_modal_dialog_host.h" 15#include "components/web_modal/web_contents_modal_dialog_manager.h" 16#include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" 17#include "content/public/browser/browser_thread.h" 18#include "content/public/browser/render_view_host.h" 19#include "content/public/browser/web_contents.h" 20#include "content/public/browser/web_contents_view.h" 21#include "grit/generated_resources.h" 22#include "net/url_request/url_request.h" 23#include "ui/base/l10n/l10n_util.h" 24#include "ui/views/widget/widget.h" 25#include "ui/views/window/dialog_delegate.h" 26 27using autofill::PasswordForm; 28using content::BrowserThread; 29using content::WebContents; 30using web_modal::WebContentsModalDialogManager; 31using web_modal::WebContentsModalDialogManagerDelegate; 32 33// ---------------------------------------------------------------------------- 34// LoginHandlerViews 35 36// This class simply forwards the authentication from the LoginView (on 37// the UI thread) to the net::URLRequest (on the I/O thread). 38// This class uses ref counting to ensure that it lives until all InvokeLaters 39// have been called. 40class LoginHandlerViews : public LoginHandler, 41 public views::DialogDelegate { 42 public: 43 LoginHandlerViews(net::AuthChallengeInfo* auth_info, net::URLRequest* request) 44 : LoginHandler(auth_info, request), 45 login_view_(NULL), 46 dialog_(NULL) { 47 } 48 49 // LoginModelObserver implementation. 50 virtual void OnAutofillDataAvailable(const string16& username, 51 const string16& password) OVERRIDE { 52 // Nothing to do here since LoginView takes care of autofill for win. 53 } 54 virtual void OnLoginModelDestroying() OVERRIDE {} 55 56 // views::DialogDelegate methods: 57 virtual string16 GetDialogButtonLabel( 58 ui::DialogButton button) const OVERRIDE { 59 if (button == ui::DIALOG_BUTTON_OK) 60 return l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_OK_BUTTON_LABEL); 61 return DialogDelegate::GetDialogButtonLabel(button); 62 } 63 64 virtual string16 GetWindowTitle() const OVERRIDE { 65 return l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_TITLE); 66 } 67 68 virtual void WindowClosing() OVERRIDE { 69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 70 71 WebContents* tab = GetWebContentsForLogin(); 72 if (tab) 73 tab->GetRenderViewHost()->SetIgnoreInputEvents(false); 74 75 // Reference is no longer valid. 76 dialog_ = NULL; 77 78 CancelAuth(); 79 } 80 81 virtual void DeleteDelegate() OVERRIDE { 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 83 84 // The widget is going to delete itself; clear our pointer. 85 dialog_ = NULL; 86 SetModel(NULL); 87 88 ReleaseSoon(); 89 } 90 91 virtual ui::ModalType GetModalType() const OVERRIDE { 92#if defined(USE_ASH) 93 return ui::MODAL_TYPE_CHILD; 94#else 95 return views::WidgetDelegate::GetModalType(); 96#endif 97 } 98 99 virtual bool Cancel() OVERRIDE { 100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 101 102 CancelAuth(); 103 return true; 104 } 105 106 virtual bool Accept() OVERRIDE { 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 108 109 SetAuth(login_view_->GetUsername(), login_view_->GetPassword()); 110 return true; 111 } 112 113 // TODO(wittman): Remove this override once we move to the new style frame 114 // view on all dialogs. 115 virtual views::NonClientFrameView* CreateNonClientFrameView( 116 views::Widget* widget) OVERRIDE { 117 return CreateConstrainedStyleNonClientFrameView( 118 widget, 119 GetWebContentsForLogin()->GetBrowserContext()); 120 } 121 122 virtual views::View* GetInitiallyFocusedView() OVERRIDE { 123 return login_view_->GetInitiallyFocusedView(); 124 } 125 126 virtual views::View* GetContentsView() OVERRIDE { 127 return login_view_; 128 } 129 virtual views::Widget* GetWidget() OVERRIDE { 130 return login_view_->GetWidget(); 131 } 132 virtual const views::Widget* GetWidget() const OVERRIDE { 133 return login_view_->GetWidget(); 134 } 135 136 // LoginHandler: 137 138 virtual void BuildViewForPasswordManager( 139 PasswordManager* manager, 140 const string16& explanation) OVERRIDE { 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 142 143 // Create a new LoginView and set the model for it. The model (password 144 // manager) is owned by the WebContents, but the view is parented to the 145 // browser window, so the view may be destroyed after the password 146 // manager. The view listens for model destruction and unobserves 147 // accordingly. 148 login_view_ = new LoginView(explanation, manager); 149 150 // Scary thread safety note: This can potentially be called *after* SetAuth 151 // or CancelAuth (say, if the request was cancelled before the UI thread got 152 // control). However, that's OK since any UI interaction in those functions 153 // will occur via an InvokeLater on the UI thread, which is guaranteed 154 // to happen after this is called (since this was InvokeLater'd first). 155 WebContents* requesting_contents = GetWebContentsForLogin(); 156 WebContentsModalDialogManager* web_contents_modal_dialog_manager = 157 WebContentsModalDialogManager::FromWebContents(requesting_contents); 158 WebContentsModalDialogManagerDelegate* modal_delegate = 159 web_contents_modal_dialog_manager->delegate(); 160 DCHECK(modal_delegate); 161 dialog_ = views::Widget::CreateWindowAsFramelessChild( 162 this, 163 requesting_contents->GetView()->GetNativeView(), 164 modal_delegate->GetWebContentsModalDialogHost()->GetHostView()); 165 web_contents_modal_dialog_manager->ShowDialog(dialog_->GetNativeView()); 166 web_contents_modal_dialog_manager->SetCloseOnInterstitialWebUI( 167 dialog_->GetNativeView(), true); 168 NotifyAuthNeeded(); 169 } 170 171 virtual void CloseDialog() OVERRIDE { 172 // The hosting widget may have been freed. 173 if (dialog_) 174 dialog_->Close(); 175 } 176 177 private: 178 friend class base::RefCountedThreadSafe<LoginHandlerViews>; 179 friend class LoginPrompt; 180 181 virtual ~LoginHandlerViews() {} 182 183 // The LoginView that contains the user's login information 184 LoginView* login_view_; 185 186 views::Widget* dialog_; 187 188 DISALLOW_COPY_AND_ASSIGN(LoginHandlerViews); 189}; 190 191// static 192LoginHandler* LoginHandler::Create(net::AuthChallengeInfo* auth_info, 193 net::URLRequest* request) { 194 return new LoginHandlerViews(auth_info, request); 195} 196