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 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef Dictionary_h 27 #define Dictionary_h 28 29 #include "bindings/v8/ExceptionMessages.h" 30 #include "bindings/v8/ExceptionState.h" 31 #include "bindings/v8/ScriptValue.h" 32 #include "bindings/v8/V8Binding.h" 33 #include "bindings/v8/V8BindingMacros.h" 34 #include "core/events/EventListener.h" 35 #include "core/dom/MessagePort.h" 36 #include <v8.h> 37 #include "wtf/HashMap.h" 38 #include "wtf/HashSet.h" 39 #include "wtf/Vector.h" 40 #include "wtf/text/AtomicString.h" 41 #include "wtf/text/WTFString.h" 42 43 namespace WebCore { 44 45 class ArrayValue; 46 class DOMError; 47 class DOMWindow; 48 class IDBKeyRange; 49 class MIDIPort; 50 class MediaKeyError; 51 class Notification; 52 class SpeechRecognitionError; 53 class SpeechRecognitionResult; 54 class SpeechRecognitionResultList; 55 class Storage; 56 class TrackBase; 57 class VoidCallback; 58 59 class Dictionary { 60 public: 61 Dictionary(); 62 Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate*); 63 ~Dictionary(); 64 65 Dictionary& operator=(const Dictionary&); 66 67 bool isObject() const; 68 bool isUndefinedOrNull() const; 69 70 bool get(const String&, bool&) const; 71 bool get(const String&, int32_t&) const; 72 bool get(const String&, double&, bool& hasValue) const; 73 bool get(const String&, double&) const; 74 bool get(const String&, String&) const; 75 bool get(const String&, ScriptValue&) const; 76 bool get(const String&, short&) const; 77 bool get(const String&, unsigned short&) const; 78 bool get(const String&, unsigned&) const; 79 bool get(const String&, unsigned long&) const; 80 bool get(const String&, unsigned long long&) const; 81 bool get(const String&, RefPtr<DOMWindow>&) const; 82 bool get(const String&, RefPtr<Storage>&) const; 83 bool get(const String&, MessagePortArray&) const; 84 bool get(const String&, RefPtr<Uint8Array>&) const; 85 bool get(const String&, RefPtr<ArrayBufferView>&) const; 86 bool get(const String&, RefPtr<MIDIPort>&) const; 87 bool get(const String&, RefPtr<MediaKeyError>&) const; 88 bool get(const String&, RefPtr<TrackBase>&) const; 89 bool get(const String&, RefPtr<SpeechRecognitionError>&) const; 90 bool get(const String&, RefPtr<SpeechRecognitionResult>&) const; 91 bool get(const String&, RefPtr<SpeechRecognitionResultList>&) const; 92 bool get(const String&, RefPtr<MediaStream>&) const; 93 bool get(const String&, RefPtr<EventTarget>&) const; 94 bool get(const String&, HashSet<AtomicString>&) const; 95 bool get(const String&, Dictionary&) const; 96 bool get(const String&, Vector<String>&) const; 97 bool get(const String&, ArrayValue&) const; 98 bool get(const String&, RefPtr<DOMError>&) const; 99 bool get(const String&, OwnPtr<VoidCallback>&) const; 100 bool get(const String&, v8::Local<v8::Value>&) const; 101 102 class ConversionContext { 103 public: 104 ConversionContext(const String& interfaceName, const String& methodName, ExceptionState& exceptionState) 105 : m_interfaceName(interfaceName) 106 , m_methodName(methodName) 107 , m_exceptionState(exceptionState) 108 , m_dirty(true) 109 { 110 resetPerPropertyContext(); 111 } 112 113 const String& interfaceName() const { return m_interfaceName; } 114 const String& methodName() const { return m_methodName; } 115 bool forConstructor() const { return m_methodName.isEmpty(); } 116 ExceptionState& exceptionState() const { return m_exceptionState; } 117 118 bool isNullable() const { return m_isNullable; } 119 String typeName() const { return m_propertyTypeName; } 120 121 ConversionContext& setConversionType(const String&, bool); 122 123 void throwTypeError(const String& detail); 124 125 void resetPerPropertyContext(); 126 127 private: 128 const String m_interfaceName; 129 const String m_methodName; 130 ExceptionState& m_exceptionState; 131 bool m_dirty; 132 133 bool m_isNullable; 134 String m_propertyTypeName; 135 }; 136 137 class ConversionContextScope { 138 public: 139 ConversionContextScope(ConversionContext& context) 140 : m_context(context) { } 141 ~ConversionContextScope() 142 { 143 m_context.resetPerPropertyContext(); 144 } 145 private: 146 ConversionContext& m_context; 147 }; 148 149 bool convert(ConversionContext&, const String&, bool&) const; 150 bool convert(ConversionContext&, const String&, double&) const; 151 bool convert(ConversionContext&, const String&, String&) const; 152 bool convert(ConversionContext&, const String&, ScriptValue&) const; 153 154 template<typename IntegralType> 155 bool convert(ConversionContext &, const String&, IntegralType&) const; 156 bool convert(ConversionContext &, const String&, MessagePortArray&) const; 157 bool convert(ConversionContext &, const String&, HashSet<AtomicString>&) const; 158 bool convert(ConversionContext &, const String&, Dictionary&) const; 159 bool convert(ConversionContext &, const String&, Vector<String>&) const; 160 bool convert(ConversionContext &, const String&, ArrayValue&) const; 161 template<typename T> 162 bool convert(ConversionContext &, const String&, RefPtr<T>&) const; 163 164 bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const; 165 bool getOwnPropertyNames(Vector<String>&) const; 166 167 bool getWithUndefinedOrNullCheck(const String&, String&) const; 168 169 bool hasProperty(const String&) const; 170 171 // Only allow inline allocation. 172 void* operator new(size_t, NotNullTag, void* location) { return location; } 173 174 private: 175 // Disallow new allocation. 176 void* operator new(size_t); 177 178 bool getKey(const String& key, v8::Local<v8::Value>&) const; 179 180 v8::Handle<v8::Value> m_options; 181 v8::Isolate* m_isolate; 182 }; 183 184 template<> 185 struct NativeValueTraits<Dictionary> { 186 static inline Dictionary nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) 187 { 188 return Dictionary(value, isolate); 189 } 190 }; 191 192 template <typename T> 193 struct IntegralTypeTraits { 194 }; 195 196 template <> 197 struct IntegralTypeTraits<uint8_t> { 198 static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 199 { 200 return toUInt8(value, configuration, ok); 201 } 202 static const String typeName() { return "UInt8"; } 203 }; 204 205 template <> 206 struct IntegralTypeTraits<int8_t> { 207 static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 208 { 209 return toInt8(value, configuration, ok); 210 } 211 static const String typeName() { return "Int8"; } 212 }; 213 214 template <> 215 struct IntegralTypeTraits<unsigned short> { 216 static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 217 { 218 return toUInt16(value, configuration, ok); 219 } 220 static const String typeName() { return "UInt16"; } 221 }; 222 223 template <> 224 struct IntegralTypeTraits<short> { 225 static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 226 { 227 return toInt16(value, configuration, ok); 228 } 229 static const String typeName() { return "Int16"; } 230 }; 231 232 template <> 233 struct IntegralTypeTraits<unsigned> { 234 static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 235 { 236 return toUInt32(value, configuration, ok); 237 } 238 static const String typeName() { return "UInt32"; } 239 }; 240 241 template <> 242 struct IntegralTypeTraits<unsigned long> { 243 static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 244 { 245 return toUInt32(value, configuration, ok); 246 } 247 static const String typeName() { return "UInt32"; } 248 }; 249 250 template <> 251 struct IntegralTypeTraits<int> { 252 static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 253 { 254 return toInt32(value, configuration, ok); 255 } 256 static const String typeName() { return "Int32"; } 257 }; 258 259 template <> 260 struct IntegralTypeTraits<long> { 261 static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 262 { 263 return toInt32(value, configuration, ok); 264 } 265 static const String typeName() { return "Int32"; } 266 }; 267 268 template <> 269 struct IntegralTypeTraits<unsigned long long> { 270 static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 271 { 272 return toUInt64(value, configuration, ok); 273 } 274 static const String typeName() { return "UInt64"; } 275 }; 276 277 template <> 278 struct IntegralTypeTraits<long long> { 279 static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) 280 { 281 return toInt64(value, configuration, ok); 282 } 283 static const String typeName() { return "Int64"; } 284 }; 285 286 template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, T& value) const 287 { 288 ConversionContextScope scope(context); 289 290 v8::Local<v8::Value> v8Value; 291 if (!getKey(key, v8Value)) 292 return true; 293 294 bool ok = false; 295 value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, ok); 296 if (ok) 297 return true; 298 299 V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); 300 ASSERT(v8Number.IsEmpty()); 301 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have type " + IntegralTypeTraits<T>::typeName() + ".")); 302 return false; 303 } 304 305 template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, RefPtr<T>& value) const 306 { 307 ConversionContextScope scope(context); 308 309 if (!get(key, value)) 310 return true; 311 312 if (value) 313 return true; 314 315 v8::Local<v8::Value> v8Value; 316 getKey(key, v8Value); 317 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) 318 return true; 319 320 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a " + context.typeName() + " type.")); 321 return false; 322 } 323 324 } 325 326 #endif // Dictionary_h 327