Chromium Code Reviews| Index: Source/bindings/v8/SerializedScriptValue.cpp |
| diff --git a/Source/bindings/v8/SerializedScriptValue.cpp b/Source/bindings/v8/SerializedScriptValue.cpp |
| index d292d66c29773cf4d5418d30d5e607dce8c1ba3f..c9e373c0b2f9fa7d89741d869e0ec366e3b3c218 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,9 +200,9 @@ 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) |
| FileTag = 'f', // file:RawFile -> File (ref) |
| - DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref) |
| + DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref) |
| FileListTag = 'l', // length:uint32_t, files:RawFile[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; |
| @@ -458,6 +459,12 @@ public: |
| doWriteUint64(size); |
| } |
| + void writeBlob(int blobIndex) |
| + { |
| + append(BlobTag); |
| + doWriteUint32(blobIndex); |
| + } |
| + |
| void writeDOMFileSystem(int type, const String& name, const String& url) |
| { |
| append(DOMFileSystemTag); |
| @@ -472,6 +479,12 @@ public: |
| doWriteFile(file); |
| } |
| + void writeFile(int blobIndex) |
| + { |
| + append(FileTag); |
| + doWriteUint32(blobIndex); |
| + } |
| + |
| void writeFileList(const FileList& fileList) |
| { |
| append(FileListTag); |
| @@ -481,6 +494,16 @@ public: |
| doWriteFile(*fileList.item(i)); |
| } |
| + void writeFileList(const Vector<int>& blobIndices) |
| + { |
| + append(FileListTag); |
| + uint32_t length = blobIndices.size(); |
| + doWriteUint32(length); |
| + for (unsigned i = 0; i < length; ++i) { |
|
cmumford
2014/04/03 16:32:45
Nit: can ditch the braces in this for loop.
ericu
2014/04/07 23:14:20
Done.
|
| + doWriteUint32(blobIndices[i]); |
| + } |
| + } |
| + |
| bool writeCryptoKey(const blink::WebCryptoKey& key) |
| { |
| append(static_cast<uint8_t>(CryptoKeyTag)); |
| @@ -910,12 +933,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, Vector<blink::WebBlobInfo>* 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 +1283,14 @@ 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)) { |
| + ASSERT(blobIndex >= 0); |
|
cmumford
2014/04/03 16:32:45
What do you think about moving this ASSERT into wr
ericu
2014/04/07 23:14:20
Done.
|
| + m_writer.writeBlob(blobIndex); |
| + } else { |
| + m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); |
| + } |
| return 0; |
| } |
| @@ -1282,8 +1312,14 @@ 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.writeFile(blobIndex); |
| + } else { |
| + m_writer.writeFile(*file); |
| + } |
| return 0; |
| } |
| @@ -1292,10 +1328,25 @@ private: |
| FileList* fileList = V8FileList::toNative(value.As<v8::Object>()); |
| if (!fileList) |
| return; |
| - m_writer.writeFileList(*fileList); |
| 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; |
| + bool useBlobIndices = false; |
|
cmumford
2014/04/03 16:32:45
Do you need useBlobIndices, or can you instead use
ericu
2014/04/07 23:14:20
Switched to blobIndices.isEmpty().
|
| + for (unsigned i = 0; i < length; ++i) { |
| + int blobIndex = -1; |
| + const File* file = fileList->item(i); |
| + m_blobDataHandles.add(file->uuid(), file->blobDataHandle()); |
| + if (appendFileInfo(file->uuid(), file->path(), file->name(), file->type(), &blobIndex)) { |
|
cmumford
2014/04/03 16:32:45
In writeFile you call file->hasBeenClosed() and re
ericu
2014/04/07 23:14:20
No, it should be there; that's new stuff from a me
|
| + ASSERT(!i || useBlobIndices); |
| + ASSERT(blobIndex >= 0); |
| + useBlobIndices = true; |
| + blobIndices.append(blobIndex); |
| + } |
| + } |
| + if (useBlobIndices) { |
| + m_writer.writeFileList(blobIndices); |
| + } else { |
| + m_writer.writeFileList(*fileList); |
| + } |
| } |
| bool writeCryptoKey(v8::Handle<v8::Value> value) |
| @@ -1414,6 +1465,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 +1493,7 @@ private: |
| ObjectPool m_transferredMessagePorts; |
| ObjectPool m_transferredArrayBuffers; |
| uint32_t m_nextObjectReference; |
| + Vector<blink::WebBlobInfo>* m_blobInfo; |
| BlobDataHandleMap& m_blobDataHandles; |
| v8::Isolate* m_isolate; |
| }; |
| @@ -1543,12 +1613,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 Vector<blink::WebBlobInfo>* 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)); |
| @@ -2071,12 +2142,22 @@ private: |
| String uuid; |
| String type; |
| uint64_t size; |
| - if (!readWebCoreString(&uuid)) |
| - return false; |
| - if (!readWebCoreString(&type)) |
| - return false; |
| - if (!doReadUint64(&size)) |
| - return false; |
| + if (m_blobInfo) { |
| + uint32_t index; |
| + if (!doReadUint32(&index) || index >= m_blobInfo->size()) |
| + return false; |
| + const blink::WebBlobInfo& info = (*m_blobInfo)[index]; |
| + uuid = info.uuid(); |
| + type = info.type(); |
| + size = info.size(); |
| + } else { |
| + if (!readWebCoreString(&uuid)) |
| + return false; |
| + if (!readWebCoreString(&type)) |
| + return false; |
| + if (!doReadUint64(&size)) |
| + return false; |
| + } |
| RefPtrWillBeRawPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); |
| *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate); |
| return true; |
| @@ -2100,7 +2181,7 @@ private: |
| bool readFile(v8::Handle<v8::Value>* value) |
| { |
| - RefPtrWillBeRawPtr<File> file = doReadFileHelper(); |
| + RefPtrWillBeRawPtr<File> file = readFileHelper(); |
| if (!file) |
| return false; |
| *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate); |
| @@ -2116,7 +2197,7 @@ private: |
| return false; |
| RefPtrWillBeRawPtr<FileList> fileList = FileList::create(); |
| for (unsigned i = 0; i < length; ++i) { |
| - RefPtrWillBeRawPtr<File> file = doReadFileHelper(); |
| + RefPtrWillBeRawPtr<File> file = readFileHelper(); |
| if (!file) |
| return false; |
| fileList->append(file.release()); |
| @@ -2181,10 +2262,17 @@ private: |
| return true; |
| } |
| - PassRefPtrWillBeRawPtr<File> doReadFileHelper() |
| + PassRefPtr<File> readFileHelper() |
| { |
| if (m_version < 3) |
| return nullptr; |
| + if (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(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size()), info.lastModified(), info.size()); |
| + } |
| String path; |
| String name; |
| String relativePath; |
| @@ -2261,7 +2349,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 +2520,7 @@ private: |
| unsigned m_position; |
| uint32_t m_version; |
| v8::Isolate* m_isolate; |
| + const Vector<blink::WebBlobInfo>* m_blobInfo; |
| const BlobDataHandleMap& m_blobDataHandles; |
| }; |
| @@ -2674,19 +2763,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, Vector<blink::WebBlobInfo>* 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 +2899,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, Vector<blink::WebBlobInfo>* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate) |
| : m_externallyAllocatedMemory(0) |
| { |
| Writer writer; |
| @@ -2818,7 +2907,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 +2942,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 Vector<blink::WebBlobInfo>* blobInfo) |
| { |
| if (!m_data.impl()) |
| return v8::Null(isolate); |
| @@ -2866,7 +2955,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. |