Bug 482310. Add a JS api to asynchronously copy data to an output stream. r+sr=bsmedberg.
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 07 May 2009 15:21:54 -0400
changeset 28080 55339f8d68fa5fcae6dffe4bb538e5345afee9b8
parent 28079 6aa0cb2a52fb28ddc616b4c0ecb910e26c8d83c4
child 28081 135d7cdcd7838e83941bfba1589e364169e30c4f
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs482310
milestone1.9.2a1pre
Bug 482310. Add a JS api to asynchronously copy data to an output stream. r+sr=bsmedberg.
netwerk/base/src/Makefile.in
netwerk/base/src/NetUtil.jsm
netwerk/test/unit/test_localstreams.js
xpcom/build/nsXPCOMCID.h
xpcom/build/nsXPComInit.cpp
xpcom/io/Makefile.in
xpcom/io/nsIIOUtil.idl
xpcom/io/nsIOUtil.cpp
xpcom/io/nsIOUtil.h
xpcom/tests/unit/test_ioutil.js
xpcom/tests/unit/test_stringstream.js
--- a/netwerk/base/src/Makefile.in
+++ b/netwerk/base/src/Makefile.in
@@ -115,15 +115,19 @@ else
 endif
 endif
 endif
 
 EXTRA_COMPONENTS = \
 		$(srcdir)/nsProxyAutoConfig.js \
 		$(NULL)
 
+EXTRA_JS_MODULES = \
+		NetUtil.jsm \
+		$(NULL)
+
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -DIMPL_NS_NET
new file mode 100644
--- /dev/null
+++ b/netwerk/base/src/NetUtil.jsm
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *    Boris Zbarsky <bzbarsky@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/***
+ * Necko utilities
+ */
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+var NetUtil = {
+    /**
+     * Function to perform simple async copying from aSource (an input stream)
+     * to aSink (an output stream).  The copy will happen on some background
+     * thread.  Both streams will be closed when the copy completes.
+     *
+     * @param aSource the input stream to read from
+     * @param aSink the output stream to write to
+     * @param aCallback [optional] a function that will be called at copy
+     *        completion with a single argument: the nsresult status code for
+     *        the copy operation.
+     *
+     * @return an nsIRequest representing the copy operation (for example, this
+     *         can be used to cancel the copying).  The consumer can ignore the
+     *         return value if desired.
+     */
+    asyncCopy: function _asyncCopy(aSource, aSink, aCallback) {
+        if (!aSource || !aSink) {
+            throw "Must have a source and a sink";
+        }
+
+        const ioUtil = Cc["@mozilla.org/io-util;1"].getService(Ci.nsIIOUtil);
+        var sourceBuffered = ioUtil.inputStreamIsBuffered(aSource);
+        var sinkBuffered = ioUtil.outputStreamIsBuffered(aSink);
+
+        if (!sourceBuffered && !sinkBuffered) {
+            // wrap the sink in a buffered stream.
+            var bostream = Cc["@mozilla.org/network/buffered-output-stream;1"].
+                createInstance(Ci.nsIBufferedOutputStream);
+            bostream.init(aSink, 0x8000);
+            sinkBuffered = true;
+        }
+
+        // make a stream copier
+        var copier = Cc["@mozilla.org/network/async-stream-copier;1"].
+            createInstance(Ci.nsIAsyncStreamCopier);
+
+        // Initialize the copier.  The 0x8000 should match the size of the
+        // buffer our buffered stream is using, for best performance.  If we're
+        // not using our own buffered stream, that's ok too.  But maybe we
+        // should just use the default net segment size here?
+        copier.init(aSource, bostream, null, sourceBuffered, sinkBuffered,
+                    0x8000, true, true);
+
+        var observer;
+        if (aCallback) {
+            observer = {
+            onStartRequest: function(aRequest, aContext) {},
+            onStopRequest: function(aRequest, aContext, aStatusCode) {
+              aCallback(aStatusCode);
+            }
+        } else {
+            observer = null;
+        }
+
+        // start the copying
+        copier.asyncCopy(observer, null);
+        return copier;
+    }
+};
--- a/netwerk/test/unit/test_localstreams.js
+++ b/netwerk/test/unit/test_localstreams.js
@@ -9,16 +9,22 @@ function getDir(key) {
 }
 
 // Does some sanity checks on the stream and returns the number of bytes read
 // when the checks passed.
 function test_stream(stream) {
   // This test only handles blocking streams; that's desired for file streams
   // anyway.
   do_check_eq(stream.isNonBlocking(), false);
+
+  // Check that the stream is not buffered
+  do_check_eq(Components.classes["@mozilla.org/io-util;1"]
+                         .getService(Components.interfaces.nsIIOUtil)
+                         .inputStreamIsBuffered(stream),
+              false);
   
   // Wrap it in a binary stream (to avoid wrong results that
   // scriptablestream would produce with binary content)
   var binstream = Components.classes['@mozilla.org/binaryinputstream;1']
                             .createInstance(Components.interfaces.nsIBinaryInputStream);
   binstream.setInputStream(stream);
 
   var numread = 0;
--- a/xpcom/build/nsXPCOMCID.h
+++ b/xpcom/build/nsXPCOMCID.h
@@ -87,16 +87,22 @@
 /**
  * Observer Service ContractID
  * The observer service implements the global nsIObserverService object.
  * It should be used from the main thread only.
  */
 #define NS_OBSERVERSERVICE_CONTRACTID "@mozilla.org/observer-service;1"
 
 /**
+ * IO utilities service contract id.
+ * This guarantees implementation of nsIIOUtil.  Usable from any thread.
+ */
+#define NS_IOUTIL_CONTRACTID "@mozilla.org/io-util;1"
+
+/**
  * The following are the CIDs and Contract IDs of the nsISupports wrappers for 
  * primative types.  
  */
 #define NS_SUPPORTS_ID_CID \
 { 0xacf8dc40, 0x4a25, 0x11d3, \
 { 0x98, 0x90, 0x0, 0x60, 0x8, 0x96, 0x24, 0x22 } }
 #define NS_SUPPORTS_ID_CONTRACTID "@mozilla.org/supports-id;1"
 
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -116,16 +116,18 @@ NS_DECL_CLASSINFO(nsStringInputStream)
 
 #include "nsHashPropertyBag.h"
 
 #include "nsUnicharInputStream.h"
 #include "nsVariant.h"
 
 #include "nsUUIDGenerator.h"
 
+#include "nsIOUtil.h"
+
 #ifdef GC_LEAK_DETECTOR
 #include "nsLeakDetector.h"
 #endif
 #include "nsRecyclingAllocator.h"
 
 #include "SpecialSystemDirectory.h"
 
 #if defined(XP_WIN)
@@ -230,16 +232,18 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsUU
 #ifdef XP_MACOSX
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUtilsImpl)
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemInfo, Init)
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMemoryReporterManager)
 
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsIOUtil)
+
 static NS_METHOD
 nsThreadManagerGetSingleton(nsISupports* outer,
                             const nsIID& aIID,
                             void* *aInstancePtr)
 {
     NS_ASSERTION(aInstancePtr, "null outptr");
     NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
 
@@ -480,16 +484,17 @@ static const nsModuleComponentInfo compo
 
 #ifdef XP_MACOSX
     COMPONENT(MACUTILSIMPL, nsMacUtilsImplConstructor),
 #endif
 
     COMPONENT(SYSTEMINFO, nsSystemInfoConstructor),
 #define NS_MEMORY_REPORTER_MANAGER_CLASSNAME "Memory Reporter Manager"
     COMPONENT(MEMORY_REPORTER_MANAGER, nsMemoryReporterManagerConstructor),
+    COMPONENT(IOUTIL, nsIOUtilConstructor),
 };
 
 #undef COMPONENT
 
 const int components_length = sizeof(components) / sizeof(components[0]);
 
 // gDebug will be freed during shutdown.
 static nsIDebug* gDebug = nsnull;
--- a/xpcom/io/Makefile.in
+++ b/xpcom/io/Makefile.in
@@ -70,16 +70,17 @@ CPPSRCS		= \
 		nsStreamUtils.cpp \
 		nsScriptableInputStream.cpp \
 		nsSegmentedBuffer.cpp \
 		SpecialSystemDirectory.cpp \
 		nsStorageStream.cpp \
 		nsStringStream.cpp \
 		nsUnicharInputStream.cpp \
 		nsNativeCharsetUtils.cpp \
+		nsIOUtil.cpp \
 		$(NULL)
 
 ifndef MOZ_NO_FAST_LOAD
 CPPSRCS += \
 		nsFastLoadFile.cpp \
 		nsFastLoadService.cpp \
 		$(NULL)
 endif
@@ -147,16 +148,17 @@ XPIDLSRCS	= \
 		nsIStringStream.idl \
 		nsIStreamBufferAccess.idl \
 		nsIAsyncInputStream.idl \
 		nsIAsyncOutputStream.idl \
 		nsIUnicharInputStream.idl \
 		nsIUnicharOutputStream.idl \
 		nsIConverterInputStream.idl \
 		nsIConverterOutputStream.idl \
+		nsIIOUtil.idl \
 		$(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 XPIDLSRCS	+= nsILocalFileOS2.idl
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 XPIDLSRCS	+= nsILocalFileMac.idl
 endif # cocoa
new file mode 100644
--- /dev/null
+++ b/xpcom/io/nsIIOUtil.idl
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Boris Zbarsky <bzbarsky@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIInputStream;
+interface nsIOutputStream;
+
+/**
+ * nsIIOUtil provdes various xpcom/io-related utility methods.
+ */
+[scriptable, uuid(e8152f7f-4209-4c63-ad23-c3d2aa0c5a49)]
+interface nsIIOUtil : nsISupports
+{
+  /**
+   * Test whether an input stream is buffered.  See nsStreamUtils.h
+   * documentation for NS_InputStreamIsBuffered for the definition of
+   * "buffered" used here and for edge-case behavior.
+   *
+   * @throws NS_ERROR_INVALID_POINTER if null is passed in.
+   */
+  boolean inputStreamIsBuffered(in nsIInputStream aStream);
+
+  /**
+   * Test whether an output stream is buffered.  See nsStreamUtils.h
+   * documentation for NS_OutputStreamIsBuffered for the definition of
+   * "buffered" used here and for edge-case behavior.
+   *
+   * @throws NS_ERROR_INVALID_POINTER if null is passed in.
+   */
+  boolean outputStreamIsBuffered(in nsIOutputStream aStream);
+};
new file mode 100644
--- /dev/null
+++ b/xpcom/io/nsIOUtil.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Boris Zbarsky <bzbarsky@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIOUtil.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsStreamUtils.h"
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsIOUtil, nsIIOUtil)
+
+NS_IMETHODIMP
+nsIOUtil::InputStreamIsBuffered(nsIInputStream* aStream, PRBool* _retval)
+{
+  NS_ENSURE_ARG_POINTER(aStream);
+  *_retval = NS_InputStreamIsBuffered(aStream);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsIOUtil::OutputStreamIsBuffered(nsIOutputStream* aStream, PRBool* _retval)
+{
+  NS_ENSURE_ARG_POINTER(aStream);
+  *_retval = NS_OutputStreamIsBuffered(aStream);
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/xpcom/io/nsIOUtil.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Boris Zbarsky <bzbarsky@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIOUtil_h__
+#define nsIOUtil_h__
+
+#define NS_IOUTIL_CLASSNAME "XPCOM I/O utility class"
+#define NS_IOUTIL_CID                                                \
+{ 0xeb833911, 0x4f49, 0x4623,                                        \
+    { 0x84, 0x5f, 0xe5, 0x8a, 0x8e, 0x6d, 0xe4, 0xc2 } }
+
+
+#include "nsIIOUtil.h"
+
+class nsIOUtil : public nsIIOUtil
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIIOUTIL
+};
+
+#endif /* nsIOUtil_h__ */
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/unit/test_ioutil.js
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Boris Zbarsky <bzbarsky@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+const util = Cc["@mozilla.org/io-util;1"].getService(Ci.nsIIOUtil);
+
+function run_test()
+{
+    try {
+        util.inputStreamIsBuffered(null);
+        do_throw("inputStreamIsBuffered should have thrown");
+    } catch (e) {
+        do_check_eq(e.result, Cr.NS_ERROR_INVALID_POINTER);
+    }
+
+    try {
+        util.outputStreamIsBuffered(null);
+        do_throw("outputStreamIsBuffered should have thrown");
+    } catch (e) {
+        do_check_eq(e.result, Cr.NS_ERROR_INVALID_POINTER);
+    }
+
+    var s = Cc["@mozilla.org/io/string-input-stream;1"]
+              .createInstance(Ci.nsIStringInputStream);
+    var body = "This is a test";
+    s.setData(body, body.length);
+    do_check_eq(util.inputStreamIsBuffered(s), true);
+}
new file mode 100644
--- /dev/null
+++ b/xpcom/tests/unit/test_stringstream.js
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Boris Zbarsky <bzbarsky@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+function run_test()
+{
+    var s = Cc["@mozilla.org/io/string-input-stream;1"]
+              .createInstance(Ci.nsIStringInputStream);
+    var body = "This is a test";
+    s.setData(body, body.length);
+    do_check_eq(s.available(), body.length);
+
+    var sis = Cc["@mozilla.org/scriptableinputstream;1"]
+                .createInstance(Ci.nsIScriptableInputStream);
+    sis.init(s);
+
+    do_check_eq(sis.read(body.length), body);
+}