Bug 902271 - Make StorageInputStream serializable cross-process. r=bent
☠☠ backed out by 08e0f1a9d9fa ☠ ☠
authorJosh Matthews <josh@joshmatthews.net>
Tue, 05 Nov 2013 18:44:21 -0500
changeset 162150 629aa51ebfafffa7c7c4d52bb247fe7867bd2f54
parent 162149 42ac1de2e3f78f7dd864af478a07f516398495bd
child 162151 a61b0a3f2d60c32d5b8d2c949f43bf49c7e0cd32
push id4184
push useremorley@mozilla.com
push dateMon, 06 Jan 2014 12:54:23 +0000
treeherderfx-team@93fe56269382 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs902271
milestone29.0a1
Bug 902271 - Make StorageInputStream serializable cross-process. r=bent
content/base/test/unit/test_xhr_document.js
content/base/test/unit/xpcshell.ini
content/base/test/unit_ipc/test_xhr_document_ipc.js
content/base/test/unit_ipc/xpcshell.ini
xpcom/io/nsStorageStream.cpp
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit/test_xhr_document.js
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+
+var server = new HttpServer();
+server.start(-1);
+
+var docbody = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body></body></html>';
+
+function handler(metadata, response) {
+  let body = NetUtil.readInputStreamToString(metadata.bodyInputStream,
+                                             metadata.bodyInputStream.available());
+  response.setStatusLine(metadata.httpVersion, 200, "OK");
+  response.write(body, body.length);
+}
+
+function run_test() {
+  do_test_pending();
+  server.registerPathHandler("/foo", handler);
+
+  var parser = Cc["@mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
+  parser.init();
+  let doc = parser.parseFromString(docbody, "text/html");
+  let xhr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1'].createInstance(Ci.nsIXMLHttpRequest);
+  xhr.onload = function() {
+    do_check_eq(xhr.responseText, docbody);
+    server.stop(do_test_finished);
+  };
+  xhr.onerror = function() {
+    do_check_false(false);
+    server.stop(do_test_finished);
+  };
+  xhr.open("POST", "http://localhost:" + server.identity.primaryPort + "/foo", true);
+  xhr.send(doc);
+}
--- a/content/base/test/unit/xpcshell.ini
+++ b/content/base/test/unit/xpcshell.ini
@@ -23,10 +23,11 @@ support-files =
 [test_bug553888.js]
 [test_bug558431.js]
 [test_bug737966.js]
 [test_csputils.js]
 [test_cspreports.js]
 [test_error_codes.js]
 run-sequentially = Hardcoded 4444 port.
 [test_thirdpartyutil.js]
+[test_xhr_document.js]
 [test_xhr_standalone.js]
 [test_xmlserializer.js]
new file mode 100644
--- /dev/null
+++ b/content/base/test/unit_ipc/test_xhr_document_ipc.js
@@ -0,0 +1,3 @@
+function run_test() {
+  run_test_in_child("../unit/test_xhr_document.js");
+}
--- a/content/base/test/unit_ipc/xpcshell.ini
+++ b/content/base/test/unit_ipc/xpcshell.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
 head =
 tail =
 
 [test_bug553888_wrap.js]
+[test_xhr_document_ipc.js]
--- a/xpcom/io/nsStorageStream.cpp
+++ b/xpcom/io/nsStorageStream.cpp
@@ -13,22 +13,27 @@
  */
 
 #include "nsAlgorithm.h"
 #include "nsStorageStream.h"
 #include "nsSegmentedBuffer.h"
 #include "nsStreamUtils.h"
 #include "nsCOMPtr.h"
 #include "nsIInputStream.h"
+#include "nsIIPCSerializableInputStream.h"
 #include "nsISeekableStream.h"
 #include "prlog.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MathAlgorithms.h"
 
+using mozilla::ipc::InputStreamParams;
+using mozilla::ipc::StringInputStreamParams;
+
 #if defined(PR_LOGGING)
 //
 // Log module for StorageStream logging...
 //
 // To enable logging (see prlog.h for full details):
 //
 //    set NSPR_LOG_MODULES=StorageStreamLog:5
 //    set NSPR_LOG_FILE=nspr.log
@@ -308,30 +313,32 @@ nsStorageStream::Seek(int32_t aPosition)
     return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 // There can be many nsStorageInputStreams for a single nsStorageStream
 class nsStorageInputStream MOZ_FINAL : public nsIInputStream
                                      , public nsISeekableStream
+                                     , public nsIIPCSerializableInputStream
 {
 public:
     nsStorageInputStream(nsStorageStream *aStorageStream, uint32_t aSegmentSize)
         : mStorageStream(aStorageStream), mReadCursor(0),
           mSegmentEnd(0), mSegmentNum(0),
           mSegmentSize(aSegmentSize), mLogicalCursor(0),
           mStatus(NS_OK)
 	{
         NS_ADDREF(mStorageStream);
 	}
 
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIINPUTSTREAM
     NS_DECL_NSISEEKABLESTREAM
+    NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
 
 private:
     ~nsStorageInputStream()
     {
         NS_IF_RELEASE(mStorageStream);
     }
 
 protected:
@@ -347,19 +354,20 @@ private:
     uint32_t         mSegmentSize;   // All segments, except the last, are of this size
     uint32_t         mLogicalCursor; // Logical offset into stream
     nsresult         mStatus;
 
     uint32_t SegNum(uint32_t aPosition)    {return aPosition >> mStorageStream->mSegmentSizeLog2;}
     uint32_t SegOffset(uint32_t aPosition) {return aPosition & (mSegmentSize - 1);}
 };
 
-NS_IMPL_ISUPPORTS2(nsStorageInputStream,
+NS_IMPL_ISUPPORTS3(nsStorageInputStream,
                    nsIInputStream,
-                   nsISeekableStream)
+                   nsISeekableStream,
+                   nsIIPCSerializableInputStream)
 
 NS_IMETHODIMP
 nsStorageStream::NewInputStream(int32_t aStartingOffset, nsIInputStream* *aInputStream)
 {
     if (NS_WARN_IF(!mSegmentedBuffer))
         return NS_ERROR_NOT_INITIALIZED;
 
     nsStorageInputStream *inputStream = new nsStorageInputStream(this, mSegmentSize);
@@ -518,16 +526,39 @@ nsStorageInputStream::Seek(uint32_t aPos
     mSegmentNum = SegNum(aPosition);
     mReadCursor = SegOffset(aPosition);
     uint32_t available = length - aPosition;
     mSegmentEnd = mReadCursor + XPCOM_MIN(mSegmentSize - mReadCursor, available);
     mLogicalCursor = aPosition;
     return NS_OK;
 }
 
+void
+nsStorageInputStream::Serialize(InputStreamParams& aParams)
+{
+    nsCString combined;
+    int32_t capacity = mStorageStream->mLastSegmentNum;
+    uint32_t offset = mReadCursor;
+    for (int32_t i = mSegmentNum; i <= capacity; i++) {
+        combined.Append(mStorageStream->mSegmentedBuffer->GetSegment(i) + offset);
+        offset = 0;
+    }
+
+    StringInputStreamParams params;
+    params.data() = combined;
+    aParams = params;
+}
+
+bool
+nsStorageInputStream::Deserialize(const InputStreamParams& aParams)
+{
+    NS_NOTREACHED("We should never attempt to deserialize a storage input stream.");
+    return false;
+}
+
 nsresult
 NS_NewStorageStream(uint32_t segmentSize, uint32_t maxSize, nsIStorageStream **result)
 {
     nsStorageStream* storageStream = new nsStorageStream();
     if (!storageStream) return NS_ERROR_OUT_OF_MEMORY;
     
     NS_ADDREF(storageStream);
     nsresult rv = storageStream->Init(segmentSize, maxSize);