Bug 532147 - NetUtil.asyncFetch should take an nsIURI, string, nsIFile, or nsIChannel
authorShawn Wilsher <sdwilsh@shawnwilsher.com>
Tue, 15 Dec 2009 23:33:08 -0800
changeset 36725 caaa274d3b5ff91099b70c5cf692a5d8567b1224
parent 36724 404e56019315402927648527ce21c9810754fff4
child 36726 8eb57fa656b8637e352c3eee2bcce7c8e90c405c
push id10949
push usersdwilsh@shawnwilsher.com
push dateTue, 29 Dec 2009 15:05:35 +0000
treeherdermozilla-central@caaa274d3b5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs532147
milestone1.9.3a1pre
Bug 532147 - NetUtil.asyncFetch should take an nsIURI, string, nsIFile, or nsIChannel This lets consumers pass a string for a uri, an nsIURI, an nsIFile, or an nsIChannel to NetUtil.asyncFetch. It's now less code to get file contents asynchronously that to do so synchronously in JavaScript. r=bz sr=vlad
netwerk/base/src/NetUtil.jsm
netwerk/test/unit/test_NetUtil.js
--- a/netwerk/base/src/NetUtil.jsm
+++ b/netwerk/base/src/NetUtil.jsm
@@ -123,33 +123,33 @@ const NetUtil = {
         }
 
         // start the copying
         copier.asyncCopy(observer, null);
         return copier;
     },
 
     /**
-     * Asynchronously opens a channel and fetches the response.  The provided
-     * callback will get an input stream containing the response, and the result
-     * code.
+     * Asynchronously opens a source and fetches the response.  A source can be
+     * an nsIURI, nsIFile, string spec, or nsIChannel.  The provided callback
+     * will get an input stream containing the response, and the result code.
      *
-     * @param aChannel
-     *        The nsIChannel to open.
+     * @param aSource
+     *        The nsIURI, nsIFile, string spec, or nsIChannel to open.
      * @param aCallback
      *        The callback function that will be notified upon completion.  It
      *        will get two arguments:
      *        1) An nsIInputStream containing the data from the channel, if any.
-     *        2) The status code from opening the channel.
+     *        2) The status code from opening the source.
      */
-    asyncFetch: function NetUtil_asyncOpen(aChannel, aCallback)
+    asyncFetch: function NetUtil_asyncOpen(aSource, aCallback)
     {
-        if (!aChannel || !aCallback) {
+        if (!aSource || !aCallback) {
             let exception = new Components.Exception(
-                "Must have a channel and a callback",
+                "Must have a source and a callback",
                 Cr.NS_ERROR_INVALID_ARG,
                 Components.stack.caller
             );
             throw exception;
         }
 
         // Create a pipe that will create our output stream that we can use once
         // we have gotten all the data.
@@ -163,17 +163,22 @@ const NetUtil = {
         listener.init(pipe.outputStream, {
             onStartRequest: function(aRequest, aContext) {},
             onStopRequest: function(aRequest, aContext, aStatusCode) {
                 pipe.outputStream.close();
                 aCallback(pipe.inputStream, aStatusCode);
             }
         });
 
-        aChannel.asyncOpen(listener, null);
+        let channel = aSource;
+        if (!(channel instanceof Ci.nsIChannel)) {
+            channel = this.newChannel(aSource);
+        }
+
+        channel.asyncOpen(listener, null);
     },
 
     /**
      * Constructs a new URI for the given spec, character set, and base URI, or
      * an nsIFile.
      *
      * @param aTarget
      *        The string spec for the desired URI or an nsIFile.
--- a/netwerk/test/unit/test_NetUtil.js
+++ b/netwerk/test/unit/test_NetUtil.js
@@ -221,17 +221,17 @@ function test_asyncFetch_no_callback()
   }
   catch (e) {
     do_check_eq(e.result, Cr.NS_ERROR_INVALID_ARG);
   }
 
   run_next_test();
 }
 
-function test_asyncFetch()
+function test_asyncFetch_with_nsIChannel()
 {
   const TEST_DATA = "this is a test string";
 
   // Start the http server, and register our handler.
   let server = new nsHttpServer();
   server.registerPathHandler("/test", function(aRequest, aResponse) {
     aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
     aResponse.setHeader("Content-Type", "text/plain", false);
@@ -255,16 +255,117 @@ function test_asyncFetch()
     is.init(aInputStream);
     let result = is.read(TEST_DATA.length);
     do_check_eq(TEST_DATA, result);
 
     server.stop(run_next_test);
   });
 }
 
+function test_asyncFetch_with_nsIURI()
+{
+  const TEST_DATA = "this is a test string";
+
+  // Start the http server, and register our handler.
+  let server = new nsHttpServer();
+  server.registerPathHandler("/test", function(aRequest, aResponse) {
+    aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
+    aResponse.setHeader("Content-Type", "text/plain", false);
+    aResponse.write(TEST_DATA);
+  });
+  server.start(4444);
+
+  // Create our URI.
+  let uri = NetUtil.newURI("http://localhost:4444/test");
+
+  // Open our URI asynchronously.
+  NetUtil.asyncFetch(uri, function(aInputStream, aResult) {
+    // Check that we had success.
+    do_check_true(Components.isSuccessCode(aResult));
+
+    // Check that we got the right data.
+    do_check_eq(aInputStream.available(), TEST_DATA.length);
+    let is = Cc["@mozilla.org/scriptableinputstream;1"].
+             createInstance(Ci.nsIScriptableInputStream);
+    is.init(aInputStream);
+    let result = is.read(TEST_DATA.length);
+    do_check_eq(TEST_DATA, result);
+
+    server.stop(run_next_test);
+  });
+}
+
+function test_asyncFetch_with_string()
+{
+  const TEST_DATA = "this is a test string";
+
+  // Start the http server, and register our handler.
+  let server = new nsHttpServer();
+  server.registerPathHandler("/test", function(aRequest, aResponse) {
+    aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
+    aResponse.setHeader("Content-Type", "text/plain", false);
+    aResponse.write(TEST_DATA);
+  });
+  server.start(4444);
+
+  // Open our location asynchronously.
+  NetUtil.asyncFetch("http://localhost:4444/test", function(aInputStream,
+                                                            aResult) {
+    // Check that we had success.
+    do_check_true(Components.isSuccessCode(aResult));
+
+    // Check that we got the right data.
+    do_check_eq(aInputStream.available(), TEST_DATA.length);
+    let is = Cc["@mozilla.org/scriptableinputstream;1"].
+             createInstance(Ci.nsIScriptableInputStream);
+    is.init(aInputStream);
+    let result = is.read(TEST_DATA.length);
+    do_check_eq(TEST_DATA, result);
+
+    server.stop(run_next_test);
+  });
+}
+
+function test_asyncFetch_with_nsIFile()
+{
+  const TEST_DATA = "this is a test string";
+
+  // First we need a file to read from.
+  let file = Cc["@mozilla.org/file/directory_service;1"].
+             getService(Ci.nsIProperties).
+             get("ProfD", Ci.nsIFile);
+  file.append("NetUtil-asyncFetch-test-file.tmp");
+  file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+
+  // Write the test data to the file.
+  let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
+                createInstance(Ci.nsIFileOutputStream);
+  ostream.init(file, -1, -1, 0);
+  ostream.write(TEST_DATA, TEST_DATA.length);
+
+  // Sanity check to make sure the data was written.
+  do_check_eq(TEST_DATA, getFileContents(file));
+
+  // Open our file asynchronously.
+  NetUtil.asyncFetch(file, function(aInputStream, aResult) {
+    // Check that we had success.
+    do_check_true(Components.isSuccessCode(aResult));
+
+    // Check that we got the right data.
+    do_check_eq(aInputStream.available(), TEST_DATA.length);
+    let is = Cc["@mozilla.org/scriptableinputstream;1"].
+             createInstance(Ci.nsIScriptableInputStream);
+    is.init(aInputStream);
+    let result = is.read(TEST_DATA.length);
+    do_check_eq(TEST_DATA, result);
+
+    run_next_test();
+  });
+}
+
 function test_asyncFetch_does_not_block()
 {
   // Create our channel that has no data.
   let channel = NetUtil.ioService.
                 newChannel("data:text/plain,", null, null);
 
   // Open our channel asynchronously.
   NetUtil.asyncFetch(channel, function(aInputStream, aResult) {
@@ -353,17 +454,20 @@ let tests = [
   test_async_write_file,
   test_async_write_file_nsISafeOutputStream,
   test_newURI_no_spec_throws,
   test_newURI,
   test_newURI_takes_nsIFile,
   test_ioService,
   test_asyncFetch_no_channel,
   test_asyncFetch_no_callback,
-  test_asyncFetch,
+  test_asyncFetch_with_nsIChannel,
+  test_asyncFetch_with_nsIURI,
+  test_asyncFetch_with_string,
+  test_asyncFetch_with_nsIFile,
   test_asyncFetch_does_not_block,
   test_newChannel_no_specifier,
   test_newChannel_with_string,
   test_newChannel_with_nsIURI,
   test_newChannel_with_nsIFile,
 ];
 let index = 0;