Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: Source/bindings/core/v8/SerializedScriptValue.cpp

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

Powered by Google App Engine
This is Rietveld 408576698