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

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