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