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