Make <object> do the same text/plain sniffing that <iframe> does, and use the content type hint if the type comes back as application/octet-stream or sniffed-binary. Bug 389677, r+sr=biesi, a=sicking
authorbzbarsky@mit.edu
Mon, 20 Aug 2007 20:26:12 -0700
changeset 4849 488bc73ac2de8efd6ba5f747ba601e81a2953784
parent 4848 ad00aedf5ddf9771e64e6e91a987b52b76586fa5
child 4850 1b6a80097721130861886b3501112da8f30597c3
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs389677
milestone1.9a8pre
Make <object> do the same text/plain sniffing that <iframe> does, and use the content type hint if the type comes back as application/octet-stream or sniffed-binary. Bug 389677, r+sr=biesi, a=sicking
content/base/src/nsObjectLoadingContent.cpp
netwerk/build/nsNetCID.h
netwerk/build/nsNetModule.cpp
netwerk/mime/public/nsMimeTypes.h
netwerk/streamconv/converters/nsUnknownDecoder.cpp
netwerk/streamconv/converters/nsUnknownDecoder.h
uriloader/base/nsURILoader.cpp
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -70,16 +70,17 @@
 #include "nsCURILoader.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentUtils.h"
 #include "nsDocShellCID.h"
 #include "nsGkAtoms.h"
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 #include "nsPresShellIterator.h"
+#include "nsMimeTypes.h"
 
 // Concrete classes
 #include "nsFrameLoader.h"
 
 #include "nsObjectLoadingContent.h"
 
 static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
 
@@ -368,19 +369,35 @@ nsObjectLoadingContent::OnStartRequest(n
   nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
   NS_ASSERTION(chan, "Why is our request not a channel?");
 
   nsresult rv = NS_ERROR_UNEXPECTED;
   // This fallback variable MUST be declared after the notifier variable. Do NOT
   // change the order of the declarations!
   AutoFallback fallback(this, &rv);
 
-  rv = chan->GetContentType(mContentType);
+  nsCString channelType;
+  rv = chan->GetContentType(channelType);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  if (channelType.EqualsASCII(APPLICATION_GUESS_FROM_EXT)) {
+    channelType = APPLICATION_OCTET_STREAM;
+    chan->SetContentType(channelType);
+  }
+  
+  if (mContentType.IsEmpty() ||
+      !channelType.EqualsASCII(APPLICATION_OCTET_STREAM)) {
+    mContentType = channelType;
+  } else {
+    // Set the type we'll use for dispatch on the channel.  Otherwise we could
+    // end up trying to dispatch to a nsFrameLoader, which will complain that
+    // it couldn't find a way to handle application/octet-stream
+    chan->SetContentType(mContentType);
+  }
+
   // Now find out what type the content is
   // UnloadContent will set our type to null; need to be sure to only set it to
   // the real value on success
   ObjectType newType = GetTypeOfContent(mContentType);
   LOG(("OBJLC [%p]: OnStartRequest: Content Type=<%s> Old type=%u New Type=%u\n",
        this, mContentType.get(), mType, newType));
   if (mType != newType) {
     UnloadContent();
@@ -1066,17 +1083,18 @@ nsObjectLoadingContent::LoadObject(nsIUR
     mType = eType_Plugin;
 
     rv = TryInstantiate(aTypeHint, aURI);
     return NS_OK;
   }
 
   nsCOMPtr<nsILoadGroup> group = doc->GetDocumentLoadGroup();
   nsCOMPtr<nsIChannel> chan;
-  rv = NS_NewChannel(getter_AddRefs(chan), aURI, nsnull, group, this);
+  rv = NS_NewChannel(getter_AddRefs(chan), aURI, nsnull, group, this,
+                     nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Referrer
   nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
   if (httpChan) {
     httpChan->SetReferrer(doc->GetDocumentURI());
   }
 
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -779,16 +779,24 @@
 /**
  * General-purpose content sniffer component. Use with CreateInstance.
  *
  * Implements nsIContentSniffer
  */
 #define NS_GENERIC_CONTENT_SNIFFER \
     "@mozilla.org/network/content-sniffer;1"
 
+/**
+ * Detector that can act as either an nsIStreamConverter or an
+ * nsIContentSniffer to decide whether text/plain data is "really" text/plain
+ * or APPLICATION_GUESS_FROM_EXT.  Use with CreateInstance.
+ */
+#define NS_BINARYDETECTOR_CONTRACTID \
+    "@mozilla.org/network/binary-detector;1"
+
 /******************************************************************************
  * netwerk/system classes
  */
 
 // service implementing nsINetworkLinkService
 #define NS_NETWORK_LINK_SERVICE_CLASSNAME "Network Link Status"
 #define NS_NETWORK_LINK_SERVICE_CID    \
   { 0x75a500a2,                                        \
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -296,17 +296,16 @@ nsresult NS_NewStreamConv(nsStreamConver
 
 #define FTP_TO_INDEX                 "?from=text/ftp-dir&to=application/http-index-format"
 #define GOPHER_TO_INDEX              "?from=text/gopher-dir&to=application/http-index-format"
 #define INDEX_TO_HTML                "?from=application/http-index-format&to=text/html"
 #define MULTI_MIXED_X                "?from=multipart/x-mixed-replace&to=*/*"
 #define MULTI_MIXED                  "?from=multipart/mixed&to=*/*"
 #define MULTI_BYTERANGES             "?from=multipart/byteranges&to=*/*"
 #define UNKNOWN_CONTENT              "?from=" UNKNOWN_CONTENT_TYPE "&to=*/*"
-#define MAYBE_TEXT                   "?from=" APPLICATION_MAYBE_TEXT "&to=*/*"
 #define GZIP_TO_UNCOMPRESSED         "?from=gzip&to=uncompressed"
 #define XGZIP_TO_UNCOMPRESSED        "?from=x-gzip&to=uncompressed"
 #define COMPRESS_TO_UNCOMPRESSED     "?from=compress&to=uncompressed"
 #define XCOMPRESS_TO_UNCOMPRESSED    "?from=x-compress&to=uncompressed"
 #define DEFLATE_TO_UNCOMPRESSED      "?from=deflate&to=uncompressed"
 #define PLAIN_TO_HTML                "?from=text/plain&to=text/html"
 
 #ifdef BUILD_BINHEX_DECODER
@@ -316,17 +315,16 @@ nsresult NS_NewStreamConv(nsStreamConver
 static const char *const sStreamConverterArray[] = {
     FTP_TO_INDEX,
     GOPHER_TO_INDEX,
     INDEX_TO_HTML,
     MULTI_MIXED_X,
     MULTI_MIXED,
     MULTI_BYTERANGES,
     UNKNOWN_CONTENT,
-    MAYBE_TEXT,
     GZIP_TO_UNCOMPRESSED,
     XGZIP_TO_UNCOMPRESSED,
     COMPRESS_TO_UNCOMPRESSED,
     XCOMPRESS_TO_UNCOMPRESSED,
     DEFLATE_TO_UNCOMPRESSED,
 #ifdef BUILD_BINHEX_DECODER
     BINHEX_TO_WILD,
 #endif
@@ -850,18 +848,19 @@ static const nsModuleComponentInfo gNetM
     { "Unknown Content-Type Decoder",
       NS_UNKNOWNDECODER_CID,
       NS_GENERIC_CONTENT_SNIFFER,
       CreateNewUnknownDecoderFactory
     },
 
     { "Binary Detector",
       NS_BINARYDETECTOR_CID,
-      NS_ISTREAMCONVERTER_KEY MAYBE_TEXT,
-      CreateNewBinaryDetectorFactory
+      NS_BINARYDETECTOR_CONTRACTID,
+      CreateNewBinaryDetectorFactory,
+      nsBinaryDetector::Register
     },
 
     { "HttpCompressConverter", 
       NS_HTTPCOMPRESSCONVERTER_CID,
       NS_ISTREAMCONVERTER_KEY GZIP_TO_UNCOMPRESSED,
       CreateNewHTTPCompressConvFactory
     },
 
--- a/netwerk/mime/public/nsMimeTypes.h
+++ b/netwerk/mime/public/nsMimeTypes.h
@@ -186,14 +186,13 @@
 #define PARAM_MICALG_SHA1_4                 "rsa-sha-1"
 #define PARAM_MICALG_SHA1_5                 "rsa-sha"
 #define PARAM_X_MAC_CREATOR                 "x-mac-creator"
 #define PARAM_X_MAC_TYPE                    "x-mac-type"
 #define PARAM_FORMAT                        "format"
 
 #define UNKNOWN_CONTENT_TYPE                "application/x-unknown-content-type"
 #define APPLICATION_GUESS_FROM_EXT          "application/x-vnd.mozilla.guess-from-ext"
-#define APPLICATION_MAYBE_TEXT              "application/x-vnd.mozilla.maybe-text"
 #define VIEWSOURCE_CONTENT_TYPE             "application/x-view-source"
 
 #define APPLICATION_DIRECTORY				        "application/directory" /* text/x-vcard is synonym */
 
 #endif /* nsMimeTypes_h_ */
--- a/netwerk/streamconv/converters/nsUnknownDecoder.cpp
+++ b/netwerk/streamconv/converters/nsUnknownDecoder.cpp
@@ -51,27 +51,22 @@
 #include "nsISupportsPrimitives.h"
 #include "nsIContentSniffer.h"
 
 #include "nsCRT.h"
 
 #include "nsIMIMEService.h"
 
 #include "nsIViewSourceChannel.h"
+#include "nsIHttpChannel.h"
+#include "nsNetCID.h"
 
-#include "prcpucfg.h" // To get IS_LITTLE_ENDIAN / IS_BIG_ENDIAN
 
 #define MAX_BUFFER_SIZE 1024
 
-#if defined WORDS_BIGENDIAN || defined IS_BIG_ENDIAN
-#define LITTLE_TO_NATIVE16(x) ((((x) & 0xFF) << 8) | ((x) >> 8))
-#else
-#define LITTLE_TO_NATIVE16(x) x
-#endif
-
 nsUnknownDecoder::nsUnknownDecoder()
   : mBuffer(nsnull)
   , mBufferLen(0)
   , mRequireHTMLsuffix(PR_FALSE)
 {
   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (prefs) {
     PRBool val;
@@ -182,18 +177,16 @@ nsUnknownDecoder::OnDataAvailable(nsIReq
       // Adjust the source offset...  The call to FireListenerNotifications(...)
       // will make the first OnDataAvailable(...) call with an offset of 0.
       // So, this offset needs to be adjusted to reflect that...
       //
       aSourceOffset += mBufferLen;
 
       DetermineContentType(request);
 
-      NS_ASSERTION(!mContentType.IsEmpty(), 
-                   "Content type should be known by now.");
       rv = FireListenerNotifications(request, aCtxt);
     }
   }
 
   // Must not fire ODA again if it failed once
   if (aCount && NS_SUCCEEDED(rv)) {
     NS_ASSERTION(!mContentType.IsEmpty(), 
                  "Content type should be known by now.");
@@ -241,18 +234,16 @@ nsUnknownDecoder::OnStopRequest(nsIReque
 
   //
   // The total amount of data is less than the size of the sniffer buffer.
   // Analyze the buffer now...
   //
   if (mContentType.IsEmpty()) {
     DetermineContentType(request);
 
-    NS_ASSERTION(!mContentType.IsEmpty(), 
-                 "Content type should be known by now.");
     rv = FireListenerNotifications(request, aCtxt);
 
     if (NS_FAILED(rv)) {
       aStatus = rv;
     }
   }
 
   rv = mNextListener->OnStopRequest(request, aCtxt, aStatus);
@@ -359,39 +350,51 @@ void nsUnknownDecoder::DetermineContentT
                    sSnifferEntries[i].mContentTypeSniffer,
                    "Must have either a type string or a function to set the type");
       NS_ASSERTION(sSnifferEntries[i].mMimeType == nsnull ||
                    sSnifferEntries[i].mContentTypeSniffer == nsnull,
                    "Both a type string and a type sniffing function set;"
                    " using type string");
       if (sSnifferEntries[i].mMimeType) {
         mContentType = sSnifferEntries[i].mMimeType;
+        NS_ASSERTION(!mContentType.IsEmpty(), 
+                     "Content type should be known by now.");
         return;
       }
-      else if ((this->*(sSnifferEntries[i].mContentTypeSniffer))(aRequest)) {
+      if ((this->*(sSnifferEntries[i].mContentTypeSniffer))(aRequest)) {
+        NS_ASSERTION(!mContentType.IsEmpty(), 
+                     "Content type should be known by now.");
         return;
       }        
     }
   }
 
   if (TryContentSniffers(aRequest)) {
+    NS_ASSERTION(!mContentType.IsEmpty(), 
+                 "Content type should be known by now.");
     return;
   }
 
   if (SniffForHTML(aRequest)) {
+    NS_ASSERTION(!mContentType.IsEmpty(), 
+                 "Content type should be known by now.");
     return;
   }
   
   // We don't know what this is yet.  Before we just give up, try
   // the URI from the request.
   if (SniffURI(aRequest)) {
+    NS_ASSERTION(!mContentType.IsEmpty(), 
+                 "Content type should be known by now.");
     return;
   }
   
   LastDitchSniff(aRequest);
+  NS_ASSERTION(!mContentType.IsEmpty(), 
+               "Content type should be known by now.");
 }
 
 PRBool nsUnknownDecoder::TryContentSniffers(nsIRequest* aRequest)
 {
   // Enumerate content sniffers
   nsCOMPtr<nsICategoryManager> catMan(do_GetService("@mozilla.org/categorymanager;1"));
   if (!catMan) {
     return PR_FALSE;
@@ -595,34 +598,38 @@ PRBool nsUnknownDecoder::LastDitchSniff(
 
 nsresult nsUnknownDecoder::FireListenerNotifications(nsIRequest* request,
                                                      nsISupports *aCtxt)
 {
   nsresult rv = NS_OK;
 
   if (!mNextListener) return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIViewSourceChannel> viewSourceChannel = do_QueryInterface(request);
-  if (viewSourceChannel) {
-    rv = viewSourceChannel->SetOriginalContentType(mContentType);
-  } else {
-    nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
-    if (NS_SUCCEEDED(rv)) {
-      // Set the new content type on the channel...
-      rv = channel->SetContentType(mContentType);
+  if (!mContentType.IsEmpty()) {
+    nsCOMPtr<nsIViewSourceChannel> viewSourceChannel =
+      do_QueryInterface(request);
+    if (viewSourceChannel) {
+      rv = viewSourceChannel->SetOriginalContentType(mContentType);
+    } else {
+      nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
+      if (NS_SUCCEEDED(rv)) {
+        // Set the new content type on the channel...
+        rv = channel->SetContentType(mContentType);
+      }
     }
-  }
+
+    NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to set content type on channel!");
 
-  NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to set content type on channel!");
-  if (NS_FAILED(rv)) {
-    // Cancel the request to make sure it has the correct status if
-    // mNextListener looks at it.
-    request->Cancel(rv);
-    mNextListener->OnStartRequest(request, aCtxt);
-    return rv;
+    if (NS_FAILED(rv)) {
+      // Cancel the request to make sure it has the correct status if
+      // mNextListener looks at it.
+      request->Cancel(rv);
+      mNextListener->OnStartRequest(request, aCtxt);
+      return rv;
+    }
   }
 
   // Fire the OnStartRequest(...)
   rv = mNextListener->OnStartRequest(request, aCtxt);
 
   if (!mBuffer) return NS_ERROR_OUT_OF_MEMORY;
 
   // If the request was canceled, then we need to treat that equivalently
@@ -659,14 +666,68 @@ nsresult nsUnknownDecoder::FireListenerN
   mBufferLen = 0;
 
   return rv;
 }
 
 void
 nsBinaryDetector::DetermineContentType(nsIRequest* aRequest)
 {
+  nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
+  if (!httpChannel) {
+    return;
+  }
+
+  // It's an HTTP channel.  Check for the text/plain mess
+  nsCAutoString contentTypeHdr;
+  httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
+                                 contentTypeHdr);
+  nsCAutoString contentType;
+  httpChannel->GetContentType(contentType);
+
+  // Make sure to do a case-sensitive exact match comparison here.  Apache
+  // 1.x just sends text/plain for "unknown", while Apache 2.x sends
+  // text/plain with a ISO-8859-1 charset.  Debian's Apache version, just to
+  // be different, sends text/plain with iso-8859-1 charset.  Don't do
+  // general case-insensitive comparison, since we really want to apply this
+  // crap as rarely as we can.
+  if (!contentType.EqualsLiteral("text/plain") ||
+      (!contentTypeHdr.EqualsLiteral("text/plain") &&
+       !contentTypeHdr.EqualsLiteral("text/plain; charset=ISO-8859-1") &&
+       !contentTypeHdr.EqualsLiteral("text/plain; charset=iso-8859-1"))) {
+    return;
+  }
+
+  // Check whether we have content-encoding.  If we do, don't try to
+  // detect the type.
+  // XXXbz we could improve this by doing a local decompress if we
+  // wanted, I'm sure.  
+  nsCAutoString contentEncoding;
+  httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
+                                 contentEncoding);
+  if (!contentEncoding.IsEmpty()) {
+    return;
+  }
+  
   LastDitchSniff(aRequest);
   if (mContentType.Equals(APPLICATION_OCTET_STREAM)) {
     // We want to guess at it instead
     mContentType = APPLICATION_GUESS_FROM_EXT;
   }
 }
+
+NS_METHOD
+nsBinaryDetector::Register(nsIComponentManager* compMgr, nsIFile* path, 
+                           const char* registryLocation,
+                           const char* componentType, 
+                           const nsModuleComponentInfo *info)
+{
+  nsresult rv;
+  nsCOMPtr<nsICategoryManager> catman =
+    do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) 
+     return rv;
+ 
+  return catman->AddCategoryEntry(NS_CONTENT_SNIFFER_CATEGORY,
+                                  "Binary Detector", 
+                                  NS_BINARYDETECTOR_CONTRACTID,
+                                  PR_TRUE, PR_TRUE, nsnull);
+}
--- a/netwerk/streamconv/converters/nsUnknownDecoder.h
+++ b/netwerk/streamconv/converters/nsUnknownDecoder.h
@@ -36,16 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsUnknownDecoder_h__
 #define nsUnknownDecoder_h__
 
 #include "nsIStreamConverter.h"
 #include "nsIChannel.h"
 #include "nsIContentSniffer.h"
+#include "nsIGenericFactory.h"
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 
 #define NS_UNKNOWNDECODER_CID                        \
 { /* 7d7008a0-c49a-11d3-9b22-0080c7cb1080 */         \
     0x7d7008a0,                                      \
     0xc49a,                                          \
@@ -153,14 +154,20 @@ protected:
 /**
  * Class that detects whether a data stream is text or binary.  This reuses
  * most of nsUnknownDecoder except the actual content-type determination logic
  * -- our overridden DetermineContentType simply calls LastDitchSniff and sets
  * the type to APPLICATION_GUESS_FROM_EXT if the data is detected as binary.
  */
 class nsBinaryDetector : public nsUnknownDecoder
 {
+public:
+  static NS_METHOD Register(nsIComponentManager* compMgr, nsIFile* path, 
+                            const char* registryLocation,
+                            const char* componentType, 
+                            const nsModuleComponentInfo *info);
+  
 protected:
   virtual void DetermineContentType(nsIRequest* aRequest);
 };
 
 #endif /* nsUnknownDecoder_h__ */
 
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -272,72 +272,17 @@ NS_IMETHODIMP nsDocumentOpenInfo::OnStar
   
     //
     // The transaction has already reported an error - so it will be torn
     // down. Therefore, it is not necessary to return an error code...
     //
     return NS_OK;
   }
 
-  if (httpChannel && mContentType.IsEmpty()) {
-    // This is our initial dispatch, and this is an HTTP channel.  Check for
-    // the text/plain mess.
-    nsCAutoString contentTypeHdr;
-    httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
-                                   contentTypeHdr);
-    nsCAutoString contentType;
-    httpChannel->GetContentType(contentType);
-    
-    // Make sure to do a case-sensitive exact match comparison here.  Apache
-    // 1.x just sends text/plain for "unknown", while Apache 2.x sends
-    // text/plain with a ISO-8859-1 charset.  Debian's Apache version, just to
-    // be different, sends text/plain with iso-8859-1 charset.  Don't do
-    // general case-insensitive comparison, since we really want to apply this
-    // crap as rarely as we can.
-    if (contentType.EqualsLiteral("text/plain") &&
-        (contentTypeHdr.EqualsLiteral("text/plain") ||
-         contentTypeHdr.Equals(
-             NS_LITERAL_CSTRING("text/plain; charset=ISO-8859-1")) ||
-         contentTypeHdr.Equals(
-             NS_LITERAL_CSTRING("text/plain; charset=iso-8859-1")))) {
-      // Check whether we have content-encoding.  If we do, don't try to detect
-      // the type, since that will lead to the content being automatically
-      // decompressed....
-      nsCAutoString contentEncoding;
-      httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
-                                     contentEncoding);
-      if (contentEncoding.IsEmpty()) {
-        // OK, this is initial dispatch of an HTTP response and its Content-Type
-        // header is exactly "text/plain".  We need to check whether this is
-        // really text....  Note that some of our listeners will actually
-        // accept all types, including the APPLICATION_MAYBE_TEXT internal
-        // type, so we need to call ConvertData here manually instead of
-        // relying on DispatchContent to do it.
-        LOG(("  Possibly bogus text/plain; trying to sniff for real type"));
-        rv = ConvertData(request, m_contentListener,
-                         NS_LITERAL_CSTRING(APPLICATION_MAYBE_TEXT),
-                         NS_LITERAL_CSTRING("*/*"));
-        if (NS_FAILED(rv)) {
-          // We failed to convert.  Just go ahead and handle as the original
-          // type.  If ConvertData happened to set our m_targetStreamListener,
-          // we don't want it!
-          m_targetStreamListener = nsnull;
-        }
-        else {
-          LOG((APPLICATION_MAYBE_TEXT " converter taking over now"));
-        }
-      }
-    }
-  }
-
-  // If we sniffed text/plain above, m_targetStreamListener may already be
-  // non-null.
-  if (!m_targetStreamListener) {
-    rv = DispatchContent(request, aCtxt);
-  }
+  rv = DispatchContent(request, aCtxt);
 
   LOG(("  After dispatch, m_targetStreamListener: 0x%p, rv: 0x%08X", m_targetStreamListener.get(), rv));
 
   NS_ASSERTION(NS_SUCCEEDED(rv) || !m_targetStreamListener,
                "Must not have an m_targetStreamListener with a failure return!");
 
   NS_ENSURE_SUCCESS(rv, rv);