OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "bindings/core/v8/ScriptValueSerializer.h" |
| 7 |
| 8 #include "bindings/core/v8/V8ArrayBuffer.h" |
| 9 #include "bindings/core/v8/V8ArrayBufferView.h" |
| 10 #include "bindings/core/v8/V8Blob.h" |
| 11 #include "bindings/core/v8/V8File.h" |
| 12 #include "bindings/core/v8/V8FileList.h" |
| 13 #include "bindings/core/v8/V8ImageData.h" |
| 14 #include "bindings/core/v8/V8MessagePort.h" |
| 15 #include "bindings/modules/v8/V8CryptoKey.h" |
| 16 #include "bindings/modules/v8/V8DOMFileSystem.h" |
| 17 #include "core/dom/DOMDataView.h" |
| 18 #include "core/fileapi/Blob.h" |
| 19 #include "core/fileapi/File.h" |
| 20 #include "core/fileapi/FileList.h" |
| 21 #include "public/platform/Platform.h" |
| 22 #include "public/platform/WebBlobInfo.h" |
| 23 #include "wtf/ArrayBuffer.h" |
| 24 #include "wtf/ArrayBufferContents.h" |
| 25 #include "wtf/ArrayBufferView.h" |
| 26 #include "wtf/text/StringHash.h" |
| 27 #include "wtf/text/StringUTF8Adaptor.h" |
| 28 |
| 29 namespace blink { |
| 30 |
| 31 namespace SerializedScriptValueInternal { |
| 32 |
| 33 // This code implements the HTML5 Structured Clone algorithm: |
| 34 // http://www.whatwg.org/specs/web-apps/current-work/multipage/urls.html#safe-pa
ssing-of-structured-data |
| 35 |
| 36 // ZigZag encoding helps VarInt encoding stay small for negative |
| 37 // numbers with small absolute values. |
| 38 class ZigZag { |
| 39 public: |
| 40 static uint32_t encode(uint32_t value) |
| 41 { |
| 42 if (value & (1U << 31)) |
| 43 value = ((~value) << 1) + 1; |
| 44 else |
| 45 value <<= 1; |
| 46 return value; |
| 47 } |
| 48 |
| 49 static uint32_t decode(uint32_t value) |
| 50 { |
| 51 if (value & 1) |
| 52 value = ~(value >> 1); |
| 53 else |
| 54 value >>= 1; |
| 55 return value; |
| 56 } |
| 57 |
| 58 private: |
| 59 ZigZag(); |
| 60 }; |
| 61 |
| 62 static const int maxDepth = 20000; |
| 63 |
| 64 static bool shouldCheckForCycles(int depth) |
| 65 { |
| 66 ASSERT(depth >= 0); |
| 67 // Since we are not required to spot the cycle as soon as it |
| 68 // happens we can check for cycles only when the current depth |
| 69 // is a power of two. |
| 70 return !(depth & (depth - 1)); |
| 71 } |
| 72 |
| 73 void Writer::writeUndefined() |
| 74 { |
| 75 append(UndefinedTag); |
| 76 } |
| 77 |
| 78 void Writer::writeNull() |
| 79 { |
| 80 append(NullTag); |
| 81 } |
| 82 |
| 83 void Writer::writeTrue() |
| 84 { |
| 85 append(TrueTag); |
| 86 } |
| 87 |
| 88 void Writer::writeFalse() |
| 89 { |
| 90 append(FalseTag); |
| 91 } |
| 92 |
| 93 void Writer::writeBooleanObject(bool value) |
| 94 { |
| 95 append(value ? TrueObjectTag : FalseObjectTag); |
| 96 } |
| 97 |
| 98 void Writer::writeOneByteString(v8::Handle<v8::String>& string) |
| 99 { |
| 100 int stringLength = string->Length(); |
| 101 int utf8Length = string->Utf8Length(); |
| 102 ASSERT(stringLength >= 0 && utf8Length >= 0); |
| 103 |
| 104 append(StringTag); |
| 105 doWriteUint32(static_cast<uint32_t>(utf8Length)); |
| 106 ensureSpace(utf8Length); |
| 107 |
| 108 // ASCII fast path. |
| 109 if (stringLength == utf8Length) { |
| 110 string->WriteOneByte(byteAt(m_position), 0, utf8Length, v8StringWriteOpt
ions()); |
| 111 } else { |
| 112 char* buffer = reinterpret_cast<char*>(byteAt(m_position)); |
| 113 string->WriteUtf8(buffer, utf8Length, 0, v8StringWriteOptions()); |
| 114 } |
| 115 m_position += utf8Length; |
| 116 } |
| 117 |
| 118 void Writer::writeUCharString(v8::Handle<v8::String>& string) |
| 119 { |
| 120 int length = string->Length(); |
| 121 ASSERT(length >= 0); |
| 122 |
| 123 int size = length * sizeof(UChar); |
| 124 int bytes = bytesNeededToWireEncode(static_cast<uint32_t>(size)); |
| 125 if ((m_position + 1 + bytes) & 1) |
| 126 append(PaddingTag); |
| 127 |
| 128 append(StringUCharTag); |
| 129 doWriteUint32(static_cast<uint32_t>(size)); |
| 130 ensureSpace(size); |
| 131 |
| 132 ASSERT(!(m_position & 1)); |
| 133 uint16_t* buffer = reinterpret_cast<uint16_t*>(byteAt(m_position)); |
| 134 string->Write(buffer, 0, length, v8StringWriteOptions()); |
| 135 m_position += size; |
| 136 } |
| 137 |
| 138 void Writer::writeStringObject(const char* data, int length) |
| 139 { |
| 140 ASSERT(length >= 0); |
| 141 append(StringObjectTag); |
| 142 doWriteString(data, length); |
| 143 } |
| 144 |
| 145 void Writer::writeWebCoreString(const String& string) |
| 146 { |
| 147 // Uses UTF8 encoding so we can read it back as either V8 or |
| 148 // WebCore string. |
| 149 append(StringTag); |
| 150 doWriteWebCoreString(string); |
| 151 } |
| 152 |
| 153 void Writer::writeVersion() |
| 154 { |
| 155 append(VersionTag); |
| 156 doWriteUint32(SerializedScriptValue::wireFormatVersion); |
| 157 } |
| 158 |
| 159 void Writer::writeInt32(int32_t value) |
| 160 { |
| 161 append(Int32Tag); |
| 162 doWriteUint32(ZigZag::encode(static_cast<uint32_t>(value))); |
| 163 } |
| 164 |
| 165 void Writer::writeUint32(uint32_t value) |
| 166 { |
| 167 append(Uint32Tag); |
| 168 doWriteUint32(value); |
| 169 } |
| 170 |
| 171 void Writer::writeDate(double numberValue) |
| 172 { |
| 173 append(DateTag); |
| 174 doWriteNumber(numberValue); |
| 175 } |
| 176 |
| 177 void Writer::writeNumber(double number) |
| 178 { |
| 179 append(NumberTag); |
| 180 doWriteNumber(number); |
| 181 } |
| 182 |
| 183 void Writer::writeNumberObject(double number) |
| 184 { |
| 185 append(NumberObjectTag); |
| 186 doWriteNumber(number); |
| 187 } |
| 188 |
| 189 void Writer::writeBlob(const String& uuid, const String& type, unsigned long lon
g size) |
| 190 { |
| 191 append(BlobTag); |
| 192 doWriteWebCoreString(uuid); |
| 193 doWriteWebCoreString(type); |
| 194 doWriteUint64(size); |
| 195 } |
| 196 |
| 197 void Writer::writeDOMFileSystem(int type, const String& name, const String& url) |
| 198 { |
| 199 append(DOMFileSystemTag); |
| 200 doWriteUint32(type); |
| 201 doWriteWebCoreString(name); |
| 202 doWriteWebCoreString(url); |
| 203 } |
| 204 |
| 205 void Writer::writeBlobIndex(int blobIndex) |
| 206 { |
| 207 ASSERT(blobIndex >= 0); |
| 208 append(BlobIndexTag); |
| 209 doWriteUint32(blobIndex); |
| 210 } |
| 211 |
| 212 void Writer::writeFile(const File& file) |
| 213 { |
| 214 append(FileTag); |
| 215 doWriteFile(file); |
| 216 } |
| 217 |
| 218 void Writer::writeFileIndex(int blobIndex) |
| 219 { |
| 220 append(FileIndexTag); |
| 221 doWriteUint32(blobIndex); |
| 222 } |
| 223 |
| 224 void Writer::writeFileList(const FileList& fileList) |
| 225 { |
| 226 append(FileListTag); |
| 227 uint32_t length = fileList.length(); |
| 228 doWriteUint32(length); |
| 229 for (unsigned i = 0; i < length; ++i) |
| 230 doWriteFile(*fileList.item(i)); |
| 231 } |
| 232 |
| 233 void Writer::writeFileListIndex(const Vector<int>& blobIndices) |
| 234 { |
| 235 append(FileListIndexTag); |
| 236 uint32_t length = blobIndices.size(); |
| 237 doWriteUint32(length); |
| 238 for (unsigned i = 0; i < length; ++i) |
| 239 doWriteUint32(blobIndices[i]); |
| 240 } |
| 241 |
| 242 bool Writer::writeCryptoKey(const WebCryptoKey& key) |
| 243 { |
| 244 append(static_cast<uint8_t>(CryptoKeyTag)); |
| 245 |
| 246 switch (key.algorithm().paramsType()) { |
| 247 case WebCryptoKeyAlgorithmParamsTypeAes: |
| 248 doWriteAesKey(key); |
| 249 break; |
| 250 case WebCryptoKeyAlgorithmParamsTypeHmac: |
| 251 doWriteHmacKey(key); |
| 252 break; |
| 253 case WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
| 254 doWriteRsaHashedKey(key); |
| 255 break; |
| 256 case WebCryptoKeyAlgorithmParamsTypeNone: |
| 257 ASSERT_NOT_REACHED(); |
| 258 return false; |
| 259 } |
| 260 |
| 261 doWriteKeyUsages(key.usages(), key.extractable()); |
| 262 |
| 263 WebVector<uint8_t> keyData; |
| 264 if (!Platform::current()->crypto()->serializeKeyForClone(key, keyData)) |
| 265 return false; |
| 266 |
| 267 doWriteUint32(keyData.size()); |
| 268 append(keyData.data(), keyData.size()); |
| 269 return true; |
| 270 } |
| 271 |
| 272 void Writer::writeArrayBuffer(const ArrayBuffer& arrayBuffer) |
| 273 { |
| 274 append(ArrayBufferTag); |
| 275 doWriteArrayBuffer(arrayBuffer); |
| 276 } |
| 277 |
| 278 void Writer::writeArrayBufferView(const ArrayBufferView& arrayBufferView) |
| 279 { |
| 280 append(ArrayBufferViewTag); |
| 281 #if ENABLE(ASSERT) |
| 282 const ArrayBuffer& arrayBuffer = *arrayBufferView.buffer(); |
| 283 ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byt
eOffset() == |
| 284 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); |
| 285 #endif |
| 286 ArrayBufferView::ViewType type = arrayBufferView.type(); |
| 287 |
| 288 if (type == ArrayBufferView::TypeInt8) |
| 289 append(ByteArrayTag); |
| 290 else if (type == ArrayBufferView::TypeUint8Clamped) |
| 291 append(UnsignedByteClampedArrayTag); |
| 292 else if (type == ArrayBufferView::TypeUint8) |
| 293 append(UnsignedByteArrayTag); |
| 294 else if (type == ArrayBufferView::TypeInt16) |
| 295 append(ShortArrayTag); |
| 296 else if (type == ArrayBufferView::TypeUint16) |
| 297 append(UnsignedShortArrayTag); |
| 298 else if (type == ArrayBufferView::TypeInt32) |
| 299 append(IntArrayTag); |
| 300 else if (type == ArrayBufferView::TypeUint32) |
| 301 append(UnsignedIntArrayTag); |
| 302 else if (type == ArrayBufferView::TypeFloat32) |
| 303 append(FloatArrayTag); |
| 304 else if (type == ArrayBufferView::TypeFloat64) |
| 305 append(DoubleArrayTag); |
| 306 else if (type == ArrayBufferView::TypeDataView) |
| 307 append(DataViewTag); |
| 308 else |
| 309 ASSERT_NOT_REACHED(); |
| 310 doWriteUint32(arrayBufferView.byteOffset()); |
| 311 doWriteUint32(arrayBufferView.byteLength()); |
| 312 } |
| 313 |
| 314 void Writer::writeImageData(uint32_t width, uint32_t height, const uint8_t* pixe
lData, uint32_t pixelDataLength) |
| 315 { |
| 316 append(ImageDataTag); |
| 317 doWriteUint32(width); |
| 318 doWriteUint32(height); |
| 319 doWriteUint32(pixelDataLength); |
| 320 append(pixelData, pixelDataLength); |
| 321 } |
| 322 |
| 323 void Writer::writeRegExp(v8::Local<v8::String> pattern, v8::RegExp::Flags flags) |
| 324 { |
| 325 append(RegExpTag); |
| 326 v8::String::Utf8Value patternUtf8Value(pattern); |
| 327 doWriteString(*patternUtf8Value, patternUtf8Value.length()); |
| 328 doWriteUint32(static_cast<uint32_t>(flags)); |
| 329 } |
| 330 |
| 331 void Writer::writeTransferredMessagePort(uint32_t index) |
| 332 { |
| 333 append(MessagePortTag); |
| 334 doWriteUint32(index); |
| 335 } |
| 336 |
| 337 void Writer::writeTransferredArrayBuffer(uint32_t index) |
| 338 { |
| 339 append(ArrayBufferTransferTag); |
| 340 doWriteUint32(index); |
| 341 } |
| 342 |
| 343 void Writer::writeObjectReference(uint32_t reference) |
| 344 { |
| 345 append(ObjectReferenceTag); |
| 346 doWriteUint32(reference); |
| 347 } |
| 348 |
| 349 void Writer::writeObject(uint32_t numProperties) |
| 350 { |
| 351 append(ObjectTag); |
| 352 doWriteUint32(numProperties); |
| 353 } |
| 354 |
| 355 void Writer::writeSparseArray(uint32_t numProperties, uint32_t length) |
| 356 { |
| 357 append(SparseArrayTag); |
| 358 doWriteUint32(numProperties); |
| 359 doWriteUint32(length); |
| 360 } |
| 361 |
| 362 void Writer::writeDenseArray(uint32_t numProperties, uint32_t length) |
| 363 { |
| 364 append(DenseArrayTag); |
| 365 doWriteUint32(numProperties); |
| 366 doWriteUint32(length); |
| 367 } |
| 368 |
| 369 String Writer::takeWireString() |
| 370 { |
| 371 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); |
| 372 fillHole(); |
| 373 String data = String(m_buffer.data(), m_buffer.size()); |
| 374 data.impl()->truncateAssumingIsolated((m_position + 1) / sizeof(BufferValueT
ype)); |
| 375 return data; |
| 376 } |
| 377 |
| 378 void Writer::writeReferenceCount(uint32_t numberOfReferences) |
| 379 { |
| 380 append(ReferenceCountTag); |
| 381 doWriteUint32(numberOfReferences); |
| 382 } |
| 383 |
| 384 void Writer::writeGenerateFreshObject() |
| 385 { |
| 386 append(GenerateFreshObjectTag); |
| 387 } |
| 388 |
| 389 void Writer::writeGenerateFreshSparseArray(uint32_t length) |
| 390 { |
| 391 append(GenerateFreshSparseArrayTag); |
| 392 doWriteUint32(length); |
| 393 } |
| 394 |
| 395 void Writer::writeGenerateFreshDenseArray(uint32_t length) |
| 396 { |
| 397 append(GenerateFreshDenseArrayTag); |
| 398 doWriteUint32(length); |
| 399 } |
| 400 |
| 401 void Writer::doWriteFile(const File& file) |
| 402 { |
| 403 doWriteWebCoreString(file.hasBackingFile() ? file.path() : ""); |
| 404 doWriteWebCoreString(file.name()); |
| 405 doWriteWebCoreString(file.webkitRelativePath()); |
| 406 doWriteWebCoreString(file.uuid()); |
| 407 doWriteWebCoreString(file.type()); |
| 408 |
| 409 // FIXME don't use 1 byte to encode a flag. |
| 410 if (file.hasValidSnapshotMetadata()) { |
| 411 doWriteUint32(static_cast<uint8_t>(1)); |
| 412 |
| 413 long long size; |
| 414 double lastModified; |
| 415 file.captureSnapshot(size, lastModified); |
| 416 doWriteUint64(static_cast<uint64_t>(size)); |
| 417 doWriteNumber(lastModified); |
| 418 } else { |
| 419 doWriteUint32(static_cast<uint8_t>(0)); |
| 420 } |
| 421 |
| 422 doWriteUint32(static_cast<uint8_t>((file.userVisibility() == File::IsUserVis
ible) ? 1 : 0)); |
| 423 } |
| 424 |
| 425 void Writer::doWriteArrayBuffer(const ArrayBuffer& arrayBuffer) |
| 426 { |
| 427 uint32_t byteLength = arrayBuffer.byteLength(); |
| 428 doWriteUint32(byteLength); |
| 429 append(static_cast<const uint8_t*>(arrayBuffer.data()), byteLength); |
| 430 } |
| 431 |
| 432 void Writer::doWriteString(const char* data, int length) |
| 433 { |
| 434 doWriteUint32(static_cast<uint32_t>(length)); |
| 435 append(reinterpret_cast<const uint8_t*>(data), length); |
| 436 } |
| 437 |
| 438 void Writer::doWriteWebCoreString(const String& string) |
| 439 { |
| 440 StringUTF8Adaptor stringUTF8(string); |
| 441 doWriteString(stringUTF8.data(), stringUTF8.length()); |
| 442 } |
| 443 |
| 444 void Writer::doWriteHmacKey(const WebCryptoKey& key) |
| 445 { |
| 446 ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeHmac); |
| 447 |
| 448 append(static_cast<uint8_t>(HmacKeyTag)); |
| 449 ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8)); |
| 450 doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8); |
| 451 doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id()); |
| 452 } |
| 453 |
| 454 void Writer::doWriteAesKey(const WebCryptoKey& key) |
| 455 { |
| 456 ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeAes); |
| 457 |
| 458 append(static_cast<uint8_t>(AesKeyTag)); |
| 459 doWriteAlgorithmId(key.algorithm().id()); |
| 460 // Converting the key length from bits to bytes is lossless and makes |
| 461 // it fit in 1 byte. |
| 462 ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8)); |
| 463 doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8); |
| 464 } |
| 465 |
| 466 void Writer::doWriteRsaHashedKey(const WebCryptoKey& key) |
| 467 { |
| 468 ASSERT(key.algorithm().rsaHashedParams()); |
| 469 append(static_cast<uint8_t>(RsaHashedKeyTag)); |
| 470 |
| 471 doWriteAlgorithmId(key.algorithm().id()); |
| 472 |
| 473 switch (key.type()) { |
| 474 case WebCryptoKeyTypePublic: |
| 475 doWriteUint32(PublicKeyType); |
| 476 break; |
| 477 case WebCryptoKeyTypePrivate: |
| 478 doWriteUint32(PrivateKeyType); |
| 479 break; |
| 480 case WebCryptoKeyTypeSecret: |
| 481 ASSERT_NOT_REACHED(); |
| 482 } |
| 483 |
| 484 const WebCryptoRsaHashedKeyAlgorithmParams* params = key.algorithm().rsaHash
edParams(); |
| 485 doWriteUint32(params->modulusLengthBits()); |
| 486 doWriteUint32(params->publicExponent().size()); |
| 487 append(params->publicExponent().data(), params->publicExponent().size()); |
| 488 doWriteAlgorithmId(key.algorithm().rsaHashedParams()->hash().id()); |
| 489 } |
| 490 |
| 491 void Writer::doWriteAlgorithmId(WebCryptoAlgorithmId id) |
| 492 { |
| 493 switch (id) { |
| 494 case WebCryptoAlgorithmIdAesCbc: |
| 495 return doWriteUint32(AesCbcTag); |
| 496 case WebCryptoAlgorithmIdHmac: |
| 497 return doWriteUint32(HmacTag); |
| 498 case WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
| 499 return doWriteUint32(RsaSsaPkcs1v1_5Tag); |
| 500 case WebCryptoAlgorithmIdSha1: |
| 501 return doWriteUint32(Sha1Tag); |
| 502 case WebCryptoAlgorithmIdSha256: |
| 503 return doWriteUint32(Sha256Tag); |
| 504 case WebCryptoAlgorithmIdSha384: |
| 505 return doWriteUint32(Sha384Tag); |
| 506 case WebCryptoAlgorithmIdSha512: |
| 507 return doWriteUint32(Sha512Tag); |
| 508 case WebCryptoAlgorithmIdAesGcm: |
| 509 return doWriteUint32(AesGcmTag); |
| 510 case WebCryptoAlgorithmIdRsaOaep: |
| 511 return doWriteUint32(RsaOaepTag); |
| 512 case WebCryptoAlgorithmIdAesCtr: |
| 513 return doWriteUint32(AesCtrTag); |
| 514 case WebCryptoAlgorithmIdAesKw: |
| 515 return doWriteUint32(AesKwTag); |
| 516 case WebCryptoAlgorithmIdRsaPss: |
| 517 return doWriteUint32(RsaPssTag); |
| 518 } |
| 519 ASSERT_NOT_REACHED(); |
| 520 } |
| 521 |
| 522 void Writer::doWriteKeyUsages(const WebCryptoKeyUsageMask usages, bool extractab
le) |
| 523 { |
| 524 // Reminder to update this when adding new key usages. |
| 525 COMPILE_ASSERT(EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); |
| 526 |
| 527 uint32_t value = 0; |
| 528 |
| 529 if (extractable) |
| 530 value |= ExtractableUsage; |
| 531 |
| 532 if (usages & WebCryptoKeyUsageEncrypt) |
| 533 value |= EncryptUsage; |
| 534 if (usages & WebCryptoKeyUsageDecrypt) |
| 535 value |= DecryptUsage; |
| 536 if (usages & WebCryptoKeyUsageSign) |
| 537 value |= SignUsage; |
| 538 if (usages & WebCryptoKeyUsageVerify) |
| 539 value |= VerifyUsage; |
| 540 if (usages & WebCryptoKeyUsageDeriveKey) |
| 541 value |= DeriveKeyUsage; |
| 542 if (usages & WebCryptoKeyUsageWrapKey) |
| 543 value |= WrapKeyUsage; |
| 544 if (usages & WebCryptoKeyUsageUnwrapKey) |
| 545 value |= UnwrapKeyUsage; |
| 546 if (usages & WebCryptoKeyUsageDeriveBits) |
| 547 value |= DeriveBitsUsage; |
| 548 |
| 549 doWriteUint32(value); |
| 550 } |
| 551 |
| 552 int Writer::bytesNeededToWireEncode(uint32_t value) |
| 553 { |
| 554 int bytes = 1; |
| 555 while (true) { |
| 556 value >>= SerializedScriptValue::varIntShift; |
| 557 if (!value) |
| 558 break; |
| 559 ++bytes; |
| 560 } |
| 561 |
| 562 return bytes; |
| 563 } |
| 564 |
| 565 void Writer::doWriteUint32(uint32_t value) |
| 566 { |
| 567 doWriteUintHelper(value); |
| 568 } |
| 569 |
| 570 void Writer::doWriteUint64(uint64_t value) |
| 571 { |
| 572 doWriteUintHelper(value); |
| 573 } |
| 574 |
| 575 void Writer::doWriteNumber(double number) |
| 576 { |
| 577 append(reinterpret_cast<uint8_t*>(&number), sizeof(number)); |
| 578 } |
| 579 |
| 580 void Writer::append(SerializationTag tag) |
| 581 { |
| 582 append(static_cast<uint8_t>(tag)); |
| 583 } |
| 584 |
| 585 void Writer::append(uint8_t b) |
| 586 { |
| 587 ensureSpace(1); |
| 588 *byteAt(m_position++) = b; |
| 589 } |
| 590 |
| 591 void Writer::append(const uint8_t* data, int length) |
| 592 { |
| 593 ensureSpace(length); |
| 594 memcpy(byteAt(m_position), data, length); |
| 595 m_position += length; |
| 596 } |
| 597 |
| 598 void Writer::ensureSpace(unsigned extra) |
| 599 { |
| 600 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); |
| 601 m_buffer.resize((m_position + extra + 1) / sizeof(BufferValueType)); // "+ 1
" to round up. |
| 602 } |
| 603 |
| 604 void Writer::fillHole() |
| 605 { |
| 606 COMPILE_ASSERT(sizeof(BufferValueType) == 2, BufferValueTypeIsTwoBytes); |
| 607 // If the writer is at odd position in the buffer, then one of |
| 608 // the bytes in the last UChar is not initialized. |
| 609 if (m_position % 2) |
| 610 *byteAt(m_position) = static_cast<uint8_t>(PaddingTag); |
| 611 } |
| 612 |
| 613 uint8_t* Writer::byteAt(int position) |
| 614 { |
| 615 return reinterpret_cast<uint8_t*>(m_buffer.data()) + position; |
| 616 } |
| 617 |
| 618 int Writer::v8StringWriteOptions() |
| 619 { |
| 620 return v8::String::NO_NULL_TERMINATION; |
| 621 } |
| 622 |
| 623 Serializer::StateBase* Serializer::AbstractObjectState::serializeProperties(bool
ignoreIndexed, Serializer& serializer) |
| 624 { |
| 625 while (m_index < m_propertyNames->Length()) { |
| 626 if (!m_nameDone) { |
| 627 v8::Local<v8::Value> propertyName = m_propertyNames->Get(m_index); |
| 628 if (StateBase* newState = serializer.checkException(this)) |
| 629 return newState; |
| 630 if (propertyName.IsEmpty()) |
| 631 return serializer.handleError(InputError, "Empty property names
cannot be cloned.", this); |
| 632 bool hasStringProperty = propertyName->IsString() && composite()->Ha
sRealNamedProperty(propertyName.As<v8::String>()); |
| 633 if (StateBase* newState = serializer.checkException(this)) |
| 634 return newState; |
| 635 bool hasIndexedProperty = !hasStringProperty && propertyName->IsUint
32() && composite()->HasRealIndexedProperty(propertyName->Uint32Value()); |
| 636 if (StateBase* newState = serializer.checkException(this)) |
| 637 return newState; |
| 638 if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed)) { |
| 639 m_propertyName = propertyName; |
| 640 } else { |
| 641 ++m_index; |
| 642 continue; |
| 643 } |
| 644 } |
| 645 ASSERT(!m_propertyName.IsEmpty()); |
| 646 if (!m_nameDone) { |
| 647 m_nameDone = true; |
| 648 if (StateBase* newState = serializer.doSerialize(m_propertyName, thi
s)) |
| 649 return newState; |
| 650 } |
| 651 v8::Local<v8::Value> value = composite()->Get(m_propertyName); |
| 652 if (StateBase* newState = serializer.checkException(this)) |
| 653 return newState; |
| 654 m_nameDone = false; |
| 655 m_propertyName.Clear(); |
| 656 ++m_index; |
| 657 ++m_numSerializedProperties; |
| 658 // If we return early here, it's either because we have pushed a new sta
te onto the |
| 659 // serialization state stack or because we have encountered an error (an
d in both cases |
| 660 // we are unwinding the native stack). |
| 661 if (StateBase* newState = serializer.doSerialize(value, this)) |
| 662 return newState; |
| 663 } |
| 664 return objectDone(m_numSerializedProperties, serializer); |
| 665 } |
| 666 |
| 667 Serializer::StateBase* Serializer::ObjectState::advance(Serializer& serializer) |
| 668 { |
| 669 if (m_propertyNames.IsEmpty()) { |
| 670 m_propertyNames = composite()->GetPropertyNames(); |
| 671 if (StateBase* newState = serializer.checkException(this)) |
| 672 return newState; |
| 673 if (m_propertyNames.IsEmpty()) |
| 674 return serializer.handleError(InputError, "Empty property names cann
ot be cloned.", nextState()); |
| 675 } |
| 676 return serializeProperties(false, serializer); |
| 677 } |
| 678 |
| 679 Serializer::StateBase* Serializer::ObjectState::objectDone(unsigned numPropertie
s, Serializer& serializer) |
| 680 { |
| 681 return serializer.writeObject(numProperties, this); |
| 682 } |
| 683 |
| 684 Serializer::StateBase* Serializer::DenseArrayState::advance(Serializer& serializ
er) |
| 685 { |
| 686 while (m_arrayIndex < m_arrayLength) { |
| 687 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIn
dex); |
| 688 m_arrayIndex++; |
| 689 if (StateBase* newState = serializer.checkException(this)) |
| 690 return newState; |
| 691 if (StateBase* newState = serializer.doSerialize(value, this)) |
| 692 return newState; |
| 693 } |
| 694 return serializeProperties(true, serializer); |
| 695 } |
| 696 |
| 697 Serializer::StateBase* Serializer::DenseArrayState::objectDone(unsigned numPrope
rties, Serializer& serializer) |
| 698 { |
| 699 return serializer.writeDenseArray(numProperties, m_arrayLength, this); |
| 700 } |
| 701 |
| 702 Serializer::StateBase* Serializer::SparseArrayState::advance(Serializer& seriali
zer) |
| 703 { |
| 704 return serializeProperties(false, serializer); |
| 705 } |
| 706 |
| 707 Serializer::StateBase* Serializer::SparseArrayState::objectDone(unsigned numProp
erties, Serializer& serializer) |
| 708 { |
| 709 return serializer.writeSparseArray(numProperties, composite().As<v8::Array>(
)->Length(), this); |
| 710 } |
| 711 |
| 712 static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Handle<v8::Objec
t> creationContext, v8::Isolate* isolate) |
| 713 { |
| 714 if (!impl) |
| 715 return v8::Handle<v8::Object>(); |
| 716 v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); |
| 717 ASSERT(wrapper->IsObject()); |
| 718 return wrapper.As<v8::Object>(); |
| 719 } |
| 720 |
| 721 static v8::Handle<v8::ArrayBuffer> toV8Object(DOMArrayBuffer* impl, v8::Handle<v
8::Object> creationContext, v8::Isolate* isolate) |
| 722 { |
| 723 if (!impl) |
| 724 return v8::Handle<v8::ArrayBuffer>(); |
| 725 v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); |
| 726 ASSERT(wrapper->IsArrayBuffer()); |
| 727 return wrapper.As<v8::ArrayBuffer>(); |
| 728 } |
| 729 |
| 730 // Returns true if the provided object is to be considered a 'host object', as u
sed in the |
| 731 // HTML5 structured clone algorithm. |
| 732 static bool isHostObject(v8::Handle<v8::Object> object) |
| 733 { |
| 734 // If the object has any internal fields, then we won't be able to serialize
or deserialize |
| 735 // them; conveniently, this is also a quick way to detect DOM wrapper object
s, because |
| 736 // the mechanism for these relies on data stored in these fields. We should |
| 737 // catch external array data as a special case. |
| 738 return object->InternalFieldCount() || object->HasIndexedPropertiesInExterna
lArrayData(); |
| 739 } |
| 740 |
| 741 Serializer::Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBuff
erArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHa
ndles, v8::TryCatch& tryCatch, ScriptState* scriptState) |
| 742 : m_scriptState(scriptState) |
| 743 , m_writer(writer) |
| 744 , m_tryCatch(tryCatch) |
| 745 , m_depth(0) |
| 746 , m_status(Success) |
| 747 , m_nextObjectReference(0) |
| 748 , m_blobInfo(blobInfo) |
| 749 , m_blobDataHandles(blobDataHandles) |
| 750 { |
| 751 ASSERT(!tryCatch.HasCaught()); |
| 752 v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global(); |
| 753 if (messagePorts) { |
| 754 for (size_t i = 0; i < messagePorts->size(); i++) |
| 755 m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(),
creationContext, isolate()), i); |
| 756 } |
| 757 if (arrayBuffers) { |
| 758 for (size_t i = 0; i < arrayBuffers->size(); i++) { |
| 759 v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i
).get(), creationContext, isolate()); |
| 760 // Coalesce multiple occurences of the same buffer to the first inde
x. |
| 761 if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) |
| 762 m_transferredArrayBuffers.set(v8ArrayBuffer, i); |
| 763 } |
| 764 } |
| 765 } |
| 766 |
| 767 Serializer::Status Serializer::serialize(v8::Handle<v8::Value> value) |
| 768 { |
| 769 v8::HandleScope scope(isolate()); |
| 770 m_writer.writeVersion(); |
| 771 StateBase* state = doSerialize(value, 0); |
| 772 while (state) |
| 773 state = state->advance(*this); |
| 774 return m_status; |
| 775 } |
| 776 |
| 777 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Seri
alizer::StateBase* next) |
| 778 { |
| 779 m_writer.writeReferenceCount(m_nextObjectReference); |
| 780 uint32_t objectReference; |
| 781 uint32_t arrayBufferIndex; |
| 782 if ((value->IsObject() || value->IsDate() || value->IsRegExp()) |
| 783 && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { |
| 784 // Note that IsObject() also detects wrappers (eg, it will catch the thi
ngs |
| 785 // that we grey and write below). |
| 786 ASSERT(!value->IsString()); |
| 787 m_writer.writeObjectReference(objectReference); |
| 788 } else if (value.IsEmpty()) { |
| 789 return handleError(InputError, "The empty property name cannot be cloned
.", next); |
| 790 } else if (value->IsUndefined()) { |
| 791 m_writer.writeUndefined(); |
| 792 } else if (value->IsNull()) { |
| 793 m_writer.writeNull(); |
| 794 } else if (value->IsTrue()) { |
| 795 m_writer.writeTrue(); |
| 796 } else if (value->IsFalse()) { |
| 797 m_writer.writeFalse(); |
| 798 } else if (value->IsInt32()) { |
| 799 m_writer.writeInt32(value->Int32Value()); |
| 800 } else if (value->IsUint32()) { |
| 801 m_writer.writeUint32(value->Uint32Value()); |
| 802 } else if (value->IsNumber()) { |
| 803 m_writer.writeNumber(value.As<v8::Number>()->Value()); |
| 804 } else if (V8ArrayBufferView::hasInstance(value, isolate())) { |
| 805 return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); |
| 806 } else if (value->IsString()) { |
| 807 writeString(value); |
| 808 } else if (V8MessagePort::hasInstance(value, isolate())) { |
| 809 uint32_t messagePortIndex; |
| 810 if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePor
tIndex)) { |
| 811 m_writer.writeTransferredMessagePort(messagePortIndex); |
| 812 } else { |
| 813 return handleError(DataCloneError, "A MessagePort could not be clone
d.", next); |
| 814 } |
| 815 } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArra
yBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) { |
| 816 return writeTransferredArrayBuffer(value, arrayBufferIndex, next); |
| 817 } else { |
| 818 v8::Handle<v8::Object> jsObject = value.As<v8::Object>(); |
| 819 if (jsObject.IsEmpty()) |
| 820 return handleError(DataCloneError, "An object could not be cloned.",
next); |
| 821 greyObject(jsObject); |
| 822 if (value->IsDate()) { |
| 823 m_writer.writeDate(value->NumberValue()); |
| 824 } else if (value->IsStringObject()) { |
| 825 writeStringObject(value); |
| 826 } else if (value->IsNumberObject()) { |
| 827 writeNumberObject(value); |
| 828 } else if (value->IsBooleanObject()) { |
| 829 writeBooleanObject(value); |
| 830 } else if (value->IsArray()) { |
| 831 return startArrayState(value.As<v8::Array>(), next); |
| 832 } else if (V8File::hasInstance(value, isolate())) { |
| 833 return writeFile(value, next); |
| 834 } else if (V8Blob::hasInstance(value, isolate())) { |
| 835 return writeBlob(value, next); |
| 836 } else if (V8DOMFileSystem::hasInstance(value, isolate())) { |
| 837 return writeDOMFileSystem(value, next); |
| 838 } else if (V8FileList::hasInstance(value, isolate())) { |
| 839 return writeFileList(value, next); |
| 840 } else if (V8CryptoKey::hasInstance(value, isolate())) { |
| 841 if (!writeCryptoKey(value)) |
| 842 return handleError(DataCloneError, "Couldn't serialize key data"
, next); |
| 843 } else if (V8ImageData::hasInstance(value, isolate())) { |
| 844 writeImageData(value); |
| 845 } else if (value->IsRegExp()) { |
| 846 writeRegExp(value); |
| 847 } else if (V8ArrayBuffer::hasInstance(value, isolate())) { |
| 848 return writeArrayBuffer(value, next); |
| 849 } else if (value->IsObject()) { |
| 850 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNat
iveError()) |
| 851 return handleError(DataCloneError, "An object could not be clone
d.", next); |
| 852 return startObjectState(jsObject, next); |
| 853 } else { |
| 854 return handleError(DataCloneError, "A value could not be cloned.", n
ext); |
| 855 } |
| 856 } |
| 857 return 0; |
| 858 } |
| 859 |
| 860 Serializer::StateBase* Serializer::doSerializeArrayBuffer(v8::Handle<v8::Value>
arrayBuffer, Serializer::StateBase* next) |
| 861 { |
| 862 return doSerialize(arrayBuffer, next); |
| 863 } |
| 864 |
| 865 Serializer::StateBase* Serializer::checkException(Serializer::StateBase* state) |
| 866 { |
| 867 return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0; |
| 868 } |
| 869 |
| 870 Serializer::StateBase* Serializer::writeObject(uint32_t numProperties, Serialize
r::StateBase* state) |
| 871 { |
| 872 m_writer.writeObject(numProperties); |
| 873 return pop(state); |
| 874 } |
| 875 |
| 876 Serializer::StateBase* Serializer::writeSparseArray(uint32_t numProperties, uint
32_t length, Serializer::StateBase* state) |
| 877 { |
| 878 m_writer.writeSparseArray(numProperties, length); |
| 879 return pop(state); |
| 880 } |
| 881 |
| 882 Serializer::StateBase* Serializer::writeDenseArray(uint32_t numProperties, uint3
2_t length, Serializer::StateBase* state) |
| 883 { |
| 884 m_writer.writeDenseArray(numProperties, length); |
| 885 return pop(state); |
| 886 } |
| 887 |
| 888 Serializer::StateBase* Serializer::handleError(Serializer::Status errorStatus, c
onst String& message, Serializer::StateBase* state) |
| 889 { |
| 890 ASSERT(errorStatus != Success); |
| 891 m_status = errorStatus; |
| 892 m_errorMessage = message; |
| 893 while (state) { |
| 894 StateBase* tmp = state->nextState(); |
| 895 delete state; |
| 896 state = tmp; |
| 897 } |
| 898 return new ErrorState; |
| 899 } |
| 900 |
| 901 bool Serializer::checkComposite(Serializer::StateBase* top) |
| 902 { |
| 903 ASSERT(top); |
| 904 if (m_depth > maxDepth) |
| 905 return false; |
| 906 if (!shouldCheckForCycles(m_depth)) |
| 907 return true; |
| 908 v8::Handle<v8::Value> composite = top->composite(); |
| 909 for (StateBase* state = top->nextState(); state; state = state->nextState())
{ |
| 910 if (state->composite() == composite) |
| 911 return false; |
| 912 } |
| 913 return true; |
| 914 } |
| 915 |
| 916 void Serializer::writeString(v8::Handle<v8::Value> value) |
| 917 { |
| 918 v8::Handle<v8::String> string = value.As<v8::String>(); |
| 919 if (!string->Length() || string->IsOneByte()) |
| 920 m_writer.writeOneByteString(string); |
| 921 else |
| 922 m_writer.writeUCharString(string); |
| 923 } |
| 924 |
| 925 void Serializer::writeStringObject(v8::Handle<v8::Value> value) |
| 926 { |
| 927 v8::Handle<v8::StringObject> stringObject = value.As<v8::StringObject>(); |
| 928 v8::String::Utf8Value stringValue(stringObject->ValueOf()); |
| 929 m_writer.writeStringObject(*stringValue, stringValue.length()); |
| 930 } |
| 931 |
| 932 void Serializer::writeNumberObject(v8::Handle<v8::Value> value) |
| 933 { |
| 934 v8::Handle<v8::NumberObject> numberObject = value.As<v8::NumberObject>(); |
| 935 m_writer.writeNumberObject(numberObject->ValueOf()); |
| 936 } |
| 937 |
| 938 void Serializer::writeBooleanObject(v8::Handle<v8::Value> value) |
| 939 { |
| 940 v8::Handle<v8::BooleanObject> booleanObject = value.As<v8::BooleanObject>(); |
| 941 m_writer.writeBooleanObject(booleanObject->ValueOf()); |
| 942 } |
| 943 |
| 944 Serializer::StateBase* Serializer::writeBlob(v8::Handle<v8::Value> value, Serial
izer::StateBase* next) |
| 945 { |
| 946 Blob* blob = V8Blob::toImpl(value.As<v8::Object>()); |
| 947 if (!blob) |
| 948 return 0; |
| 949 if (blob->hasBeenClosed()) |
| 950 return handleError(DataCloneError, "A Blob object has been closed, and c
ould therefore not be cloned.", next); |
| 951 int blobIndex = -1; |
| 952 m_blobDataHandles.set(blob->uuid(), blob->blobDataHandle()); |
| 953 if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)) |
| 954 m_writer.writeBlobIndex(blobIndex); |
| 955 else |
| 956 m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); |
| 957 return 0; |
| 958 } |
| 959 |
| 960 Serializer::StateBase* Serializer::writeDOMFileSystem(v8::Handle<v8::Value> valu
e, StateBase* next) |
| 961 { |
| 962 DOMFileSystem* fs = V8DOMFileSystem::toImpl(value.As<v8::Object>()); |
| 963 if (!fs) |
| 964 return 0; |
| 965 if (!fs->clonable()) |
| 966 return handleError(DataCloneError, "A FileSystem object could not be clo
ned.", next); |
| 967 m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string()); |
| 968 return 0; |
| 969 } |
| 970 |
| 971 Serializer::StateBase* Serializer::writeFile(v8::Handle<v8::Value> value, Serial
izer::StateBase* next) |
| 972 { |
| 973 File* file = V8File::toImpl(value.As<v8::Object>()); |
| 974 if (!file) |
| 975 return 0; |
| 976 if (file->hasBeenClosed()) |
| 977 return handleError(DataCloneError, "A File object has been closed, and c
ould therefore not be cloned.", next); |
| 978 int blobIndex = -1; |
| 979 m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); |
| 980 if (appendFileInfo(file, &blobIndex)) { |
| 981 ASSERT(blobIndex >= 0); |
| 982 m_writer.writeFileIndex(blobIndex); |
| 983 } else { |
| 984 m_writer.writeFile(*file); |
| 985 } |
| 986 return 0; |
| 987 } |
| 988 |
| 989 Serializer::StateBase* Serializer::writeFileList(v8::Handle<v8::Value> value, Se
rializer::StateBase* next) |
| 990 { |
| 991 FileList* fileList = V8FileList::toImpl(value.As<v8::Object>()); |
| 992 if (!fileList) |
| 993 return 0; |
| 994 unsigned length = fileList->length(); |
| 995 Vector<int> blobIndices; |
| 996 for (unsigned i = 0; i < length; ++i) { |
| 997 int blobIndex = -1; |
| 998 const File* file = fileList->item(i); |
| 999 if (file->hasBeenClosed()) |
| 1000 return handleError(DataCloneError, "A File object has been closed, a
nd could therefore not be cloned.", next); |
| 1001 m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); |
| 1002 if (appendFileInfo(file, &blobIndex)) { |
| 1003 ASSERT(!i || blobIndex > 0); |
| 1004 ASSERT(blobIndex >= 0); |
| 1005 blobIndices.append(blobIndex); |
| 1006 } |
| 1007 } |
| 1008 if (!blobIndices.isEmpty()) |
| 1009 m_writer.writeFileListIndex(blobIndices); |
| 1010 else |
| 1011 m_writer.writeFileList(*fileList); |
| 1012 return 0; |
| 1013 } |
| 1014 |
| 1015 bool Serializer::writeCryptoKey(v8::Handle<v8::Value> value) |
| 1016 { |
| 1017 CryptoKey* key = V8CryptoKey::toImpl(value.As<v8::Object>()); |
| 1018 if (!key) |
| 1019 return false; |
| 1020 return m_writer.writeCryptoKey(key->key()); |
| 1021 } |
| 1022 |
| 1023 void Serializer::writeImageData(v8::Handle<v8::Value> value) |
| 1024 { |
| 1025 ImageData* imageData = V8ImageData::toImpl(value.As<v8::Object>()); |
| 1026 if (!imageData) |
| 1027 return; |
| 1028 Uint8ClampedArray* pixelArray = imageData->data(); |
| 1029 m_writer.writeImageData(imageData->width(), imageData->height(), pixelArray-
>data(), pixelArray->length()); |
| 1030 } |
| 1031 |
| 1032 void Serializer::writeRegExp(v8::Handle<v8::Value> value) |
| 1033 { |
| 1034 v8::Handle<v8::RegExp> regExp = value.As<v8::RegExp>(); |
| 1035 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); |
| 1036 } |
| 1037 |
| 1038 Serializer::StateBase* Serializer::writeAndGreyArrayBufferView(v8::Handle<v8::Ob
ject> object, Serializer::StateBase* next) |
| 1039 { |
| 1040 ASSERT(!object.IsEmpty()); |
| 1041 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); |
| 1042 if (!arrayBufferView) |
| 1043 return 0; |
| 1044 if (!arrayBufferView->buffer()) |
| 1045 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); |
| 1046 v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_s
criptState->context()->Global(), isolate()); |
| 1047 if (underlyingBuffer.IsEmpty()) |
| 1048 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); |
| 1049 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); |
| 1050 if (stateOut) |
| 1051 return stateOut; |
| 1052 m_writer.writeArrayBufferView(*arrayBufferView->view()); |
| 1053 // This should be safe: we serialize something that we know to be a wrapper
(see |
| 1054 // the toV8 call above), so the call to doSerializeArrayBuffer should neithe
r |
| 1055 // cause the system stack to overflow nor should it have potential to reach |
| 1056 // this ArrayBufferView again. |
| 1057 // |
| 1058 // We do need to grey the underlying buffer before we grey its view, however
; |
| 1059 // ArrayBuffers may be shared, so they need to be given reference IDs, and a
n |
| 1060 // ArrayBufferView cannot be constructed without a corresponding ArrayBuffer |
| 1061 // (or without an additional tag that would allow us to do two-stage constru
ction |
| 1062 // like we do for Objects and Arrays). |
| 1063 greyObject(object); |
| 1064 return 0; |
| 1065 } |
| 1066 |
| 1067 Serializer::StateBase* Serializer::writeArrayBuffer(v8::Handle<v8::Value> value,
Serializer::StateBase* next) |
| 1068 { |
| 1069 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>()); |
| 1070 if (!arrayBuffer) |
| 1071 return 0; |
| 1072 if (arrayBuffer->isNeutered()) |
| 1073 return handleError(DataCloneError, "An ArrayBuffer is neutered and could
not be cloned.", next); |
| 1074 ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>())); |
| 1075 m_writer.writeArrayBuffer(*arrayBuffer->buffer()); |
| 1076 return 0; |
| 1077 } |
| 1078 |
| 1079 Serializer::StateBase* Serializer::writeTransferredArrayBuffer(v8::Handle<v8::Va
lue> value, uint32_t index, Serializer::StateBase* next) |
| 1080 { |
| 1081 DOMArrayBuffer* arrayBuffer = V8ArrayBuffer::toImpl(value.As<v8::Object>()); |
| 1082 if (!arrayBuffer) |
| 1083 return 0; |
| 1084 if (arrayBuffer->isNeutered()) |
| 1085 return handleError(DataCloneError, "An ArrayBuffer is neutered and could
not be cloned.", next); |
| 1086 m_writer.writeTransferredArrayBuffer(index); |
| 1087 return 0; |
| 1088 } |
| 1089 |
| 1090 bool Serializer::shouldSerializeDensely(uint32_t length, uint32_t propertyCount) |
| 1091 { |
| 1092 // Let K be the cost of serializing all property values that are there |
| 1093 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t k
ey) |
| 1094 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for a
ll properties that are not there) |
| 1095 // so densely is better than sparsly whenever 6*propertyCount > length |
| 1096 return 6 * propertyCount >= length; |
| 1097 } |
| 1098 |
| 1099 Serializer::StateBase* Serializer::startArrayState(v8::Handle<v8::Array> array,
Serializer::StateBase* next) |
| 1100 { |
| 1101 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames(); |
| 1102 if (StateBase* newState = checkException(next)) |
| 1103 return newState; |
| 1104 uint32_t length = array->Length(); |
| 1105 |
| 1106 if (shouldSerializeDensely(length, propertyNames->Length())) { |
| 1107 m_writer.writeGenerateFreshDenseArray(length); |
| 1108 return push(new DenseArrayState(array, propertyNames, next, isolate())); |
| 1109 } |
| 1110 |
| 1111 m_writer.writeGenerateFreshSparseArray(length); |
| 1112 return push(new SparseArrayState(array, propertyNames, next, isolate())); |
| 1113 } |
| 1114 |
| 1115 Serializer::StateBase* Serializer::startObjectState(v8::Handle<v8::Object> objec
t, Serializer::StateBase* next) |
| 1116 { |
| 1117 m_writer.writeGenerateFreshObject(); |
| 1118 // FIXME: check not a wrapper |
| 1119 return push(new ObjectState(object, next)); |
| 1120 } |
| 1121 |
| 1122 // Marks object as having been visited by the serializer and assigns it a unique
object reference ID. |
| 1123 // An object may only be greyed once. |
| 1124 void Serializer::greyObject(const v8::Handle<v8::Object>& object) |
| 1125 { |
| 1126 ASSERT(!m_objectPool.contains(object)); |
| 1127 uint32_t objectReference = m_nextObjectReference++; |
| 1128 m_objectPool.set(object, objectReference); |
| 1129 } |
| 1130 |
| 1131 bool Serializer::appendBlobInfo(const String& uuid, const String& type, unsigned
long long size, int* index) |
| 1132 { |
| 1133 if (!m_blobInfo) |
| 1134 return false; |
| 1135 *index = m_blobInfo->size(); |
| 1136 m_blobInfo->append(WebBlobInfo(uuid, type, size)); |
| 1137 return true; |
| 1138 } |
| 1139 |
| 1140 bool Serializer::appendFileInfo(const File* file, int* index) |
| 1141 { |
| 1142 if (!m_blobInfo) |
| 1143 return false; |
| 1144 |
| 1145 long long size = -1; |
| 1146 double lastModified = invalidFileTime(); |
| 1147 file->captureSnapshot(size, lastModified); |
| 1148 *index = m_blobInfo->size(); |
| 1149 m_blobInfo->append(WebBlobInfo(file->uuid(), file->path(), file->name(), fil
e->type(), lastModified, size)); |
| 1150 return true; |
| 1151 } |
| 1152 |
| 1153 bool Reader::read(v8::Handle<v8::Value>* value, CompositeCreator& creator) |
| 1154 { |
| 1155 SerializationTag tag; |
| 1156 if (!readTag(&tag)) |
| 1157 return false; |
| 1158 switch (tag) { |
| 1159 case ReferenceCountTag: { |
| 1160 if (!m_version) |
| 1161 return false; |
| 1162 uint32_t referenceTableSize; |
| 1163 if (!doReadUint32(&referenceTableSize)) |
| 1164 return false; |
| 1165 // If this test fails, then the serializer and deserializer disagree abo
ut the assignment |
| 1166 // of object reference IDs. On the deserialization side, this means ther
e are too many or too few |
| 1167 // calls to pushObjectReference. |
| 1168 if (referenceTableSize != creator.objectReferenceCount()) |
| 1169 return false; |
| 1170 return true; |
| 1171 } |
| 1172 case InvalidTag: |
| 1173 return false; |
| 1174 case PaddingTag: |
| 1175 return true; |
| 1176 case UndefinedTag: |
| 1177 *value = v8::Undefined(isolate()); |
| 1178 break; |
| 1179 case NullTag: |
| 1180 *value = v8::Null(isolate()); |
| 1181 break; |
| 1182 case TrueTag: |
| 1183 *value = v8Boolean(true, isolate()); |
| 1184 break; |
| 1185 case FalseTag: |
| 1186 *value = v8Boolean(false, isolate()); |
| 1187 break; |
| 1188 case TrueObjectTag: |
| 1189 *value = v8::BooleanObject::New(true); |
| 1190 creator.pushObjectReference(*value); |
| 1191 break; |
| 1192 case FalseObjectTag: |
| 1193 *value = v8::BooleanObject::New(false); |
| 1194 creator.pushObjectReference(*value); |
| 1195 break; |
| 1196 case StringTag: |
| 1197 if (!readString(value)) |
| 1198 return false; |
| 1199 break; |
| 1200 case StringUCharTag: |
| 1201 if (!readUCharString(value)) |
| 1202 return false; |
| 1203 break; |
| 1204 case StringObjectTag: |
| 1205 if (!readStringObject(value)) |
| 1206 return false; |
| 1207 creator.pushObjectReference(*value); |
| 1208 break; |
| 1209 case Int32Tag: |
| 1210 if (!readInt32(value)) |
| 1211 return false; |
| 1212 break; |
| 1213 case Uint32Tag: |
| 1214 if (!readUint32(value)) |
| 1215 return false; |
| 1216 break; |
| 1217 case DateTag: |
| 1218 if (!readDate(value)) |
| 1219 return false; |
| 1220 creator.pushObjectReference(*value); |
| 1221 break; |
| 1222 case NumberTag: |
| 1223 if (!readNumber(value)) |
| 1224 return false; |
| 1225 break; |
| 1226 case NumberObjectTag: |
| 1227 if (!readNumberObject(value)) |
| 1228 return false; |
| 1229 creator.pushObjectReference(*value); |
| 1230 break; |
| 1231 case BlobTag: |
| 1232 case BlobIndexTag: |
| 1233 if (!readBlob(value, tag == BlobIndexTag)) |
| 1234 return false; |
| 1235 creator.pushObjectReference(*value); |
| 1236 break; |
| 1237 case FileTag: |
| 1238 case FileIndexTag: |
| 1239 if (!readFile(value, tag == FileIndexTag)) |
| 1240 return false; |
| 1241 creator.pushObjectReference(*value); |
| 1242 break; |
| 1243 case DOMFileSystemTag: |
| 1244 if (!readDOMFileSystem(value)) |
| 1245 return false; |
| 1246 creator.pushObjectReference(*value); |
| 1247 break; |
| 1248 case FileListTag: |
| 1249 case FileListIndexTag: |
| 1250 if (!readFileList(value, tag == FileListIndexTag)) |
| 1251 return false; |
| 1252 creator.pushObjectReference(*value); |
| 1253 break; |
| 1254 case CryptoKeyTag: |
| 1255 if (!readCryptoKey(value)) |
| 1256 return false; |
| 1257 creator.pushObjectReference(*value); |
| 1258 break; |
| 1259 case ImageDataTag: |
| 1260 if (!readImageData(value)) |
| 1261 return false; |
| 1262 creator.pushObjectReference(*value); |
| 1263 break; |
| 1264 |
| 1265 case RegExpTag: |
| 1266 if (!readRegExp(value)) |
| 1267 return false; |
| 1268 creator.pushObjectReference(*value); |
| 1269 break; |
| 1270 case ObjectTag: { |
| 1271 uint32_t numProperties; |
| 1272 if (!doReadUint32(&numProperties)) |
| 1273 return false; |
| 1274 if (!creator.completeObject(numProperties, value)) |
| 1275 return false; |
| 1276 break; |
| 1277 } |
| 1278 case SparseArrayTag: { |
| 1279 uint32_t numProperties; |
| 1280 uint32_t length; |
| 1281 if (!doReadUint32(&numProperties)) |
| 1282 return false; |
| 1283 if (!doReadUint32(&length)) |
| 1284 return false; |
| 1285 if (!creator.completeSparseArray(numProperties, length, value)) |
| 1286 return false; |
| 1287 break; |
| 1288 } |
| 1289 case DenseArrayTag: { |
| 1290 uint32_t numProperties; |
| 1291 uint32_t length; |
| 1292 if (!doReadUint32(&numProperties)) |
| 1293 return false; |
| 1294 if (!doReadUint32(&length)) |
| 1295 return false; |
| 1296 if (!creator.completeDenseArray(numProperties, length, value)) |
| 1297 return false; |
| 1298 break; |
| 1299 } |
| 1300 case ArrayBufferViewTag: { |
| 1301 if (!m_version) |
| 1302 return false; |
| 1303 if (!readArrayBufferView(value, creator)) |
| 1304 return false; |
| 1305 creator.pushObjectReference(*value); |
| 1306 break; |
| 1307 } |
| 1308 case ArrayBufferTag: { |
| 1309 if (!m_version) |
| 1310 return false; |
| 1311 if (!readArrayBuffer(value)) |
| 1312 return false; |
| 1313 creator.pushObjectReference(*value); |
| 1314 break; |
| 1315 } |
| 1316 case GenerateFreshObjectTag: { |
| 1317 if (!m_version) |
| 1318 return false; |
| 1319 if (!creator.newObject()) |
| 1320 return false; |
| 1321 return true; |
| 1322 } |
| 1323 case GenerateFreshSparseArrayTag: { |
| 1324 if (!m_version) |
| 1325 return false; |
| 1326 uint32_t length; |
| 1327 if (!doReadUint32(&length)) |
| 1328 return false; |
| 1329 if (!creator.newSparseArray(length)) |
| 1330 return false; |
| 1331 return true; |
| 1332 } |
| 1333 case GenerateFreshDenseArrayTag: { |
| 1334 if (!m_version) |
| 1335 return false; |
| 1336 uint32_t length; |
| 1337 if (!doReadUint32(&length)) |
| 1338 return false; |
| 1339 if (!creator.newDenseArray(length)) |
| 1340 return false; |
| 1341 return true; |
| 1342 } |
| 1343 case MessagePortTag: { |
| 1344 if (!m_version) |
| 1345 return false; |
| 1346 uint32_t index; |
| 1347 if (!doReadUint32(&index)) |
| 1348 return false; |
| 1349 if (!creator.tryGetTransferredMessagePort(index, value)) |
| 1350 return false; |
| 1351 break; |
| 1352 } |
| 1353 case ArrayBufferTransferTag: { |
| 1354 if (!m_version) |
| 1355 return false; |
| 1356 uint32_t index; |
| 1357 if (!doReadUint32(&index)) |
| 1358 return false; |
| 1359 if (!creator.tryGetTransferredArrayBuffer(index, value)) |
| 1360 return false; |
| 1361 break; |
| 1362 } |
| 1363 case ObjectReferenceTag: { |
| 1364 if (!m_version) |
| 1365 return false; |
| 1366 uint32_t reference; |
| 1367 if (!doReadUint32(&reference)) |
| 1368 return false; |
| 1369 if (!creator.tryGetObjectFromObjectReference(reference, value)) |
| 1370 return false; |
| 1371 break; |
| 1372 } |
| 1373 default: |
| 1374 return false; |
| 1375 } |
| 1376 return !value->IsEmpty(); |
| 1377 } |
| 1378 |
| 1379 bool Reader::readVersion(uint32_t& version) |
| 1380 { |
| 1381 SerializationTag tag; |
| 1382 if (!readTag(&tag)) { |
| 1383 // This is a nullary buffer. We're still version 0. |
| 1384 version = 0; |
| 1385 return true; |
| 1386 } |
| 1387 if (tag != VersionTag) { |
| 1388 // Versions of the format past 0 start with the version tag. |
| 1389 version = 0; |
| 1390 // Put back the tag. |
| 1391 undoReadTag(); |
| 1392 return true; |
| 1393 } |
| 1394 // Version-bearing messages are obligated to finish the version tag. |
| 1395 return doReadUint32(&version); |
| 1396 } |
| 1397 |
| 1398 void Reader::setVersion(uint32_t version) |
| 1399 { |
| 1400 m_version = version; |
| 1401 } |
| 1402 |
| 1403 bool Reader::readTag(SerializationTag* tag) |
| 1404 { |
| 1405 if (m_position >= m_length) |
| 1406 return false; |
| 1407 *tag = static_cast<SerializationTag>(m_buffer[m_position++]); |
| 1408 return true; |
| 1409 } |
| 1410 |
| 1411 void Reader::undoReadTag() |
| 1412 { |
| 1413 if (m_position > 0) |
| 1414 --m_position; |
| 1415 } |
| 1416 |
| 1417 bool Reader::readArrayBufferViewSubTag(ArrayBufferViewSubTag* tag) |
| 1418 { |
| 1419 if (m_position >= m_length) |
| 1420 return false; |
| 1421 *tag = static_cast<ArrayBufferViewSubTag>(m_buffer[m_position++]); |
| 1422 return true; |
| 1423 } |
| 1424 |
| 1425 bool Reader::readString(v8::Handle<v8::Value>* value) |
| 1426 { |
| 1427 uint32_t length; |
| 1428 if (!doReadUint32(&length)) |
| 1429 return false; |
| 1430 if (m_position + length > m_length) |
| 1431 return false; |
| 1432 *value = v8::String::NewFromUtf8(isolate(), reinterpret_cast<const char*>(m_
buffer + m_position), v8::String::kNormalString, length); |
| 1433 m_position += length; |
| 1434 return true; |
| 1435 } |
| 1436 |
| 1437 bool Reader::readUCharString(v8::Handle<v8::Value>* value) |
| 1438 { |
| 1439 uint32_t length; |
| 1440 if (!doReadUint32(&length) || (length & 1)) |
| 1441 return false; |
| 1442 if (m_position + length > m_length) |
| 1443 return false; |
| 1444 ASSERT(!(m_position & 1)); |
| 1445 *value = v8::String::NewFromTwoByte(isolate(), reinterpret_cast<const uint16
_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar)); |
| 1446 m_position += length; |
| 1447 return true; |
| 1448 } |
| 1449 |
| 1450 bool Reader::readStringObject(v8::Handle<v8::Value>* value) |
| 1451 { |
| 1452 v8::Handle<v8::Value> stringValue; |
| 1453 if (!readString(&stringValue) || !stringValue->IsString()) |
| 1454 return false; |
| 1455 *value = v8::StringObject::New(stringValue.As<v8::String>()); |
| 1456 return true; |
| 1457 } |
| 1458 |
| 1459 bool Reader::readWebCoreString(String* string) |
| 1460 { |
| 1461 uint32_t length; |
| 1462 if (!doReadUint32(&length)) |
| 1463 return false; |
| 1464 if (m_position + length > m_length) |
| 1465 return false; |
| 1466 *string = String::fromUTF8(reinterpret_cast<const char*>(m_buffer + m_positi
on), length); |
| 1467 m_position += length; |
| 1468 return true; |
| 1469 } |
| 1470 |
| 1471 bool Reader::readInt32(v8::Handle<v8::Value>* value) |
| 1472 { |
| 1473 uint32_t rawValue; |
| 1474 if (!doReadUint32(&rawValue)) |
| 1475 return false; |
| 1476 *value = v8::Integer::New(isolate(), static_cast<int32_t>(ZigZag::decode(raw
Value))); |
| 1477 return true; |
| 1478 } |
| 1479 |
| 1480 bool Reader::readUint32(v8::Handle<v8::Value>* value) |
| 1481 { |
| 1482 uint32_t rawValue; |
| 1483 if (!doReadUint32(&rawValue)) |
| 1484 return false; |
| 1485 *value = v8::Integer::NewFromUnsigned(isolate(), rawValue); |
| 1486 return true; |
| 1487 } |
| 1488 |
| 1489 bool Reader::readDate(v8::Handle<v8::Value>* value) |
| 1490 { |
| 1491 double numberValue; |
| 1492 if (!doReadNumber(&numberValue)) |
| 1493 return false; |
| 1494 *value = v8DateOrNaN(numberValue, isolate()); |
| 1495 return true; |
| 1496 } |
| 1497 |
| 1498 bool Reader::readNumber(v8::Handle<v8::Value>* value) |
| 1499 { |
| 1500 double number; |
| 1501 if (!doReadNumber(&number)) |
| 1502 return false; |
| 1503 *value = v8::Number::New(isolate(), number); |
| 1504 return true; |
| 1505 } |
| 1506 |
| 1507 bool Reader::readNumberObject(v8::Handle<v8::Value>* value) |
| 1508 { |
| 1509 double number; |
| 1510 if (!doReadNumber(&number)) |
| 1511 return false; |
| 1512 *value = v8::NumberObject::New(isolate(), number); |
| 1513 return true; |
| 1514 } |
| 1515 |
| 1516 bool Reader::readImageData(v8::Handle<v8::Value>* value) |
| 1517 { |
| 1518 uint32_t width; |
| 1519 uint32_t height; |
| 1520 uint32_t pixelDataLength; |
| 1521 if (!doReadUint32(&width)) |
| 1522 return false; |
| 1523 if (!doReadUint32(&height)) |
| 1524 return false; |
| 1525 if (!doReadUint32(&pixelDataLength)) |
| 1526 return false; |
| 1527 if (m_position + pixelDataLength > m_length) |
| 1528 return false; |
| 1529 RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(IntSize(width, h
eight)); |
| 1530 Uint8ClampedArray* pixelArray = imageData->data(); |
| 1531 ASSERT(pixelArray); |
| 1532 ASSERT(pixelArray->length() >= pixelDataLength); |
| 1533 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); |
| 1534 m_position += pixelDataLength; |
| 1535 *value = toV8(imageData.release(), m_scriptState->context()->Global(), isola
te()); |
| 1536 return true; |
| 1537 } |
| 1538 |
| 1539 PassRefPtr<ArrayBuffer> Reader::doReadArrayBuffer() |
| 1540 { |
| 1541 uint32_t byteLength; |
| 1542 if (!doReadUint32(&byteLength)) |
| 1543 return nullptr; |
| 1544 if (m_position + byteLength > m_length) |
| 1545 return nullptr; |
| 1546 const void* bufferStart = m_buffer + m_position; |
| 1547 m_position += byteLength; |
| 1548 return ArrayBuffer::create(bufferStart, byteLength); |
| 1549 } |
| 1550 |
| 1551 bool Reader::readArrayBuffer(v8::Handle<v8::Value>* value) |
| 1552 { |
| 1553 RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer(); |
| 1554 if (!arrayBuffer) |
| 1555 return false; |
| 1556 *value = toV8(DOMArrayBuffer::create(arrayBuffer.release()), m_scriptState->
context()->Global(), isolate()); |
| 1557 return true; |
| 1558 } |
| 1559 |
| 1560 bool Reader::readArrayBufferView(v8::Handle<v8::Value>* value, CompositeCreator&
creator) |
| 1561 { |
| 1562 ArrayBufferViewSubTag subTag; |
| 1563 uint32_t byteOffset; |
| 1564 uint32_t byteLength; |
| 1565 RefPtr<DOMArrayBuffer> arrayBuffer; |
| 1566 v8::Handle<v8::Value> arrayBufferV8Value; |
| 1567 if (!readArrayBufferViewSubTag(&subTag)) |
| 1568 return false; |
| 1569 if (!doReadUint32(&byteOffset)) |
| 1570 return false; |
| 1571 if (!doReadUint32(&byteLength)) |
| 1572 return false; |
| 1573 if (!creator.consumeTopOfStack(&arrayBufferV8Value)) |
| 1574 return false; |
| 1575 if (arrayBufferV8Value.IsEmpty()) |
| 1576 return false; |
| 1577 arrayBuffer = V8ArrayBuffer::toImpl(arrayBufferV8Value.As<v8::Object>()); |
| 1578 if (!arrayBuffer) |
| 1579 return false; |
| 1580 |
| 1581 v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global(); |
| 1582 switch (subTag) { |
| 1583 case ByteArrayTag: |
| 1584 *value = toV8(DOMInt8Array::create(arrayBuffer.release(), byteOffset, by
teLength), creationContext, isolate()); |
| 1585 break; |
| 1586 case UnsignedByteArrayTag: |
| 1587 *value = toV8(DOMUint8Array::create(arrayBuffer.release(), byteOffset, b
yteLength), creationContext, isolate()); |
| 1588 break; |
| 1589 case UnsignedByteClampedArrayTag: |
| 1590 *value = toV8(DOMUint8ClampedArray::create(arrayBuffer.release(), byteOf
fset, byteLength), creationContext, isolate()); |
| 1591 break; |
| 1592 case ShortArrayTag: { |
| 1593 uint32_t shortLength = byteLength / sizeof(int16_t); |
| 1594 if (shortLength * sizeof(int16_t) != byteLength) |
| 1595 return false; |
| 1596 *value = toV8(DOMInt16Array::create(arrayBuffer.release(), byteOffset, s
hortLength), creationContext, isolate()); |
| 1597 break; |
| 1598 } |
| 1599 case UnsignedShortArrayTag: { |
| 1600 uint32_t shortLength = byteLength / sizeof(uint16_t); |
| 1601 if (shortLength * sizeof(uint16_t) != byteLength) |
| 1602 return false; |
| 1603 *value = toV8(DOMUint16Array::create(arrayBuffer.release(), byteOffset,
shortLength), creationContext, isolate()); |
| 1604 break; |
| 1605 } |
| 1606 case IntArrayTag: { |
| 1607 uint32_t intLength = byteLength / sizeof(int32_t); |
| 1608 if (intLength * sizeof(int32_t) != byteLength) |
| 1609 return false; |
| 1610 *value = toV8(DOMInt32Array::create(arrayBuffer.release(), byteOffset, i
ntLength), creationContext, isolate()); |
| 1611 break; |
| 1612 } |
| 1613 case UnsignedIntArrayTag: { |
| 1614 uint32_t intLength = byteLength / sizeof(uint32_t); |
| 1615 if (intLength * sizeof(uint32_t) != byteLength) |
| 1616 return false; |
| 1617 *value = toV8(DOMUint32Array::create(arrayBuffer.release(), byteOffset,
intLength), creationContext, isolate()); |
| 1618 break; |
| 1619 } |
| 1620 case FloatArrayTag: { |
| 1621 uint32_t floatLength = byteLength / sizeof(float); |
| 1622 if (floatLength * sizeof(float) != byteLength) |
| 1623 return false; |
| 1624 *value = toV8(DOMFloat32Array::create(arrayBuffer.release(), byteOffset,
floatLength), creationContext, isolate()); |
| 1625 break; |
| 1626 } |
| 1627 case DoubleArrayTag: { |
| 1628 uint32_t floatLength = byteLength / sizeof(double); |
| 1629 if (floatLength * sizeof(double) != byteLength) |
| 1630 return false; |
| 1631 *value = toV8(DOMFloat64Array::create(arrayBuffer.release(), byteOffset,
floatLength), creationContext, isolate()); |
| 1632 break; |
| 1633 } |
| 1634 case DataViewTag: |
| 1635 *value = toV8(DOMDataView::create(arrayBuffer.release(), byteOffset, byt
eLength), creationContext, isolate()); |
| 1636 break; |
| 1637 default: |
| 1638 return false; |
| 1639 } |
| 1640 // The various *Array::create() methods will return null if the range the vi
ew expects is |
| 1641 // mismatched with the range the buffer can provide or if the byte offset is
not aligned |
| 1642 // to the size of the element type. |
| 1643 return !value->IsEmpty(); |
| 1644 } |
| 1645 |
| 1646 bool Reader::readRegExp(v8::Handle<v8::Value>* value) |
| 1647 { |
| 1648 v8::Handle<v8::Value> pattern; |
| 1649 if (!readString(&pattern)) |
| 1650 return false; |
| 1651 uint32_t flags; |
| 1652 if (!doReadUint32(&flags)) |
| 1653 return false; |
| 1654 *value = v8::RegExp::New(pattern.As<v8::String>(), static_cast<v8::RegExp::F
lags>(flags)); |
| 1655 return true; |
| 1656 } |
| 1657 |
| 1658 bool Reader::readBlob(v8::Handle<v8::Value>* value, bool isIndexed) |
| 1659 { |
| 1660 if (m_version < 3) |
| 1661 return false; |
| 1662 Blob* blob = nullptr; |
| 1663 if (isIndexed) { |
| 1664 if (m_version < 6) |
| 1665 return false; |
| 1666 ASSERT(m_blobInfo); |
| 1667 uint32_t index; |
| 1668 if (!doReadUint32(&index) || index >= m_blobInfo->size()) |
| 1669 return false; |
| 1670 const WebBlobInfo& info = (*m_blobInfo)[index]; |
| 1671 blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type(),
info.size())); |
| 1672 } else { |
| 1673 ASSERT(!m_blobInfo); |
| 1674 String uuid; |
| 1675 String type; |
| 1676 uint64_t size; |
| 1677 ASSERT(!m_blobInfo); |
| 1678 if (!readWebCoreString(&uuid)) |
| 1679 return false; |
| 1680 if (!readWebCoreString(&type)) |
| 1681 return false; |
| 1682 if (!doReadUint64(&size)) |
| 1683 return false; |
| 1684 blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); |
| 1685 } |
| 1686 *value = toV8(blob, m_scriptState->context()->Global(), isolate()); |
| 1687 return true; |
| 1688 } |
| 1689 |
| 1690 bool Reader::readDOMFileSystem(v8::Handle<v8::Value>* value) |
| 1691 { |
| 1692 uint32_t type; |
| 1693 String name; |
| 1694 String url; |
| 1695 if (!doReadUint32(&type)) |
| 1696 return false; |
| 1697 if (!readWebCoreString(&name)) |
| 1698 return false; |
| 1699 if (!readWebCoreString(&url)) |
| 1700 return false; |
| 1701 DOMFileSystem* fs = DOMFileSystem::create(m_scriptState->executionContext(),
name, static_cast<FileSystemType>(type), KURL(ParsedURLString, url)); |
| 1702 *value = toV8(fs, m_scriptState->context()->Global(), isolate()); |
| 1703 return true; |
| 1704 } |
| 1705 |
| 1706 bool Reader::readFile(v8::Handle<v8::Value>* value, bool isIndexed) |
| 1707 { |
| 1708 File* file = nullptr; |
| 1709 if (isIndexed) { |
| 1710 if (m_version < 6) |
| 1711 return false; |
| 1712 file = readFileIndexHelper(); |
| 1713 } else { |
| 1714 file = readFileHelper(); |
| 1715 } |
| 1716 if (!file) |
| 1717 return false; |
| 1718 *value = toV8(file, m_scriptState->context()->Global(), isolate()); |
| 1719 return true; |
| 1720 } |
| 1721 |
| 1722 bool Reader::readFileList(v8::Handle<v8::Value>* value, bool isIndexed) |
| 1723 { |
| 1724 if (m_version < 3) |
| 1725 return false; |
| 1726 uint32_t length; |
| 1727 if (!doReadUint32(&length)) |
| 1728 return false; |
| 1729 FileList* fileList = FileList::create(); |
| 1730 for (unsigned i = 0; i < length; ++i) { |
| 1731 File* file = nullptr; |
| 1732 if (isIndexed) { |
| 1733 if (m_version < 6) |
| 1734 return false; |
| 1735 file = readFileIndexHelper(); |
| 1736 } else { |
| 1737 file = readFileHelper(); |
| 1738 } |
| 1739 if (!file) |
| 1740 return false; |
| 1741 fileList->append(file); |
| 1742 } |
| 1743 *value = toV8(fileList, m_scriptState->context()->Global(), isolate()); |
| 1744 return true; |
| 1745 } |
| 1746 |
| 1747 bool Reader::readCryptoKey(v8::Handle<v8::Value>* value) |
| 1748 { |
| 1749 uint32_t rawKeyType; |
| 1750 if (!doReadUint32(&rawKeyType)) |
| 1751 return false; |
| 1752 |
| 1753 WebCryptoKeyAlgorithm algorithm; |
| 1754 WebCryptoKeyType type = WebCryptoKeyTypeSecret; |
| 1755 |
| 1756 switch (static_cast<CryptoKeySubTag>(rawKeyType)) { |
| 1757 case AesKeyTag: |
| 1758 if (!doReadAesKey(algorithm, type)) |
| 1759 return false; |
| 1760 break; |
| 1761 case HmacKeyTag: |
| 1762 if (!doReadHmacKey(algorithm, type)) |
| 1763 return false; |
| 1764 break; |
| 1765 case RsaHashedKeyTag: |
| 1766 if (!doReadRsaHashedKey(algorithm, type)) |
| 1767 return false; |
| 1768 break; |
| 1769 default: |
| 1770 return false; |
| 1771 } |
| 1772 |
| 1773 WebCryptoKeyUsageMask usages; |
| 1774 bool extractable; |
| 1775 if (!doReadKeyUsages(usages, extractable)) |
| 1776 return false; |
| 1777 |
| 1778 uint32_t keyDataLength; |
| 1779 if (!doReadUint32(&keyDataLength)) |
| 1780 return false; |
| 1781 |
| 1782 if (m_position + keyDataLength > m_length) |
| 1783 return false; |
| 1784 |
| 1785 const uint8_t* keyData = m_buffer + m_position; |
| 1786 m_position += keyDataLength; |
| 1787 |
| 1788 WebCryptoKey key = WebCryptoKey::createNull(); |
| 1789 if (!Platform::current()->crypto()->deserializeKeyForClone( |
| 1790 algorithm, type, extractable, usages, keyData, keyDataLength, key)) { |
| 1791 return false; |
| 1792 } |
| 1793 |
| 1794 *value = toV8(CryptoKey::create(key), m_scriptState->context()->Global(), is
olate()); |
| 1795 return true; |
| 1796 } |
| 1797 |
| 1798 File* Reader::readFileHelper() |
| 1799 { |
| 1800 if (m_version < 3) |
| 1801 return nullptr; |
| 1802 ASSERT(!m_blobInfo); |
| 1803 String path; |
| 1804 String name; |
| 1805 String relativePath; |
| 1806 String uuid; |
| 1807 String type; |
| 1808 uint32_t hasSnapshot = 0; |
| 1809 uint64_t size = 0; |
| 1810 double lastModified = 0; |
| 1811 if (!readWebCoreString(&path)) |
| 1812 return nullptr; |
| 1813 if (m_version >= 4 && !readWebCoreString(&name)) |
| 1814 return nullptr; |
| 1815 if (m_version >= 4 && !readWebCoreString(&relativePath)) |
| 1816 return nullptr; |
| 1817 if (!readWebCoreString(&uuid)) |
| 1818 return nullptr; |
| 1819 if (!readWebCoreString(&type)) |
| 1820 return nullptr; |
| 1821 if (m_version >= 4 && !doReadUint32(&hasSnapshot)) |
| 1822 return nullptr; |
| 1823 if (hasSnapshot) { |
| 1824 if (!doReadUint64(&size)) |
| 1825 return nullptr; |
| 1826 if (!doReadNumber(&lastModified)) |
| 1827 return nullptr; |
| 1828 } |
| 1829 uint32_t isUserVisible = 1; |
| 1830 if (m_version >= 7 && !doReadUint32(&isUserVisible)) |
| 1831 return nullptr; |
| 1832 const File::UserVisibility userVisibility = (isUserVisible > 0) ? File::IsUs
erVisible : File::IsNotUserVisible; |
| 1833 return File::createFromSerialization(path, name, relativePath, userVisibilit
y, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type)); |
| 1834 } |
| 1835 |
| 1836 File* Reader::readFileIndexHelper() |
| 1837 { |
| 1838 if (m_version < 3) |
| 1839 return nullptr; |
| 1840 ASSERT(m_blobInfo); |
| 1841 uint32_t index; |
| 1842 if (!doReadUint32(&index) || index >= m_blobInfo->size()) |
| 1843 return nullptr; |
| 1844 const WebBlobInfo& info = (*m_blobInfo)[index]; |
| 1845 return File::createFromIndexedSerialization(info.filePath(), info.fileName()
, info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), info.
type(), info.size())); |
| 1846 } |
| 1847 |
| 1848 bool Reader::doReadUint32(uint32_t* value) |
| 1849 { |
| 1850 return doReadUintHelper(value); |
| 1851 } |
| 1852 |
| 1853 bool Reader::doReadUint64(uint64_t* value) |
| 1854 { |
| 1855 return doReadUintHelper(value); |
| 1856 } |
| 1857 |
| 1858 bool Reader::doReadNumber(double* number) |
| 1859 { |
| 1860 if (m_position + sizeof(double) > m_length) |
| 1861 return false; |
| 1862 uint8_t* numberAsByteArray = reinterpret_cast<uint8_t*>(number); |
| 1863 for (unsigned i = 0; i < sizeof(double); ++i) |
| 1864 numberAsByteArray[i] = m_buffer[m_position++]; |
| 1865 return true; |
| 1866 } |
| 1867 |
| 1868 PassRefPtr<BlobDataHandle> Reader::getOrCreateBlobDataHandle(const String& uuid,
const String& type, long long size) |
| 1869 { |
| 1870 // The containing ssv may have a BDH for this uuid if this ssv is just being |
| 1871 // passed from main to worker thread (for example). We use those values when
creating |
| 1872 // the new blob instead of cons'ing up a new BDH. |
| 1873 // |
| 1874 // FIXME: Maybe we should require that it work that way where the ssv must h
ave a BDH for any |
| 1875 // blobs it comes across during deserialization. Would require callers to ex
plicitly populate |
| 1876 // the collection of BDH's for blobs to work, which would encourage lifetime
s to be considered |
| 1877 // when passing ssv's around cross process. At present, we get 'lucky' in so
me cases because |
| 1878 // the blob in the src process happens to still exist at the time the dest p
rocess is deserializing. |
| 1879 // For example in sharedWorker.postMessage(...). |
| 1880 BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid); |
| 1881 if (it != m_blobDataHandles.end()) { |
| 1882 // make assertions about type and size? |
| 1883 return it->value; |
| 1884 } |
| 1885 return BlobDataHandle::create(uuid, type, size); |
| 1886 } |
| 1887 |
| 1888 bool Reader::doReadHmacKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& t
ype) |
| 1889 { |
| 1890 uint32_t lengthBytes; |
| 1891 if (!doReadUint32(&lengthBytes)) |
| 1892 return false; |
| 1893 WebCryptoAlgorithmId hash; |
| 1894 if (!doReadAlgorithmId(hash)) |
| 1895 return false; |
| 1896 algorithm = WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8); |
| 1897 type = WebCryptoKeyTypeSecret; |
| 1898 return !algorithm.isNull(); |
| 1899 } |
| 1900 |
| 1901 bool Reader::doReadAesKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& ty
pe) |
| 1902 { |
| 1903 WebCryptoAlgorithmId id; |
| 1904 if (!doReadAlgorithmId(id)) |
| 1905 return false; |
| 1906 uint32_t lengthBytes; |
| 1907 if (!doReadUint32(&lengthBytes)) |
| 1908 return false; |
| 1909 algorithm = WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8); |
| 1910 type = WebCryptoKeyTypeSecret; |
| 1911 return !algorithm.isNull(); |
| 1912 } |
| 1913 |
| 1914 bool Reader::doReadRsaHashedKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyTy
pe& type) |
| 1915 { |
| 1916 WebCryptoAlgorithmId id; |
| 1917 if (!doReadAlgorithmId(id)) |
| 1918 return false; |
| 1919 |
| 1920 uint32_t rawType; |
| 1921 if (!doReadUint32(&rawType)) |
| 1922 return false; |
| 1923 |
| 1924 switch (static_cast<AssymetricCryptoKeyType>(rawType)) { |
| 1925 case PublicKeyType: |
| 1926 type = WebCryptoKeyTypePublic; |
| 1927 break; |
| 1928 case PrivateKeyType: |
| 1929 type = WebCryptoKeyTypePrivate; |
| 1930 break; |
| 1931 default: |
| 1932 return false; |
| 1933 } |
| 1934 |
| 1935 uint32_t modulusLengthBits; |
| 1936 if (!doReadUint32(&modulusLengthBits)) |
| 1937 return false; |
| 1938 |
| 1939 uint32_t publicExponentSize; |
| 1940 if (!doReadUint32(&publicExponentSize)) |
| 1941 return false; |
| 1942 |
| 1943 if (m_position + publicExponentSize > m_length) |
| 1944 return false; |
| 1945 |
| 1946 const uint8_t* publicExponent = m_buffer + m_position; |
| 1947 m_position += publicExponentSize; |
| 1948 |
| 1949 WebCryptoAlgorithmId hash; |
| 1950 if (!doReadAlgorithmId(hash)) |
| 1951 return false; |
| 1952 algorithm = WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits, pu
blicExponent, publicExponentSize, hash); |
| 1953 |
| 1954 return !algorithm.isNull(); |
| 1955 } |
| 1956 |
| 1957 bool Reader::doReadAlgorithmId(WebCryptoAlgorithmId& id) |
| 1958 { |
| 1959 uint32_t rawId; |
| 1960 if (!doReadUint32(&rawId)) |
| 1961 return false; |
| 1962 |
| 1963 switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) { |
| 1964 case AesCbcTag: |
| 1965 id = WebCryptoAlgorithmIdAesCbc; |
| 1966 return true; |
| 1967 case HmacTag: |
| 1968 id = WebCryptoAlgorithmIdHmac; |
| 1969 return true; |
| 1970 case RsaSsaPkcs1v1_5Tag: |
| 1971 id = WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; |
| 1972 return true; |
| 1973 case Sha1Tag: |
| 1974 id = WebCryptoAlgorithmIdSha1; |
| 1975 return true; |
| 1976 case Sha256Tag: |
| 1977 id = WebCryptoAlgorithmIdSha256; |
| 1978 return true; |
| 1979 case Sha384Tag: |
| 1980 id = WebCryptoAlgorithmIdSha384; |
| 1981 return true; |
| 1982 case Sha512Tag: |
| 1983 id = WebCryptoAlgorithmIdSha512; |
| 1984 return true; |
| 1985 case AesGcmTag: |
| 1986 id = WebCryptoAlgorithmIdAesGcm; |
| 1987 return true; |
| 1988 case RsaOaepTag: |
| 1989 id = WebCryptoAlgorithmIdRsaOaep; |
| 1990 return true; |
| 1991 case AesCtrTag: |
| 1992 id = WebCryptoAlgorithmIdAesCtr; |
| 1993 return true; |
| 1994 case AesKwTag: |
| 1995 id = WebCryptoAlgorithmIdAesKw; |
| 1996 return true; |
| 1997 case RsaPssTag: |
| 1998 id = WebCryptoAlgorithmIdRsaPss; |
| 1999 return true; |
| 2000 } |
| 2001 |
| 2002 return false; |
| 2003 } |
| 2004 |
| 2005 bool Reader::doReadKeyUsages(WebCryptoKeyUsageMask& usages, bool& extractable) |
| 2006 { |
| 2007 // Reminder to update this when adding new key usages. |
| 2008 COMPILE_ASSERT(EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); |
| 2009 const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | Decrypt
Usage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage
| DeriveBitsUsage; |
| 2010 |
| 2011 uint32_t rawUsages; |
| 2012 if (!doReadUint32(&rawUsages)) |
| 2013 return false; |
| 2014 |
| 2015 // Make sure it doesn't contain an unrecognized usage value. |
| 2016 if (rawUsages & ~allPossibleUsages) |
| 2017 return false; |
| 2018 |
| 2019 usages = 0; |
| 2020 |
| 2021 extractable = rawUsages & ExtractableUsage; |
| 2022 |
| 2023 if (rawUsages & EncryptUsage) |
| 2024 usages |= WebCryptoKeyUsageEncrypt; |
| 2025 if (rawUsages & DecryptUsage) |
| 2026 usages |= WebCryptoKeyUsageDecrypt; |
| 2027 if (rawUsages & SignUsage) |
| 2028 usages |= WebCryptoKeyUsageSign; |
| 2029 if (rawUsages & VerifyUsage) |
| 2030 usages |= WebCryptoKeyUsageVerify; |
| 2031 if (rawUsages & DeriveKeyUsage) |
| 2032 usages |= WebCryptoKeyUsageDeriveKey; |
| 2033 if (rawUsages & WrapKeyUsage) |
| 2034 usages |= WebCryptoKeyUsageWrapKey; |
| 2035 if (rawUsages & UnwrapKeyUsage) |
| 2036 usages |= WebCryptoKeyUsageUnwrapKey; |
| 2037 if (rawUsages & DeriveBitsUsage) |
| 2038 usages |= WebCryptoKeyUsageDeriveBits; |
| 2039 |
| 2040 return true; |
| 2041 } |
| 2042 |
| 2043 v8::Handle<v8::Value> Deserializer::deserialize() |
| 2044 { |
| 2045 v8::Isolate* isolate = m_reader.scriptState()->isolate(); |
| 2046 if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::w
ireFormatVersion) |
| 2047 return v8::Null(isolate); |
| 2048 m_reader.setVersion(m_version); |
| 2049 v8::EscapableHandleScope scope(isolate); |
| 2050 while (!m_reader.isEof()) { |
| 2051 if (!doDeserialize()) |
| 2052 return v8::Null(isolate); |
| 2053 } |
| 2054 if (stackDepth() != 1 || m_openCompositeReferenceStack.size()) |
| 2055 return v8::Null(isolate); |
| 2056 v8::Handle<v8::Value> result = scope.Escape(element(0)); |
| 2057 return result; |
| 2058 } |
| 2059 |
| 2060 bool Deserializer::newSparseArray(uint32_t) |
| 2061 { |
| 2062 v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(
), 0); |
| 2063 openComposite(array); |
| 2064 return true; |
| 2065 } |
| 2066 |
| 2067 bool Deserializer::newDenseArray(uint32_t length) |
| 2068 { |
| 2069 v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(
), length); |
| 2070 openComposite(array); |
| 2071 return true; |
| 2072 } |
| 2073 |
| 2074 bool Deserializer::consumeTopOfStack(v8::Handle<v8::Value>* object) |
| 2075 { |
| 2076 if (stackDepth() < 1) |
| 2077 return false; |
| 2078 *object = element(stackDepth() - 1); |
| 2079 pop(1); |
| 2080 return true; |
| 2081 } |
| 2082 |
| 2083 bool Deserializer::newObject() |
| 2084 { |
| 2085 v8::Local<v8::Object> object = v8::Object::New(m_reader.scriptState()->isola
te()); |
| 2086 if (object.IsEmpty()) |
| 2087 return false; |
| 2088 openComposite(object); |
| 2089 return true; |
| 2090 } |
| 2091 |
| 2092 bool Deserializer::completeObject(uint32_t numProperties, v8::Handle<v8::Value>*
value) |
| 2093 { |
| 2094 v8::Local<v8::Object> object; |
| 2095 if (m_version > 0) { |
| 2096 v8::Local<v8::Value> composite; |
| 2097 if (!closeComposite(&composite)) |
| 2098 return false; |
| 2099 object = composite.As<v8::Object>(); |
| 2100 } else { |
| 2101 object = v8::Object::New(m_reader.scriptState()->isolate()); |
| 2102 } |
| 2103 if (object.IsEmpty()) |
| 2104 return false; |
| 2105 return initializeObject(object, numProperties, value); |
| 2106 } |
| 2107 |
| 2108 bool Deserializer::completeSparseArray(uint32_t numProperties, uint32_t length,
v8::Handle<v8::Value>* value) |
| 2109 { |
| 2110 v8::Local<v8::Array> array; |
| 2111 if (m_version > 0) { |
| 2112 v8::Local<v8::Value> composite; |
| 2113 if (!closeComposite(&composite)) |
| 2114 return false; |
| 2115 array = composite.As<v8::Array>(); |
| 2116 } else { |
| 2117 array = v8::Array::New(m_reader.scriptState()->isolate()); |
| 2118 } |
| 2119 if (array.IsEmpty()) |
| 2120 return false; |
| 2121 return initializeObject(array, numProperties, value); |
| 2122 } |
| 2123 |
| 2124 bool Deserializer::completeDenseArray(uint32_t numProperties, uint32_t length, v
8::Handle<v8::Value>* value) |
| 2125 { |
| 2126 v8::Local<v8::Array> array; |
| 2127 if (m_version > 0) { |
| 2128 v8::Local<v8::Value> composite; |
| 2129 if (!closeComposite(&composite)) |
| 2130 return false; |
| 2131 array = composite.As<v8::Array>(); |
| 2132 } |
| 2133 if (array.IsEmpty()) |
| 2134 return false; |
| 2135 if (!initializeObject(array, numProperties, value)) |
| 2136 return false; |
| 2137 if (length > stackDepth()) |
| 2138 return false; |
| 2139 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stac
kPos++) { |
| 2140 v8::Local<v8::Value> elem = element(stackPos); |
| 2141 if (!elem->IsUndefined()) |
| 2142 array->Set(i, elem); |
| 2143 } |
| 2144 pop(length); |
| 2145 return true; |
| 2146 } |
| 2147 |
| 2148 void Deserializer::pushObjectReference(const v8::Handle<v8::Value>& object) |
| 2149 { |
| 2150 m_objectPool.append(object); |
| 2151 } |
| 2152 |
| 2153 bool Deserializer::tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::V
alue>* object) |
| 2154 { |
| 2155 if (!m_transferredMessagePorts) |
| 2156 return false; |
| 2157 if (index >= m_transferredMessagePorts->size()) |
| 2158 return false; |
| 2159 v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->
Global(); |
| 2160 *object = toV8(m_transferredMessagePorts->at(index).get(), creationContext,
m_reader.scriptState()->isolate()); |
| 2161 return true; |
| 2162 } |
| 2163 |
| 2164 bool Deserializer::tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::V
alue>* object) |
| 2165 { |
| 2166 if (!m_arrayBufferContents) |
| 2167 return false; |
| 2168 if (index >= m_arrayBuffers.size()) |
| 2169 return false; |
| 2170 v8::Handle<v8::Object> result = m_arrayBuffers.at(index); |
| 2171 if (result.IsEmpty()) { |
| 2172 RefPtr<DOMArrayBuffer> buffer = DOMArrayBuffer::create(m_arrayBufferCont
ents->at(index)); |
| 2173 v8::Isolate* isolate = m_reader.scriptState()->isolate(); |
| 2174 v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context
()->Global(); |
| 2175 result = toV8Object(buffer.get(), creationContext, isolate); |
| 2176 m_arrayBuffers[index] = result; |
| 2177 } |
| 2178 *object = result; |
| 2179 return true; |
| 2180 } |
| 2181 |
| 2182 bool Deserializer::tryGetObjectFromObjectReference(uint32_t reference, v8::Handl
e<v8::Value>* object) |
| 2183 { |
| 2184 if (reference >= m_objectPool.size()) |
| 2185 return false; |
| 2186 *object = m_objectPool[reference]; |
| 2187 return object; |
| 2188 } |
| 2189 |
| 2190 uint32_t Deserializer::objectReferenceCount() |
| 2191 { |
| 2192 return m_objectPool.size(); |
| 2193 } |
| 2194 |
| 2195 bool Deserializer::initializeObject(v8::Handle<v8::Object> object, uint32_t numP
roperties, v8::Handle<v8::Value>* value) |
| 2196 { |
| 2197 unsigned length = 2 * numProperties; |
| 2198 if (length > stackDepth()) |
| 2199 return false; |
| 2200 for (unsigned i = stackDepth() - length; i < stackDepth(); i += 2) { |
| 2201 v8::Local<v8::Value> propertyName = element(i); |
| 2202 v8::Local<v8::Value> propertyValue = element(i + 1); |
| 2203 object->Set(propertyName, propertyValue); |
| 2204 } |
| 2205 pop(length); |
| 2206 *value = object; |
| 2207 return true; |
| 2208 } |
| 2209 |
| 2210 bool Deserializer::read(v8::Local<v8::Value>* value) |
| 2211 { |
| 2212 return m_reader.read(value, *this); |
| 2213 } |
| 2214 |
| 2215 bool Deserializer::doDeserialize() |
| 2216 { |
| 2217 v8::Local<v8::Value> value; |
| 2218 if (!read(&value)) |
| 2219 return false; |
| 2220 if (!value.IsEmpty()) |
| 2221 push(value); |
| 2222 return true; |
| 2223 } |
| 2224 |
| 2225 v8::Local<v8::Value> Deserializer::element(unsigned index) |
| 2226 { |
| 2227 ASSERT_WITH_SECURITY_IMPLICATION(index < m_stack.size()); |
| 2228 return m_stack[index]; |
| 2229 } |
| 2230 |
| 2231 void Deserializer::openComposite(const v8::Local<v8::Value>& object) |
| 2232 { |
| 2233 uint32_t newObjectReference = m_objectPool.size(); |
| 2234 m_openCompositeReferenceStack.append(newObjectReference); |
| 2235 m_objectPool.append(object); |
| 2236 } |
| 2237 |
| 2238 bool Deserializer::closeComposite(v8::Handle<v8::Value>* object) |
| 2239 { |
| 2240 if (!m_openCompositeReferenceStack.size()) |
| 2241 return false; |
| 2242 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe
renceStack.size() - 1]; |
| 2243 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
1); |
| 2244 if (objectReference >= m_objectPool.size()) |
| 2245 return false; |
| 2246 *object = m_objectPool[objectReference]; |
| 2247 return true; |
| 2248 } |
| 2249 |
| 2250 } // SerializedScriptValueInternal |
| 2251 |
| 2252 } // namespace blink |
OLD | NEW |