Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / constrained_web_dialog_delegate_views.cc
blob66af06898c6d2d61e947d95c8db84038c540ed32
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.
5 #include "chrome/browser/ui/webui/constrained_web_dialog_delegate_base.h"
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/webui/chrome_web_contents_handler.h"
11 #include "components/constrained_window/constrained_window_views.h"
12 #include "components/web_modal/web_contents_modal_dialog_manager.h"
13 #include "content/public/browser/native_web_keyboard_event.h"
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
17 #include "ui/views/controls/webview/webview.h"
18 #include "ui/views/view.h"
19 #include "ui/views/widget/widget.h"
20 #include "ui/views/window/dialog_delegate.h"
21 #include "ui/web_dialogs/web_dialog_delegate.h"
22 #include "ui/web_dialogs/web_dialog_ui.h"
24 namespace {
26 // WebContentsObserver that tracks the lifetime of the WebContents to avoid
27 // potential use after destruction.
28 class InitiatorWebContentsObserver
29 : public content::WebContentsObserver {
30 public:
31 explicit InitiatorWebContentsObserver(content::WebContents* web_contents)
32 : content::WebContentsObserver(web_contents) {
35 private:
36 DISALLOW_COPY_AND_ASSIGN(InitiatorWebContentsObserver);
39 class WebDialogWebContentsDelegateViews
40 : public ui::WebDialogWebContentsDelegate {
41 public:
42 WebDialogWebContentsDelegateViews(content::BrowserContext* browser_context,
43 InitiatorWebContentsObserver* observer,
44 views::WebView* web_view)
45 : ui::WebDialogWebContentsDelegate(browser_context,
46 new ChromeWebContentsHandler()),
47 initiator_observer_(observer),
48 web_view_(web_view) {
50 ~WebDialogWebContentsDelegateViews() override {}
52 // ui::WebDialogWebContentsDelegate:
53 void HandleKeyboardEvent(
54 content::WebContents* source,
55 const content::NativeWebKeyboardEvent& event) override {
56 // Forward shortcut keys in dialog to our initiator's delegate.
57 // http://crbug.com/104586
58 // Disabled on Mac due to http://crbug.com/112173
59 #if !defined(OS_MACOSX)
60 if (!initiator_observer_->web_contents())
61 return;
63 auto delegate = initiator_observer_->web_contents()->GetDelegate();
64 if (!delegate)
65 return;
66 delegate->HandleKeyboardEvent(initiator_observer_->web_contents(), event);
67 #endif
70 void ResizeDueToAutoResize(content::WebContents* source,
71 const gfx::Size& preferred_size) override {
72 if (source != web_view_->GetWebContents())
73 return;
75 if (!initiator_observer_->web_contents())
76 return;
78 // Sets WebView's preferred size based on auto-resized contents.
79 web_view_->SetPreferredSize(preferred_size);
81 constrained_window::UpdateWebContentsModalDialogPosition(
82 web_view_->GetWidget(),
83 web_modal::WebContentsModalDialogManager::FromWebContents(
84 initiator_observer_->web_contents())->delegate()->
85 GetWebContentsModalDialogHost());
88 private:
89 InitiatorWebContentsObserver* const initiator_observer_;
90 views::WebView* web_view_;
92 DISALLOW_COPY_AND_ASSIGN(WebDialogWebContentsDelegateViews);
95 class ConstrainedWebDialogDelegateViews
96 : public ConstrainedWebDialogDelegateBase {
97 public:
98 ConstrainedWebDialogDelegateViews(content::BrowserContext* context,
99 ui::WebDialogDelegate* delegate,
100 InitiatorWebContentsObserver* observer,
101 views::WebView* view)
102 : ConstrainedWebDialogDelegateBase(context, delegate,
103 new WebDialogWebContentsDelegateViews(context, observer, view)),
104 view_(view) {}
106 ~ConstrainedWebDialogDelegateViews() override {}
108 // ui::WebDialogWebContentsDelegate:
109 void CloseContents(content::WebContents* source) override {
110 view_->GetWidget()->Close();
113 // contents::WebContentsDelegate:
114 void HandleKeyboardEvent(
115 content::WebContents* source,
116 const content::NativeWebKeyboardEvent& event) override {
117 unhandled_keyboard_event_handler_.HandleKeyboardEvent(
118 event, view_->GetFocusManager());
121 // ConstrainedWebDialogDelegate:
122 gfx::NativeWindow GetNativeDialog() override {
123 return view_->GetWidget()->GetNativeWindow();
126 private:
127 // Converts keyboard events on the WebContents to accelerators.
128 views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
130 views::WebView* view_;
132 DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateViews);
135 class ConstrainedWebDialogDelegateViewViews
136 : public views::WebView,
137 public ConstrainedWebDialogDelegate,
138 public views::WidgetDelegate {
139 public:
140 ConstrainedWebDialogDelegateViewViews(
141 content::BrowserContext* browser_context,
142 ui::WebDialogDelegate* delegate,
143 content::WebContents* web_contents,
144 const gfx::Size& min_size,
145 const gfx::Size& max_size)
146 : views::WebView(browser_context),
147 initiator_observer_(web_contents),
148 impl_(new ConstrainedWebDialogDelegateViews(browser_context, delegate,
149 &initiator_observer_,
150 this)),
151 min_size_(min_size),
152 max_size_(max_size) {
153 SetWebContents(GetWebContents());
154 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
156 ~ConstrainedWebDialogDelegateViewViews() override {}
158 // ConstrainedWebDialogDelegate:
159 const ui::WebDialogDelegate* GetWebDialogDelegate() const override {
160 return impl_->GetWebDialogDelegate();
162 ui::WebDialogDelegate* GetWebDialogDelegate() override {
163 return impl_->GetWebDialogDelegate();
165 void OnDialogCloseFromWebUI() override {
166 return impl_->OnDialogCloseFromWebUI();
168 void ReleaseWebContentsOnDialogClose() override {
169 return impl_->ReleaseWebContentsOnDialogClose();
171 gfx::NativeWindow GetNativeDialog() override {
172 return impl_->GetNativeDialog();
174 content::WebContents* GetWebContents() override {
175 return impl_->GetWebContents();
178 // views::WidgetDelegate:
179 views::View* GetInitiallyFocusedView() override { return this; }
180 void WindowClosing() override {
181 if (!impl_->closed_via_webui())
182 GetWebDialogDelegate()->OnDialogClosed(std::string());
184 views::Widget* GetWidget() override { return View::GetWidget(); }
185 const views::Widget* GetWidget() const override { return View::GetWidget(); }
186 base::string16 GetWindowTitle() const override {
187 return impl_->closed_via_webui() ? base::string16() :
188 GetWebDialogDelegate()->GetDialogTitle();
190 views::View* GetContentsView() override { return this; }
191 views::NonClientFrameView* CreateNonClientFrameView(
192 views::Widget* widget) override {
193 return views::DialogDelegate::CreateDialogFrameView(widget);
195 bool ShouldShowCloseButton() const override {
196 // No close button if the dialog doesn't want a title bar.
197 return impl_->GetWebDialogDelegate()->ShouldShowDialogTitle();
199 ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_CHILD; }
201 // views::WebView:
202 bool AcceleratorPressed(const ui::Accelerator& accelerator) override {
203 // Pressing ESC closes the dialog.
204 DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.key_code());
205 GetWidget()->Close();
206 return true;
208 gfx::Size GetPreferredSize() const override {
209 gfx::Size size;
210 if (!impl_->closed_via_webui()) {
211 // The size is set here if the dialog has been auto-resized in
212 // WebDialogWebContentsDelegateViews's ResizeDueToAutoResize.
213 size = WebView::GetPreferredSize();
214 if (size.IsEmpty()) {
215 // The size set here if the dialog has not been auto-resized or
216 // auto-resizable is not enabled.
217 GetWebDialogDelegate()->GetDialogSize(&size);
220 return size;
222 gfx::Size GetMinimumSize() const override {
223 return min_size_;
225 gfx::Size GetMaximumSize() const override {
226 return !max_size_.IsEmpty() ? max_size_ : WebView::GetMaximumSize();
228 void RenderViewCreated(content::RenderViewHost* render_view_host) override {
229 if (!max_size_.IsEmpty())
230 EnableAutoResize();
232 void RenderViewHostChanged(content::RenderViewHost* old_host,
233 content::RenderViewHost* new_host) override {
234 if (!max_size_.IsEmpty())
235 EnableAutoResize();
237 void DocumentOnLoadCompletedInMainFrame() override {
238 if (!max_size_.IsEmpty()) {
239 EnableAutoResize();
240 if (initiator_observer_.web_contents()) {
241 web_modal::WebContentsModalDialogManager::FromWebContents(
242 initiator_observer_.web_contents())
243 ->ShowModalDialog(GetWidget()->GetNativeWindow());
248 private:
249 void EnableAutoResize() {
250 content::RenderViewHost* render_view_host =
251 GetWebContents()->GetRenderViewHost();
252 render_view_host->EnableAutoResize(min_size_, max_size_);
255 InitiatorWebContentsObserver initiator_observer_;
257 scoped_ptr<ConstrainedWebDialogDelegateViews> impl_;
259 // Minimum and maximum sizes to determine dialog bounds for auto-resizing.
260 const gfx::Size min_size_;
261 const gfx::Size max_size_;
263 DISALLOW_COPY_AND_ASSIGN(ConstrainedWebDialogDelegateViewViews);
266 } // namespace
268 ConstrainedWebDialogDelegate* ShowConstrainedWebDialog(
269 content::BrowserContext* browser_context,
270 ui::WebDialogDelegate* delegate,
271 content::WebContents* web_contents) {
272 ConstrainedWebDialogDelegateViewViews* dialog =
273 new ConstrainedWebDialogDelegateViewViews(
274 browser_context, delegate, web_contents,
275 gfx::Size(), gfx::Size());
276 constrained_window::ShowWebModalDialogViews(dialog, web_contents);
277 return dialog;
280 ConstrainedWebDialogDelegate* ShowConstrainedWebDialogWithAutoResize(
281 content::BrowserContext* browser_context,
282 ui::WebDialogDelegate* delegate,
283 content::WebContents* web_contents,
284 const gfx::Size& min_size,
285 const gfx::Size& max_size) {
286 DCHECK(!min_size.IsEmpty());
287 DCHECK(!max_size.IsEmpty());
288 ConstrainedWebDialogDelegateViewViews* dialog =
289 new ConstrainedWebDialogDelegateViewViews(
290 browser_context, delegate, web_contents,
291 min_size, max_size);
292 constrained_window::CreateWebModalDialogViews(dialog, web_contents);
293 return dialog;