OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "webkit/plugins/ppapi/npapi_glue.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/ref_counted.h" |
| 9 #include "base/string_util.h" |
| 10 #include "webkit/plugins/ppapi/plugin_object.h" |
| 11 #include "webkit/plugins/ppapi/var.h" |
| 12 #include "third_party/npapi/bindings/npapi.h" |
| 13 #include "third_party/npapi/bindings/npruntime.h" |
| 14 #include "third_party/WebKit/WebKit/chromium/public/WebBindings.h" |
| 15 |
| 16 using WebKit::WebBindings; |
| 17 |
| 18 namespace webkit { |
| 19 namespace ppapi { |
| 20 |
| 21 namespace { |
| 22 |
| 23 const char kInvalidPluginValue[] = "Error: Plugin returned invalid value."; |
| 24 |
| 25 } // namespace |
| 26 |
| 27 // Utilities ------------------------------------------------------------------- |
| 28 |
| 29 bool PPVarToNPVariant(PP_Var var, NPVariant* result) { |
| 30 switch (var.type) { |
| 31 case PP_VARTYPE_UNDEFINED: |
| 32 VOID_TO_NPVARIANT(*result); |
| 33 break; |
| 34 case PP_VARTYPE_NULL: |
| 35 NULL_TO_NPVARIANT(*result); |
| 36 break; |
| 37 case PP_VARTYPE_BOOL: |
| 38 BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result); |
| 39 break; |
| 40 case PP_VARTYPE_INT32: |
| 41 INT32_TO_NPVARIANT(var.value.as_int, *result); |
| 42 break; |
| 43 case PP_VARTYPE_DOUBLE: |
| 44 DOUBLE_TO_NPVARIANT(var.value.as_double, *result); |
| 45 break; |
| 46 case PP_VARTYPE_STRING: { |
| 47 scoped_refptr<StringVar> string(StringVar::FromPPVar(var)); |
| 48 if (!string) { |
| 49 VOID_TO_NPVARIANT(*result); |
| 50 return false; |
| 51 } |
| 52 const std::string& value = string->value(); |
| 53 STRINGN_TO_NPVARIANT(base::strdup(value.c_str()), value.size(), *result); |
| 54 break; |
| 55 } |
| 56 case PP_VARTYPE_OBJECT: { |
| 57 scoped_refptr<ObjectVar> object(ObjectVar::FromPPVar(var)); |
| 58 if (!object) { |
| 59 VOID_TO_NPVARIANT(*result); |
| 60 return false; |
| 61 } |
| 62 OBJECT_TO_NPVARIANT(WebBindings::retainObject(object->np_object()), |
| 63 *result); |
| 64 break; |
| 65 } |
| 66 } |
| 67 return true; |
| 68 } |
| 69 |
| 70 // PPResultAndExceptionToNPResult ---------------------------------------------- |
| 71 |
| 72 PPResultAndExceptionToNPResult::PPResultAndExceptionToNPResult( |
| 73 NPObject* object_var, |
| 74 NPVariant* np_result) |
| 75 : object_var_(object_var), |
| 76 np_result_(np_result), |
| 77 exception_(PP_MakeUndefined()), |
| 78 success_(false), |
| 79 checked_exception_(false) { |
| 80 } |
| 81 |
| 82 PPResultAndExceptionToNPResult::~PPResultAndExceptionToNPResult() { |
| 83 // The user should have called SetResult or CheckExceptionForNoResult |
| 84 // before letting this class go out of scope, or the exception will have |
| 85 // been lost. |
| 86 DCHECK(checked_exception_); |
| 87 |
| 88 ObjectVar::PluginReleasePPVar(exception_); |
| 89 } |
| 90 |
| 91 // Call this with the return value of the PPAPI function. It will convert |
| 92 // the result to the NPVariant output parameter and pass any exception on to |
| 93 // the JS engine. It will update the success flag and return it. |
| 94 bool PPResultAndExceptionToNPResult::SetResult(PP_Var result) { |
| 95 DCHECK(!checked_exception_); // Don't call more than once. |
| 96 DCHECK(np_result_); // Should be expecting a result. |
| 97 |
| 98 checked_exception_ = true; |
| 99 |
| 100 if (has_exception()) { |
| 101 ThrowException(); |
| 102 success_ = false; |
| 103 } else if (!PPVarToNPVariant(result, np_result_)) { |
| 104 WebBindings::setException(object_var_, kInvalidPluginValue); |
| 105 success_ = false; |
| 106 } else { |
| 107 success_ = true; |
| 108 } |
| 109 |
| 110 // No matter what happened, we need to release the reference to the |
| 111 // value passed in. On success, a reference to this value will be in |
| 112 // the np_result_. |
| 113 Var::PluginReleasePPVar(result); |
| 114 return success_; |
| 115 } |
| 116 |
| 117 // Call this after calling a PPAPI function that could have set the |
| 118 // exception. It will pass the exception on to the JS engine and update |
| 119 // the success flag. |
| 120 // |
| 121 // The success flag will be returned. |
| 122 bool PPResultAndExceptionToNPResult::CheckExceptionForNoResult() { |
| 123 DCHECK(!checked_exception_); // Don't call more than once. |
| 124 DCHECK(!np_result_); // Can't have a result when doing this. |
| 125 |
| 126 checked_exception_ = true; |
| 127 |
| 128 if (has_exception()) { |
| 129 ThrowException(); |
| 130 success_ = false; |
| 131 return false; |
| 132 } |
| 133 success_ = true; |
| 134 return true; |
| 135 } |
| 136 |
| 137 // Call this to ignore any exception. This prevents the DCHECK from failing |
| 138 // in the destructor. |
| 139 void PPResultAndExceptionToNPResult::IgnoreException() { |
| 140 checked_exception_ = true; |
| 141 } |
| 142 |
| 143 // Throws the current exception to JS. The exception must be set. |
| 144 void PPResultAndExceptionToNPResult::ThrowException() { |
| 145 scoped_refptr<StringVar> string(StringVar::FromPPVar(exception_)); |
| 146 if (string) { |
| 147 WebBindings::setException(object_var_, string->value().c_str()); |
| 148 } |
| 149 } |
| 150 |
| 151 // PPVarArrayFromNPVariantArray ------------------------------------------------ |
| 152 |
| 153 PPVarArrayFromNPVariantArray::PPVarArrayFromNPVariantArray(PluginModule* module, |
| 154 size_t size, |
| 155 const NPVariant* variants) |
| 156 : size_(size) { |
| 157 if (size_ > 0) { |
| 158 array_.reset(new PP_Var[size_]); |
| 159 for (size_t i = 0; i < size_; i++) |
| 160 array_[i] = Var::NPVariantToPPVar(module, &variants[i]); |
| 161 } |
| 162 } |
| 163 |
| 164 PPVarArrayFromNPVariantArray::~PPVarArrayFromNPVariantArray() { |
| 165 for (size_t i = 0; i < size_; i++) |
| 166 Var::PluginReleasePPVar(array_[i]); |
| 167 } |
| 168 |
| 169 // PPVarFromNPObject ----------------------------------------------------------- |
| 170 |
| 171 PPVarFromNPObject::PPVarFromNPObject(PluginModule* module, NPObject* object) |
| 172 : var_(ObjectVar::NPObjectToPPVar(module, object)) { |
| 173 } |
| 174 |
| 175 PPVarFromNPObject::~PPVarFromNPObject() { |
| 176 Var::PluginReleasePPVar(var_); |
| 177 } |
| 178 |
| 179 // NPObjectAccessorWithIdentifier ---------------------------------------------- |
| 180 |
| 181 NPObjectAccessorWithIdentifier::NPObjectAccessorWithIdentifier( |
| 182 NPObject* object, |
| 183 NPIdentifier identifier, |
| 184 bool allow_integer_identifier) |
| 185 : object_(PluginObject::FromNPObject(object)), |
| 186 identifier_(PP_MakeUndefined()) { |
| 187 if (object_) { |
| 188 identifier_ = Var::NPIdentifierToPPVar(object_->module(), identifier); |
| 189 if (identifier_.type == PP_VARTYPE_INT32 && !allow_integer_identifier) |
| 190 identifier_.type = PP_VARTYPE_UNDEFINED; // Mark it invalid. |
| 191 } |
| 192 } |
| 193 |
| 194 NPObjectAccessorWithIdentifier::~NPObjectAccessorWithIdentifier() { |
| 195 Var::PluginReleasePPVar(identifier_); |
| 196 } |
| 197 |
| 198 } // namespace ppapi |
| 199 } // namespace webkit |
OLD | NEW |