| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // This file contains definitions for CppVariant. | |
| 6 | |
| 7 #include <limits> | |
| 8 #include "base/logging.h" | |
| 9 #include "base/strings/string_util.h" | |
| 10 #include "base/strings/stringprintf.h" | |
| 11 #include "base/strings/utf_string_conversions.h" | |
| 12 #include "third_party/WebKit/public/web/WebBindings.h" | |
| 13 #include "webkit/renderer/cpp_variant.h" | |
| 14 | |
| 15 using WebKit::WebBindings; | |
| 16 | |
| 17 namespace webkit_glue { | |
| 18 | |
| 19 CppVariant::CppVariant() { | |
| 20 type = NPVariantType_Null; | |
| 21 } | |
| 22 | |
| 23 // Note that Set() performs a deep copy, which is necessary to safely | |
| 24 // call FreeData() on the value in the destructor. | |
| 25 CppVariant::CppVariant(const CppVariant& original) { | |
| 26 type = NPVariantType_Null; | |
| 27 Set(original); | |
| 28 } | |
| 29 | |
| 30 // See comment for copy constructor, above. | |
| 31 CppVariant& CppVariant::operator=(const CppVariant& original) { | |
| 32 if (&original != this) | |
| 33 Set(original); | |
| 34 return *this; | |
| 35 } | |
| 36 | |
| 37 CppVariant::~CppVariant() { | |
| 38 FreeData(); | |
| 39 } | |
| 40 | |
| 41 void CppVariant::FreeData() { | |
| 42 WebBindings::releaseVariantValue(this); | |
| 43 } | |
| 44 | |
| 45 bool CppVariant::isEqual(const CppVariant& other) const { | |
| 46 if (type != other.type) | |
| 47 return false; | |
| 48 | |
| 49 switch (type) { | |
| 50 case NPVariantType_Bool: { | |
| 51 return (value.boolValue == other.value.boolValue); | |
| 52 } | |
| 53 case NPVariantType_Int32: { | |
| 54 return (value.intValue == other.value.intValue); | |
| 55 } | |
| 56 case NPVariantType_Double: { | |
| 57 return (value.doubleValue == other.value.doubleValue); | |
| 58 } | |
| 59 case NPVariantType_String: { | |
| 60 const NPString *this_value = &value.stringValue; | |
| 61 const NPString *other_value = &other.value.stringValue; | |
| 62 uint32_t len = this_value->UTF8Length; | |
| 63 return (len == other_value->UTF8Length && | |
| 64 !strncmp(this_value->UTF8Characters, other_value->UTF8Characters, | |
| 65 len)); | |
| 66 } | |
| 67 case NPVariantType_Null: | |
| 68 case NPVariantType_Void: { | |
| 69 return true; | |
| 70 } | |
| 71 case NPVariantType_Object: { | |
| 72 NPObject *this_value = value.objectValue; | |
| 73 NPObject *other_value = other.value.objectValue; | |
| 74 return (this_value->_class == other_value->_class && | |
| 75 this_value->referenceCount == other_value->referenceCount); | |
| 76 } | |
| 77 } | |
| 78 return false; | |
| 79 } | |
| 80 | |
| 81 void CppVariant::CopyToNPVariant(NPVariant* result) const { | |
| 82 result->type = type; | |
| 83 switch (type) { | |
| 84 case NPVariantType_Bool: | |
| 85 result->value.boolValue = value.boolValue; | |
| 86 break; | |
| 87 case NPVariantType_Int32: | |
| 88 result->value.intValue = value.intValue; | |
| 89 break; | |
| 90 case NPVariantType_Double: | |
| 91 result->value.doubleValue = value.doubleValue; | |
| 92 break; | |
| 93 case NPVariantType_String: | |
| 94 WebBindings::initializeVariantWithStringCopy(result, &value.stringValue); | |
| 95 break; | |
| 96 case NPVariantType_Null: | |
| 97 case NPVariantType_Void: | |
| 98 // Nothing to set. | |
| 99 break; | |
| 100 case NPVariantType_Object: | |
| 101 result->type = NPVariantType_Object; | |
| 102 result->value.objectValue = WebBindings::retainObject(value.objectValue); | |
| 103 break; | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 void CppVariant::Set(const NPVariant& new_value) { | |
| 108 FreeData(); | |
| 109 switch (new_value.type) { | |
| 110 case NPVariantType_Bool: | |
| 111 Set(new_value.value.boolValue); | |
| 112 break; | |
| 113 case NPVariantType_Int32: | |
| 114 Set(new_value.value.intValue); | |
| 115 break; | |
| 116 case NPVariantType_Double: | |
| 117 Set(new_value.value.doubleValue); | |
| 118 break; | |
| 119 case NPVariantType_String: | |
| 120 Set(new_value.value.stringValue); | |
| 121 break; | |
| 122 case NPVariantType_Null: | |
| 123 case NPVariantType_Void: | |
| 124 type = new_value.type; | |
| 125 break; | |
| 126 case NPVariantType_Object: | |
| 127 Set(new_value.value.objectValue); | |
| 128 break; | |
| 129 } | |
| 130 } | |
| 131 | |
| 132 void CppVariant::SetNull() { | |
| 133 FreeData(); | |
| 134 type = NPVariantType_Null; | |
| 135 } | |
| 136 | |
| 137 void CppVariant::Set(bool new_value) { | |
| 138 FreeData(); | |
| 139 type = NPVariantType_Bool; | |
| 140 value.boolValue = new_value; | |
| 141 } | |
| 142 | |
| 143 void CppVariant::Set(int32_t new_value) { | |
| 144 FreeData(); | |
| 145 type = NPVariantType_Int32; | |
| 146 value.intValue = new_value; | |
| 147 } | |
| 148 | |
| 149 void CppVariant::Set(double new_value) { | |
| 150 FreeData(); | |
| 151 type = NPVariantType_Double; | |
| 152 value.doubleValue = new_value; | |
| 153 } | |
| 154 | |
| 155 // The new_value must be a null-terminated string. | |
| 156 void CppVariant::Set(const char* new_value) { | |
| 157 FreeData(); | |
| 158 type = NPVariantType_String; | |
| 159 NPString new_string = {new_value, | |
| 160 static_cast<uint32_t>(strlen(new_value))}; | |
| 161 WebBindings::initializeVariantWithStringCopy(this, &new_string); | |
| 162 } | |
| 163 | |
| 164 void CppVariant::Set(const std::string& new_value) { | |
| 165 FreeData(); | |
| 166 type = NPVariantType_String; | |
| 167 NPString new_string = {new_value.data(), | |
| 168 static_cast<uint32_t>(new_value.size())}; | |
| 169 WebBindings::initializeVariantWithStringCopy(this, &new_string); | |
| 170 } | |
| 171 void CppVariant::Set(const NPString& new_value) { | |
| 172 FreeData(); | |
| 173 type = NPVariantType_String; | |
| 174 WebBindings::initializeVariantWithStringCopy(this, &new_value); | |
| 175 } | |
| 176 | |
| 177 void CppVariant::Set(NPObject* new_value) { | |
| 178 FreeData(); | |
| 179 type = NPVariantType_Object; | |
| 180 value.objectValue = WebBindings::retainObject(new_value); | |
| 181 } | |
| 182 | |
| 183 std::string CppVariant::ToString() const { | |
| 184 DCHECK(isString()); | |
| 185 return std::string(value.stringValue.UTF8Characters, | |
| 186 value.stringValue.UTF8Length); | |
| 187 } | |
| 188 | |
| 189 int32_t CppVariant::ToInt32() const { | |
| 190 if (isInt32()) { | |
| 191 return value.intValue; | |
| 192 } else if (isDouble()) { | |
| 193 return static_cast<int32_t>(value.doubleValue); | |
| 194 } else { | |
| 195 NOTREACHED(); | |
| 196 return 0; | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 double CppVariant::ToDouble() const { | |
| 201 if (isInt32()) { | |
| 202 return static_cast<double>(value.intValue); | |
| 203 } else if (isDouble()) { | |
| 204 return value.doubleValue; | |
| 205 } else { | |
| 206 NOTREACHED(); | |
| 207 return 0.0; | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 bool CppVariant::ToBoolean() const { | |
| 212 DCHECK(isBool()); | |
| 213 return value.boolValue; | |
| 214 } | |
| 215 | |
| 216 std::vector<CppVariant> CppVariant::ToVector() const { | |
| 217 DCHECK(isObject()); | |
| 218 std::vector<CppVariant> vector; | |
| 219 NPObject* np_value = value.objectValue; | |
| 220 NPIdentifier length_id = WebBindings::getStringIdentifier("length"); | |
| 221 | |
| 222 if (WebBindings::hasProperty(NULL, np_value, length_id)) { | |
| 223 CppVariant length_value; | |
| 224 if (WebBindings::getProperty(NULL, np_value, length_id, &length_value)) { | |
| 225 int length = 0; | |
| 226 // The length is a double in some cases. | |
| 227 if (NPVARIANT_IS_DOUBLE(length_value)) | |
| 228 length = static_cast<int>(NPVARIANT_TO_DOUBLE(length_value)); | |
| 229 else if (NPVARIANT_IS_INT32(length_value)) | |
| 230 length = NPVARIANT_TO_INT32(length_value); | |
| 231 else | |
| 232 NOTREACHED(); | |
| 233 | |
| 234 // For sanity, only allow 60000 items. | |
| 235 length = std::min(60000, length); | |
| 236 for (int i = 0; i < length; ++i) { | |
| 237 // Get each of the items. | |
| 238 NPIdentifier index = WebBindings::getIntIdentifier(i); | |
| 239 if (WebBindings::hasProperty(NULL, np_value, index)) { | |
| 240 CppVariant index_value; | |
| 241 if (WebBindings::getProperty(NULL, np_value, index, &index_value)) | |
| 242 vector.push_back(index_value); | |
| 243 } | |
| 244 } | |
| 245 } | |
| 246 } else { | |
| 247 NOTREACHED(); | |
| 248 } | |
| 249 return vector; | |
| 250 } | |
| 251 | |
| 252 bool CppVariant::Invoke(const std::string& method, const CppVariant* args, | |
| 253 uint32 arg_count, CppVariant& result) const { | |
| 254 DCHECK(isObject()); | |
| 255 NPIdentifier method_name = WebBindings::getStringIdentifier(method.c_str()); | |
| 256 NPObject* np_object = value.objectValue; | |
| 257 if (WebBindings::hasMethod(NULL, np_object, method_name)) { | |
| 258 NPVariant r; | |
| 259 bool status = | |
| 260 WebBindings::invoke(NULL, np_object, method_name, args, arg_count, &r); | |
| 261 result.Set(r); | |
| 262 return status; | |
| 263 } else { | |
| 264 return false; | |
| 265 } | |
| 266 } | |
| 267 | |
| 268 } // namespace webkit_glue | |
| OLD | NEW |