• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "CppVariant.h"
33 
34 #include "WebBindings.h"
35 #include <limits>
36 #include <wtf/Assertions.h>
37 #include <wtf/StringExtras.h>
38 
39 using namespace WebKit;
40 using namespace std;
41 
CppVariant()42 CppVariant::CppVariant()
43 {
44     type = NPVariantType_Null;
45 }
46 
47 // Note that Set() performs a deep copy, which is necessary to safely
48 // call FreeData() on the value in the destructor.
CppVariant(const CppVariant & original)49 CppVariant::CppVariant(const CppVariant& original)
50 {
51     type = NPVariantType_Null;
52     set(original);
53 }
54 
55 // See comment for copy constructor, above.
operator =(const CppVariant & original)56 CppVariant& CppVariant::operator=(const CppVariant& original)
57 {
58     if (&original != this)
59         set(original);
60     return *this;
61 }
62 
~CppVariant()63 CppVariant::~CppVariant()
64 {
65     freeData();
66 }
67 
freeData()68 void CppVariant::freeData()
69 {
70     WebBindings::releaseVariantValue(this);
71 }
72 
isEqual(const CppVariant & other) const73 bool CppVariant::isEqual(const CppVariant& other) const
74 {
75     if (type != other.type)
76         return false;
77 
78     switch (type) {
79     case NPVariantType_Bool:
80         return (value.boolValue == other.value.boolValue);
81     case NPVariantType_Int32:
82         return (value.intValue == other.value.intValue);
83     case NPVariantType_Double:
84         return (value.doubleValue == other.value.doubleValue);
85     case NPVariantType_String: {
86         const NPString *this_value = &value.stringValue;
87         const NPString *other_value = &other.value.stringValue;
88         uint32_t len = this_value->UTF8Length;
89         return len == other_value->UTF8Length
90             && !strncmp(this_value->UTF8Characters,
91                         other_value->UTF8Characters, len);
92     }
93     case NPVariantType_Null:
94     case NPVariantType_Void:
95         return true;
96     case NPVariantType_Object: {
97         NPObject* thisValue = value.objectValue;
98         NPObject* otherValue = other.value.objectValue;
99         return thisValue->_class == otherValue->_class
100             && thisValue->referenceCount == otherValue->referenceCount;
101     }
102     }
103     return false;
104 }
105 
copyToNPVariant(NPVariant * result) const106 void CppVariant::copyToNPVariant(NPVariant* result) const
107 {
108     result->type = type;
109     switch (type) {
110     case NPVariantType_Bool:
111         result->value.boolValue = value.boolValue;
112         break;
113     case NPVariantType_Int32:
114         result->value.intValue = value.intValue;
115         break;
116     case NPVariantType_Double:
117         result->value.doubleValue = value.doubleValue;
118         break;
119     case NPVariantType_String:
120         WebBindings::initializeVariantWithStringCopy(result, &value.stringValue);
121         break;
122     case NPVariantType_Null:
123     case NPVariantType_Void:
124         // Nothing to set.
125         break;
126     case NPVariantType_Object:
127         result->type = NPVariantType_Object;
128         result->value.objectValue = WebBindings::retainObject(value.objectValue);
129         break;
130     }
131 }
132 
set(const NPVariant & newValue)133 void CppVariant::set(const NPVariant& newValue)
134 {
135     freeData();
136     switch (newValue.type) {
137     case NPVariantType_Bool:
138         set(newValue.value.boolValue);
139         break;
140     case NPVariantType_Int32:
141         set(newValue.value.intValue);
142         break;
143     case NPVariantType_Double:
144         set(newValue.value.doubleValue);
145         break;
146     case NPVariantType_String:
147         set(newValue.value.stringValue);
148         break;
149     case NPVariantType_Null:
150     case NPVariantType_Void:
151         type = newValue.type;
152         break;
153     case NPVariantType_Object:
154         set(newValue.value.objectValue);
155         break;
156     }
157 }
158 
setNull()159 void CppVariant::setNull()
160 {
161     freeData();
162     type = NPVariantType_Null;
163 }
164 
set(bool newValue)165 void CppVariant::set(bool newValue)
166 {
167     freeData();
168     type = NPVariantType_Bool;
169     value.boolValue = newValue;
170 }
171 
set(int32_t newValue)172 void CppVariant::set(int32_t newValue)
173 {
174     freeData();
175     type = NPVariantType_Int32;
176     value.intValue = newValue;
177 }
178 
set(double newValue)179 void CppVariant::set(double newValue)
180 {
181     freeData();
182     type = NPVariantType_Double;
183     value.doubleValue = newValue;
184 }
185 
186 // The newValue must be a null-terminated string.
set(const char * newValue)187 void CppVariant::set(const char* newValue)
188 {
189     freeData();
190     type = NPVariantType_String;
191     NPString newString = {newValue,
192                           static_cast<uint32_t>(strlen(newValue))};
193     WebBindings::initializeVariantWithStringCopy(this, &newString);
194 }
195 
set(const string & newValue)196 void CppVariant::set(const string& newValue)
197 {
198     freeData();
199     type = NPVariantType_String;
200     NPString newString = {newValue.data(),
201                           static_cast<uint32_t>(newValue.size())};
202     WebBindings::initializeVariantWithStringCopy(this, &newString);
203 }
204 
set(const NPString & newValue)205 void CppVariant::set(const NPString& newValue)
206 {
207     freeData();
208     type = NPVariantType_String;
209     WebBindings::initializeVariantWithStringCopy(this, &newValue);
210 }
211 
set(NPObject * newValue)212 void CppVariant::set(NPObject* newValue)
213 {
214     freeData();
215     type = NPVariantType_Object;
216     value.objectValue = WebBindings::retainObject(newValue);
217 }
218 
toString() const219 string CppVariant::toString() const
220 {
221     ASSERT(isString());
222     return string(value.stringValue.UTF8Characters,
223                   value.stringValue.UTF8Length);
224 }
225 
toInt32() const226 int32_t CppVariant::toInt32() const
227 {
228     if (isInt32())
229         return value.intValue;
230     if (isDouble())
231         return static_cast<int32_t>(value.doubleValue);
232     ASSERT_NOT_REACHED();
233     return 0;
234 }
235 
toDouble() const236 double CppVariant::toDouble() const
237 {
238     if (isInt32())
239         return static_cast<double>(value.intValue);
240     if (isDouble())
241         return value.doubleValue;
242     ASSERT_NOT_REACHED();
243     return 0;
244 }
245 
toBoolean() const246 bool CppVariant::toBoolean() const
247 {
248     ASSERT(isBool());
249     return value.boolValue;
250 }
251 
toStringVector() const252 Vector<string> CppVariant::toStringVector() const
253 {
254 
255     ASSERT(isObject());
256     Vector<string> stringVector;
257     NPObject* npValue = value.objectValue;
258     NPIdentifier lengthId = WebBindings::getStringIdentifier("length");
259 
260     if (!WebBindings::hasProperty(0, npValue, lengthId))
261         return stringVector;
262 
263     NPVariant lengthValue;
264     if (!WebBindings::getProperty(0, npValue, lengthId, &lengthValue))
265         return stringVector;
266 
267     int length = 0;
268     // The length is a double in some cases.
269     if (NPVARIANT_IS_DOUBLE(lengthValue))
270         length = static_cast<int>(NPVARIANT_TO_DOUBLE(lengthValue));
271     else if (NPVARIANT_IS_INT32(lengthValue))
272         length = NPVARIANT_TO_INT32(lengthValue);
273     WebBindings::releaseVariantValue(&lengthValue);
274 
275     // For sanity, only allow 100 items.
276     length = min(100, length);
277     for (int i = 0; i < length; ++i) {
278         // Get each of the items.
279         char indexInChar[20]; // Enough size to store 32-bit integer
280         snprintf(indexInChar, 20, "%d", i);
281         string index(indexInChar);
282         NPIdentifier indexId = WebBindings::getStringIdentifier(index.c_str());
283         if (!WebBindings::hasProperty(0, npValue, indexId))
284             continue;
285         NPVariant indexValue;
286         if (!WebBindings::getProperty(0, npValue, indexId, &indexValue))
287             continue;
288         if (NPVARIANT_IS_STRING(indexValue)) {
289             string item(NPVARIANT_TO_STRING(indexValue).UTF8Characters,
290                         NPVARIANT_TO_STRING(indexValue).UTF8Length);
291             stringVector.append(item);
292         }
293         WebBindings::releaseVariantValue(&indexValue);
294     }
295     return stringVector;
296 }
297 
invoke(const string & method,const CppVariant * arguments,uint32_t argumentCount,CppVariant & result) const298 bool CppVariant::invoke(const string& method, const CppVariant* arguments,
299                         uint32_t argumentCount, CppVariant& result) const
300 {
301     ASSERT(isObject());
302     NPIdentifier methodName = WebBindings::getStringIdentifier(method.c_str());
303     NPObject* npObject = value.objectValue;
304     if (!WebBindings::hasMethod(0, npObject, methodName))
305         return false;
306     NPVariant r;
307     bool status = WebBindings::invoke(0, npObject, methodName, arguments, argumentCount, &r);
308     result.set(r);
309     return status;
310 }
311