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