Linux: cefclient: Add a GTK implementation of CefJSDialogHandler (issue #1258).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1760 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2014-07-09 17:13:06 +00:00
parent 824f8f4009
commit da1ac7dde5
3 changed files with 194 additions and 0 deletions

View File

@ -98,6 +98,10 @@ ClientHandler::ClientHandler()
m_StopHwnd(NULL),
m_ReloadHwnd(NULL),
m_bFocusOnEditableField(false) {
#if defined(OS_LINUX)
gtk_dialog_ = NULL;
#endif
// Read command line settings.
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
@ -260,6 +264,32 @@ bool ClientHandler::OnRequestGeolocationPermission(
return true;
}
#if !defined(OS_LINUX)
bool ClientHandler::OnJSDialog(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
const CefString& accept_lang,
JSDialogType dialog_type,
const CefString& message_text,
const CefString& default_prompt_text,
CefRefPtr<CefJSDialogCallback> callback,
bool& suppress_message) {
return false;
}
bool ClientHandler::OnBeforeUnloadDialog(
CefRefPtr<CefBrowser> browser,
const CefString& message_text,
bool is_reload,
CefRefPtr<CefJSDialogCallback> callback) {
return false;
}
void ClientHandler::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
}
#endif // !defined(OS_LINUX)
bool ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event,

View File

@ -33,6 +33,7 @@ class ClientHandler : public CefClient,
public CefDownloadHandler,
public CefDragHandler,
public CefGeolocationHandler,
public CefJSDialogHandler,
public CefKeyboardHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
@ -66,6 +67,9 @@ class ClientHandler : public CefClient,
virtual CefRefPtr<CefGeolocationHandler> GetGeolocationHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE {
return this;
}
@ -131,6 +135,22 @@ class ClientHandler : public CefClient,
int request_id,
CefRefPtr<CefGeolocationCallback> callback) OVERRIDE;
// CefJSDialogHandler methods
virtual bool OnJSDialog(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
const CefString& accept_lang,
JSDialogType dialog_type,
const CefString& message_text,
const CefString& default_prompt_text,
CefRefPtr<CefJSDialogCallback> callback,
bool& suppress_message) OVERRIDE;
virtual bool OnBeforeUnloadDialog(
CefRefPtr<CefBrowser> browser,
const CefString& message_text,
bool is_reload,
CefRefPtr<CefJSDialogCallback> callback) OVERRIDE;
virtual void OnResetDialogState(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefKeyboardHandler methods
virtual bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
@ -334,6 +354,14 @@ class ClientHandler : public CefClient,
// when the number of windows reaches 0.
static int m_BrowserCount;
#if defined(OS_LINUX)
static void OnDialogResponse(GtkDialog *dialog,
gint response_id,
ClientHandler* handler);
GtkWidget* gtk_dialog_;
CefRefPtr<CefJSDialogCallback> js_dialog_callback_;
#endif
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(ClientHandler);
// Include the default locking implementation.

View File

@ -13,6 +13,22 @@
#include "include/cef_browser.h"
#include "include/cef_frame.h"
namespace {
const char kPromptTextId[] = "cef_prompt_text";
// If there's a text entry in the dialog, get the text from the first one and
// return it.
std::string GetPromptText(GtkDialog* dialog) {
GtkWidget* widget = static_cast<GtkWidget*>(
g_object_get_data(G_OBJECT(dialog), kPromptTextId));
if (widget)
return gtk_entry_get_text(GTK_ENTRY(widget));
return std::string();
}
} // namespace
void ClientHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) {
@ -75,6 +91,126 @@ void ClientHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
}
}
bool ClientHandler::OnJSDialog(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
const CefString& accept_lang,
JSDialogType dialog_type,
const CefString& message_text,
const CefString& default_prompt_text,
CefRefPtr<CefJSDialogCallback> callback,
bool& suppress_message) {
GtkButtonsType buttons = GTK_BUTTONS_NONE;
GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER;
std::string title;
switch (dialog_type) {
case JSDIALOGTYPE_ALERT:
buttons = GTK_BUTTONS_NONE;
gtk_message_type = GTK_MESSAGE_WARNING;
title = "JavaScript Alert";
break;
case JSDIALOGTYPE_CONFIRM:
buttons = GTK_BUTTONS_CANCEL;
gtk_message_type = GTK_MESSAGE_QUESTION;
title = "JavaScript Confirm";
break;
case JSDIALOGTYPE_PROMPT:
buttons = GTK_BUTTONS_CANCEL;
gtk_message_type = GTK_MESSAGE_QUESTION;
title = "JavaScript Prompt";
break;
}
js_dialog_callback_ = callback;
if (!origin_url.empty()) {
title += " - ";
title += origin_url.ToString();
}
GtkWidget* window =
gtk_widget_get_ancestor(GTK_WIDGET(GetMainHwnd()), GTK_TYPE_WINDOW);
gtk_dialog_ = gtk_message_dialog_new(GTK_WINDOW(window),
GTK_DIALOG_MODAL,
gtk_message_type,
buttons,
"%s",
message_text.ToString().c_str());
g_signal_connect(gtk_dialog_,
"delete-event",
G_CALLBACK(gtk_widget_hide_on_delete),
NULL);
gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str());
GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
GTK_STOCK_OK,
GTK_RESPONSE_OK);
if (dialog_type != JSDIALOGTYPE_PROMPT)
gtk_widget_grab_focus(ok_button);
if (dialog_type == JSDIALOGTYPE_PROMPT) {
GtkWidget* content_area =
gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_));
GtkWidget* text_box = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(text_box),
default_prompt_text.ToString().c_str());
gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0);
g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
}
gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK);
g_signal_connect(gtk_dialog_, "response", G_CALLBACK(OnDialogResponse), this);
gtk_widget_show_all(GTK_WIDGET(gtk_dialog_));
return true;
}
bool ClientHandler::OnBeforeUnloadDialog(
CefRefPtr<CefBrowser> browser,
const CefString& message_text,
bool is_reload,
CefRefPtr<CefJSDialogCallback> callback) {
const std::string& new_message_text =
message_text.ToString() + "\n\nIs it OK to leave/reload this page?";
bool suppress_message = false;
return OnJSDialog(browser, CefString(), CefString(), JSDIALOGTYPE_CONFIRM,
new_message_text, CefString(), callback, suppress_message);
}
void ClientHandler::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
if (!gtk_dialog_)
return;
gtk_widget_destroy(gtk_dialog_);
gtk_dialog_ = NULL;
js_dialog_callback_ = NULL;
}
// static
void ClientHandler::OnDialogResponse(GtkDialog* dialog,
gint response_id,
ClientHandler* handler) {
ASSERT(dialog == GTK_DIALOG(handler->gtk_dialog_));
switch (response_id) {
case GTK_RESPONSE_OK:
handler->js_dialog_callback_->Continue(true, GetPromptText(dialog));
break;
case GTK_RESPONSE_CANCEL:
case GTK_RESPONSE_DELETE_EVENT:
handler->js_dialog_callback_->Continue(false, CefString());
break;
default:
ASSERT(false); // Not reached
}
handler->OnResetDialogState(NULL);
}
void ClientHandler::SendNotification(NotificationType type) {
// TODO(port): Implement this method.
}