| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/views/html_dialog_view.h" |
| |
| #include <vector> |
| |
| #include "base/utf_string_conversions.h" |
| #include "chrome/browser/ui/browser_dialogs.h" |
| #include "chrome/browser/ui/views/window.h" |
| #include "content/browser/tab_contents/tab_contents.h" |
| #include "content/public/browser/native_web_keyboard_event.h" |
| #include "content/public/browser/notification_details.h" |
| #include "content/public/browser/notification_source.h" |
| #include "content/public/browser/notification_types.h" |
| #include "ui/base/keycodes/keyboard_codes.h" |
| #include "views/events/event.h" |
| #include "views/widget/root_view.h" |
| #include "views/widget/widget.h" |
| |
| #if defined(TOOLKIT_USES_GTK) |
| #include "views/widget/native_widget_gtk.h" |
| #endif |
| |
| class RenderWidgetHost; |
| |
| namespace browser { |
| |
| // Declared in browser_dialogs.h so that others don't need to depend on our .h. |
| gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, |
| Profile* profile, |
| HtmlDialogUIDelegate* delegate) { |
| HtmlDialogView* html_view = new HtmlDialogView(profile, delegate); |
| browser::CreateViewsWindow(parent, html_view); |
| html_view->InitDialog(); |
| html_view->GetWidget()->Show(); |
| return html_view->GetWidget()->GetNativeWindow(); |
| } |
| |
| } // namespace browser |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // HtmlDialogView, public: |
| |
| HtmlDialogView::HtmlDialogView(Profile* profile, |
| HtmlDialogUIDelegate* delegate) |
| : DOMView(), |
| HtmlDialogTabContentsDelegate(profile), |
| state_(NONE), |
| delegate_(delegate) { |
| } |
| |
| HtmlDialogView::~HtmlDialogView() { |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // HtmlDialogView, views::View implementation: |
| |
| gfx::Size HtmlDialogView::GetPreferredSize() { |
| gfx::Size out; |
| if (delegate_) |
| delegate_->GetDialogSize(&out); |
| return out; |
| } |
| |
| bool HtmlDialogView::AcceleratorPressed(const views::Accelerator& accelerator) { |
| // Pressing ESC closes the dialog. |
| DCHECK_EQ(ui::VKEY_ESCAPE, accelerator.key_code()); |
| OnDialogClosed(std::string()); |
| return true; |
| } |
| |
| void HtmlDialogView::ViewHierarchyChanged( |
| bool is_add, View* parent, View* child) { |
| DOMView::ViewHierarchyChanged(is_add, parent, child); |
| if (is_add && GetWidget() && state_ == NONE) { |
| state_ = INITIALIZED; |
| #if defined(OS_CHROMEOS) && defined(TOOLKIT_USES_GTK) |
| CHECK( |
| static_cast<views::NativeWidgetGtk*>( |
| GetWidget()->native_widget())->SuppressFreezeUpdates()); |
| #endif |
| RegisterDialogAccelerators(); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // HtmlDialogView, views::WidgetDelegate implementation: |
| |
| bool HtmlDialogView::CanResize() const { |
| return true; |
| } |
| |
| bool HtmlDialogView::IsModal() const { |
| if (delegate_) |
| return delegate_->IsDialogModal(); |
| return false; |
| } |
| |
| string16 HtmlDialogView::GetWindowTitle() const { |
| if (delegate_) |
| return delegate_->GetDialogTitle(); |
| return string16(); |
| } |
| |
| void HtmlDialogView::WindowClosing() { |
| // If we still have a delegate that means we haven't notified it of the |
| // dialog closing. This happens if the user clicks the Close button on the |
| // dialog. |
| if (delegate_) |
| OnDialogClosed(""); |
| } |
| |
| views::View* HtmlDialogView::GetContentsView() { |
| return this; |
| } |
| |
| views::View* HtmlDialogView::GetInitiallyFocusedView() { |
| return this; |
| } |
| |
| bool HtmlDialogView::ShouldShowWindowTitle() const { |
| return ShouldShowDialogTitle(); |
| } |
| |
| views::Widget* HtmlDialogView::GetWidget() { |
| return View::GetWidget(); |
| } |
| |
| const views::Widget* HtmlDialogView::GetWidget() const { |
| return View::GetWidget(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // HtmlDialogUIDelegate implementation: |
| |
| bool HtmlDialogView::IsDialogModal() const { |
| return IsModal(); |
| } |
| |
| string16 HtmlDialogView::GetDialogTitle() const { |
| return GetWindowTitle(); |
| } |
| |
| GURL HtmlDialogView::GetDialogContentURL() const { |
| if (delegate_) |
| return delegate_->GetDialogContentURL(); |
| return GURL(); |
| } |
| |
| void HtmlDialogView::GetWebUIMessageHandlers( |
| std::vector<WebUIMessageHandler*>* handlers) const { |
| if (delegate_) |
| delegate_->GetWebUIMessageHandlers(handlers); |
| } |
| |
| void HtmlDialogView::GetDialogSize(gfx::Size* size) const { |
| if (delegate_) |
| delegate_->GetDialogSize(size); |
| } |
| |
| std::string HtmlDialogView::GetDialogArgs() const { |
| if (delegate_) |
| return delegate_->GetDialogArgs(); |
| return std::string(); |
| } |
| |
| void HtmlDialogView::OnDialogClosed(const std::string& json_retval) { |
| HtmlDialogTabContentsDelegate::Detach(); |
| if (delegate_) { |
| HtmlDialogUIDelegate* dialog_delegate = delegate_; |
| delegate_ = NULL; // We will not communicate further with the delegate. |
| dialog_delegate->OnDialogClosed(json_retval); |
| } |
| GetWidget()->Close(); |
| } |
| |
| void HtmlDialogView::OnCloseContents(TabContents* source, |
| bool* out_close_dialog) { |
| if (delegate_) |
| delegate_->OnCloseContents(source, out_close_dialog); |
| } |
| |
| bool HtmlDialogView::ShouldShowDialogTitle() const { |
| if (delegate_) |
| return delegate_->ShouldShowDialogTitle(); |
| return true; |
| } |
| |
| bool HtmlDialogView::HandleContextMenu(const ContextMenuParams& params) { |
| if (delegate_) |
| return delegate_->HandleContextMenu(params); |
| return HtmlDialogTabContentsDelegate::HandleContextMenu(params); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // TabContentsDelegate implementation: |
| |
| void HtmlDialogView::MoveContents(TabContents* source, const gfx::Rect& pos) { |
| // The contained web page wishes to resize itself. We let it do this because |
| // if it's a dialog we know about, we trust it not to be mean to the user. |
| GetWidget()->SetBounds(pos); |
| } |
| |
| // A simplified version of BrowserView::HandleKeyboardEvent(). |
| // We don't handle global keyboard shortcuts here, but that's fine since |
| // they're all browser-specific. (This may change in the future.) |
| void HtmlDialogView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { |
| #if defined(USE_AURA) |
| // TODO(saintlou): Need to provide some Aura handling. |
| #elif defined(OS_WIN) |
| // Any unhandled keyboard/character messages should be defproced. |
| // This allows stuff like F10, etc to work correctly. |
| DefWindowProc(event.os_event.hwnd, event.os_event.message, |
| event.os_event.wParam, event.os_event.lParam); |
| #elif defined(TOOLKIT_USES_GTK) |
| views::NativeWidgetGtk* window_gtk = |
| static_cast<views::NativeWidgetGtk*>(GetWidget()->native_widget()); |
| if (event.os_event && !event.skip_in_browser) { |
| views::KeyEvent views_event(reinterpret_cast<GdkEvent*>(event.os_event)); |
| window_gtk->HandleKeyboardEvent(views_event); |
| } |
| #endif |
| } |
| |
| void HtmlDialogView::CloseContents(TabContents* source) { |
| bool close_dialog = false; |
| OnCloseContents(source, &close_dialog); |
| if (close_dialog) |
| OnDialogClosed(std::string()); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // HtmlDialogView: |
| |
| void HtmlDialogView::InitDialog() { |
| // Now Init the DOMView. This view runs in its own process to render the html. |
| DOMView::Init(profile(), NULL); |
| |
| TabContents* tab_contents = dom_contents_->tab_contents(); |
| tab_contents->set_delegate(this); |
| |
| // Set the delegate. This must be done before loading the page. See |
| // the comment above HtmlDialogUI in its header file for why. |
| HtmlDialogUI::GetPropertyAccessor().SetProperty( |
| tab_contents->property_bag(), this); |
| notification_registrar_.Add( |
| this, |
| content::NOTIFICATION_RENDER_VIEW_HOST_CREATED_FOR_TAB, |
| content::Source<TabContents>(tab_contents)); |
| notification_registrar_.Add( |
| this, |
| content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, |
| content::Source<TabContents>(tab_contents)); |
| |
| DOMView::LoadURL(GetDialogContentURL()); |
| } |
| |
| void HtmlDialogView::Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) { |
| switch (type) { |
| case content::NOTIFICATION_RENDER_VIEW_HOST_CREATED_FOR_TAB: { |
| RenderWidgetHost* rwh = content::Details<RenderWidgetHost>(details).ptr(); |
| notification_registrar_.Add( |
| this, |
| content::NOTIFICATION_RENDER_WIDGET_HOST_DID_PAINT, |
| content::Source<RenderWidgetHost>(rwh)); |
| break; |
| } |
| case content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME: |
| if (state_ == INITIALIZED) |
| state_ = LOADED; |
| break; |
| case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_PAINT: |
| if (state_ == LOADED) { |
| state_ = PAINTED; |
| #if defined(OS_CHROMEOS) && defined(TOOLKIT_USES_GTK) |
| views::NativeWidgetGtk::UpdateFreezeUpdatesProperty( |
| GTK_WINDOW(GetWidget()->GetNativeView()), false); |
| #endif |
| } |
| break; |
| default: |
| NOTREACHED() << "unknown type" << type; |
| } |
| } |
| |
| void HtmlDialogView::RegisterDialogAccelerators() { |
| // Pressing the ESC key will close the dialog. |
| AddAccelerator(views::Accelerator(ui::VKEY_ESCAPE, false, false, false)); |
| } |