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/webui/constrained_web_dialog_delegate_base.h"
      6 
      7 #include "base/strings/utf_string_conversions.h"
      8 #include "chrome/browser/ui/browser_finder.h"
      9 #include "chrome/browser/ui/browser_window.h"
     10 #include "chrome/browser/ui/views/constrained_window_views.h"
     11 #include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
     12 #include "content/public/browser/native_web_keyboard_event.h"
     13 #include "content/public/browser/web_contents.h"
     14 #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
     15 #include "ui/views/controls/webview/webview.h"
     16 #include "ui/views/widget/widget.h"
     17 #include "ui/views/window/dialog_delegate.h"
     18 #include "ui/web_dialogs/web_dialog_delegate.h"
     19 #include "ui/web_dialogs/web_dialog_ui.h"
     20 
     21 namespace {
     22 
     23 class WebDialogWebContentsDelegateViews
     24     : public ui::WebDialogWebContentsDelegate {
     25  public:
     26   WebDialogWebContentsDelegateViews(content::BrowserContext* browser_context,
     27                                     content::WebContents* initiator,
     28                                     views::WebView* web_view)
     29       : ui::WebDialogWebContentsDelegate(browser_context,
     30                                          new ChromeWebContentsHandler()),
     31         initiator_(initiator),
     32         web_view_(web_view) {
     33   }
     34   virtual ~WebDialogWebContentsDelegateViews() {}
     35 
     36   // ui::WebDialogWebContentsDelegate:
     37   virtual void WebContentsFocused(content::WebContents* contents) OVERRIDE {
     38     // Ensure the WebView is focused when its WebContents is focused.
     39     web_view_->RequestFocus();
     40   }
     41   virtual void HandleKeyboardEvent(
     42       content::WebContents* source,
     43       const content::NativeWebKeyboardEvent& event) OVERRIDE {
     44     // Forward shortcut keys in dialog to the browser. http://crbug.com/104586
     45     // Disabled on Mac due to http://crbug.com/112173
     46 #if !defined(OS_MACOSX)
     47     Browser* current_browser = chrome::FindBrowserWithWebContents(initiator_);
     48     if (!current_browser)
     49       return;
     50     current_browser->window()->HandleKeyboardEvent(event);
     51 #endif
     52   }
     53 
     54  private:
     55   content::WebContents* initiator_;
     56   views::WebView* web_view_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(WebDialogWebContentsDelegateViews);
     59 };
     60 
     61 class ConstrainedWebDialogDelegateViews
     62     : public ConstrainedWebDialogDelegateBase {
     63  public:
     64   ConstrainedWebDialogDelegateViews(content::BrowserContext* context,
     65                                     ui::WebDialogDelegate* delegate,
     66                                     content::WebContents* web_contents,
     67                                     views::WebView* view)
     68       : ConstrainedWebDialogDelegateBase(context, delegate,
     69             new WebDialogWebContentsDelegateViews(context, web_contents, view)),
     70         view_(view) {}
     71 
     72   virtual ~ConstrainedWebDialogDelegateViews() {}
     73 
     74   // ui::WebDialogWebContentsDelegate:
     75   virtual void CloseContents(content::WebContents* source) OVERRIDE {
     76     view_->GetWidget()->Close();
     77   }
     78 
     79   // contents::WebContentsDelegate:
     80   virtual void HandleKeyboardEvent(
     81       content::WebContents* source,
     82       const content::NativeWebKeyboardEvent& event) OVERRIDE {
     83     unhandled_keyboard_event_handler_.HandleKeyboardEvent(
     84         event, view_->GetFocusManager());
     85   }
     86 
     87   // ConstrainedWebDialogDelegate:
     88   virtual web_modal::NativeWebContentsModalDialog GetNativeDialog() OVERRIDE {
     89     return view_->GetWidget()->GetNativeView();
     90   }
     91 
     92  private:
     93   // Converts keyboard events on the WebContents to accelerators.
     94   views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
     95 
     96   views::WebView* view_;
     97 
     98   DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateViews);
     99 };
    100 
    101 class ConstrainedWebDialogDelegateViewViews
    102     : public views::WebView,
    103       public ConstrainedWebDialogDelegate,
    104       public views::WidgetDelegate {
    105  public:
    106   ConstrainedWebDialogDelegateViewViews(
    107       content::BrowserContext* browser_context,
    108       ui::WebDialogDelegate* delegate,
    109       content::WebContents* web_contents)
    110       : views::WebView(browser_context),
    111         impl_(new ConstrainedWebDialogDelegateViews(browser_context, delegate,
    112                                                     web_contents, this)) {
    113     SetWebContents(GetWebContents());
    114     AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
    115   }
    116   virtual ~ConstrainedWebDialogDelegateViewViews() {}
    117 
    118   // ConstrainedWebDialogDelegate:
    119   virtual const ui::WebDialogDelegate* GetWebDialogDelegate() const OVERRIDE {
    120     return impl_->GetWebDialogDelegate();
    121   }
    122   virtual ui::WebDialogDelegate* GetWebDialogDelegate() OVERRIDE {
    123     return impl_->GetWebDialogDelegate();
    124   }
    125   virtual void OnDialogCloseFromWebUI() OVERRIDE {
    126     return impl_->OnDialogCloseFromWebUI();
    127   }
    128   virtual void ReleaseWebContentsOnDialogClose() OVERRIDE {
    129     return impl_->ReleaseWebContentsOnDialogClose();
    130   }
    131   virtual web_modal::NativeWebContentsModalDialog GetNativeDialog() OVERRIDE {
    132     return impl_->GetNativeDialog();
    133   }
    134   virtual content::WebContents* GetWebContents() OVERRIDE {
    135     return impl_->GetWebContents();
    136   }
    137 
    138   // views::WidgetDelegate:
    139   virtual views::View* GetInitiallyFocusedView() OVERRIDE {
    140     return this;
    141   }
    142   virtual void WindowClosing() OVERRIDE {
    143     if (!impl_->closed_via_webui())
    144       GetWebDialogDelegate()->OnDialogClosed(std::string());
    145   }
    146   virtual views::Widget* GetWidget() OVERRIDE {
    147     return View::GetWidget();
    148   }
    149   virtual const views::Widget* GetWidget() const OVERRIDE {
    150     return View::GetWidget();
    151   }
    152   virtual base::string16 GetWindowTitle() const OVERRIDE {
    153     return impl_->closed_via_webui() ? base::string16() :
    154         GetWebDialogDelegate()->GetDialogTitle();
    155   }
    156   virtual views::View* GetContentsView() OVERRIDE {
    157     return this;
    158   }
    159   virtual views::NonClientFrameView* CreateNonClientFrameView(
    160       views::Widget* widget) OVERRIDE {
    161     return views::DialogDelegate::CreateDialogFrameView(widget);
    162   }
    163   virtual bool ShouldShowCloseButton() const OVERRIDE {
    164     // No close button if the dialog doesn't want a title bar.
    165     return impl_->GetWebDialogDelegate()->ShouldShowDialogTitle();
    166   }
    167   virtual ui::ModalType GetModalType() const OVERRIDE {
    168     return ui::MODAL_TYPE_CHILD;
    169   }
    170 
    171   // views::WebView:
    172   virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
    173     // Pressing ESC closes the dialog.
    174     DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.key_code());
    175     GetWidget()->Close();
    176     return true;
    177   }
    178   virtual gfx::Size GetPreferredSize() const OVERRIDE {
    179     gfx::Size size;
    180     if (!impl_->closed_via_webui())
    181       GetWebDialogDelegate()->GetDialogSize(&size);
    182     return size;
    183   }
    184   virtual gfx::Size GetMinimumSize() const OVERRIDE {
    185     // Return an empty size so that we can be made smaller.
    186     return gfx::Size();
    187   }
    188 
    189  private:
    190   scoped_ptr<ConstrainedWebDialogDelegateViews> impl_;
    191 
    192   DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateViewViews);
    193 };
    194 
    195 }  // namespace
    196 
    197 ConstrainedWebDialogDelegate* CreateConstrainedWebDialog(
    198     content::BrowserContext* browser_context,
    199     ui::WebDialogDelegate* delegate,
    200     content::WebContents* web_contents) {
    201   ConstrainedWebDialogDelegateViewViews* dialog =
    202       new ConstrainedWebDialogDelegateViewViews(
    203           browser_context, delegate, web_contents);
    204   ShowWebModalDialogViews(dialog, web_contents);
    205   return dialog;
    206 }
    207