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