OLD | NEW |
| (Empty) |
1 // Copyright 2010 The Ginsu Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can | |
3 // be found in the LICENSE file. | |
4 | |
5 #include "c_salt/npapi/javascript_object_proxy.h" | |
6 | |
7 #include "c_salt/npapi/scoped_npid_to_string_converter.h" | |
8 #include "c_salt/variant.h" | |
9 | |
10 namespace c_salt { | |
11 | |
12 namespace npapi { | |
13 | |
14 namespace { | |
15 // RAII wrappers for NPVariant that calls NPN_ReleaseVariantValue on | |
16 // destruction. NPVariantSentry is for most uses where you want to create an | |
17 // NPVariant on the stack and have it released at the end of scope. In those | |
18 // cases, simply create an NPVariantSentry, and when you need to use the | |
19 // NPVariant it owns, call my_sentry.np_variant() to get a reference to it. | |
20 class NPVariantSentry { | |
21 public: | |
22 NPVariantSentry() : np_variant_() {} | |
23 NPVariant& np_variant() { return np_variant_; } | |
24 ~NPVariantSentry() { NPN_ReleaseVariantValue(&np_variant_); } | |
25 private: | |
26 NPVariant np_variant_; | |
27 }; | |
28 // NPVariantPtrSentry is used when you want to own the NPVariant some other | |
29 // way, but you want NPN_ReleaseVariantValue to be invoked when the | |
30 // NPVariantPtrSentry goes out of scope. | |
31 class NPVariantPtrSentry { | |
32 public: | |
33 NPVariantPtrSentry() : np_variant_(NULL) {} | |
34 explicit NPVariantPtrSentry(NPVariant* np_variant) | |
35 : np_variant_(np_variant) {} | |
36 NPVariant* np_variant() { return np_variant_; } | |
37 void set_np_variant(NPVariant* np_variant) { | |
38 release(); | |
39 np_variant_ = np_variant; | |
40 } | |
41 void release() { | |
42 if (np_variant_) { | |
43 NPN_ReleaseVariantValue(np_variant_); | |
44 } | |
45 np_variant_ = NULL; | |
46 } | |
47 ~NPVariantPtrSentry() { release(); } | |
48 private: | |
49 NPVariant* np_variant_; | |
50 }; | |
51 } | |
52 | |
53 JavaScriptObjectProxy::JavaScriptObjectProxy(NPObject* np_object, | |
54 NPP instance) | |
55 : instance_(instance), np_object_(np_object), variant_converter_(instance) { | |
56 NPN_RetainObject(np_object_); | |
57 } | |
58 | |
59 JavaScriptObjectProxy::~JavaScriptObjectProxy() { | |
60 NPN_ReleaseObject(np_object_); | |
61 } | |
62 | |
63 void JavaScriptObjectProxy::Invalidate() { | |
64 instance_ = NULL; | |
65 np_object_ = NULL; | |
66 } | |
67 | |
68 bool JavaScriptObjectProxy::Valid() const { | |
69 return (instance_ && np_object_); | |
70 } | |
71 | |
72 bool JavaScriptObjectProxy::HasScriptMethod(const std::string& name) { | |
73 if (!Valid()) return false; | |
74 NPIdentifier name_id = NPN_GetStringIdentifier(name.c_str()); | |
75 return NPN_HasMethod(instance_, np_object_, name_id); | |
76 } | |
77 | |
78 bool | |
79 JavaScriptObjectProxy::InvokeScriptMethod( | |
80 const std::string& method_name, | |
81 const SharedVariant* params_begin, | |
82 const SharedVariant* params_end, | |
83 ::c_salt::SharedVariant* return_value) { | |
84 if (!Valid()) return false; | |
85 // Allocate a vector of NPVariants to hold the parameters and convet the | |
86 // c_salt variants to them. | |
87 std::size_t arg_count = params_end - params_begin; | |
88 std::vector<NPVariant> np_var_vector(arg_count); | |
89 // Make a vector of sentries to ensure the NPVariants are cleaned up | |
90 // regardless of how we exit this function. | |
91 std::vector<NPVariantPtrSentry> np_var_sentry_vector(arg_count); | |
92 for (size_t i = 0; i < arg_count; ++i) { | |
93 // Point the i-th sentry at the i-th NPVariant. Note that it's not | |
94 // necessary prior to this, as the i-th sentry is still NULL until after the | |
95 // conversion. | |
96 np_var_sentry_vector[i].set_np_variant(&np_var_vector[i]); | |
97 variant_converter_.ConvertVariantToNPVariant(*params_begin[i], | |
98 &np_var_vector[i]); | |
99 } | |
100 bool success = false; | |
101 NPVariantSentry return_var; | |
102 if (!method_name.empty()) { | |
103 NPIdentifier name_id = NPN_GetStringIdentifier(method_name.c_str()); | |
104 success = NPN_Invoke(instance_, | |
105 np_object_, | |
106 name_id, | |
107 &(*np_var_vector.begin()), | |
108 np_var_vector.size(), | |
109 &return_var.np_variant()); | |
110 } else { | |
111 success = NPN_InvokeDefault(instance_, | |
112 np_object_, | |
113 &(*np_var_vector.begin()), | |
114 np_var_vector.size(), | |
115 &return_var.np_variant()); | |
116 } | |
117 if (success) { | |
118 (*return_value) = | |
119 variant_converter_.CreateVariantFromNPVariant(return_var.np_variant()); | |
120 } | |
121 return success; | |
122 } | |
123 | |
124 void JavaScriptObjectProxy::GetAllPropertyNames( | |
125 std::vector<std::string>* prop_names) | |
126 const { | |
127 if (!Valid()) return; | |
128 if (prop_names) { | |
129 // Use the copy-and-swap idiom to ensure prop_names is only modified if | |
130 // everything succeeds. | |
131 std::vector<std::string> keys; | |
132 NPIdentifier* npid_array; | |
133 uint32_t array_size; | |
134 if (NPN_Enumerate(instance_, np_object_, &npid_array, &array_size)) { | |
135 keys.resize(array_size); | |
136 for (uint32_t i = 0; i < array_size; ++i) { | |
137 keys[i] = ScopedNPIdToStringConverter(npid_array[i]).string_value(); | |
138 } | |
139 } | |
140 NPN_MemFree(npid_array); | |
141 prop_names->swap(keys); | |
142 } | |
143 } | |
144 | |
145 bool JavaScriptObjectProxy::HasScriptProperty(const std::string& name) { | |
146 if (!Valid()) return false; | |
147 NPIdentifier name_id = NPN_GetStringIdentifier(name.c_str()); | |
148 return NPN_HasProperty(instance_, np_object_, name_id); | |
149 } | |
150 | |
151 bool | |
152 JavaScriptObjectProxy::GetScriptProperty(const std::string& name, | |
153 SharedVariant* return_value) const { | |
154 if (!Valid()) return false; | |
155 assert(return_value); | |
156 if (NULL == return_value) { | |
157 return false; | |
158 } | |
159 NPIdentifier name_id = NPN_GetStringIdentifier(name.c_str()); | |
160 NPVariantSentry result; | |
161 bool success = NPN_GetProperty(instance_, | |
162 np_object_, | |
163 name_id, | |
164 &result.np_variant()); | |
165 if (success) { | |
166 *return_value = variant_converter_. | |
167 CreateVariantFromNPVariant(result.np_variant()); | |
168 } | |
169 return success; | |
170 } | |
171 | |
172 bool JavaScriptObjectProxy::SetScriptProperty(const std::string& name, | |
173 const SharedVariant& value) { | |
174 if (!Valid()) return false; | |
175 NPIdentifier name_id = NPN_GetStringIdentifier(name.c_str()); | |
176 NPVariantSentry np_var; | |
177 variant_converter_.ConvertVariantToNPVariant(*value, &np_var.np_variant()); | |
178 bool success = NPN_SetProperty(instance_, | |
179 np_object_, | |
180 name_id, | |
181 &np_var.np_variant()); | |
182 return success; | |
183 } | |
184 | |
185 bool JavaScriptObjectProxy::RemoveScriptProperty(const std::string& name) { | |
186 if (!Valid()) return false; | |
187 NPIdentifier name_id = NPN_GetStringIdentifier(name.c_str()); | |
188 return NPN_RemoveProperty(instance_, np_object_, name_id); | |
189 } | |
190 | |
191 } // namespace npapi | |
192 } // namespace c_salt | |
OLD | NEW |