Merge e10s -> m-c. a=patches
authorDan Witte <dwitte@mozilla.com>
Fri, 27 Aug 2010 08:04:00 -0700
changeset 51568 db88acba9e11f160e01c57de6ce03c3c2a4e33e8
parent 51564 a6c18a123fbbd3b8eee55177e6b56deb13f01c8a (current diff)
parent 51567 54a5ae891dba6ba156238b42825176deebf78a7f (diff)
child 51569 d8396a35d70aee853cf615d4eabf28659efa6ecd
push idunknown
push userunknown
push dateunknown
reviewerspatches
milestone2.0b5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge e10s -> m-c. a=patches
content/base/src/nsDocument.cpp
dom/ipc/TabChild.cpp
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -6713,24 +6713,21 @@ nsDocument::RetrieveRelevantHeaders(nsIC
 
         if (NS_SUCCEEDED(rv)) {
           PRInt64 intermediateValue;
           LL_I2L(intermediateValue, PR_USEC_PER_MSEC);
           LL_MUL(modDate, msecs, intermediateValue);
         }
       }
     } else {
-      nsCOMPtr<nsIMultiPartChannel> partChannel = do_QueryInterface(aChannel);
-      if (partChannel) {
-        nsCAutoString contentDisp;
-        rv = partChannel->GetContentDisposition(contentDisp);
-        if (NS_SUCCEEDED(rv) && !contentDisp.IsEmpty()) {
-          SetHeaderData(nsGkAtoms::headerContentDisposition,
-                        NS_ConvertASCIItoUTF16(contentDisp));
-        }
+      nsCAutoString contentDisp;
+      rv = aChannel->GetContentDisposition(contentDisp);
+      if (NS_SUCCEEDED(rv) && !contentDisp.IsEmpty()) {
+        SetHeaderData(nsGkAtoms::headerContentDisposition,
+                      NS_ConvertASCIItoUTF16(contentDisp));
       }
     }
   }
 
   if (LL_IS_ZERO(modDate)) {
     // We got nothing from our attempt to ask nsIFileChannel and
     // nsIHttpChannel for the last modified time. Return the current
     // time.
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -2402,16 +2402,17 @@ NOT_IMPLEMENTED_IF_FUNC_1(GetOwner, nsIS
 NOT_IMPLEMENTED_IF_FUNC_1(SetOwner, nsISupports *owner)
 NOT_IMPLEMENTED_IF_FUNC_1(SetNotificationCallbacks,
                           nsIInterfaceRequestor *callbacks)
 NOT_IMPLEMENTED_IF_FUNC_1(GetSecurityInfo, nsISupports **securityInfo)
 NOT_IMPLEMENTED_IF_FUNC_1(GetContentType, nsACString &value)
 NOT_IMPLEMENTED_IF_FUNC_1(SetContentType, const nsACString &value)
 NOT_IMPLEMENTED_IF_FUNC_1(GetContentCharset, nsACString &value)
 NOT_IMPLEMENTED_IF_FUNC_1(SetContentCharset, const nsACString &value)
+NOT_IMPLEMENTED_IF_FUNC_1(GetContentDisposition, nsACString &value)
 NOT_IMPLEMENTED_IF_FUNC_1(GetContentLength, PRInt64 *value)
 NOT_IMPLEMENTED_IF_FUNC_1(SetContentLength, PRInt64 value)
 NOT_IMPLEMENTED_IF_FUNC_1(Open, nsIInputStream **_retval)
 NOT_IMPLEMENTED_IF_FUNC_2(AsyncOpen, nsIStreamListener *listener,
                           nsISupports *context)
 
 //-----------------------------------------------------------------------------
 // nsWebSocketEstablishedConnection::nsIHttpAuthenticableChannel
--- a/content/html/document/src/nsWyciwygChannel.cpp
+++ b/content/html/document/src/nsWyciwygChannel.cpp
@@ -260,16 +260,23 @@ nsWyciwygChannel::GetContentCharset(nsAC
 
 NS_IMETHODIMP
 nsWyciwygChannel::SetContentCharset(const nsACString &aContentCharset)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+nsWyciwygChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+  aContentDisposition.Truncate();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsWyciwygChannel::GetContentLength(PRInt64 *aContentLength)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsWyciwygChannel::SetContentLength(PRInt64 aContentLength)
 {
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -116,17 +116,19 @@ parent:
 
     PGeolocationRequest(URI uri);
 
     PContentDialog(PRUint32 aType, nsCString aName, nsCString aFeatures,
                    PRInt32[] aIntParams, nsString[] aStringParams);
 
     __delete__();
 
-    PExternalHelperApp(URI uri, nsCString aMimeContentType, bool aForceSave, PRInt64 aContentLength);
+    PExternalHelperApp(URI uri, nsCString aMimeContentType,
+                       nsCString aContentDisposition, bool aForceSave,
+                       PRInt64 aContentLength);
 
 child:
     CreateWidget(MagicWindowHandle parentWidget);
 
     LoadURL(nsCString uri);
 
     Move(PRUint32 x,
          PRUint32 y,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1247,16 +1247,17 @@ TabChildGlobal::GetPrincipal()
   if (!mTabChild)
     return nsnull;
   return mTabChild->GetPrincipal();
 }
 
 PExternalHelperAppChild*
 TabChild::AllocPExternalHelperApp(const IPC::URI& uri,
                                   const nsCString& aMimeContentType,
+                                  const nsCString& aContentDisposition,
                                   const bool& aForceSave,
                                   const PRInt64& aContentLength)
 {
   ExternalHelperAppChild *child = new ExternalHelperAppChild();
   child->AddRef();
   return child;
 }
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -222,16 +222,17 @@ public:
                                                      const nsCString&,
                                                      const nsCString&,
                                                      const nsTArray<int>&,
                                                      const nsTArray<nsString>&);
     virtual bool DeallocPContentDialog(PContentDialogChild* aDialog);
     virtual PExternalHelperAppChild *AllocPExternalHelperApp(
             const IPC::URI& uri,
             const nsCString& aMimeContentType,
+            const nsCString& aContentDisposition,
             const bool& aForceSave,
             const PRInt64& aContentLength);
     virtual bool DeallocPExternalHelperApp(PExternalHelperAppChild *aService);
     static void ParamsToArrays(nsIDialogParamBlock* aParams,
                                nsTArray<int>& aIntParams,
                                nsTArray<nsString>& aStringParams);
     static void ArraysToParams(const nsTArray<int>& aIntParams,
                                const nsTArray<nsString>& aStringParams,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -806,22 +806,23 @@ TabParent::GetFrameLoader() const
 {
   nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(mFrameElement);
   return frameLoaderOwner ? frameLoaderOwner->GetFrameLoader() : nsnull;
 }
 
 PExternalHelperAppParent*
 TabParent::AllocPExternalHelperApp(const IPC::URI& uri,
                                    const nsCString& aMimeContentType,
+                                   const nsCString& aContentDisposition,
                                    const bool& aForceSave,
                                    const PRInt64& aContentLength)
 {
   ExternalHelperAppParent *parent = new ExternalHelperAppParent(uri, aContentLength);
   parent->AddRef();
-  parent->Init(this, aMimeContentType, aForceSave);
+  parent->Init(this, aMimeContentType, aContentDisposition, aForceSave);
   return parent;
 }
 
 bool
 TabParent::DeallocPExternalHelperApp(PExternalHelperAppParent* aService)
 {
   ExternalHelperAppParent *parent = static_cast<ExternalHelperAppParent *>(aService);
   parent->Release();
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -145,16 +145,17 @@ public:
     {
       delete aDialog;
       return true;
     }
 
     virtual PExternalHelperAppParent* AllocPExternalHelperApp(
             const IPC::URI& uri,
             const nsCString& aMimeContentType,
+            const nsCString& aContentDisposition,
             const bool& aForceSave,
             const PRInt64& aContentLength);
     virtual bool DeallocPExternalHelperApp(PExternalHelperAppParent* aService);
 
     void LoadURL(nsIURI* aURI);
     void Move(PRUint32 x, PRUint32 y, PRUint32 width, PRUint32 height);
     void Activate();
     void SendMouseEvent(const nsAString& aType, float aX, float aY,
--- a/dom/src/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -1007,16 +1007,22 @@ nsJSChannel::GetContentCharset(nsACStrin
 
 NS_IMETHODIMP
 nsJSChannel::SetContentCharset(const nsACString &aContentCharset)
 {
     return mStreamChannel->SetContentCharset(aContentCharset);
 }
 
 NS_IMETHODIMP
+nsJSChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+    return mStreamChannel->GetContentDisposition(aContentDisposition);
+}
+
+NS_IMETHODIMP
 nsJSChannel::GetContentLength(PRInt64 *aContentLength)
 {
     return mStreamChannel->GetContentLength(aContentLength);
 }
 
 NS_IMETHODIMP
 nsJSChannel::SetContentLength(PRInt64 aContentLength)
 {
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -627,16 +627,23 @@ nsJARChannel::GetContentCharset(nsACStri
 NS_IMETHODIMP
 nsJARChannel::SetContentCharset(const nsACString &aContentCharset)
 {
     mContentCharset = aContentCharset;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsJARChannel::GetContentDisposition(nsACString &result)
+{
+    result = mContentDisposition;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsJARChannel::GetContentLength(PRInt64 *result)
 {
     // if content length is unknown, query mJarInput...
     if (mContentLength < 0 && mJarInput)
         mContentLength = mJarInput->GetContentLength();
 
     *result = mContentLength;
     return NS_OK;
@@ -766,51 +773,45 @@ nsJARChannel::OnDownloadComplete(nsIDown
             }
             if (NS_SUCCEEDED(status)) {
                 status = rv;
             }
         }
     }
 
     if (NS_SUCCEEDED(status) && channel) {
-        nsCAutoString header;
         // Grab the security info from our base channel
         channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
 
         nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
         if (httpChannel) {
             // We only want to run scripts if the server really intended to
             // send us a JAR file.  Check the server-supplied content type for
             // a JAR type.
+            nsCAutoString header;
             httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
                                            header);
             nsCAutoString contentType;
             nsCAutoString charset;
             NS_ParseContentType(header, contentType, charset);
             nsCAutoString channelContentType;
             channel->GetContentType(channelContentType);
             mIsUnsafe = !(contentType.Equals(channelContentType) &&
                           (contentType.EqualsLiteral("application/java-archive") ||
                            contentType.EqualsLiteral("application/x-jar")));
-            rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Disposition"),
-                                                header);
-            if (NS_SUCCEEDED(rv))
-                SetPropertyAsACString(NS_CHANNEL_PROP_CONTENT_DISPOSITION, header);
         } else {
             nsCOMPtr<nsIJARChannel> innerJARChannel(do_QueryInterface(channel));
             if (innerJARChannel) {
                 PRBool unsafe;
                 innerJARChannel->GetIsUnsafe(&unsafe);
                 mIsUnsafe = unsafe;
             }
-            // Soon-to-be common way to get Disposition: right now only nsIJARChannel
-            rv = NS_GetContentDisposition(request, header);
-            if (NS_SUCCEEDED(rv))
-                SetPropertyAsACString(NS_CHANNEL_PROP_CONTENT_DISPOSITION, header);
         }
+
+        channel->GetContentDisposition(mContentDisposition);
     }
 
     if (NS_SUCCEEDED(status) && mIsUnsafe) {
         PRBool allowUnpack = PR_FALSE;
 
         nsCOMPtr<nsIPrefBranch> prefs =
             do_GetService(NS_PREFSERVICE_CONTRACTID);
         if (prefs) {
--- a/modules/libjar/nsJARChannel.h
+++ b/modules/libjar/nsJARChannel.h
@@ -91,16 +91,17 @@ private:
     nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
     nsCOMPtr<nsISupports>           mSecurityInfo;
     nsCOMPtr<nsIProgressEventSink>  mProgressSink;
     nsCOMPtr<nsILoadGroup>          mLoadGroup;
     nsCOMPtr<nsIStreamListener>     mListener;
     nsCOMPtr<nsISupports>           mListenerContext;
     nsCString                       mContentType;
     nsCString                       mContentCharset;
+    nsCString                       mContentDisposition;
     PRInt64                         mContentLength;
     PRUint32                        mLoadFlags;
     nsresult                        mStatus;
     PRPackedBool                    mIsPending;
     PRPackedBool                    mIsUnsafe;
 
     nsJARInputThunk                *mJarInput;
     nsCOMPtr<nsIStreamListener>     mDownloader;
--- a/modules/libpr0n/decoders/icon/beos/nsIconChannel.cpp
+++ b/modules/libpr0n/decoders/icon/beos/nsIconChannel.cpp
@@ -402,16 +402,23 @@ NS_IMETHODIMP nsIconChannel::GetContentC
 NS_IMETHODIMP
 nsIconChannel::SetContentCharset(const nsACString &aContentCharset)
 {
   // It doesn't make sense to set the content-charset on this type
   // of channel...
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+nsIconChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+  aContentDisposition.Truncate();
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt64 *aContentLength)
 {
   *aContentLength = mContentLength;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt64 aContentLength)
 {
--- a/modules/libpr0n/decoders/icon/mac/nsIconChannelCocoa.mm
+++ b/modules/libpr0n/decoders/icon/mac/nsIconChannelCocoa.mm
@@ -394,16 +394,23 @@ NS_IMETHODIMP nsIconChannel::GetContentC
 NS_IMETHODIMP
 nsIconChannel::SetContentCharset(const nsACString &aContentCharset)
 {
   //It doesn't make sense to set the content-type on this type
   // of channel...
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+nsIconChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+  aContentDisposition.Truncate();
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt64 *aContentLength)
 {
   *aContentLength = mContentLength;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt64 aContentLength)
 {
--- a/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp
+++ b/modules/libpr0n/decoders/icon/os2/nsIconChannel.cpp
@@ -631,16 +631,23 @@ NS_IMETHODIMP nsIconChannel::GetContentC
 NS_IMETHODIMP
 nsIconChannel::SetContentCharset(const nsACString &aContentCharset)
 {
   // It doesn't make sense to set the content-charset on this type
   // of channel...
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+nsIconChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+  aContentDisposition.Truncate();
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt64 *aContentLength)
 {
   *aContentLength = mContentLength;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt64 aContentLength)
 {
--- a/modules/libpr0n/decoders/icon/win/nsIconChannel.cpp
+++ b/modules/libpr0n/decoders/icon/win/nsIconChannel.cpp
@@ -688,16 +688,23 @@ NS_IMETHODIMP nsIconChannel::GetContentC
 NS_IMETHODIMP
 nsIconChannel::SetContentCharset(const nsACString &aContentCharset)
 {
   // It doesn't make sense to set the content-charset on this type
   // of channel...
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+nsIconChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+  aContentDisposition.Truncate();
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt64 *aContentLength)
 {
   *aContentLength = mContentLength;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt64 aContentLength)
 {
--- a/modules/libpr0n/src/imgRequest.cpp
+++ b/modules/libpr0n/src/imgRequest.cpp
@@ -968,21 +968,20 @@ NS_IMETHODIMP imgRequest::OnDataAvailabl
      */
     PRUint32 out;
     inStr->ReadSegments(sniff_mimetype_callback, this, count, &out);
 
 #ifdef NS_DEBUG
     /* NS_WARNING if the content type from the channel isn't the same if the sniffing */
 #endif
 
+    nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
     if (mContentType.IsEmpty()) {
       LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |sniffing of mimetype failed|");
 
-      nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
-
       rv = NS_ERROR_FAILURE;
       if (chan) {
         rv = chan->GetContentType(mContentType);
       }
 
       if (NS_FAILED(rv)) {
         PR_LOG(gImgLog, PR_LOG_ERROR,
                ("[this=%p] imgRequest::OnDataAvailable -- Content type unavailable from the channel\n",
@@ -1012,24 +1011,18 @@ NS_IMETHODIMP imgRequest::OnDataAvailabl
     nsCOMPtr<nsISupportsCString> contentType(do_CreateInstance("@mozilla.org/supports-cstring;1"));
     if (contentType) {
       contentType->SetData(mContentType);
       mProperties->Set("type", contentType);
     }
 
     /* set our content disposition as a property */
     nsCAutoString disposition;
-    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
-    if (httpChannel) {
-      httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"), disposition);
-    } else {
-      nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
-      if (multiPartChannel) {
-        multiPartChannel->GetContentDisposition(disposition);
-      }
+    if (chan) {
+      chan->GetContentDisposition(disposition);
     }
     if (!disposition.IsEmpty()) {
       nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1"));
       if (contentDisposition) {
         contentDisposition->SetData(disposition);
         mProperties->Set("content-disposition", contentDisposition);
       }
     }
@@ -1079,16 +1072,17 @@ NS_IMETHODIMP imgRequest::OnDataAvailabl
     if (NS_FAILED(rv)) { // Probably bad mimetype
 
       this->Cancel(rv);
       return NS_BINDING_ABORTED;
     }
 
     if (imageType == imgIContainer::TYPE_RASTER) {
       /* Use content-length as a size hint for http channels. */
+      nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
       if (httpChannel) {
         PRInt64 contentLength;
         rv = httpChannel->GetContentLength(&contentLength);
         if (NS_SUCCEEDED(rv)) {
           // Pass anything usable on so that the RasterImage can preallocate
           // its source buffer
           if (contentLength > 0) {
             PRUint32 sizeHint = (PRUint32) contentLength;
--- a/netwerk/base/public/nsChannelProperties.h
+++ b/netwerk/base/public/nsChannelProperties.h
@@ -46,32 +46,22 @@
  * @file
  * This file contains constants for properties channels can expose.
  * They can be accessed by using QueryInterface to access the nsIPropertyBag
  * or nsIPropertyBag2 interface on a channel and reading the value.
  */
 
 
 /**
- * MIME Content-Disposition header of channel.  
- * Not available before onStartRequest. 
- * Type: nsACString
- */
-#define NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR "content-disposition"
-
-/**
  * Exists to allow content policy mechanism to function properly during channel
  * redirects.  Contains security contextual information about the load.
  * Type: nsIChannelPolicy
  */
 #define NS_CHANNEL_PROP_CHANNEL_POLICY_STR "channel-policy"
 
 #ifdef IMPL_NS_NET
-#define NS_CHANNEL_PROP_CONTENT_DISPOSITION gNetStrings->kContentDisposition
 #define NS_CHANNEL_PROP_CHANNEL_POLICY gNetStrings->kChannelPolicy
 #else
-#define NS_CHANNEL_PROP_CONTENT_DISPOSITION \
-  NS_LITERAL_STRING(NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR)
 #define NS_CHANNEL_PROP_CHANNEL_POLICY \
   NS_LITERAL_STRING(NS_CHANNEL_PROP_CHANNEL_POLICY_STR)
 #endif
 
 #endif
--- a/netwerk/base/public/nsIChannel.idl
+++ b/netwerk/base/public/nsIChannel.idl
@@ -51,17 +51,17 @@ interface nsIStreamListener;
  * by calling nsIChannel::open or nsIChannel::asyncOpen.
  *
  * After a request has been completed, the channel is still valid for accessing
  * protocol-specific results.  For example, QI'ing to nsIHttpChannel allows
  * response headers to be retrieved for the corresponding http transaction.
  *
  * This interface must be used only from the XPCOM main thread.
  */
-[scriptable, uuid(e0bb5c49-c54e-4efb-8f0d-6a7edd926fab)]
+[scriptable, uuid(3906f857-3d79-4716-be55-ed2455d666f4)]
 interface nsIChannel : nsIRequest
 {
     /**
      * The original URI used to construct the channel. This is used in
      * the case of a redirect or URI "resolution" (e.g. resolving a
      * resource: URI to a file: URI) so that the original pre-redirect
      * URI can still be obtained.  This is never null.  Attempts to
      * set it to null must throw.
@@ -153,16 +153,23 @@ interface nsIChannel : nsIRequest
      * The length of the data associated with the channel if available.  A value
      * of -1 indicates that the content length is unknown. Note that this
      * is a 64-bit value and obsoletes the "content-length" property used on
      * some channels.
      */
     attribute PRInt64 contentLength;
 
     /**
+     * Access to the Content-Disposition header if available and if applicable.
+     * This allows getting the preferred handling method, preferred filename,
+     * etc.  See RFC 2183.
+     */
+    readonly attribute ACString contentDisposition;
+
+    /**
      * Synchronously open the channel.
      *
      * @return blocking input stream to the channel's data.
      *
      * NOTE: nsIChannel implementations are not required to implement this
      * method.  Moreover, since this method may block the calling thread, it
      * should not be called on a thread that processes UI events.  Like any
      * other nsIChannel method it must not be called on any thread other
--- a/netwerk/base/public/nsIMultiPartChannel.idl
+++ b/netwerk/base/public/nsIMultiPartChannel.idl
@@ -40,32 +40,25 @@
 
 interface nsIChannel;
 
 /**
  * An interface to access the the base channel 
  * associated with a MultiPartChannel.
  */
 
-[scriptable, uuid(ba78db7b-b88c-4b76-baf9-3c2296a585ae)]
+[scriptable, uuid(51698f28-c975-4bce-a951-25130cda0113)]
 interface nsIMultiPartChannel : nsISupports
 {
     /**
      * readonly attribute to access the underlying channel
      */
     readonly attribute nsIChannel baseChannel;
 
     /**
-     * Access to the Content-Disposition header field of this part of
-     * a multipart message.  This allows getting the preferred
-     * handling method, preferred filename, etc.  See RFC 2183.
-     */
-    attribute ACString contentDisposition;
-
-    /**
      * Attribute guaranteed to be different for different parts of
      * the same multipart document.
      */
     readonly attribute PRUint32 partID;
 
     /**
      * Set to true when onStopRequest is received from the base channel.
      * The listener can check this from its onStopRequest to determine
--- a/netwerk/base/public/nsNetStrings.h
+++ b/netwerk/base/public/nsNetStrings.h
@@ -42,16 +42,15 @@
 /**
  * Class on which wide strings are available, to avoid constructing strings
  * wherever these strings are used.
  */
 class nsNetStrings {
 public:
   nsNetStrings();
 
-  const nsLiteralString kContentDisposition;
   const nsLiteralString kChannelPolicy;
 };
 
 extern NS_HIDDEN_(nsNetStrings*) gNetStrings;
 
 
 #endif
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -233,29 +233,16 @@ NS_NewChannel(nsIChannel           **res
             }
             if (NS_SUCCEEDED(rv))
                 chan.forget(result);
         }
     }
     return rv;
 }
 
-// For now, works only with JARChannel.  Future: with all channels that may
-// have Content-Disposition header (JAR, nsIHttpChannel, and nsIMultiPartChannel).
-inline nsresult
-NS_GetContentDisposition(nsIRequest     *channel,
-                         nsACString     &result)
-{
-    nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(channel));
-    if (props)
-        return props->GetPropertyAsACString(NS_CHANNEL_PROP_CONTENT_DISPOSITION,
-                                            result);
-    return NS_ERROR_NOT_AVAILABLE;
-}
-
 // Use this function with CAUTION. It creates a stream that blocks when you
 // Read() from it and blocking the UI thread is a bad idea. If you don't want
 // to implement a full blown asynchronous consumer (via nsIStreamListener) look
 // at nsIStreamLoader instead.
 inline nsresult
 NS_OpenURI(nsIInputStream       **result,
            nsIURI                *uri,
            nsIIOService          *ioService = nsnull,     // pass in nsIIOService to optimize callers
--- a/netwerk/base/src/nsBaseChannel.cpp
+++ b/netwerk/base/src/nsBaseChannel.cpp
@@ -499,16 +499,23 @@ nsBaseChannel::GetContentCharset(nsACStr
 NS_IMETHODIMP
 nsBaseChannel::SetContentCharset(const nsACString &aContentCharset)
 {
   mContentCharset = aContentCharset;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsBaseChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+  aContentDisposition = mContentDisposition;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsBaseChannel::GetContentLength(PRInt64 *aContentLength)
 {
   *aContentLength = mContentLength;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::SetContentLength(PRInt64 aContentLength)
--- a/netwerk/base/src/nsBaseChannel.h
+++ b/netwerk/base/src/nsBaseChannel.h
@@ -285,16 +285,17 @@ private:
   nsCOMPtr<nsILoadGroup>              mLoadGroup;
   nsCOMPtr<nsISupports>               mOwner;
   nsCOMPtr<nsISupports>               mSecurityInfo;
   nsCOMPtr<nsIStreamListener>         mListener;
   nsCOMPtr<nsISupports>               mListenerContext;
   nsCOMPtr<nsIChannel>                mRedirectChannel;
   nsCString                           mContentType;
   nsCString                           mContentCharset;
+  nsCString                           mContentDisposition;
   PRInt64                             mContentLength;
   PRUint32                            mLoadFlags;
   nsresult                            mStatus;
   PRPackedBool                        mQueriedProgressSink;
   PRPackedBool                        mSynthProgressEvents;
   PRPackedBool                        mWasOpened;
   PRPackedBool                        mWaitingOnAsyncRedirect;
   PRPackedBool                        mOpenRedirectChannel;
--- a/netwerk/base/src/nsNetStrings.cpp
+++ b/netwerk/base/src/nsNetStrings.cpp
@@ -35,13 +35,12 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsNetStrings.h"
 #include "nsChannelProperties.h"
 
 NS_HIDDEN_(nsNetStrings*) gNetStrings;
 
 nsNetStrings::nsNetStrings()
-  : NS_LITERAL_STRING_INIT(kContentDisposition, NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR),
-    NS_LITERAL_STRING_INIT(kChannelPolicy, NS_CHANNEL_PROP_CHANNEL_POLICY_STR)
+  : NS_LITERAL_STRING_INIT(kChannelPolicy, NS_CHANNEL_PROP_CHANNEL_POLICY_STR)
 {}
 
 
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -354,16 +354,28 @@ HttpBaseChannel::SetContentCharset(const
   } else {
     // Charset hint
     mContentCharsetHint = aContentCharset;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
+HttpBaseChannel::GetContentDisposition(nsACString& aContentDisposition)
+{
+  aContentDisposition.Truncate();
+
+  if (!mResponseHead)
+    return NS_ERROR_NOT_AVAILABLE;
+
+  mResponseHead->GetHeader(nsHttp::Content_Disposition, aContentDisposition);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 HttpBaseChannel::GetContentLength(PRInt64 *aContentLength)
 {
   if (!mResponseHead)
     return NS_ERROR_NOT_AVAILABLE;
 
   *aContentLength = mResponseHead->ContentLength();
   return NS_OK;
 }
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -124,16 +124,17 @@ public:
   NS_IMETHOD GetOwner(nsISupports **aOwner);
   NS_IMETHOD SetOwner(nsISupports *aOwner);
   NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks);
   NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks);
   NS_IMETHOD GetContentType(nsACString& aContentType);
   NS_IMETHOD SetContentType(const nsACString& aContentType);
   NS_IMETHOD GetContentCharset(nsACString& aContentCharset);
   NS_IMETHOD SetContentCharset(const nsACString& aContentCharset);
+  NS_IMETHOD GetContentDisposition(nsACString& aContentDisposition);
   NS_IMETHOD GetContentLength(PRInt64 *aContentLength);
   NS_IMETHOD SetContentLength(PRInt64 aContentLength);
   NS_IMETHOD Open(nsIInputStream **aResult);
 
   // HttpBaseChannel::nsIHttpChannel
   NS_IMETHOD GetRequestMethod(nsACString& aMethod);
   NS_IMETHOD SetRequestMethod(const nsACString& aMethod);
   NS_IMETHOD GetReferrer(nsIURI **referrer);
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -365,16 +365,24 @@ NS_IMETHODIMP
 nsViewSourceChannel::SetContentCharset(const nsACString &aContentCharset)
 {
     NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
 
     return mChannel->SetContentCharset(aContentCharset);
 }
 
 NS_IMETHODIMP
+nsViewSourceChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+    NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
+
+    return mChannel->GetContentDisposition(aContentDisposition);
+}
+
+NS_IMETHODIMP
 nsViewSourceChannel::GetContentLength(PRInt64 *aContentLength)
 {
     NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);
 
     return mChannel->GetContentLength(aContentLength);
 }
 
 NS_IMETHODIMP
--- a/netwerk/streamconv/converters/nsMultiMixedConv.cpp
+++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
@@ -340,23 +340,16 @@ nsPartChannel::SetContentLength(PRInt64 
 NS_IMETHODIMP
 nsPartChannel::GetContentDisposition(nsACString &aContentDisposition)
 {
     aContentDisposition = mContentDisposition;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPartChannel::SetContentDisposition(const nsACString &aContentDisposition)
-{
-    mContentDisposition = aContentDisposition;
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 nsPartChannel::GetPartID(PRUint32 *aPartID)
 {
     *aPartID = mPartID;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPartChannel::GetIsLastPart(PRBool *aIsLastPart)
@@ -795,18 +788,17 @@ nsMultiMixedConv::SendStart(nsIChannel *
     mPartChannel = newChannel;
 
     rv = mPartChannel->SetContentType(mContentType);
     if (NS_FAILED(rv)) return rv;
 
     rv = mPartChannel->SetContentLength(mContentLength);
     if (NS_FAILED(rv)) return rv;
 
-    rv = mPartChannel->SetContentDisposition(mContentDisposition);
-    if (NS_FAILED(rv)) return rv;
+    mPartChannel->SetContentDisposition(mContentDisposition);
 
     nsLoadFlags loadFlags = 0;
     mPartChannel->GetLoadFlags(&loadFlags);
     loadFlags |= nsIChannel::LOAD_REPLACE;
     mPartChannel->SetLoadFlags(loadFlags);
 
     nsCOMPtr<nsILoadGroup> loadGroup;
     (void)mPartChannel->GetLoadGroup(getter_AddRefs(loadGroup));
--- a/netwerk/streamconv/converters/nsMultiMixedConv.h
+++ b/netwerk/streamconv/converters/nsMultiMixedConv.h
@@ -72,16 +72,21 @@ public:
 
   void InitializeByteRange(PRInt64 aStart, PRInt64 aEnd);
   void SetIsLastPart() { mIsLastPart = PR_TRUE; }
   nsresult SendOnStartRequest(nsISupports* aContext);
   nsresult SendOnDataAvailable(nsISupports* aContext, nsIInputStream* aStream,
                                PRUint32 aOffset, PRUint32 aLen);
   nsresult SendOnStopRequest(nsISupports* aContext, nsresult aStatus);
 
+  void SetContentDisposition(const nsACString& aDisposition)
+  {
+    mContentDisposition = aDisposition;
+  }
+
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUEST
   NS_DECL_NSICHANNEL
   NS_DECL_NSIBYTERANGEREQUEST
   NS_DECL_NSIMULTIPARTCHANNEL
 
 protected:
   ~nsPartChannel();
--- a/netwerk/test/httpserver/nsIHttpServer.idl
+++ b/netwerk/test/httpserver/nsIHttpServer.idl
@@ -31,17 +31,17 @@
  * 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 "nsIPropertyBag.idl"
+#include "nsISupports.idl"
 
 interface nsIInputStream;
 interface nsILocalFile;
 interface nsIOutputStream;
 interface nsISimpleEnumerator;
 
 interface nsIHttpServer;
 interface nsIHttpServerStoppedCallback;
@@ -386,18 +386,18 @@ interface nsIHttpRequestHandler : nsISup
    */
   void handle(in nsIHttpRequest request, in nsIHttpResponse response);
 };
 
 
 /**
  * A representation of the data included in an HTTP request.
  */
-[scriptable, uuid(80cbca71-dc51-4fa0-9010-1cec262dbd4a)]
-interface nsIHttpRequest : nsIPropertyBag
+[scriptable, uuid(978cf30e-ad73-42ee-8f22-fe0aaf1bf5d2)]
+interface nsIHttpRequest : nsISupports
 {
   /**
    * The request type for this request (see RFC 2616, section 5.1.1).
    */
   readonly attribute string method;
 
   /**
    * The scheme of the requested path, usually 'http' but might possibly be
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -381,45 +381,31 @@ nsresult nsDocumentOpenInfo::DispatchCon
     aChannel->SetContentType(NS_LITERAL_CSTRING(APPLICATION_OCTET_STREAM));
   }
 
   // Check whether the data should be forced to be handled externally.  This
   // could happen because the Content-Disposition header is set so, or, in the
   // future, because the user has specified external handling for the MIME
   // type.
   PRBool forceExternalHandling = PR_FALSE;
+  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
   nsCAutoString disposition;
-  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
-  nsCOMPtr<nsIURI> uri;
-  if (httpChannel)
-  {
-    rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"),
-                                        disposition);
-    httpChannel->GetURI(getter_AddRefs(uri));
-  }
-  else
-  {
-    nsCOMPtr<nsIMultiPartChannel> multipartChannel(do_QueryInterface(request));
-    if (multipartChannel)
-    {
-      rv = multipartChannel->GetContentDisposition(disposition);
-    } else {
-      // Soon-to-be common way to get Disposition: right now only JARChannel
-      rv = NS_GetContentDisposition(request, disposition);
-    }
-  }
+  rv = aChannel->GetContentDisposition(disposition);
 
   LOG(("  Disposition header: '%s'", disposition.get()));
 
   if (NS_SUCCEEDED(rv) && !disposition.IsEmpty())
   {
     nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar = do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);
     if (NS_SUCCEEDED(rv))
     {
       nsCAutoString fallbackCharset;
+      nsCOMPtr<nsIURI> uri;
+      if (httpChannel)
+        httpChannel->GetURI(getter_AddRefs(uri));
       if (uri)
         uri->GetOriginCharset(fallbackCharset);
       nsAutoString dispToken;
       // Get the disposition type
       rv = mimehdrpar->GetParameter(disposition, "", fallbackCharset,
                                     PR_TRUE, nsnull, dispToken);
       // RFC 2183, section 2.8 says that an unknown disposition
       // value should be treated as "attachment"
--- a/uriloader/exthandler/ExternalHelperAppParent.cpp
+++ b/uriloader/exthandler/ExternalHelperAppParent.cpp
@@ -64,29 +64,31 @@ ExternalHelperAppParent::ExternalHelperA
   , mStatus(NS_OK)
   , mContentLength(aContentLength)
 {
 }
 
 void
 ExternalHelperAppParent::Init(TabParent *parent,
                               const nsCString& aMimeContentType,
+                              const nsCString& aContentDisposition,
                               const PRBool& aForceSave)
 {
   nsHashPropertyBag::Init();
 
   NS_ASSERTION(parent, "must have a non-null TabParent");
   nsCOMPtr<nsIContent> frame = do_QueryInterface(parent->GetOwnerElement());
   nsCOMPtr<nsISupports> container = frame->GetOwnerDoc()->GetContainer();
   nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(container);
 
   nsCOMPtr<nsIExternalHelperAppService> helperAppService =
     do_GetService(NS_EXTERNALHELPERAPPSERVICE_CONTRACTID);
   NS_ASSERTION(helperAppService, "No Helper App Service!");
 
+  mContentDisposition = aContentDisposition;
   helperAppService->DoContent(aMimeContentType, this, ir,
                               aForceSave, getter_AddRefs(mListener));
 }
 
 bool
 ExternalHelperAppParent::RecvOnStartRequest(const nsCString& entityID)
 {
   mEntityID = entityID;
@@ -291,16 +293,23 @@ ExternalHelperAppParent::GetContentChars
 
 NS_IMETHODIMP
 ExternalHelperAppParent::SetContentCharset(const nsACString& aContentCharset)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+ExternalHelperAppParent::GetContentDisposition(nsACString& aContentDisposition)
+{
+  aContentDisposition = mContentDisposition;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 ExternalHelperAppParent::GetContentLength(PRInt64 *aContentLength)
 {
   *aContentLength = mContentLength;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 ExternalHelperAppParent::SetContentLength(PRInt64 aContentLength)
--- a/uriloader/exthandler/ExternalHelperAppParent.h
+++ b/uriloader/exthandler/ExternalHelperAppParent.h
@@ -64,23 +64,25 @@ public:
 
     bool RecvOnStartRequest(const nsCString& entityID);
     bool RecvOnDataAvailable(const nsCString& data, const PRUint32& offset, const PRUint32& count);
     bool RecvOnStopRequest(const nsresult& code);
     
     ExternalHelperAppParent(const IPC::URI& uri, const PRInt64& contentLength);
     void Init(TabParent *parent,
               const nsCString& aMimeContentType,
+              const nsCString& aContentDisposition,
               const PRBool& aForceSave);
     virtual ~ExternalHelperAppParent();
 
 private:
   nsCOMPtr<nsIStreamListener> mListener;
   nsCOMPtr<nsIURI> mURI;
   PRBool mPending;
   nsLoadFlags mLoadFlags;
   nsresult mStatus;
   PRInt64 mContentLength;
+  nsCString mContentDisposition;
   nsCString mEntityID;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -217,41 +217,16 @@ static nsresult UnescapeFragment(const n
 {
   nsAutoString result;
   nsresult rv = UnescapeFragment(aFragment, aURI, result);
   if (NS_SUCCEEDED(rv))
     CopyUTF16toUTF8(result, aResult);
   return rv;
 }
 
-/** Gets the content-disposition header from a channel, using nsIHttpChannel
- * or nsIMultipartChannel if available
- * @param aChannel The channel to extract the disposition header from
- * @param aDisposition Reference to a string where the header is to be stored
- */
-static void ExtractDisposition(nsIChannel* aChannel, nsACString& aDisposition)
-{
-  aDisposition.Truncate();
-  // First see whether this is an http channel
-  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
-  if (httpChannel) 
-  {
-    httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"), aDisposition);
-  }
-  if (aDisposition.IsEmpty())
-  {
-    nsCOMPtr<nsIMultiPartChannel> multipartChannel(do_QueryInterface(aChannel));
-    if (multipartChannel)
-    {
-      multipartChannel->GetContentDisposition(aDisposition);
-    }
-  }
-
-}
-
 /** Extracts the filename out of a content-disposition header
  * @param aFilename [out] The filename. Can be empty on error.
  * @param aDisposition Value of a Content-Disposition header
  * @param aURI Optional. Will be used to get a fallback charset for the
  *        filename, if it is QI'able to nsIURL
  * @param aMIMEHeaderParam Optional. Pointer to a nsIMIMEHeaderParam class, so
  *        that it doesn't need to be fetched by this function.
  */
@@ -309,17 +284,17 @@ static PRBool GetFilenameAndExtensionFro
   /*
    * If the channel is an http or part of a multipart channel and we
    * have a content disposition header set, then use the file name
    * suggested there as the preferred file name to SUGGEST to the
    * user.  we shouldn't actually use that without their
    * permission... otherwise just use our temp file
    */
   nsCAutoString disp;
-  ExtractDisposition(aChannel, disp);
+  aChannel->GetContentDisposition(disp);
   PRBool handleExternally = PR_FALSE;
   nsCOMPtr<nsIURI> uri;
   nsresult rv;
   aChannel->GetURI(getter_AddRefs(uri));
   // content-disposition: has format:
   // disposition-type < ; name=value >* < ; filename=value > < ; name=value >*
   if (!disp.IsEmpty()) 
   {
@@ -673,29 +648,33 @@ NS_IMETHODIMP nsExternalHelperAppService
     item->GetTreeOwner(getter_AddRefs(owner));
     NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsITabChild> tabchild = do_GetInterface(owner);
     if (!tabchild)
       return NS_ERROR_FAILURE;
 
     PRInt64 contentLength = -1;
-    if (channel)
+    nsCString disp;
+    if (channel) {
       channel->GetContentLength(&contentLength);
+      channel->GetContentDisposition(disp);
+    }
+
 
     // Now we build a protocol for forwarding our data to the parent.  The
     // protocol will act as a listener on the child-side and create a "real"
     // helperAppService listener on the parent-side, via another call to
     // DoContent.
     using mozilla::dom::TabChild;
     using mozilla::dom::ExternalHelperAppChild;
     TabChild *child = static_cast<TabChild*>(tabchild.get());
     mozilla::dom::PExternalHelperAppChild *pc;
     pc = child->SendPExternalHelperAppConstructor(IPC::URI(uri),
-                                                  nsCString(aMimeContentType),
+                                                  nsCString(aMimeContentType), disp,
                                                   aForceSave, contentLength);
     ExternalHelperAppChild *childListener = static_cast<ExternalHelperAppChild *>(pc);
 
     NS_ADDREF(*aStreamListener = childListener);
 
     // FIXME:  Eventually we'll use this original listener to finish up client-side
     // work, such as closing a no-longer-needed window.  (Bug 588255)
     // nsExternalAppHandler * handler = new nsExternalAppHandler(nsnull,
--- a/uriloader/exthandler/nsExternalProtocolHandler.cpp
+++ b/uriloader/exthandler/nsExternalProtocolHandler.cpp
@@ -242,16 +242,22 @@ NS_IMETHODIMP nsExtProtocolChannel::GetC
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP nsExtProtocolChannel::SetContentCharset(const nsACString &aContentCharset)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP nsExtProtocolChannel::GetContentDisposition(nsACString &aContentDisposition)
+{
+  aContentDisposition.Truncate();
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsExtProtocolChannel::GetContentLength(PRInt64 * aContentLength)
 {
   *aContentLength = -1;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsExtProtocolChannel::SetContentLength(PRInt64 aContentLength)