[gnome-shell] Add a hack to block calls to certain introspected functions



commit fe542f873240547091e583086341056c062f162c
Author: Dan Winship <danw gnome org>
Date:   Fri Mar 26 16:38:03 2010 -0400

    Add a hack to block calls to certain introspected functions
    
    This is useful for keeping people from using methods that only fail in
    certain circumstances, by making them fail in all circumstances
    instead.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=618918

 js/ui/environment.js |   47 ++++++++++++++++++++++++++++++++++-
 src/shell-global.c   |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/shell-global.h   |    5 ++++
 3 files changed, 115 insertions(+), 2 deletions(-)
---
diff --git a/js/ui/environment.js b/js/ui/environment.js
index 209cdc8..67682d8 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -1,5 +1,6 @@
 /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
+const Shell = imports.gi.Shell;
 const St = imports.gi.St;
 const Gettext_gtk20 = imports.gettext.domain('gtk20');
 
@@ -28,8 +29,34 @@ function _patchContainerClass(containerClass) {
     };
 }
 
-_patchContainerClass(St.BoxLayout);
-_patchContainerClass(St.Table);
+// Replace @method with something that throws an error instead
+function _blockMethod(method, replacement, reason) {
+    let match = method.match(/^(.+)\.([^.]+)$/);
+    if (!match)
+        throw new Error('Bad method name "' + method + '"');
+    let proto = 'imports.gi.' + match[1] + '.prototype';
+    let property = match[2];
+
+    if (!global.set_property_mutable(proto, property, true))
+        throw new Error('Bad method name "' + method + '"');
+
+    // eval() is evil in general, but we know it's safe here since
+    // set_property_mutable() would have failed if proto was
+    // malformed.
+    let node = eval(proto);
+
+    let msg = 'Do not use "' + method + '".';
+    if (replacement)
+        msg += ' Use "' + replacement + '" instead.';
+    if (reason)
+        msg += ' (' + reason + ')';
+
+    node[property] = function() {
+        throw new Error(msg);
+    };
+
+    global.set_property_mutable(proto, property, false);
+}
 
 function init() {
     Tweener.init();
@@ -39,4 +66,20 @@ function init() {
     if (Gettext_gtk20.gettext('default:LTR') == 'default:RTL') {
         St.Widget.set_default_direction(St.TextDirection.RTL);
     }
+
+    _patchContainerClass(St.BoxLayout);
+    _patchContainerClass(St.Table);
+
+    _blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
+                 'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
+    _blockMethod('Gdk.Display.get_pointer', 'global.get_pointer',
+                 'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
+    _blockMethod('Gdk.Window.get_pointer', 'global.get_pointer',
+                 'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
+
+    // Now close the back door to prevent extensions from trying to
+    // abuse it. We can't actually delete it since
+    // Shell.Global.prototype itself is read-only.
+    global.set_property_mutable('imports.gi.Shell.Global.prototype', 'set_property_mutable', true);
+    Shell.Global.prototype.set_property_mutable = undefined;
 }
diff --git a/src/shell-global.c b/src/shell-global.c
index 758af54..5d61e41 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -1327,3 +1327,68 @@ shell_global_create_app_launch_context (ShellGlobal *global)
 
   return (GAppLaunchContext *)context;
 }
+
+/**
+ * shell_global_set_property_mutable:
+ * @global: the #ShellGlobal
+ * @object: the "path" to a JS object, starting from the root object.
+ *  (Eg, "global.stage" or "imports.gi.Gtk.Window.prototype")
+ * @property: a property on @object
+ * @mutable: %TRUE or %FALSE
+ *
+ * If @mutable is %TRUE, this clears the "permanent" and "readonly" flags
+ * on @property of @object. If @mutable is %FALSE, it sets them.
+ *
+ * You can use this to make it possible to modify properties that
+ * would otherwise be read-only from JavaScript.
+ *
+ * Return value: success or failure.
+ */
+gboolean
+shell_global_set_property_mutable (ShellGlobal *global,
+                                   const char  *object,
+                                   const char  *property,
+                                   gboolean     mutable)
+{
+  JSContext *context = gjs_context_get_native_context (global->js_context);
+  char **parts;
+  JSObject *obj;
+  jsval val = JSVAL_VOID;
+  int i;
+  jsuint attrs;
+  JSBool found;
+
+  JS_AddRoot (context, &val);
+
+  parts = g_strsplit (object, ".", -1);
+  obj = JS_GetGlobalObject (context);
+  for (i = 0; parts[i]; i++)
+    {
+      if (!JS_GetProperty (context, obj, parts[i], &val))
+        {
+          g_strfreev (parts);
+          JS_RemoveRoot (context, &val);
+          gjs_log_exception (context, NULL);
+          return FALSE;
+        }
+      obj = JSVAL_TO_OBJECT (val);
+    }
+  g_strfreev (parts);
+
+  if (!JS_GetPropertyAttributes (context, obj, property, &attrs, &found) || !found)
+    {
+      JS_RemoveRoot (context, &val);
+      gjs_log_exception (context, NULL);
+      return FALSE;
+    }
+
+  if (mutable)
+    attrs &= ~(JSPROP_PERMANENT | JSPROP_READONLY);
+  else
+    attrs |= (JSPROP_PERMANENT | JSPROP_READONLY);
+
+  JS_SetPropertyAttributes (context, obj, property, attrs, &found);
+
+  JS_RemoveRoot (context, &val);
+  return !gjs_log_exception (context, NULL);
+}
diff --git a/src/shell-global.h b/src/shell-global.h
index 5ac31d8..27c43be 100644
--- a/src/shell-global.h
+++ b/src/shell-global.h
@@ -96,6 +96,11 @@ guint32 shell_global_get_current_time (ShellGlobal *global);
 
 GAppLaunchContext *shell_global_create_app_launch_context (ShellGlobal *global);
 
+gboolean shell_global_set_property_mutable (ShellGlobal *global,
+                                            const char  *object,
+                                            const char  *property,
+                                            gboolean     mutable);
+
 G_END_DECLS
 
 #endif /* __SHELL_GLOBAL_H__ */



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