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