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