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 blink::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 |