| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "bindings/core/v8/SerializedScriptValue.h" | 32 #include "bindings/core/v8/SerializedScriptValue.h" |
| 33 | 33 |
| 34 #include "bindings/core/v8/DOMDataStore.h" |
| 35 #include "bindings/core/v8/DOMWrapperWorld.h" |
| 34 #include "bindings/core/v8/ExceptionState.h" | 36 #include "bindings/core/v8/ExceptionState.h" |
| 37 #include "bindings/core/v8/ScriptValueSerializer.h" |
| 35 #include "bindings/core/v8/V8ArrayBuffer.h" | 38 #include "bindings/core/v8/V8ArrayBuffer.h" |
| 36 #include "bindings/core/v8/V8ArrayBufferView.h" | 39 #include "bindings/core/v8/V8ArrayBufferView.h" |
| 37 #include "bindings/core/v8/V8Binding.h" | 40 #include "bindings/core/v8/V8Binding.h" |
| 38 #include "bindings/core/v8/V8Blob.h" | |
| 39 #include "bindings/core/v8/V8DataView.h" | |
| 40 #include "bindings/core/v8/V8File.h" | |
| 41 #include "bindings/core/v8/V8FileList.h" | |
| 42 #include "bindings/core/v8/V8Float32Array.h" | |
| 43 #include "bindings/core/v8/V8Float64Array.h" | |
| 44 #include "bindings/core/v8/V8ImageData.h" | |
| 45 #include "bindings/core/v8/V8Int16Array.h" | |
| 46 #include "bindings/core/v8/V8Int32Array.h" | |
| 47 #include "bindings/core/v8/V8Int8Array.h" | |
| 48 #include "bindings/core/v8/V8MessagePort.h" | 41 #include "bindings/core/v8/V8MessagePort.h" |
| 49 #include "bindings/core/v8/V8Uint16Array.h" | 42 #include "core/dom/DOMArrayBuffer.h" |
| 50 #include "bindings/core/v8/V8Uint32Array.h" | |
| 51 #include "bindings/core/v8/V8Uint8Array.h" | |
| 52 #include "bindings/core/v8/V8Uint8ClampedArray.h" | |
| 53 #include "bindings/core/v8/WorkerScriptController.h" | |
| 54 #include "bindings/modules/v8/V8CryptoKey.h" | |
| 55 #include "bindings/modules/v8/V8DOMFileSystem.h" | |
| 56 #include "core/dom/ExceptionCode.h" | 43 #include "core/dom/ExceptionCode.h" |
| 57 #include "core/dom/MessagePort.h" | |
| 58 #include "core/fileapi/Blob.h" | |
| 59 #include "core/fileapi/File.h" | |
| 60 #include "core/fileapi/FileList.h" | |
| 61 #include "core/html/ImageData.h" | |
| 62 #include "core/html/canvas/DataView.h" | |
| 63 #include "platform/SharedBuffer.h" | 44 #include "platform/SharedBuffer.h" |
| 45 #include "platform/blob/BlobData.h" |
| 64 #include "platform/heap/Handle.h" | 46 #include "platform/heap/Handle.h" |
| 65 #include "public/platform/Platform.h" | 47 #include "public/platform/Platform.h" |
| 66 #include "public/platform/WebBlobInfo.h" | |
| 67 #include "public/platform/WebCrypto.h" | |
| 68 #include "public/platform/WebCryptoKey.h" | |
| 69 #include "public/platform/WebCryptoKeyAlgorithm.h" | |
| 70 #include "wtf/ArrayBuffer.h" | 48 #include "wtf/ArrayBuffer.h" |
| 71 #include "wtf/ArrayBufferContents.h" | 49 #include "wtf/ArrayBufferContents.h" |
| 72 #include "wtf/ArrayBufferView.h" | 50 #include "wtf/ArrayBufferView.h" |
| 73 #include "wtf/Assertions.h" | 51 #include "wtf/Assertions.h" |
| 74 #include "wtf/ByteOrder.h" | 52 #include "wtf/ByteOrder.h" |
| 75 #include "wtf/Float32Array.h" | |
| 76 #include "wtf/Float64Array.h" | |
| 77 #include "wtf/Int16Array.h" | |
| 78 #include "wtf/Int32Array.h" | |
| 79 #include "wtf/Int8Array.h" | |
| 80 #include "wtf/RefCounted.h" | |
| 81 #include "wtf/Uint16Array.h" | |
| 82 #include "wtf/Uint32Array.h" | |
| 83 #include "wtf/Uint8Array.h" | |
| 84 #include "wtf/Uint8ClampedArray.h" | 53 #include "wtf/Uint8ClampedArray.h" |
| 85 #include "wtf/Vector.h" | 54 #include "wtf/Vector.h" |
| 86 #include "wtf/text/StringBuffer.h" | 55 #include "wtf/text/StringBuffer.h" |
| 56 #include "wtf/text/StringHash.h" |
| 87 #include "wtf/text/StringUTF8Adaptor.h" | 57 #include "wtf/text/StringUTF8Adaptor.h" |
| 88 | 58 |
| 89 // FIXME: consider crashing in debug mode on deserialization errors | |
| 90 // NOTE: be sure to change wireFormatVersion as necessary! | |
| 91 | |
| 92 namespace blink { | 59 namespace blink { |
| 93 | 60 |
| 94 namespace { | |
| 95 | |
| 96 // This code implements the HTML5 Structured Clone algorithm: | |
| 97 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-pa
ssing-of-structured-data | |
| 98 | |
| 99 // V8ObjectMap is a map from V8 objects to arbitrary values of type T. | |
| 100 // V8 objects (or handles to V8 objects) cannot be used as keys in ordinary wtf:
:HashMaps; | |
| 101 // this class should be used instead. GCObject must be a subtype of v8::Object. | |
| 102 // Suggested usage: | |
| 103 // V8ObjectMap<v8::Object, int> map; | |
| 104 // v8::Handle<v8::Object> obj = ...; | |
| 105 // map.set(obj, 42); | |
| 106 template<typename GCObject, typename T> | |
| 107 class V8ObjectMap { | |
| 108 public: | |
| 109 bool contains(const v8::Handle<GCObject>& handle) | |
| 110 { | |
| 111 return m_map.contains(*handle); | |
| 112 } | |
| 113 | |
| 114 bool tryGet(const v8::Handle<GCObject>& handle, T* valueOut) | |
| 115 { | |
| 116 typename HandleToT::iterator result = m_map.find(*handle); | |
| 117 if (result != m_map.end()) { | |
| 118 *valueOut = result->value; | |
| 119 return true; | |
| 120 } | |
| 121 return false; | |
| 122 } | |
| 123 | |
| 124 void set(const v8::Handle<GCObject>& handle, const T& value) | |
| 125 { | |
| 126 m_map.set(*handle, value); | |
| 127 } | |
| 128 | |
| 129 private: | |
| 130 // This implementation uses GetIdentityHash(), which sets a hidden property
on the object containing | |
| 131 // a random integer (or returns the one that had been previously set). This
ensures that the table | |
| 132 // never needs to be rebuilt across garbage collections at the expense of do
ing additional allocation | |
| 133 // and making more round trips into V8. Note that since GetIdentityHash() is
defined only on | |
| 134 // v8::Objects, this V8ObjectMap cannot be used to map v8::Strings to T (bec
ause the public V8 API | |
| 135 // considers a v8::String to be a v8::Primitive). | |
| 136 | |
| 137 // If V8 exposes a way to get at the address of the object held by a handle,
then we can produce | |
| 138 // an alternate implementation that does not need to do any V8-side allocati
on; however, it will | |
| 139 // need to rehash after every garbage collection because a key object may ha
ve been moved. | |
| 140 template<typename G> | |
| 141 struct V8HandlePtrHash { | |
| 142 static v8::Handle<G> unsafeHandleFromRawValue(const G* value) | |
| 143 { | |
| 144 const v8::Handle<G>* handle = reinterpret_cast<const v8::Handle<G>*>
(&value); | |
| 145 return *handle; | |
| 146 } | |
| 147 | |
| 148 static unsigned hash(const G* key) | |
| 149 { | |
| 150 return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdent
ityHash()); | |
| 151 } | |
| 152 static bool equal(const G* a, const G* b) | |
| 153 { | |
| 154 return unsafeHandleFromRawValue(a) == unsafeHandleFromRawValue(b); | |
| 155 } | |
| 156 // For HashArg. | |
| 157 static const bool safeToCompareToEmptyOrDeleted = false; | |
| 158 }; | |
| 159 | |
| 160 typedef WTF::HashMap<GCObject*, T, V8HandlePtrHash<GCObject> > HandleToT; | |
| 161 HandleToT m_map; | |
| 162 }; | |
| 163 | |
| 164 typedef UChar BufferValueType; | |
| 165 | |
| 166 // Serialization format is a sequence of tags followed by zero or more data argu
ments. | |
| 167 // Tags always take exactly one byte. A serialized stream first begins with | |
| 168 // a complete VersionTag. If the stream does not begin with a VersionTag, we ass
ume that | |
| 169 // the stream is in format 0. | |
| 170 | |
| 171 // This format is private to the implementation of SerializedScriptValue. Do not
rely on it | |
| 172 // externally. It is safe to persist a SerializedScriptValue as a binary blob, b
ut this | |
| 173 // code should always be used to interpret it. | |
| 174 | |
| 175 // WebCoreStrings are read as (length:uint32_t, string:UTF8[length]). | |
| 176 // RawStrings are read as (length:uint32_t, string:UTF8[length]). | |
| 177 // RawUCharStrings are read as (length:uint32_t, string:UChar[length/sizeof(UCha
r)]). | |
| 178 // RawFiles are read as (path:WebCoreString, url:WebCoreStrng, type:WebCoreStrin
g). | |
| 179 // There is a reference table that maps object references (uint32_t) to v8::Valu
es. | |
| 180 // Tokens marked with (ref) are inserted into the reference table and given the
next object reference ID after decoding. | |
| 181 // All tags except InvalidTag, PaddingTag, ReferenceCountTag, VersionTag, Genera
teFreshObjectTag | |
| 182 // and GenerateFreshArrayTag push their results to the deserialization stack
. | |
| 183 // There is also an 'open' stack that is used to resolve circular references. Ob
jects or arrays may | |
| 184 // contain self-references. Before we begin to deserialize the contents of t
hese values, they | |
| 185 // are first given object reference IDs (by GenerateFreshObjectTag/GenerateF
reshArrayTag); | |
| 186 // these reference IDs are then used with ObjectReferenceTag to tie the recu
rsive knot. | |
| 187 enum SerializationTag { | |
| 188 InvalidTag = '!', // Causes deserialization to fail. | |
| 189 PaddingTag = '\0', // Is ignored (but consumed). | |
| 190 UndefinedTag = '_', // -> <undefined> | |
| 191 NullTag = '0', // -> <null> | |
| 192 TrueTag = 'T', // -> <true> | |
| 193 FalseTag = 'F', // -> <false> | |
| 194 StringTag = 'S', // string:RawString -> string | |
| 195 StringUCharTag = 'c', // string:RawUCharString -> string | |
| 196 Int32Tag = 'I', // value:ZigZag-encoded int32 -> Integer | |
| 197 Uint32Tag = 'U', // value:uint32_t -> Integer | |
| 198 DateTag = 'D', // value:double -> Date (ref) | |
| 199 MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with tra
nsferred MessagePort. | |
| 200 NumberTag = 'N', // value:double -> Number | |
| 201 BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> B
lob (ref) | |
| 202 BlobIndexTag = 'i', // index:int32_t -> Blob (ref) | |
| 203 FileTag = 'f', // file:RawFile -> File (ref) | |
| 204 FileIndexTag = 'e', // index:int32_t -> File (ref) | |
| 205 DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreStr
ing -> FileSystem (ref) | |
| 206 FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (re
f) | |
| 207 FileListIndexTag = 'L', // length:uint32_t, files:int32_t[length] -> FileLis
t (ref) | |
| 208 ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint
32_t, data:byte[pixelDataLength] -> ImageData (ref) | |
| 209 ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the
open stack; | |
| 210 // fills it with the last numProp
erties name,value pairs pushed onto the deserialization stack | |
| 211 SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the
last object from the open stack; | |
| 212 // fills it
with the last numProperties name,value pairs pushed onto the deserialization st
ack | |
| 213 DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the
last object from the open stack; | |
| 214 // fills it
with the last length elements and numProperties name,value pairs pushed onto des
erialization stack | |
| 215 RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref) | |
| 216 ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> Array
Buffer (ref) | |
| 217 ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuf
fer transfer | |
| 218 ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:ui
nt32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the des
erialization stack. | |
| 219 CryptoKeyTag = 'K', // subtag:byte, props, usages:uint32_t, keyDataLength:ui
nt32_t, keyData:byte[keyDataLength] | |
| 220 // If subtag=AesKeyTag: | |
| 221 // props = keyLengthBytes:uint32_t, algorithmId:ui
nt32_t | |
| 222 // If subtag=HmacKeyTag: | |
| 223 // props = keyLengthBytes:uint32_t, hashId:uint32_
t | |
| 224 // If subtag=RsaHashedKeyTag: | |
| 225 // props = algorithmId:uint32_t, type:uint32_t, mo
dulusLengthBits:uint32_t, publicExponentLength:uint32_t, publicExponent:byte[pub
licExponentLength], hashId:uint32_t | |
| 226 // If subtag=EcKeyTag: | |
| 227 // props = algorithmId:uint32_t, type:uint32_t, na
medCurve:uint32_t | |
| 228 ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref] | |
| 229 GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and
pushed onto the open stack (ref) | |
| 230 GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length]
allocated an object ID and pushed onto the open stack (ref) | |
| 231 GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length]
allocated an object ID and pushed onto the open stack (ref) | |
| 232 ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table
is not refTableSize big, fails. | |
| 233 StringObjectTag = 's', // string:RawString -> new String(string) (ref) | |
| 234 NumberObjectTag = 'n', // value:double -> new Number(value) (ref) | |
| 235 TrueObjectTag = 'y', // new Boolean(true) (ref) | |
| 236 FalseObjectTag = 'x', // new Boolean(false) (ref) | |
| 237 VersionTag = 0xFF // version:uint32_t -> Uses this as the file version. | |
| 238 }; | |
| 239 | |
| 240 enum ArrayBufferViewSubTag { | |
| 241 ByteArrayTag = 'b', | |
| 242 UnsignedByteArrayTag = 'B', | |
| 243 UnsignedByteClampedArrayTag = 'C', | |
| 244 ShortArrayTag = 'w', | |
| 245 UnsignedShortArrayTag = 'W', | |
| 246 IntArrayTag = 'd', | |
| 247 UnsignedIntArrayTag = 'D', | |
| 248 FloatArrayTag = 'f', | |
| 249 DoubleArrayTag = 'F', | |
| 250 DataViewTag = '?' | |
| 251 }; | |
| 252 | |
| 253 enum CryptoKeySubTag { | |
| 254 AesKeyTag = 1, | |
| 255 HmacKeyTag = 2, | |
| 256 // ID 3 was used by RsaKeyTag, while still behind experimental flag. | |
| 257 RsaHashedKeyTag = 4, | |
| 258 EcKeyTag = 5, | |
| 259 // Maximum allowed value is 255 | |
| 260 }; | |
| 261 | |
| 262 enum AssymetricCryptoKeyType { | |
| 263 PublicKeyType = 1, | |
| 264 PrivateKeyType = 2, | |
| 265 // Maximum allowed value is 2^32-1 | |
| 266 }; | |
| 267 | |
| 268 enum CryptoKeyAlgorithmTag { | |
| 269 AesCbcTag = 1, | |
| 270 HmacTag = 2, | |
| 271 RsaSsaPkcs1v1_5Tag = 3, | |
| 272 // ID 4 was used by RsaEs, while still behind experimental flag. | |
| 273 Sha1Tag = 5, | |
| 274 Sha256Tag = 6, | |
| 275 Sha384Tag = 7, | |
| 276 Sha512Tag = 8, | |
| 277 AesGcmTag = 9, | |
| 278 RsaOaepTag = 10, | |
| 279 AesCtrTag = 11, | |
| 280 AesKwTag = 12, | |
| 281 RsaPssTag = 13, | |
| 282 EcdsaTag = 14, | |
| 283 // Maximum allowed value is 2^32-1 | |
| 284 }; | |
| 285 | |
| 286 enum NamedCurveTag { | |
| 287 P256Tag = 1, | |
| 288 P384Tag = 2, | |
| 289 P521Tag = 3, | |
| 290 }; | |
| 291 | |
| 292 enum CryptoKeyUsage { | |
| 293 // Extractability is not a "usage" in the WebCryptoKeyUsages sense, however | |
| 294 // it fits conveniently into this bitfield. | |
| 295 ExtractableUsage = 1 << 0, | |
| 296 | |
| 297 EncryptUsage = 1 << 1, | |
| 298 DecryptUsage = 1 << 2, | |
| 299 SignUsage = 1 << 3, | |
| 300 VerifyUsage = 1 << 4, | |
| 301 DeriveKeyUsage = 1 << 5, | |
| 302 WrapKeyUsage = 1 << 6, | |
| 303 UnwrapKeyUsage = 1 << 7, | |
| 304 DeriveBitsUsage = 1 << 8, | |
| 305 // Maximum allowed value is 1 << 31 | |
| 306 }; | |
| 307 | |
| 308 static bool shouldCheckForCycles(int depth) | |
| 309 { | |
| 310 ASSERT(depth >= 0); | |
| 311 // Since we are not required to spot the cycle as soon as it | |
| 312 // happens we can check for cycles only when the current depth | |
| 313 // is a power of two. | |
| 314 return !(depth & (depth - 1)); | |
| 315 } | |
| 316 | |
| 317 static const int maxDepth = 20000; | |
| 318 | |
| 319 // VarInt encoding constants. | |
| 320 static const int varIntShift = 7; | |
| 321 static const int varIntMask = (1 << varIntShift) - 1; | |
| 322 | |
| 323 // ZigZag encoding helps VarInt encoding stay small for negative | |
| 324 // numbers with small absolute values. | |
| 325 class ZigZag { | |
| 326 public: | |
| 327 static uint32_t encode(uint32_t value) | |
| 328 { | |
| 329 if (value & (1U << 31)) | |
| 330 value = ((~value) << 1) + 1; | |
| 331 else | |
| 332 value <<= 1; | |
| 333 return value; | |
| 334 } | |
| 335 | |
| 336 static uint32_t decode(uint32_t value) | |
| 337 { | |
| 338 if (value & 1) | |
| 339 value = ~(value >> 1); | |
| 340 else | |
| 341 value >>= 1; | |
| 342 return value; | |
| 343 } | |
| 344 | |
| 345 private: | |
| 346 ZigZag(); | |
| 347 }; | |
| 348 | |
| 349 // Writer is responsible for serializing primitive types and storing | |
| 350 // information used to reconstruct composite types. | |
| 351 class Writer { | |
| 352 WTF_MAKE_NONCOPYABLE(Writer); | |
| 353 public: | |
| 354 Writer() | |
| 355 : m_position(0) | |
| 356 { | |
| 357 } | |
| 358 | |
| 359 // Write functions for primitive types. | |
| 360 | |
| 361 void writeUndefined() { append(UndefinedTag); } | |
| 362 | |
| 363 void writeNull() { append(NullTag); } | |
| 364 | |
| 365 void writeTrue() { append(TrueTag); } | |
| 366 | |
| 367 void writeFalse() { append(FalseTag); } | |
| 368 | |
| 369 void writeBooleanObject(bool value) | |
| 370 { | |
| 371 append(value ? TrueObjectTag : FalseObjectTag); | |
| 372 } | |
| 373 | |
| 374 void writeOneByteString(v8::Handle<v8::String>& string) | |
| 375 { | |
| 376 int stringLength = string->Length(); | |
| 377 int utf8Length = string->Utf8Length(); | |
| 378 ASSERT(stringLength >= 0 && utf8Length >= 0); | |
| 379 | |
| 380 append(StringTag); | |
| 381 doWriteUint32(static_cast<uint32_t>(utf8Length)); | |
| 382 ensureSpace(utf8Length); | |
| 383 | |
| 384 // ASCII fast path. | |
| 385 if (stringLength == utf8Length) { | |
| 386 string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWrit
eOptions()); | |
| 387 } else { | |
| 388 char* buffer = reinterpret_cast<char*>(byteAt(m_position)); | |
| 389 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions()); | |
| 390 } | |
| 391 m_position += utf8Length; | |
| 392 } | |
| 393 | |
| 394 void writeUCharString(v8::Handle<v8::String>& string) | |
| 395 { | |
| 396 int length = string->Length(); | |
| 397 ASSERT(length >= 0); | |
| 398 | |
| 399 int size = length * sizeof(UChar); | |
| 400 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size)); | |
| 401 if ((m_position + 1 + bytes) & 1) | |
| 402 append(PaddingTag); | |
| 403 | |
| 404 append(StringUCharTag); | |
| 405 doWriteUint32(static_cast<uint32_t>(size)); | |
| 406 ensureSpace(size); | |
| 407 | |
| 408 ASSERT(!(m_position & 1)); | |
| 409 uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position)); | |
| 410 string->Write(buffer, 0, length, v8StringWriteOptions()); | |
| 411 m_position += size; | |
| 412 } | |
| 413 | |
| 414 void writeStringObject(const char* data, int length) | |
| 415 { | |
| 416 ASSERT(length >= 0); | |
| 417 append(StringObjectTag); | |
| 418 doWriteString(data, length); | |
| 419 } | |
| 420 | |
| 421 void writeWebCoreString(const String& string) | |
| 422 { | |
| 423 // Uses UTF8 encoding so we can read it back as either V8 or | |
| 424 // WebCore string. | |
| 425 append(StringTag); | |
| 426 doWriteWebCoreString(string); | |
| 427 } | |
| 428 | |
| 429 void writeVersion() | |
| 430 { | |
| 431 append(VersionTag); | |
| 432 doWriteUint32(SerializedScriptValue::wireFormatVersion); | |
| 433 } | |
| 434 | |
| 435 void writeInt32(int32_t value) | |
| 436 { | |
| 437 append(Int32Tag); | |
| 438 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value))); | |
| 439 } | |
| 440 | |
| 441 void writeUint32(uint32_t value) | |
| 442 { | |
| 443 append(Uint32Tag); | |
| 444 doWriteUint32(value); | |
| 445 } | |
| 446 | |
| 447 void writeDate(double numberValue) | |
| 448 { | |
| 449 append(DateTag); | |
| 450 doWriteNumber(numberValue); | |
| 451 } | |
| 452 | |
| 453 void writeNumber(double number) | |
| 454 { | |
| 455 append(NumberTag); | |
| 456 doWriteNumber(number); | |
| 457 } | |
| 458 | |
| 459 void writeNumberObject(double number) | |
| 460 { | |
| 461 append(NumberObjectTag); | |
| 462 doWriteNumber(number); | |
| 463 } | |
| 464 | |
| 465 void writeBlob(const String& uuid, const String& type, unsigned long long si
ze) | |
| 466 { | |
| 467 append(BlobTag); | |
| 468 doWriteWebCoreString(uuid); | |
| 469 doWriteWebCoreString(type); | |
| 470 doWriteUint64(size); | |
| 471 } | |
| 472 | |
| 473 void writeBlobIndex(int blobIndex) | |
| 474 { | |
| 475 ASSERT(blobIndex >= 0); | |
| 476 append(BlobIndexTag); | |
| 477 doWriteUint32(blobIndex); | |
| 478 } | |
| 479 | |
| 480 void writeDOMFileSystem(int type, const String& name, const String& url) | |
| 481 { | |
| 482 append(DOMFileSystemTag); | |
| 483 doWriteUint32(type); | |
| 484 doWriteWebCoreString(name); | |
| 485 doWriteWebCoreString(url); | |
| 486 } | |
| 487 | |
| 488 void writeFile(const File& file) | |
| 489 { | |
| 490 append(FileTag); | |
| 491 doWriteFile(file); | |
| 492 } | |
| 493 | |
| 494 void writeFileIndex(int blobIndex) | |
| 495 { | |
| 496 append(FileIndexTag); | |
| 497 doWriteUint32(blobIndex); | |
| 498 } | |
| 499 | |
| 500 void writeFileList(const FileList& fileList) | |
| 501 { | |
| 502 append(FileListTag); | |
| 503 uint32_t length = fileList.length(); | |
| 504 doWriteUint32(length); | |
| 505 for (unsigned i = 0; i < length; ++i) | |
| 506 doWriteFile(*fileList.item(i)); | |
| 507 } | |
| 508 | |
| 509 void writeFileListIndex(const Vector<int>& blobIndices) | |
| 510 { | |
| 511 append(FileListIndexTag); | |
| 512 uint32_t length = blobIndices.size(); | |
| 513 doWriteUint32(length); | |
| 514 for (unsigned i = 0; i < length; ++i) | |
| 515 doWriteUint32(blobIndices[i]); | |
| 516 } | |
| 517 | |
| 518 bool writeCryptoKey(const WebCryptoKey& key) | |
| 519 { | |
| 520 append(static_cast<uint8_t>(CryptoKeyTag)); | |
| 521 | |
| 522 switch (key.algorithm().paramsType()) { | |
| 523 case WebCryptoKeyAlgorithmParamsTypeAes: | |
| 524 doWriteAesKey(key); | |
| 525 break; | |
| 526 case WebCryptoKeyAlgorithmParamsTypeHmac: | |
| 527 doWriteHmacKey(key); | |
| 528 break; | |
| 529 case WebCryptoKeyAlgorithmParamsTypeRsaHashed: | |
| 530 doWriteRsaHashedKey(key); | |
| 531 break; | |
| 532 case WebCryptoKeyAlgorithmParamsTypeEc: | |
| 533 doWriteEcKey(key); | |
| 534 break; | |
| 535 case WebCryptoKeyAlgorithmParamsTypeNone: | |
| 536 ASSERT_NOT_REACHED(); | |
| 537 return false; | |
| 538 } | |
| 539 | |
| 540 doWriteKeyUsages(key.usages(), key.extractable()); | |
| 541 | |
| 542 WebVector<uint8_t> keyData; | |
| 543 if (!Platform::current()->crypto()->serializeKeyForClone(key, keyData)) | |
| 544 return false; | |
| 545 | |
| 546 doWriteUint32(keyData.size()); | |
| 547 append(keyData.data(), keyData.size()); | |
| 548 return true; | |
| 549 } | |
| 550 | |
| 551 void writeArrayBuffer(const ArrayBuffer& arrayBuffer) | |
| 552 { | |
| 553 append(ArrayBufferTag); | |
| 554 doWriteArrayBuffer(arrayBuffer); | |
| 555 } | |
| 556 | |
| 557 void writeArrayBufferView(const ArrayBufferView& arrayBufferView) | |
| 558 { | |
| 559 append(ArrayBufferViewTag); | |
| 560 #if ENABLE(ASSERT) | |
| 561 const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer(); | |
| 562 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView
.byteOffset() == | |
| 563 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); | |
| 564 #endif | |
| 565 ArrayBufferView::ViewType type = arrayBufferView.type(); | |
| 566 | |
| 567 if (type == ArrayBufferView::TypeInt8) | |
| 568 append(ByteArrayTag); | |
| 569 else if (type == ArrayBufferView::TypeUint8Clamped) | |
| 570 append(UnsignedByteClampedArrayTag); | |
| 571 else if (type == ArrayBufferView::TypeUint8) | |
| 572 append(UnsignedByteArrayTag); | |
| 573 else if (type == ArrayBufferView::TypeInt16) | |
| 574 append(ShortArrayTag); | |
| 575 else if (type == ArrayBufferView::TypeUint16) | |
| 576 append(UnsignedShortArrayTag); | |
| 577 else if (type == ArrayBufferView::TypeInt32) | |
| 578 append(IntArrayTag); | |
| 579 else if (type == ArrayBufferView::TypeUint32) | |
| 580 append(UnsignedIntArrayTag); | |
| 581 else if (type == ArrayBufferView::TypeFloat32) | |
| 582 append(FloatArrayTag); | |
| 583 else if (type == ArrayBufferView::TypeFloat64) | |
| 584 append(DoubleArrayTag); | |
| 585 else if (type == ArrayBufferView::TypeDataView) | |
| 586 append(DataViewTag); | |
| 587 else | |
| 588 ASSERT_NOT_REACHED(); | |
| 589 doWriteUint32(arrayBufferView.byteOffset()); | |
| 590 doWriteUint32(arrayBufferView.byteLength()); | |
| 591 } | |
| 592 | |
| 593 void writeImageData(uint32_t width, uint32_t height, const uint8_t* pixelDat
a, uint32_t pixelDataLength) | |
| 594 { | |
| 595 append(ImageDataTag); | |
| 596 doWriteUint32(width); | |
| 597 doWriteUint32(height); | |
| 598 doWriteUint32(pixelDataLength); | |
| 599 append(pixelData, pixelDataLength); | |
| 600 } | |
| 601 | |
| 602 void writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags) | |
| 603 { | |
| 604 append(RegExpTag); | |
| 605 v8::String::Utf8Value patternUtf8Value(pattern); | |
| 606 doWriteString(*patternUtf8Value, patternUtf8Value.length()); | |
| 607 doWriteUint32(static_cast<uint32_t>(flags)); | |
| 608 } | |
| 609 | |
| 610 void writeTransferredMessagePort(uint32_t index) | |
| 611 { | |
| 612 append(MessagePortTag); | |
| 613 doWriteUint32(index); | |
| 614 } | |
| 615 | |
| 616 void writeTransferredArrayBuffer(uint32_t index) | |
| 617 { | |
| 618 append(ArrayBufferTransferTag); | |
| 619 doWriteUint32(index); | |
| 620 } | |
| 621 | |
| 622 void writeObjectReference(uint32_t reference) | |
| 623 { | |
| 624 append(ObjectReferenceTag); | |
| 625 doWriteUint32(reference); | |
| 626 } | |
| 627 | |
| 628 void writeObject(uint32_t numProperties) | |
| 629 { | |
| 630 append(ObjectTag); | |
| 631 doWriteUint32(numProperties); | |
| 632 } | |
| 633 | |
| 634 void writeSparseArray(uint32_t numProperties, uint32_t length) | |
| 635 { | |
| 636 append(SparseArrayTag); | |
| 637 doWriteUint32(numProperties); | |
| 638 doWriteUint32(length); | |
| 639 } | |
| 640 | |
| 641 void writeDenseArray(uint32_t numProperties, uint32_t length) | |
| 642 { | |
| 643 append(DenseArrayTag); | |
| 644 doWriteUint32(numProperties); | |
| 645 doWriteUint32(length); | |
| 646 } | |
| 647 | |
| 648 String takeWireString() | |
| 649 { | |
| 650 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); | |
| 651 fillHole(); | |
| 652 String data = String(m_buffer.data(), m_buffer.size()); | |
| 653 data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferVa
lueType)); | |
| 654 return data; | |
| 655 } | |
| 656 | |
| 657 void writeReferenceCount(uint32_t numberOfReferences) | |
| 658 { | |
| 659 append(ReferenceCountTag); | |
| 660 doWriteUint32(numberOfReferences); | |
| 661 } | |
| 662 | |
| 663 void writeGenerateFreshObject() | |
| 664 { | |
| 665 append(GenerateFreshObjectTag); | |
| 666 } | |
| 667 | |
| 668 void writeGenerateFreshSparseArray(uint32_t length) | |
| 669 { | |
| 670 append(GenerateFreshSparseArrayTag); | |
| 671 doWriteUint32(length); | |
| 672 } | |
| 673 | |
| 674 void writeGenerateFreshDenseArray(uint32_t length) | |
| 675 { | |
| 676 append(GenerateFreshDenseArrayTag); | |
| 677 doWriteUint32(length); | |
| 678 } | |
| 679 | |
| 680 private: | |
| 681 void doWriteFile(const File& file) | |
| 682 { | |
| 683 doWriteWebCoreString(file.hasBackingFile() ? file.path() : ""); | |
| 684 doWriteWebCoreString(file.name()); | |
| 685 doWriteWebCoreString(file.webkitRelativePath()); | |
| 686 doWriteWebCoreString(file.uuid()); | |
| 687 doWriteWebCoreString(file.type()); | |
| 688 | |
| 689 // FIXME don't use 1 byte to encode a flag. | |
| 690 if (file.hasValidSnapshotMetadata()) { | |
| 691 doWriteUint32(static_cast<uint8_t>(1)); | |
| 692 | |
| 693 long long size; | |
| 694 double lastModified; | |
| 695 file.captureSnapshot(size, lastModified); | |
| 696 doWriteUint64(static_cast<uint64_t>(size)); | |
| 697 doWriteNumber(lastModified); | |
| 698 } else { | |
| 699 doWriteUint32(static_cast<uint8_t>(0)); | |
| 700 } | |
| 701 | |
| 702 doWriteUint32(static_cast<uint8_t>((file.userVisibility() == File::IsUse
rVisible) ? 1 : 0)); | |
| 703 } | |
| 704 | |
| 705 void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer) | |
| 706 { | |
| 707 uint32_t byteLength = arrayBuffer.byteLength(); | |
| 708 doWriteUint32(byteLength); | |
| 709 append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength); | |
| 710 } | |
| 711 | |
| 712 void doWriteString(const char* data, int length) | |
| 713 { | |
| 714 doWriteUint32(static_cast<uint32_t>(length)); | |
| 715 append(reinterpret_cast<const uint8_t*>(data), length); | |
| 716 } | |
| 717 | |
| 718 void doWriteWebCoreString(const String& string) | |
| 719 { | |
| 720 StringUTF8Adaptor stringUTF8(string); | |
| 721 doWriteString(stringUTF8.data(), stringUTF8.length()); | |
| 722 } | |
| 723 | |
| 724 void doWriteHmacKey(const WebCryptoKey& key) | |
| 725 { | |
| 726 ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeHm
ac); | |
| 727 | |
| 728 append(static_cast<uint8_t>(HmacKeyTag)); | |
| 729 ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8)); | |
| 730 doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8); | |
| 731 doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id()); | |
| 732 } | |
| 733 | |
| 734 void doWriteAesKey(const WebCryptoKey& key) | |
| 735 { | |
| 736 ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeAe
s); | |
| 737 | |
| 738 append(static_cast<uint8_t>(AesKeyTag)); | |
| 739 doWriteAlgorithmId(key.algorithm().id()); | |
| 740 // Converting the key length from bits to bytes is lossless and makes | |
| 741 // it fit in 1 byte. | |
| 742 ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8)); | |
| 743 doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8); | |
| 744 } | |
| 745 | |
| 746 void doWriteRsaHashedKey(const WebCryptoKey& key) | |
| 747 { | |
| 748 ASSERT(key.algorithm().rsaHashedParams()); | |
| 749 append(static_cast<uint8_t>(RsaHashedKeyTag)); | |
| 750 | |
| 751 doWriteAlgorithmId(key.algorithm().id()); | |
| 752 doWriteAsymmetricKeyType(key.type()); | |
| 753 | |
| 754 const WebCryptoRsaHashedKeyAlgorithmParams* params = key.algorithm().rsa
HashedParams(); | |
| 755 doWriteUint32(params->modulusLengthBits()); | |
| 756 doWriteUint32(params->publicExponent().size()); | |
| 757 append(params->publicExponent().data(), params->publicExponent().size())
; | |
| 758 doWriteAlgorithmId(params->hash().id()); | |
| 759 } | |
| 760 | |
| 761 void doWriteEcKey(const WebCryptoKey& key) | |
| 762 { | |
| 763 ASSERT(key.algorithm().ecParams()); | |
| 764 append(static_cast<uint8_t>(EcKeyTag)); | |
| 765 | |
| 766 doWriteAlgorithmId(key.algorithm().id()); | |
| 767 doWriteAsymmetricKeyType(key.type()); | |
| 768 doWriteNamedCurve(key.algorithm().ecParams()->namedCurve()); | |
| 769 } | |
| 770 | |
| 771 void doWriteAlgorithmId(WebCryptoAlgorithmId id) | |
| 772 { | |
| 773 switch (id) { | |
| 774 case WebCryptoAlgorithmIdAesCbc: | |
| 775 return doWriteUint32(AesCbcTag); | |
| 776 case WebCryptoAlgorithmIdHmac: | |
| 777 return doWriteUint32(HmacTag); | |
| 778 case WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | |
| 779 return doWriteUint32(RsaSsaPkcs1v1_5Tag); | |
| 780 case WebCryptoAlgorithmIdSha1: | |
| 781 return doWriteUint32(Sha1Tag); | |
| 782 case WebCryptoAlgorithmIdSha256: | |
| 783 return doWriteUint32(Sha256Tag); | |
| 784 case WebCryptoAlgorithmIdSha384: | |
| 785 return doWriteUint32(Sha384Tag); | |
| 786 case WebCryptoAlgorithmIdSha512: | |
| 787 return doWriteUint32(Sha512Tag); | |
| 788 case WebCryptoAlgorithmIdAesGcm: | |
| 789 return doWriteUint32(AesGcmTag); | |
| 790 case WebCryptoAlgorithmIdRsaOaep: | |
| 791 return doWriteUint32(RsaOaepTag); | |
| 792 case WebCryptoAlgorithmIdAesCtr: | |
| 793 return doWriteUint32(AesCtrTag); | |
| 794 case WebCryptoAlgorithmIdAesKw: | |
| 795 return doWriteUint32(AesKwTag); | |
| 796 case WebCryptoAlgorithmIdRsaPss: | |
| 797 return doWriteUint32(RsaPssTag); | |
| 798 case WebCryptoAlgorithmIdEcdsa: | |
| 799 return doWriteUint32(EcdsaTag); | |
| 800 } | |
| 801 ASSERT_NOT_REACHED(); | |
| 802 } | |
| 803 | |
| 804 void doWriteAsymmetricKeyType(WebCryptoKeyType keyType) | |
| 805 { | |
| 806 switch (keyType) { | |
| 807 case WebCryptoKeyTypePublic: | |
| 808 doWriteUint32(PublicKeyType); | |
| 809 break; | |
| 810 case WebCryptoKeyTypePrivate: | |
| 811 doWriteUint32(PrivateKeyType); | |
| 812 break; | |
| 813 case WebCryptoKeyTypeSecret: | |
| 814 ASSERT_NOT_REACHED(); | |
| 815 } | |
| 816 } | |
| 817 | |
| 818 void doWriteNamedCurve(WebCryptoNamedCurve namedCurve) | |
| 819 { | |
| 820 switch (namedCurve) { | |
| 821 case WebCryptoNamedCurveP256: | |
| 822 return doWriteUint32(P256Tag); | |
| 823 case WebCryptoNamedCurveP384: | |
| 824 return doWriteUint32(P384Tag); | |
| 825 case WebCryptoNamedCurveP521: | |
| 826 return doWriteUint32(P521Tag); | |
| 827 } | |
| 828 ASSERT_NOT_REACHED(); | |
| 829 } | |
| 830 | |
| 831 void doWriteKeyUsages(const WebCryptoKeyUsageMask usages, bool extractable) | |
| 832 { | |
| 833 // Reminder to update this when adding new key usages. | |
| 834 COMPILE_ASSERT(EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); | |
| 835 | |
| 836 uint32_t value = 0; | |
| 837 | |
| 838 if (extractable) | |
| 839 value |= ExtractableUsage; | |
| 840 | |
| 841 if (usages & WebCryptoKeyUsageEncrypt) | |
| 842 value |= EncryptUsage; | |
| 843 if (usages & WebCryptoKeyUsageDecrypt) | |
| 844 value |= DecryptUsage; | |
| 845 if (usages & WebCryptoKeyUsageSign) | |
| 846 value |= SignUsage; | |
| 847 if (usages & WebCryptoKeyUsageVerify) | |
| 848 value |= VerifyUsage; | |
| 849 if (usages & WebCryptoKeyUsageDeriveKey) | |
| 850 value |= DeriveKeyUsage; | |
| 851 if (usages & WebCryptoKeyUsageWrapKey) | |
| 852 value |= WrapKeyUsage; | |
| 853 if (usages & WebCryptoKeyUsageUnwrapKey) | |
| 854 value |= UnwrapKeyUsage; | |
| 855 if (usages & WebCryptoKeyUsageDeriveBits) | |
| 856 value |= DeriveBitsUsage; | |
| 857 | |
| 858 doWriteUint32(value); | |
| 859 } | |
| 860 | |
| 861 int bytesNeededToWireEncode(uint32_t value) | |
| 862 { | |
| 863 int bytes = 1; | |
| 864 while (true) { | |
| 865 value >>= varIntShift; | |
| 866 if (!value) | |
| 867 break; | |
| 868 ++bytes; | |
| 869 } | |
| 870 | |
| 871 return bytes; | |
| 872 } | |
| 873 | |
| 874 template<class T> | |
| 875 void doWriteUintHelper(T value) | |
| 876 { | |
| 877 while (true) { | |
| 878 uint8_t b = (value & varIntMask); | |
| 879 value >>= varIntShift; | |
| 880 if (!value) { | |
| 881 append(b); | |
| 882 break; | |
| 883 } | |
| 884 append(b | (1 << varIntShift)); | |
| 885 } | |
| 886 } | |
| 887 | |
| 888 void doWriteUint32(uint32_t value) | |
| 889 { | |
| 890 doWriteUintHelper(value); | |
| 891 } | |
| 892 | |
| 893 void doWriteUint64(uint64_t value) | |
| 894 { | |
| 895 doWriteUintHelper(value); | |
| 896 } | |
| 897 | |
| 898 void doWriteNumber(double number) | |
| 899 { | |
| 900 append(reinterpret_cast<uint8_t*>(&number), sizeof(number)); | |
| 901 } | |
| 902 | |
| 903 void append(SerializationTag tag) | |
| 904 { | |
| 905 append(static_cast<uint8_t>(tag)); | |
| 906 } | |
| 907 | |
| 908 void append(uint8_t b) | |
| 909 { | |
| 910 ensureSpace(1); | |
| 911 *byteAt(m_position++) = b; | |
| 912 } | |
| 913 | |
| 914 void append(const uint8_t* data, int length) | |
| 915 { | |
| 916 ensureSpace(length); | |
| 917 memcpy(byteAt(m_position), data, length); | |
| 918 m_position += length; | |
| 919 } | |
| 920 | |
| 921 void ensureSpace(unsigned extra) | |
| 922 { | |
| 923 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); | |
| 924 m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); //
"+ 1" to round up. | |
| 925 } | |
| 926 | |
| 927 void fillHole() | |
| 928 { | |
| 929 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); | |
| 930 // If the writer is at odd position in the buffer, then one of | |
| 931 // the bytes in the last UChar is not initialized. | |
| 932 if (m_position % 2) | |
| 933 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag); | |
| 934 } | |
| 935 | |
| 936 uint8_t* byteAt(int position) | |
| 937 { | |
| 938 return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; | |
| 939 } | |
| 940 | |
| 941 int v8StringWriteOptions() | |
| 942 { | |
| 943 return v8::String::NO_NULL_TERMINATION; | |
| 944 } | |
| 945 | |
| 946 Vector<BufferValueType> m_buffer; | |
| 947 unsigned m_position; | |
| 948 }; | |
| 949 | |
| 950 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Handle<v8::Objec
t> creationContext, v8::Isolate* isolate) | |
| 951 { | |
| 952 if (!impl) | |
| 953 return v8::Handle<v8::Object>(); | |
| 954 v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 955 ASSERT(wrapper->IsObject()); | |
| 956 return wrapper.As<v8::Object>(); | |
| 957 } | |
| 958 | |
| 959 static v8::Handle<v8::ArrayBuffer> toV8Object(DOMArrayBuffer* impl, v8::Handle<v
8::Object> creationContext, v8::Isolate* isolate) | |
| 960 { | |
| 961 if (!impl) | |
| 962 return v8::Handle<v8::ArrayBuffer>(); | |
| 963 v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); | |
| 964 ASSERT(wrapper->IsArrayBuffer()); | |
| 965 return wrapper.As<v8::ArrayBuffer>(); | |
| 966 } | |
| 967 | |
| 968 class Serializer { | |
| 969 class StateBase; | |
| 970 public: | |
| 971 enum Status { | |
| 972 Success, | |
| 973 InputError, | |
| 974 DataCloneError, | |
| 975 JSException | |
| 976 }; | |
| 977 | |
| 978 Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray*
arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v
8::TryCatch& tryCatch, ScriptState* scriptState) | |
| 979 : m_scriptState(scriptState) | |
| 980 , m_writer(writer) | |
| 981 , m_tryCatch(tryCatch) | |
| 982 , m_depth(0) | |
| 983 , m_status(Success) | |
| 984 , m_nextObjectReference(0) | |
| 985 , m_blobInfo(blobInfo) | |
| 986 , m_blobDataHandles(blobDataHandles) | |
| 987 { | |
| 988 ASSERT(!tryCatch.HasCaught()); | |
| 989 v8::Handle<v8::Object> creationContext = m_scriptState->context()->Globa
l(); | |
| 990 if (messagePorts) { | |
| 991 for (size_t i = 0; i < messagePorts->size(); i++) | |
| 992 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get
(), creationContext, isolate()), i); | |
| 993 } | |
| 994 if (arrayBuffers) { | |
| 995 for (size_t i = 0; i < arrayBuffers->size(); i++) { | |
| 996 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->
at(i).get(), creationContext, isolate()); | |
| 997 // Coalesce multiple occurences of the same buffer to the first
index. | |
| 998 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) | |
| 999 m_transferredArrayBuffers.set(v8ArrayBuffer, i); | |
| 1000 } | |
| 1001 } | |
| 1002 } | |
| 1003 | |
| 1004 v8::Isolate* isolate() { return m_scriptState->isolate(); } | |
| 1005 | |
| 1006 Status serialize(v8::Handle<v8::Value> value) | |
| 1007 { | |
| 1008 v8::HandleScope scope(isolate()); | |
| 1009 m_writer.writeVersion(); | |
| 1010 StateBase* state = doSerialize(value, 0); | |
| 1011 while (state) | |
| 1012 state = state->advance(*this); | |
| 1013 return m_status; | |
| 1014 } | |
| 1015 | |
| 1016 String errorMessage() { return m_errorMessage; } | |
| 1017 | |
| 1018 // Functions used by serialization states. | |
| 1019 StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); | |
| 1020 | |
| 1021 StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBa
se* next) | |
| 1022 { | |
| 1023 return doSerialize(arrayBuffer, next); | |
| 1024 } | |
| 1025 | |
| 1026 StateBase* checkException(StateBase* state) | |
| 1027 { | |
| 1028 return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0; | |
| 1029 } | |
| 1030 | |
| 1031 StateBase* writeObject(uint32_t numProperties, StateBase* state) | |
| 1032 { | |
| 1033 m_writer.writeObject(numProperties); | |
| 1034 return pop(state); | |
| 1035 } | |
| 1036 | |
| 1037 StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBa
se* state) | |
| 1038 { | |
| 1039 m_writer.writeSparseArray(numProperties, length); | |
| 1040 return pop(state); | |
| 1041 } | |
| 1042 | |
| 1043 StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBas
e* state) | |
| 1044 { | |
| 1045 m_writer.writeDenseArray(numProperties, length); | |
| 1046 return pop(state); | |
| 1047 } | |
| 1048 | |
| 1049 | |
| 1050 private: | |
| 1051 class StateBase { | |
| 1052 WTF_MAKE_NONCOPYABLE(StateBase); | |
| 1053 public: | |
| 1054 virtual ~StateBase() { } | |
| 1055 | |
| 1056 // Link to the next state to form a stack. | |
| 1057 StateBase* nextState() { return m_next; } | |
| 1058 | |
| 1059 // Composite object we're processing in this state. | |
| 1060 v8::Handle<v8::Value> composite() { return m_composite; } | |
| 1061 | |
| 1062 // Serializes (a part of) the current composite and returns | |
| 1063 // the next state to process or null when this is the final | |
| 1064 // state. | |
| 1065 virtual StateBase* advance(Serializer&) = 0; | |
| 1066 | |
| 1067 protected: | |
| 1068 StateBase(v8::Handle<v8::Value> composite, StateBase* next) | |
| 1069 : m_composite(composite) | |
| 1070 , m_next(next) | |
| 1071 { | |
| 1072 } | |
| 1073 | |
| 1074 private: | |
| 1075 v8::Handle<v8::Value> m_composite; | |
| 1076 StateBase* m_next; | |
| 1077 }; | |
| 1078 | |
| 1079 // Dummy state that is used to signal serialization errors. | |
| 1080 class ErrorState final : public StateBase { | |
| 1081 public: | |
| 1082 ErrorState() | |
| 1083 : StateBase(v8Undefined(), 0) | |
| 1084 { | |
| 1085 } | |
| 1086 | |
| 1087 virtual StateBase* advance(Serializer&) override | |
| 1088 { | |
| 1089 delete this; | |
| 1090 return 0; | |
| 1091 } | |
| 1092 }; | |
| 1093 | |
| 1094 template <typename T> | |
| 1095 class State : public StateBase { | |
| 1096 public: | |
| 1097 v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::compos
ite()); } | |
| 1098 | |
| 1099 protected: | |
| 1100 State(v8::Handle<T> composite, StateBase* next) | |
| 1101 : StateBase(composite, next) | |
| 1102 { | |
| 1103 } | |
| 1104 }; | |
| 1105 | |
| 1106 class AbstractObjectState : public State<v8::Object> { | |
| 1107 public: | |
| 1108 AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next) | |
| 1109 : State<v8::Object>(object, next) | |
| 1110 , m_index(0) | |
| 1111 , m_numSerializedProperties(0) | |
| 1112 , m_nameDone(false) | |
| 1113 { | |
| 1114 } | |
| 1115 | |
| 1116 protected: | |
| 1117 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; | |
| 1118 | |
| 1119 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serialize
r) | |
| 1120 { | |
| 1121 while (m_index < m_propertyNames->Length()) { | |
| 1122 if (!m_nameDone) { | |
| 1123 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_i
ndex); | |
| 1124 if (StateBase* newState = serializer.checkException(this)) | |
| 1125 return newState; | |
| 1126 if (propertyName.IsEmpty()) | |
| 1127 return serializer.handleError(InputError, "Empty propert
y names cannot be cloned.", this); | |
| 1128 bool hasStringProperty = propertyName->IsString() && composi
te()->HasRealNamedProperty(propertyName.As<v8::String>()); | |
| 1129 if (StateBase* newState = serializer.checkException(this)) | |
| 1130 return newState; | |
| 1131 bool hasIndexedProperty = !hasStringProperty && propertyName
->IsUint32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value())
; | |
| 1132 if (StateBase* newState = serializer.checkException(this)) | |
| 1133 return newState; | |
| 1134 if (hasStringProperty || (hasIndexedProperty && !ignoreIndex
ed)) { | |
| 1135 m_propertyName = propertyName; | |
| 1136 } else { | |
| 1137 ++m_index; | |
| 1138 continue; | |
| 1139 } | |
| 1140 } | |
| 1141 ASSERT(!m_propertyName.IsEmpty()); | |
| 1142 if (!m_nameDone) { | |
| 1143 m_nameDone = true; | |
| 1144 if (StateBase* newState = serializer.doSerialize(m_propertyN
ame, this)) | |
| 1145 return newState; | |
| 1146 } | |
| 1147 v8::Local<v8::Value> value = composite()->Get(m_propertyName); | |
| 1148 if (StateBase* newState = serializer.checkException(this)) | |
| 1149 return newState; | |
| 1150 m_nameDone = false; | |
| 1151 m_propertyName.Clear(); | |
| 1152 ++m_index; | |
| 1153 ++m_numSerializedProperties; | |
| 1154 // If we return early here, it's either because we have pushed a
new state onto the | |
| 1155 // serialization state stack or because we have encountered an e
rror (and in both cases | |
| 1156 // we are unwinding the native stack). | |
| 1157 if (StateBase* newState = serializer.doSerialize(value, this)) | |
| 1158 return newState; | |
| 1159 } | |
| 1160 return objectDone(m_numSerializedProperties, serializer); | |
| 1161 } | |
| 1162 | |
| 1163 v8::Local<v8::Array> m_propertyNames; | |
| 1164 | |
| 1165 private: | |
| 1166 v8::Local<v8::Value> m_propertyName; | |
| 1167 unsigned m_index; | |
| 1168 unsigned m_numSerializedProperties; | |
| 1169 bool m_nameDone; | |
| 1170 }; | |
| 1171 | |
| 1172 class ObjectState final : public AbstractObjectState { | |
| 1173 public: | |
| 1174 ObjectState(v8::Handle<v8::Object> object, StateBase* next) | |
| 1175 : AbstractObjectState(object, next) | |
| 1176 { | |
| 1177 } | |
| 1178 | |
| 1179 virtual StateBase* advance(Serializer& serializer) override | |
| 1180 { | |
| 1181 if (m_propertyNames.IsEmpty()) { | |
| 1182 m_propertyNames = composite()->GetPropertyNames(); | |
| 1183 if (StateBase* newState = serializer.checkException(this)) | |
| 1184 return newState; | |
| 1185 if (m_propertyNames.IsEmpty()) | |
| 1186 return serializer.handleError(InputError, "Empty property na
mes cannot be cloned.", nextState()); | |
| 1187 } | |
| 1188 return serializeProperties(false, serializer); | |
| 1189 } | |
| 1190 | |
| 1191 protected: | |
| 1192 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) override | |
| 1193 { | |
| 1194 return serializer.writeObject(numProperties, this); | |
| 1195 } | |
| 1196 }; | |
| 1197 | |
| 1198 class DenseArrayState final : public AbstractObjectState { | |
| 1199 public: | |
| 1200 DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> prope
rtyNames, StateBase* next, v8::Isolate* isolate) | |
| 1201 : AbstractObjectState(array, next) | |
| 1202 , m_arrayIndex(0) | |
| 1203 , m_arrayLength(array->Length()) | |
| 1204 { | |
| 1205 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); | |
| 1206 } | |
| 1207 | |
| 1208 virtual StateBase* advance(Serializer& serializer) override | |
| 1209 { | |
| 1210 while (m_arrayIndex < m_arrayLength) { | |
| 1211 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m
_arrayIndex); | |
| 1212 m_arrayIndex++; | |
| 1213 if (StateBase* newState = serializer.checkException(this)) | |
| 1214 return newState; | |
| 1215 if (StateBase* newState = serializer.doSerialize(value, this)) | |
| 1216 return newState; | |
| 1217 } | |
| 1218 return serializeProperties(true, serializer); | |
| 1219 } | |
| 1220 | |
| 1221 protected: | |
| 1222 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) override | |
| 1223 { | |
| 1224 return serializer.writeDenseArray(numProperties, m_arrayLength, this
); | |
| 1225 } | |
| 1226 | |
| 1227 private: | |
| 1228 uint32_t m_arrayIndex; | |
| 1229 uint32_t m_arrayLength; | |
| 1230 }; | |
| 1231 | |
| 1232 class SparseArrayState final : public AbstractObjectState { | |
| 1233 public: | |
| 1234 SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> prop
ertyNames, StateBase* next, v8::Isolate* isolate) | |
| 1235 : AbstractObjectState(array, next) | |
| 1236 { | |
| 1237 m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); | |
| 1238 } | |
| 1239 | |
| 1240 virtual StateBase* advance(Serializer& serializer) override | |
| 1241 { | |
| 1242 return serializeProperties(false, serializer); | |
| 1243 } | |
| 1244 | |
| 1245 protected: | |
| 1246 virtual StateBase* objectDone(unsigned numProperties, Serializer& serial
izer) override | |
| 1247 { | |
| 1248 return serializer.writeSparseArray(numProperties, composite().As<v8:
:Array>()->Length(), this); | |
| 1249 } | |
| 1250 }; | |
| 1251 | |
| 1252 StateBase* push(StateBase* state) | |
| 1253 { | |
| 1254 ASSERT(state); | |
| 1255 ++m_depth; | |
| 1256 return checkComposite(state) ? state : handleError(InputError, "Value be
ing cloned is either cyclic or too deeply nested.", state); | |
| 1257 } | |
| 1258 | |
| 1259 StateBase* pop(StateBase* state) | |
| 1260 { | |
| 1261 ASSERT(state); | |
| 1262 --m_depth; | |
| 1263 StateBase* next = state->nextState(); | |
| 1264 delete state; | |
| 1265 return next; | |
| 1266 } | |
| 1267 | |
| 1268 StateBase* handleError(Status errorStatus, const String& message, StateBase*
state) | |
| 1269 { | |
| 1270 ASSERT(errorStatus != Success); | |
| 1271 m_status = errorStatus; | |
| 1272 m_errorMessage = message; | |
| 1273 while (state) { | |
| 1274 StateBase* tmp = state->nextState(); | |
| 1275 delete state; | |
| 1276 state = tmp; | |
| 1277 } | |
| 1278 return new ErrorState; | |
| 1279 } | |
| 1280 | |
| 1281 bool checkComposite(StateBase* top) | |
| 1282 { | |
| 1283 ASSERT(top); | |
| 1284 if (m_depth > maxDepth) | |
| 1285 return false; | |
| 1286 if (!shouldCheckForCycles(m_depth)) | |
| 1287 return true; | |
| 1288 v8::Handle<v8::Value> composite = top->composite(); | |
| 1289 for (StateBase* state = top->nextState(); state; state = state->nextStat
e()) { | |
| 1290 if (state->composite() == composite) | |
| 1291 return false; | |
| 1292 } | |
| 1293 return true; | |
| 1294 } | |
| 1295 | |
| 1296 void writeString(v8::Handle<v8::Value> value) | |
| 1297 { | |
| 1298 v8::Handle<v8::String> string = value.As<v8::String>(); | |
| 1299 if (!string->Length() || string->IsOneByte()) | |
| 1300 m_writer.writeOneByteString(string); | |
| 1301 else | |
| 1302 m_writer.writeUCharString(string); | |
| 1303 } | |
| 1304 | |
| 1305 void writeStringObject(v8::Handle<v8::Value> value) | |
| 1306 { | |
| 1307 v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>()
; | |
| 1308 v8::String::Utf8Value stringValue(stringObject->ValueOf()); | |
| 1309 m_writer.writeStringObject(*stringValue, stringValue.length()); | |
| 1310 } | |
| 1311 | |
| 1312 void writeNumberObject(v8::Handle<v8::Value> value) | |
| 1313 { | |
| 1314 v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>()
; | |
| 1315 m_writer.writeNumberObject(numberObject->ValueOf()); | |
| 1316 } | |
| 1317 | |
| 1318 void writeBooleanObject(v8::Handle<v8::Value> value) | |
| 1319 { | |
| 1320 v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject
>(); | |
| 1321 m_writer.writeBooleanObject(booleanObject->ValueOf()); | |
| 1322 } | |
| 1323 | |
| 1324 StateBase* writeBlob(v8::Handle<v8::Value> value, StateBase* next) | |
| 1325 { | |
| 1326 Blob* blob = V8Blob::toImpl(value.As<v8::Object>()); | |
| 1327 if (!blob) | |
| 1328 return 0; | |
| 1329 if (blob->hasBeenClosed()) | |
| 1330 return handleError(DataCloneError, "A Blob object has been closed, a
nd could therefore not be cloned.", next); | |
| 1331 int blobIndex = -1; | |
| 1332 m_blobDataHandles.set(blob->uuid(), blob->blobDataHandle()); | |
| 1333 if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)
) | |
| 1334 m_writer.writeBlobIndex(blobIndex); | |
| 1335 else | |
| 1336 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); | |
| 1337 return 0; | |
| 1338 } | |
| 1339 | |
| 1340 StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next) | |
| 1341 { | |
| 1342 DOMFileSystem* fs = V8DOMFileSystem::toImpl(value.As<v8::Object>()); | |
| 1343 if (!fs) | |
| 1344 return 0; | |
| 1345 if (!fs->clonable()) | |
| 1346 return handleError(DataCloneError, "A FileSystem object could not be
cloned.", next); | |
| 1347 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string
()); | |
| 1348 return 0; | |
| 1349 } | |
| 1350 | |
| 1351 StateBase* writeFile(v8::Handle<v8::Value> value, StateBase* next) | |
| 1352 { | |
| 1353 File* file = V8File::toImpl(value.As<v8::Object>()); | |
| 1354 if (!file) | |
| 1355 return 0; | |
| 1356 if (file->hasBeenClosed()) | |
| 1357 return handleError(DataCloneError, "A File object has been closed, a
nd could therefore not be cloned.", next); | |
| 1358 int blobIndex = -1; | |
| 1359 m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); | |
| 1360 if (appendFileInfo(file, &blobIndex)) { | |
| 1361 ASSERT(blobIndex >= 0); | |
| 1362 m_writer.writeFileIndex(blobIndex); | |
| 1363 } else { | |
| 1364 m_writer.writeFile(*file); | |
| 1365 } | |
| 1366 return 0; | |
| 1367 } | |
| 1368 | |
| 1369 StateBase* writeFileList(v8::Handle<v8::Value> value, StateBase* next) | |
| 1370 { | |
| 1371 FileList* fileList = V8FileList::toImpl(value.As<v8::Object>()); | |
| 1372 if (!fileList) | |
| 1373 return 0; | |
| 1374 unsigned length = fileList->length(); | |
| 1375 Vector<int> blobIndices; | |
| 1376 for (unsigned i = 0; i < length; ++i) { | |
| 1377 int blobIndex = -1; | |
| 1378 const File* file = fileList->item(i); | |
| 1379 if (file->hasBeenClosed()) | |
| 1380 return handleError(DataCloneError, "A File object has been close
d, and could therefore not be cloned.", next); | |
| 1381 m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); | |
| 1382 if (appendFileInfo(file, &blobIndex)) { | |
| 1383 ASSERT(!i || blobIndex > 0); | |
| 1384 ASSERT(blobIndex >= 0); | |
| 1385 blobIndices.append(blobIndex); | |
| 1386 } | |
| 1387 } | |
| 1388 if (!blobIndices.isEmpty()) | |
| 1389 m_writer.writeFileListIndex(blobIndices); | |
| 1390 else | |
| 1391 m_writer.writeFileList(*fileList); | |
| 1392 return 0; | |
| 1393 } | |
| 1394 | |
| 1395 bool writeCryptoKey(v8::Handle<v8::Value> value) | |
| 1396 { | |
| 1397 CryptoKey* key = V8CryptoKey::toImpl(value.As<v8::Object>()); | |
| 1398 if (!key) | |
| 1399 return false; | |
| 1400 return m_writer.writeCryptoKey(key->key()); | |
| 1401 } | |
| 1402 | |
| 1403 void writeImageData(v8::Handle<v8::Value> value) | |
| 1404 { | |
| 1405 ImageData* imageData = V8ImageData::toImpl(value.As<v8::Object>()); | |
| 1406 if (!imageData) | |
| 1407 return; | |
| 1408 Uint8ClampedArray* pixelArray = imageData->data(); | |
| 1409 m_writer.writeImageData(imageData->width(), imageData->height(), pixelAr
ray->data(), pixelArray->length()); | |
| 1410 } | |
| 1411 | |
| 1412 void writeRegExp(v8::Handle<v8::Value> value) | |
| 1413 { | |
| 1414 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>(); | |
| 1415 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); | |
| 1416 } | |
| 1417 | |
| 1418 StateBase* writeAndGreyArrayBufferView(v8::Handle<v8::Object> object, StateB
ase* next) | |
| 1419 { | |
| 1420 ASSERT(!object.IsEmpty()); | |
| 1421 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); | |
| 1422 if (!arrayBufferView) | |
| 1423 return 0; | |
| 1424 if (!arrayBufferView->buffer()) | |
| 1425 return handleError(DataCloneError, "An ArrayBuffer could not be clon
ed.", next); | |
| 1426 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(),
m_scriptState->context()->Global(), isolate()); | |
| 1427 if (underlyingBuffer.IsEmpty()) | |
| 1428 return handleError(DataCloneError, "An ArrayBuffer could not be clon
ed.", next); | |
| 1429 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); | |
| 1430 if (stateOut) | |
| 1431 return stateOut; | |
| 1432 m_writer.writeArrayBufferView(*arrayBufferView->view()); | |
| 1433 // This should be safe: we serialize something that we know to be a wrap
per (see | |
| 1434 // the toV8 call above), so the call to doSerializeArrayBuffer should ne
ither | |
| 1435 // cause the system stack to overflow nor should it have potential to re
ach | |
| 1436 // this ArrayBufferView again. | |
| 1437 // | |
| 1438 // We do need to grey the underlying buffer before we grey its view, how
ever; | |
| 1439 // ArrayBuffers may be shared, so they need to be given reference IDs, a
nd an | |
| 1440 // ArrayBufferView cannot be constructed without a corresponding ArrayBu
ffer | |
| 1441 // (or without an additional tag that would allow us to do two-stage con
struction | |
| 1442 // like we do for Objects and Arrays). | |
| 1443 greyObject(object); | |
| 1444 return 0; | |
| 1445 } | |
| 1446 | |
| 1447 StateBase* writeArrayBuffer(v8::Handle<v8::Value> value, StateBase* next) | |
| 1448 { | |
| 1449 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>
()); | |
| 1450 if (!arrayBuffer) | |
| 1451 return 0; | |
| 1452 if (arrayBuffer->isNeutered()) | |
| 1453 return handleError(DataCloneError, "An ArrayBuffer is neutered and c
ould not be cloned.", next); | |
| 1454 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>())); | |
| 1455 m_writer.writeArrayBuffer(*arrayBuffer->buffer()); | |
| 1456 return 0; | |
| 1457 } | |
| 1458 | |
| 1459 StateBase* writeTransferredArrayBuffer(v8::Handle<v8::Value> value, uint32_t
index, StateBase* next) | |
| 1460 { | |
| 1461 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>
()); | |
| 1462 if (!arrayBuffer) | |
| 1463 return 0; | |
| 1464 if (arrayBuffer->isNeutered()) | |
| 1465 return handleError(DataCloneError, "An ArrayBuffer is neutered and c
ould not be cloned.", next); | |
| 1466 m_writer.writeTransferredArrayBuffer(index); | |
| 1467 return 0; | |
| 1468 } | |
| 1469 | |
| 1470 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount) | |
| 1471 { | |
| 1472 // Let K be the cost of serializing all property values that are there | |
| 1473 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32
_t key) | |
| 1474 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte f
or all properties that are not there) | |
| 1475 // so densely is better than sparsly whenever 6*propertyCount > length | |
| 1476 return 6 * propertyCount >= length; | |
| 1477 } | |
| 1478 | |
| 1479 StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next) | |
| 1480 { | |
| 1481 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames(); | |
| 1482 if (StateBase* newState = checkException(next)) | |
| 1483 return newState; | |
| 1484 uint32_t length = array->Length(); | |
| 1485 | |
| 1486 if (shouldSerializeDensely(length, propertyNames->Length())) { | |
| 1487 m_writer.writeGenerateFreshDenseArray(length); | |
| 1488 return push(new DenseArrayState(array, propertyNames, next, isolate(
))); | |
| 1489 } | |
| 1490 | |
| 1491 m_writer.writeGenerateFreshSparseArray(length); | |
| 1492 return push(new SparseArrayState(array, propertyNames, next, isolate()))
; | |
| 1493 } | |
| 1494 | |
| 1495 StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next) | |
| 1496 { | |
| 1497 m_writer.writeGenerateFreshObject(); | |
| 1498 // FIXME: check not a wrapper | |
| 1499 return push(new ObjectState(object, next)); | |
| 1500 } | |
| 1501 | |
| 1502 // Marks object as having been visited by the serializer and assigns it a un
ique object reference ID. | |
| 1503 // An object may only be greyed once. | |
| 1504 void greyObject(const v8::Handle<v8::Object>& object) | |
| 1505 { | |
| 1506 ASSERT(!m_objectPool.contains(object)); | |
| 1507 uint32_t objectReference = m_nextObjectReference++; | |
| 1508 m_objectPool.set(object, objectReference); | |
| 1509 } | |
| 1510 | |
| 1511 bool appendBlobInfo(const String& uuid, const String& type, unsigned long lo
ng size, int* index) | |
| 1512 { | |
| 1513 if (!m_blobInfo) | |
| 1514 return false; | |
| 1515 *index = m_blobInfo->size(); | |
| 1516 m_blobInfo->append(WebBlobInfo(uuid, type, size)); | |
| 1517 return true; | |
| 1518 } | |
| 1519 | |
| 1520 bool appendFileInfo(const File* file, int* index) | |
| 1521 { | |
| 1522 if (!m_blobInfo) | |
| 1523 return false; | |
| 1524 | |
| 1525 long long size = -1; | |
| 1526 double lastModified = invalidFileTime(); | |
| 1527 file->captureSnapshot(size, lastModified); | |
| 1528 *index = m_blobInfo->size(); | |
| 1529 m_blobInfo->append(WebBlobInfo(file->uuid(), file->path(), file->name(),
file->type(), lastModified, size)); | |
| 1530 return true; | |
| 1531 } | |
| 1532 | |
| 1533 RefPtr<ScriptState> m_scriptState; | |
| 1534 Writer& m_writer; | |
| 1535 v8::TryCatch& m_tryCatch; | |
| 1536 int m_depth; | |
| 1537 Status m_status; | |
| 1538 String m_errorMessage; | |
| 1539 typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; | |
| 1540 ObjectPool m_objectPool; | |
| 1541 ObjectPool m_transferredMessagePorts; | |
| 1542 ObjectPool m_transferredArrayBuffers; | |
| 1543 uint32_t m_nextObjectReference; | |
| 1544 WebBlobInfoArray* m_blobInfo; | |
| 1545 BlobDataHandleMap& m_blobDataHandles; | |
| 1546 }; | |
| 1547 | |
| 1548 // Returns true if the provided object is to be considered a 'host object', as u
sed in the | |
| 1549 // HTML5 structured clone algorithm. | |
| 1550 static bool isHostObject(v8::Handle<v8::Object> object) | |
| 1551 { | |
| 1552 // If the object has any internal fields, then we won't be able to serialize
or deserialize | |
| 1553 // them; conveniently, this is also a quick way to detect DOM wrapper object
s, because | |
| 1554 // the mechanism for these relies on data stored in these fields. We should | |
| 1555 // catch external array data as a special case. | |
| 1556 return object->InternalFieldCount() || object->HasIndexedPropertiesInExterna
lArrayData(); | |
| 1557 } | |
| 1558 | |
| 1559 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
eBase* next) | |
| 1560 { | |
| 1561 m_writer.writeReferenceCount(m_nextObjectReference); | |
| 1562 uint32_t objectReference; | |
| 1563 uint32_t arrayBufferIndex; | |
| 1564 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) | |
| 1565 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { | |
| 1566 // Note that IsObject() also detects wrappers (eg, it will catch the thi
ngs | |
| 1567 // that we grey and write below). | |
| 1568 ASSERT(!value->IsString()); | |
| 1569 m_writer.writeObjectReference(objectReference); | |
| 1570 } else if (value.IsEmpty()) { | |
| 1571 return handleError(InputError, "The empty property name cannot be cloned
.", next); | |
| 1572 } else if (value->IsUndefined()) { | |
| 1573 m_writer.writeUndefined(); | |
| 1574 } else if (value->IsNull()) { | |
| 1575 m_writer.writeNull(); | |
| 1576 } else if (value->IsTrue()) { | |
| 1577 m_writer.writeTrue(); | |
| 1578 } else if (value->IsFalse()) { | |
| 1579 m_writer.writeFalse(); | |
| 1580 } else if (value->IsInt32()) { | |
| 1581 m_writer.writeInt32(value->Int32Value()); | |
| 1582 } else if (value->IsUint32()) { | |
| 1583 m_writer.writeUint32(value->Uint32Value()); | |
| 1584 } else if (value->IsNumber()) { | |
| 1585 m_writer.writeNumber(value.As<v8::Number>()->Value()); | |
| 1586 } else if (V8ArrayBufferView::hasInstance(value, isolate())) { | |
| 1587 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); | |
| 1588 } else if (value->IsString()) { | |
| 1589 writeString(value); | |
| 1590 } else if (V8MessagePort::hasInstance(value, isolate())) { | |
| 1591 uint32_t messagePortIndex; | |
| 1592 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePor
tIndex)) { | |
| 1593 m_writer.writeTransferredMessagePort(messagePortIndex); | |
| 1594 } else { | |
| 1595 return handleError(DataCloneError, "A MessagePort could not be clone
d.", next); | |
| 1596 } | |
| 1597 } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArra
yBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) { | |
| 1598 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); | |
| 1599 } else { | |
| 1600 v8::Handle<v8::Object> jsObject = value.As<v8::Object>(); | |
| 1601 if (jsObject.IsEmpty()) | |
| 1602 return handleError(DataCloneError, "An object could not be cloned.",
next); | |
| 1603 greyObject(jsObject); | |
| 1604 if (value->IsDate()) { | |
| 1605 m_writer.writeDate(value->NumberValue()); | |
| 1606 } else if (value->IsStringObject()) { | |
| 1607 writeStringObject(value); | |
| 1608 } else if (value->IsNumberObject()) { | |
| 1609 writeNumberObject(value); | |
| 1610 } else if (value->IsBooleanObject()) { | |
| 1611 writeBooleanObject(value); | |
| 1612 } else if (value->IsArray()) { | |
| 1613 return startArrayState(value.As<v8::Array>(), next); | |
| 1614 } else if (V8File::hasInstance(value, isolate())) { | |
| 1615 return writeFile(value, next); | |
| 1616 } else if (V8Blob::hasInstance(value, isolate())) { | |
| 1617 return writeBlob(value, next); | |
| 1618 } else if (V8DOMFileSystem::hasInstance(value, isolate())) { | |
| 1619 return writeDOMFileSystem(value, next); | |
| 1620 } else if (V8FileList::hasInstance(value, isolate())) { | |
| 1621 return writeFileList(value, next); | |
| 1622 } else if (V8CryptoKey::hasInstance(value, isolate())) { | |
| 1623 if (!writeCryptoKey(value)) | |
| 1624 return handleError(DataCloneError, "Couldn't serialize key data"
, next); | |
| 1625 } else if (V8ImageData::hasInstance(value, isolate())) { | |
| 1626 writeImageData(value); | |
| 1627 } else if (value->IsRegExp()) { | |
| 1628 writeRegExp(value); | |
| 1629 } else if (V8ArrayBuffer::hasInstance(value, isolate())) { | |
| 1630 return writeArrayBuffer(value, next); | |
| 1631 } else if (value->IsObject()) { | |
| 1632 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNat
iveError()) | |
| 1633 return handleError(DataCloneError, "An object could not be clone
d.", next); | |
| 1634 return startObjectState(jsObject, next); | |
| 1635 } else { | |
| 1636 return handleError(DataCloneError, "A value could not be cloned.", n
ext); | |
| 1637 } | |
| 1638 } | |
| 1639 return 0; | |
| 1640 } | |
| 1641 | |
| 1642 // Interface used by Reader to create objects of composite types. | |
| 1643 class CompositeCreator { | |
| 1644 STACK_ALLOCATED(); | |
| 1645 public: | |
| 1646 virtual ~CompositeCreator() { } | |
| 1647 | |
| 1648 virtual bool consumeTopOfStack(v8::Handle<v8::Value>*) = 0; | |
| 1649 virtual uint32_t objectReferenceCount() = 0; | |
| 1650 virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0; | |
| 1651 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<
v8::Value>*) = 0; | |
| 1652 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Val
ue>*) = 0; | |
| 1653 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Val
ue>*) = 0; | |
| 1654 virtual bool newSparseArray(uint32_t length) = 0; | |
| 1655 virtual bool newDenseArray(uint32_t length) = 0; | |
| 1656 virtual bool newObject() = 0; | |
| 1657 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*)
= 0; | |
| 1658 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8
::Handle<v8::Value>*) = 0; | |
| 1659 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8:
:Handle<v8::Value>*) = 0; | |
| 1660 }; | |
| 1661 | |
| 1662 // Reader is responsible for deserializing primitive types and | |
| 1663 // restoring information about saved objects of composite types. | |
| 1664 class Reader { | |
| 1665 public: | |
| 1666 Reader(const uint8_t* buffer, int length, const WebBlobInfoArray* blobInfo,
BlobDataHandleMap& blobDataHandles, ScriptState* scriptState) | |
| 1667 : m_scriptState(scriptState) | |
| 1668 , m_buffer(buffer) | |
| 1669 , m_length(length) | |
| 1670 , m_position(0) | |
| 1671 , m_version(0) | |
| 1672 , m_blobInfo(blobInfo) | |
| 1673 , m_blobDataHandles(blobDataHandles) | |
| 1674 { | |
| 1675 ASSERT(!(reinterpret_cast<size_t>(buffer) & 1)); | |
| 1676 ASSERT(length >= 0); | |
| 1677 } | |
| 1678 | |
| 1679 bool isEof() const { return m_position >= m_length; } | |
| 1680 | |
| 1681 ScriptState* scriptState() const { return m_scriptState.get(); } | |
| 1682 | |
| 1683 private: | |
| 1684 v8::Isolate* isolate() const { return m_scriptState->isolate(); } | |
| 1685 | |
| 1686 public: | |
| 1687 bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator) | |
| 1688 { | |
| 1689 SerializationTag tag; | |
| 1690 if (!readTag(&tag)) | |
| 1691 return false; | |
| 1692 switch (tag) { | |
| 1693 case ReferenceCountTag: { | |
| 1694 if (!m_version) | |
| 1695 return false; | |
| 1696 uint32_t referenceTableSize; | |
| 1697 if (!doReadUint32(&referenceTableSize)) | |
| 1698 return false; | |
| 1699 // If this test fails, then the serializer and deserializer disagree
about the assignment | |
| 1700 // of object reference IDs. On the deserialization side, this means
there are too many or too few | |
| 1701 // calls to pushObjectReference. | |
| 1702 if (referenceTableSize != creator.objectReferenceCount()) | |
| 1703 return false; | |
| 1704 return true; | |
| 1705 } | |
| 1706 case InvalidTag: | |
| 1707 return false; | |
| 1708 case PaddingTag: | |
| 1709 return true; | |
| 1710 case UndefinedTag: | |
| 1711 *value = v8::Undefined(isolate()); | |
| 1712 break; | |
| 1713 case NullTag: | |
| 1714 *value = v8::Null(isolate()); | |
| 1715 break; | |
| 1716 case TrueTag: | |
| 1717 *value = v8Boolean(true, isolate()); | |
| 1718 break; | |
| 1719 case FalseTag: | |
| 1720 *value = v8Boolean(false, isolate()); | |
| 1721 break; | |
| 1722 case TrueObjectTag: | |
| 1723 *value = v8::BooleanObject::New(true); | |
| 1724 creator.pushObjectReference(*value); | |
| 1725 break; | |
| 1726 case FalseObjectTag: | |
| 1727 *value = v8::BooleanObject::New(false); | |
| 1728 creator.pushObjectReference(*value); | |
| 1729 break; | |
| 1730 case StringTag: | |
| 1731 if (!readString(value)) | |
| 1732 return false; | |
| 1733 break; | |
| 1734 case StringUCharTag: | |
| 1735 if (!readUCharString(value)) | |
| 1736 return false; | |
| 1737 break; | |
| 1738 case StringObjectTag: | |
| 1739 if (!readStringObject(value)) | |
| 1740 return false; | |
| 1741 creator.pushObjectReference(*value); | |
| 1742 break; | |
| 1743 case Int32Tag: | |
| 1744 if (!readInt32(value)) | |
| 1745 return false; | |
| 1746 break; | |
| 1747 case Uint32Tag: | |
| 1748 if (!readUint32(value)) | |
| 1749 return false; | |
| 1750 break; | |
| 1751 case DateTag: | |
| 1752 if (!readDate(value)) | |
| 1753 return false; | |
| 1754 creator.pushObjectReference(*value); | |
| 1755 break; | |
| 1756 case NumberTag: | |
| 1757 if (!readNumber(value)) | |
| 1758 return false; | |
| 1759 break; | |
| 1760 case NumberObjectTag: | |
| 1761 if (!readNumberObject(value)) | |
| 1762 return false; | |
| 1763 creator.pushObjectReference(*value); | |
| 1764 break; | |
| 1765 case BlobTag: | |
| 1766 case BlobIndexTag: | |
| 1767 if (!readBlob(value, tag == BlobIndexTag)) | |
| 1768 return false; | |
| 1769 creator.pushObjectReference(*value); | |
| 1770 break; | |
| 1771 case FileTag: | |
| 1772 case FileIndexTag: | |
| 1773 if (!readFile(value, tag == FileIndexTag)) | |
| 1774 return false; | |
| 1775 creator.pushObjectReference(*value); | |
| 1776 break; | |
| 1777 case DOMFileSystemTag: | |
| 1778 if (!readDOMFileSystem(value)) | |
| 1779 return false; | |
| 1780 creator.pushObjectReference(*value); | |
| 1781 break; | |
| 1782 case FileListTag: | |
| 1783 case FileListIndexTag: | |
| 1784 if (!readFileList(value, tag == FileListIndexTag)) | |
| 1785 return false; | |
| 1786 creator.pushObjectReference(*value); | |
| 1787 break; | |
| 1788 case CryptoKeyTag: | |
| 1789 if (!readCryptoKey(value)) | |
| 1790 return false; | |
| 1791 creator.pushObjectReference(*value); | |
| 1792 break; | |
| 1793 case ImageDataTag: | |
| 1794 if (!readImageData(value)) | |
| 1795 return false; | |
| 1796 creator.pushObjectReference(*value); | |
| 1797 break; | |
| 1798 | |
| 1799 case RegExpTag: | |
| 1800 if (!readRegExp(value)) | |
| 1801 return false; | |
| 1802 creator.pushObjectReference(*value); | |
| 1803 break; | |
| 1804 case ObjectTag: { | |
| 1805 uint32_t numProperties; | |
| 1806 if (!doReadUint32(&numProperties)) | |
| 1807 return false; | |
| 1808 if (!creator.completeObject(numProperties, value)) | |
| 1809 return false; | |
| 1810 break; | |
| 1811 } | |
| 1812 case SparseArrayTag: { | |
| 1813 uint32_t numProperties; | |
| 1814 uint32_t length; | |
| 1815 if (!doReadUint32(&numProperties)) | |
| 1816 return false; | |
| 1817 if (!doReadUint32(&length)) | |
| 1818 return false; | |
| 1819 if (!creator.completeSparseArray(numProperties, length, value)) | |
| 1820 return false; | |
| 1821 break; | |
| 1822 } | |
| 1823 case DenseArrayTag: { | |
| 1824 uint32_t numProperties; | |
| 1825 uint32_t length; | |
| 1826 if (!doReadUint32(&numProperties)) | |
| 1827 return false; | |
| 1828 if (!doReadUint32(&length)) | |
| 1829 return false; | |
| 1830 if (!creator.completeDenseArray(numProperties, length, value)) | |
| 1831 return false; | |
| 1832 break; | |
| 1833 } | |
| 1834 case ArrayBufferViewTag: { | |
| 1835 if (!m_version) | |
| 1836 return false; | |
| 1837 if (!readArrayBufferView(value, creator)) | |
| 1838 return false; | |
| 1839 creator.pushObjectReference(*value); | |
| 1840 break; | |
| 1841 } | |
| 1842 case ArrayBufferTag: { | |
| 1843 if (!m_version) | |
| 1844 return false; | |
| 1845 if (!readArrayBuffer(value)) | |
| 1846 return false; | |
| 1847 creator.pushObjectReference(*value); | |
| 1848 break; | |
| 1849 } | |
| 1850 case GenerateFreshObjectTag: { | |
| 1851 if (!m_version) | |
| 1852 return false; | |
| 1853 if (!creator.newObject()) | |
| 1854 return false; | |
| 1855 return true; | |
| 1856 } | |
| 1857 case GenerateFreshSparseArrayTag: { | |
| 1858 if (!m_version) | |
| 1859 return false; | |
| 1860 uint32_t length; | |
| 1861 if (!doReadUint32(&length)) | |
| 1862 return false; | |
| 1863 if (!creator.newSparseArray(length)) | |
| 1864 return false; | |
| 1865 return true; | |
| 1866 } | |
| 1867 case GenerateFreshDenseArrayTag: { | |
| 1868 if (!m_version) | |
| 1869 return false; | |
| 1870 uint32_t length; | |
| 1871 if (!doReadUint32(&length)) | |
| 1872 return false; | |
| 1873 if (!creator.newDenseArray(length)) | |
| 1874 return false; | |
| 1875 return true; | |
| 1876 } | |
| 1877 case MessagePortTag: { | |
| 1878 if (!m_version) | |
| 1879 return false; | |
| 1880 uint32_t index; | |
| 1881 if (!doReadUint32(&index)) | |
| 1882 return false; | |
| 1883 if (!creator.tryGetTransferredMessagePort(index, value)) | |
| 1884 return false; | |
| 1885 break; | |
| 1886 } | |
| 1887 case ArrayBufferTransferTag: { | |
| 1888 if (!m_version) | |
| 1889 return false; | |
| 1890 uint32_t index; | |
| 1891 if (!doReadUint32(&index)) | |
| 1892 return false; | |
| 1893 if (!creator.tryGetTransferredArrayBuffer(index, value)) | |
| 1894 return false; | |
| 1895 break; | |
| 1896 } | |
| 1897 case ObjectReferenceTag: { | |
| 1898 if (!m_version) | |
| 1899 return false; | |
| 1900 uint32_t reference; | |
| 1901 if (!doReadUint32(&reference)) | |
| 1902 return false; | |
| 1903 if (!creator.tryGetObjectFromObjectReference(reference, value)) | |
| 1904 return false; | |
| 1905 break; | |
| 1906 } | |
| 1907 default: | |
| 1908 return false; | |
| 1909 } | |
| 1910 return !value->IsEmpty(); | |
| 1911 } | |
| 1912 | |
| 1913 bool readVersion(uint32_t& version) | |
| 1914 { | |
| 1915 SerializationTag tag; | |
| 1916 if (!readTag(&tag)) { | |
| 1917 // This is a nullary buffer. We're still version 0. | |
| 1918 version = 0; | |
| 1919 return true; | |
| 1920 } | |
| 1921 if (tag != VersionTag) { | |
| 1922 // Versions of the format past 0 start with the version tag. | |
| 1923 version = 0; | |
| 1924 // Put back the tag. | |
| 1925 undoReadTag(); | |
| 1926 return true; | |
| 1927 } | |
| 1928 // Version-bearing messages are obligated to finish the version tag. | |
| 1929 return doReadUint32(&version); | |
| 1930 } | |
| 1931 | |
| 1932 void setVersion(uint32_t version) | |
| 1933 { | |
| 1934 m_version = version; | |
| 1935 } | |
| 1936 | |
| 1937 private: | |
| 1938 bool readTag(SerializationTag* tag) | |
| 1939 { | |
| 1940 if (m_position >= m_length) | |
| 1941 return false; | |
| 1942 *tag = static_cast<SerializationTag>(m_buffer[m_position++]); | |
| 1943 return true; | |
| 1944 } | |
| 1945 | |
| 1946 void undoReadTag() | |
| 1947 { | |
| 1948 if (m_position > 0) | |
| 1949 --m_position; | |
| 1950 } | |
| 1951 | |
| 1952 bool readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag) | |
| 1953 { | |
| 1954 if (m_position >= m_length) | |
| 1955 return false; | |
| 1956 *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]); | |
| 1957 return true; | |
| 1958 } | |
| 1959 | |
| 1960 bool readString(v8::Handle<v8::Value>* value) | |
| 1961 { | |
| 1962 uint32_t length; | |
| 1963 if (!doReadUint32(&length)) | |
| 1964 return false; | |
| 1965 if (m_position + length > m_length) | |
| 1966 return false; | |
| 1967 *value = v8::String::NewFromUtf8(isolate(), reinterpret_cast<const char*
>(m_buffer + m_position), v8::String::kNormalString, length); | |
| 1968 m_position += length; | |
| 1969 return true; | |
| 1970 } | |
| 1971 | |
| 1972 bool readUCharString(v8::Handle<v8::Value>* value) | |
| 1973 { | |
| 1974 uint32_t length; | |
| 1975 if (!doReadUint32(&length) || (length & 1)) | |
| 1976 return false; | |
| 1977 if (m_position + length > m_length) | |
| 1978 return false; | |
| 1979 ASSERT(!(m_position & 1)); | |
| 1980 *value = v8::String::NewFromTwoByte(isolate(), reinterpret_cast<const ui
nt16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UCha
r)); | |
| 1981 m_position += length; | |
| 1982 return true; | |
| 1983 } | |
| 1984 | |
| 1985 bool readStringObject(v8::Handle<v8::Value>* value) | |
| 1986 { | |
| 1987 v8::Handle<v8::Value> stringValue; | |
| 1988 if (!readString(&stringValue) || !stringValue->IsString()) | |
| 1989 return false; | |
| 1990 *value = v8::StringObject::New(stringValue.As<v8::String>()); | |
| 1991 return true; | |
| 1992 } | |
| 1993 | |
| 1994 bool readWebCoreString(String* string) | |
| 1995 { | |
| 1996 uint32_t length; | |
| 1997 if (!doReadUint32(&length)) | |
| 1998 return false; | |
| 1999 if (m_position + length > m_length) | |
| 2000 return false; | |
| 2001 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_po
sition), length); | |
| 2002 m_position += length; | |
| 2003 return true; | |
| 2004 } | |
| 2005 | |
| 2006 bool readInt32(v8::Handle<v8::Value>* value) | |
| 2007 { | |
| 2008 uint32_t rawValue; | |
| 2009 if (!doReadUint32(&rawValue)) | |
| 2010 return false; | |
| 2011 *value = v8::Integer::New(isolate(), static_cast<int32_t>(ZigZag::decode
(rawValue))); | |
| 2012 return true; | |
| 2013 } | |
| 2014 | |
| 2015 bool readUint32(v8::Handle<v8::Value>* value) | |
| 2016 { | |
| 2017 uint32_t rawValue; | |
| 2018 if (!doReadUint32(&rawValue)) | |
| 2019 return false; | |
| 2020 *value = v8::Integer::NewFromUnsigned(isolate(), rawValue); | |
| 2021 return true; | |
| 2022 } | |
| 2023 | |
| 2024 bool readDate(v8::Handle<v8::Value>* value) | |
| 2025 { | |
| 2026 double numberValue; | |
| 2027 if (!doReadNumber(&numberValue)) | |
| 2028 return false; | |
| 2029 *value = v8DateOrNaN(numberValue, isolate()); | |
| 2030 return true; | |
| 2031 } | |
| 2032 | |
| 2033 bool readNumber(v8::Handle<v8::Value>* value) | |
| 2034 { | |
| 2035 double number; | |
| 2036 if (!doReadNumber(&number)) | |
| 2037 return false; | |
| 2038 *value = v8::Number::New(isolate(), number); | |
| 2039 return true; | |
| 2040 } | |
| 2041 | |
| 2042 bool readNumberObject(v8::Handle<v8::Value>* value) | |
| 2043 { | |
| 2044 double number; | |
| 2045 if (!doReadNumber(&number)) | |
| 2046 return false; | |
| 2047 *value = v8::NumberObject::New(isolate(), number); | |
| 2048 return true; | |
| 2049 } | |
| 2050 | |
| 2051 bool readImageData(v8::Handle<v8::Value>* value) | |
| 2052 { | |
| 2053 uint32_t width; | |
| 2054 uint32_t height; | |
| 2055 uint32_t pixelDataLength; | |
| 2056 if (!doReadUint32(&width)) | |
| 2057 return false; | |
| 2058 if (!doReadUint32(&height)) | |
| 2059 return false; | |
| 2060 if (!doReadUint32(&pixelDataLength)) | |
| 2061 return false; | |
| 2062 if (m_position + pixelDataLength > m_length) | |
| 2063 return false; | |
| 2064 RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(IntSize(widt
h, height)); | |
| 2065 Uint8ClampedArray* pixelArray = imageData->data(); | |
| 2066 ASSERT(pixelArray); | |
| 2067 ASSERT(pixelArray->length() >= pixelDataLength); | |
| 2068 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); | |
| 2069 m_position += pixelDataLength; | |
| 2070 *value = toV8(imageData.release(), m_scriptState->context()->Global(), i
solate()); | |
| 2071 return true; | |
| 2072 } | |
| 2073 | |
| 2074 PassRefPtr<ArrayBuffer> doReadArrayBuffer() | |
| 2075 { | |
| 2076 uint32_t byteLength; | |
| 2077 if (!doReadUint32(&byteLength)) | |
| 2078 return nullptr; | |
| 2079 if (m_position + byteLength > m_length) | |
| 2080 return nullptr; | |
| 2081 const void* bufferStart = m_buffer + m_position; | |
| 2082 m_position += byteLength; | |
| 2083 return ArrayBuffer::create(bufferStart, byteLength); | |
| 2084 } | |
| 2085 | |
| 2086 bool readArrayBuffer(v8::Handle<v8::Value>* value) | |
| 2087 { | |
| 2088 RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer(); | |
| 2089 if (!arrayBuffer) | |
| 2090 return false; | |
| 2091 *value = toV8(DOMArrayBuffer::create(arrayBuffer.release()), m_scriptSta
te->context()->Global(), isolate()); | |
| 2092 return true; | |
| 2093 } | |
| 2094 | |
| 2095 bool readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator& cre
ator) | |
| 2096 { | |
| 2097 ArrayBufferViewSubTag subTag; | |
| 2098 uint32_t byteOffset; | |
| 2099 uint32_t byteLength; | |
| 2100 RefPtr<DOMArrayBuffer> arrayBuffer; | |
| 2101 v8::Handle<v8::Value> arrayBufferV8Value; | |
| 2102 if (!readArrayBufferViewSubTag(&subTag)) | |
| 2103 return false; | |
| 2104 if (!doReadUint32(&byteOffset)) | |
| 2105 return false; | |
| 2106 if (!doReadUint32(&byteLength)) | |
| 2107 return false; | |
| 2108 if (!creator.consumeTopOfStack(&arrayBufferV8Value)) | |
| 2109 return false; | |
| 2110 if (arrayBufferV8Value.IsEmpty()) | |
| 2111 return false; | |
| 2112 arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>())
; | |
| 2113 if (!arrayBuffer) | |
| 2114 return false; | |
| 2115 | |
| 2116 v8::Handle<v8::Object> creationContext = m_scriptState->context()->Globa
l(); | |
| 2117 switch (subTag) { | |
| 2118 case ByteArrayTag: | |
| 2119 *value = toV8(DOMInt8Array::create(arrayBuffer.release(), byteOffset
, byteLength), creationContext, isolate()); | |
| 2120 break; | |
| 2121 case UnsignedByteArrayTag: | |
| 2122 *value = toV8(DOMUint8Array::create(arrayBuffer.release(), byteOffse
t, byteLength), creationContext, isolate()); | |
| 2123 break; | |
| 2124 case UnsignedByteClampedArrayTag: | |
| 2125 *value = toV8(DOMUint8ClampedArray::create(arrayBuffer.release(), by
teOffset, byteLength), creationContext, isolate()); | |
| 2126 break; | |
| 2127 case ShortArrayTag: { | |
| 2128 uint32_t shortLength = byteLength / sizeof(int16_t); | |
| 2129 if (shortLength * sizeof(int16_t) != byteLength) | |
| 2130 return false; | |
| 2131 *value = toV8(DOMInt16Array::create(arrayBuffer.release(), byteOffse
t, shortLength), creationContext, isolate()); | |
| 2132 break; | |
| 2133 } | |
| 2134 case UnsignedShortArrayTag: { | |
| 2135 uint32_t shortLength = byteLength / sizeof(uint16_t); | |
| 2136 if (shortLength * sizeof(uint16_t) != byteLength) | |
| 2137 return false; | |
| 2138 *value = toV8(DOMUint16Array::create(arrayBuffer.release(), byteOffs
et, shortLength), creationContext, isolate()); | |
| 2139 break; | |
| 2140 } | |
| 2141 case IntArrayTag: { | |
| 2142 uint32_t intLength = byteLength / sizeof(int32_t); | |
| 2143 if (intLength * sizeof(int32_t) != byteLength) | |
| 2144 return false; | |
| 2145 *value = toV8(DOMInt32Array::create(arrayBuffer.release(), byteOffse
t, intLength), creationContext, isolate()); | |
| 2146 break; | |
| 2147 } | |
| 2148 case UnsignedIntArrayTag: { | |
| 2149 uint32_t intLength = byteLength / sizeof(uint32_t); | |
| 2150 if (intLength * sizeof(uint32_t) != byteLength) | |
| 2151 return false; | |
| 2152 *value = toV8(DOMUint32Array::create(arrayBuffer.release(), byteOffs
et, intLength), creationContext, isolate()); | |
| 2153 break; | |
| 2154 } | |
| 2155 case FloatArrayTag: { | |
| 2156 uint32_t floatLength = byteLength / sizeof(float); | |
| 2157 if (floatLength * sizeof(float) != byteLength) | |
| 2158 return false; | |
| 2159 *value = toV8(DOMFloat32Array::create(arrayBuffer.release(), byteOff
set, floatLength), creationContext, isolate()); | |
| 2160 break; | |
| 2161 } | |
| 2162 case DoubleArrayTag: { | |
| 2163 uint32_t floatLength = byteLength / sizeof(double); | |
| 2164 if (floatLength * sizeof(double) != byteLength) | |
| 2165 return false; | |
| 2166 *value = toV8(DOMFloat64Array::create(arrayBuffer.release(), byteOff
set, floatLength), creationContext, isolate()); | |
| 2167 break; | |
| 2168 } | |
| 2169 case DataViewTag: | |
| 2170 *value = toV8(DOMDataView::create(arrayBuffer.release(), byteOffset,
byteLength), creationContext, isolate()); | |
| 2171 break; | |
| 2172 default: | |
| 2173 return false; | |
| 2174 } | |
| 2175 // The various *Array::create() methods will return null if the range th
e view expects is | |
| 2176 // mismatched with the range the buffer can provide or if the byte offse
t is not aligned | |
| 2177 // to the size of the element type. | |
| 2178 return !value->IsEmpty(); | |
| 2179 } | |
| 2180 | |
| 2181 bool readRegExp(v8::Handle<v8::Value>* value) | |
| 2182 { | |
| 2183 v8::Handle<v8::Value> pattern; | |
| 2184 if (!readString(&pattern)) | |
| 2185 return false; | |
| 2186 uint32_t flags; | |
| 2187 if (!doReadUint32(&flags)) | |
| 2188 return false; | |
| 2189 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegEx
p::Flags>(flags)); | |
| 2190 return true; | |
| 2191 } | |
| 2192 | |
| 2193 bool readBlob(v8::Handle<v8::Value>* value, bool isIndexed) | |
| 2194 { | |
| 2195 if (m_version < 3) | |
| 2196 return false; | |
| 2197 Blob* blob = nullptr; | |
| 2198 if (isIndexed) { | |
| 2199 if (m_version < 6) | |
| 2200 return false; | |
| 2201 ASSERT(m_blobInfo); | |
| 2202 uint32_t index; | |
| 2203 if (!doReadUint32(&index) || index >= m_blobInfo->size()) | |
| 2204 return false; | |
| 2205 const WebBlobInfo& info = (*m_blobInfo)[index]; | |
| 2206 blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type
(), info.size())); | |
| 2207 } else { | |
| 2208 ASSERT(!m_blobInfo); | |
| 2209 String uuid; | |
| 2210 String type; | |
| 2211 uint64_t size; | |
| 2212 ASSERT(!m_blobInfo); | |
| 2213 if (!readWebCoreString(&uuid)) | |
| 2214 return false; | |
| 2215 if (!readWebCoreString(&type)) | |
| 2216 return false; | |
| 2217 if (!doReadUint64(&size)) | |
| 2218 return false; | |
| 2219 blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); | |
| 2220 } | |
| 2221 *value = toV8(blob, m_scriptState->context()->Global(), isolate()); | |
| 2222 return true; | |
| 2223 } | |
| 2224 | |
| 2225 bool readDOMFileSystem(v8::Handle<v8::Value>* value) | |
| 2226 { | |
| 2227 uint32_t type; | |
| 2228 String name; | |
| 2229 String url; | |
| 2230 if (!doReadUint32(&type)) | |
| 2231 return false; | |
| 2232 if (!readWebCoreString(&name)) | |
| 2233 return false; | |
| 2234 if (!readWebCoreString(&url)) | |
| 2235 return false; | |
| 2236 DOMFileSystem* fs = DOMFileSystem::create(m_scriptState->executionContex
t(), name, static_cast<FileSystemType>(type), KURL(ParsedURLString, url)); | |
| 2237 *value = toV8(fs, m_scriptState->context()->Global(), isolate()); | |
| 2238 return true; | |
| 2239 } | |
| 2240 | |
| 2241 bool readFile(v8::Handle<v8::Value>* value, bool isIndexed) | |
| 2242 { | |
| 2243 File* file = nullptr; | |
| 2244 if (isIndexed) { | |
| 2245 if (m_version < 6) | |
| 2246 return false; | |
| 2247 file = readFileIndexHelper(); | |
| 2248 } else { | |
| 2249 file = readFileHelper(); | |
| 2250 } | |
| 2251 if (!file) | |
| 2252 return false; | |
| 2253 *value = toV8(file, m_scriptState->context()->Global(), isolate()); | |
| 2254 return true; | |
| 2255 } | |
| 2256 | |
| 2257 bool readFileList(v8::Handle<v8::Value>* value, bool isIndexed) | |
| 2258 { | |
| 2259 if (m_version < 3) | |
| 2260 return false; | |
| 2261 uint32_t length; | |
| 2262 if (!doReadUint32(&length)) | |
| 2263 return false; | |
| 2264 FileList* fileList = FileList::create(); | |
| 2265 for (unsigned i = 0; i < length; ++i) { | |
| 2266 File* file = nullptr; | |
| 2267 if (isIndexed) { | |
| 2268 if (m_version < 6) | |
| 2269 return false; | |
| 2270 file = readFileIndexHelper(); | |
| 2271 } else { | |
| 2272 file = readFileHelper(); | |
| 2273 } | |
| 2274 if (!file) | |
| 2275 return false; | |
| 2276 fileList->append(file); | |
| 2277 } | |
| 2278 *value = toV8(fileList, m_scriptState->context()->Global(), isolate()); | |
| 2279 return true; | |
| 2280 } | |
| 2281 | |
| 2282 bool readCryptoKey(v8::Handle<v8::Value>* value) | |
| 2283 { | |
| 2284 uint32_t rawKeyType; | |
| 2285 if (!doReadUint32(&rawKeyType)) | |
| 2286 return false; | |
| 2287 | |
| 2288 WebCryptoKeyAlgorithm algorithm; | |
| 2289 WebCryptoKeyType type = WebCryptoKeyTypeSecret; | |
| 2290 | |
| 2291 switch (static_cast<CryptoKeySubTag>(rawKeyType)) { | |
| 2292 case AesKeyTag: | |
| 2293 if (!doReadAesKey(algorithm, type)) | |
| 2294 return false; | |
| 2295 break; | |
| 2296 case HmacKeyTag: | |
| 2297 if (!doReadHmacKey(algorithm, type)) | |
| 2298 return false; | |
| 2299 break; | |
| 2300 case RsaHashedKeyTag: | |
| 2301 if (!doReadRsaHashedKey(algorithm, type)) | |
| 2302 return false; | |
| 2303 break; | |
| 2304 case EcKeyTag: | |
| 2305 if (!doReadEcKey(algorithm, type)) | |
| 2306 return false; | |
| 2307 break; | |
| 2308 default: | |
| 2309 return false; | |
| 2310 } | |
| 2311 | |
| 2312 WebCryptoKeyUsageMask usages; | |
| 2313 bool extractable; | |
| 2314 if (!doReadKeyUsages(usages, extractable)) | |
| 2315 return false; | |
| 2316 | |
| 2317 uint32_t keyDataLength; | |
| 2318 if (!doReadUint32(&keyDataLength)) | |
| 2319 return false; | |
| 2320 | |
| 2321 if (m_position + keyDataLength > m_length) | |
| 2322 return false; | |
| 2323 | |
| 2324 const uint8_t* keyData = m_buffer + m_position; | |
| 2325 m_position += keyDataLength; | |
| 2326 | |
| 2327 WebCryptoKey key = WebCryptoKey::createNull(); | |
| 2328 if (!Platform::current()->crypto()->deserializeKeyForClone( | |
| 2329 algorithm, type, extractable, usages, keyData, keyDataLength, key))
{ | |
| 2330 return false; | |
| 2331 } | |
| 2332 | |
| 2333 *value = toV8(CryptoKey::create(key), m_scriptState->context()->Global()
, isolate()); | |
| 2334 return true; | |
| 2335 } | |
| 2336 | |
| 2337 File* readFileHelper() | |
| 2338 { | |
| 2339 if (m_version < 3) | |
| 2340 return nullptr; | |
| 2341 ASSERT(!m_blobInfo); | |
| 2342 String path; | |
| 2343 String name; | |
| 2344 String relativePath; | |
| 2345 String uuid; | |
| 2346 String type; | |
| 2347 uint32_t hasSnapshot = 0; | |
| 2348 uint64_t size = 0; | |
| 2349 double lastModified = 0; | |
| 2350 if (!readWebCoreString(&path)) | |
| 2351 return nullptr; | |
| 2352 if (m_version >= 4 && !readWebCoreString(&name)) | |
| 2353 return nullptr; | |
| 2354 if (m_version >= 4 && !readWebCoreString(&relativePath)) | |
| 2355 return nullptr; | |
| 2356 if (!readWebCoreString(&uuid)) | |
| 2357 return nullptr; | |
| 2358 if (!readWebCoreString(&type)) | |
| 2359 return nullptr; | |
| 2360 if (m_version >= 4 && !doReadUint32(&hasSnapshot)) | |
| 2361 return nullptr; | |
| 2362 if (hasSnapshot) { | |
| 2363 if (!doReadUint64(&size)) | |
| 2364 return nullptr; | |
| 2365 if (!doReadNumber(&lastModified)) | |
| 2366 return nullptr; | |
| 2367 } | |
| 2368 uint32_t isUserVisible = 1; | |
| 2369 if (m_version >= 7 && !doReadUint32(&isUserVisible)) | |
| 2370 return nullptr; | |
| 2371 const File::UserVisibility userVisibility = (isUserVisible > 0) ? File::
IsUserVisible : File::IsNotUserVisible; | |
| 2372 return File::createFromSerialization(path, name, relativePath, userVisib
ility, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type
)); | |
| 2373 } | |
| 2374 | |
| 2375 File* readFileIndexHelper() | |
| 2376 { | |
| 2377 if (m_version < 3) | |
| 2378 return nullptr; | |
| 2379 ASSERT(m_blobInfo); | |
| 2380 uint32_t index; | |
| 2381 if (!doReadUint32(&index) || index >= m_blobInfo->size()) | |
| 2382 return nullptr; | |
| 2383 const WebBlobInfo& info = (*m_blobInfo)[index]; | |
| 2384 return File::createFromIndexedSerialization(info.filePath(), info.fileNa
me(), info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), i
nfo.type(), info.size())); | |
| 2385 } | |
| 2386 | |
| 2387 template<class T> | |
| 2388 bool doReadUintHelper(T* value) | |
| 2389 { | |
| 2390 *value = 0; | |
| 2391 uint8_t currentByte; | |
| 2392 int shift = 0; | |
| 2393 do { | |
| 2394 if (m_position >= m_length) | |
| 2395 return false; | |
| 2396 currentByte = m_buffer[m_position++]; | |
| 2397 *value |= ((currentByte & varIntMask) << shift); | |
| 2398 shift += varIntShift; | |
| 2399 } while (currentByte & (1 << varIntShift)); | |
| 2400 return true; | |
| 2401 } | |
| 2402 | |
| 2403 bool doReadUint32(uint32_t* value) | |
| 2404 { | |
| 2405 return doReadUintHelper(value); | |
| 2406 } | |
| 2407 | |
| 2408 bool doReadUint64(uint64_t* value) | |
| 2409 { | |
| 2410 return doReadUintHelper(value); | |
| 2411 } | |
| 2412 | |
| 2413 bool doReadNumber(double* number) | |
| 2414 { | |
| 2415 if (m_position + sizeof(double) > m_length) | |
| 2416 return false; | |
| 2417 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number); | |
| 2418 for (unsigned i = 0; i < sizeof(double); ++i) | |
| 2419 numberAsByteArray[i] = m_buffer[m_position++]; | |
| 2420 return true; | |
| 2421 } | |
| 2422 | |
| 2423 PassRefPtr<BlobDataHandle> getOrCreateBlobDataHandle(const String& uuid, con
st String& type, long long size = -1) | |
| 2424 { | |
| 2425 // The containing ssv may have a BDH for this uuid if this ssv is just b
eing | |
| 2426 // passed from main to worker thread (for example). We use those values
when creating | |
| 2427 // the new blob instead of cons'ing up a new BDH. | |
| 2428 // | |
| 2429 // FIXME: Maybe we should require that it work that way where the ssv mu
st have a BDH for any | |
| 2430 // blobs it comes across during deserialization. Would require callers t
o explicitly populate | |
| 2431 // the collection of BDH's for blobs to work, which would encourage life
times to be considered | |
| 2432 // when passing ssv's around cross process. At present, we get 'lucky' i
n some cases because | |
| 2433 // the blob in the src process happens to still exist at the time the de
st process is deserializing. | |
| 2434 // For example in sharedWorker.postMessage(...). | |
| 2435 BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid); | |
| 2436 if (it != m_blobDataHandles.end()) { | |
| 2437 // make assertions about type and size? | |
| 2438 return it->value; | |
| 2439 } | |
| 2440 return BlobDataHandle::create(uuid, type, size); | |
| 2441 } | |
| 2442 | |
| 2443 bool doReadHmacKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& type) | |
| 2444 { | |
| 2445 uint32_t lengthBytes; | |
| 2446 if (!doReadUint32(&lengthBytes)) | |
| 2447 return false; | |
| 2448 WebCryptoAlgorithmId hash; | |
| 2449 if (!doReadAlgorithmId(hash)) | |
| 2450 return false; | |
| 2451 algorithm = WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8); | |
| 2452 type = WebCryptoKeyTypeSecret; | |
| 2453 return !algorithm.isNull(); | |
| 2454 } | |
| 2455 | |
| 2456 bool doReadAesKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& type) | |
| 2457 { | |
| 2458 WebCryptoAlgorithmId id; | |
| 2459 if (!doReadAlgorithmId(id)) | |
| 2460 return false; | |
| 2461 uint32_t lengthBytes; | |
| 2462 if (!doReadUint32(&lengthBytes)) | |
| 2463 return false; | |
| 2464 algorithm = WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8); | |
| 2465 type = WebCryptoKeyTypeSecret; | |
| 2466 return !algorithm.isNull(); | |
| 2467 } | |
| 2468 | |
| 2469 bool doReadRsaHashedKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType&
type) | |
| 2470 { | |
| 2471 WebCryptoAlgorithmId id; | |
| 2472 if (!doReadAlgorithmId(id)) | |
| 2473 return false; | |
| 2474 | |
| 2475 if (!doReadAsymmetricKeyType(type)) | |
| 2476 return false; | |
| 2477 | |
| 2478 uint32_t modulusLengthBits; | |
| 2479 if (!doReadUint32(&modulusLengthBits)) | |
| 2480 return false; | |
| 2481 | |
| 2482 uint32_t publicExponentSize; | |
| 2483 if (!doReadUint32(&publicExponentSize)) | |
| 2484 return false; | |
| 2485 | |
| 2486 if (m_position + publicExponentSize > m_length) | |
| 2487 return false; | |
| 2488 | |
| 2489 const uint8_t* publicExponent = m_buffer + m_position; | |
| 2490 m_position += publicExponentSize; | |
| 2491 | |
| 2492 WebCryptoAlgorithmId hash; | |
| 2493 if (!doReadAlgorithmId(hash)) | |
| 2494 return false; | |
| 2495 algorithm = WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits
, publicExponent, publicExponentSize, hash); | |
| 2496 | |
| 2497 return !algorithm.isNull(); | |
| 2498 } | |
| 2499 | |
| 2500 bool doReadEcKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& type) | |
| 2501 { | |
| 2502 WebCryptoAlgorithmId id; | |
| 2503 if (!doReadAlgorithmId(id)) | |
| 2504 return false; | |
| 2505 | |
| 2506 if (!doReadAsymmetricKeyType(type)) | |
| 2507 return false; | |
| 2508 | |
| 2509 WebCryptoNamedCurve namedCurve; | |
| 2510 if (!doReadNamedCurve(namedCurve)) | |
| 2511 return false; | |
| 2512 | |
| 2513 algorithm = WebCryptoKeyAlgorithm::createEc(id, namedCurve); | |
| 2514 return !algorithm.isNull(); | |
| 2515 } | |
| 2516 | |
| 2517 bool doReadAlgorithmId(WebCryptoAlgorithmId& id) | |
| 2518 { | |
| 2519 uint32_t rawId; | |
| 2520 if (!doReadUint32(&rawId)) | |
| 2521 return false; | |
| 2522 | |
| 2523 switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) { | |
| 2524 case AesCbcTag: | |
| 2525 id = WebCryptoAlgorithmIdAesCbc; | |
| 2526 return true; | |
| 2527 case HmacTag: | |
| 2528 id = WebCryptoAlgorithmIdHmac; | |
| 2529 return true; | |
| 2530 case RsaSsaPkcs1v1_5Tag: | |
| 2531 id = WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; | |
| 2532 return true; | |
| 2533 case Sha1Tag: | |
| 2534 id = WebCryptoAlgorithmIdSha1; | |
| 2535 return true; | |
| 2536 case Sha256Tag: | |
| 2537 id = WebCryptoAlgorithmIdSha256; | |
| 2538 return true; | |
| 2539 case Sha384Tag: | |
| 2540 id = WebCryptoAlgorithmIdSha384; | |
| 2541 return true; | |
| 2542 case Sha512Tag: | |
| 2543 id = WebCryptoAlgorithmIdSha512; | |
| 2544 return true; | |
| 2545 case AesGcmTag: | |
| 2546 id = WebCryptoAlgorithmIdAesGcm; | |
| 2547 return true; | |
| 2548 case RsaOaepTag: | |
| 2549 id = WebCryptoAlgorithmIdRsaOaep; | |
| 2550 return true; | |
| 2551 case AesCtrTag: | |
| 2552 id = WebCryptoAlgorithmIdAesCtr; | |
| 2553 return true; | |
| 2554 case AesKwTag: | |
| 2555 id = WebCryptoAlgorithmIdAesKw; | |
| 2556 return true; | |
| 2557 case RsaPssTag: | |
| 2558 id = WebCryptoAlgorithmIdRsaPss; | |
| 2559 return true; | |
| 2560 case EcdsaTag: | |
| 2561 id = WebCryptoAlgorithmIdEcdsa; | |
| 2562 return true; | |
| 2563 } | |
| 2564 | |
| 2565 return false; | |
| 2566 } | |
| 2567 | |
| 2568 bool doReadAsymmetricKeyType(WebCryptoKeyType& type) | |
| 2569 { | |
| 2570 uint32_t rawType; | |
| 2571 if (!doReadUint32(&rawType)) | |
| 2572 return false; | |
| 2573 | |
| 2574 switch (static_cast<AssymetricCryptoKeyType>(rawType)) { | |
| 2575 case PublicKeyType: | |
| 2576 type = WebCryptoKeyTypePublic; | |
| 2577 return true; | |
| 2578 case PrivateKeyType: | |
| 2579 type = WebCryptoKeyTypePrivate; | |
| 2580 return true; | |
| 2581 } | |
| 2582 | |
| 2583 return false; | |
| 2584 } | |
| 2585 | |
| 2586 bool doReadNamedCurve(WebCryptoNamedCurve& namedCurve) | |
| 2587 { | |
| 2588 uint32_t rawName; | |
| 2589 if (!doReadUint32(&rawName)) | |
| 2590 return false; | |
| 2591 | |
| 2592 switch (static_cast<NamedCurveTag>(rawName)) { | |
| 2593 case P256Tag: | |
| 2594 namedCurve = WebCryptoNamedCurveP256; | |
| 2595 return true; | |
| 2596 case P384Tag: | |
| 2597 namedCurve = WebCryptoNamedCurveP384; | |
| 2598 return true; | |
| 2599 case P521Tag: | |
| 2600 namedCurve = WebCryptoNamedCurveP521; | |
| 2601 return true; | |
| 2602 } | |
| 2603 | |
| 2604 return false; | |
| 2605 } | |
| 2606 | |
| 2607 bool doReadKeyUsages(WebCryptoKeyUsageMask& usages, bool& extractable) | |
| 2608 { | |
| 2609 // Reminder to update this when adding new key usages. | |
| 2610 COMPILE_ASSERT(EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); | |
| 2611 const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | Dec
ryptUsage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyU
sage | DeriveBitsUsage; | |
| 2612 | |
| 2613 uint32_t rawUsages; | |
| 2614 if (!doReadUint32(&rawUsages)) | |
| 2615 return false; | |
| 2616 | |
| 2617 // Make sure it doesn't contain an unrecognized usage value. | |
| 2618 if (rawUsages & ~allPossibleUsages) | |
| 2619 return false; | |
| 2620 | |
| 2621 usages = 0; | |
| 2622 | |
| 2623 extractable = rawUsages & ExtractableUsage; | |
| 2624 | |
| 2625 if (rawUsages & EncryptUsage) | |
| 2626 usages |= WebCryptoKeyUsageEncrypt; | |
| 2627 if (rawUsages & DecryptUsage) | |
| 2628 usages |= WebCryptoKeyUsageDecrypt; | |
| 2629 if (rawUsages & SignUsage) | |
| 2630 usages |= WebCryptoKeyUsageSign; | |
| 2631 if (rawUsages & VerifyUsage) | |
| 2632 usages |= WebCryptoKeyUsageVerify; | |
| 2633 if (rawUsages & DeriveKeyUsage) | |
| 2634 usages |= WebCryptoKeyUsageDeriveKey; | |
| 2635 if (rawUsages & WrapKeyUsage) | |
| 2636 usages |= WebCryptoKeyUsageWrapKey; | |
| 2637 if (rawUsages & UnwrapKeyUsage) | |
| 2638 usages |= WebCryptoKeyUsageUnwrapKey; | |
| 2639 if (rawUsages & DeriveBitsUsage) | |
| 2640 usages |= WebCryptoKeyUsageDeriveBits; | |
| 2641 | |
| 2642 return true; | |
| 2643 } | |
| 2644 | |
| 2645 RefPtr<ScriptState> m_scriptState; | |
| 2646 const uint8_t* m_buffer; | |
| 2647 const unsigned m_length; | |
| 2648 unsigned m_position; | |
| 2649 uint32_t m_version; | |
| 2650 const WebBlobInfoArray* m_blobInfo; | |
| 2651 const BlobDataHandleMap& m_blobDataHandles; | |
| 2652 }; | |
| 2653 | |
| 2654 | |
| 2655 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; | |
| 2656 | |
| 2657 class Deserializer final : public CompositeCreator { | |
| 2658 public: | |
| 2659 Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferCont
entsArray* arrayBufferContents) | |
| 2660 : m_reader(reader) | |
| 2661 , m_transferredMessagePorts(messagePorts) | |
| 2662 , m_arrayBufferContents(arrayBufferContents) | |
| 2663 , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0) | |
| 2664 , m_version(0) | |
| 2665 { | |
| 2666 } | |
| 2667 | |
| 2668 v8::Handle<v8::Value> deserialize() | |
| 2669 { | |
| 2670 v8::Isolate* isolate = m_reader.scriptState()->isolate(); | |
| 2671 if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValu
e::wireFormatVersion) | |
| 2672 return v8::Null(isolate); | |
| 2673 m_reader.setVersion(m_version); | |
| 2674 v8::EscapableHandleScope scope(isolate); | |
| 2675 while (!m_reader.isEof()) { | |
| 2676 if (!doDeserialize()) | |
| 2677 return v8::Null(isolate); | |
| 2678 } | |
| 2679 if (stackDepth() != 1 || m_openCompositeReferenceStack.size()) | |
| 2680 return v8::Null(isolate); | |
| 2681 v8::Handle<v8::Value> result = scope.Escape(element(0)); | |
| 2682 return result; | |
| 2683 } | |
| 2684 | |
| 2685 virtual bool newSparseArray(uint32_t) override | |
| 2686 { | |
| 2687 v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isol
ate(), 0); | |
| 2688 openComposite(array); | |
| 2689 return true; | |
| 2690 } | |
| 2691 | |
| 2692 virtual bool newDenseArray(uint32_t length) override | |
| 2693 { | |
| 2694 v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isol
ate(), length); | |
| 2695 openComposite(array); | |
| 2696 return true; | |
| 2697 } | |
| 2698 | |
| 2699 virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) override | |
| 2700 { | |
| 2701 if (stackDepth() < 1) | |
| 2702 return false; | |
| 2703 *object = element(stackDepth() - 1); | |
| 2704 pop(1); | |
| 2705 return true; | |
| 2706 } | |
| 2707 | |
| 2708 virtual bool newObject() override | |
| 2709 { | |
| 2710 v8::Local<v8::Object> object = v8::Object::New(m_reader.scriptState()->i
solate()); | |
| 2711 if (object.IsEmpty()) | |
| 2712 return false; | |
| 2713 openComposite(object); | |
| 2714 return true; | |
| 2715 } | |
| 2716 | |
| 2717 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* v
alue) override | |
| 2718 { | |
| 2719 v8::Local<v8::Object> object; | |
| 2720 if (m_version > 0) { | |
| 2721 v8::Local<v8::Value> composite; | |
| 2722 if (!closeComposite(&composite)) | |
| 2723 return false; | |
| 2724 object = composite.As<v8::Object>(); | |
| 2725 } else { | |
| 2726 object = v8::Object::New(m_reader.scriptState()->isolate()); | |
| 2727 } | |
| 2728 if (object.IsEmpty()) | |
| 2729 return false; | |
| 2730 return initializeObject(object, numProperties, value); | |
| 2731 } | |
| 2732 | |
| 2733 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8
::Handle<v8::Value>* value) override | |
| 2734 { | |
| 2735 v8::Local<v8::Array> array; | |
| 2736 if (m_version > 0) { | |
| 2737 v8::Local<v8::Value> composite; | |
| 2738 if (!closeComposite(&composite)) | |
| 2739 return false; | |
| 2740 array = composite.As<v8::Array>(); | |
| 2741 } else { | |
| 2742 array = v8::Array::New(m_reader.scriptState()->isolate()); | |
| 2743 } | |
| 2744 if (array.IsEmpty()) | |
| 2745 return false; | |
| 2746 return initializeObject(array, numProperties, value); | |
| 2747 } | |
| 2748 | |
| 2749 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8:
:Handle<v8::Value>* value) override | |
| 2750 { | |
| 2751 v8::Local<v8::Array> array; | |
| 2752 if (m_version > 0) { | |
| 2753 v8::Local<v8::Value> composite; | |
| 2754 if (!closeComposite(&composite)) | |
| 2755 return false; | |
| 2756 array = composite.As<v8::Array>(); | |
| 2757 } | |
| 2758 if (array.IsEmpty()) | |
| 2759 return false; | |
| 2760 if (!initializeObject(array, numProperties, value)) | |
| 2761 return false; | |
| 2762 if (length > stackDepth()) | |
| 2763 return false; | |
| 2764 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++,
stackPos++) { | |
| 2765 v8::Local<v8::Value> elem = element(stackPos); | |
| 2766 if (!elem->IsUndefined()) | |
| 2767 array->Set(i, elem); | |
| 2768 } | |
| 2769 pop(length); | |
| 2770 return true; | |
| 2771 } | |
| 2772 | |
| 2773 virtual void pushObjectReference(const v8::Handle<v8::Value>& object) overri
de | |
| 2774 { | |
| 2775 m_objectPool.append(object); | |
| 2776 } | |
| 2777 | |
| 2778 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Val
ue>* object) override | |
| 2779 { | |
| 2780 if (!m_transferredMessagePorts) | |
| 2781 return false; | |
| 2782 if (index >= m_transferredMessagePorts->size()) | |
| 2783 return false; | |
| 2784 v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context
()->Global(); | |
| 2785 *object = toV8(m_transferredMessagePorts->at(index).get(), creationConte
xt, m_reader.scriptState()->isolate()); | |
| 2786 return true; | |
| 2787 } | |
| 2788 | |
| 2789 virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Val
ue>* object) override | |
| 2790 { | |
| 2791 if (!m_arrayBufferContents) | |
| 2792 return false; | |
| 2793 if (index >= m_arrayBuffers.size()) | |
| 2794 return false; | |
| 2795 v8::Handle<v8::Object> result = m_arrayBuffers.at(index); | |
| 2796 if (result.IsEmpty()) { | |
| 2797 RefPtr<DOMArrayBuffer> buffer = DOMArrayBuffer::create(m_arrayBuffer
Contents->at(index)); | |
| 2798 v8::Isolate* isolate = m_reader.scriptState()->isolate(); | |
| 2799 v8::Handle<v8::Object> creationContext = m_reader.scriptState()->con
text()->Global(); | |
| 2800 result = toV8Object(buffer.get(), creationContext, isolate); | |
| 2801 m_arrayBuffers[index] = result; | |
| 2802 } | |
| 2803 *object = result; | |
| 2804 return true; | |
| 2805 } | |
| 2806 | |
| 2807 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<
v8::Value>* object) override | |
| 2808 { | |
| 2809 if (reference >= m_objectPool.size()) | |
| 2810 return false; | |
| 2811 *object = m_objectPool[reference]; | |
| 2812 return object; | |
| 2813 } | |
| 2814 | |
| 2815 virtual uint32_t objectReferenceCount() override | |
| 2816 { | |
| 2817 return m_objectPool.size(); | |
| 2818 } | |
| 2819 | |
| 2820 private: | |
| 2821 bool initializeObject(v8::Handle<v8::Object> object, uint32_t numProperties,
v8::Handle<v8::Value>* value) | |
| 2822 { | |
| 2823 unsigned length = 2 * numProperties; | |
| 2824 if (length > stackDepth()) | |
| 2825 return false; | |
| 2826 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) { | |
| 2827 v8::Local<v8::Value> propertyName = element(i); | |
| 2828 v8::Local<v8::Value> propertyValue = element(i + 1); | |
| 2829 object->Set(propertyName, propertyValue); | |
| 2830 } | |
| 2831 pop(length); | |
| 2832 *value = object; | |
| 2833 return true; | |
| 2834 } | |
| 2835 | |
| 2836 bool doDeserialize() | |
| 2837 { | |
| 2838 v8::Local<v8::Value> value; | |
| 2839 if (!m_reader.read(&value, *this)) | |
| 2840 return false; | |
| 2841 if (!value.IsEmpty()) | |
| 2842 push(value); | |
| 2843 return true; | |
| 2844 } | |
| 2845 | |
| 2846 void push(v8::Local<v8::Value> value) { m_stack.append(value); } | |
| 2847 | |
| 2848 void pop(unsigned length) | |
| 2849 { | |
| 2850 ASSERT(length <= m_stack.size()); | |
| 2851 m_stack.shrink(m_stack.size() - length); | |
| 2852 } | |
| 2853 | |
| 2854 unsigned stackDepth() const { return m_stack.size(); } | |
| 2855 | |
| 2856 v8::Local<v8::Value> element(unsigned index) | |
| 2857 { | |
| 2858 ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size()); | |
| 2859 return m_stack[index]; | |
| 2860 } | |
| 2861 | |
| 2862 void openComposite(const v8::Local<v8::Value>& object) | |
| 2863 { | |
| 2864 uint32_t newObjectReference = m_objectPool.size(); | |
| 2865 m_openCompositeReferenceStack.append(newObjectReference); | |
| 2866 m_objectPool.append(object); | |
| 2867 } | |
| 2868 | |
| 2869 bool closeComposite(v8::Handle<v8::Value>* object) | |
| 2870 { | |
| 2871 if (!m_openCompositeReferenceStack.size()) | |
| 2872 return false; | |
| 2873 uint32_t objectReference = m_openCompositeReferenceStack[m_openComposite
ReferenceStack.size() - 1]; | |
| 2874 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size(
) - 1); | |
| 2875 if (objectReference >= m_objectPool.size()) | |
| 2876 return false; | |
| 2877 *object = m_objectPool[objectReference]; | |
| 2878 return true; | |
| 2879 } | |
| 2880 | |
| 2881 Reader& m_reader; | |
| 2882 Vector<v8::Local<v8::Value> > m_stack; | |
| 2883 Vector<v8::Handle<v8::Value> > m_objectPool; | |
| 2884 Vector<uint32_t> m_openCompositeReferenceStack; | |
| 2885 RawPtrWillBeMember<MessagePortArray> m_transferredMessagePorts; | |
| 2886 ArrayBufferContentsArray* m_arrayBufferContents; | |
| 2887 Vector<v8::Handle<v8::Object> > m_arrayBuffers; | |
| 2888 uint32_t m_version; | |
| 2889 }; | |
| 2890 | |
| 2891 } // namespace | |
| 2892 | |
| 2893 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::V
alue> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Exc
eptionState& exceptionState, v8::Isolate* isolate) | 61 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::V
alue> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Exc
eptionState& exceptionState, v8::Isolate* isolate) |
| 2894 { | 62 { |
| 2895 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers,
0, exceptionState, isolate)); | 63 return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers,
0, exceptionState, isolate)); |
| 2896 } | 64 } |
| 2897 | 65 |
| 2898 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExcepti
ons(v8::Isolate* isolate, v8::Handle<v8::Value> value) | 66 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExcepti
ons(v8::Isolate* isolate, v8::Handle<v8::Value> value) |
| 2899 { | 67 { |
| 2900 TrackExceptionState exceptionState; | 68 TrackExceptionState exceptionState; |
| 2901 return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, is
olate)); | 69 return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, is
olate)); |
| 2902 } | 70 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2926 return createFromWire(String::adopt(buffer)); | 94 return createFromWire(String::adopt(buffer)); |
| 2927 } | 95 } |
| 2928 | 96 |
| 2929 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da
ta) | 97 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da
ta) |
| 2930 { | 98 { |
| 2931 return create(data, v8::Isolate::GetCurrent()); | 99 return create(data, v8::Isolate::GetCurrent()); |
| 2932 } | 100 } |
| 2933 | 101 |
| 2934 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da
ta, v8::Isolate* isolate) | 102 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da
ta, v8::Isolate* isolate) |
| 2935 { | 103 { |
| 2936 Writer writer; | 104 SerializedScriptValueInternal::Writer writer; |
| 2937 writer.writeWebCoreString(data); | 105 writer.writeWebCoreString(data); |
| 2938 String wireData = writer.takeWireString(); | 106 String wireData = writer.takeWireString(); |
| 2939 return adoptRef(new SerializedScriptValue(wireData)); | 107 return adoptRef(new SerializedScriptValue(wireData)); |
| 2940 } | 108 } |
| 2941 | 109 |
| 2942 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create() | 110 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create() |
| 2943 { | 111 { |
| 2944 return adoptRef(new SerializedScriptValue()); | 112 return adoptRef(new SerializedScriptValue()); |
| 2945 } | 113 } |
| 2946 | 114 |
| 2947 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() | 115 PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() |
| 2948 { | 116 { |
| 2949 Writer writer; | 117 SerializedScriptValueInternal::Writer writer; |
| 2950 writer.writeNull(); | 118 writer.writeNull(); |
| 2951 String wireData = writer.takeWireString(); | 119 String wireData = writer.takeWireString(); |
| 2952 return adoptRef(new SerializedScriptValue(wireData)); | 120 return adoptRef(new SerializedScriptValue(wireData)); |
| 2953 } | 121 } |
| 2954 | 122 |
| 2955 // Convert serialized string to big endian wire data. | 123 // Convert serialized string to big endian wire data. |
| 2956 void SerializedScriptValue::toWireBytes(Vector<char>& result) const | 124 void SerializedScriptValue::toWireBytes(Vector<char>& result) const |
| 2957 { | 125 { |
| 2958 ASSERT(result.isEmpty()); | 126 ASSERT(result.isEmpty()); |
| 2959 size_t length = m_data.length(); | 127 size_t length = m_data.length(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3024 } | 192 } |
| 3025 | 193 |
| 3026 neuterArrayBufferInAllWorlds(arrayBuffers[i].get()); | 194 neuterArrayBufferInAllWorlds(arrayBuffers[i].get()); |
| 3027 } | 195 } |
| 3028 return contents.release(); | 196 return contents.release(); |
| 3029 } | 197 } |
| 3030 | 198 |
| 3031 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, Messag
ePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blob
Info, ExceptionState& exceptionState, v8::Isolate* isolate) | 199 SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, Messag
ePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blob
Info, ExceptionState& exceptionState, v8::Isolate* isolate) |
| 3032 : m_externallyAllocatedMemory(0) | 200 : m_externallyAllocatedMemory(0) |
| 3033 { | 201 { |
| 3034 Writer writer; | 202 SerializedScriptValueInternal::Writer writer; |
| 3035 Serializer::Status status; | 203 SerializedScriptValueInternal::Serializer::Status status; |
| 3036 String errorMessage; | 204 String errorMessage; |
| 3037 { | 205 { |
| 3038 v8::TryCatch tryCatch; | 206 v8::TryCatch tryCatch; |
| 3039 Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_bl
obDataHandles, tryCatch, ScriptState::current(isolate)); | 207 SerializedScriptValueInternal::Serializer serializer(writer, messagePort
s, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, ScriptState::current(iso
late)); |
| 3040 status = serializer.serialize(value); | 208 status = serializer.serialize(value); |
| 3041 if (status == Serializer::JSException) { | 209 if (status == SerializedScriptValueInternal::Serializer::JSException) { |
| 3042 // If there was a JS exception thrown, re-throw it. | 210 // If there was a JS exception thrown, re-throw it. |
| 3043 exceptionState.rethrowV8Exception(tryCatch.Exception()); | 211 exceptionState.rethrowV8Exception(tryCatch.Exception()); |
| 3044 return; | 212 return; |
| 3045 } | 213 } |
| 3046 errorMessage = serializer.errorMessage(); | 214 errorMessage = serializer.errorMessage(); |
| 3047 } | 215 } |
| 3048 switch (status) { | 216 switch (status) { |
| 3049 case Serializer::InputError: | 217 case SerializedScriptValueInternal::Serializer::InputError: |
| 3050 case Serializer::DataCloneError: | 218 case SerializedScriptValueInternal::Serializer::DataCloneError: |
| 3051 exceptionState.throwDOMException(DataCloneError, errorMessage); | 219 exceptionState.throwDOMException(DataCloneError, errorMessage); |
| 3052 return; | 220 return; |
| 3053 case Serializer::Success: | 221 case SerializedScriptValueInternal::Serializer::Success: |
| 3054 m_data = writer.takeWireString(); | 222 m_data = writer.takeWireString(); |
| 3055 ASSERT(m_data.impl()->hasOneRef()); | 223 ASSERT(m_data.impl()->hasOneRef()); |
| 3056 if (arrayBuffers && arrayBuffers->size()) | 224 if (arrayBuffers && arrayBuffers->size()) |
| 3057 m_arrayBufferContentsArray = transferArrayBuffers(isolate, *arrayBuf
fers, exceptionState); | 225 m_arrayBufferContentsArray = transferArrayBuffers(isolate, *arrayBuf
fers, exceptionState); |
| 3058 return; | 226 return; |
| 3059 case Serializer::JSException: | 227 case SerializedScriptValueInternal::Serializer::JSException: |
| 3060 ASSERT_NOT_REACHED(); | 228 ASSERT_NOT_REACHED(); |
| 3061 break; | 229 break; |
| 3062 } | 230 } |
| 3063 ASSERT_NOT_REACHED(); | 231 ASSERT_NOT_REACHED(); |
| 3064 } | 232 } |
| 3065 | 233 |
| 3066 SerializedScriptValue::SerializedScriptValue(const String& wireData) | 234 SerializedScriptValue::SerializedScriptValue(const String& wireData) |
| 3067 : m_externallyAllocatedMemory(0) | 235 : m_externallyAllocatedMemory(0) |
| 3068 { | 236 { |
| 3069 m_data = wireData.isolatedCopy(); | 237 m_data = wireData.isolatedCopy(); |
| 3070 } | 238 } |
| 3071 | 239 |
| 3072 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messa
gePorts) | 240 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messa
gePorts) |
| 3073 { | 241 { |
| 3074 return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0); | 242 return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0); |
| 3075 } | 243 } |
| 3076 | 244 |
| 3077 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M
essagePortArray* messagePorts, const WebBlobInfoArray* blobInfo) | 245 v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M
essagePortArray* messagePorts, const WebBlobInfoArray* blobInfo) |
| 3078 { | 246 { |
| 3079 if (!m_data.impl()) | 247 if (!m_data.impl()) |
| 3080 return v8::Null(isolate); | 248 return v8::Null(isolate); |
| 3081 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); | 249 COMPILE_ASSERT(sizeof(SerializedScriptValueInternal::Writer::BufferValueType
) == 2, BufferValueTypeIsTwoBytes); |
| 3082 m_data.ensure16Bit(); | 250 m_data.ensure16Bit(); |
| 3083 // FIXME: SerializedScriptValue shouldn't use String for its underlying | 251 // FIXME: SerializedScriptValue shouldn't use String for its underlying |
| 3084 // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The | 252 // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The |
| 3085 // information stored in m_data isn't even encoded in UTF-16. Instead, | 253 // information stored in m_data isn't even encoded in UTF-16. Instead, |
| 3086 // unicode characters are encoded as UTF-8 with two code units per UChar. | 254 // unicode characters are encoded as UTF-8 with two code units per UChar. |
| 3087 Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()
), 2 * m_data.length(), blobInfo, m_blobDataHandles, ScriptState::current(isolat
e)); | 255 SerializedScriptValueInternal::Reader reader(reinterpret_cast<const uint8_t*
>(m_data.impl()->characters16()), 2 * m_data.length(), blobInfo, m_blobDataHandl
es, ScriptState::current(isolate)); |
| 3088 Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.g
et()); | 256 SerializedScriptValueInternal::Deserializer deserializer(reader, messagePort
s, m_arrayBufferContentsArray.get()); |
| 3089 | 257 |
| 3090 // deserialize() can run arbitrary script (e.g., setters), which could resul
t in |this| being destroyed. | 258 // deserialize() can run arbitrary script (e.g., setters), which could resul
t in |this| being destroyed. |
| 3091 // Holding a RefPtr ensures we are alive (along with our internal data) thro
ughout the operation. | 259 // Holding a RefPtr ensures we are alive (along with our internal data) thro
ughout the operation. |
| 3092 RefPtr<SerializedScriptValue> protect(this); | 260 RefPtr<SerializedScriptValue> protect(this); |
| 3093 return deserializer.deserialize(); | 261 return deserializer.deserialize(); |
| 3094 } | 262 } |
| 3095 | 263 |
| 3096 bool SerializedScriptValue::extractTransferables(v8::Isolate* isolate, v8::Local
<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray&
arrayBuffers, ExceptionState& exceptionState) | 264 bool SerializedScriptValue::extractTransferables(v8::Isolate* isolate, v8::Local
<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray&
arrayBuffers, ExceptionState& exceptionState) |
| 3097 { | 265 { |
| 3098 if (isUndefinedOrNull(value)) { | 266 if (isUndefinedOrNull(value)) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3158 // If the allocated memory was not registered before, then this class is lik
ely | 326 // If the allocated memory was not registered before, then this class is lik
ely |
| 3159 // used in a context other then Worker's onmessage environment and the prese
nce of | 327 // used in a context other then Worker's onmessage environment and the prese
nce of |
| 3160 // current v8 context is not guaranteed. Avoid calling v8 then. | 328 // current v8 context is not guaranteed. Avoid calling v8 then. |
| 3161 if (m_externallyAllocatedMemory) { | 329 if (m_externallyAllocatedMemory) { |
| 3162 ASSERT(v8::Isolate::GetCurrent()); | 330 ASSERT(v8::Isolate::GetCurrent()); |
| 3163 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_exte
rnallyAllocatedMemory); | 331 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_exte
rnallyAllocatedMemory); |
| 3164 } | 332 } |
| 3165 } | 333 } |
| 3166 | 334 |
| 3167 } // namespace blink | 335 } // namespace blink |
| OLD | NEW |