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