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/Nullable.h" 32 #include "bindings/v8/ScriptValue.h" 33 #include "bindings/v8/V8Binding.h" 34 #include "bindings/v8/V8BindingMacros.h" 35 #include "core/events/EventListener.h" 36 #include "core/dom/MessagePort.h" 37 #include <v8.h> 38 #include "wtf/HashMap.h" 39 #include "wtf/HashSet.h" 40 #include "wtf/Vector.h" 41 #include "wtf/text/AtomicString.h" 42 #include "wtf/text/WTFString.h" 43 44 namespace WebCore { 45 46 class ArrayValue; 47 class DOMError; 48 class LocalDOMWindow; 49 class Gamepad; 50 class MediaStream; 51 class HeaderMap; 52 class IDBKeyRange; 53 class MIDIPort; 54 class MediaKeyError; 55 class Notification; 56 class SpeechRecognitionResult; 57 class SpeechRecognitionResultList; 58 class Storage; 59 class TrackBase; 60 class VoidCallback; 61 62 class Dictionary { 63 ALLOW_ONLY_INLINE_ALLOCATION(); 64 public: 65 Dictionary(); 66 Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate*); 67 ~Dictionary(); 68 69 Dictionary& operator=(const Dictionary&); 70 71 bool isObject() const; 72 bool isUndefinedOrNull() const; 73 74 bool get(const String&, bool&) const; 75 bool get(const String&, int32_t&) const; 76 bool get(const String&, double&, bool& hasValue) const; 77 bool get(const String&, double&) const; 78 bool get(const String&, String&) const; 79 bool get(const String&, AtomicString&) const; 80 bool get(const String&, ScriptValue&) const; 81 bool get(const String&, short&) const; 82 bool get(const String&, unsigned short&) const; 83 bool get(const String&, unsigned&) const; 84 bool get(const String&, unsigned long&) const; 85 bool get(const String&, unsigned long long&) const; 86 bool get(const String&, RefPtrWillBeMember<LocalDOMWindow>&) const; 87 bool get(const String&, RefPtrWillBeMember<Storage>&) const; 88 bool get(const String&, MessagePortArray&) const; 89 bool get(const String&, RefPtr<Uint8Array>&) const; 90 bool get(const String&, RefPtr<ArrayBufferView>&) const; 91 bool get(const String&, RefPtrWillBeMember<MIDIPort>&) const; 92 bool get(const String&, RefPtr<MediaKeyError>&) const; 93 bool get(const String&, RefPtrWillBeMember<TrackBase>&) const; 94 bool get(const String&, Member<SpeechRecognitionResult>&) const; 95 bool get(const String&, Member<SpeechRecognitionResultList>&) const; 96 bool get(const String&, Member<Gamepad>&) const; 97 bool get(const String&, RefPtr<MediaStream>&) const; 98 bool get(const String&, RefPtrWillBeMember<EventTarget>&) const; 99 bool get(const String&, HashSet<AtomicString>&) const; 100 bool get(const String&, Dictionary&) const; 101 bool get(const String&, Vector<String>&) const; 102 bool get(const String&, ArrayValue&) const; 103 bool get(const String&, RefPtrWillBeMember<DOMError>&) const; 104 bool get(const String&, v8::Local<v8::Value>&) const; 105 bool get(const String&, RefPtr<HeaderMap>&) const; 106 107 class ConversionContext { 108 public: 109 ConversionContext(const String& interfaceName, const String& methodName, ExceptionState& exceptionState) 110 : m_interfaceName(interfaceName) 111 , m_methodName(methodName) 112 , m_exceptionState(exceptionState) 113 , m_dirty(true) 114 { 115 resetPerPropertyContext(); 116 } 117 118 const String& interfaceName() const { return m_interfaceName; } 119 const String& methodName() const { return m_methodName; } 120 bool forConstructor() const { return m_methodName.isEmpty(); } 121 ExceptionState& exceptionState() const { return m_exceptionState; } 122 123 bool isNullable() const { return m_isNullable; } 124 String typeName() const { return m_propertyTypeName; } 125 126 ConversionContext& setConversionType(const String&, bool); 127 128 void throwTypeError(const String& detail); 129 130 void resetPerPropertyContext(); 131 132 private: 133 const String m_interfaceName; 134 const String m_methodName; 135 ExceptionState& m_exceptionState; 136 bool m_dirty; 137 138 bool m_isNullable; 139 String m_propertyTypeName; 140 }; 141 142 class ConversionContextScope { 143 public: 144 ConversionContextScope(ConversionContext& context) 145 : m_context(context) { } 146 ~ConversionContextScope() 147 { 148 m_context.resetPerPropertyContext(); 149 } 150 private: 151 ConversionContext& m_context; 152 }; 153 154 bool convert(ConversionContext&, const String&, bool&) const; 155 bool convert(ConversionContext&, const String&, double&) const; 156 bool convert(ConversionContext&, const String&, String&) const; 157 bool convert(ConversionContext&, const String&, ScriptValue&) const; 158 159 template<typename IntegralType> 160 bool convert(ConversionContext&, const String&, IntegralType&) const; 161 template<typename IntegralType> 162 bool convert(ConversionContext&, const String&, Nullable<IntegralType>&) const; 163 164 bool convert(ConversionContext&, const String&, MessagePortArray&) const; 165 bool convert(ConversionContext&, const String&, HashSet<AtomicString>&) const; 166 bool convert(ConversionContext&, const String&, Dictionary&) const; 167 bool convert(ConversionContext&, const String&, Vector<String>&) const; 168 bool convert(ConversionContext&, const String&, ArrayValue&) const; 169 template<template <typename> class PointerType, typename T> 170 bool convert(ConversionContext&, const String&, PointerType<T>&) const; 171 172 template<typename StringType> 173 bool getStringType(const String&, StringType&) const; 174 175 bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const; 176 bool getOwnPropertyNames(Vector<String>&) const; 177 178 bool getWithUndefinedOrNullCheck(const String&, String&) const; 179 180 bool hasProperty(const String&) const; 181 182 private: 183 bool getKey(const String& key, v8::Local<v8::Value>&) const; 184 185 v8::Handle<v8::Value> m_options; 186 v8::Isolate* m_isolate; 187 }; 188 189 template<> 190 struct NativeValueTraits<Dictionary> { 191 static inline Dictionary nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) 192 { 193 return Dictionary(value, isolate); 194 } 195 }; 196 197 template <typename T> 198 struct IntegralTypeTraits { 199 }; 200 201 template <> 202 struct IntegralTypeTraits<uint8_t> { 203 static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 204 { 205 return toUInt8(value, configuration, exceptionState); 206 } 207 static const String typeName() { return "UInt8"; } 208 }; 209 210 template <> 211 struct IntegralTypeTraits<int8_t> { 212 static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 213 { 214 return toInt8(value, configuration, exceptionState); 215 } 216 static const String typeName() { return "Int8"; } 217 }; 218 219 template <> 220 struct IntegralTypeTraits<unsigned short> { 221 static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 222 { 223 return toUInt16(value, configuration, exceptionState); 224 } 225 static const String typeName() { return "UInt16"; } 226 }; 227 228 template <> 229 struct IntegralTypeTraits<short> { 230 static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 231 { 232 return toInt16(value, configuration, exceptionState); 233 } 234 static const String typeName() { return "Int16"; } 235 }; 236 237 template <> 238 struct IntegralTypeTraits<unsigned> { 239 static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 240 { 241 return toUInt32(value, configuration, exceptionState); 242 } 243 static const String typeName() { return "UInt32"; } 244 }; 245 246 template <> 247 struct IntegralTypeTraits<unsigned long> { 248 static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 249 { 250 return toUInt32(value, configuration, exceptionState); 251 } 252 static const String typeName() { return "UInt32"; } 253 }; 254 255 template <> 256 struct IntegralTypeTraits<int> { 257 static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 258 { 259 return toInt32(value, configuration, exceptionState); 260 } 261 static const String typeName() { return "Int32"; } 262 }; 263 264 template <> 265 struct IntegralTypeTraits<long> { 266 static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 267 { 268 return toInt32(value, configuration, exceptionState); 269 } 270 static const String typeName() { return "Int32"; } 271 }; 272 273 template <> 274 struct IntegralTypeTraits<unsigned long long> { 275 static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 276 { 277 return toUInt64(value, configuration, exceptionState); 278 } 279 static const String typeName() { return "UInt64"; } 280 }; 281 282 template <> 283 struct IntegralTypeTraits<long long> { 284 static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) 285 { 286 return toInt64(value, configuration, exceptionState); 287 } 288 static const String typeName() { return "Int64"; } 289 }; 290 291 template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, T& value) const 292 { 293 ConversionContextScope scope(context); 294 295 v8::Local<v8::Value> v8Value; 296 if (!getKey(key, v8Value)) 297 return true; 298 299 value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState()); 300 if (context.exceptionState().throwIfNeeded()) 301 return false; 302 303 return true; 304 } 305 306 template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, Nullable<T>& value) const 307 { 308 ConversionContextScope scope(context); 309 310 v8::Local<v8::Value> v8Value; 311 if (!getKey(key, v8Value)) 312 return true; 313 314 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) { 315 value = Nullable<T>(); 316 return true; 317 } 318 319 T converted = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState()); 320 321 if (context.exceptionState().throwIfNeeded()) 322 return false; 323 324 value = Nullable<T>(converted); 325 return true; 326 } 327 328 template<template <typename> class PointerType, typename T> bool Dictionary::convert(ConversionContext& context, const String& key, PointerType<T>& value) const 329 { 330 ConversionContextScope scope(context); 331 332 if (!get(key, value)) 333 return true; 334 335 if (value) 336 return true; 337 338 v8::Local<v8::Value> v8Value; 339 getKey(key, v8Value); 340 if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) 341 return true; 342 343 context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have a " + context.typeName() + " type.")); 344 return false; 345 } 346 347 } 348 349 #endif // Dictionary_h 350