[gnome-shell] browser-plugin: Do not create a new object every time NPPVpluginScriptableNPObject is requested



commit d95d78ac15778c497e30e07c1d78b0827f72f5bb
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Tue Nov 17 14:41:03 2015 +0100

    browser-plugin: Do not create a new object every time NPPVpluginScriptableNPObject is requested
    
    Merge PluginData and PluginObject structs into a single one and create
    the scriptable object associated to the plugin instance in NPP_New. Then,
    when NPPVpluginScriptableNPObject is requested we just return the
    scriptable object associated to the given instance. This caused the
    crashes in NPN_InvokeDefault with WebKit, since we had multiple
    scriptable objects for the same instance, but only one of those objects
    had the onchange listener installed. Firefox seems to cache the
    scriptable object for the instance and therefore NPPVpluginScriptableNPObject
    is requested only once.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=737932

 browser-plugin/browser-plugin.c |  306 +++++++++++++++++++--------------------
 1 files changed, 150 insertions(+), 156 deletions(-)
---
diff --git a/browser-plugin/browser-plugin.c b/browser-plugin/browser-plugin.c
index dbeac33..4555a96 100644
--- a/browser-plugin/browser-plugin.c
+++ b/browser-plugin/browser-plugin.c
@@ -43,10 +43,6 @@
 
 #define EXTENSION_DISABLE_VERSION_CHECK_KEY "disable-extension-version-validation"
 
-typedef struct {
-  GDBusProxy *proxy;
-} PluginData;
-
 static NPNetscapeFuncs funcs;
 
 static inline gchar *
@@ -145,125 +141,6 @@ check_origin_and_protocol (NPP instance)
   return ret;
 }
 
-/* =============== public entry points =================== */
-
-NPError
-NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
-{
-  /* global initialization routine, called once when plugin
-     is loaded */
-
-  g_debug ("plugin loaded");
-
-  memcpy (&funcs, pfuncs, sizeof (funcs));
-
-  plugin->size = sizeof(NPPluginFuncs);
-  plugin->newp = NPP_New;
-  plugin->destroy = NPP_Destroy;
-  plugin->getvalue = NPP_GetValue;
-  plugin->setwindow = NPP_SetWindow;
-  plugin->event = NPP_HandleEvent;
-
-  return NPERR_NO_ERROR;
-}
-
-NPError
-NP_Shutdown(void)
-{
-  return NPERR_NO_ERROR;
-}
-
-const char*
-NP_GetMIMEDescription(void)
-{
-  return PLUGIN_MIME_STRING;
-}
-
-NPError
-NP_GetValue(void         *instance,
-            NPPVariable   variable,
-            void         *value)
-{
-  switch (variable) {
-  case NPPVpluginNameString:
-    *(char**)value = PLUGIN_NAME;
-    break;
-  case NPPVpluginDescriptionString:
-    *(char**)value = PLUGIN_DESCRIPTION;
-    break;
-  default:
-    ;
-  }
-
-  return NPERR_NO_ERROR;
-}
-
-NPError
-NPP_New(NPMIMEType    mimetype,
-        NPP           instance,
-        uint16_t      mode,
-        int16_t       argc,
-        char        **argn,
-        char        **argv,
-        NPSavedData  *saved)
-{
-  /* instance initialization function */
-  PluginData *data;
-  GError *error = NULL;
-
-  g_debug ("plugin created");
-
-  if (!check_origin_and_protocol (instance))
-    return NPERR_GENERIC_ERROR;
-
-  data = g_slice_new (PluginData);
-  instance->pdata = data;
-
-  /* set windowless mode */
-  funcs.setvalue(instance, NPPVpluginWindowBool, NULL);
-
-  data->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
-                                               G_DBUS_PROXY_FLAGS_NONE,
-                                               NULL, /* interface info */
-                                               "org.gnome.Shell",
-                                               "/org/gnome/Shell",
-                                               "org.gnome.Shell.Extensions",
-                                               NULL, /* GCancellable */
-                                               &error);
-  if (!data->proxy)
-    {
-      /* ignore error if the shell is not running, otherwise warn */
-      if (error->domain != G_DBUS_ERROR ||
-          error->code != G_DBUS_ERROR_NAME_HAS_NO_OWNER)
-        {
-          g_warning ("Failed to set up Shell proxy: %s", error->message);
-        }
-      g_clear_error (&error);
-      return NPERR_GENERIC_ERROR;
-    }
-
-  g_debug ("plugin created successfully");
-
-  return NPERR_NO_ERROR;
-}
-
-NPError
-NPP_Destroy(NPP           instance,
-           NPSavedData **saved)
-{
-  /* instance finalization function */
-
-  PluginData *data = instance->pdata;
-
-  g_debug ("plugin destroyed");
-
-  g_object_unref (data->proxy);
-
-  g_slice_free (PluginData, data);
-
-  return NPERR_NO_ERROR;
-}
-
 /* =================== scripting interface =================== */
 
 typedef struct {
@@ -334,45 +211,18 @@ static NPObject *
 plugin_object_allocate (NPP      instance,
                         NPClass *klass)
 {
-  PluginData *data = instance->pdata;
-  PluginObject *obj = g_slice_new0 (PluginObject);
+  PluginObject *obj = (PluginObject *) funcs.memalloc (sizeof (PluginObject));
 
+  memset (obj, 0, sizeof (PluginObject));
   obj->instance = instance;
-  obj->proxy = g_object_ref (data->proxy);
-  obj->settings = g_settings_new (SHELL_SCHEMA);
-  obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
-                                     G_CALLBACK (on_shell_signal), obj);
 
-  obj->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
-                                         "org.gnome.Shell",
-                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
-                                         on_shell_appeared,
-                                         NULL,
-                                         obj,
-                                         NULL);
-
-  g_debug ("plugin object created");
-
-  return (NPObject*)obj;
+  return (NPObject*) obj;
 }
 
 static void
 plugin_object_deallocate (NPObject *npobj)
 {
-  PluginObject *obj = (PluginObject*)npobj;
-
-  g_signal_handler_disconnect (obj->proxy, obj->signal_id);
-  g_object_unref (obj->proxy);
-
-  if (obj->listener)
-    funcs.releaseobject (obj->listener);
-
-  if (obj->watch_name_id)
-    g_bus_unwatch_name (obj->watch_name_id);
-
-  g_debug ("plugin object destroyed");
-
-  g_slice_free (PluginObject, obj);
+  funcs.memfree (npobj);
 }
 
 static inline gboolean
@@ -1023,6 +873,149 @@ init_methods_and_properties (void)
   onextension_changed_id = funcs.getstringidentifier ("onchange");
 }
 
+/* =============== public entry points =================== */
+
+NPError
+NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
+{
+  /* global initialization routine, called once when plugin
+     is loaded */
+
+  g_debug ("plugin loaded");
+
+  memcpy (&funcs, pfuncs, sizeof (funcs));
+
+  plugin->size = sizeof(NPPluginFuncs);
+  plugin->newp = NPP_New;
+  plugin->destroy = NPP_Destroy;
+  plugin->getvalue = NPP_GetValue;
+  plugin->setwindow = NPP_SetWindow;
+  plugin->event = NPP_HandleEvent;
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+NP_Shutdown(void)
+{
+  return NPERR_NO_ERROR;
+}
+
+const char*
+NP_GetMIMEDescription(void)
+{
+  return PLUGIN_MIME_STRING;
+}
+
+NPError
+NP_GetValue(void         *instance,
+            NPPVariable   variable,
+            void         *value)
+{
+  switch (variable) {
+  case NPPVpluginNameString:
+    *(char**)value = PLUGIN_NAME;
+    break;
+  case NPPVpluginDescriptionString:
+    *(char**)value = PLUGIN_DESCRIPTION;
+    break;
+  default:
+    ;
+  }
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+NPP_New(NPMIMEType    mimetype,
+        NPP           instance,
+        uint16_t      mode,
+        int16_t       argc,
+        char        **argn,
+        char        **argv,
+        NPSavedData  *saved)
+{
+  /* instance initialization function */
+  PluginObject *obj;
+  GError *error = NULL;
+
+  g_debug ("plugin created");
+
+  if (!check_origin_and_protocol (instance))
+    return NPERR_GENERIC_ERROR;
+
+  /* set windowless mode */
+  funcs.setvalue(instance, NPPVpluginWindowBool, NULL);
+
+  g_debug ("creating scriptable object");
+  init_methods_and_properties ();
+  obj = (PluginObject *) funcs.createobject (instance, &plugin_class);
+  instance->pdata = obj;
+
+  obj->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                              G_DBUS_PROXY_FLAGS_NONE,
+                                              NULL, /* interface info */
+                                              "org.gnome.Shell",
+                                              "/org/gnome/Shell",
+                                              "org.gnome.Shell.Extensions",
+                                              NULL, /* GCancellable */
+                                              &error);
+  if (!obj->proxy)
+    {
+      /* ignore error if the shell is not running, otherwise warn */
+      if (!g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
+        {
+          g_warning ("Failed to set up Shell proxy: %s", error->message);
+        }
+      g_clear_error (&error);
+      return NPERR_GENERIC_ERROR;
+    }
+
+  obj->settings = g_settings_new (SHELL_SCHEMA);
+  obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
+                                     G_CALLBACK (on_shell_signal), obj);
+  obj->watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                         "org.gnome.Shell",
+                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                         on_shell_appeared,
+                                         NULL,
+                                         obj,
+                                         NULL);
+
+  g_debug ("plugin created successfully");
+
+  return NPERR_NO_ERROR;
+}
+
+NPError
+NPP_Destroy(NPP           instance,
+           NPSavedData **saved)
+{
+  /* instance finalization function */
+  PluginObject *obj = (PluginObject *) instance->pdata;
+
+  if (!obj)
+    return NPERR_INVALID_INSTANCE_ERROR;
+
+  g_debug ("plugin destroyed");
+
+  g_signal_handler_disconnect (obj->proxy, obj->signal_id);
+  g_object_unref (obj->proxy);
+
+  if (obj->listener)
+    funcs.releaseobject (obj->listener);
+
+  if (obj->restart_listener)
+    funcs.releaseobject (obj->restart_listener);
+
+  if (obj->watch_name_id)
+    g_bus_unwatch_name (obj->watch_name_id);
+
+  funcs.releaseobject((NPObject *)obj);
+
+  return NPERR_NO_ERROR;
+}
+
 NPError
 NPP_GetValue(NPP          instance,
             NPPVariable  variable,
@@ -1033,9 +1026,10 @@ NPP_GetValue(NPP          instance,
   switch (variable) {
   case NPPVpluginScriptableNPObject:
     g_debug ("creating scriptable object");
-    init_methods_and_properties ();
+    if (!instance->pdata)
+      return NPERR_INVALID_INSTANCE_ERROR;
 
-    *(NPObject**)value = funcs.createobject (instance, &plugin_class);
+    *(NPObject**)value = instance->pdata;
     break;
 
   default:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]