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