Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / javascript_app_modal_dialog_gtk.cc
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 "chrome/browser/ui/gtk/javascript_app_modal_dialog_gtk.h"
6
7 #include <gtk/gtk.h>
8
9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
12 #include "chrome/browser/ui/gtk/gtk_util.h"
13 #include "grit/generated_resources.h"
14 #include "grit/locale_settings.h"
15 #include "ui/base/l10n/l10n_util.h"
16 #include "ui/base/ui_base_types.h"
17
18 namespace {
19
20 // We stash pointers to widgets on the gtk_dialog so we can refer to them
21 // after dialog creation.
22 const char kPromptTextId[] = "chrome_prompt_text";
23 const char kSuppressCheckboxId[] = "chrome_suppress_checkbox";
24
25 // If there's a text entry in the dialog, get the text from the first one and
26 // return it.
27 base::string16 GetPromptText(GtkDialog* dialog) {
28   GtkWidget* widget = static_cast<GtkWidget*>(
29       g_object_get_data(G_OBJECT(dialog), kPromptTextId));
30   if (widget)
31     return base::UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(widget)));
32   return base::string16();
33 }
34
35 // If there's a toggle button in the dialog, return the toggled state.
36 // Otherwise, return false.
37 bool ShouldSuppressJSDialogs(GtkDialog* dialog) {
38   GtkWidget* widget = static_cast<GtkWidget*>(
39       g_object_get_data(G_OBJECT(dialog), kSuppressCheckboxId));
40   if (widget)
41     return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
42   return false;
43 }
44
45 }  // namespace
46
47 ////////////////////////////////////////////////////////////////////////////////
48 // JavaScriptAppModalDialogGtk, public:
49
50 JavaScriptAppModalDialogGtk::JavaScriptAppModalDialogGtk(
51     JavaScriptAppModalDialog* dialog,
52     gfx::NativeWindow parent_window)
53     : dialog_(dialog) {
54   GtkButtonsType buttons = GTK_BUTTONS_NONE;
55   GtkMessageType message_type = GTK_MESSAGE_OTHER;
56
57   // We add in the OK button manually later because we want to focus it
58   // explicitly.
59   switch (dialog_->javascript_message_type()) {
60     case content::JAVASCRIPT_MESSAGE_TYPE_ALERT:
61       buttons = GTK_BUTTONS_NONE;
62       message_type = GTK_MESSAGE_WARNING;
63       break;
64
65     case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
66       if (dialog_->is_before_unload_dialog()) {
67         // onbeforeunload also uses a confirm prompt, it just has custom
68         // buttons.  We add the buttons using gtk_dialog_add_button below.
69         buttons = GTK_BUTTONS_NONE;
70       } else {
71         buttons = GTK_BUTTONS_CANCEL;
72       }
73       message_type = GTK_MESSAGE_QUESTION;
74       break;
75
76     case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT:
77       buttons = GTK_BUTTONS_CANCEL;
78       message_type = GTK_MESSAGE_QUESTION;
79       break;
80
81     default:
82       NOTREACHED();
83   }
84
85   // We want the alert to be app modal so put all the browser windows into the
86   // same window group.
87   gtk_util::MakeAppModalWindowGroup();
88
89   gtk_dialog_ = gtk_message_dialog_new(parent_window,
90       GTK_DIALOG_MODAL, message_type, buttons, "%s",
91       base::UTF16ToUTF8(dialog_->message_text()).c_str());
92   g_signal_connect(gtk_dialog_, "delete-event",
93                    G_CALLBACK(gtk_widget_hide_on_delete), NULL);
94   gtk_util::ApplyMessageDialogQuirks(gtk_dialog_);
95   gtk_window_set_title(GTK_WINDOW(gtk_dialog_),
96                        base::UTF16ToUTF8(dialog_->title()).c_str());
97
98   // Adjust content area as needed.  Set up the prompt text entry or
99   // suppression check box.
100   if (dialog_->javascript_message_type() ==
101           content::JAVASCRIPT_MESSAGE_TYPE_PROMPT) {
102     GtkWidget* content_area =
103         gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_));
104     GtkWidget* text_box = gtk_entry_new();
105     gtk_entry_set_text(GTK_ENTRY(text_box),
106         base::UTF16ToUTF8(dialog_->default_prompt_text()).c_str());
107     gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0);
108     g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
109     gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
110   }
111
112   if (dialog_->display_suppress_checkbox()) {
113     GtkWidget* content_area =
114         gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_));
115     GtkWidget* check_box = gtk_check_button_new_with_label(
116         l10n_util::GetStringUTF8(
117         IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION).c_str());
118     gtk_box_pack_start(GTK_BOX(content_area), check_box, TRUE, TRUE, 0);
119     g_object_set_data(G_OBJECT(gtk_dialog_), kSuppressCheckboxId, check_box);
120   }
121
122   // Adjust buttons/action area as needed.
123   if (dialog_->is_before_unload_dialog()) {
124     std::string button_text = l10n_util::GetStringUTF8(
125         dialog_->is_reload() ?
126         IDS_BEFORERELOAD_MESSAGEBOX_OK_BUTTON_LABEL :
127         IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL);
128     gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), button_text.c_str(),
129         GTK_RESPONSE_OK);
130
131     button_text = l10n_util::GetStringUTF8(
132         dialog_->is_reload() ?
133         IDS_BEFORERELOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL :
134         IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL);
135     gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), button_text.c_str(),
136         GTK_RESPONSE_CANCEL);
137   } else {
138     // Add the OK button and focus it.
139     GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
140         GTK_STOCK_OK, GTK_RESPONSE_OK);
141     if (dialog_->javascript_message_type() !=
142             content::JAVASCRIPT_MESSAGE_TYPE_PROMPT)
143       gtk_widget_grab_focus(ok_button);
144   }
145
146   gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK);
147   g_signal_connect(gtk_dialog_, "response", G_CALLBACK(OnResponseThunk), this);
148 }
149
150 JavaScriptAppModalDialogGtk::~JavaScriptAppModalDialogGtk() {
151 }
152
153 ////////////////////////////////////////////////////////////////////////////////
154 // JavaScriptAppModalDialogGtk, NativeAppModalDialog implementation:
155
156 int JavaScriptAppModalDialogGtk::GetAppModalDialogButtons() const {
157   switch (dialog_->javascript_message_type()) {
158     case content::JAVASCRIPT_MESSAGE_TYPE_ALERT:
159       return ui::DIALOG_BUTTON_OK;
160
161     case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM:
162       return ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
163
164     case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT:
165       return ui::DIALOG_BUTTON_OK;
166
167     default:
168       NOTREACHED();
169       return 0;
170   }
171 }
172
173 void JavaScriptAppModalDialogGtk::ShowAppModalDialog() {
174   gtk_util::ShowDialogWithMinLocalizedWidth(GTK_WIDGET(gtk_dialog_),
175       IDS_ALERT_DIALOG_WIDTH_CHARS);
176 }
177
178 void JavaScriptAppModalDialogGtk::ActivateAppModalDialog() {
179   DCHECK(gtk_dialog_);
180   gtk_window_present(GTK_WINDOW(gtk_dialog_));
181 }
182
183 void JavaScriptAppModalDialogGtk::CloseAppModalDialog() {
184   DCHECK(gtk_dialog_);
185   OnResponse(gtk_dialog_, GTK_RESPONSE_DELETE_EVENT);
186 }
187
188 void JavaScriptAppModalDialogGtk::AcceptAppModalDialog() {
189   OnResponse(gtk_dialog_, GTK_RESPONSE_OK);
190 }
191
192 void JavaScriptAppModalDialogGtk::CancelAppModalDialog() {
193   OnResponse(gtk_dialog_, GTK_RESPONSE_CANCEL);
194 }
195
196 ////////////////////////////////////////////////////////////////////////////////
197 // JavaScriptAppModalDialogGtk, private:
198
199 void JavaScriptAppModalDialogGtk::OnResponse(GtkWidget* dialog,
200                                              int response_id) {
201   switch (response_id) {
202     case GTK_RESPONSE_OK:
203       // The first arg is the prompt text and the second is true if we want to
204       // suppress additional popups from the page.
205       dialog_->OnAccept(GetPromptText(GTK_DIALOG(dialog)),
206                         ShouldSuppressJSDialogs(GTK_DIALOG(dialog)));
207       break;
208
209     case GTK_RESPONSE_CANCEL:
210     case GTK_RESPONSE_DELETE_EVENT:   // User hit the X on the dialog.
211       dialog_->OnCancel(ShouldSuppressJSDialogs(GTK_DIALOG(dialog)));
212       break;
213
214     default:
215       NOTREACHED();
216   }
217   gtk_widget_destroy(dialog);
218
219   // Now that the dialog is gone, we can put all the  windows into separate
220   // window groups so other dialogs are no longer app modal.
221   gtk_util::AppModalDismissedUngroupWindows();
222   delete this;
223 }
224
225 ////////////////////////////////////////////////////////////////////////////////
226 // NativeAppModalDialog, public:
227
228 // static
229 NativeAppModalDialog* NativeAppModalDialog::CreateNativeJavaScriptPrompt(
230     JavaScriptAppModalDialog* dialog,
231     gfx::NativeWindow parent_window) {
232   return new JavaScriptAppModalDialogGtk(dialog, parent_window);
233 }