OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "bindings/core/v8/ScriptValueSerializer.h" | 6 #include "bindings/core/v8/ScriptValueSerializer.h" |
7 | 7 |
8 #include "bindings/core/v8/V8ArrayBuffer.h" | 8 #include "bindings/core/v8/V8ArrayBuffer.h" |
9 #include "bindings/core/v8/V8ArrayBufferView.h" | 9 #include "bindings/core/v8/V8ArrayBufferView.h" |
10 #include "bindings/core/v8/V8Blob.h" | 10 #include "bindings/core/v8/V8Blob.h" |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu
ffer) | 244 void SerializedScriptValueWriter::writeArrayBuffer(const DOMArrayBuffer& arrayBu
ffer) |
245 { | 245 { |
246 append(ArrayBufferTag); | 246 append(ArrayBufferTag); |
247 doWriteArrayBuffer(arrayBuffer); | 247 doWriteArrayBuffer(arrayBuffer); |
248 } | 248 } |
249 | 249 |
250 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView&
arrayBufferView) | 250 void SerializedScriptValueWriter::writeArrayBufferView(const DOMArrayBufferView&
arrayBufferView) |
251 { | 251 { |
252 append(ArrayBufferViewTag); | 252 append(ArrayBufferViewTag); |
253 #if ENABLE(ASSERT) | 253 #if ENABLE(ASSERT) |
254 ASSERT(static_cast<const uint8_t*>(arrayBufferView.bufferBase()->data()) + a
rrayBufferView.byteOffset() == | 254 { |
255 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); | 255 ReftPtr<DOMArrayBuffer> buffer = arrayBufferView.bufferBaseOrNull(); |
| 256 ASSERT(buffer); |
| 257 ASSERT(static_cast<const uint8_t*>(buffer->data()) + arrayBufferView.byt
eOffset() == |
| 258 static_cast<const uint8_t*>(arrayBufferView.baseAddress())); |
| 259 } |
256 #endif | 260 #endif |
257 DOMArrayBufferView::ViewType type = arrayBufferView.type(); | 261 DOMArrayBufferView::ViewType type = arrayBufferView.type(); |
258 | 262 |
259 switch (type) { | 263 switch (type) { |
260 case DOMArrayBufferView::TypeInt8: | 264 case DOMArrayBufferView::TypeInt8: |
261 append(ByteArrayTag); | 265 append(ByteArrayTag); |
262 break; | 266 break; |
263 case DOMArrayBufferView::TypeUint8Clamped: | 267 case DOMArrayBufferView::TypeUint8Clamped: |
264 append(UnsignedByteClampedArrayTag); | 268 append(UnsignedByteClampedArrayTag); |
265 break; | 269 break; |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 { | 973 { |
970 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); | 974 v8::Local<v8::RegExp> regExp = value.As<v8::RegExp>(); |
971 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); | 975 m_writer.writeRegExp(regExp->GetSource(), regExp->GetFlags()); |
972 } | 976 } |
973 | 977 |
974 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer
View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) | 978 ScriptValueSerializer::StateBase* ScriptValueSerializer::writeAndGreyArrayBuffer
View(v8::Local<v8::Object> object, ScriptValueSerializer::StateBase* next) |
975 { | 979 { |
976 ASSERT(!object.IsEmpty()); | 980 ASSERT(!object.IsEmpty()); |
977 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); | 981 DOMArrayBufferView* arrayBufferView = V8ArrayBufferView::toImpl(object); |
978 if (!arrayBufferView) | 982 if (!arrayBufferView) |
979 return 0; | 983 return nullptr; |
980 if (!arrayBufferView->bufferBase()) | 984 if (!arrayBufferView->bufferBase()) |
981 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); | 985 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); |
982 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(),
m_scriptState->context()->Global(), isolate()); | 986 v8::Local<v8::Value> underlyingBuffer = toV8(arrayBufferView->bufferBase(),
m_scriptState->context()->Global(), isolate()); |
983 if (underlyingBuffer.IsEmpty()) | 987 if (underlyingBuffer.IsEmpty()) |
984 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); | 988 return handleError(DataCloneError, "An ArrayBuffer could not be cloned."
, next); |
985 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); | 989 StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); |
986 if (stateOut) | 990 if (stateOut) |
987 return stateOut; | 991 return stateOut; |
988 m_writer.writeArrayBufferView(*arrayBufferView); | 992 m_writer.writeArrayBufferView(*arrayBufferView); |
989 // This should be safe: we serialize something that we know to be a wrapper
(see | 993 // This should be safe: we serialize something that we know to be a wrapper
(see |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 uint32_t height; | 1529 uint32_t height; |
1526 uint32_t pixelDataLength; | 1530 uint32_t pixelDataLength; |
1527 if (!doReadUint32(&width)) | 1531 if (!doReadUint32(&width)) |
1528 return false; | 1532 return false; |
1529 if (!doReadUint32(&height)) | 1533 if (!doReadUint32(&height)) |
1530 return false; | 1534 return false; |
1531 if (!doReadUint32(&pixelDataLength)) | 1535 if (!doReadUint32(&pixelDataLength)) |
1532 return false; | 1536 return false; |
1533 if (m_position + pixelDataLength > m_length) | 1537 if (m_position + pixelDataLength > m_length) |
1534 return false; | 1538 return false; |
1535 ImageData* imageData = ImageData::create(IntSize(width, height)); | 1539 // TODO(junov): crbug.com/536816 |
| 1540 // Here we use a NonThorwableExceptionState in order to fail silently |
| 1541 // when ImageData allocation fails. It needs to be ascertained whether |
| 1542 // the call sites that depend on value deserialization agree with |
| 1543 // re-throwing a RangeError exception from here, which is what happens |
| 1544 // when the ArrayBuffer encapsulated in the ImageData fails to be |
| 1545 // allocated, as per the ECMAScript spec: |
| 1546 // http://ecma-international.org/ecma-262/6.0/#sec-createbytedatablock |
| 1547 // Before we decide to propagate the exception down to the script |
| 1548 // execution context, all the APIs that depend on this routine would |
| 1549 // need to have specifications stating that exceptions thrown by sub |
| 1550 // routines involved in the deserialization process are re-thrown. |
| 1551 NonThrowableExceptionState exceptionState; |
| 1552 ImageData* imageData = ImageData::create(IntSize(width, height), exceptionSt
ate); |
| 1553 if (exceptionState.hadException()) |
| 1554 return false; |
1536 DOMUint8ClampedArray* pixelArray = imageData->data(); | 1555 DOMUint8ClampedArray* pixelArray = imageData->data(); |
1537 ASSERT(pixelArray); | 1556 ASSERT(pixelArray); |
1538 ASSERT(pixelArray->length() >= pixelDataLength); | 1557 ASSERT(pixelArray->length() >= pixelDataLength); |
1539 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); | 1558 memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); |
1540 m_position += pixelDataLength; | 1559 m_position += pixelDataLength; |
1541 *value = toV8(imageData, m_scriptState->context()->Global(), isolate()); | 1560 *value = toV8(imageData, m_scriptState->context()->Global(), isolate()); |
1542 return !value->IsEmpty(); | 1561 return !value->IsEmpty(); |
1543 } | 1562 } |
1544 | 1563 |
1545 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu
e) | 1564 bool SerializedScriptValueReader::readCompositorProxy(v8::Local<v8::Value>* valu
e) |
(...skipping 12 matching lines...) Expand all Loading... |
1558 | 1577 |
1559 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBuffer() | 1578 PassRefPtr<DOMArrayBuffer> SerializedScriptValueReader::doReadArrayBuffer() |
1560 { | 1579 { |
1561 uint32_t byteLength; | 1580 uint32_t byteLength; |
1562 if (!doReadUint32(&byteLength)) | 1581 if (!doReadUint32(&byteLength)) |
1563 return nullptr; | 1582 return nullptr; |
1564 if (m_position + byteLength > m_length) | 1583 if (m_position + byteLength > m_length) |
1565 return nullptr; | 1584 return nullptr; |
1566 const void* bufferStart = m_buffer + m_position; | 1585 const void* bufferStart = m_buffer + m_position; |
1567 m_position += byteLength; | 1586 m_position += byteLength; |
1568 return DOMArrayBuffer::create(bufferStart, byteLength); | 1587 // TODO(junov): crbug.com/536816 |
| 1588 // Should use createOrNull to avoid crashing. |
| 1589 // To do that, we need to make sure that call sites of readArrayBuffer |
| 1590 // would react correctly in this case, with 'value' not having been set. |
| 1591 return DOMArrayBuffer::deprecatedCreateOrCrash(bufferStart, byteLength); |
1569 } | 1592 } |
1570 | 1593 |
1571 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) | 1594 bool SerializedScriptValueReader::readArrayBuffer(v8::Local<v8::Value>* value) |
1572 { | 1595 { |
1573 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBuffer(); | 1596 RefPtr<DOMArrayBuffer> arrayBuffer = doReadArrayBuffer(); |
1574 if (!arrayBuffer) | |
1575 return false; | |
1576 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso
late()); | 1597 *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), iso
late()); |
1577 return !value->IsEmpty(); | 1598 return !value->IsEmpty(); |
1578 } | 1599 } |
1579 | 1600 |
1580 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu
e, ScriptValueCompositeCreator& creator) | 1601 bool SerializedScriptValueReader::readArrayBufferView(v8::Local<v8::Value>* valu
e, ScriptValueCompositeCreator& creator) |
1581 { | 1602 { |
1582 ArrayBufferViewSubTag subTag; | 1603 ArrayBufferViewSubTag subTag; |
1583 uint32_t byteOffset; | 1604 uint32_t byteOffset; |
1584 uint32_t byteLength; | 1605 uint32_t byteLength; |
1585 RefPtr<DOMArrayBufferBase> arrayBuffer; | 1606 RefPtr<DOMArrayBufferBase> arrayBuffer; |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2157 return false; | 2178 return false; |
2158 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe
renceStack.size() - 1]; | 2179 uint32_t objectReference = m_openCompositeReferenceStack[m_openCompositeRefe
renceStack.size() - 1]; |
2159 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
1); | 2180 m_openCompositeReferenceStack.shrink(m_openCompositeReferenceStack.size() -
1); |
2160 if (objectReference >= m_objectPool.size()) | 2181 if (objectReference >= m_objectPool.size()) |
2161 return false; | 2182 return false; |
2162 *object = m_objectPool[objectReference]; | 2183 *object = m_objectPool[objectReference]; |
2163 return true; | 2184 return true; |
2164 } | 2185 } |
2165 | 2186 |
2166 } // namespace blink | 2187 } // namespace blink |
OLD | NEW |