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