1 // Copyright (c) 2011 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/gtk/html_dialog_gtk.h" 6 7 #include <gtk/gtk.h> 8 9 #include "base/utf_string_conversions.h" 10 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser_dialogs.h" 12 #include "chrome/browser/ui/browser_window.h" 13 #include "chrome/browser/ui/gtk/gtk_util.h" 14 #include "chrome/browser/ui/gtk/tab_contents_container_gtk.h" 15 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 16 #include "chrome/browser/ui/webui/html_dialog_ui.h" 17 #include "content/browser/tab_contents/tab_contents.h" 18 #include "content/common/native_web_keyboard_event.h" 19 20 namespace browser { 21 22 gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile, 23 HtmlDialogUIDelegate* delegate) { 24 HtmlDialogGtk* html_dialog = 25 new HtmlDialogGtk(profile, delegate, parent); 26 return html_dialog->InitDialog(); 27 } 28 29 } // namespace browser 30 31 //////////////////////////////////////////////////////////////////////////////// 32 // HtmlDialogGtk, public: 33 34 HtmlDialogGtk::HtmlDialogGtk(Profile* profile, 35 HtmlDialogUIDelegate* delegate, 36 gfx::NativeWindow parent_window) 37 : HtmlDialogTabContentsDelegate(profile), 38 delegate_(delegate), 39 parent_window_(parent_window), 40 dialog_(NULL) { 41 } 42 43 HtmlDialogGtk::~HtmlDialogGtk() { 44 } 45 46 //////////////////////////////////////////////////////////////////////////////// 47 // HtmlDialogUIDelegate implementation: 48 49 bool HtmlDialogGtk::IsDialogModal() const { 50 return delegate_ ? delegate_->IsDialogModal() : false; 51 } 52 53 std::wstring HtmlDialogGtk::GetDialogTitle() const { 54 return delegate_ ? delegate_->GetDialogTitle() : L""; 55 } 56 57 GURL HtmlDialogGtk::GetDialogContentURL() const { 58 if (delegate_) 59 return delegate_->GetDialogContentURL(); 60 else 61 return GURL(); 62 } 63 64 void HtmlDialogGtk::GetWebUIMessageHandlers( 65 std::vector<WebUIMessageHandler*>* handlers) const { 66 if (delegate_) 67 delegate_->GetWebUIMessageHandlers(handlers); 68 else 69 handlers->clear(); 70 } 71 72 void HtmlDialogGtk::GetDialogSize(gfx::Size* size) const { 73 if (delegate_) 74 delegate_->GetDialogSize(size); 75 else 76 *size = gfx::Size(); 77 } 78 79 std::string HtmlDialogGtk::GetDialogArgs() const { 80 if (delegate_) 81 return delegate_->GetDialogArgs(); 82 else 83 return std::string(); 84 } 85 86 void HtmlDialogGtk::OnDialogClosed(const std::string& json_retval) { 87 DCHECK(dialog_); 88 89 Detach(); 90 if (delegate_) { 91 HtmlDialogUIDelegate* dialog_delegate = delegate_; 92 delegate_ = NULL; // We will not communicate further with the delegate. 93 dialog_delegate->OnDialogClosed(json_retval); 94 } 95 gtk_widget_destroy(dialog_); 96 delete this; 97 } 98 99 bool HtmlDialogGtk::ShouldShowDialogTitle() const { 100 return true; 101 } 102 103 //////////////////////////////////////////////////////////////////////////////// 104 // TabContentsDelegate implementation: 105 106 void HtmlDialogGtk::MoveContents(TabContents* source, const gfx::Rect& pos) { 107 // The contained web page wishes to resize itself. We let it do this because 108 // if it's a dialog we know about, we trust it not to be mean to the user. 109 } 110 111 // A simplified version of BrowserWindowGtk::HandleKeyboardEvent(). 112 // We don't handle global keyboard shortcuts here, but that's fine since 113 // they're all browser-specific. (This may change in the future.) 114 void HtmlDialogGtk::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { 115 GdkEventKey* os_event = event.os_event; 116 if (!os_event || event.type == WebKit::WebInputEvent::Char) 117 return; 118 119 // To make sure the default key bindings can still work, such as Escape to 120 // close the dialog. 121 gtk_bindings_activate_event(GTK_OBJECT(dialog_), os_event); 122 } 123 124 //////////////////////////////////////////////////////////////////////////////// 125 // HtmlDialogGtk: 126 127 gfx::NativeWindow HtmlDialogGtk::InitDialog() { 128 tab_.reset(new TabContentsWrapper( 129 new TabContents(profile(), NULL, MSG_ROUTING_NONE, NULL, NULL))); 130 tab_->tab_contents()->set_delegate(this); 131 132 // This must be done before loading the page; see the comments in 133 // HtmlDialogUI. 134 HtmlDialogUI::GetPropertyAccessor().SetProperty( 135 tab_->tab_contents()->property_bag(), this); 136 137 tab_->controller().LoadURL(GetDialogContentURL(), 138 GURL(), PageTransition::START_PAGE); 139 GtkDialogFlags flags = GTK_DIALOG_NO_SEPARATOR; 140 if (delegate_->IsDialogModal()) 141 flags = static_cast<GtkDialogFlags>(flags | GTK_DIALOG_MODAL); 142 143 dialog_ = gtk_dialog_new_with_buttons( 144 WideToUTF8(delegate_->GetDialogTitle()).c_str(), 145 parent_window_, 146 flags, 147 NULL); 148 149 g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this); 150 151 tab_contents_container_.reset(new TabContentsContainerGtk(NULL)); 152 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), 153 tab_contents_container_->widget(), TRUE, TRUE, 0); 154 155 tab_contents_container_->SetTab(tab_.get()); 156 157 gfx::Size dialog_size; 158 delegate_->GetDialogSize(&dialog_size); 159 160 gtk_widget_set_size_request(GTK_WIDGET(tab_contents_container_->widget()), 161 dialog_size.width(), 162 dialog_size.height()); 163 164 gtk_widget_show_all(dialog_); 165 166 return GTK_WINDOW(dialog_); 167 } 168 169 void HtmlDialogGtk::OnResponse(GtkWidget* dialog, int response_id) { 170 OnDialogClosed(std::string()); 171 } 172