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
20namespace browser {
21
22gfx::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
34HtmlDialogGtk::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
43HtmlDialogGtk::~HtmlDialogGtk() {
44}
45
46////////////////////////////////////////////////////////////////////////////////
47// HtmlDialogUIDelegate implementation:
48
49bool HtmlDialogGtk::IsDialogModal() const {
50  return delegate_ ? delegate_->IsDialogModal() : false;
51}
52
53std::wstring HtmlDialogGtk::GetDialogTitle() const {
54  return delegate_ ? delegate_->GetDialogTitle() : L"";
55}
56
57GURL HtmlDialogGtk::GetDialogContentURL() const {
58  if (delegate_)
59    return delegate_->GetDialogContentURL();
60  else
61    return GURL();
62}
63
64void HtmlDialogGtk::GetWebUIMessageHandlers(
65    std::vector<WebUIMessageHandler*>* handlers) const {
66  if (delegate_)
67    delegate_->GetWebUIMessageHandlers(handlers);
68  else
69    handlers->clear();
70}
71
72void HtmlDialogGtk::GetDialogSize(gfx::Size* size) const {
73  if (delegate_)
74    delegate_->GetDialogSize(size);
75  else
76    *size = gfx::Size();
77}
78
79std::string HtmlDialogGtk::GetDialogArgs() const {
80  if (delegate_)
81    return delegate_->GetDialogArgs();
82  else
83    return std::string();
84}
85
86void 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
99bool HtmlDialogGtk::ShouldShowDialogTitle() const {
100  return true;
101}
102
103////////////////////////////////////////////////////////////////////////////////
104// TabContentsDelegate implementation:
105
106void 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.)
114void 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
127gfx::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
169void HtmlDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
170  OnDialogClosed(std::string());
171}
172