• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "grit/generated_resources.h"
21 #include "net/url_request/url_request.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/views/window/dialog_delegate.h"
25 
26 using autofill::PasswordForm;
27 using content::BrowserThread;
28 using content::WebContents;
29 using web_modal::WebContentsModalDialogManager;
30 using web_modal::WebContentsModalDialogManagerDelegate;
31 
32 // ----------------------------------------------------------------------------
33 // LoginHandlerViews
34 
35 // This class simply forwards the authentication from the LoginView (on
36 // the UI thread) to the net::URLRequest (on the I/O thread).
37 // This class uses ref counting to ensure that it lives until all InvokeLaters
38 // have been called.
39 class LoginHandlerViews : public LoginHandler,
40                           public views::DialogDelegate {
41  public:
LoginHandlerViews(net::AuthChallengeInfo * auth_info,net::URLRequest * request)42   LoginHandlerViews(net::AuthChallengeInfo* auth_info, net::URLRequest* request)
43       : LoginHandler(auth_info, request),
44         login_view_(NULL),
45         dialog_(NULL) {
46   }
47 
48   // LoginModelObserver implementation.
OnAutofillDataAvailable(const base::string16 & username,const base::string16 & password)49   virtual void OnAutofillDataAvailable(
50       const base::string16& username,
51       const base::string16& password) OVERRIDE {
52     // Nothing to do here since LoginView takes care of autofill for win.
53   }
OnLoginModelDestroying()54   virtual void OnLoginModelDestroying() OVERRIDE {}
55 
56   // views::DialogDelegate methods:
GetDialogButtonLabel(ui::DialogButton button) const57   virtual base::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 
GetWindowTitle() const64   virtual base::string16 GetWindowTitle() const OVERRIDE {
65     return l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_TITLE);
66   }
67 
WindowClosing()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 
DeleteDelegate()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 
GetModalType() const91   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 
Cancel()99   virtual bool Cancel() OVERRIDE {
100     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
101 
102     CancelAuth();
103     return true;
104   }
105 
Accept()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.
CreateNonClientFrameView(views::Widget * widget)115   virtual views::NonClientFrameView* CreateNonClientFrameView(
116       views::Widget* widget) OVERRIDE {
117     return CreateConstrainedStyleNonClientFrameView(
118         widget,
119         GetWebContentsForLogin()->GetBrowserContext());
120   }
121 
GetInitiallyFocusedView()122   virtual views::View* GetInitiallyFocusedView() OVERRIDE {
123     return login_view_->GetInitiallyFocusedView();
124   }
125 
GetContentsView()126   virtual views::View* GetContentsView() OVERRIDE {
127     return login_view_;
128   }
GetWidget()129   virtual views::Widget* GetWidget() OVERRIDE {
130     return login_view_->GetWidget();
131   }
GetWidget() const132   virtual const views::Widget* GetWidget() const OVERRIDE {
133     return login_view_->GetWidget();
134   }
135 
136   // LoginHandler:
137 
BuildViewForPasswordManager(PasswordManager * manager,const base::string16 & explanation)138   virtual void BuildViewForPasswordManager(
139       PasswordManager* manager,
140       const base::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     CHECK(modal_delegate);
161     dialog_ = views::Widget::CreateWindowAsFramelessChild(
162         this, modal_delegate->GetWebContentsModalDialogHost()->GetHostView());
163     web_contents_modal_dialog_manager->ShowDialog(dialog_->GetNativeView());
164     NotifyAuthNeeded();
165   }
166 
CloseDialog()167   virtual void CloseDialog() OVERRIDE {
168     // The hosting widget may have been freed.
169     if (dialog_)
170       dialog_->Close();
171   }
172 
173  private:
174   friend class base::RefCountedThreadSafe<LoginHandlerViews>;
175   friend class LoginPrompt;
176 
~LoginHandlerViews()177   virtual ~LoginHandlerViews() {}
178 
179   // The LoginView that contains the user's login information
180   LoginView* login_view_;
181 
182   views::Widget* dialog_;
183 
184   DISALLOW_COPY_AND_ASSIGN(LoginHandlerViews);
185 };
186 
187 // static
Create(net::AuthChallengeInfo * auth_info,net::URLRequest * request)188 LoginHandler* LoginHandler::Create(net::AuthChallengeInfo* auth_info,
189                                    net::URLRequest* request) {
190   return new LoginHandlerViews(auth_info, request);
191 }
192