OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 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 "content/shell/renderer/test_runner/CppVariant.h" |
| 6 |
| 7 #include <limits> |
| 8 #include "content/shell/renderer/test_runner/TestCommon.h" |
| 9 |
| 10 using namespace blink; |
| 11 using namespace std; |
| 12 |
| 13 namespace WebTestRunner { |
| 14 |
| 15 CppVariant::CppVariant() |
| 16 { |
| 17 type = NPVariantType_Null; |
| 18 } |
| 19 |
| 20 // Note that Set() performs a deep copy, which is necessary to safely |
| 21 // call FreeData() on the value in the destructor. |
| 22 CppVariant::CppVariant(const CppVariant& original) |
| 23 { |
| 24 type = NPVariantType_Null; |
| 25 set(original); |
| 26 } |
| 27 |
| 28 // See comment for copy constructor, above. |
| 29 CppVariant& CppVariant::operator=(const CppVariant& original) |
| 30 { |
| 31 if (&original != this) |
| 32 set(original); |
| 33 return *this; |
| 34 } |
| 35 |
| 36 CppVariant::~CppVariant() |
| 37 { |
| 38 freeData(); |
| 39 } |
| 40 |
| 41 void CppVariant::freeData() |
| 42 { |
| 43 WebBindings::releaseVariantValue(this); |
| 44 } |
| 45 |
| 46 bool CppVariant::isEqual(const CppVariant& other) const |
| 47 { |
| 48 if (type != other.type) |
| 49 return false; |
| 50 |
| 51 switch (type) { |
| 52 case NPVariantType_Bool: |
| 53 return (value.boolValue == other.value.boolValue); |
| 54 case NPVariantType_Int32: |
| 55 return (value.intValue == other.value.intValue); |
| 56 case NPVariantType_Double: |
| 57 return (value.doubleValue == other.value.doubleValue); |
| 58 case NPVariantType_String: { |
| 59 const NPString *this_value = &value.stringValue; |
| 60 const NPString *other_value = &other.value.stringValue; |
| 61 uint32_t len = this_value->UTF8Length; |
| 62 return len == other_value->UTF8Length |
| 63 && !strncmp(this_value->UTF8Characters, |
| 64 other_value->UTF8Characters, len); |
| 65 } |
| 66 case NPVariantType_Null: |
| 67 case NPVariantType_Void: |
| 68 return true; |
| 69 case NPVariantType_Object: { |
| 70 NPObject* thisValue = value.objectValue; |
| 71 NPObject* otherValue = other.value.objectValue; |
| 72 return thisValue->_class == otherValue->_class |
| 73 && thisValue->referenceCount == otherValue->referenceCount; |
| 74 } |
| 75 } |
| 76 return false; |
| 77 } |
| 78 |
| 79 void CppVariant::copyToNPVariant(NPVariant* result) const |
| 80 { |
| 81 result->type = type; |
| 82 switch (type) { |
| 83 case NPVariantType_Bool: |
| 84 result->value.boolValue = value.boolValue; |
| 85 break; |
| 86 case NPVariantType_Int32: |
| 87 result->value.intValue = value.intValue; |
| 88 break; |
| 89 case NPVariantType_Double: |
| 90 result->value.doubleValue = value.doubleValue; |
| 91 break; |
| 92 case NPVariantType_String: |
| 93 WebBindings::initializeVariantWithStringCopy(result, &value.stringValue)
; |
| 94 break; |
| 95 case NPVariantType_Null: |
| 96 case NPVariantType_Void: |
| 97 // Nothing to set. |
| 98 break; |
| 99 case NPVariantType_Object: |
| 100 result->type = NPVariantType_Object; |
| 101 result->value.objectValue = WebBindings::retainObject(value.objectValue)
; |
| 102 break; |
| 103 } |
| 104 } |
| 105 |
| 106 void CppVariant::set(const NPVariant& newValue) |
| 107 { |
| 108 freeData(); |
| 109 switch (newValue.type) { |
| 110 case NPVariantType_Bool: |
| 111 set(newValue.value.boolValue); |
| 112 break; |
| 113 case NPVariantType_Int32: |
| 114 set(newValue.value.intValue); |
| 115 break; |
| 116 case NPVariantType_Double: |
| 117 set(newValue.value.doubleValue); |
| 118 break; |
| 119 case NPVariantType_String: |
| 120 set(newValue.value.stringValue); |
| 121 break; |
| 122 case NPVariantType_Null: |
| 123 case NPVariantType_Void: |
| 124 type = newValue.type; |
| 125 break; |
| 126 case NPVariantType_Object: |
| 127 set(newValue.value.objectValue); |
| 128 break; |
| 129 } |
| 130 } |
| 131 |
| 132 void CppVariant::setNull() |
| 133 { |
| 134 freeData(); |
| 135 type = NPVariantType_Null; |
| 136 } |
| 137 |
| 138 void CppVariant::set(bool newValue) |
| 139 { |
| 140 freeData(); |
| 141 type = NPVariantType_Bool; |
| 142 value.boolValue = newValue; |
| 143 } |
| 144 |
| 145 void CppVariant::set(int32_t newValue) |
| 146 { |
| 147 freeData(); |
| 148 type = NPVariantType_Int32; |
| 149 value.intValue = newValue; |
| 150 } |
| 151 |
| 152 void CppVariant::set(double newValue) |
| 153 { |
| 154 freeData(); |
| 155 type = NPVariantType_Double; |
| 156 value.doubleValue = newValue; |
| 157 } |
| 158 |
| 159 // The newValue must be a null-terminated string. |
| 160 void CppVariant::set(const char* newValue) |
| 161 { |
| 162 freeData(); |
| 163 type = NPVariantType_String; |
| 164 NPString newString = {newValue, |
| 165 static_cast<uint32_t>(strlen(newValue))}; |
| 166 WebBindings::initializeVariantWithStringCopy(this, &newString); |
| 167 } |
| 168 |
| 169 void CppVariant::set(const string& newValue) |
| 170 { |
| 171 freeData(); |
| 172 type = NPVariantType_String; |
| 173 NPString newString = {newValue.data(), |
| 174 static_cast<uint32_t>(newValue.size())}; |
| 175 WebBindings::initializeVariantWithStringCopy(this, &newString); |
| 176 } |
| 177 |
| 178 void CppVariant::set(const NPString& newValue) |
| 179 { |
| 180 freeData(); |
| 181 type = NPVariantType_String; |
| 182 WebBindings::initializeVariantWithStringCopy(this, &newValue); |
| 183 } |
| 184 |
| 185 void CppVariant::set(NPObject* newValue) |
| 186 { |
| 187 freeData(); |
| 188 type = NPVariantType_Object; |
| 189 value.objectValue = WebBindings::retainObject(newValue); |
| 190 } |
| 191 |
| 192 string CppVariant::toString() const |
| 193 { |
| 194 BLINK_ASSERT(isString()); |
| 195 return string(value.stringValue.UTF8Characters, |
| 196 value.stringValue.UTF8Length); |
| 197 } |
| 198 |
| 199 int32_t CppVariant::toInt32() const |
| 200 { |
| 201 if (isInt32()) |
| 202 return value.intValue; |
| 203 if (isDouble()) |
| 204 return static_cast<int32_t>(value.doubleValue); |
| 205 BLINK_ASSERT_NOT_REACHED(); |
| 206 return 0; |
| 207 } |
| 208 |
| 209 double CppVariant::toDouble() const |
| 210 { |
| 211 if (isInt32()) |
| 212 return static_cast<double>(value.intValue); |
| 213 if (isDouble()) |
| 214 return value.doubleValue; |
| 215 BLINK_ASSERT_NOT_REACHED(); |
| 216 return 0; |
| 217 } |
| 218 |
| 219 bool CppVariant::toBoolean() const |
| 220 { |
| 221 BLINK_ASSERT(isBool()); |
| 222 return value.boolValue; |
| 223 } |
| 224 |
| 225 vector<string> CppVariant::toStringVector() const |
| 226 { |
| 227 |
| 228 BLINK_ASSERT(isObject()); |
| 229 vector<string> stringVector; |
| 230 NPObject* npValue = value.objectValue; |
| 231 NPIdentifier lengthId = WebBindings::getStringIdentifier("length"); |
| 232 |
| 233 if (!WebBindings::hasProperty(0, npValue, lengthId)) |
| 234 return stringVector; |
| 235 |
| 236 NPVariant lengthValue; |
| 237 if (!WebBindings::getProperty(0, npValue, lengthId, &lengthValue)) |
| 238 return stringVector; |
| 239 |
| 240 int length = 0; |
| 241 // The length is a double in some cases. |
| 242 if (NPVARIANT_IS_DOUBLE(lengthValue)) |
| 243 length = static_cast<int>(NPVARIANT_TO_DOUBLE(lengthValue)); |
| 244 else if (NPVARIANT_IS_INT32(lengthValue)) |
| 245 length = NPVARIANT_TO_INT32(lengthValue); |
| 246 WebBindings::releaseVariantValue(&lengthValue); |
| 247 |
| 248 // For sanity, only allow 100 items. |
| 249 length = min(100, length); |
| 250 for (int i = 0; i < length; ++i) { |
| 251 // Get each of the items. |
| 252 char indexInChar[20]; // Enough size to store 32-bit integer |
| 253 snprintf(indexInChar, 20, "%d", i); |
| 254 string index(indexInChar); |
| 255 NPIdentifier indexId = WebBindings::getStringIdentifier(index.c_str()); |
| 256 if (!WebBindings::hasProperty(0, npValue, indexId)) |
| 257 continue; |
| 258 NPVariant indexValue; |
| 259 if (!WebBindings::getProperty(0, npValue, indexId, &indexValue)) |
| 260 continue; |
| 261 if (NPVARIANT_IS_STRING(indexValue)) { |
| 262 string item(NPVARIANT_TO_STRING(indexValue).UTF8Characters, |
| 263 NPVARIANT_TO_STRING(indexValue).UTF8Length); |
| 264 stringVector.push_back(item); |
| 265 } |
| 266 WebBindings::releaseVariantValue(&indexValue); |
| 267 } |
| 268 return stringVector; |
| 269 } |
| 270 |
| 271 bool CppVariant::invoke(const string& method, const CppVariant* arguments, |
| 272 uint32_t argumentCount, CppVariant& result) const |
| 273 { |
| 274 BLINK_ASSERT(isObject()); |
| 275 NPIdentifier methodName = WebBindings::getStringIdentifier(method.c_str()); |
| 276 NPObject* npObject = value.objectValue; |
| 277 if (!WebBindings::hasMethod(0, npObject, methodName)) |
| 278 return false; |
| 279 NPVariant r; |
| 280 bool status = WebBindings::invoke(0, npObject, methodName, arguments, argume
ntCount, &r); |
| 281 result.set(r); |
| 282 return status; |
| 283 } |
| 284 |
| 285 bool CppVariant::invokeDefault(const CppVariant* arguments, uint32_t argumentCou
nt, |
| 286 CppVariant& result) const |
| 287 { |
| 288 BLINK_ASSERT(isObject()); |
| 289 NPObject* npObject = value.objectValue; |
| 290 NPVariant r; |
| 291 bool status = WebBindings::invokeDefault(0, npObject, arguments, argumentCou
nt, &r); |
| 292 result.set(r); |
| 293 return status; |
| 294 } |
| 295 |
| 296 } |
OLD | NEW |