| OLD | NEW |
| (Empty) |
| 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 "ui/views/controls/webview/web_dialog_view.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/strings/utf_string_conversions.h" | |
| 10 #include "content/public/browser/browser_context.h" | |
| 11 #include "content/public/browser/native_web_keyboard_event.h" | |
| 12 #include "content/public/browser/notification_details.h" | |
| 13 #include "content/public/browser/notification_source.h" | |
| 14 #include "content/public/browser/notification_types.h" | |
| 15 #include "content/public/browser/render_frame_host.h" | |
| 16 #include "content/public/browser/web_contents.h" | |
| 17 #include "ui/events/event.h" | |
| 18 #include "ui/events/keycodes/keyboard_codes.h" | |
| 19 #include "ui/views/controls/webview/webview.h" | |
| 20 #include "ui/views/layout/fill_layout.h" | |
| 21 #include "ui/views/widget/native_widget_private.h" | |
| 22 #include "ui/views/widget/root_view.h" | |
| 23 #include "ui/views/widget/widget.h" | |
| 24 #include "ui/web_dialogs/web_dialog_delegate.h" | |
| 25 #include "ui/web_dialogs/web_dialog_ui.h" | |
| 26 | |
| 27 using content::NativeWebKeyboardEvent; | |
| 28 using content::WebContents; | |
| 29 using content::WebUIMessageHandler; | |
| 30 using ui::WebDialogDelegate; | |
| 31 using ui::WebDialogUI; | |
| 32 using ui::WebDialogWebContentsDelegate; | |
| 33 | |
| 34 namespace views { | |
| 35 | |
| 36 //////////////////////////////////////////////////////////////////////////////// | |
| 37 // WebDialogView, public: | |
| 38 | |
| 39 WebDialogView::WebDialogView( | |
| 40 content::BrowserContext* context, | |
| 41 WebDialogDelegate* delegate, | |
| 42 WebContentsHandler* handler) | |
| 43 : ClientView(NULL, NULL), | |
| 44 WebDialogWebContentsDelegate(context, handler), | |
| 45 delegate_(delegate), | |
| 46 web_view_(new views::WebView(context)), | |
| 47 is_attempting_close_dialog_(false), | |
| 48 before_unload_fired_(false), | |
| 49 closed_via_webui_(false), | |
| 50 close_contents_called_(false) { | |
| 51 web_view_->set_allow_accelerators(true); | |
| 52 AddChildView(web_view_); | |
| 53 set_contents_view(web_view_); | |
| 54 SetLayoutManager(new views::FillLayout); | |
| 55 // Pressing the ESC key will close the dialog. | |
| 56 AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); | |
| 57 } | |
| 58 | |
| 59 WebDialogView::~WebDialogView() { | |
| 60 } | |
| 61 | |
| 62 content::WebContents* WebDialogView::web_contents() { | |
| 63 return web_view_->web_contents(); | |
| 64 } | |
| 65 | |
| 66 //////////////////////////////////////////////////////////////////////////////// | |
| 67 // WebDialogView, views::View implementation: | |
| 68 | |
| 69 gfx::Size WebDialogView::GetPreferredSize() const { | |
| 70 gfx::Size out; | |
| 71 if (delegate_) | |
| 72 delegate_->GetDialogSize(&out); | |
| 73 return out; | |
| 74 } | |
| 75 | |
| 76 gfx::Size WebDialogView::GetMinimumSize() const { | |
| 77 gfx::Size out; | |
| 78 if (delegate_) | |
| 79 delegate_->GetMinimumDialogSize(&out); | |
| 80 return out; | |
| 81 } | |
| 82 | |
| 83 bool WebDialogView::AcceleratorPressed(const ui::Accelerator& accelerator) { | |
| 84 // Pressing ESC closes the dialog. | |
| 85 DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.key_code()); | |
| 86 if (GetWidget()) | |
| 87 GetWidget()->Close(); | |
| 88 return true; | |
| 89 } | |
| 90 | |
| 91 void WebDialogView::ViewHierarchyChanged( | |
| 92 const ViewHierarchyChangedDetails& details) { | |
| 93 if (details.is_add && GetWidget()) | |
| 94 InitDialog(); | |
| 95 } | |
| 96 | |
| 97 bool WebDialogView::CanClose() { | |
| 98 // Don't close UI if |delegate_| does not allow users to close it by | |
| 99 // clicking on "x" button or pressing Esc shortcut key on hosting dialog. | |
| 100 if (!delegate_->CanCloseDialog() && !close_contents_called_) | |
| 101 return false; | |
| 102 | |
| 103 // If CloseContents() is called before CanClose(), which is called by | |
| 104 // RenderViewHostImpl::ClosePageIgnoringUnloadEvents, it indicates | |
| 105 // beforeunload event should not be fired during closing. | |
| 106 if ((is_attempting_close_dialog_ && before_unload_fired_) || | |
| 107 close_contents_called_) { | |
| 108 is_attempting_close_dialog_ = false; | |
| 109 before_unload_fired_ = false; | |
| 110 return true; | |
| 111 } | |
| 112 | |
| 113 if (!is_attempting_close_dialog_) { | |
| 114 // Fire beforeunload event when user attempts to close the dialog. | |
| 115 is_attempting_close_dialog_ = true; | |
| 116 web_view_->web_contents()->DispatchBeforeUnload(false); | |
| 117 } | |
| 118 return false; | |
| 119 } | |
| 120 | |
| 121 //////////////////////////////////////////////////////////////////////////////// | |
| 122 // WebDialogView, views::WidgetDelegate implementation: | |
| 123 | |
| 124 bool WebDialogView::CanResize() const { | |
| 125 if (delegate_) | |
| 126 return delegate_->CanResizeDialog(); | |
| 127 return true; | |
| 128 } | |
| 129 | |
| 130 ui::ModalType WebDialogView::GetModalType() const { | |
| 131 return GetDialogModalType(); | |
| 132 } | |
| 133 | |
| 134 base::string16 WebDialogView::GetWindowTitle() const { | |
| 135 if (delegate_) | |
| 136 return delegate_->GetDialogTitle(); | |
| 137 return base::string16(); | |
| 138 } | |
| 139 | |
| 140 std::string WebDialogView::GetWindowName() const { | |
| 141 if (delegate_) | |
| 142 return delegate_->GetDialogName(); | |
| 143 return std::string(); | |
| 144 } | |
| 145 | |
| 146 void WebDialogView::WindowClosing() { | |
| 147 // If we still have a delegate that means we haven't notified it of the | |
| 148 // dialog closing. This happens if the user clicks the Close button on the | |
| 149 // dialog. | |
| 150 if (delegate_) | |
| 151 OnDialogClosed(""); | |
| 152 } | |
| 153 | |
| 154 views::View* WebDialogView::GetContentsView() { | |
| 155 return this; | |
| 156 } | |
| 157 | |
| 158 views::ClientView* WebDialogView::CreateClientView(views::Widget* widget) { | |
| 159 return this; | |
| 160 } | |
| 161 | |
| 162 views::View* WebDialogView::GetInitiallyFocusedView() { | |
| 163 return web_view_; | |
| 164 } | |
| 165 | |
| 166 bool WebDialogView::ShouldShowWindowTitle() const { | |
| 167 return ShouldShowDialogTitle(); | |
| 168 } | |
| 169 | |
| 170 views::Widget* WebDialogView::GetWidget() { | |
| 171 return View::GetWidget(); | |
| 172 } | |
| 173 | |
| 174 const views::Widget* WebDialogView::GetWidget() const { | |
| 175 return View::GetWidget(); | |
| 176 } | |
| 177 | |
| 178 //////////////////////////////////////////////////////////////////////////////// | |
| 179 // WebDialogDelegate implementation: | |
| 180 | |
| 181 ui::ModalType WebDialogView::GetDialogModalType() const { | |
| 182 if (delegate_) | |
| 183 return delegate_->GetDialogModalType(); | |
| 184 return ui::MODAL_TYPE_NONE; | |
| 185 } | |
| 186 | |
| 187 base::string16 WebDialogView::GetDialogTitle() const { | |
| 188 return GetWindowTitle(); | |
| 189 } | |
| 190 | |
| 191 GURL WebDialogView::GetDialogContentURL() const { | |
| 192 if (delegate_) | |
| 193 return delegate_->GetDialogContentURL(); | |
| 194 return GURL(); | |
| 195 } | |
| 196 | |
| 197 void WebDialogView::GetWebUIMessageHandlers( | |
| 198 std::vector<WebUIMessageHandler*>* handlers) const { | |
| 199 if (delegate_) | |
| 200 delegate_->GetWebUIMessageHandlers(handlers); | |
| 201 } | |
| 202 | |
| 203 void WebDialogView::GetDialogSize(gfx::Size* size) const { | |
| 204 if (delegate_) | |
| 205 delegate_->GetDialogSize(size); | |
| 206 } | |
| 207 | |
| 208 void WebDialogView::GetMinimumDialogSize(gfx::Size* size) const { | |
| 209 if (delegate_) | |
| 210 delegate_->GetMinimumDialogSize(size); | |
| 211 } | |
| 212 | |
| 213 std::string WebDialogView::GetDialogArgs() const { | |
| 214 if (delegate_) | |
| 215 return delegate_->GetDialogArgs(); | |
| 216 return std::string(); | |
| 217 } | |
| 218 | |
| 219 void WebDialogView::OnDialogShown(content::WebUI* webui, | |
| 220 content::RenderViewHost* render_view_host) { | |
| 221 if (delegate_) | |
| 222 delegate_->OnDialogShown(webui, render_view_host); | |
| 223 } | |
| 224 | |
| 225 void WebDialogView::OnDialogClosed(const std::string& json_retval) { | |
| 226 Detach(); | |
| 227 if (delegate_) { | |
| 228 // Store the dialog content area size. | |
| 229 delegate_->StoreDialogSize(GetContentsBounds().size()); | |
| 230 } | |
| 231 | |
| 232 if (GetWidget()) | |
| 233 GetWidget()->Close(); | |
| 234 | |
| 235 if (delegate_) { | |
| 236 delegate_->OnDialogClosed(json_retval); | |
| 237 delegate_ = NULL; // We will not communicate further with the delegate. | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 void WebDialogView::OnDialogCloseFromWebUI(const std::string& json_retval) { | |
| 242 closed_via_webui_ = true; | |
| 243 dialog_close_retval_ = json_retval; | |
| 244 if (GetWidget()) | |
| 245 GetWidget()->Close(); | |
| 246 } | |
| 247 | |
| 248 void WebDialogView::OnCloseContents(WebContents* source, | |
| 249 bool* out_close_dialog) { | |
| 250 if (delegate_) | |
| 251 delegate_->OnCloseContents(source, out_close_dialog); | |
| 252 } | |
| 253 | |
| 254 bool WebDialogView::ShouldShowDialogTitle() const { | |
| 255 if (delegate_) | |
| 256 return delegate_->ShouldShowDialogTitle(); | |
| 257 return true; | |
| 258 } | |
| 259 | |
| 260 bool WebDialogView::HandleContextMenu( | |
| 261 const content::ContextMenuParams& params) { | |
| 262 if (delegate_) | |
| 263 return delegate_->HandleContextMenu(params); | |
| 264 return WebDialogWebContentsDelegate::HandleContextMenu(params); | |
| 265 } | |
| 266 | |
| 267 //////////////////////////////////////////////////////////////////////////////// | |
| 268 // content::WebContentsDelegate implementation: | |
| 269 | |
| 270 void WebDialogView::MoveContents(WebContents* source, const gfx::Rect& pos) { | |
| 271 // The contained web page wishes to resize itself. We let it do this because | |
| 272 // if it's a dialog we know about, we trust it not to be mean to the user. | |
| 273 GetWidget()->SetBounds(pos); | |
| 274 } | |
| 275 | |
| 276 // A simplified version of BrowserView::HandleKeyboardEvent(). | |
| 277 // We don't handle global keyboard shortcuts here, but that's fine since | |
| 278 // they're all browser-specific. (This may change in the future.) | |
| 279 void WebDialogView::HandleKeyboardEvent(content::WebContents* source, | |
| 280 const NativeWebKeyboardEvent& event) { | |
| 281 if (!event.os_event) | |
| 282 return; | |
| 283 | |
| 284 GetWidget()->native_widget_private()->RepostNativeEvent(event.os_event); | |
| 285 } | |
| 286 | |
| 287 void WebDialogView::CloseContents(WebContents* source) { | |
| 288 close_contents_called_ = true; | |
| 289 bool close_dialog = false; | |
| 290 OnCloseContents(source, &close_dialog); | |
| 291 if (close_dialog) | |
| 292 OnDialogClosed(closed_via_webui_ ? dialog_close_retval_ : std::string()); | |
| 293 } | |
| 294 | |
| 295 content::WebContents* WebDialogView::OpenURLFromTab( | |
| 296 content::WebContents* source, | |
| 297 const content::OpenURLParams& params) { | |
| 298 content::WebContents* new_contents = NULL; | |
| 299 if (delegate_ && | |
| 300 delegate_->HandleOpenURLFromTab(source, params, &new_contents)) { | |
| 301 return new_contents; | |
| 302 } | |
| 303 return WebDialogWebContentsDelegate::OpenURLFromTab(source, params); | |
| 304 } | |
| 305 | |
| 306 void WebDialogView::AddNewContents(content::WebContents* source, | |
| 307 content::WebContents* new_contents, | |
| 308 WindowOpenDisposition disposition, | |
| 309 const gfx::Rect& initial_pos, | |
| 310 bool user_gesture, | |
| 311 bool* was_blocked) { | |
| 312 if (delegate_ && delegate_->HandleAddNewContents( | |
| 313 source, new_contents, disposition, initial_pos, user_gesture)) { | |
| 314 return; | |
| 315 } | |
| 316 WebDialogWebContentsDelegate::AddNewContents( | |
| 317 source, new_contents, disposition, initial_pos, user_gesture, | |
| 318 was_blocked); | |
| 319 } | |
| 320 | |
| 321 void WebDialogView::LoadingStateChanged(content::WebContents* source, | |
| 322 bool to_different_document) { | |
| 323 if (delegate_) | |
| 324 delegate_->OnLoadingStateChanged(source); | |
| 325 } | |
| 326 | |
| 327 void WebDialogView::BeforeUnloadFired(content::WebContents* tab, | |
| 328 bool proceed, | |
| 329 bool* proceed_to_fire_unload) { | |
| 330 before_unload_fired_ = true; | |
| 331 *proceed_to_fire_unload = proceed; | |
| 332 } | |
| 333 | |
| 334 //////////////////////////////////////////////////////////////////////////////// | |
| 335 // WebDialogView, private: | |
| 336 | |
| 337 void WebDialogView::InitDialog() { | |
| 338 content::WebContents* web_contents = web_view_->GetWebContents(); | |
| 339 if (web_contents->GetDelegate() == this) | |
| 340 return; | |
| 341 | |
| 342 web_contents->SetDelegate(this); | |
| 343 | |
| 344 // Set the delegate. This must be done before loading the page. See | |
| 345 // the comment above WebDialogUI in its header file for why. | |
| 346 WebDialogUI::SetDelegate(web_contents, this); | |
| 347 | |
| 348 web_view_->LoadInitialURL(GetDialogContentURL()); | |
| 349 } | |
| 350 | |
| 351 } // namespace views | |
| OLD | NEW |