| Index: Source/bindings/v8/SerializedScriptValue.cpp
|
| diff --git a/Source/bindings/v8/SerializedScriptValue.cpp b/Source/bindings/v8/SerializedScriptValue.cpp
|
| index 7de88cbe5d9bb862f7bb978d6dbc55729868a72b..7ba4d063bdfb5e93dbe21c6c30027b27f57fe2d4 100644
|
| --- a/Source/bindings/v8/SerializedScriptValue.cpp
|
| +++ b/Source/bindings/v8/SerializedScriptValue.cpp
|
| @@ -65,6 +65,7 @@
|
| #include "heap/Handle.h"
|
| #include "platform/SharedBuffer.h"
|
| #include "public/platform/Platform.h"
|
| +#include "public/platform/WebBlobInfo.h"
|
| #include "public/platform/WebCrypto.h"
|
| #include "public/platform/WebCryptoKey.h"
|
| #include "public/platform/WebCryptoKeyAlgorithm.h"
|
| @@ -199,10 +200,13 @@ enum SerializationTag {
|
| DateTag = 'D', // value:double -> Date (ref)
|
| MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort.
|
| NumberTag = 'N', // value:double -> Number
|
| - BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
|
| + BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref)
|
| + BlobIndexTag = 'i', // index:int32_t -> Blob (ref)
|
| FileTag = 'f', // file:RawFile -> File (ref)
|
| - DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref)
|
| + FileIndexTag = 'e', // index:int32_t -> File (ref)
|
| + DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref)
|
| FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
|
| + FileListIndexTag = 'L', // length:uint32_t, files:int32_t[length] -> FileList (ref)
|
| ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
|
| ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
|
| // fills it with the last numProperties name,value pairs pushed onto the deserialization stack
|
| @@ -458,6 +462,13 @@ public:
|
| doWriteUint64(size);
|
| }
|
|
|
| + void writeBlobIndex(int blobIndex)
|
| + {
|
| + ASSERT(blobIndex >= 0);
|
| + append(BlobIndexTag);
|
| + doWriteUint32(blobIndex);
|
| + }
|
| +
|
| void writeDOMFileSystem(int type, const String& name, const String& url)
|
| {
|
| append(DOMFileSystemTag);
|
| @@ -472,6 +483,12 @@ public:
|
| doWriteFile(file);
|
| }
|
|
|
| + void writeFileIndex(int blobIndex)
|
| + {
|
| + append(FileIndexTag);
|
| + doWriteUint32(blobIndex);
|
| + }
|
| +
|
| void writeFileList(const FileList& fileList)
|
| {
|
| append(FileListTag);
|
| @@ -481,6 +498,15 @@ public:
|
| doWriteFile(*fileList.item(i));
|
| }
|
|
|
| + void writeFileListIndex(const Vector<int>& blobIndices)
|
| + {
|
| + append(FileListIndexTag);
|
| + uint32_t length = blobIndices.size();
|
| + doWriteUint32(length);
|
| + for (unsigned i = 0; i < length; ++i)
|
| + doWriteUint32(blobIndices[i]);
|
| + }
|
| +
|
| bool writeCryptoKey(const blink::WebCryptoKey& key)
|
| {
|
| append(static_cast<uint8_t>(CryptoKeyTag));
|
| @@ -910,12 +936,13 @@ public:
|
| JSException
|
| };
|
|
|
| - Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
|
| + Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
|
| : m_writer(writer)
|
| , m_tryCatch(tryCatch)
|
| , m_depth(0)
|
| , m_status(Success)
|
| , m_nextObjectReference(0)
|
| + , m_blobInfo(blobInfo)
|
| , m_blobDataHandles(blobDataHandles)
|
| , m_isolate(isolate)
|
| {
|
| @@ -1259,8 +1286,12 @@ private:
|
| return 0;
|
| if (blob->hasBeenClosed())
|
| return handleError(DataCloneError, "A Blob object has been closed, and could therefore not be cloned.", next);
|
| - m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
|
| + int blobIndex = -1;
|
| m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle());
|
| + if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex))
|
| + m_writer.writeBlobIndex(blobIndex);
|
| + else
|
| + m_writer.writeBlob(blob->uuid(), blob->type(), blob->size());
|
| return 0;
|
| }
|
|
|
| @@ -1282,20 +1313,41 @@ private:
|
| return 0;
|
| if (file->hasBeenClosed())
|
| return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
|
| - m_writer.writeFile(*file);
|
| + int blobIndex = -1;
|
| m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
|
| + if (appendFileInfo(file->uuid(), file->path(), file->name(), file->type(), &blobIndex)) {
|
| + ASSERT(blobIndex >= 0);
|
| + m_writer.writeFileIndex(blobIndex);
|
| + } else {
|
| + m_writer.writeFile(*file);
|
| + }
|
| return 0;
|
| }
|
|
|
| - void writeFileList(v8::Handle<v8::Value> value)
|
| + StateBase* writeFileList(v8::Handle<v8::Value> value, StateBase* next)
|
| {
|
| FileList* fileList = V8FileList::toNative(value.As<v8::Object>());
|
| if (!fileList)
|
| - return;
|
| - m_writer.writeFileList(*fileList);
|
| + return 0;
|
| unsigned length = fileList->length();
|
| - for (unsigned i = 0; i < length; ++i)
|
| - m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle());
|
| + Vector<int> blobIndices;
|
| + for (unsigned i = 0; i < length; ++i) {
|
| + int blobIndex = -1;
|
| + const File* file = fileList->item(i);
|
| + if (file->hasBeenClosed())
|
| + return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next);
|
| + m_blobDataHandles.add(file->uuid(), file->blobDataHandle());
|
| + if (appendFileInfo(file->uuid(), file->path(), file->name(), file->type(), &blobIndex)) {
|
| + ASSERT(!i || blobIndex > 0);
|
| + ASSERT(blobIndex >= 0);
|
| + blobIndices.append(blobIndex);
|
| + }
|
| + }
|
| + if (!blobIndices.isEmpty())
|
| + m_writer.writeFileListIndex(blobIndices);
|
| + else
|
| + m_writer.writeFileList(*fileList);
|
| + return 0;
|
| }
|
|
|
| bool writeCryptoKey(v8::Handle<v8::Value> value)
|
| @@ -1414,6 +1466,24 @@ private:
|
| m_objectPool.set(object, objectReference);
|
| }
|
|
|
| + bool appendBlobInfo(const String& uuid, const String& type, unsigned long long size, int* index)
|
| + {
|
| + if (!m_blobInfo)
|
| + return false;
|
| + *index = m_blobInfo->size();
|
| + m_blobInfo->append(blink::WebBlobInfo(uuid, type, size));
|
| + return true;
|
| + }
|
| +
|
| + bool appendFileInfo(const String& uuid, const String& filePath, const String& fileName, const String& type, int* index)
|
| + {
|
| + if (!m_blobInfo)
|
| + return false;
|
| + *index = m_blobInfo->size();
|
| + m_blobInfo->append(blink::WebBlobInfo(uuid, filePath, fileName, type));
|
| + return true;
|
| + }
|
| +
|
| Writer& m_writer;
|
| v8::TryCatch& m_tryCatch;
|
| int m_depth;
|
| @@ -1424,6 +1494,7 @@ private:
|
| ObjectPool m_transferredMessagePorts;
|
| ObjectPool m_transferredArrayBuffers;
|
| uint32_t m_nextObjectReference;
|
| + WebBlobInfoArray* m_blobInfo;
|
| BlobDataHandleMap& m_blobDataHandles;
|
| v8::Isolate* m_isolate;
|
| };
|
| @@ -1500,7 +1571,7 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
|
| else if (V8DOMFileSystem::hasInstance(value, m_isolate))
|
| return writeDOMFileSystem(value, next);
|
| else if (V8FileList::hasInstance(value, m_isolate))
|
| - writeFileList(value);
|
| + return writeFileList(value, next);
|
| else if (V8Key::hasInstance(value, m_isolate)) {
|
| if (!writeCryptoKey(value))
|
| return handleError(DataCloneError, "Couldn't serialize key data", next);
|
| @@ -1543,12 +1614,13 @@ public:
|
| // restoring information about saved objects of composite types.
|
| class Reader {
|
| public:
|
| - Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const BlobDataHandleMap& blobDataHandles)
|
| + Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles)
|
| : m_buffer(buffer)
|
| , m_length(length)
|
| , m_position(0)
|
| , m_version(0)
|
| , m_isolate(isolate)
|
| + , m_blobInfo(blobInfo)
|
| , m_blobDataHandles(blobDataHandles)
|
| {
|
| ASSERT(!(reinterpret_cast<size_t>(buffer) & 1));
|
| @@ -1638,12 +1710,14 @@ public:
|
| creator.pushObjectReference(*value);
|
| break;
|
| case BlobTag:
|
| - if (!readBlob(value))
|
| + case BlobIndexTag:
|
| + if (!readBlob(value, tag == BlobIndexTag))
|
| return false;
|
| creator.pushObjectReference(*value);
|
| break;
|
| case FileTag:
|
| - if (!readFile(value))
|
| + case FileIndexTag:
|
| + if (!readFile(value, tag == FileIndexTag))
|
| return false;
|
| creator.pushObjectReference(*value);
|
| break;
|
| @@ -1653,7 +1727,8 @@ public:
|
| creator.pushObjectReference(*value);
|
| break;
|
| case FileListTag:
|
| - if (!readFileList(value))
|
| + case FileListIndexTag:
|
| + if (!readFileList(value, tag == FileListIndexTag))
|
| return false;
|
| creator.pushObjectReference(*value);
|
| break;
|
| @@ -2064,20 +2139,34 @@ private:
|
| return true;
|
| }
|
|
|
| - bool readBlob(v8::Handle<v8::Value>* value)
|
| + bool readBlob(v8::Handle<v8::Value>* value, bool isIndexed)
|
| {
|
| if (m_version < 3)
|
| return false;
|
| - String uuid;
|
| - String type;
|
| - uint64_t size;
|
| - if (!readWebCoreString(&uuid))
|
| - return false;
|
| - if (!readWebCoreString(&type))
|
| - return false;
|
| - if (!doReadUint64(&size))
|
| - return false;
|
| - RefPtrWillBeRawPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
|
| + RefPtrWillBeRawPtr<Blob> blob;
|
| + if (isIndexed) {
|
| + if (m_version < 6)
|
| + return false;
|
| + ASSERT(m_blobInfo);
|
| + uint32_t index;
|
| + if (!doReadUint32(&index) || index >= m_blobInfo->size())
|
| + return false;
|
| + const blink::WebBlobInfo& info = (*m_blobInfo)[index];
|
| + blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
|
| + } else {
|
| + ASSERT(!m_blobInfo);
|
| + String uuid;
|
| + String type;
|
| + uint64_t size;
|
| + ASSERT(!m_blobInfo);
|
| + if (!readWebCoreString(&uuid))
|
| + return false;
|
| + if (!readWebCoreString(&type))
|
| + return false;
|
| + if (!doReadUint64(&size))
|
| + return false;
|
| + blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size));
|
| + }
|
| *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate);
|
| return true;
|
| }
|
| @@ -2098,16 +2187,23 @@ private:
|
| return true;
|
| }
|
|
|
| - bool readFile(v8::Handle<v8::Value>* value)
|
| + bool readFile(v8::Handle<v8::Value>* value, bool isIndexed)
|
| {
|
| - RefPtrWillBeRawPtr<File> file = doReadFileHelper();
|
| + RefPtrWillBeRawPtr<File> file;
|
| + if (isIndexed) {
|
| + if (m_version < 6)
|
| + return false;
|
| + file = readFileIndexHelper();
|
| + } else {
|
| + file = readFileHelper();
|
| + }
|
| if (!file)
|
| return false;
|
| *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate);
|
| return true;
|
| }
|
|
|
| - bool readFileList(v8::Handle<v8::Value>* value)
|
| + bool readFileList(v8::Handle<v8::Value>* value, bool isIndexed)
|
| {
|
| if (m_version < 3)
|
| return false;
|
| @@ -2116,7 +2212,14 @@ private:
|
| return false;
|
| RefPtrWillBeRawPtr<FileList> fileList = FileList::create();
|
| for (unsigned i = 0; i < length; ++i) {
|
| - RefPtrWillBeRawPtr<File> file = doReadFileHelper();
|
| + RefPtrWillBeRawPtr<File> file;
|
| + if (isIndexed) {
|
| + if (m_version < 6)
|
| + return false;
|
| + file = readFileIndexHelper();
|
| + } else {
|
| + file = readFileHelper();
|
| + }
|
| if (!file)
|
| return false;
|
| fileList->append(file.release());
|
| @@ -2181,10 +2284,11 @@ private:
|
| return true;
|
| }
|
|
|
| - PassRefPtrWillBeRawPtr<File> doReadFileHelper()
|
| + PassRefPtrWillBeRawPtr<File> readFileHelper()
|
| {
|
| if (m_version < 3)
|
| return nullptr;
|
| + ASSERT(!m_blobInfo);
|
| String path;
|
| String name;
|
| String relativePath;
|
| @@ -2214,6 +2318,18 @@ private:
|
| return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type));
|
| }
|
|
|
| + PassRefPtrWillBeRawPtr<File> readFileIndexHelper()
|
| + {
|
| + if (m_version < 3)
|
| + return nullptr;
|
| + ASSERT(m_blobInfo);
|
| + uint32_t index;
|
| + if (!doReadUint32(&index) || index >= m_blobInfo->size())
|
| + return nullptr;
|
| + const blink::WebBlobInfo& info = (*m_blobInfo)[index];
|
| + return File::create(info.filePath(), info.fileName(), info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()));
|
| + }
|
| +
|
| template<class T>
|
| bool doReadUintHelper(T* value)
|
| {
|
| @@ -2261,7 +2377,7 @@ private:
|
| // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered
|
| // when passing ssv's around cross process. At present, we get 'lucky' in some cases because
|
| // the blob in the src process happens to still exist at the time the dest process is deserializing.
|
| - // For example in sharedWorker.postMesssage(...).
|
| + // For example in sharedWorker.postMessage(...).
|
| BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid);
|
| if (it != m_blobDataHandles.end()) {
|
| // make assertions about type and size?
|
| @@ -2432,6 +2548,7 @@ private:
|
| unsigned m_position;
|
| uint32_t m_version;
|
| v8::Isolate* m_isolate;
|
| + const WebBlobInfoArray* m_blobInfo;
|
| const BlobDataHandleMap& m_blobDataHandles;
|
| };
|
|
|
| @@ -2674,19 +2791,19 @@ private:
|
|
|
| PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
|
| {
|
| - return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, exceptionState, isolate));
|
| + return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, 0, exceptionState, isolate));
|
| }
|
|
|
| PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
|
| {
|
| TrackExceptionState exceptionState;
|
| - return adoptRef(new SerializedScriptValue(value, 0, 0, exceptionState, isolate));
|
| + return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, isolate));
|
| }
|
|
|
| -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, ExceptionState& exceptionState, ScriptState* state)
|
| +PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, ScriptState* state)
|
| {
|
| ScriptScope scope(state);
|
| - return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, exceptionState, state->isolate()));
|
| + return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, blobInfo, exceptionState, state->isolate()));
|
| }
|
|
|
| PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
|
| @@ -2810,7 +2927,7 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu
|
| return contents.release();
|
| }
|
|
|
| -SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
|
| +SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate)
|
| : m_externallyAllocatedMemory(0)
|
| {
|
| Writer writer;
|
| @@ -2818,7 +2935,7 @@ SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, Messag
|
| String errorMessage;
|
| {
|
| v8::TryCatch tryCatch;
|
| - Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate);
|
| + Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, isolate);
|
| status = serializer.serialize(value);
|
| if (status == Serializer::JSException) {
|
| // If there was a JS exception thrown, re-throw it.
|
| @@ -2853,10 +2970,10 @@ SerializedScriptValue::SerializedScriptValue(const String& wireData)
|
|
|
| v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts)
|
| {
|
| - return deserialize(v8::Isolate::GetCurrent(), messagePorts);
|
| + return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0);
|
| }
|
|
|
| -v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts)
|
| +v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo)
|
| {
|
| if (!m_data.impl())
|
| return v8::Null(isolate);
|
| @@ -2866,7 +2983,7 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M
|
| // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The
|
| // information stored in m_data isn't even encoded in UTF-16. Instead,
|
| // unicode characters are encoded as UTF-8 with two code units per UChar.
|
| - Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles);
|
| + Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, blobInfo, m_blobDataHandles);
|
| Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get());
|
|
|
| // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed.
|
|
|