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.
5 #include "chrome/browser/ui/gtk/javascript_app_modal_dialog_gtk.h"
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"
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";
25 // If there's a text entry in the dialog, get the text from the first one and
27 base::string16
GetPromptText(GtkDialog
* dialog
) {
28 GtkWidget
* widget
= static_cast<GtkWidget
*>(
29 g_object_get_data(G_OBJECT(dialog
), kPromptTextId
));
31 return base::UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(widget
)));
32 return base::string16();
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
));
41 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget
));
47 ////////////////////////////////////////////////////////////////////////////////
48 // JavaScriptAppModalDialogGtk, public:
50 JavaScriptAppModalDialogGtk::JavaScriptAppModalDialogGtk(
51 JavaScriptAppModalDialog
* dialog
,
52 gfx::NativeWindow parent_window
)
54 GtkButtonsType buttons
= GTK_BUTTONS_NONE
;
55 GtkMessageType message_type
= GTK_MESSAGE_OTHER
;
57 // We add in the OK button manually later because we want to focus it
59 switch (dialog_
->javascript_message_type()) {
60 case content::JAVASCRIPT_MESSAGE_TYPE_ALERT
:
61 buttons
= GTK_BUTTONS_NONE
;
62 message_type
= GTK_MESSAGE_WARNING
;
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
;
71 buttons
= GTK_BUTTONS_CANCEL
;
73 message_type
= GTK_MESSAGE_QUESTION
;
76 case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT
:
77 buttons
= GTK_BUTTONS_CANCEL
;
78 message_type
= GTK_MESSAGE_QUESTION
;
85 // We want the alert to be app modal so put all the browser windows into the
87 gtk_util::MakeAppModalWindowGroup();
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());
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
);
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
);
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(),
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
);
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
);
146 gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_
), GTK_RESPONSE_OK
);
147 g_signal_connect(gtk_dialog_
, "response", G_CALLBACK(OnResponseThunk
), this);
150 JavaScriptAppModalDialogGtk::~JavaScriptAppModalDialogGtk() {
153 ////////////////////////////////////////////////////////////////////////////////
154 // JavaScriptAppModalDialogGtk, NativeAppModalDialog implementation:
156 int JavaScriptAppModalDialogGtk::GetAppModalDialogButtons() const {
157 switch (dialog_
->javascript_message_type()) {
158 case content::JAVASCRIPT_MESSAGE_TYPE_ALERT
:
159 return ui::DIALOG_BUTTON_OK
;
161 case content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM
:
162 return ui::DIALOG_BUTTON_OK
| ui::DIALOG_BUTTON_CANCEL
;
164 case content::JAVASCRIPT_MESSAGE_TYPE_PROMPT
:
165 return ui::DIALOG_BUTTON_OK
;
173 void JavaScriptAppModalDialogGtk::ShowAppModalDialog() {
174 gtk_util::ShowDialogWithMinLocalizedWidth(GTK_WIDGET(gtk_dialog_
),
175 IDS_ALERT_DIALOG_WIDTH_CHARS
);
178 void JavaScriptAppModalDialogGtk::ActivateAppModalDialog() {
180 gtk_window_present(GTK_WINDOW(gtk_dialog_
));
183 void JavaScriptAppModalDialogGtk::CloseAppModalDialog() {
185 OnResponse(gtk_dialog_
, GTK_RESPONSE_DELETE_EVENT
);
188 void JavaScriptAppModalDialogGtk::AcceptAppModalDialog() {
189 OnResponse(gtk_dialog_
, GTK_RESPONSE_OK
);
192 void JavaScriptAppModalDialogGtk::CancelAppModalDialog() {
193 OnResponse(gtk_dialog_
, GTK_RESPONSE_CANCEL
);
196 ////////////////////////////////////////////////////////////////////////////////
197 // JavaScriptAppModalDialogGtk, private:
199 void JavaScriptAppModalDialogGtk::OnResponse(GtkWidget
* dialog
,
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
)));
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
)));
217 gtk_widget_destroy(dialog
);
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();
225 ////////////////////////////////////////////////////////////////////////////////
226 // NativeAppModalDialog, public:
229 NativeAppModalDialog
* NativeAppModalDialog::CreateNativeJavaScriptPrompt(
230 JavaScriptAppModalDialog
* dialog
,
231 gfx::NativeWindow parent_window
) {
232 return new JavaScriptAppModalDialogGtk(dialog
, parent_window
);