• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
contains(const v8::Handle<GCObject> & handle)109     bool contains(const v8::Handle<GCObject>& handle)
110     {
111         return m_map.contains(*handle);
112     }
113 
tryGet(const v8::Handle<GCObject> & handle,T * valueOut)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 
set(const v8::Handle<GCObject> & handle,const T & value)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 {
unsafeHandleFromRawValueWebCore::__anona12e75660111::V8ObjectMap::V8HandlePtrHash142         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 
hashWebCore::__anona12e75660111::V8ObjectMap::V8HandlePtrHash148         static unsigned hash(const G* key)
149         {
150             return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash());
151         }
equalWebCore::__anona12e75660111::V8ObjectMap::V8HandlePtrHash152         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 
shouldCheckForCycles(int depth)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:
encode(uint32_t value)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 
decode(uint32_t value)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:
Writer()343     Writer()
344         : m_position(0)
345     {
346     }
347 
348     // Write functions for primitive types.
349 
writeUndefined()350     void writeUndefined() { append(UndefinedTag); }
351 
writeNull()352     void writeNull() { append(NullTag); }
353 
writeTrue()354     void writeTrue() { append(TrueTag); }
355 
writeFalse()356     void writeFalse() { append(FalseTag); }
357 
writeBooleanObject(bool value)358     void writeBooleanObject(bool value)
359     {
360         append(value ? TrueObjectTag : FalseObjectTag);
361     }
362 
writeOneByteString(v8::Handle<v8::String> & string)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 
writeUCharString(v8::Handle<v8::String> & string)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 
writeStringObject(const char * data,int length)403     void writeStringObject(const char* data, int length)
404     {
405         ASSERT(length >= 0);
406         append(StringObjectTag);
407         doWriteString(data, length);
408     }
409 
writeWebCoreString(const String & string)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 
writeVersion()418     void writeVersion()
419     {
420         append(VersionTag);
421         doWriteUint32(SerializedScriptValue::wireFormatVersion);
422     }
423 
writeInt32(int32_t value)424     void writeInt32(int32_t value)
425     {
426         append(Int32Tag);
427         doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value)));
428     }
429 
writeUint32(uint32_t value)430     void writeUint32(uint32_t value)
431     {
432         append(Uint32Tag);
433         doWriteUint32(value);
434     }
435 
writeDate(double numberValue)436     void writeDate(double numberValue)
437     {
438         append(DateTag);
439         doWriteNumber(numberValue);
440     }
441 
writeNumber(double number)442     void writeNumber(double number)
443     {
444         append(NumberTag);
445         doWriteNumber(number);
446     }
447 
writeNumberObject(double number)448     void writeNumberObject(double number)
449     {
450         append(NumberObjectTag);
451         doWriteNumber(number);
452     }
453 
writeBlob(const String & uuid,const String & type,unsigned long long size)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 
writeBlobIndex(int blobIndex)462     void writeBlobIndex(int blobIndex)
463     {
464         ASSERT(blobIndex >= 0);
465         append(BlobIndexTag);
466         doWriteUint32(blobIndex);
467     }
468 
writeDOMFileSystem(int type,const String & name,const String & url)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 
writeFile(const File & file)477     void writeFile(const File& file)
478     {
479         append(FileTag);
480         doWriteFile(file);
481     }
482 
writeFileIndex(int blobIndex)483     void writeFileIndex(int blobIndex)
484     {
485         append(FileIndexTag);
486         doWriteUint32(blobIndex);
487     }
488 
writeFileList(const FileList & fileList)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 
writeFileListIndex(const Vector<int> & blobIndices)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 
writeCryptoKey(const blink::WebCryptoKey & key)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 
writeArrayBuffer(const ArrayBuffer & arrayBuffer)537     void writeArrayBuffer(const ArrayBuffer& arrayBuffer)
538     {
539         append(ArrayBufferTag);
540         doWriteArrayBuffer(arrayBuffer);
541     }
542 
writeArrayBufferView(const ArrayBufferView & arrayBufferView)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 
writeImageData(uint32_t width,uint32_t height,const uint8_t * pixelData,uint32_t pixelDataLength)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 
writeRegExp(v8::Local<v8::String> pattern,v8::RegExp::Flags flags)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 
writeTransferredMessagePort(uint32_t index)596     void writeTransferredMessagePort(uint32_t index)
597     {
598         append(MessagePortTag);
599         doWriteUint32(index);
600     }
601 
writeTransferredArrayBuffer(uint32_t index)602     void writeTransferredArrayBuffer(uint32_t index)
603     {
604         append(ArrayBufferTransferTag);
605         doWriteUint32(index);
606     }
607 
writeObjectReference(uint32_t reference)608     void writeObjectReference(uint32_t reference)
609     {
610         append(ObjectReferenceTag);
611         doWriteUint32(reference);
612     }
613 
writeObject(uint32_t numProperties)614     void writeObject(uint32_t numProperties)
615     {
616         append(ObjectTag);
617         doWriteUint32(numProperties);
618     }
619 
writeSparseArray(uint32_t numProperties,uint32_t length)620     void writeSparseArray(uint32_t numProperties, uint32_t length)
621     {
622         append(SparseArrayTag);
623         doWriteUint32(numProperties);
624         doWriteUint32(length);
625     }
626 
writeDenseArray(uint32_t numProperties,uint32_t length)627     void writeDenseArray(uint32_t numProperties, uint32_t length)
628     {
629         append(DenseArrayTag);
630         doWriteUint32(numProperties);
631         doWriteUint32(length);
632     }
633 
takeWireString()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 
writeReferenceCount(uint32_t numberOfReferences)643     void writeReferenceCount(uint32_t numberOfReferences)
644     {
645         append(ReferenceCountTag);
646         doWriteUint32(numberOfReferences);
647     }
648 
writeGenerateFreshObject()649     void writeGenerateFreshObject()
650     {
651         append(GenerateFreshObjectTag);
652     }
653 
writeGenerateFreshSparseArray(uint32_t length)654     void writeGenerateFreshSparseArray(uint32_t length)
655     {
656         append(GenerateFreshSparseArrayTag);
657         doWriteUint32(length);
658     }
659 
writeGenerateFreshDenseArray(uint32_t length)660     void writeGenerateFreshDenseArray(uint32_t length)
661     {
662         append(GenerateFreshDenseArrayTag);
663         doWriteUint32(length);
664     }
665 
666 private:
doWriteFile(const File & file)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 
doWriteArrayBuffer(const ArrayBuffer & arrayBuffer)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 
doWriteString(const char * data,int length)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 
doWriteWebCoreString(const String & string)702     void doWriteWebCoreString(const String& string)
703     {
704         StringUTF8Adaptor stringUTF8(string);
705         doWriteString(stringUTF8.data(), stringUTF8.length());
706     }
707 
doWriteHmacKey(const blink::WebCryptoKey & key)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 
doWriteAesKey(const blink::WebCryptoKey & key)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 
doWriteRsaHashedKey(const blink::WebCryptoKey & key)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 
doWriteAlgorithmId(blink::WebCryptoAlgorithmId id)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 
doWriteKeyUsages(const blink::WebCryptoKeyUsageMask usages,bool extractable)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 
bytesNeededToWireEncode(uint32_t value)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>
doWriteUintHelper(T value)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 
doWriteUint32(uint32_t value)841     void doWriteUint32(uint32_t value)
842     {
843         doWriteUintHelper(value);
844     }
845 
doWriteUint64(uint64_t value)846     void doWriteUint64(uint64_t value)
847     {
848         doWriteUintHelper(value);
849     }
850 
doWriteNumber(double number)851     void doWriteNumber(double number)
852     {
853         append(reinterpret_cast<uint8_t*>(&number), sizeof(number));
854     }
855 
append(SerializationTag tag)856     void append(SerializationTag tag)
857     {
858         append(static_cast<uint8_t>(tag));
859     }
860 
append(uint8_t b)861     void append(uint8_t b)
862     {
863         ensureSpace(1);
864         *byteAt(m_position++) = b;
865     }
866 
append(const uint8_t * data,int length)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 
ensureSpace(unsigned extra)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 
fillHole()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 
byteAt(int position)889     uint8_t* byteAt(int position)
890     {
891         return reinterpret_cast<uint8_t*>(m_buffer.data()) + position;
892     }
893 
v8StringWriteOptions()894     int v8StringWriteOptions()
895     {
896         return v8::String::NO_NULL_TERMINATION;
897     }
898 
899     Vector<BufferValueType> m_buffer;
900     unsigned m_position;
901 };
902 
toV8Object(MessagePort * impl,v8::Handle<v8::Object> creationContext,v8::Isolate * isolate)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 
toV8Object(ArrayBuffer * impl,v8::Handle<v8::Object> creationContext,v8::Isolate * isolate)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 
Serializer(Writer & writer,MessagePortArray * messagePorts,ArrayBufferArray * arrayBuffers,WebBlobInfoArray * blobInfo,BlobDataHandleMap & blobDataHandles,v8::TryCatch & tryCatch,ScriptState * scriptState)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 
isolate()957     v8::Isolate* isolate() { return m_scriptState->isolate(); }
958 
serialize(v8::Handle<v8::Value> value)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 
errorMessage()969     String errorMessage() { return m_errorMessage; }
970 
971     // Functions used by serialization states.
972     StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
973 
doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer,StateBase * next)974     StateBase* doSerializeArrayBuffer(v8::Handle<v8::Value> arrayBuffer, StateBase* next)
975     {
976         return doSerialize(arrayBuffer, next);
977     }
978 
checkException(StateBase * state)979     StateBase* checkException(StateBase* state)
980     {
981         return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0;
982     }
983 
writeObject(uint32_t numProperties,StateBase * state)984     StateBase* writeObject(uint32_t numProperties, StateBase* state)
985     {
986         m_writer.writeObject(numProperties);
987         return pop(state);
988     }
989 
writeSparseArray(uint32_t numProperties,uint32_t length,StateBase * state)990     StateBase* writeSparseArray(uint32_t numProperties, uint32_t length, StateBase* state)
991     {
992         m_writer.writeSparseArray(numProperties, length);
993         return pop(state);
994     }
995 
writeDenseArray(uint32_t numProperties,uint32_t length,StateBase * state)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:
~StateBase()1007         virtual ~StateBase() { }
1008 
1009         // Link to the next state to form a stack.
nextState()1010         StateBase* nextState() { return m_next; }
1011 
1012         // Composite object we're processing in this state.
composite()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:
StateBase(v8::Handle<v8::Value> composite,StateBase * next)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:
ErrorState()1035         ErrorState()
1036             : StateBase(v8Undefined(), 0)
1037         {
1038         }
1039 
advance(Serializer &)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:
composite()1050         v8::Handle<T> composite() { return v8::Handle<T>::Cast(StateBase::composite()); }
1051 
1052     protected:
State(v8::Handle<T> composite,StateBase * next)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:
AbstractObjectState(v8::Handle<v8::Object> object,StateBase * next)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 
serializeProperties(bool ignoreIndexed,Serializer & serializer)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:
ObjectState(v8::Handle<v8::Object> object,StateBase * next)1127         ObjectState(v8::Handle<v8::Object> object, StateBase* next)
1128             : AbstractObjectState(object, next)
1129         {
1130         }
1131 
advance(Serializer & serializer)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:
objectDone(unsigned numProperties,Serializer & serializer)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:
DenseArrayState(v8::Handle<v8::Array> array,v8::Handle<v8::Array> propertyNames,StateBase * next,v8::Isolate * isolate)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 
advance(Serializer & serializer)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:
objectDone(unsigned numProperties,Serializer & serializer)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:
SparseArrayState(v8::Handle<v8::Array> array,v8::Handle<v8::Array> propertyNames,StateBase * next,v8::Isolate * isolate)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 
advance(Serializer & serializer)1193         virtual StateBase* advance(Serializer& serializer) OVERRIDE
1194         {
1195             return serializeProperties(false, serializer);
1196         }
1197 
1198     protected:
objectDone(unsigned numProperties,Serializer & serializer)1199         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE
1200         {
1201             return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this);
1202         }
1203     };
1204 
push(StateBase * state)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 
pop(StateBase * state)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 
handleError(Status errorStatus,const String & message,StateBase * state)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 
checkComposite(StateBase * top)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 
writeString(v8::Handle<v8::Value> value)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 
writeStringObject(v8::Handle<v8::Value> value)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 
writeNumberObject(v8::Handle<v8::Value> value)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 
writeBooleanObject(v8::Handle<v8::Value> value)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 
writeBlob(v8::Handle<v8::Value> value,StateBase * next)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 
writeDOMFileSystem(v8::Handle<v8::Value> value,StateBase * next)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 
writeFile(v8::Handle<v8::Value> value,StateBase * next)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 
writeFileList(v8::Handle<v8::Value> value,StateBase * next)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 
writeCryptoKey(v8::Handle<v8::Value> value)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 
writeImageData(v8::Handle<v8::Value> value)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 
writeRegExp(v8::Handle<v8::Value> value)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 
writeAndGreyArrayBufferView(v8::Handle<v8::Object> object,StateBase * next)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 
writeArrayBuffer(v8::Handle<v8::Value> value,StateBase * next)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 
writeTransferredArrayBuffer(v8::Handle<v8::Value> value,uint32_t index,StateBase * next)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 
shouldSerializeDensely(uint32_t length,uint32_t propertyCount)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 
startArrayState(v8::Handle<v8::Array> array,StateBase * next)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 
startObjectState(v8::Handle<v8::Object> object,StateBase * next)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.
greyObject(const v8::Handle<v8::Object> & object)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 
appendBlobInfo(const String & uuid,const String & type,unsigned long long size,int * index)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 
appendFileInfo(const File * file,int * index)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.
isHostObject(v8::Handle<v8::Object> object)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 
doSerialize(v8::Handle<v8::Value> value,StateBase * next)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:
~CompositeCreator()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:
Reader(const uint8_t * buffer,int length,const WebBlobInfoArray * blobInfo,BlobDataHandleMap & blobDataHandles,ScriptState * scriptState)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 
isEof() const1629     bool isEof() const { return m_position >= m_length; }
1630 
scriptState() const1631     ScriptState* scriptState() const { return m_scriptState.get(); }
1632 
1633 private:
isolate() const1634     v8::Isolate* isolate() const { return m_scriptState->isolate(); }
1635 
1636 public:
read(v8::Handle<v8::Value> * value,CompositeCreator & creator)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 
readVersion(uint32_t & version)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 
setVersion(uint32_t version)1882     void setVersion(uint32_t version)
1883     {
1884         m_version = version;
1885     }
1886 
1887 private:
readTag(SerializationTag * tag)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 
undoReadTag()1896     void undoReadTag()
1897     {
1898         if (m_position > 0)
1899             --m_position;
1900     }
1901 
readArrayBufferViewSubTag(ArrayBufferViewSubTag * tag)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 
readString(v8::Handle<v8::Value> * value)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 
readUCharString(v8::Handle<v8::Value> * value)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 
readStringObject(v8::Handle<v8::Value> * value)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 
readWebCoreString(String * string)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 
readInt32(v8::Handle<v8::Value> * value)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 
readUint32(v8::Handle<v8::Value> * value)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 
readDate(v8::Handle<v8::Value> * value)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 
readNumber(v8::Handle<v8::Value> * value)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 
readNumberObject(v8::Handle<v8::Value> * value)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 
readImageData(v8::Handle<v8::Value> * value)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 
doReadArrayBuffer()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 
readArrayBuffer(v8::Handle<v8::Value> * value)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 
readArrayBufferView(v8::Handle<v8::Value> * value,CompositeCreator & creator)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 
readRegExp(v8::Handle<v8::Value> * value)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 
readBlob(v8::Handle<v8::Value> * value,bool isIndexed)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 
readDOMFileSystem(v8::Handle<v8::Value> * value)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 
readFile(v8::Handle<v8::Value> * value,bool isIndexed)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 
readFileList(v8::Handle<v8::Value> * value,bool isIndexed)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 
readCryptoKey(v8::Handle<v8::Value> * value)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 
readFileHelper()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 
readFileIndexHelper()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>
doReadUintHelper(T * value)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 
doReadUint32(uint32_t * value)2347     bool doReadUint32(uint32_t* value)
2348     {
2349         return doReadUintHelper(value);
2350     }
2351 
doReadUint64(uint64_t * value)2352     bool doReadUint64(uint64_t* value)
2353     {
2354         return doReadUintHelper(value);
2355     }
2356 
doReadNumber(double * number)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 
getOrCreateBlobDataHandle(const String & uuid,const String & type,long long size=-1)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 
doReadHmacKey(blink::WebCryptoKeyAlgorithm & algorithm,blink::WebCryptoKeyType & type)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 
doReadAesKey(blink::WebCryptoKeyAlgorithm & algorithm,blink::WebCryptoKeyType & type)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 
doReadRsaHashedKey(blink::WebCryptoKeyAlgorithm & algorithm,blink::WebCryptoKeyType & type)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 
doReadAlgorithmId(blink::WebCryptoAlgorithmId & id)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 
doReadKeyUsages(blink::WebCryptoKeyUsageMask & usages,bool & extractable)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:
Deserializer(Reader & reader,MessagePortArray * messagePorts,ArrayBufferContentsArray * arrayBufferContents)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 
deserialize()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 
newSparseArray(uint32_t)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 
newDenseArray(uint32_t length)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 
consumeTopOfStack(v8::Handle<v8::Value> * object)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 
newObject()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 
completeObject(uint32_t numProperties,v8::Handle<v8::Value> * value)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 
completeSparseArray(uint32_t numProperties,uint32_t length,v8::Handle<v8::Value> * value)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 
completeDenseArray(uint32_t numProperties,uint32_t length,v8::Handle<v8::Value> * value)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 
pushObjectReference(const v8::Handle<v8::Value> & object)2667     virtual void pushObjectReference(const v8::Handle<v8::Value>& object) OVERRIDE
2668     {
2669         m_objectPool.append(object);
2670     }
2671 
tryGetTransferredMessagePort(uint32_t index,v8::Handle<v8::Value> * object)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 
tryGetTransferredArrayBuffer(uint32_t index,v8::Handle<v8::Value> * object)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 
tryGetObjectFromObjectReference(uint32_t reference,v8::Handle<v8::Value> * object)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 
objectReferenceCount()2711     virtual uint32_t objectReferenceCount() OVERRIDE
2712     {
2713         return m_objectPool.size();
2714     }
2715 
2716 private:
initializeObject(v8::Handle<v8::Object> object,uint32_t numProperties,v8::Handle<v8::Value> * value)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 
doDeserialize()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 
push(v8::Local<v8::Value> value)2742     void push(v8::Local<v8::Value> value) { m_stack.append(value); }
2743 
pop(unsigned length)2744     void pop(unsigned length)
2745     {
2746         ASSERT(length <= m_stack.size());
2747         m_stack.shrink(m_stack.size() - length);
2748     }
2749 
stackDepth() const2750     unsigned stackDepth() const { return m_stack.size(); }
2751 
element(unsigned index)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 
openComposite(const v8::Local<v8::Value> & object)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 
closeComposite(v8::Handle<v8::Value> * object)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 
create(v8::Handle<v8::Value> value,MessagePortArray * messagePorts,ArrayBufferArray * arrayBuffers,ExceptionState & exceptionState,v8::Isolate * isolate)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 
createAndSwallowExceptions(v8::Handle<v8::Value> value,v8::Isolate * isolate)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 
create(const ScriptValue & value,WebBlobInfoArray * blobInfo,ExceptionState & exceptionState,v8::Isolate * isolate)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 
createFromWire(const String & data)2806 PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
2807 {
2808     return adoptRef(new SerializedScriptValue(data));
2809 }
2810 
createFromWireBytes(const Vector<uint8_t> & data)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 
create(const String & data)2825 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data)
2826 {
2827     return create(data, v8::Isolate::GetCurrent());
2828 }
2829 
create(const String & data,v8::Isolate * isolate)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 
create()2838 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
2839 {
2840     return adoptRef(new SerializedScriptValue());
2841 }
2842 
nullValue()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.
toWireBytes(Vector<char> & result) const2852 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 
SerializedScriptValue()2870 SerializedScriptValue::SerializedScriptValue()
2871     : m_externallyAllocatedMemory(0)
2872 {
2873 }
2874 
neuterArrayBufferInAllWorlds(ArrayBuffer * object)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 
transferArrayBuffers(ArrayBufferArray & arrayBuffers,ExceptionState & exceptionState,v8::Isolate * isolate)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 
SerializedScriptValue(v8::Handle<v8::Value> value,MessagePortArray * messagePorts,ArrayBufferArray * arrayBuffers,WebBlobInfoArray * blobInfo,ExceptionState & exceptionState,v8::Isolate * isolate)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 
SerializedScriptValue(const String & wireData)2962 SerializedScriptValue::SerializedScriptValue(const String& wireData)
2963     : m_externallyAllocatedMemory(0)
2964 {
2965     m_data = wireData.isolatedCopy();
2966 }
2967 
deserialize(MessagePortArray * messagePorts)2968 v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
2969 {
2970     return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0);
2971 }
2972 
deserialize(v8::Isolate * isolate,MessagePortArray * messagePorts,const WebBlobInfoArray * blobInfo)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 
extractTransferables(v8::Local<v8::Value> value,int argumentIndex,MessagePortArray & ports,ArrayBufferArray & arrayBuffers,ExceptionState & exceptionState,v8::Isolate * isolate)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 
registerMemoryAllocatedWithCurrentScriptContext()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 
~SerializedScriptValue()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