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