• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CppVariant()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.
CppVariant(const CppVariant & original)25 CppVariant::CppVariant(const CppVariant& original) {
26   type = NPVariantType_Null;
27   Set(original);
28 }
29 
30 // See comment for copy constructor, above.
operator =(const CppVariant & original)31 CppVariant& CppVariant::operator=(const CppVariant& original) {
32   if (&original != this)
33     Set(original);
34   return *this;
35 }
36 
~CppVariant()37 CppVariant::~CppVariant() {
38   FreeData();
39 }
40 
FreeData()41 void CppVariant::FreeData() {
42   WebBindings::releaseVariantValue(this);
43 }
44 
isEqual(const CppVariant & other) const45 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 
CopyToNPVariant(NPVariant * result) const81 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 
Set(const NPVariant & new_value)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 
SetNull()132 void CppVariant::SetNull() {
133   FreeData();
134   type = NPVariantType_Null;
135 }
136 
Set(bool new_value)137 void CppVariant::Set(bool new_value) {
138   FreeData();
139   type = NPVariantType_Bool;
140   value.boolValue = new_value;
141 }
142 
Set(int32_t new_value)143 void CppVariant::Set(int32_t new_value) {
144   FreeData();
145   type = NPVariantType_Int32;
146   value.intValue = new_value;
147 }
148 
Set(double new_value)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.
Set(const char * new_value)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 
Set(const std::string & new_value)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 }
Set(const NPString & new_value)171 void CppVariant::Set(const NPString& new_value) {
172   FreeData();
173   type = NPVariantType_String;
174   WebBindings::initializeVariantWithStringCopy(this, &new_value);
175 }
176 
Set(NPObject * new_value)177 void CppVariant::Set(NPObject* new_value) {
178   FreeData();
179   type = NPVariantType_Object;
180   value.objectValue = WebBindings::retainObject(new_value);
181 }
182 
ToString() const183 std::string CppVariant::ToString() const {
184   DCHECK(isString());
185   return std::string(value.stringValue.UTF8Characters,
186                      value.stringValue.UTF8Length);
187 }
188 
ToInt32() const189 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 
ToDouble() const200 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 
ToBoolean() const211 bool CppVariant::ToBoolean() const {
212   DCHECK(isBool());
213   return value.boolValue;
214 }
215 
ToVector() const216 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 
Invoke(const std::string & method,const CppVariant * args,uint32 arg_count,CppVariant & result) const252 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
269