]> spindle.queued.net Git - midori/commitdiff
Use midori_view_get_web_view in extensions
authorArno Renevier <arno@renevier.net>
Tue, 30 Mar 2010 20:44:04 +0000 (22:44 +0200)
committerChristian Dywan <christian@twotoasts.de>
Tue, 30 Mar 2010 22:18:42 +0000 (00:18 +0200)
extensions/adblock.c
extensions/formhistory.c
extensions/javascript.c [new file with mode: 0644]
extensions/mouse-gestures.c
extensions/tab-switcher.c

index 5d9847e26194ef0779bdfb294c82f68f251c0bcc..6112a946041ca381526f4f4fa4a9dc045b60b0a9 100644 (file)
@@ -935,7 +935,7 @@ adblock_add_tab_cb (MidoriBrowser*   browser,
                     MidoriView*      view,
                     MidoriExtension* extension)
 {
-    GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
+    GtkWidget* web_view = midori_view_get_web_view (view);
     #if HAVE_WEBKIT_RESOURCE_REQUEST
     GtkWidget* image = g_object_get_data (G_OBJECT (browser), "status-image");
     #endif
@@ -1282,7 +1282,7 @@ adblock_deactivate_tabs (MidoriView*      view,
                          MidoriBrowser*   browser,
                          MidoriExtension* extension)
 {
-    GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
+    GtkWidget* web_view = midori_view_get_web_view (view);
     #if HAVE_WEBKIT_RESOURCE_REQUEST
     GtkWidget* image = g_object_get_data (G_OBJECT (browser), "status-image");
     #endif
index 9b33300e32d68cbcfa1357234870955301527c30..f0790af855c15359690a2e479983e883604f3cd4 100644 (file)
@@ -306,7 +306,7 @@ formhistory_add_tab_cb (MidoriBrowser*   browser,
                         MidoriView*      view,
                         MidoriExtension* extension)
 {
-    GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
+    GtkWidget* web_view = midori_view_get_web_view (view);
     g_signal_connect (web_view, "window-object-cleared",
             G_CALLBACK (formhistory_window_object_cleared_cb), NULL);
     #if WEBKIT_CHECK_VERSION (1, 1, 4)
@@ -348,7 +348,7 @@ formhistory_deactivate_tabs (MidoriView*      view,
                              MidoriBrowser*   browser,
                              MidoriExtension* extension)
 {
-    GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
+    GtkWidget* web_view = midori_view_get_web_view (view);
     g_signal_handlers_disconnect_by_func (
        web_view, formhistory_window_object_cleared_cb, NULL);
     #if WEBKIT_CHECK_VERSION (1, 1, 4)
diff --git a/extensions/javascript.c b/extensions/javascript.c
new file mode 100644 (file)
index 0000000..2b41756
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
+
+ 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.1 of the License, or (at your option) any later version.
+
+ See the file COPYING for the full license text.
+*/
+
+/*
+midori.tabs
+midori.windows
+midori.currentWindow
+midori.createAction({name:'Example',label:'_Example',icon:'gtk-info',tooltip:'Examples',activate:function()})
+action = midori.currentWindow.getAction(name)
+foreach (window as midori.windows) window.getAction('myaction').activate()
+midori.window[i].tabs
+midori.addWindow
+midori.addTab
+midori.removeWindow
+midori.removeTab
+*/
+
+#if HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <midori/midori.h>
+#include <midori/sokoke.h>
+#include <JavaScriptCore/JavaScript.h>
+
+gchar*
+sokoke_js_string_utf8 (JSStringRef js_string)
+{
+    size_t size_utf8;
+    gchar* string_utf8;
+
+    g_return_val_if_fail (js_string, NULL);
+
+    size_utf8 = JSStringGetMaximumUTF8CStringSize (js_string);
+    string_utf8 = g_new (gchar, size_utf8);
+    JSStringGetUTF8CString (js_string, string_utf8, size_utf8);
+    return string_utf8;
+}
+
+static void
+javascript_deactivate_cb (MidoriExtension* extension,
+                          MidoriBrowser*   browser)
+{
+    /* FIXME: Unload all javascript extensions */
+}
+
+static JSValueRef
+midori_javascript_midori_action_cb (JSContextRef     js_context,
+                                    JSObjectRef      js_function,
+                                    JSObjectRef      js_this,
+                                    size_t           n_arguments,
+                                    const JSValueRef js_arguments[],
+                                    JSValueRef*      js_exception)
+{
+    GtkAction* action;
+    JSObjectRef js_meta;
+    JSPropertyNameArrayRef js_properties;
+    size_t n_properties;
+    guint i;
+    MidoriApp* app;
+
+    if (n_arguments != 1)
+    {
+        *js_exception = JSValueMakeString (js_context,
+                                           JSStringCreateWithUTF8CString (
+            "MidoriError: Wrong number of arguments; 'midori.createAction ({property:value, ...})'"));
+        return JSValueMakeNull (js_context);
+    }
+
+    if (!JSValueIsObject (js_context, js_arguments[0]))
+    {
+        *js_exception = JSValueMakeString (js_context,
+                                           JSStringCreateWithUTF8CString (
+            "MidoriError: Argument is not an object; 'midori.createAction ({property:value, ...})'"));
+        return JSValueMakeNull (js_context);
+    }
+
+    action = g_object_new (GTK_TYPE_ACTION, NULL);
+    js_meta = JSValueToObject (js_context, js_arguments[0], NULL);
+    js_properties = JSObjectCopyPropertyNames (js_context, js_meta);
+    n_properties = JSPropertyNameArrayGetCount (js_properties);
+    for (i = 0; i < n_properties; i++)
+    {
+        JSStringRef js_name;
+        gchar* name;
+        JSValueRef js_property;
+        JSStringRef js_string;
+        gchar* string;
+
+        js_name = JSPropertyNameArrayGetNameAtIndex (js_properties, i);
+        name = sokoke_js_string_utf8 (js_name);
+        if (g_str_equal (name, "label"))
+        {
+            js_property = JSObjectGetProperty (js_context, js_meta, js_name, NULL);
+            js_string = JSValueToStringCopy (js_context, js_property, NULL);
+            string = sokoke_js_string_utf8 (js_string);
+            JSStringRelease (js_string);
+            g_object_set (action, "label", string, NULL);
+            g_free (string);
+        }
+        else if (g_str_equal (name, "icon"))
+        {
+            js_property = JSObjectGetProperty (js_context, js_meta, js_name, NULL);
+            js_string = JSValueToStringCopy (js_context, js_property, NULL);
+            string = sokoke_js_string_utf8 (js_string);
+            JSStringRelease (js_string);
+            /* FIXME: stock-id, or icon-name, or URI */
+            g_object_set (action, "stock-id", string, NULL);
+            g_free (string);
+        }
+        else if (g_str_equal (name, "tooltip"))
+        {
+            js_property = JSObjectGetProperty (js_context, js_meta, js_name, NULL);
+            js_string = JSValueToStringCopy (js_context, js_property, NULL);
+            string = sokoke_js_string_utf8 (js_string);
+            JSStringRelease (js_string);
+            g_object_set (action, "tooltip", string, NULL);
+            g_free (string);
+        }
+        else if (g_str_equal (name, "activate"))
+        {
+            /* FIXME */
+        }
+        else
+        {
+            *js_exception = JSValueMakeString (js_context,
+                                               JSStringCreateWithUTF8CString (
+                "MidoriError: Unknown property; 'midori.createAction ({property:value, ...})'"));
+            return JSValueMakeNull (js_context);
+        }
+    }
+
+    if ((app = JSObjectGetPrivate (js_this)))
+    {
+        /* TODO: Offer the user to add a toolbar button */
+    }
+    /* TODO: add action to all existing and future browsers */
+    /* gtk_action_connect_accelerator */
+    return JSValueMakeNull (js_context);
+}
+
+static JSContextRef
+midori_javascript_context (MidoriApp* app)
+{
+    JSContextRef js_context = JSGlobalContextCreateInGroup (NULL, NULL);
+    JSClassDefinition js_class_def = kJSClassDefinitionEmpty;
+    JSClassRef js_class;
+    JSObjectRef js_object;
+    JSStringRef js_name;
+    JSStaticFunction functions[] = {
+        { "createAction", midori_javascript_midori_action_cb, kJSPropertyAttributeNone },
+        { NULL, NULL, 0 }
+    };
+
+    js_class_def.className = "midori";
+    js_class_def.staticFunctions = functions;
+    js_class = JSClassCreate (&js_class_def);
+    js_object = JSObjectMake (js_context, js_class, app);
+
+    js_name = JSStringCreateWithUTF8CString ("midori");
+    JSObjectSetProperty (js_context, JSContextGetGlobalObject (js_context),
+                         js_name, js_object, kJSPropertyAttributeNone, NULL);
+    JSStringRelease (js_name);
+
+    return js_context;
+}
+
+static void
+midori_javascript_extension_activate_cb (MidoriExtension* extension,
+                                         MidoriApp*       app)
+{
+    gchar* filename = g_object_get_data (G_OBJECT (extension), "filename");
+    gchar* fullname = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
+        PACKAGE_NAME, "extensions", filename, NULL);
+    gchar* script;
+    GError* error = NULL;
+    if (g_file_get_contents (fullname, &script, NULL, &error))
+    {
+        JSContextRef js_context = midori_javascript_context (app);
+        gchar* exception = NULL;
+        g_free (sokoke_js_script_eval (js_context, script, &exception));
+        if (exception)
+        {
+            g_object_set (extension, "description",
+                          exception, "version", NULL, NULL);
+            g_warning ("%s", exception);
+            g_free (exception);
+        }
+    }
+    else
+    {
+        g_object_set (extension, "description",
+                      error->message, "version", NULL, NULL);
+        g_warning ("%s", error->message);
+        g_error_free (error);
+    }
+    g_free (fullname);
+    g_free (script);
+}
+
+static void
+javascript_load_extensions (gchar**      active,
+                            MidoriApp*   app,
+                            const gchar* path)
+{
+    GDir* dir;
+
+    /* TODO: Monitor folder for new files or modifications at runtime */
+    if ((dir = g_dir_open (path, 0, NULL)))
+    {
+        KatzeArray* extensions = katze_object_get_object (app, "extensions");
+        JSContextRef js_context = midori_javascript_context (app);
+        const gchar* filename;
+
+        while ((filename = g_dir_read_name (dir)))
+        {
+            gchar* fullname;
+            GError* error;
+            gchar* script;
+            MidoriExtension* extension;
+
+            /* Ignore files which don't have the correct suffix */
+            if (!g_str_has_suffix (filename, ".js"))
+                continue;
+
+            fullname = g_build_filename (path, filename, NULL);
+            error = NULL;
+            extension = g_object_new (MIDORI_TYPE_EXTENSION, "name", filename, NULL);
+            if (g_file_get_contents (fullname, &script, NULL, &error))
+            {
+                JSStringRef js_script;
+                JSValueRef js_exception;
+
+                js_script = JSStringCreateWithUTF8CString (script);
+                if (JSCheckScriptSyntax (js_context, js_script, NULL,
+                                         0, &js_exception))
+                {
+                    /* FIXME: Read meta data from .js file */
+                    g_object_set (extension, "description", "",
+                                  "version", "0.1", "authors", "", NULL);
+                    /* Signal that we want the extension to load and save */
+                    g_object_set_data_full (G_OBJECT (extension), "filename",
+                                            g_strdup (filename), g_free);
+                    if (midori_extension_is_prepared (extension))
+                        midori_extension_get_config_dir (extension);
+                    g_signal_connect (extension, "activate",
+                        G_CALLBACK (midori_javascript_extension_activate_cb), NULL);
+                }
+                else
+                {
+                    JSStringRef js_string = JSValueToStringCopy (js_context,
+                        js_exception, NULL);
+                    gchar* string = sokoke_js_string_utf8 (js_string);
+                    JSStringRelease (js_string);
+                    g_object_set (extension, "description", string, NULL);
+                    g_warning ("%s", string);
+                    g_free (string);
+                }
+            }
+            else
+            {
+                g_object_set (extension, "description", error->message, NULL);
+                g_warning ("%s", error->message);
+                g_error_free (error);
+            }
+            g_free (fullname);
+            katze_array_add_item (extensions, extension);
+            if (active)
+            {
+                guint i = 0;
+                gchar* name;
+                while ((name = active[i++]))
+                    if (!g_strcmp0 (filename, name))
+                        g_signal_emit_by_name (extension, "activate", app);
+            }
+            /* FIXME main.c needs to monitor extensions
+            g_signal_connect_after (extension, "activate",
+                G_CALLBACK (extension_activate_cb), app);
+            g_signal_connect_after (extension, "deactivate",
+                G_CALLBACK (extension_activate_cb), app); */
+            g_object_unref (extension);
+        }
+        g_object_unref (extensions);
+        g_dir_close (dir);
+    }
+}
+
+static void
+javascript_activate_cb (MidoriExtension* extension,
+                        MidoriApp*       app)
+{
+    gchar** active = midori_extension_get_string_list (extension, "extensions", NULL);
+    /* FIXME Scan system data dirs */
+    gchar* path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (),
+                                PACKAGE_NAME, "extensions", NULL);
+    javascript_load_extensions (active, app, path);
+    g_free (path);
+    g_strfreev (active);
+
+    g_signal_connect (extension, "deactivate",
+        G_CALLBACK (javascript_deactivate_cb), NULL);
+}
+
+MidoriExtension*
+extension_init (void)
+{
+    MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
+        "name", _("Javascript extensions"),
+        "description", _("Enable extensions written in Javascript"),
+        "version", "0.1",
+        "authors", "Christian Dywan <christian@twotoasts.de>",
+        NULL);
+    midori_extension_install_string_list (extension, "extensions", NULL, G_MAXSIZE);
+
+    g_signal_connect (extension, "activate",
+        G_CALLBACK (javascript_activate_cb), NULL);
+
+    return extension;
+}
index eedaa5721d9400caec55e56e53b6feb4cfbed8e5..be775588adacc4aaacbc9c1584bc13f3b48506d7 100644 (file)
@@ -190,7 +190,7 @@ mouse_gestures_add_tab_cb (MidoriBrowser*   browser,
                            MidoriView*      view,
                            MidoriExtension* extension)
 {
-    GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
+    GtkWidget* web_view = midori_view_get_web_view (view);
 
     g_object_connect (web_view,
         "signal::button-press-event",
@@ -231,7 +231,7 @@ static void
 mouse_gestures_deactivate_tabs (MidoriView*    view,
                                 MidoriBrowser* browser)
 {
-    GtkWidget* web_view = gtk_bin_get_child (GTK_BIN (view));
+    GtkWidget* web_view = midori_view_get_web_view (view);
 
     g_object_disconnect (web_view,
         "any_signal::button-press-event",
index d4749e83a7ca22aa7e3c52db94e1bc45ecf7887a..add09df152378624b2036c7a5f5448a9f6d38656 100644 (file)
@@ -25,7 +25,8 @@ static GdkPixbuf* tab_selector_get_snapshot(MidoriView* view,
     gfloat factor;
 
     g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
-    web_view = gtk_bin_get_child (GTK_BIN (view));
+
+    web_view = midori_view_get_web_view (view);
 
     if(maxwidth < 0) {
         maxwidth *= -1;