/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* * Copyright © 2015 Damián Nohales * Copyright © 2015 – 2017 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, see . */ #include "config.h" #include #include "goaoauthprovider.h" #include "goaoauth2provider.h" #include "goaoauth2provider-web-extension.h" #include "goaprovider.h" #include "goawebextension.h" struct _GoaWebExtension { GObject parent; GoaProvider *provider; WebKitWebExtension *wk_extension; gchar *existing_identity; gchar *provider_type; }; struct _GoaWebExtensionClass { GObjectClass parent; }; enum { PROP_0, PROP_EXISTING_IDENTITY, PROP_PROVIDER_TYPE, PROP_WK_EXTENSION }; G_DEFINE_TYPE (GoaWebExtension, goa_web_extension, G_TYPE_OBJECT) static void web_extension_dom_node_deny_click_cb (WebKitDOMNode *element, WebKitDOMEvent *event, gpointer user_data) { WebKitDOMDOMWindow *dom_window = WEBKIT_DOM_DOM_WINDOW (user_data); webkit_dom_dom_window_webkit_message_handlers_post_message (dom_window, "deny-click", ""); } static void web_extension_dom_node_password_submit_cb (WebKitDOMNode *element, WebKitDOMEvent *event, gpointer user_data) { WebKitDOMDOMWindow *dom_window = WEBKIT_DOM_DOM_WINDOW (user_data); WebKitDOMHTMLInputElement *password_node; gchar *password; password_node = WEBKIT_DOM_HTML_INPUT_ELEMENT (g_object_get_data (G_OBJECT (dom_window), "goa-password-node")); password = webkit_dom_html_input_element_get_value (password_node); webkit_dom_dom_window_webkit_message_handlers_post_message (dom_window, "password-submit", password); g_free (password); } static void web_extension_document_loaded_cb (WebKitWebPage *web_page, gpointer user_data) { GoaWebExtension *self = GOA_WEB_EXTENSION (user_data); WebKitDOMDocument *document; WebKitDOMDOMWindow *dom_window; WebKitDOMHTMLCollection *elements = NULL; gulong element_count; gulong i; document = webkit_web_page_get_dom_document (web_page); elements = webkit_dom_document_get_elements_by_tag_name_as_html_collection (document, "*"); element_count = webkit_dom_html_collection_get_length (elements); dom_window = webkit_dom_document_get_default_view (document); for (i = 0; i < element_count; i++) { WebKitDOMNode *element = webkit_dom_html_collection_item (elements, i); if ((GOA_IS_OAUTH_PROVIDER (self->provider) && goa_oauth_provider_is_deny_node (GOA_OAUTH_PROVIDER (self->provider), element)) || (GOA_IS_OAUTH2_PROVIDER (self->provider) && goa_oauth2_provider_is_deny_node (GOA_OAUTH2_PROVIDER (self->provider), element))) { webkit_dom_event_target_add_event_listener (WEBKIT_DOM_EVENT_TARGET (element), "click", G_CALLBACK (web_extension_dom_node_deny_click_cb), FALSE, dom_window); } else if (self->existing_identity != NULL && self->existing_identity[0] != '\0' && WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (element) && ((GOA_IS_OAUTH_PROVIDER (self->provider) && goa_oauth_provider_is_identity_node (GOA_OAUTH_PROVIDER (self->provider), WEBKIT_DOM_HTML_INPUT_ELEMENT (element))) || (GOA_IS_OAUTH2_PROVIDER (self->provider) && goa_oauth2_provider_is_identity_node (GOA_OAUTH2_PROVIDER (self->provider), WEBKIT_DOM_HTML_INPUT_ELEMENT (element))))) { webkit_dom_html_input_element_set_value (WEBKIT_DOM_HTML_INPUT_ELEMENT (element), self->existing_identity); webkit_dom_html_input_element_set_read_only (WEBKIT_DOM_HTML_INPUT_ELEMENT (element), TRUE); } else if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (element) && ((GOA_IS_OAUTH_PROVIDER (self->provider) && goa_oauth_provider_is_password_node (GOA_OAUTH_PROVIDER (self->provider), WEBKIT_DOM_HTML_INPUT_ELEMENT (element))) || (GOA_IS_OAUTH2_PROVIDER (self->provider) && goa_oauth2_provider_is_password_node (GOA_OAUTH2_PROVIDER (self->provider), WEBKIT_DOM_HTML_INPUT_ELEMENT (element))))) { WebKitDOMHTMLFormElement *form; form = webkit_dom_html_input_element_get_form (WEBKIT_DOM_HTML_INPUT_ELEMENT (element)); if (form != NULL) { g_object_set_data_full (G_OBJECT (dom_window), "goa-password-node", g_object_ref (element), g_object_unref); webkit_dom_event_target_add_event_listener (WEBKIT_DOM_EVENT_TARGET (form), "submit", G_CALLBACK (web_extension_dom_node_password_submit_cb), FALSE, dom_window); } } } g_clear_object (&elements); } static void web_extension_page_created_cb (GoaWebExtension *self, WebKitWebPage *web_page) { g_signal_connect_object (web_page, "document-loaded", G_CALLBACK (web_extension_document_loaded_cb), self, 0); } static void goa_web_extension_constructed (GObject *object) { GoaWebExtension *self = GOA_WEB_EXTENSION (object); G_OBJECT_CLASS (goa_web_extension_parent_class)->constructed (object); self->provider = goa_provider_get_for_provider_type (self->provider_type); g_signal_connect_object (self->wk_extension, "page-created", G_CALLBACK (web_extension_page_created_cb), self, G_CONNECT_SWAPPED); } static void goa_web_extension_dispose (GObject *object) { GoaWebExtension *self = GOA_WEB_EXTENSION (object); g_clear_object (&self->provider); g_clear_object (&self->wk_extension); G_OBJECT_CLASS (goa_web_extension_parent_class)->dispose (object); } static void goa_web_extension_finalize (GObject *object) { GoaWebExtension *self = GOA_WEB_EXTENSION (object); g_free (self->existing_identity); g_free (self->provider_type); G_OBJECT_CLASS (goa_web_extension_parent_class)->finalize (object); } static void goa_web_extension_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { GoaWebExtension *self = GOA_WEB_EXTENSION (object); switch (prop_id) { case PROP_EXISTING_IDENTITY: self->existing_identity = g_value_dup_string (value); break; case PROP_PROVIDER_TYPE: self->provider_type = g_value_dup_string (value); break; case PROP_WK_EXTENSION: self->wk_extension = WEBKIT_WEB_EXTENSION (g_value_dup_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void goa_web_extension_class_init (GoaWebExtensionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = goa_web_extension_constructed; object_class->dispose = goa_web_extension_dispose; object_class->finalize = goa_web_extension_finalize; object_class->set_property = goa_web_extension_set_property; g_object_class_install_property (object_class, PROP_EXISTING_IDENTITY, g_param_spec_string ("existing-identity", "A GoaAccount identity", "The user name with which we want to prefill the form", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PROVIDER_TYPE, g_param_spec_string ("provider-type", "A GoaProvider type", "The provider type that is represented by this view", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_WK_EXTENSION, g_param_spec_object ("wk-extension", "A WebKitWebExtension", "The associated WebKitWebExtension", WEBKIT_TYPE_WEB_EXTENSION, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } static void goa_web_extension_init (GoaWebExtension *self) { } GoaWebExtension * goa_web_extension_new (WebKitWebExtension *wk_extension, const gchar *provider_type, const gchar *existing_identity) { return g_object_new (GOA_TYPE_WEB_EXTENSION, "existing-identity", existing_identity, "provider-type", provider_type, "wk-extension", wk_extension, NULL); }