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