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