| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Scriptable handle implementation. | 5 // Scriptable plugin implementation. |
| 6 | 6 |
| 7 #include "native_client/src/trusted/plugin/scriptable_handle.h" | 7 #include "native_client/src/trusted/plugin/scriptable_plugin.h" |
| 8 | 8 |
| 9 #include <stdio.h> | |
| 10 #include <string.h> | 9 #include <string.h> |
| 11 | 10 |
| 12 #include <assert.h> | |
| 13 #include <set> | |
| 14 #include <sstream> | 11 #include <sstream> |
| 15 #include <string> | 12 #include <string> |
| 16 #include <vector> | 13 #include <vector> |
| 17 | 14 |
| 18 | |
| 19 #include "native_client/src/include/checked_cast.h" | |
| 20 #include "native_client/src/include/nacl_macros.h" | 15 #include "native_client/src/include/nacl_macros.h" |
| 21 #include "native_client/src/include/nacl_string.h" | 16 #include "native_client/src/include/nacl_string.h" |
| 22 #include "native_client/src/include/portability.h" | 17 #include "native_client/src/include/portability.h" |
| 23 #include "native_client/src/shared/platform/nacl_check.h" | 18 #include "native_client/src/shared/platform/nacl_check.h" |
| 24 #include "native_client/src/shared/srpc/nacl_srpc.h" | 19 #include "native_client/src/shared/srpc/nacl_srpc.h" |
| 25 #include "native_client/src/trusted/plugin/array_ppapi.h" | |
| 26 #include "native_client/src/trusted/plugin/browser_interface.h" | |
| 27 #include "native_client/src/trusted/plugin/desc_based_handle.h" | |
| 28 #include "native_client/src/trusted/plugin/method_map.h" | |
| 29 #include "native_client/src/trusted/plugin/plugin.h" | 20 #include "native_client/src/trusted/plugin/plugin.h" |
| 30 #include "native_client/src/trusted/plugin/utility.h" | 21 #include "native_client/src/trusted/plugin/utility.h" |
| 31 #include "native_client/src/trusted/plugin/var_utils.h" | |
| 32 | 22 |
| 33 | 23 |
| 34 namespace plugin { | 24 namespace plugin { |
| 35 | 25 |
| 36 namespace { | 26 namespace { |
| 37 | 27 |
| 38 // For security we keep track of the set of scriptable handles that were | |
| 39 // created. | |
| 40 | |
| 41 std::set<const plugin::ScriptableHandle*>* g_ValidHandles = 0; | |
| 42 | |
| 43 void RememberValidHandle(const ScriptableHandle* handle) { | |
| 44 // Initialize the set. | |
| 45 // BUG: this is not thread safe. We may leak sets, or worse, may not | |
| 46 // correctly insert valid handles into the set. | |
| 47 // TODO(sehr): use pthread_once or similar initialization. | |
| 48 if (NULL == g_ValidHandles) { | |
| 49 g_ValidHandles = new(std::nothrow) std::set<const ScriptableHandle*>; | |
| 50 if (NULL == g_ValidHandles) { | |
| 51 return; | |
| 52 } | |
| 53 } | |
| 54 // Remember the handle. | |
| 55 g_ValidHandles->insert(handle); | |
| 56 } | |
| 57 | |
| 58 pp::Var Error(const nacl::string& call_name, const char* caller, | 28 pp::Var Error(const nacl::string& call_name, const char* caller, |
| 59 const char* error, pp::Var* exception) { | 29 const char* error, pp::Var* exception) { |
| 60 nacl::stringstream error_stream; | 30 nacl::stringstream error_stream; |
| 61 error_stream << call_name << ": " << error; | 31 error_stream << call_name << ": " << error; |
| 62 if (!exception->is_undefined()) { | 32 if (!exception->is_undefined()) { |
| 63 error_stream << " - " + exception->AsString(); | 33 error_stream << " - " + exception->AsString(); |
| 64 } | 34 } |
| 65 // Get the error string in 2 steps; otherwise, the temporary string returned | 35 // Get the error string in 2 steps; otherwise, the temporary string returned |
| 66 // by the stream is destructed, causing a dangling pointer. | 36 // by the stream is destructed, causing a dangling pointer. |
| 67 std::string str = error_stream.str(); | 37 std::string str = error_stream.str(); |
| 68 const char* e = str.c_str(); | 38 const char* e = str.c_str(); |
| 69 PLUGIN_PRINTF(("ScriptableHandle::%s (%s)\n", caller, e)); | 39 PLUGIN_PRINTF(("ScriptablePlugin::%s (%s)\n", caller, e)); |
| 70 *exception = pp::Var(e); | 40 *exception = pp::Var(e); |
| 71 return pp::Var(); | 41 return pp::Var(); |
| 72 } | 42 } |
| 73 | 43 |
| 74 // Helper functionality common to HasProperty and HasMethod. | 44 // In JavaScript, foo[1] is equivalent to foo["1"], so map both indexed and |
| 75 bool HasCallType(Plugin* plugin, | 45 // string names to a string. |
| 76 CallType call_type, | 46 nacl::string NameAsString(const pp::Var& name) { |
| 77 const nacl::string& call_name, | 47 if (name.is_string()) |
| 78 const char* caller) { | 48 return name.AsString(); |
| 79 uintptr_t id = plugin->browser_interface()->StringToIdentifier(call_name); | 49 CHECK(name.is_int()); |
| 80 PLUGIN_PRINTF(("ScriptableHandle::%s (id=%"NACL_PRIxPTR")\n", | 50 nacl::stringstream namestream; |
| 81 caller, id)); | 51 namestream << name.AsInt(); |
| 82 return plugin->HasMethod(id, call_type); | 52 return namestream.str(); |
| 83 } | 53 } |
| 84 | 54 |
| 85 // Helper functionality common to GetProperty, SetProperty and Call. | 55 // Returns a pp::Var corresponding to |arg| or void. Sets |exception| on error. |
| 86 // If |call_type| is PROPERTY_GET, ignores args and expects 1 return var. | 56 pp::Var NaClSrpcArgToPPVar(const NaClSrpcArg* arg, pp::Var* exception) { |
| 87 // If |call_type| is PROPERTY_SET, expects 1 arg and returns void var. | 57 PLUGIN_PRINTF((" NaClSrpcArgToPPVar (arg->tag='%c')\n", arg->tag)); |
| 88 // Sets |exception| on failure. | 58 pp::Var var; |
| 89 pp::Var Invoke(Plugin* plugin, | 59 switch (arg->tag) { |
| 90 CallType call_type, | 60 case NACL_SRPC_ARG_TYPE_BOOL: |
| 91 const nacl::string& call_name, | 61 var = pp::Var(arg->u.bval != 0); |
| 92 const char* caller, | 62 break; |
| 93 const std::vector<pp::Var>& args, | 63 case NACL_SRPC_ARG_TYPE_DOUBLE: |
| 94 pp::Var* exception) { | 64 var = pp::Var(arg->u.dval); |
| 95 uintptr_t id = plugin->browser_interface()->StringToIdentifier(call_name); | 65 break; |
| 96 | 66 case NACL_SRPC_ARG_TYPE_INT: |
| 97 // Initialize input/output parameters. | 67 var = pp::Var(arg->u.ival); |
| 98 SrpcParams params; | 68 break; |
| 99 NaClSrpcArg** inputs = params.ins(); | 69 case NACL_SRPC_ARG_TYPE_LONG: |
| 100 NaClSrpcArg** outputs = params.outs(); | 70 // PPAPI does not have a 64-bit integral type. Downcast. |
| 101 if (!plugin->InitParams(id, call_type, ¶ms)) { | 71 var = pp::Var(static_cast<int32_t>(arg->u.lval)); |
| 102 return Error(call_name, caller, | 72 break; |
| 103 "srpc parameter initialization failed", exception); | 73 case NACL_SRPC_ARG_TYPE_STRING: |
| 104 } | 74 var = pp::Var(arg->arrays.str); |
| 105 uint32_t input_length = params.InputLength(); | 75 break; |
| 106 int32_t output_length = params.OutputLength(); | 76 case NACL_SRPC_ARG_TYPE_CHAR_ARRAY: |
| 107 PLUGIN_PRINTF(("ScriptableHandle::%s (initialized %"NACL_PRIu32" ins, %" | 77 case NACL_SRPC_ARG_TYPE_DOUBLE_ARRAY: |
| 108 NACL_PRId32" outs)\n", caller, input_length, output_length)); | 78 case NACL_SRPC_ARG_TYPE_INT_ARRAY: |
| 109 | 79 case NACL_SRPC_ARG_TYPE_LONG_ARRAY: |
| 110 // Verify input/output parameter list length. | 80 case NACL_SRPC_ARG_TYPE_OBJECT: |
| 111 if (args.size() != params.SignatureLength()) { | 81 case NACL_SRPC_ARG_TYPE_HANDLE: |
| 112 return Error(call_name, caller, | 82 case NACL_SRPC_ARG_TYPE_VARIANT_ARRAY: |
| 113 "incompatible srpc parameter list", exception); | 83 case NACL_SRPC_ARG_TYPE_INVALID: |
| 114 } | 84 default: |
| 115 PLUGIN_PRINTF(("ScriptableHandle::%s (verified signature)\n", caller)); | 85 *exception = "variant array and invalid argument types are not supported"; |
| 116 | 86 } |
| 117 // Marshall input parameters. | 87 PLUGIN_PRINTF((" NaClSrpcArgToPPVar (return var=%s, exception=%s)\n", |
| 118 if (input_length > 0) { | 88 var.DebugString().c_str(), exception->DebugString().c_str())); |
| 119 assert(call_type != PROPERTY_GET); // expect no inputs for "get" | 89 return var; |
| 120 for (int i = 0; (i < NACL_SRPC_MAX_ARGS) && (inputs[i] != NULL); ++i) { | |
| 121 if (!PPVarToNaClSrpcArg(args[i], inputs[i], exception)) { | |
| 122 return Error(call_name, caller, | |
| 123 "srpc input marshalling failed", exception); | |
| 124 } | |
| 125 } | |
| 126 } | |
| 127 if (call_type == PROPERTY_SET) assert(input_length == 1); | |
| 128 PLUGIN_PRINTF(("ScriptableHandle::%s (marshalled inputs)\n", caller)); | |
| 129 | |
| 130 // Allocate array-typed output parameters. | |
| 131 if (args.size() > input_length) { | |
| 132 for (int i = 0; (i < NACL_SRPC_MAX_ARGS) && (outputs[i] != NULL); ++i) { | |
| 133 if (!PPVarToAllocateNaClSrpcArg(args[input_length + i], | |
| 134 outputs[i], exception)) { | |
| 135 return Error(call_name, caller, "srpc output array allocation failed", | |
| 136 exception); | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 PLUGIN_PRINTF(("ScriptableHandle::%s (output array allocation done)\n", | |
| 141 caller)); | |
| 142 | |
| 143 // Invoke. | |
| 144 if (!plugin->Invoke(id, call_type, ¶ms)) { | |
| 145 nacl::string err = nacl::string(caller) + "('" + call_name + "') failed\n"; | |
| 146 if (params.exception_string() != NULL) { | |
| 147 err = params.exception_string(); | |
| 148 } | |
| 149 *exception = pp::Var(err.c_str()); | |
| 150 return Error(call_name, caller, "invocation failed", exception); | |
| 151 } | |
| 152 PLUGIN_PRINTF(("ScriptableHandle::%s (invocation done)\n", caller)); | |
| 153 | |
| 154 // Marshall output parameters. | |
| 155 pp::Var retvar; | |
| 156 if (output_length > 0) { | |
| 157 assert(call_type != PROPERTY_SET); // expect no outputs for "set" | |
| 158 retvar = NaClSrpcArgToPPVar(outputs[0], plugin, exception); | |
| 159 if (output_length > 1) { | |
| 160 ArrayPpapi* array = new(std::nothrow) ArrayPpapi(plugin); | |
| 161 if (array == NULL) { | |
| 162 *exception = pp::Var("failed to allocate output array"); | |
| 163 } else { | |
| 164 array->SetProperty(pp::Var(0), retvar, exception); | |
| 165 for (int32_t i = 1; i < output_length; ++i) { | |
| 166 pp::Var v = NaClSrpcArgToPPVar(outputs[i], plugin, exception); | |
| 167 array->SetProperty(pp::Var(i), v, exception); | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 retvar = pp::VarPrivate(plugin, array); | |
| 172 } | |
| 173 if (!exception->is_undefined()) { | |
| 174 return Error(call_name, caller, "srpc output marshalling failed", | |
| 175 exception); | |
| 176 } | |
| 177 } | |
| 178 if (call_type == PROPERTY_GET) assert(output_length == 1); | |
| 179 return retvar; | |
| 180 } | 90 } |
| 181 | 91 |
| 182 } // namespace | 92 } // namespace |
| 183 | 93 |
| 184 ScriptableHandle::ScriptableHandle(Plugin* plugin) | 94 ScriptablePlugin::ScriptablePlugin(Plugin* plugin) |
| 185 : var_(NULL), num_unref_calls_(0), plugin_(plugin), desc_handle_(NULL) { | 95 : var_(NULL), num_unref_calls_(0), plugin_(plugin) { |
| 186 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p, plugin=%p)\n", | 96 PLUGIN_PRINTF(("ScriptablePlugin::ScriptablePlugin (this=%p, plugin=%p)\n", |
| 187 static_cast<void*>(this), | 97 static_cast<void*>(this), |
| 188 static_cast<void*>(plugin))); | 98 static_cast<void*>(plugin))); |
| 189 RememberValidHandle(this); | 99 } |
| 190 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p)\n", | 100 |
| 101 ScriptablePlugin::~ScriptablePlugin() { |
| 102 PLUGIN_PRINTF(("ScriptablePlugin::~ScriptablePlugin (this=%p)\n", |
| 191 static_cast<void*>(this))); | 103 static_cast<void*>(this))); |
| 192 } | 104 PLUGIN_PRINTF(("ScriptablePlugin::~ScriptablePlugin (this=%p, return)\n", |
| 193 | |
| 194 ScriptableHandle::ScriptableHandle(DescBasedHandle* desc_handle) | |
| 195 : var_(NULL), num_unref_calls_(0), plugin_(NULL), desc_handle_(desc_handle) { | |
| 196 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p," | |
| 197 " desc_handle=%p)\n", | |
| 198 static_cast<void*>(this), | |
| 199 static_cast<void*>(desc_handle))); | |
| 200 RememberValidHandle(this); | |
| 201 PLUGIN_PRINTF(("ScriptableHandle::ScriptableHandle (this=%p)\n", | |
| 202 static_cast<void*>(this))); | |
| 203 } | |
| 204 | |
| 205 ScriptableHandle::~ScriptableHandle() { | |
| 206 PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle (this=%p)\n", | |
| 207 static_cast<void*>(this))); | |
| 208 // If the set was empty, just return. | |
| 209 if (NULL == g_ValidHandles) { | |
| 210 return; | |
| 211 } | |
| 212 // Remove the scriptable handle from the set of valid handles. | |
| 213 g_ValidHandles->erase(this); | |
| 214 // If handle is a plugin, the browser is deleting it (and might have | |
| 215 // already done so). Otherwise, delete here. | |
| 216 if (desc_handle_ != NULL) { | |
| 217 PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle " | |
| 218 "(this=%p, delete desc_handle=%p)\n", | |
| 219 static_cast<void*>(this), static_cast<void*>(desc_handle_))); | |
| 220 delete desc_handle_; | |
| 221 desc_handle_ = NULL; | |
| 222 } | |
| 223 PLUGIN_PRINTF(("ScriptableHandle::~ScriptableHandle (this=%p, return)\n", | |
| 224 static_cast<void*>(this))); | 105 static_cast<void*>(this))); |
| 225 } | 106 } |
| 226 | 107 |
| 227 // Check that an object is a validly created ScriptableHandle. | 108 void ScriptablePlugin::Unref(ScriptablePlugin** handle) { |
| 228 bool ScriptableHandle::is_valid(const ScriptableHandle* handle) { | |
| 229 PLUGIN_PRINTF(("ScriptableHandle::is_valid (handle=%p)\n", | |
| 230 static_cast<void*>(const_cast<ScriptableHandle*>(handle)))); | |
| 231 if (NULL == g_ValidHandles) { | |
| 232 PLUGIN_PRINTF(("ScriptableHandle::is_valid (return 0)\n")); | |
| 233 return false; | |
| 234 } | |
| 235 size_t count = | |
| 236 g_ValidHandles->count(static_cast<const ScriptableHandle*>(handle)); | |
| 237 PLUGIN_PRINTF(("ScriptableHandle::is_valid (handle=%p, count=%" | |
| 238 NACL_PRIuS")\n", | |
| 239 static_cast<void*>(const_cast<ScriptableHandle*>(handle)), | |
| 240 count)); | |
| 241 return 0 != count; | |
| 242 } | |
| 243 | |
| 244 void ScriptableHandle::Unref(ScriptableHandle** handle) { | |
| 245 if (*handle != NULL) { | 109 if (*handle != NULL) { |
| 246 (*handle)->Unref(); | 110 (*handle)->Unref(); |
| 247 *handle = NULL; | 111 *handle = NULL; |
| 248 } | 112 } |
| 249 } | 113 } |
| 250 | 114 |
| 251 ScriptableHandle* ScriptableHandle::NewPlugin(Plugin* plugin) { | 115 ScriptablePlugin* ScriptablePlugin::NewPlugin(Plugin* plugin) { |
| 252 PLUGIN_PRINTF(("ScriptableHandle::NewPlugin (plugin=%p)\n", | 116 PLUGIN_PRINTF(("ScriptablePlugin::NewPlugin (plugin=%p)\n", |
| 253 static_cast<void*>(plugin))); | 117 static_cast<void*>(plugin))); |
| 254 if (plugin == NULL) { | 118 if (plugin == NULL) { |
| 255 return NULL; | 119 return NULL; |
| 256 } | 120 } |
| 257 ScriptableHandle* scriptable_handle = | 121 ScriptablePlugin* scriptable_plugin = new ScriptablePlugin(plugin); |
| 258 new(std::nothrow) ScriptableHandle(plugin); | 122 if (scriptable_plugin == NULL) { |
| 259 if (scriptable_handle == NULL) { | |
| 260 return NULL; | 123 return NULL; |
| 261 } | 124 } |
| 262 PLUGIN_PRINTF(("ScriptableHandle::NewPlugin (return %p)\n", | 125 PLUGIN_PRINTF(("ScriptablePlugin::NewPlugin (return %p)\n", |
| 263 static_cast<void*>(scriptable_handle))); | 126 static_cast<void*>(scriptable_plugin))); |
| 264 return scriptable_handle; | 127 return scriptable_plugin; |
| 265 } | 128 } |
| 266 | 129 |
| 267 | 130 bool ScriptablePlugin::HasProperty(const pp::Var& name, pp::Var* exception) { |
| 268 ScriptableHandle* ScriptableHandle::NewDescHandle( | |
| 269 DescBasedHandle* desc_handle) { | |
| 270 PLUGIN_PRINTF(("ScriptableHandle::NewDescHandle (desc_handle=%p)\n", | |
| 271 static_cast<void*>(desc_handle))); | |
| 272 if (desc_handle == NULL) { | |
| 273 return NULL; | |
| 274 } | |
| 275 ScriptableHandle* scriptable_handle = | |
| 276 new(std::nothrow) ScriptableHandle(desc_handle); | |
| 277 if (scriptable_handle == NULL) { | |
| 278 return NULL; | |
| 279 } | |
| 280 PLUGIN_PRINTF(("ScriptableHandle::NewDescHandle (return %p)\n", | |
| 281 static_cast<void*>(scriptable_handle))); | |
| 282 return scriptable_handle; | |
| 283 } | |
| 284 | |
| 285 | |
| 286 bool ScriptableHandle::HasProperty(const pp::Var& name, pp::Var* exception) { | |
| 287 UNREFERENCED_PARAMETER(exception); | 131 UNREFERENCED_PARAMETER(exception); |
| 288 PLUGIN_PRINTF(("ScriptableHandle::HasProperty (this=%p, name=%s)\n", | 132 PLUGIN_PRINTF(("ScriptablePlugin::HasProperty (this=%p, name=%s)\n", |
| 289 static_cast<void*>(this), name.DebugString().c_str())); | 133 static_cast<void*>(this), name.DebugString().c_str())); |
| 290 if (plugin_ == NULL) { | 134 if (plugin_ == NULL) { |
| 291 return false; | 135 return false; |
| 292 } | 136 } |
| 293 if (!name.is_string() && !name.is_int()) | 137 if (!name.is_string() && !name.is_int()) |
| 294 return false; | 138 return false; |
| 295 bool has_property = HasCallType(plugin_, | 139 bool has_property = plugin_->HasProperty(name.AsString()); |
| 296 PROPERTY_GET, | 140 PLUGIN_PRINTF(("ScriptablePlugin::HasProperty (has_property=%d)\n", |
| 297 name.AsString(), | |
| 298 "HasProperty"); | |
| 299 PLUGIN_PRINTF(("ScriptableHandle::HasProperty (has_property=%d)\n", | |
| 300 has_property)); | 141 has_property)); |
| 301 return has_property; | 142 return has_property; |
| 302 } | 143 } |
| 303 | 144 |
| 304 | 145 |
| 305 bool ScriptableHandle::HasMethod(const pp::Var& name, pp::Var* exception) { | 146 bool ScriptablePlugin::HasMethod(const pp::Var& name, pp::Var* exception) { |
| 306 UNREFERENCED_PARAMETER(exception); | 147 UNREFERENCED_PARAMETER(exception); |
| 307 PLUGIN_PRINTF(("ScriptableHandle::HasMethod (this=%p, name='%s')\n", | 148 PLUGIN_PRINTF(("ScriptablePlugin::HasMethod (this=%p, name='%s')\n", |
| 308 static_cast<void*>(this), name.DebugString().c_str())); | 149 static_cast<void*>(this), name.DebugString().c_str())); |
| 309 if (plugin_ == NULL) { | 150 return false; |
| 310 return false; | 151 } |
| 311 } | 152 |
| 312 if (!name.is_string()) | 153 |
| 313 return false; | 154 pp::Var ScriptablePlugin::GetProperty(const pp::Var& name, |
| 314 bool has_method = HasCallType(plugin_, | |
| 315 METHOD_CALL, | |
| 316 name.AsString(), | |
| 317 "HasMethod"); | |
| 318 PLUGIN_PRINTF(("ScriptableHandle::HasMethod (has_method=%d)\n", | |
| 319 has_method)); | |
| 320 return has_method; | |
| 321 } | |
| 322 | |
| 323 | |
| 324 pp::Var ScriptableHandle::GetProperty(const pp::Var& name, | |
| 325 pp::Var* exception) { | 155 pp::Var* exception) { |
| 326 PLUGIN_PRINTF(("ScriptableHandle::GetProperty (name=%s)\n", | 156 PLUGIN_PRINTF(("ScriptablePlugin::GetProperty (name=%s)\n", |
| 327 name.DebugString().c_str())); | 157 name.DebugString().c_str())); |
| 328 if (plugin_ == NULL) { | 158 if (plugin_ == NULL) { |
| 329 return pp::Var(); | 159 return pp::Var(); |
| 330 } | 160 } |
| 331 pp::Var property = Invoke(plugin_, | 161 // Get the property. |
| 332 PROPERTY_GET, | 162 NaClSrpcArg prop_value; |
| 333 NameAsString(name), | 163 nacl::string prop_name = NameAsString(name); |
| 334 "GetProperty", | 164 if (!plugin_->GetProperty(prop_name, &prop_value)) { |
| 335 std::vector<pp::Var>(), exception); | 165 return Error(prop_name, "GetProperty", "invocation failed", exception); |
| 336 PLUGIN_PRINTF(("ScriptableHandle::GetProperty (property=%s)\n", | 166 } |
| 167 PLUGIN_PRINTF(("ScriptablePlugin::GetProperty (invocation done)\n")); |
| 168 // Marshall output parameter. |
| 169 pp::Var property = NaClSrpcArgToPPVar(&prop_value, exception); |
| 170 if (!exception->is_undefined()) { |
| 171 return Error(prop_name, "GetProperty", "output marshalling failed", |
| 172 exception); |
| 173 } |
| 174 PLUGIN_PRINTF(("ScriptablePlugin::GetProperty (property=%s)\n", |
| 337 property.DebugString().c_str())); | 175 property.DebugString().c_str())); |
| 338 return property; | 176 return property; |
| 339 } | 177 } |
| 340 | 178 |
| 341 | 179 |
| 342 void ScriptableHandle::SetProperty(const pp::Var& name, | 180 void ScriptablePlugin::SetProperty(const pp::Var& name, |
| 343 const pp::Var& value, | 181 const pp::Var& value, |
| 344 pp::Var* exception) { | 182 pp::Var* exception) { |
| 345 PLUGIN_PRINTF(("ScriptableHandle::SetProperty (name=%s, value=%s)\n", | 183 PLUGIN_PRINTF(("ScriptablePlugin::SetProperty (name=%s, value=%s)\n", |
| 346 name.DebugString().c_str(), value.DebugString().c_str())); | 184 name.DebugString().c_str(), value.DebugString().c_str())); |
| 347 if (plugin_ == NULL) { | 185 Error("SetProperty", name.DebugString().c_str(), |
| 348 return; | 186 "property setting is not supported", exception); |
| 349 } | 187 } |
| 350 std::vector<pp::Var> args; | 188 |
| 351 args.push_back(pp::Var(pp::Var::DontManage(), value.pp_var())); | 189 |
| 352 Invoke(plugin_, | 190 void ScriptablePlugin::RemoveProperty(const pp::Var& name, |
| 353 PROPERTY_SET, | |
| 354 NameAsString(name), | |
| 355 "SetProperty", | |
| 356 args, | |
| 357 exception); | |
| 358 std::string exception_string("NULL"); | |
| 359 if (!exception->is_undefined()) { | |
| 360 exception_string = exception->DebugString(); | |
| 361 } | |
| 362 PLUGIN_PRINTF(("ScriptableHandle::SetProperty (exception=%s)\n", | |
| 363 exception_string.c_str())); | |
| 364 } | |
| 365 | |
| 366 | |
| 367 void ScriptableHandle::RemoveProperty(const pp::Var& name, | |
| 368 pp::Var* exception) { | 191 pp::Var* exception) { |
| 369 PLUGIN_PRINTF(("ScriptableHandle::RemoveProperty (name=%s)\n", | 192 PLUGIN_PRINTF(("ScriptablePlugin::RemoveProperty (name=%s)\n", |
| 370 name.DebugString().c_str())); | 193 name.DebugString().c_str())); |
| 371 Error(NameAsString(name), "RemoveProperty", | 194 Error(NameAsString(name), "RemoveProperty", |
| 372 "property removal is not supported", exception); | 195 "property removal is not supported", exception); |
| 373 } | 196 } |
| 374 | 197 |
| 375 // TODO(polina): should methods also be added? | 198 void ScriptablePlugin::GetAllPropertyNames(std::vector<pp::Var>* properties, |
| 376 // This is currently never called and the exact semantics is not clear. | |
| 377 // http://code.google.com/p/chromium/issues/detail?id=51089 | |
| 378 void ScriptableHandle::GetAllPropertyNames(std::vector<pp::Var>* properties, | |
| 379 pp::Var* exception) { | 199 pp::Var* exception) { |
| 200 PLUGIN_PRINTF(("ScriptablePlugin::GetAllPropertyNames ()\n")); |
| 201 UNREFERENCED_PARAMETER(properties); |
| 380 UNREFERENCED_PARAMETER(exception); | 202 UNREFERENCED_PARAMETER(exception); |
| 381 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames ()\n")); | 203 Error("GetAllPropertyNames", "", "GetAllPropertyNames is not supported", |
| 382 if (plugin_ == NULL) { | 204 exception); |
| 383 return; | 205 } |
| 384 } | 206 |
| 385 std::vector<uintptr_t>* ids = plugin_->GetPropertyIdentifiers(); | 207 |
| 386 if (ids == NULL) { | 208 pp::Var ScriptablePlugin::Call(const pp::Var& name, |
| 387 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames " | |
| 388 "(ids=%p)\n", reinterpret_cast<void*>(ids))); | |
| 389 return; | |
| 390 } | |
| 391 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames " | |
| 392 "(ids->size()=%"NACL_PRIuS")\n", ids->size())); | |
| 393 for (size_t i = 0; i < ids->size(); ++i) { | |
| 394 nacl::string name = | |
| 395 plugin_->browser_interface()->IdentifierToString(ids->at(i)); | |
| 396 properties->push_back(pp::Var(name)); | |
| 397 } | |
| 398 PLUGIN_PRINTF(("ScriptableHandle::GetAllPropertyNames " | |
| 399 "(properties=%"NACL_PRIuS")\n", properties->size())); | |
| 400 } | |
| 401 | |
| 402 | |
| 403 pp::Var ScriptableHandle::Call(const pp::Var& name, | |
| 404 const std::vector<pp::Var>& args, | 209 const std::vector<pp::Var>& args, |
| 405 pp::Var* exception) { | 210 pp::Var* exception) { |
| 406 PLUGIN_PRINTF(("ScriptableHandle::Call (name=%s, %"NACL_PRIuS | 211 PLUGIN_PRINTF(("ScriptablePlugin::Call (name=%s, %"NACL_PRIuS |
| 407 " args)\n", name.DebugString().c_str(), args.size())); | 212 " args)\n", name.DebugString().c_str(), args.size())); |
| 408 if (plugin_ == NULL) { | 213 return Error("Call", name.DebugString().c_str(), |
| 409 return pp::Var(); | 214 "method invocation is not supported", exception); |
| 410 } | 215 } |
| 411 if (name.is_undefined()) // invoke default | 216 |
| 412 return pp::Var(); | 217 |
| 413 assert(name.is_string()); | 218 pp::Var ScriptablePlugin::Construct(const std::vector<pp::Var>& args, |
| 414 pp::Var return_var = Invoke(plugin_, | |
| 415 METHOD_CALL, | |
| 416 name.AsString(), | |
| 417 "Call", | |
| 418 args, | |
| 419 exception); | |
| 420 PLUGIN_PRINTF(("ScriptableHandle::Call (return=%s)\n", | |
| 421 return_var.DebugString().c_str())); | |
| 422 return return_var; | |
| 423 } | |
| 424 | |
| 425 | |
| 426 pp::Var ScriptableHandle::Construct(const std::vector<pp::Var>& args, | |
| 427 pp::Var* exception) { | 219 pp::Var* exception) { |
| 428 PLUGIN_PRINTF(("ScriptableHandle::Construct (%"NACL_PRIuS | 220 PLUGIN_PRINTF(("ScriptablePlugin::Construct (%"NACL_PRIuS |
| 429 " args)\n", args.size())); | 221 " args)\n", args.size())); |
| 430 return Error("constructor", "Construct", "constructor is not supported", | 222 return Error("constructor", "Construct", "constructor is not supported", |
| 431 exception); | 223 exception); |
| 432 } | 224 } |
| 433 | 225 |
| 434 | 226 |
| 435 ScriptableHandle* ScriptableHandle::AddRef() { | 227 ScriptablePlugin* ScriptablePlugin::AddRef() { |
| 436 // This is called when we are about to share this object with the browser, | 228 // This is called when we are about to share this object with the browser, |
| 437 // and we need to make sure we have an internal plugin reference, so this | 229 // and we need to make sure we have an internal plugin reference, so this |
| 438 // object doesn't get deallocated when the browser discards its references. | 230 // object doesn't get deallocated when the browser discards its references. |
| 439 if (var_ == NULL) { | 231 if (var_ == NULL) { |
| 440 var_ = new(std::nothrow) pp::VarPrivate(plugin_, this); | 232 var_ = new pp::VarPrivate(plugin_, this); |
| 441 CHECK(var_ != NULL); | 233 CHECK(var_ != NULL); |
| 442 } | 234 } |
| 443 PLUGIN_PRINTF(("ScriptableHandle::AddRef (this=%p, var=%p)\n", | 235 PLUGIN_PRINTF(("ScriptablePlugin::AddRef (this=%p, var=%p)\n", |
| 444 static_cast<void*>(this), static_cast<void*>(var_))); | 236 static_cast<void*>(this), static_cast<void*>(var_))); |
| 445 return this; | 237 return this; |
| 446 } | 238 } |
| 447 | 239 |
| 448 | 240 |
| 449 void ScriptableHandle::Unref() { | 241 void ScriptablePlugin::Unref() { |
| 450 // We should have no more than one internal owner of this object, so this | 242 // We should have no more than one internal owner of this object, so this |
| 451 // should be called no more than once. | 243 // should be called no more than once. |
| 452 CHECK(++num_unref_calls_ == 1); | 244 CHECK(++num_unref_calls_ == 1); |
| 453 PLUGIN_PRINTF(("ScriptableHandle::Unref (this=%p, var=%p)\n", | 245 PLUGIN_PRINTF(("ScriptablePlugin::Unref (this=%p, var=%p)\n", |
| 454 static_cast<void*>(this), static_cast<void*>(var_))); | 246 static_cast<void*>(this), static_cast<void*>(var_))); |
| 455 if (var_ != NULL) { | 247 if (var_ != NULL) { |
| 456 // We have shared this with the browser while keeping our own var | 248 // We have shared this with the browser while keeping our own var |
| 457 // reference, but we no longer need ours. If the browser has copies, | 249 // reference, but we no longer need ours. If the browser has copies, |
| 458 // it will clean things up later, otherwise this object will get | 250 // it will clean things up later, otherwise this object will get |
| 459 // deallocated right away. | 251 // deallocated right away. |
| 460 PLUGIN_PRINTF(("ScriptableHandle::Unref (delete var)\n")); | 252 PLUGIN_PRINTF(("ScriptablePlugin::Unref (delete var)\n")); |
| 461 pp::Var* var = var_; | 253 pp::Var* var = var_; |
| 462 var_ = NULL; | 254 var_ = NULL; |
| 463 delete var; | 255 delete var; |
| 464 } else { | 256 } else { |
| 465 // Neither the browser nor plugin ever var referenced this object, | 257 // Neither the browser nor plugin ever var referenced this object, |
| 466 // so it can safely discarded. | 258 // so it can safely discarded. |
| 467 PLUGIN_PRINTF(("ScriptableHandle::Unref (delete this)\n")); | 259 PLUGIN_PRINTF(("ScriptablePlugin::Unref (delete this)\n")); |
| 468 CHECK(var_ == NULL); | 260 CHECK(var_ == NULL); |
| 469 delete this; | 261 delete this; |
| 470 } | 262 } |
| 471 } | 263 } |
| 472 | 264 |
| 473 | 265 |
| 474 } // namespace plugin | 266 } // namespace plugin |
| OLD | NEW |