ppBrowserObject.cxx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /**
  2. * PANDA 3D SOFTWARE
  3. * Copyright (c) Carnegie Mellon University. All rights reserved.
  4. *
  5. * All use of this software is subject to the terms of the revised BSD
  6. * license. You should have received a copy of this license along
  7. * with this source code in a file named "LICENSE."
  8. *
  9. * @file ppBrowserObject.cxx
  10. * @author drose
  11. * @date 2009-07-05
  12. */
  13. #include "ppBrowserObject.h"
  14. #include "ppInstance.h"
  15. #include <sstream>
  16. #include <string.h> // strncpy
  17. // The following functions are C-style wrappers around the above
  18. // PPBrowserObject methods; they are defined to allow us to create the C-style
  19. // P3D_class_definition method table to store in the P3D_object structure.
  20. static void
  21. object_finish(P3D_object *object) {
  22. delete ((PPBrowserObject *)object);
  23. }
  24. static int
  25. object_get_repr(P3D_object *object, char *buffer, int buffer_length) {
  26. return ((const PPBrowserObject *)object)->get_repr(buffer, buffer_length);
  27. }
  28. static P3D_object *
  29. object_get_property(P3D_object *object, const char *property) {
  30. return ((const PPBrowserObject *)object)->get_property(property);
  31. }
  32. static bool
  33. object_set_property(P3D_object *object, const char *property,
  34. bool needs_response, P3D_object *value) {
  35. return ((PPBrowserObject *)object)->set_property(property, needs_response, value);
  36. }
  37. static P3D_object *
  38. object_call(P3D_object *object, const char *method_name,
  39. bool needs_response,
  40. P3D_object *params[], int num_params) {
  41. if (method_name == nullptr) {
  42. method_name = "";
  43. }
  44. P3D_object *response = ((const PPBrowserObject *)object)->call(method_name, params, num_params);
  45. if (!needs_response) {
  46. // No response was expected. Throw away the response we received, so we
  47. // can be consistent with defined semantics.
  48. P3D_OBJECT_XDECREF(response);
  49. response = nullptr;
  50. }
  51. return response;
  52. }
  53. static P3D_object *
  54. object_eval(P3D_object *object, const char *expression) {
  55. return ((const PPBrowserObject *)object)->eval(expression);
  56. }
  57. P3D_class_definition *PPBrowserObject::_browser_object_class;
  58. /**
  59. *
  60. */
  61. PPBrowserObject::
  62. PPBrowserObject(PPInstance *inst, NPObject *npobj) :
  63. _instance(inst),
  64. _npobj(npobj)
  65. {
  66. _class = get_class_definition();
  67. _ref_count = 1;
  68. browser->retainobject(_npobj);
  69. }
  70. /**
  71. *
  72. */
  73. PPBrowserObject::
  74. PPBrowserObject(const PPBrowserObject &copy) :
  75. _instance(copy._instance),
  76. _npobj(copy._npobj)
  77. {
  78. _class = get_class_definition();
  79. _ref_count = 1;
  80. browser->retainobject(_npobj);
  81. }
  82. /**
  83. *
  84. */
  85. PPBrowserObject::
  86. ~PPBrowserObject() {
  87. assert(_ref_count == 0);
  88. browser->releaseobject(_npobj);
  89. }
  90. /**
  91. * Returns a user-friendly representation of the object, similar to
  92. * get_string(), above.
  93. */
  94. int PPBrowserObject::
  95. get_repr(char *buffer, int buffer_length) const {
  96. ostringstream strm;
  97. strm << "NPObject " << _npobj;
  98. string result = strm.str();
  99. strncpy(buffer, result.c_str(), buffer_length);
  100. return (int)result.size();
  101. }
  102. /**
  103. * Returns the named property element in the object. The return value is a
  104. * freshly-allocated PPBrowserObject object that must be deleted by the
  105. * caller, or NULL on error.
  106. */
  107. P3D_object *PPBrowserObject::
  108. get_property(const string &property) const {
  109. NPIdentifier property_name = browser->getstringidentifier(property.c_str());
  110. if (!browser->hasproperty(_instance->get_npp_instance(), _npobj,
  111. property_name)) {
  112. // No such property.
  113. return nullptr;
  114. }
  115. NPVariant result;
  116. if (!browser->getproperty(_instance->get_npp_instance(), _npobj,
  117. property_name, &result)) {
  118. // Failed to retrieve property.
  119. return nullptr;
  120. }
  121. P3D_object *object = _instance->variant_to_p3dobj(&result);
  122. browser->releasevariantvalue(&result);
  123. return object;
  124. }
  125. /**
  126. * Modifies (or deletes, if value is NULL) the named property element in the
  127. * object. Returns true on success, false on failure.
  128. */
  129. bool PPBrowserObject::
  130. set_property(const string &property, bool needs_response, P3D_object *value) {
  131. NPIdentifier property_name = browser->getstringidentifier(property.c_str());
  132. bool result;
  133. if (value != nullptr) {
  134. // Set the property.
  135. NPVariant npvalue;
  136. _instance->p3dobj_to_variant(&npvalue, value);
  137. result = browser->setproperty(_instance->get_npp_instance(), _npobj,
  138. property_name, &npvalue);
  139. browser->releasevariantvalue(&npvalue);
  140. } else {
  141. // Delete the property.
  142. result = browser->removeproperty(_instance->get_npp_instance(), _npobj,
  143. property_name);
  144. }
  145. return result;
  146. }
  147. /**
  148. * Invokes the named method on the object, passing the indicated parameters.
  149. * If the method name is empty, invokes the object itself. Returns the return
  150. * value on success, NULL on error.
  151. */
  152. P3D_object *PPBrowserObject::
  153. call(const string &method_name, P3D_object *params[], int num_params) const {
  154. // First, convert all of the parameters.
  155. NPVariant *npparams = new NPVariant[num_params];
  156. for (int i = 0; i < num_params; ++i) {
  157. _instance->p3dobj_to_variant(&npparams[i], params[i]);
  158. }
  159. NPVariant result;
  160. if (method_name.empty()) {
  161. // Call the default method.
  162. if (!browser->invokeDefault(_instance->get_npp_instance(), _npobj,
  163. npparams, num_params, &result)) {
  164. // Failed to invoke.
  165. delete[] npparams;
  166. return nullptr;
  167. }
  168. } else {
  169. // Call the named method.
  170. NPIdentifier method_id = browser->getstringidentifier(method_name.c_str());
  171. if (!browser->invoke(_instance->get_npp_instance(), _npobj, method_id,
  172. npparams, num_params, &result)) {
  173. // Failed to invoke.
  174. delete[] npparams;
  175. return nullptr;
  176. }
  177. }
  178. delete[] npparams;
  179. P3D_object *object = _instance->variant_to_p3dobj(&result);
  180. browser->releasevariantvalue(&result);
  181. return object;
  182. }
  183. /**
  184. * Evaluates the indicated JavaScript expression in the context of the object.
  185. */
  186. P3D_object *PPBrowserObject::
  187. eval(const string &expression) const {
  188. NPString npexpr = { expression.c_str(), (uint32_t)expression.length() };
  189. NPVariant result;
  190. if (!browser->evaluate(_instance->get_npp_instance(), _npobj,
  191. &npexpr, &result)) {
  192. // Failed to eval.
  193. return nullptr;
  194. }
  195. P3D_object *object = _instance->variant_to_p3dobj(&result);
  196. browser->releasevariantvalue(&result);
  197. return object;
  198. }
  199. /**
  200. * Should be called when the core API is unloaded, and the associated class
  201. * definition object is therefore invalidated.
  202. */
  203. void PPBrowserObject::
  204. clear_class_definition() {
  205. _browser_object_class = nullptr;
  206. }
  207. /**
  208. * Returns a pointer to the P3D_class_definition object that lists all of the
  209. * C-style method pointers for this class object.
  210. */
  211. P3D_class_definition *PPBrowserObject::
  212. get_class_definition() {
  213. if (_browser_object_class == nullptr) {
  214. // Create a default class_definition object, and fill in the appropriate
  215. // pointers.
  216. _browser_object_class = P3D_make_class_definition_ptr();
  217. _browser_object_class->_finish = &object_finish;
  218. _browser_object_class->_get_repr = &object_get_repr;
  219. _browser_object_class->_get_property = &object_get_property;
  220. _browser_object_class->_set_property = &object_set_property;
  221. _browser_object_class->_call = &object_call;
  222. _browser_object_class->_eval = &object_eval;
  223. }
  224. return _browser_object_class;
  225. }