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