[Xfce4-commits] <midori:master> Implement extension de/activation via -e/ --execute

Christian Dywan noreply at xfce.org
Thu Mar 28 18:30:02 CET 2013


Updating branch refs/heads/master
         to af47fac15886d32352265b7e784d70f55f43fc45 (commit)
       from 3acf3d986bf8d463660d873349bbf0845943f961 (commit)

commit af47fac15886d32352265b7e784d70f55f43fc45
Author: Christian Dywan <christian at twotoasts.de>
Date:   Thu Mar 28 18:03:24 2013 +0100

    Implement extension de/activation via -e/ --execute

 midori/midori-app.c            |   21 ++++++++-
 midori/midori-app.h            |    3 +
 midori/midori-browser.c        |   94 ++++++++++++++++++++++++++++-----------
 midori/midori-extension.c      |   53 ++++++++++++----------
 midori/midori-locationaction.c |    8 ++--
 5 files changed, 123 insertions(+), 56 deletions(-)

diff --git a/midori/midori-app.c b/midori/midori-app.c
index 1dfd95a..04f0d71 100644
--- a/midori/midori-app.c
+++ b/midori/midori-app.c
@@ -788,7 +788,7 @@ midori_app_init (MidoriApp* app)
     app->search_engines = NULL;
     app->history = NULL;
     app->speeddial = NULL;
-    app->extensions = NULL;
+    app->extensions = katze_array_new (KATZE_TYPE_ARRAY);
     app->browsers = katze_array_new (MIDORI_TYPE_BROWSER);
 
     app->instance = MidoriAppInstanceNull;
@@ -930,6 +930,25 @@ midori_app_new (const gchar* name)
     return g_object_new (MIDORI_TYPE_APP, "name", name, NULL);
 }
 
+/**
+ * midori_app_new_proxy:
+ * @app: a #MidoriApp, or %NULL
+ *
+ * Instantiates a proxy #MidoriApp that can be passed to untrusted code
+ * or for sensitive use cases. Properties can be freely changed.
+ *
+ * Return value: a new #MidoriApp
+ *
+ * Since: 0.5.0
+ **/
+MidoriApp*
+midori_app_new_proxy (MidoriApp* app)
+{
+    g_return_val_if_fail (MIDORI_IS_APP (app) || !app, NULL);
+
+    return midori_app_new (NULL);
+}
+
 static gboolean instance_is_not_running = FALSE;
 static gboolean instance_is_running = FALSE;
 
diff --git a/midori/midori-app.h b/midori/midori-app.h
index 8ec9f4b..64cd278 100644
--- a/midori/midori-app.h
+++ b/midori/midori-app.h
@@ -41,6 +41,9 @@ midori_app_get_type               (void) G_GNUC_CONST;
 MidoriApp*
 midori_app_new                    (const gchar*       name);
 
+MidoriApp*
+midori_app_new_proxy              (MidoriApp*         app);
+
 const gchar*
 midori_app_get_name               (MidoriApp*         app);
 
diff --git a/midori/midori-browser.c b/midori/midori-browser.c
index 60fdbb5..7ea2b57 100644
--- a/midori/midori-browser.c
+++ b/midori/midori-browser.c
@@ -14,6 +14,7 @@
 #include "midori-browser.h"
 
 #include "midori-app.h"
+#include "midori-extension.h"
 #include "midori-array.h"
 #include "midori-view.h"
 #include "midori-preferences.h"
@@ -532,7 +533,7 @@ midori_browser_update_history_title (MidoriBrowser* browser,
 /**
  * midori_browser_assert_action:
  * @browser: a #MidoriBrowser
- * @name: name of the action or setting=value expression
+ * @name: action, setting=value expression or extension=true|false
  *
  * Assert that @name is a valid action or setting expression,
  * if it fails the program will terminate with an error.
@@ -552,14 +553,25 @@ midori_browser_assert_action (MidoriBrowser* browser,
         gchar** parts = g_strsplit (name, "=", 0);
         GObjectClass* class = G_OBJECT_GET_CLASS (browser->settings);
         GParamSpec* pspec = g_object_class_find_property (class, parts[0]);
-        GType type = pspec ? G_PARAM_SPEC_TYPE (pspec) : G_TYPE_INVALID;
-        if (!(
-            (type == G_TYPE_PARAM_BOOLEAN && (!strcmp (parts[1], "true") || !strcmp (parts[1], "false")))
-         || type == G_TYPE_PARAM_STRING
-         || type == G_TYPE_PARAM_INT
-         || type == G_TYPE_PARAM_FLOAT
-         || type == G_TYPE_PARAM_ENUM))
-            midori_error (_("Value '%s' is invalid for %s"), parts[1], parts[0]);
+        if (pspec != NULL)
+        {
+            GType type = G_PARAM_SPEC_TYPE (pspec);
+            if (!(
+                (type == G_TYPE_PARAM_BOOLEAN && (!strcmp (parts[1], "true") || !strcmp (parts[1], "false")))
+             || type == G_TYPE_PARAM_STRING
+             || type == G_TYPE_PARAM_INT
+             || type == G_TYPE_PARAM_FLOAT
+             || type == G_TYPE_PARAM_ENUM))
+                midori_error (_("Value '%s' is invalid for %s"), parts[1], parts[0]);
+        }
+        else
+        {
+            gchar* extension_path = midori_paths_get_lib_path (PACKAGE_NAME);
+            GObject* extension = midori_extension_load_from_file (extension_path, parts[0], FALSE, FALSE);
+            g_free (extension_path);
+            if (!extension || (strcmp (parts[1], "true") && strcmp (parts[1], "false")))
+                midori_error (_("Unexpected setting '%s'"), name);
+        }
         g_strfreev (parts);
     }
     else
@@ -570,6 +582,11 @@ midori_browser_assert_action (MidoriBrowser* browser,
     }
 }
 
+void
+midori_app_set_browsers (MidoriApp*     app,
+                         KatzeArray*    browsers,
+                         MidoriBrowser* browser);
+
 static void
 _midori_browser_activate_action (MidoriBrowser* browser,
                                  const gchar*   name)
@@ -581,28 +598,51 @@ _midori_browser_activate_action (MidoriBrowser* browser,
         gchar** parts = g_strsplit (name, "=", 0);
         GObjectClass* class = G_OBJECT_GET_CLASS (browser->settings);
         GParamSpec* pspec = g_object_class_find_property (class, parts[0]);
-        GType type = pspec ? G_PARAM_SPEC_TYPE (pspec) : G_TYPE_INVALID;
-        if (type == G_TYPE_PARAM_BOOLEAN && !strcmp ("true", parts[1]))
-            g_object_set (browser->settings, parts[0], TRUE, NULL);
-        else if (type == G_TYPE_PARAM_BOOLEAN && !strcmp ("false", parts[1]))
-            g_object_set (browser->settings, parts[0], FALSE, NULL);
-        else if (type == G_TYPE_PARAM_STRING)
-            g_object_set (browser->settings, parts[0], parts[1], NULL);
-        else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT)
-            g_object_set (browser->settings, parts[0], atoi (parts[1]), NULL);
-        else if (type == G_TYPE_PARAM_FLOAT)
-            g_object_set (browser->settings, parts[0], g_ascii_strtod (parts[1], NULL), NULL);
-        else if (type == G_TYPE_PARAM_ENUM)
+        if (pspec != NULL)
         {
-            GEnumClass* enum_class = G_ENUM_CLASS (g_type_class_peek (pspec->value_type));
-            GEnumValue* enum_value = g_enum_get_value_by_name (enum_class, parts[1]);
-            if (enum_value != NULL)
-                g_object_set (browser->settings, parts[0], enum_value->value, NULL);
+            GType type = G_PARAM_SPEC_TYPE (pspec);
+            if (type == G_TYPE_PARAM_BOOLEAN && !strcmp ("true", parts[1]))
+                g_object_set (browser->settings, parts[0], TRUE, NULL);
+            else if (type == G_TYPE_PARAM_BOOLEAN && !strcmp ("false", parts[1]))
+                g_object_set (browser->settings, parts[0], FALSE, NULL);
+            else if (type == G_TYPE_PARAM_STRING)
+                g_object_set (browser->settings, parts[0], parts[1], NULL);
+            else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT)
+                g_object_set (browser->settings, parts[0], atoi (parts[1]), NULL);
+            else if (type == G_TYPE_PARAM_FLOAT)
+                g_object_set (browser->settings, parts[0], g_ascii_strtod (parts[1], NULL), NULL);
+            else if (type == G_TYPE_PARAM_ENUM)
+            {
+                GEnumClass* enum_class = G_ENUM_CLASS (g_type_class_peek (pspec->value_type));
+                GEnumValue* enum_value = g_enum_get_value_by_name (enum_class, parts[1]);
+                if (enum_value != NULL)
+                    g_object_set (browser->settings, parts[0], enum_value->value, NULL);
+                else
+                    g_warning (_("Value '%s' is invalid for %s"), parts[1], parts[0]);
+            }
             else
                 g_warning (_("Value '%s' is invalid for %s"), parts[1], parts[0]);
         }
         else
-            g_warning (_("Value '%s' is invalid for %s"), parts[1], parts[0]);
+        {
+            gchar* extension_path = midori_paths_get_lib_path (PACKAGE_NAME);
+            GObject* extension = midori_extension_load_from_file (extension_path, parts[0], TRUE, FALSE);
+            MidoriApp* app = midori_app_new_proxy (NULL);
+            g_object_set (app,
+                "settings", browser->settings,
+                NULL);
+            /* FIXME: tabs of multiple windows */
+            KatzeArray* browsers = katze_array_new (MIDORI_TYPE_BROWSER);
+            katze_array_add_item (browsers, browser);
+            midori_app_set_browsers (app, browsers, browser);
+            g_free (extension_path);
+            if (extension && !strcmp (parts[1], "true"))
+                midori_extension_activate (extension, NULL, TRUE, app);
+            else if (extension && !strcmp (parts[1], "false"))
+                midori_extension_deactivate (MIDORI_EXTENSION (extension));
+            else
+                g_warning (_("Unexpected setting '%s'"), name);
+        }
         g_strfreev (parts);
     }
     else
@@ -7422,7 +7462,7 @@ midori_browser_add_uri (MidoriBrowser* browser,
 /**
  * midori_browser_activate_action:
  * @browser: a #MidoriBrowser
- * @name: name of the action or setting=value expression
+ * @name: action, setting=value expression or extension=true|false
  *
  * Activates the specified action. See also midori_browser_assert_action().
  **/
diff --git a/midori/midori-extension.c b/midori/midori-extension.c
index cdda21b..afab7ea 100644
--- a/midori/midori-extension.c
+++ b/midori/midori-extension.c
@@ -580,6 +580,10 @@ midori_extension_load_from_file (const gchar* extension_path,
     typedef GObject* (*extension_init_func)(void);
     extension_init_func extension_init;
     static GHashTable* modules = NULL;
+    GObject* extension;
+
+    g_return_val_if_fail (extension_path != NULL, NULL);
+    g_return_val_if_fail (filename != NULL, NULL);
 
     /* Ignore files which don't have the correct suffix */
     if (!g_str_has_suffix (filename, G_MODULE_SUFFIX))
@@ -600,24 +604,24 @@ midori_extension_load_from_file (const gchar* extension_path,
     /* GModule detects repeated loading but exposes no API to check it.
        Skip any modules that were loaded before. */
     if (modules == NULL)
-        modules = g_hash_table_new (g_direct_hash, g_direct_equal);
-    if (g_hash_table_lookup (modules, module))
-        return NULL;
-
-    g_hash_table_insert (modules, module, g_strdup (filename));
+        modules = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref);
+    if ((extension = g_hash_table_lookup (modules, module)))
+        return extension;
 
     if (module && g_module_symbol (module, "extension_init",
                                    (gpointer) &extension_init))
     {
         typedef void (*extension_test_func)(void);
         extension_test_func extension_test;
-        GObject* extension = extension_init ();
-        if (test && extension && g_module_symbol (module, "extension_test", (gpointer) &extension_test))
-            extension_test ();
-        return extension;
+        if ((extension = extension_init ()))
+        {
+            if (test && g_module_symbol (module, "extension_test", (gpointer) &extension_test))
+                extension_test ();
+            g_hash_table_insert (modules, module, extension);
+        }
     }
 
-    return NULL;
+    return extension;
 }
 
 void
@@ -639,18 +643,24 @@ midori_extension_activate_gracefully (MidoriApp*   app,
         g_warning ("%s", g_module_error ());
         katze_array_add_item (extensions, extension);
         g_object_unref (extensions);
-    }
-
-    if (extension != NULL)
         g_object_unref (extension);
+    }
 }
 
 static void
-midori_load_extension (MidoriApp*       app,
-                       MidoriExtension* extension,
-                       const gchar*     filename)
+midori_extension_add_to_list (MidoriApp*       app,
+                              MidoriExtension* extension,
+                              const gchar*     filename)
 {
+    if (filename == NULL)
+        return;
+
+    g_return_if_fail (MIDORI_IS_APP (app));
     KatzeArray* extensions = katze_object_get_object (app, "extensions");
+    g_return_if_fail (KATZE_IS_ARRAY (extensions));
+    if (g_object_get_data (G_OBJECT (extension), "filename"))
+        return;
+
     /* Signal that we want the extension to load and save */
     g_object_set_data_full (G_OBJECT (extension), "filename",
                             g_strdup (filename), g_free);
@@ -668,8 +678,7 @@ midori_extension_activate (GObject*     extension,
 {
     if (MIDORI_IS_EXTENSION (extension))
     {
-        if (filename != NULL)
-            midori_load_extension (app, MIDORI_EXTENSION (extension), filename);
+        midori_extension_add_to_list (app, MIDORI_EXTENSION (extension), filename);
         if (activate)
             g_signal_emit_by_name (extension, "activate", app);
     }
@@ -679,16 +688,12 @@ midori_extension_activate (GObject*     extension,
         KATZE_ARRAY_FOREACH_ITEM (extension_item, KATZE_ARRAY (extension))
             if (MIDORI_IS_EXTENSION (extension_item))
             {
-                gchar* key;
-
-                if (filename != NULL)
-                    midori_load_extension (app, extension_item, filename);
+                midori_extension_add_to_list (app, extension_item, filename);
                 if (activate)
                 {
-                    key = katze_object_get_string (extension_item, "key");
+                    gchar* key = extension_item->priv->key;
                     if (key && filename && strstr (filename, key))
                         g_signal_emit_by_name (extension_item, "activate", app);
-                    g_free (key);
                 }
             }
     }
diff --git a/midori/midori-locationaction.c b/midori/midori-locationaction.c
index a9feb98..e3af218 100644
--- a/midori/midori-locationaction.c
+++ b/midori/midori-locationaction.c
@@ -654,17 +654,17 @@ midori_location_action_popup_timeout_cb (gpointer data)
 
     if (action->autocompleter == NULL)
     {
-        /* We use a proxy app to control what can be accessed */
+        MidoriApp* app = midori_app_new_proxy (NULL);
         MidoriBrowser* browser = midori_browser_get_for_widget (action->entry);
-        GObject* app = g_object_new (MIDORI_TYPE_APP,
+        g_object_set (app,
             "history", action->history,
             "search-engines", action->search_engines,
             NULL);
         /* FIXME: tabs of multiple windows */
         KatzeArray* browsers = katze_array_new (MIDORI_TYPE_BROWSER);
         katze_array_add_item (browsers, browser);
-        midori_app_set_browsers (MIDORI_APP (app), browsers, browser);
-        action->autocompleter = midori_autocompleter_new (app);
+        midori_app_set_browsers (app, browsers, browser);
+        action->autocompleter = midori_autocompleter_new (G_OBJECT (app));
         g_signal_connect (action->autocompleter, "populated",
             G_CALLBACK (midori_location_action_populated_suggestions_cb), action);
         g_object_unref (app);


More information about the Xfce4-commits mailing list