[Chromium] IndexedDB: Assertion failure when storing File objects
authorjsbell@chromium.org <jsbell@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Mar 2012 19:26:00 +0000 (19:26 +0000)
committerjsbell@chromium.org <jsbell@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 Mar 2012 19:26:00 +0000 (19:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=76746

Source/WebCore:

The blob data in Blob/File/FileList objects is serialized "by reference" (the
internal URL) rather than "by value" (the actual data); this is sufficient for
postMessage() but not for IndexedDB since the referenced data is not retained
Expose a mechanism to enumerate the URLs so that SSVs can be rejected by IDB
until blob data serialization can is implemented (outside the SSV mechanism, and
potentially asynchronously).

Also, correct issue in V8DOMWrapper::instantiateV8Object where context is assumed
to be a Worker context if it's not a Window, which is incorrect for the
Chromium utility process; this is hit if Blobs are not blocked.

Reviewed by Tony Chang.

Test: storage/indexeddb/noblobs.html

* Modules/indexeddb/IDBCursor.cpp:
(WebCore::IDBCursor::update): Reject SSVs that contain blob references.
* Modules/indexeddb/IDBObjectStore.cpp:
(WebCore::IDBObjectStore::add): Reject SSVs that contain blob references.
(WebCore::IDBObjectStore::put): Reject SSVs that contain blob references.
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):
(WebCore::CloneSerializer::CloneSerializer):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneSerializer::write):
(CloneSerializer):
(WebCore::SerializedScriptValue::SerializedScriptValue):
(WebCore::SerializedScriptValue::create):
(WebCore::SerializedScriptValue::undefinedValue):
(WebCore::SerializedScriptValue::booleanValue):
* bindings/js/SerializedScriptValue.h: New API to enable the clients to be picky.
* bindings/v8/SerializedScriptValue.cpp:
(WebCore::SerializedScriptValue::SerializedScriptValue):
* bindings/v8/SerializedScriptValue.h: New API to enable the clients to be picky.
(WebCore::SerializedScriptValue::blobURLs):
(SerializedScriptValue):
* bindings/v8/V8DOMWrapper.cpp:
(WebCore::V8DOMWrapper::instantiateV8Object):  Ensure context is a worker context before treating it as such.

LayoutTests:

Ensure that Blob/File/FileList types are rejected in IDB values, to detect regressions.

Reviewed by Tony Chang.

* storage/indexeddb/noblobs-expected.txt: Added.
* storage/indexeddb/noblobs.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@111044 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/noblobs-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/noblobs.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBCursor.cpp
Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/bindings/js/SerializedScriptValue.h
Source/WebCore/bindings/v8/SerializedScriptValue.cpp
Source/WebCore/bindings/v8/SerializedScriptValue.h
Source/WebCore/bindings/v8/V8DOMWrapper.cpp

index cfcba88..14fe21d 100644 (file)
@@ -1,3 +1,15 @@
+2012-03-16  Joshua Bell  <jsbell@chromium.org>
+
+        [Chromium] IndexedDB: Assertion failure when storing File objects
+        https://bugs.webkit.org/show_bug.cgi?id=76746
+
+        Ensure that Blob/File/FileList types are rejected in IDB values, to detect regressions.
+
+        Reviewed by Tony Chang.
+
+        * storage/indexeddb/noblobs-expected.txt: Added.
+        * storage/indexeddb/noblobs.html: Added.
+
 2012-03-16  Erik Arvidsson  <arv@chromium.org>
 
         [V8] Ensure that invalid syntax in inline event handlers does not cause a crash
diff --git a/LayoutTests/storage/indexeddb/noblobs-expected.txt b/LayoutTests/storage/indexeddb/noblobs-expected.txt
new file mode 100644 (file)
index 0000000..1865024
--- /dev/null
@@ -0,0 +1,82 @@
+
+Confirm Blob/File/FileList limitations of WebKit's IndexedDB implementation.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+PASS Boolean(indexedDB && IDBCursor && IDBDatabase && IDBDatabaseError && IDBDatabaseException && IDBFactory && IDBIndex && IDBKeyRange && IDBObjectStore && IDBRequest && IDBTransaction) is true
+
+
+Prepare Database
+indexedDB.deleteDatabase('noblobs')
+indexedDB.open('noblobs')
+db = request.result
+PASS db.version is ""
+db.setVersion('1')
+store = db.createObjectStore('storeName')
+store.put('value', 'key')
+
+testBlob():
+BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder
+PASS BlobBuilder != null is true
+PASS FileReader != null is true
+builder = new BlobBuilder()
+test_content = 'This is a test. This is only a test.'
+builder.append(test_content)
+blob = builder.getBlob()
+
+validateExceptions(blob):
+transaction = db.transaction('storeName', IDBTransaction.READ_WRITE)
+store = transaction.objectStore('storeName')
+Expecting exception from store.put(blob, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+Expecting exception from store.add(blob, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+request = store.openCursor()
+cursor = request.result
+Expecting exception from cursor.update(blob)
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+
+testFile():
+file = fileInput.files[0]
+
+validateExceptions(file):
+transaction = db.transaction('storeName', IDBTransaction.READ_WRITE)
+store = transaction.objectStore('storeName')
+Expecting exception from store.put(file, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+Expecting exception from store.add(file, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+request = store.openCursor()
+cursor = request.result
+Expecting exception from cursor.update(file)
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+
+testFileList():
+filelist = fileInput.files
+
+validateExceptions(filelist):
+transaction = db.transaction('storeName', IDBTransaction.READ_WRITE)
+store = transaction.objectStore('storeName')
+Expecting exception from store.put(filelist, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+Expecting exception from store.add(filelist, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+request = store.openCursor()
+cursor = request.result
+Expecting exception from cursor.update(filelist)
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/noblobs.html b/LayoutTests/storage/indexeddb/noblobs.html
new file mode 100644 (file)
index 0000000..99ced9b
--- /dev/null
@@ -0,0 +1,115 @@
+<html>
+<head>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="resources/shared.js"></script>
+</head>
+<body>
+<input type="file" id="fileInput" multiple></input>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+
+description("Confirm Blob/File/FileList limitations of WebKit's IndexedDB implementation.");
+// FIXME: This verifies that blob-type data is rejected for now, rather than silently failing.
+// Tracked for the Chromium port as: http://crbug.com/108012
+
+fileInput = document.getElementById("fileInput");
+if (window.eventSender) {
+    var fileRect = fileInput.getClientRects()[0];
+    var targetX = fileRect.left + fileRect.width / 2;
+    var targetY = fileRect.top + fileRect.height / 2;
+    eventSender.beginDragWithFiles(['resources/test-data.html', 'resources/test-data.txt']);
+    eventSender.mouseMoveTo(targetX, targetY);
+    eventSender.mouseUp();
+}
+
+function test()
+{
+    removeVendorPrefixes();
+    prepareDatabase();
+}
+
+function prepareDatabase()
+{
+    debug("");
+    debug("Prepare Database");
+    request = evalAndLog("indexedDB.deleteDatabase('noblobs')");
+    request.onerror = unexpectedErrorCallback;
+    request.onsuccess = function(e) {
+        request = evalAndLog("indexedDB.open('noblobs')");
+        request.onerror = unexpectedErrorCallback;
+        request.onsuccess = function(e) {
+            evalAndLog("db = request.result");
+            shouldBeEqualToString("db.version", "");
+            request = evalAndLog("db.setVersion('1')");
+            request.onerror = unexpectedErrorCallback;
+            request.onsuccess = function(e) {
+                evalAndLog("store = db.createObjectStore('storeName')");
+                evalAndLog("store.put('value', 'key')");
+                var trans = request.result;
+                trans.onerror = unexpectedErrorCallback;
+                trans.onabort = unexpectedAbortCallback;
+                trans.oncomplete = testBlob();
+            };
+        };
+    };
+}
+
+function testBlob()
+{
+    debug("");
+    debug("testBlob():");
+
+    evalAndLog("BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder");
+    shouldBeTrue("BlobBuilder != null");
+    shouldBeTrue("FileReader != null");
+    evalAndLog("builder = new BlobBuilder()");
+    evalAndLog("test_content = 'This is a test. This is only a test.'");
+    evalAndLog("builder.append(test_content)");
+    evalAndLog("blob = builder.getBlob()");
+    validateExceptions("blob", testFile);
+}
+
+function testFile()
+{
+    debug("");
+    debug("testFile():");
+    evalAndLog("file = fileInput.files[0]");
+    validateExceptions("file", testFileList);
+}
+
+function testFileList()
+{
+    debug("");
+    debug("testFileList():");
+    evalAndLog("filelist = fileInput.files");
+    validateExceptions("filelist", finishJSTest);
+}
+
+function validateExceptions(variable, onComplete)
+{
+    debug("");
+    debug("validateExceptions(" + variable + "):");
+    evalAndLog("transaction = db.transaction('storeName', IDBTransaction.READ_WRITE)");
+    evalAndLog("store = transaction.objectStore('storeName')");
+    evalAndExpectException("store.put(" + variable + ", 'key')", "DOMException.DATA_CLONE_ERR");
+    evalAndExpectException("store.add(" + variable + ", 'key')", "DOMException.DATA_CLONE_ERR");
+    evalAndLog("request = store.openCursor()");
+    request.onsuccess = function () {
+        evalAndLog("cursor = request.result");
+        evalAndExpectException("cursor.update(" + variable + ")", "DOMException.DATA_CLONE_ERR");
+    };
+    transaction.oncomplete = onComplete;
+}
+
+if (window.eventSender) {
+    test();
+} else {
+    alert("Select file(s) using the input control above to initiate the test");
+    document.getElementById("fileInput").onchange = test;
+}
+
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index 247cd97..1906d13 100644 (file)
@@ -1,3 +1,47 @@
+2012-03-16  Joshua Bell  <jsbell@chromium.org>
+
+        [Chromium] IndexedDB: Assertion failure when storing File objects
+        https://bugs.webkit.org/show_bug.cgi?id=76746
+
+        The blob data in Blob/File/FileList objects is serialized "by reference" (the
+        internal URL) rather than "by value" (the actual data); this is sufficient for
+        postMessage() but not for IndexedDB since the referenced data is not retained
+        Expose a mechanism to enumerate the URLs so that SSVs can be rejected by IDB
+        until blob data serialization can is implemented (outside the SSV mechanism, and
+        potentially asynchronously).
+
+        Also, correct issue in V8DOMWrapper::instantiateV8Object where context is assumed
+        to be a Worker context if it's not a Window, which is incorrect for the
+        Chromium utility process; this is hit if Blobs are not blocked.
+
+        Reviewed by Tony Chang.
+
+        Test: storage/indexeddb/noblobs.html
+
+        * Modules/indexeddb/IDBCursor.cpp:
+        (WebCore::IDBCursor::update): Reject SSVs that contain blob references.
+        * Modules/indexeddb/IDBObjectStore.cpp:
+        (WebCore::IDBObjectStore::add): Reject SSVs that contain blob references.
+        (WebCore::IDBObjectStore::put): Reject SSVs that contain blob references.
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::serialize):
+        (WebCore::CloneSerializer::CloneSerializer):
+        (WebCore::CloneSerializer::dumpIfTerminal):
+        (WebCore::CloneSerializer::write):
+        (CloneSerializer):
+        (WebCore::SerializedScriptValue::SerializedScriptValue):
+        (WebCore::SerializedScriptValue::create):
+        (WebCore::SerializedScriptValue::undefinedValue):
+        (WebCore::SerializedScriptValue::booleanValue):
+        * bindings/js/SerializedScriptValue.h: New API to enable the clients to be picky.
+        * bindings/v8/SerializedScriptValue.cpp:
+        (WebCore::SerializedScriptValue::SerializedScriptValue):
+        * bindings/v8/SerializedScriptValue.h: New API to enable the clients to be picky.
+        (WebCore::SerializedScriptValue::blobURLs):
+        (SerializedScriptValue):
+        * bindings/v8/V8DOMWrapper.cpp:
+        (WebCore::V8DOMWrapper::instantiateV8Object):  Ensure context is a worker context before treating it as such.
+
 2012-03-16  Erik Arvidsson  <arv@chromium.org>
 
         [V8] Ensure that invalid syntax in inline event handlers does not cause a crash
index e7a01ec..274f995 100644 (file)
@@ -91,9 +91,17 @@ IDBAny* IDBCursor::source() const
     return m_source.get();
 }
 
-PassRefPtr<IDBRequest> IDBCursor::update(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, ExceptionCode& ec)
+PassRefPtr<IDBRequest> IDBCursor::update(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, ExceptionCode& ec)
 {
     IDB_TRACE("IDBCursor::update");
+
+    RefPtr<SerializedScriptValue> value = prpValue;
+    if (value->blobURLs().size() > 0) {
+        // FIXME: Add Blob/File/FileList support
+        ec = DATA_CLONE_ERR;
+        return 0;
+    }
+
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->update(value, request, ec);
     if (ec) {
index 3a5a073..df926f4 100644 (file)
@@ -95,7 +95,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::get(ScriptExecutionContext* context, Pass
     return request.release();
 }
 
-PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, ExceptionCode& ec)
+PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     IDB_TRACE("IDBObjectStore::add");
     if (key && (key->type() == IDBKey::InvalidType)) {
@@ -103,6 +103,13 @@ PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, Pass
         return 0;
     }
 
+    RefPtr<SerializedScriptValue> value = prpValue;
+    if (value->blobURLs().size() > 0) {
+        // FIXME: Add Blob/File/FileList support
+        ec = DATA_CLONE_ERR;
+        return 0;
+    }
+
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->put(value, key, IDBObjectStoreBackendInterface::AddOnly, request, m_transaction->backend(), ec);
     if (ec) {
@@ -112,7 +119,7 @@ PassRefPtr<IDBRequest> IDBObjectStore::add(ScriptExecutionContext* context, Pass
     return request.release();
 }
 
-PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> key, ExceptionCode& ec)
+PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> key, ExceptionCode& ec)
 {
     IDB_TRACE("IDBObjectStore::put");
     if (key && (key->type() == IDBKey::InvalidType)) {
@@ -120,6 +127,13 @@ PassRefPtr<IDBRequest> IDBObjectStore::put(ScriptExecutionContext* context, Pass
         return 0;
     }
 
+    RefPtr<SerializedScriptValue> value = prpValue;
+    if (value->blobURLs().size() > 0) {
+        // FIXME: Add Blob/File/FileList support
+        ec = DATA_CLONE_ERR;
+        return 0;
+    }
+
     RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this), m_transaction.get());
     m_backend->put(value, key, IDBObjectStoreBackendInterface::AddOrUpdate, request, m_transaction->backend(), ec);
     if (ec) {
index e235945..96f0a81 100644 (file)
@@ -321,9 +321,9 @@ class CloneSerializer : CloneBase {
 public:
     static SerializationReturnCode serialize(ExecState* exec, JSValue value,
                                              MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
-                                             Vector<uint8_t>& out)
+                                             Vector<String>& blobURLs, Vector<uint8_t>& out)
     {
-        CloneSerializer serializer(exec, messagePorts, arrayBuffers, out);
+        CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out);
         return serializer.serialize(value);
     }
 
@@ -354,9 +354,10 @@ public:
 private:
     typedef HashMap<JSObject*, uint32_t> ObjectPool;
 
-    CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<uint8_t>& out)
+    CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out)
         : CloneBase(exec)
         , m_buffer(out)
+        , m_blobURLs(blobURLs)
         , m_emptyIdentifier(exec, UString("", 0))
     {
         write(CurrentVersion);
@@ -583,6 +584,7 @@ private:
             if (obj->inherits(&JSBlob::s_info)) {
                 write(BlobTag);
                 Blob* blob = toBlob(obj);
+                m_blobURLs.append(blob->url());
                 write(blob->url());
                 write(blob->type());
                 write(blob->size());
@@ -767,6 +769,7 @@ private:
 
     void write(const File* file)
     {
+        m_blobURLs.append(file->url());
         write(file->path());
         write(file->url());
         write(file->type());
@@ -778,6 +781,7 @@ private:
     }
 
     Vector<uint8_t>& m_buffer;
+    Vector<String>& m_blobURLs;
     ObjectPool m_objectPool;
     ObjectPool m_transferredMessagePorts;
     ObjectPool m_transferredArrayBuffers;
@@ -1662,10 +1666,17 @@ SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
     m_data.swap(buffer);
 }
 
-SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, PassOwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray)
+SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs)
+{
+    m_data.swap(buffer);
+    m_blobURLs.swap(blobURLs);
+}
+
+SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray)
     : m_arrayBufferContentsArray(arrayBufferContentsArray)
 {
     m_data.swap(buffer);
+    m_blobURLs.swap(blobURLs);
 }
 
 PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(
@@ -1703,7 +1714,8 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec,
                                                                 SerializationErrorMode throwExceptions)
 {
     Vector<uint8_t> buffer;
-    SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, buffer);
+    Vector<String> blobURLs;
+    SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer);
 
     OwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray;
 
@@ -1716,7 +1728,7 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec,
     if (!serializationDidCompleteSuccessfully(code))
         return 0;
 
-    return adoptRef(new SerializedScriptValue(buffer, arrayBufferContentsArray.release()));
+    return adoptRef(new SerializedScriptValue(buffer, blobURLs, arrayBufferContentsArray.release()));
 }
 
 PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
index 858e8c9..1a2de00 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef SerializedScriptValue_h
 #define SerializedScriptValue_h
 
+#include "PlatformString.h"
 #include "ScriptState.h"
 #include <heap/Strong.h>
 #include <runtime/JSValue.h>
@@ -92,6 +93,7 @@ public:
 #endif
 
     const Vector<uint8_t>& data() { return m_data; }
+    const Vector<String>& blobURLs() const { return m_blobURLs; }
 
 #if ENABLE(INDEXED_DATABASE)
     static PassRefPtr<SerializedScriptValue> create(JSC::ExecState*, JSC::JSValue);
@@ -108,11 +110,13 @@ private:
     static void maybeThrowExceptionIfSerializationFailed(JSC::ExecState*, SerializationReturnCode);
     static bool serializationDidCompleteSuccessfully(SerializationReturnCode);
     static PassOwnPtr<ArrayBufferContentsArray> transferArrayBuffers(ArrayBufferArray&, SerializationReturnCode&);
-    
+
     SerializedScriptValue(Vector<unsigned char>&);
-    SerializedScriptValue(Vector<unsigned char>&, PassOwnPtr<ArrayBufferContentsArray>);
+    SerializedScriptValue(Vector<unsigned char>&, Vector<String>& blobURLs);
+    SerializedScriptValue(Vector<unsigned char>&, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray>);
     Vector<unsigned char> m_data;
     OwnPtr<ArrayBufferContentsArray> m_arrayBufferContentsArray;
+    Vector<String> m_blobURLs;
 };
 
 }
index c6738cd..46db6d1 100644 (file)
@@ -606,13 +606,14 @@ public:
         JSFailure
     };
 
-    Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, v8::TryCatch& tryCatch)
+    Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, v8::TryCatch& tryCatch)
         : m_writer(writer)
         , m_tryCatch(tryCatch)
         , m_depth(0)
         , m_execDepth(0)
         , m_status(Success)
         , m_nextObjectReference(0)
+        , m_blobURLs(blobURLs)
     {
         ASSERT(!tryCatch.HasCaught());
         if (messagePorts) {
@@ -977,6 +978,7 @@ private:
         if (!blob)
             return;
         m_writer.writeBlob(blob->url().string(), blob->type(), blob->size());
+        m_blobURLs.append(blob->url().string());
     }
 
     void writeFile(v8::Handle<v8::Value> value)
@@ -985,6 +987,7 @@ private:
         if (!file)
             return;
         m_writer.writeFile(file->path(), file->url().string(), file->type());
+        m_blobURLs.append(file->url().string());
     }
 
     void writeFileList(v8::Handle<v8::Value> value)
@@ -993,6 +996,9 @@ private:
         if (!fileList)
             return;
         m_writer.writeFileList(*fileList);
+        unsigned length = fileList->length();
+        for (unsigned i = 0; i < length; ++i)
+            m_blobURLs.append(fileList->item(i)->url().string());
     }
 
     void writeImageData(v8::Handle<v8::Value> value)
@@ -1111,6 +1117,7 @@ private:
     ObjectPool m_transferredMessagePorts;
     ObjectPool m_transferredArrayBuffers;
     uint32_t m_nextObjectReference;
+    Vector<String>& m_blobURLs;
 };
 
 Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next)
@@ -2204,7 +2211,7 @@ SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value,
     Serializer::Status status;
     {
         v8::TryCatch tryCatch;
-        Serializer serializer(writer, messagePorts, arrayBuffers, tryCatch);
+        Serializer serializer(writer, messagePorts, arrayBuffers, m_blobURLs, tryCatch);
         status = serializer.serialize(value);
         if (status == Serializer::JSException) {
             // If there was a JS exception thrown, re-throw it.
index 68b1954..7f6b9e0 100644 (file)
@@ -80,6 +80,8 @@ public:
     ScriptValue deserializeForInspector(ScriptState*);
 #endif
 
+    const Vector<String>& blobURLs() const { return m_blobURLs; }
+
 private:
     enum StringDataMode {
         StringValue,
@@ -95,6 +97,7 @@ private:
 
     String m_data;
     OwnPtr<ArrayBufferContentsArray> m_arrayBufferContentsArray;
+    Vector<String> m_blobURLs;
 };
 
 } // namespace WebCore
index c995274..a3a41de 100644 (file)
@@ -216,7 +216,7 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, WrapperT
                     proxy = V8Proxy::retrieve(frame);
             }
 #if ENABLE(WORKERS)
-            else
+            else if (isWrapperOfType(globalPrototype, &V8WorkerContext::info))
                 workerContext = V8WorkerContext::toNative(lookupDOMWrapper(V8WorkerContext::GetTemplate(), context->Global()));
 #endif
         }