Browse Source

more inbound scripting

David Rose 16 năm trước cách đây
mục cha
commit
165a57a38a
2 tập tin đã thay đổi với 151 bổ sung12 xóa
  1. 143 11
      direct/src/plugin_npapi/ppObject.cxx
  2. 8 1
      direct/src/plugin_npapi/ppObject.h

+ 143 - 11
direct/src/plugin_npapi/ppObject.cxx

@@ -45,7 +45,7 @@ make_new(PPInstance *inst, P3D_object *p3d_object) {
   NPObject *npobj = 
     browser->createobject(inst->get_npp_instance(), &_object_class);
   PPObject *ppobj = (PPObject *)npobj;
-  ppobj->construct(p3d_object);
+  ppobj->construct(inst, p3d_object);
   return ppobj;
 }
 
@@ -53,7 +53,8 @@ make_new(PPInstance *inst, P3D_object *p3d_object) {
 //     Function: PPObject::set_p3d_object
 //       Access: Public
 //  Description: Changes the p3d_object this PPObject maps to.  The
-//               previous object, if any, is deleted.
+//               previous object, if any, is deleted.  Ownership of
+//               the new object is passed to the PPObject.
 ////////////////////////////////////////////////////////////////////
 void PPObject::
 set_p3d_object(P3D_object *p3d_object) {
@@ -74,8 +75,9 @@ set_p3d_object(P3D_object *p3d_object) {
 //               following NPN_CreateObject().
 ////////////////////////////////////////////////////////////////////
 void PPObject::
-construct(P3D_object *p3d_object) {
+construct(PPInstance *inst, P3D_object *p3d_object) {
   logfile << "construct: " << this << "\n" << flush;
+  _instance = inst;
   _p3d_object = p3d_object;
 }
 
@@ -87,6 +89,7 @@ construct(P3D_object *p3d_object) {
 void PPObject::
 invalidate() {
   logfile << "invalidate: " << this << "\n" << flush;
+  _instance = NULL;
   set_p3d_object(NULL);
 }
 
@@ -98,7 +101,8 @@ invalidate() {
 ////////////////////////////////////////////////////////////////////
 bool PPObject::
 has_method(NPIdentifier name) {
-  logfile << "has_method: " << this << "\n" << flush;
+  string property_name = identifier_to_string(name);
+  logfile << "has_method: " << this << ", " << property_name << "\n" << flush;
   return false;
 }
 
@@ -138,8 +142,14 @@ invoke_default(const NPVariant *args, uint32_t argCount,
 ////////////////////////////////////////////////////////////////////
 bool PPObject::
 has_property(NPIdentifier name) {
-  logfile << "has_property: " << this << "\n" << flush;
-  return false;
+  string property_name = identifier_to_string(name);
+  logfile << "has_property: " << this << ", " << property_name << "\n" << flush;
+
+  // If we say we don't have a given property, then set_property()
+  // will never be called.  So we always say we *do* have any
+  // particular property, whether we currently have it right now or
+  // not (since we *could* have it if you call set_property()).
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -151,8 +161,23 @@ has_property(NPIdentifier name) {
 ////////////////////////////////////////////////////////////////////
 bool PPObject::
 get_property(NPIdentifier name, NPVariant *result) {
-  logfile << "get_property: " << this << "\n" << flush;
-  return false;
+  string property_name = identifier_to_string(name);
+  logfile << "get_property: " << this << ", " << property_name << "\n" << flush;
+  if (_p3d_object == NULL) {
+    // Not powered up yet.
+    return false;
+  }
+
+  P3D_object *value = P3D_OBJECT_GET_PROPERTY(_p3d_object, property_name.c_str());
+  if (value == NULL) {
+    // No such property.
+    return false;
+  }
+
+  // We have the property, and its value is stored in value.
+  object_to_variant(result, value);
+  P3D_OBJECT_FINISH(value);
+  return true;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -163,8 +188,16 @@ get_property(NPIdentifier name, NPVariant *result) {
 ////////////////////////////////////////////////////////////////////
 bool PPObject::
 set_property(NPIdentifier name, const NPVariant *value) {
-  logfile << "set_property: " << this << "\n" << flush;
-  return false;
+  string property_name = identifier_to_string(name);
+  logfile << "set_property: " << this << ", " << property_name << "\n" << flush;
+  if (_p3d_object == NULL) {
+    // Not powered up yet.
+    return false;
+  }
+
+  P3D_object *object = variant_to_object(value);
+  bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
+  return result;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -197,6 +230,101 @@ enumerate(NPIdentifier **value, uint32_t *count) {
   return false;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PPObject::identifier_to_string
+//       Access: Private, Static
+//  Description: Gets the string equivalent of the indicated
+//               identifier.
+////////////////////////////////////////////////////////////////////
+string PPObject::
+identifier_to_string(NPIdentifier ident) {
+  if (browser->identifierisstring(ident)) {
+    NPUTF8 *result = browser->utf8fromidentifier(ident);
+    if (result != NULL) {
+      string strval(result);
+      browser->memfree(result);
+      return strval;
+    }
+  }
+
+  return string();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPObject::object_to_variant
+//       Access: Private
+//  Description: Converts the indicated P3D_object to the equivalent
+//               NPVariant, and stores it in result.
+////////////////////////////////////////////////////////////////////
+void PPObject::
+object_to_variant(NPVariant *result, const P3D_object *object) {
+  switch (P3D_OBJECT_GET_TYPE(object)) {
+  case P3D_OT_none:
+    VOID_TO_NPVARIANT(*result);
+    break;
+
+  case P3D_OT_bool:
+    BOOLEAN_TO_NPVARIANT(P3D_OBJECT_GET_BOOL(object), *result);
+    break;
+
+  case P3D_OT_int:
+    INT32_TO_NPVARIANT(P3D_OBJECT_GET_INT(object), *result);
+    break;
+
+  case P3D_OT_float:
+    DOUBLE_TO_NPVARIANT(P3D_OBJECT_GET_FLOAT(object), *result);
+    break;
+
+  case P3D_OT_string:
+    {
+      int size = P3D_OBJECT_GET_STRING(object, NULL, 0);
+      char *buffer = (char *)browser->memalloc(size);
+      P3D_OBJECT_GET_STRING(object, buffer, size);
+      STRINGN_TO_NPVARIANT(buffer, size, *result);
+    }
+    break;
+
+  case P3D_OT_list:
+  case P3D_OT_object:
+    {
+      PPObject *ppobj = PPObject::make_new(_instance, P3D_OBJECT_COPY(object));
+      OBJECT_TO_NPVARIANT(ppobj, *result);
+    }
+    break;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PPObject::variant_to_object
+//       Access: Private
+//  Description: Converts the indicated NPVariant to the equivalent
+//               P3D_object, and returns it (newly-allocated).  The
+//               caller is responsible for freeing the returned object
+//               later.
+////////////////////////////////////////////////////////////////////
+P3D_object *PPObject::
+variant_to_object(const NPVariant *variant) {
+  if (NPVARIANT_IS_VOID(*variant) ||
+      NPVARIANT_IS_NULL(*variant)) {
+    return P3D_new_none_object();
+  } else if (NPVARIANT_IS_BOOLEAN(*variant)) {
+    return P3D_new_bool_object(NPVARIANT_TO_BOOLEAN(*variant));
+  } else if (NPVARIANT_IS_INT32(*variant)) {
+    return P3D_new_int_object(NPVARIANT_TO_INT32(*variant));
+  } else if (NPVARIANT_IS_DOUBLE(*variant)) {
+    return P3D_new_float_object(NPVARIANT_TO_DOUBLE(*variant));
+  } else if (NPVARIANT_IS_STRING(*variant)) {
+    NPString str = NPVARIANT_TO_STRING(*variant);
+    return P3D_new_string_object(str.utf8characters, str.utf8length);
+  } else if (NPVARIANT_IS_OBJECT(*variant)) {
+    // TODO.
+    return P3D_new_none_object();
+  }
+
+  // Hmm, none of the above?
+  return P3D_new_none_object();
+}
+
 
 // The remaining function bodies are the C-style function wrappers
 // that are called directly by NPAPI, and which redirect into the
@@ -224,6 +352,7 @@ NPAllocate(NPP npp, NPClass *aClass) {
 void PPObject::
 NPDeallocate(NPObject *npobj) {
   logfile << "NPDeallocate: " << npobj << "\n" << flush;
+  ((PPObject *)npobj)->invalidate();
   free(npobj);
 }
 
@@ -235,7 +364,10 @@ NPDeallocate(NPObject *npobj) {
 void PPObject::
 NPInvalidate(NPObject *npobj) {
   logfile << "NPInvalidate: " << npobj << "\n" << flush;
-  ((PPObject *)npobj)->invalidate();
+
+  // It turns out that this method isn't actually called by Safari's
+  // implementation of NPAPI, so we'll move the actual destructor call
+  // into NPDeallocate, above.
 }
 
 ////////////////////////////////////////////////////////////////////

+ 8 - 1
direct/src/plugin_npapi/ppObject.h

@@ -31,7 +31,7 @@ public:
   void set_p3d_object(P3D_object *p3d_object);
 
 private:
-  void construct(P3D_object *p3d_object);
+  void construct(PPInstance *inst, P3D_object *p3d_object);
   void invalidate();
 
   bool has_method(NPIdentifier name);
@@ -48,6 +48,12 @@ private:
   bool remove_property(NPIdentifier name);
   bool enumerate(NPIdentifier **value, uint32_t *count);
 
+private:
+  static string identifier_to_string(NPIdentifier ident);
+  void object_to_variant(NPVariant *result, const P3D_object *object);
+  P3D_object *variant_to_object(const NPVariant *variant);
+  
+
 private:
   static NPObject *NPAllocate(NPP npp, NPClass *aClass);
   static void NPDeallocate(NPObject *npobj);
@@ -75,6 +81,7 @@ private:
                           NPVariant *result);
 
 private:
+  PPInstance *_instance;
   P3D_object *_p3d_object;
 
   static NPClass _object_class;