Backout ebc28a0d4b96
authorHonza Bambas <honzab.moz@firemni.cz>
Mon, 16 Nov 2009 23:07:00 +0100
changeset 34914 d2a11453df9804247b680ffb213f8bd4812997f7
parent 34905 ebc28a0d4b96b2e104e8b51dc3e3466c9dfe5f89
child 34915 a866ac2ad62f6088b3a469607eba417a2e64ca25
push idunknown
push userunknown
push dateunknown
milestone1.9.3a1pre
backs outebc28a0d4b96b2e104e8b51dc3e3466c9dfe5f89
Backout ebc28a0d4b96
netwerk/base/public/nsIStreamListenerTee.idl
netwerk/base/src/nsStreamListenerTee.cpp
netwerk/base/src/nsStreamListenerTee.h
netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp
netwerk/protocol/http/src/nsHttpChannel.cpp
netwerk/test/unit/test_traceable_channel.js
--- a/netwerk/base/public/nsIStreamListenerTee.idl
+++ b/netwerk/base/public/nsIStreamListenerTee.idl
@@ -33,37 +33,19 @@
  * 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 "nsIStreamListener.idl"
 
 interface nsIOutputStream;
-interface nsIRequestObserver;
 
 /**
  * As data "flows" into a stream listener tee, it is copied to the output stream
  * and then forwarded to the real listener.
  */
-[scriptable, uuid(8e86c460-2f6b-4595-a6ba-d5444827cd57)]
+[scriptable, uuid(fb683e76-d42b-41a4-8ae6-65a6c2b146e5)]
 interface nsIStreamListenerTee : nsIStreamListener
 {
-    /** 
-     * Initalize the tee.
-     *
-     * @param listener
-     *    the original listener the tee will propagate onStartRequest,
-     *    onDataAvailable and onStopRequest notifications to, exceptions from 
-     *    the listener will be propagated back to the channel
-     * @param sink
-     *    the stream the data coming from the channel will be written to,
-     *    should be blocking
-     * @param requestObserver
-     *    optional parameter, listener that gets only onStartRequest and
-     *    onStopRequest notifications; exceptions threw within this optional
-     *    observer are also propagated to the channel, but exceptions from
-     *    the original listener (listener parameter) are privileged 
-     */
     void init(in nsIStreamListener listener,
-              in nsIOutputStream sink,
-              [optional] in nsIRequestObserver requestObserver);
+              in nsIOutputStream sink);
 };
--- a/netwerk/base/src/nsStreamListenerTee.cpp
+++ b/netwerk/base/src/nsStreamListenerTee.cpp
@@ -42,42 +42,32 @@ NS_IMPL_ISUPPORTS3(nsStreamListenerTee,
                    nsIRequestObserver,
                    nsIStreamListenerTee)
 
 NS_IMETHODIMP
 nsStreamListenerTee::OnStartRequest(nsIRequest *request,
                                     nsISupports *context)
 {
     NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
-    nsresult rv1 = mListener->OnStartRequest(request, context);
-    nsresult rv2 = NS_OK;
-    if (mObserver)
-        rv2 = mObserver->OnStartRequest(request, context);
-  
-    // Preserve NS_SUCCESS_XXX in rv1 in case mObserver didn't throw
-    return (NS_FAILED(rv2) && NS_SUCCEEDED(rv1)) ? rv2 : rv1;
+    return mListener->OnStartRequest(request, context);
 }
 
 NS_IMETHODIMP
 nsStreamListenerTee::OnStopRequest(nsIRequest *request,
                                    nsISupports *context,
                                    nsresult status)
 {
     NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED);
     // it is critical that we close out the input stream tee
     if (mInputTee) {
         mInputTee->SetSink(nsnull);
         mInputTee = 0;
     }
     mSink = 0;
-    nsresult rv = mListener->OnStopRequest(request, context, status);
-    if (mObserver)
-        mObserver->OnStopRequest(request, context, status);
-    mObserver = 0;
-    return rv;
+    return mListener->OnStopRequest(request, context, status);
 }
 
 NS_IMETHODIMP
 nsStreamListenerTee::OnDataAvailable(nsIRequest *request,
                                      nsISupports *context,
                                      nsIInputStream *input,
                                      PRUint32 offset,
                                      PRUint32 count)
@@ -104,16 +94,14 @@ nsStreamListenerTee::OnDataAvailable(nsI
         if (NS_FAILED(rv)) return rv;
     }
 
     return mListener->OnDataAvailable(request, context, tee, offset, count);
 }
 
 NS_IMETHODIMP
 nsStreamListenerTee::Init(nsIStreamListener *listener,
-                          nsIOutputStream *sink,
-                          nsIRequestObserver *requestObserver)
+                          nsIOutputStream *sink)
 {
     mListener = listener;
     mSink = sink;
-    mObserver = requestObserver;
     return NS_OK;
 }
--- a/netwerk/base/src/nsStreamListenerTee.h
+++ b/netwerk/base/src/nsStreamListenerTee.h
@@ -53,12 +53,11 @@ public:
 
     nsStreamListenerTee() { }
     virtual ~nsStreamListenerTee() { }
 
 private:
     nsCOMPtr<nsIInputStreamTee> mInputTee;
     nsCOMPtr<nsIStreamListener> mListener;
     nsCOMPtr<nsIOutputStream>   mSink;
-    nsCOMPtr<nsIRequestObserver> mObserver;
 };
 
 #endif
--- a/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/src/nsFtpConnectionThread.cpp
@@ -1591,17 +1591,17 @@ nsFtpState::InstallCacheListener()
     nsCOMPtr<nsIOutputStream> out;
     mCacheEntry->OpenOutputStream(0, getter_AddRefs(out));
     NS_ENSURE_STATE(out);
 
     nsCOMPtr<nsIStreamListenerTee> tee =
             do_CreateInstance(NS_STREAMLISTENERTEE_CONTRACTID);
     NS_ENSURE_STATE(tee);
 
-    nsresult rv = tee->Init(mChannel->StreamListener(), out, nsnull);
+    nsresult rv = tee->Init(mChannel->StreamListener(), out);
     NS_ENSURE_SUCCESS(rv, rv);
 
     mChannel->SetStreamListener(tee);
     return NS_OK;
 }
 
 nsresult
 nsFtpState::OpenCacheDataStream()
--- a/netwerk/protocol/http/src/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/src/nsHttpChannel.cpp
@@ -2670,17 +2670,17 @@ nsHttpChannel::InstallCacheListener(PRUi
     rv = mCacheEntry->MarkValid();
     if (NS_FAILED(rv)) return rv;
 #endif
 
     nsCOMPtr<nsIStreamListenerTee> tee =
         do_CreateInstance(kStreamListenerTeeCID, &rv);
     if (NS_FAILED(rv)) return rv;
 
-    rv = tee->Init(mListener, out, nsnull);
+    rv = tee->Init(mListener, out);
     if (NS_FAILED(rv)) return rv;
 
     mListener = tee;
     return NS_OK;
 }
 
 nsresult
 nsHttpChannel::InstallOfflineCacheListener()
@@ -2696,17 +2696,17 @@ nsHttpChannel::InstallOfflineCacheListen
     nsCOMPtr<nsIOutputStream> out;
     rv = mOfflineCacheEntry->OpenOutputStream(0, getter_AddRefs(out));
     if (NS_FAILED(rv)) return rv;
 
     nsCOMPtr<nsIStreamListenerTee> tee =
         do_CreateInstance(kStreamListenerTeeCID, &rv);
     if (NS_FAILED(rv)) return rv;
 
-    rv = tee->Init(mListener, out, nsnull);
+    rv = tee->Init(mListener, out);
     if (NS_FAILED(rv)) return rv;
 
     mListener = tee;
 
     return NS_OK;
 }
 
 void
--- a/netwerk/test/unit/test_traceable_channel.js
+++ b/netwerk/test/unit/test_traceable_channel.js
@@ -1,64 +1,73 @@
 // Test nsITraceableChannel interface.
 // Replace original listener with TracingListener that modifies body of HTTP
 // response. Make sure that body received by original channel's listener
 // is correctly modified.
 
 do_load_httpd_js();
 
 var httpserver = null;
-var pipe = null;
-var streamSink = null;
-
 var originalBody = "original http response body";
-var gotOnStartRequest = false;
+var replacedBody = "replaced http response body";
 
 function TracingListener() {}
 
 TracingListener.prototype = {
+
+  // Replace received response body.
+  onDataAvailable: function(request, context, inputStream,
+                           offset, count) {
+    dump("*** tracing listener onDataAvailable\n");
+    var binaryInputStream = Cc["@mozilla.org/binaryinputstream;1"].
+      createInstance(Components.interfaces.nsIBinaryInputStream);
+    binaryInputStream.setInputStream(inputStream);
+
+    var data = binaryInputStream.readBytes(count);
+    var origBody = originalBody.substr(offset, count);
+    do_check_eq(origBody, data);
+
+    var storageStream = Cc["@mozilla.org/storagestream;1"].
+      createInstance(Components.interfaces.nsIStorageStream);
+    var binaryOutputStream = Cc["@mozilla.org/binaryoutputstream;1"].
+      createInstance(Components.interfaces.nsIBinaryOutputStream);
+
+    storageStream.init(8192, 100, null);
+    binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
+
+    var newBody = replacedBody.substr(offset, count);
+    binaryOutputStream.writeBytes(newBody, newBody.length);
+
+    this.listener.onDataAvailable(request, context,
+                                  storageStream.newInputStream(0), 0,
+                                  replacedBody.length);
+  },
+
   onStartRequest: function(request, context) {
-    dump("*** tracing listener onStartRequest\n");
-
-    gotOnStartRequest = true;
+    this.listener.onStartRequest(request, context);
 
     // Make sure listener can't be replaced after OnStartRequest was called.
     request.QueryInterface(Components.interfaces.nsITraceableChannel);
     try {
       var newListener = new TracingListener();
       newListener.listener = request.setNewListener(newListener);
     } catch(e) {
       return; // OK
     }
     do_throw("replaced channel's listener during onStartRequest.");
   },
 
   onStopRequest: function(request, context, statusCode) {
-    dump("*** tracing listener onStopRequest\n");
-    
-    do_check_eq(gotOnStartRequest, true);
-    
-    var sin = Components.classes["@mozilla.org/scriptableinputstream;1"].
-        createInstance(Ci.nsIScriptableInputStream);
-
-    streamSink.close();
-    var input = pipe.inputStream;
-    sin.init(input);
-    do_check_eq(sin.available(), originalBody.length);
-    
-    var result = sin.read(originalBody.length);
-    do_check_eq(result, originalBody);
-    
-    input.close();
-    
+    this.listener.onStopRequest(request, context, statusCode);
     httpserver.stop(do_test_finished);
   },
 
   QueryInterface: function(iid) {
-    if (iid.equals(Components.interfaces.nsIRequestObserver) ||
+    if (iid.equals(Components.interfaces.nsIStreamListener) ||
+        iid.equals(Components.interfaces.nsIRequestObserver) ||
         iid.equals(Components.interfaces.nsISupports)
         )
       return this;
     throw Components.results.NS_NOINTERFACE;
   },
 
   listener: null
 }
@@ -72,32 +81,24 @@ HttpResponseExaminer.prototype = {
       getService(Components.interfaces.nsIObserverService).
       addObserver(this, "http-on-examine-response", true);
   },
 
   // Replace channel's listener.
   observe: function(subject, topic, data) {
     try {
       subject.QueryInterface(Components.interfaces.nsITraceableChannel);
-      
-      var tee = Cc["@mozilla.org/network/stream-listener-tee;1"].
-          createInstance(Ci.nsIStreamListenerTee);
       var newListener = new TracingListener();
-      pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
-      pipe.init(false, false, 0, 0xffffffff, null);
-      streamSink = pipe.outputStream;
-      
-      var originalListener = subject.setNewListener(tee);
-      tee.init(originalListener, streamSink, newListener);
+      newListener.listener = subject.setNewListener(newListener);
     } catch(e) {
-      do_throw("can't replace listener " + e);
+      do_throw("can't replace listener" + e);
     }
   },
 
-  QueryInterface: function(iid) {
+ QueryInterface: function(iid) {
     if (iid.equals(Components.interfaces.nsIObserver) ||
         iid.equals(Components.interfaces.nsISupportsWeakReference) ||
         iid.equals(Components.interfaces.nsISupports))
       return this;
     throw Components.results.NS_NOINTERFACE;
   }
 }
 
@@ -110,23 +111,24 @@ function test_handler(metadata, response
 function make_channel(url) {
   var ios = Cc["@mozilla.org/network/io-service;1"].
     getService(Ci.nsIIOService);
   return ios.newChannel(url, null, null).
     QueryInterface(Components.interfaces.nsIHttpChannel);
 }
 
 // Check if received body is correctly modified.
-function channel_finished(request, input, ctx) {
+function get_data(request, input, ctx) {
+  do_check_eq(replacedBody, input);
 }
 
 function run_test() {
   var observer = new HttpResponseExaminer();
   observer.register();
 
   httpserver = new nsHttpServer();
   httpserver.registerPathHandler("/testdir", test_handler);
   httpserver.start(4444);
 
   var channel = make_channel("http://localhost:4444/testdir");
-  channel.asyncOpen(new ChannelListener(channel_finished), null);
+  channel.asyncOpen(new ChannelListener(get_data), null);
   do_test_pending();
 }