[evolution/wip-webkit2] Avoid race condition while asking for the name of HTML element that currently has focus.
- From: Tomas Popela <tpopela src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip-webkit2] Avoid race condition while asking for the name of HTML element that currently has focus.
- Date: Thu, 5 Dec 2013 15:12:51 +0000 (UTC)
commit 4005293662b7363fd3fb57a74ffa5483e18df833
Author: Tomas Popela <tpopela redhat com>
Date: Thu Dec 5 14:28:08 2013 +0100
Avoid race condition while asking for the name of HTML element that currently has focus.
e-util/e-dom-utils.c | 121 +++++++++++++++++++++++++++++-
e-util/e-dom-utils.h | 3 +
e-util/e-web-view.c | 1 -
mail/e-mail-reader.c | 24 +-----
modules/mail/e-mail-shell-view-private.c | 62 ++-------------
web-extensions/evolution-web-extension.c | 64 +++++++++++++++-
6 files changed, 198 insertions(+), 77 deletions(-)
---
diff --git a/e-util/e-dom-utils.c b/e-util/e-dom-utils.c
index 658578a..552943d 100644
--- a/e-util/e-dom-utils.c
+++ b/e-util/e-dom-utils.c
@@ -527,7 +527,7 @@ toggle_headers_visibility (WebKitDOMElement *button,
static void
toggle_address_visibility (WebKitDOMElement *button,
WebKitDOMEvent *event,
- GDBusConnection *connection)
+ GDBusConnection *connection)
{
WebKitDOMElement *full_addr, *ellipsis;
WebKitDOMElement *parent;
@@ -618,6 +618,125 @@ e_dom_utils_bind_dom (WebKitDOMDocument *document,
}
}
+static void
+e_dom_utils_bind_elements_recursively (WebKitDOMDocument *document,
+ const gchar *selector,
+ const gchar *event,
+ gpointer callback,
+ gpointer user_data)
+{
+ WebKitDOMNodeList *nodes;
+ gulong ii, length;
+
+ nodes = webkit_dom_document_query_selector_all (
+ document, selector, NULL);
+
+ length = webkit_dom_node_list_get_length (nodes);
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMNode *node;
+
+ node = webkit_dom_node_list_item (nodes, ii);
+ webkit_dom_event_target_add_event_listener (
+ WEBKIT_DOM_EVENT_TARGET (node), event,
+ G_CALLBACK (callback), FALSE, user_data);
+ }
+
+ nodes = webkit_dom_document_query_selector_all (document, "iframe", NULL);
+ length = webkit_dom_node_list_get_length (nodes);
+
+ /* Add rules to every sub document */
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMDocument *content_document = NULL;
+ WebKitDOMNode *node;
+
+ node = webkit_dom_node_list_item (nodes, ii);
+ content_document =
+ webkit_dom_html_iframe_element_get_content_document (
+ WEBKIT_DOM_HTML_IFRAME_ELEMENT (node));
+
+ if (!content_document)
+ continue;
+
+ e_dom_utils_bind_elements_recursively (
+ content_document,
+ selector,
+ event,
+ callback,
+ user_data);
+ }
+}
+
+static void
+element_focus_cb (WebKitDOMElement *element,
+ WebKitDOMEvent *event,
+ GDBusConnection *connection)
+{
+ g_dbus_connection_call (
+ connection,
+ "org.gnome.Evolution.WebExtension",
+ "/org/gnome/Evolution/WebExtension",
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ g_variant_new (
+ "(ssv)",
+ "org.gnome.Evolution.WebExtension",
+ "NeedInput",
+ g_variant_new_boolean (TRUE)),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+
+}
+
+static void
+element_blur_cb (WebKitDOMElement *element,
+ WebKitDOMEvent *event,
+ GDBusConnection *connection)
+{
+ g_dbus_connection_call (
+ connection,
+ "org.gnome.Evolution.WebExtension",
+ "/org/gnome/Evolution/WebExtension",
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ g_variant_new (
+ "(ssv)",
+ "org.gnome.Evolution.WebExtension",
+ "NeedInput",
+ g_variant_new_boolean (FALSE)),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL,
+ NULL);
+}
+
+
+void
+e_dom_utils_bind_focus_on_elements (WebKitDOMDocument *document,
+ GDBusConnection *connection)
+{
+ const gchar *elements = "input, textarea, select, button, label";
+
+ e_dom_utils_bind_elements_recursively (
+ document,
+ elements,
+ "focus",
+ element_focus_cb,
+ connection);
+
+ e_dom_utils_bind_elements_recursively (
+ document,
+ elements,
+ "blur",
+ element_blur_cb,
+ connection);
+}
+
void
e_dom_utils_e_mail_display_bind_dom (WebKitDOMDocument *document,
GDBusConnection *connection)
diff --git a/e-util/e-dom-utils.h b/e-util/e-dom-utils.h
index 56916da..6803951 100644
--- a/e-util/e-dom-utils.h
+++ b/e-util/e-dom-utils.h
@@ -48,6 +48,9 @@ void e_dom_utils_add_css_rule_into_style_sheet
const gchar *style);
void e_dom_utils_eab_contact_formatter_bind_dom
(WebKitDOMDocument *document);
+void e_dom_utils_bind_focus_on_elements
+ (WebKitDOMDocument *document,
+ GDBusConnection *connection);
void e_dom_utils_e_mail_display_bind_dom
(WebKitDOMDocument *document,
GDBusConnection *connection);
diff --git a/e-util/e-web-view.c b/e-util/e-web-view.c
index 253e6bd..ef833ae 100644
--- a/e-util/e-web-view.c
+++ b/e-util/e-web-view.c
@@ -1156,7 +1156,6 @@ web_extension_appeared_cb (GDBusConnection *connection,
g_dbus_proxy_new (
connection,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
NULL,
name,
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 167d2ed..68f2d1e 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -2469,30 +2469,14 @@ mail_reader_key_press_event_cb (EMailReader *reader,
web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (display));
if (web_extension) {
GVariant *result;
- const gchar *element_name = NULL;
-
- result = g_dbus_proxy_call_sync (
- web_extension,
- "GetActiveElementName",
- g_variant_new (
- "(t)",
- webkit_web_view_get_page_id (
- WEBKIT_WEB_VIEW (display))),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL);
+ result = g_dbus_proxy_get_cached_property (web_extension, "NeedInput");
if (result) {
- g_variant_get (result, "(&s)", &element_name);
+ gboolean need_input = g_variant_get_boolean (result);
g_variant_unref (result);
- if (element_name && *element_name) {
- if (g_strcmp0 (element_name, "input") == 0 ||
- g_strcmp0 (element_name, "textarea") == 0) {
- return FALSE;
- }
- }
+ if (need_input)
+ return FALSE;
}
}
}
diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c
index 2a6e6be..14fd7af 100644
--- a/modules/mail/e-mail-shell-view-private.c
+++ b/modules/mail/e-mail-shell-view-private.c
@@ -256,39 +256,24 @@ mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view,
static gboolean
mail_shell_view_mail_display_needs_key (EMailShellView *mail_shell_view,
- EMailDisplay *mail_display,
- gboolean with_input)
+ EMailDisplay *mail_display)
{
if (gtk_widget_has_focus (GTK_WIDGET (mail_display))) {
GDBusProxy *web_extension;
- web_extension = e_mail_shell_view_get_web_extension_proxy (mail_shell_view);
+ /* Intentionally use Evolution Web Extension */
+ web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (mail_display));
if (web_extension) {
GVariant *result;
- const gchar *element_name = NULL;
-
- result = g_dbus_proxy_call_sync (
- web_extension,
- "GetActiveElementName",
- g_variant_new (
- "(t)",
- webkit_web_view_get_page_id (
- WEBKIT_WEB_VIEW (mail_display))),
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL);
+ result = g_dbus_proxy_get_cached_property (web_extension, "NeedInput");
if (result) {
- element_name = g_variant_get_string (result, NULL);
+ gboolean need_input;
+
+ need_input = g_variant_get_boolean (result);
g_variant_unref (result);
- if (element_name && *element_name) {
- if ((with_input && g_strcmp0 (element_name, "input") == 0) ||
- g_strcmp0 (element_name, "textarea") == 0) {
- return TRUE;
- }
- }
+ return need_input;
}
}
}
@@ -327,40 +312,11 @@ mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view,
action = ACTION (MAIL_SMART_BACKWARD);
break;
- case GDK_KEY_Home:
- case GDK_KEY_Left:
- case GDK_KEY_Up:
- case GDK_KEY_Right:
- case GDK_KEY_Down:
- case GDK_KEY_Prior:
- case GDK_KEY_Next:
- case GDK_KEY_End:
- case GDK_KEY_Begin:
-#if 0
- if (!mail_shell_view_mail_display_needs_key (mail_shell_view, mail_display, FALSE) &&
- webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (mail_display)) !=
- webkit_web_view_get_focused_frame (WEBKIT_WEB_VIEW (mail_display))) {
- WebKitDOMDocument *document;
- WebKitDOMDOMWindow *window;
-
- document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (mail_display));
- window = webkit_dom_document_get_default_view (document);
-
- /* Workaround WebKit bug for key navigation, when inner IFRAME is focused.
- * EMailView's inner IFRAMEs have disabled scrolling, but WebKit doesn't post
- * key navigation events to parent's frame, thus the view doesn't scroll.
- * This is a poor workaround for this issue, the main frame is focused,
- * which has scrolling enabled.
- */
- webkit_dom_dom_window_focus (window);
- }
-#endif
- return FALSE;
default:
return FALSE;
}
- if (mail_shell_view_mail_display_needs_key (mail_shell_view, mail_display, TRUE))
+ if (mail_shell_view_mail_display_needs_key (mail_shell_view, mail_display))
return FALSE;
gtk_action_activate (action);
diff --git a/web-extensions/evolution-web-extension.c b/web-extensions/evolution-web-extension.c
index 26c205b..02fa3ba 100644
--- a/web-extensions/evolution-web-extension.c
+++ b/web-extensions/evolution-web-extension.c
@@ -30,6 +30,7 @@
/* FIXME Clean it */
static GDBusConnection *dbus_connection;
+static gboolean need_input = FALSE;
static const char introspection_xml[] =
"<node>"
@@ -103,6 +104,7 @@ static const char introspection_xml[] =
" <arg type='s' name='button_id' direction='in'/>"
" <arg type='s' name='src' direction='in'/>"
" </method>"
+" <property type='b' name='NeedInput' access='readwrite'/>"
" </interface>"
"</node>";
@@ -301,6 +303,7 @@ handle_method_call (GDBusConnection *connection,
document = webkit_web_page_get_dom_document (web_page);
e_dom_utils_e_mail_display_bind_dom (document, connection);
+ e_dom_utils_bind_focus_on_elements (document, connection);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "ElementExists") == 0) {
@@ -389,10 +392,67 @@ handle_method_call (GDBusConnection *connection,
}
}
+static GVariant *
+handle_get_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ GVariant *variant;
+
+ if (g_strcmp0 (property_name, "NeedInput") == 0) {
+ variant = g_variant_new_boolean (need_input);
+ }
+
+ return variant;
+}
+
+static gboolean
+handle_set_property (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *variant,
+ GError **error,
+ gpointer user_data)
+{
+ if (need_input != g_variant_get_boolean (variant)) {
+ GVariantBuilder *builder;
+ GError *local_error;
+
+ need_input = g_variant_get_boolean (variant);
+
+ local_error = NULL;
+ builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add (builder,
+ "{sv}",
+ "NeedInput",
+ g_variant_new_boolean (need_input));
+ g_dbus_connection_emit_signal (connection,
+ NULL,
+ object_path,
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ g_variant_new (
+ "(sa{sv}as)",
+ interface_name,
+ builder,
+ NULL),
+ &local_error);
+ g_assert_no_error (local_error);
+ }
+
+ return TRUE;
+}
+
static const GDBusInterfaceVTable interface_vtable = {
handle_method_call,
- NULL,
- NULL
+ handle_get_property,
+ handle_set_property
};
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]