aboutsummaryrefslogtreecommitdiffstats
path: root/embed
diff options
context:
space:
mode:
authorDiego Escalante Urrelo <descalante@igalia.com>2010-07-27 17:41:22 +0800
committerDiego Escalante Urrelo <descalante@igalia.com>2010-08-02 19:15:15 +0800
commit3bcf8e86178f65981821ce6cba0ae1f3b46e3591 (patch)
treec4e209cfe480c7423d5cb9fddc291fca77c6879a /embed
parent55b66ccdffde240e171e8b05033ef220e0e2022a (diff)
downloadgsoc2013-epiphany-3bcf8e86178f65981821ce6cba0ae1f3b46e3591.tar
gsoc2013-epiphany-3bcf8e86178f65981821ce6cba0ae1f3b46e3591.tar.gz
gsoc2013-epiphany-3bcf8e86178f65981821ce6cba0ae1f3b46e3591.tar.bz2
gsoc2013-epiphany-3bcf8e86178f65981821ce6cba0ae1f3b46e3591.tar.lz
gsoc2013-epiphany-3bcf8e86178f65981821ce6cba0ae1f3b46e3591.tar.xz
gsoc2013-epiphany-3bcf8e86178f65981821ce6cba0ae1f3b46e3591.tar.zst
gsoc2013-epiphany-3bcf8e86178f65981821ce6cba0ae1f3b46e3591.zip
ephy-web-view: use GObject DOM for form fill/save
Bug #625404
Diffstat (limited to 'embed')
-rw-r--r--embed/ephy-web-view.c410
1 files changed, 121 insertions, 289 deletions
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index f5d155863..bf6ab19b6 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -600,21 +600,6 @@ js_object_get_property_as_object (JSContextRef js_context,
}
static char *
-js_get_element_property (JSContextRef js_context,
- JSObjectRef object,
- const char *prop)
-{
- JSValueRef val;
- char *buffer = NULL;
-
- val = js_object_get_property (js_context, object, prop);
- if (JSValueIsString (js_context, val))
- buffer = js_value_to_string (js_context, val);
-
- return buffer;
-}
-
-static char *
js_get_element_attribute (JSContextRef js_context,
JSObjectRef object,
const char *attr)
@@ -635,68 +620,6 @@ js_get_element_attribute (JSContextRef js_context,
}
static GSList*
-js_get_all_forms (JSContextRef js_context)
-{
- JSObjectRef js_global;
- JSObjectRef js_object;
- JSValueRef js_form;
- guint index = 0;
- GSList *retval = NULL;
-
- js_global = JSContextGetGlobalObject (js_context);
-
- js_object = js_object_get_property_as_object (js_context, js_global, "document");
- if (!js_object)
- return NULL;
-
- js_object = js_object_get_property_as_object (js_context, js_object, "forms");
- if (!js_object)
- return NULL;
-
- while (TRUE) {
- js_form = JSObjectGetPropertyAtIndex (js_context, js_object, index++, NULL);
-
- if (JSValueIsUndefined (js_context, js_form))
- break;
-
- retval = g_slist_prepend (retval, (gpointer)js_form);
- }
-
- return retval;
-}
-
-static GSList*
-js_get_form_elements (JSContextRef js_context, JSValueRef js_form)
-{
- JSObjectRef js_object = JSValueToObject (js_context, js_form, NULL);
- JSStringRef js_name;
- JSValueRef value;
- guint num;
- guint count;
- GSList *retval = NULL;
-
- js_object = js_object_get_property_as_object (js_context, js_object, "elements");
- if (!js_object)
- return NULL;
-
- js_name = JSStringCreateWithUTF8CString ("length");
- value = JSObjectGetProperty (js_context, js_object, js_name, NULL);
- JSStringRelease (js_name);
-
- num = (guint)JSValueToNumber (js_context, value, NULL);
- for (count = 0; count < num; count++) {
- value = JSObjectGetPropertyAtIndex (js_context, js_object, count, NULL);
-
- if (!JSValueIsObject (js_context, value))
- continue;
-
- retval = g_slist_prepend (retval, (gpointer)value);
- }
-
- return retval;
-}
-
-static GSList*
js_get_all_links (JSContextRef js_context)
{
JSObjectRef js_global;
@@ -745,9 +668,8 @@ js_get_all_links (JSContextRef js_context)
}
typedef struct {
- JSContextRef context;
- JSObjectRef username_element;
- JSObjectRef password_element;
+ WebKitDOMNode *username_node;
+ WebKitDOMNode *password_node;
} FillData;
static void
@@ -755,6 +677,9 @@ fill_data_free (gpointer data)
{
FillData *fill_data = (FillData*)data;
+ g_object_unref (fill_data->username_node);
+ g_object_unref (fill_data->password_node);
+
g_slice_free (FillData, fill_data);
}
@@ -763,12 +688,7 @@ fill_form_cb (GnomeKeyringResult retval,
GList *results,
gpointer user_data)
{
- JSValueRef prop_value;
- JSStringRef prop_value_str, prop_name;
FillData *fill_data = (FillData*)user_data;
- JSContextRef js_context = fill_data->context;
- JSObjectRef username_element = fill_data->username_element;
- JSObjectRef password_element = fill_data->password_element;
GnomeKeyringNetworkPasswordData* keyring_data;
if (!results) {
@@ -787,59 +707,67 @@ fill_form_cb (GnomeKeyringResult retval,
LOG ("Found: user %s pass (hidden)", keyring_data->user);
- prop_name = JSStringCreateWithUTF8CString ("value");
- prop_value_str = JSStringCreateWithUTF8CString (keyring_data->user);
- prop_value = JSValueMakeString (js_context, prop_value_str);
- JSObjectSetProperty (js_context, username_element, prop_name, prop_value, 0, NULL);
-
- JSStringRelease (prop_value_str);
-
- prop_value_str = JSStringCreateWithUTF8CString (keyring_data->password);
- prop_value = JSValueMakeString (js_context, prop_value_str);
- JSObjectSetProperty (js_context, password_element, prop_name, prop_value, 0, NULL);
-
- JSStringRelease (prop_name);
- JSStringRelease (prop_value_str);
+ g_object_set (fill_data->username_node,
+ "value", keyring_data->user, NULL);
+ g_object_set (fill_data->password_node,
+ "value", keyring_data->password, NULL);
}
static void
-find_username_and_password_elements (JSContextRef js_context,
- GSList *elements,
- JSObjectRef *name_element,
- JSObjectRef *password_element)
+find_username_and_password_elements (WebKitDOMNode *form_node,
+ WebKitDOMNode **username_node,
+ WebKitDOMNode **password_node)
{
- GSList *iter = elements;
+ WebKitDOMHTMLCollection *elements;
+ WebKitDOMHTMLFormElement *form = WEBKIT_DOM_HTML_FORM_ELEMENT (form_node);
+ gulong elements_n;
+ int j;
- for (; iter; iter = iter->next) {
- JSObjectRef js_object;
- char *type;
+ elements = webkit_dom_html_form_element_get_elements (form);
+ elements_n = webkit_dom_html_collection_get_length (elements);
- js_object = JSValueToObject (js_context, (JSValueRef)iter->data, NULL);
+ if (elements_n == 0) {
+ LOG ("No elements found for this form.");
+ return;
+ }
- type = js_get_element_property (js_context, js_object, "type");
+ for (j = 0; j < elements_n; j++) {
+ WebKitDOMNode *element;
- if (!type)
- continue;
+ element = webkit_dom_html_collection_item (elements, j);
+
+ if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (element)) {
+ char *element_type;
+
+ g_object_get (element, "type", &element_type, NULL);
+
+ if (g_str_equal ("text", element_type)) {
+ /* We found more than one inputs of type text; we won't be
+ * saving here */
+ if (*username_node) {
+ g_object_unref (*username_node);
+ *username_node = NULL;
+ g_free (element_type);
- if (g_str_equal (type, "text")) {
- /* We found more than one inputs of type text; we won't be
- * saving here */
- if (*name_element) {
- *name_element = NULL;
- break;
+ break;
+ }
+
+ *username_node = g_object_ref (element);
}
+ else if (g_str_equal ("password", element_type)) {
+ if (*password_node) {
+ g_object_unref (*password_node);
+ *password_node = NULL;
+ g_free (element_type);
+
+ break;
+ }
- *name_element = js_object;
- } else if (g_str_equal (type, "password")) {
- if (*password_element) {
- *password_element = NULL;
- break;
+ *password_node = g_object_ref (element);
}
- *password_element = js_object;
+ g_free (element_type);
}
-
- g_free (type);
}
}
@@ -1011,143 +939,88 @@ should_store_cb (GnomeKeyringResult retval,
request_decision_on_storing (store_data);
}
-static JSValueRef
-form_submitted_cb (JSContextRef js_context,
- JSObjectRef js_function,
- JSObjectRef js_this,
- size_t argument_count,
- const JSValueRef js_arguments[],
- JSValueRef* js_exception)
-{
- GSList *elements = js_get_form_elements (js_context, js_this);
- JSObjectRef js_global = JSContextGetGlobalObject (js_context);
- JSObjectRef name_element = NULL;
- JSObjectRef password_element = NULL;
- JSObjectRef dummy_object;
- JSStringRef js_string;
- JSValueRef js_value;
- StorePasswordData *store_data;
- char *name_field_name = NULL;
- char *name_field_value = NULL;
- char *password_field_name = NULL;
- char *password_field_value = NULL;
+static gboolean
+form_submitted_cb (WebKitDOMHTMLFormElement *dom_form,
+ WebKitDOMEvent *dom_event,
+ EphyWebView *web_view)
+{
SoupURI *uri;
- WebKitWebView *web_view;
-
- LOG ("Form submitted!");
-
- find_username_and_password_elements (js_context, elements, &name_element, &password_element);
- g_slist_free (elements);
-
- if (!name_element || !password_element)
- return JSValueMakeUndefined (js_context);
-
- name_field_name = js_get_element_attribute (js_context, name_element, "name");
- password_field_name = js_get_element_attribute (js_context, password_element, "name");
- if (!name_field_name || !password_field_name)
- goto form_submitted_cb_finish;
-
- js_string = JSStringCreateWithUTF8CString ("value");
- js_value = JSObjectGetProperty (js_context, name_element, js_string, NULL);
-
- name_field_value = js_value_to_string (js_context, js_value);
-
- js_value = JSObjectGetProperty (js_context, password_element, js_string, NULL);
- JSStringRelease (js_string);
-
- password_field_value = js_value_to_string (js_context, js_value);
-
- if (!name_field_value || !password_field_value)
- goto form_submitted_cb_finish;
-
- if (g_str_equal (name_field_value, "") ||
- g_str_equal (password_field_value, ""))
- goto form_submitted_cb_finish;
+ StorePasswordData *store_data;
- dummy_object = js_object_get_property_as_object (js_context,
- js_global,
- "_EpiphanyInternalDummy");
- web_view = JSObjectGetPrivate (dummy_object);
+ WebKitDOMNode *username_node = NULL;
+ WebKitDOMNode *password_node = NULL;
- uri = soup_uri_new (webkit_web_view_get_uri (web_view));
+ uri = soup_uri_new (webkit_web_view_get_uri (WEBKIT_WEB_VIEW (web_view)));
if (!uri)
- goto form_submitted_cb_finish;
+ return TRUE;
- // Ignore query string in the uri, if any
soup_uri_set_query (uri, NULL);
+ find_username_and_password_elements (WEBKIT_DOM_NODE (dom_form),
+ &username_node, &password_node);
+
store_data = g_slice_new (StorePasswordData);
store_data->uri = soup_uri_to_string (uri, FALSE);
- store_data->name_field = g_strdup (name_field_name);
- store_data->name_value = g_strdup (name_field_value);
- store_data->password_field = g_strdup (password_field_name);
- store_data->password_value = g_strdup (password_field_value);
store_data->embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (web_view);
- soup_uri_free (uri);
+ g_object_get (username_node,
+ "name", &store_data->name_field,
+ "value", &store_data->name_value, NULL);
+
+ g_object_get (password_node,
+ "name", &store_data->password_field,
+ "value", &store_data->password_value, NULL);
+
+ LOG ("Form submitted! %s %s",
+ store_data->name_value,
+ store_data->password_value);
_ephy_profile_query_form_auth_data (store_data->uri,
- name_field_name,
- password_field_name,
+ store_data->name_field,
+ store_data->password_field,
should_store_cb,
store_data,
NULL);
-form_submitted_cb_finish:
- g_free (name_field_name);
- g_free (password_field_name);
- g_free (name_field_value);
- g_free (password_field_value);
-
- return JSValueMakeUndefined (js_context);
-}
-
-static void
-hook_form (JSContextRef js_context, JSValueRef js_form, JSObjectRef js_form_submitted)
-{
- JSObjectRef object = JSValueToObject (js_context, js_form, NULL);
- JSObjectRef add_event_listener = js_object_get_property_as_object (js_context, object, "addEventListener");
- JSStringRef event_name;
- JSValueRef args[3], val;
- JSValueRef js_exception;
+ soup_uri_free (uri);
- event_name = JSStringCreateWithUTF8CString ("submit");
- args[0] = JSValueMakeString (js_context, event_name);
- JSStringRelease (event_name);
+ g_object_unref (username_node);
+ g_object_unref (password_node);
- args[1] = js_form_submitted;
- args[2] = JSValueMakeBoolean (js_context, TRUE);
- val = JSObjectCallAsFunction (js_context, add_event_listener, object, 3, args, &js_exception);
+ return TRUE;
}
static void
-pre_fill_form (JSContextRef js_context,
- JSObjectRef js_object,
- JSObjectRef username_element,
- JSObjectRef password_element,
+pre_fill_form (WebKitDOMNode *username_node,
+ WebKitDOMNode *password_node,
EphyWebView *view)
{
+ GSList *p = NULL;
GSList *l = NULL;
SoupURI *uri = NULL;
- GSList *p = NULL;
uri = soup_uri_new (webkit_web_view_get_uri (WEBKIT_WEB_VIEW (view)));
if (uri)
l = ephy_embed_single_get_form_auth (EPHY_EMBED_SINGLE (ephy_embed_shell_get_embed_single (embed_shell)), uri->host);
for (p = l; p; p = p->next) {
+ char *username_field_name;
+ char *password_field_name;
EphyEmbedSingleFormAuthData *data = (EphyEmbedSingleFormAuthData*)p->data;
- char *username_field_name = js_get_element_attribute (js_context, username_element, "name");
- char *password_field_name = js_get_element_attribute (js_context, password_element, "name");
+
+ g_object_get (username_node,
+ "name", &username_field_name, NULL);
+ g_object_get (password_node,
+ "name", &password_field_name, NULL);
+
if (g_strcmp0 (username_field_name, data->form_username) == 0 &&
g_strcmp0 (password_field_name, data->form_password) == 0) {
FillData *fill_data = g_slice_new (FillData);
char *uri_str = soup_uri_to_string (uri, FALSE);
- fill_data->context = js_context;
- fill_data->username_element = username_element;
- fill_data->password_element = password_element;
+ fill_data->username_node = g_object_ref (username_node);
+ fill_data->password_node = g_object_ref (password_node);
_ephy_profile_query_form_auth_data (uri_str,
data->form_username,
@@ -1165,84 +1038,43 @@ pre_fill_form (JSContextRef js_context,
}
static void
-do_hook_into_forms (JSContextRef js_context, JSObjectRef js_form_submitted, EphyWebView *web_view)
+_ephy_web_view_hook_into_forms (EphyWebView *web_view)
{
- GSList *forms = js_get_all_forms (js_context);
- JSClassDefinition dummy_class_def;
- JSClassRef dummy_class;
- JSObjectRef dummy_object;
- JSStringRef dummy_name;
- JSObjectRef js_global;
+ WebKitDOMHTMLCollection *forms = NULL;
+ WebKitDOMDocument *document = NULL;
+ gulong forms_n;
+ int i;
- if (!forms) {
+ document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (web_view));
+ forms = webkit_dom_document_get_forms (document);
+ forms_n = webkit_dom_html_collection_get_length (forms);
+
+ if (forms_n == 0) {
LOG ("No forms found.");
return;
}
- for (; forms; forms = forms->next) {
- JSValueRef form = (JSValueRef)forms->data;
- GSList *elements = js_get_form_elements (js_context, form);
- JSObjectRef name_element = NULL;
- JSObjectRef password_element = NULL;
-
- if (!elements) {
- LOG ("No elements found for this form.");
- continue;
- }
+ for (i = 0; i < forms_n; i++) {
+ WebKitDOMNode *form;
+ WebKitDOMNode *username_node = NULL;
+ WebKitDOMNode *password_node = NULL;
- find_username_and_password_elements (js_context, elements, &name_element, &password_element);
- g_slist_free (elements);
+ form = webkit_dom_html_collection_item (forms, i);
+ find_username_and_password_elements (form, &username_node, &password_node);
/* We have a field that may be the user, and one for a password. */
- if (name_element && password_element) {
- LOG ("Hooking into, and pre-filling form: %s / %s",
- js_get_element_attribute (js_context, name_element, "name"),
- js_get_element_attribute (js_context, password_element, "name"));
-
- hook_form (js_context, form, js_form_submitted);
- pre_fill_form (js_context, JSValueToObject (js_context, form, NULL),
- name_element, password_element, web_view);
- } else
- LOG ("NOT hooking into form: username element: %p / password element: %p", name_element, password_element);
- }
+ if (username_node && password_node) {
+ LOG ("Hooking and pre-filling a form");
+ g_signal_connect (form, "submit-event",
+ G_CALLBACK (form_submitted_cb), web_view);
- /* This is required because we can only hold private data on objects
- * created with our own classes; we need to store the WebView here
- * because it is needed for form_submitted_cb */
- dummy_class_def = kJSClassDefinitionEmpty;
- dummy_class_def.className = "dummy";
- dummy_class = JSClassCreate (&dummy_class_def);
- dummy_object = JSObjectMake (js_context, dummy_class, web_view);
- g_assert (JSObjectGetPrivate (dummy_object) != NULL);
-
- js_global = JSContextGetGlobalObject (js_context);
- dummy_name = JSStringCreateWithUTF8CString ("_EpiphanyInternalDummy");
- JSObjectSetProperty (js_context, js_global, dummy_name, dummy_object, 0, NULL);
- JSStringRelease (dummy_name);
+ pre_fill_form (username_node, password_node, web_view);
- g_slist_free (forms);
-}
-
-static void
-_ephy_web_view_hook_into_forms (EphyWebView *web_view)
-{
- WebKitWebFrame *web_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
- JSGlobalContextRef js_context;
- JSObjectRef js_global;
- JSStringRef js_function_name;
- JSObjectRef js_form_submitted;
-
- js_context = webkit_web_frame_get_global_context (web_frame);
- js_global = JSContextGetGlobalObject (js_context);
-
- js_function_name = JSStringCreateWithUTF8CString ("_EpiphanyInternalFormSubmitted");
- js_form_submitted = JSObjectMakeFunctionWithCallback (js_context,
- js_function_name,
- (JSObjectCallAsFunctionCallback)form_submitted_cb);
- JSObjectSetProperty (js_context, js_global, js_function_name, js_form_submitted, 0, NULL);
- JSStringRelease (js_function_name);
-
- do_hook_into_forms (js_context, js_form_submitted, EPHY_WEB_VIEW (web_view));
+ g_object_unref (username_node);
+ g_object_unref (password_node);
+ } else
+ LOG ("No pre-fillable/hookable form found");
+ }
}
static void