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