172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/html_dialog_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/browser_dialogs.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_window.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/tab_contents_container_gtk.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/html_dialog_ui.h"
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/native_web_keyboard_event.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace browser {
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile,
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 HtmlDialogUIDelegate* delegate) {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HtmlDialogGtk* html_dialog =
2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      new HtmlDialogGtk(profile, delegate, parent);
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return html_dialog->InitDialog();
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} // namespace browser
3072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HtmlDialogGtk, public:
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHtmlDialogGtk::HtmlDialogGtk(Profile* profile,
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             HtmlDialogUIDelegate* delegate,
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             gfx::NativeWindow parent_window)
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : HtmlDialogTabContentsDelegate(profile),
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delegate_(delegate),
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parent_window_(parent_window),
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dialog_(NULL) {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHtmlDialogGtk::~HtmlDialogGtk() {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HtmlDialogUIDelegate implementation:
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HtmlDialogGtk::IsDialogModal() const {
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return delegate_ ? delegate_->IsDialogModal() : false;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::wstring HtmlDialogGtk::GetDialogTitle() const {
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return delegate_ ? delegate_->GetDialogTitle() : L"";
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL HtmlDialogGtk::GetDialogContentURL() const {
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (delegate_)
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return delegate_->GetDialogContentURL();
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return GURL();
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid HtmlDialogGtk::GetWebUIMessageHandlers(
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::vector<WebUIMessageHandler*>* handlers) const {
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (delegate_)
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    delegate_->GetWebUIMessageHandlers(handlers);
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    handlers->clear();
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HtmlDialogGtk::GetDialogSize(gfx::Size* size) const {
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (delegate_)
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delegate_->GetDialogSize(size);
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *size = gfx::Size();
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string HtmlDialogGtk::GetDialogArgs() const {
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (delegate_)
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return delegate_->GetDialogArgs();
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return std::string();
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HtmlDialogGtk::OnDialogClosed(const std::string& json_retval) {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(dialog_);
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Detach();
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (delegate_) {
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HtmlDialogUIDelegate* dialog_delegate = delegate_;
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    delegate_ = NULL;  // We will not communicate further with the delegate.
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    dialog_delegate->OnDialogClosed(json_retval);
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_destroy(dialog_);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete this;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool HtmlDialogGtk::ShouldShowDialogTitle() const {
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return true;
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TabContentsDelegate implementation:
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HtmlDialogGtk::MoveContents(TabContents* source, const gfx::Rect& pos) {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The contained web page wishes to resize itself. We let it do this because
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // if it's a dialog we know about, we trust it not to be mean to the user.
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A simplified version of BrowserWindowGtk::HandleKeyboardEvent().
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We don't handle global keyboard shortcuts here, but that's fine since
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// they're all browser-specific. (This may change in the future.)
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HtmlDialogGtk::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GdkEventKey* os_event = event.os_event;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!os_event || event.type == WebKit::WebInputEvent::Char)
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // To make sure the default key bindings can still work, such as Escape to
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // close the dialog.
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_bindings_activate_event(GTK_OBJECT(dialog_), os_event);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HtmlDialogGtk:
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsengfx::NativeWindow HtmlDialogGtk::InitDialog() {
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  tab_.reset(new TabContentsWrapper(
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new TabContents(profile(), NULL, MSG_ROUTING_NONE, NULL, NULL)));
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  tab_->tab_contents()->set_delegate(this);
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This must be done before loading the page; see the comments in
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // HtmlDialogUI.
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  HtmlDialogUI::GetPropertyAccessor().SetProperty(
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      tab_->tab_contents()->property_bag(), this);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  tab_->controller().LoadURL(GetDialogContentURL(),
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             GURL(), PageTransition::START_PAGE);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkDialogFlags flags = GTK_DIALOG_NO_SEPARATOR;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (delegate_->IsDialogModal())
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    flags = static_cast<GtkDialogFlags>(flags | GTK_DIALOG_MODAL);
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dialog_ = gtk_dialog_new_with_buttons(
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WideToUTF8(delegate_->GetDialogTitle()).c_str(),
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parent_window_,
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      flags,
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL);
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tab_contents_container_.reset(new TabContentsContainerGtk(NULL));
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox),
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     tab_contents_container_->widget(), TRUE, TRUE, 0);
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  tab_contents_container_->SetTab(tab_.get());
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size dialog_size;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_->GetDialogSize(&dialog_size);
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_set_size_request(GTK_WIDGET(tab_contents_container_->widget()),
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              dialog_size.width(),
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              dialog_size.height());
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_widget_show_all(dialog_);
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return GTK_WINDOW(dialog_);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HtmlDialogGtk::OnResponse(GtkWidget* dialog, int response_id) {
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OnDialogClosed(std::string());
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
172