Home | History | Annotate | Download | only in views
      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_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 
     26 using content::BrowserThread;
     27 using content::PasswordForm;
     28 using content::WebContents;
     29 using 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.
     38 class 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
    186 LoginHandler* LoginHandler::Create(net::AuthChallengeInfo* auth_info,
    187                                    net::URLRequest* request) {
    188   return new LoginHandlerViews(auth_info, request);
    189 }
    190