Bug 474536. Expose the underlying channel's content-disposition on jar: channels. r+sr=bzbarsky
☠☠ backed out by 8dccd5c59ad2 ☠ ☠
authorJason Duell <jduell.mcbugs@gmail.com>
Thu, 19 Feb 2009 15:25:18 -0500
changeset 25238 4bd7dd7645c209ec5065bab824994739587a7e51
parent 25237 d5aae349d1187b9476beba6dd0a923a14f241d39
child 25239 1145cd361cac627234cc19012d3e2b053a655917
child 25241 8dccd5c59ad200b7187886fd95d6847b11d03607
push id5463
push userbzbarsky@mozilla.com
push dateThu, 19 Feb 2009 20:25:39 +0000
treeherderautoland@4bd7dd7645c2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs474536
milestone1.9.2a1pre
Bug 474536. Expose the underlying channel's content-disposition on jar: channels. r+sr=bzbarsky
modules/libjar/nsJARChannel.cpp
modules/libjar/nsJARChannel.h
netwerk/base/public/nsChannelProperties.h
netwerk/base/public/nsNetStrings.h
netwerk/base/public/nsNetUtil.h
netwerk/base/src/nsNetStrings.cpp
netwerk/protocol/http/src/nsHttpAtomList.h
netwerk/streamconv/test/Makefile.in
uriloader/base/nsURILoader.cpp
--- a/modules/libjar/nsJARChannel.cpp
+++ b/modules/libjar/nsJARChannel.cpp
@@ -41,16 +41,17 @@
 #include "nsJARChannel.h"
 #include "nsJARProtocolHandler.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 #include "nsInt64.h"
 #include "nsEscape.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
+#include "nsChannelProperties.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsIFileURL.h"
 #include "nsIJAR.h"
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
@@ -213,16 +214,19 @@ nsJARInputThunk::ReadSegments(nsWriteSeg
 NS_IMETHODIMP
 nsJARInputThunk::IsNonBlocking(PRBool *nonBlocking)
 {
     *nonBlocking = PR_FALSE;
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
+// nsJARChannel
+//-----------------------------------------------------------------------------
+
 
 nsJARChannel::nsJARChannel()
     : mContentLength(-1)
     , mLoadFlags(LOAD_NORMAL)
     , mStatus(NS_OK)
     , mIsPending(PR_FALSE)
     , mIsUnsafe(PR_TRUE)
     , mJarInput(nsnull)
@@ -241,28 +245,33 @@ nsJARChannel::~nsJARChannel()
     // with the exception of certain error cases mJarInput will already be null.
     NS_IF_RELEASE(mJarInput);
 
     // release owning reference to the jar handler
     nsJARProtocolHandler *handler = gJarHandler;
     NS_RELEASE(handler); // NULL parameter
 }
 
-NS_IMPL_ISUPPORTS6(nsJARChannel,
-                   nsIRequest,
-                   nsIChannel,
-                   nsIStreamListener,
-                   nsIRequestObserver,
-                   nsIDownloadObserver,
-                   nsIJARChannel)
+NS_IMPL_ISUPPORTS_INHERITED6(nsJARChannel,
+                             nsHashPropertyBag,
+                             nsIRequest,
+                             nsIChannel,
+                             nsIStreamListener,
+                             nsIRequestObserver,
+                             nsIDownloadObserver,
+                             nsIJARChannel)
 
 nsresult 
 nsJARChannel::Init(nsIURI *uri)
 {
     nsresult rv;
+    rv = nsHashPropertyBag::Init();
+    if (NS_FAILED(rv))
+        return rv;
+
     mJarURI = do_QueryInterface(uri, &rv);
     if (NS_FAILED(rv))
         return rv;
 
     mOriginalURI = mJarURI;
 
     // Prevent loading jar:javascript URIs (see bug 290982).
     nsCOMPtr<nsIURI> innerURI;
@@ -747,41 +756,47 @@ 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);
-
             mIsUnsafe = !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);
         }
     }
 
     if (NS_SUCCEEDED(status) && mIsUnsafe) {
         PRBool allowUnpack = PR_FALSE;
 
         nsCOMPtr<nsIPrefBranch> prefs =
             do_GetService(NS_PREFSERVICE_CONTRACTID);
--- a/modules/libjar/nsJARChannel.h
+++ b/modules/libjar/nsJARChannel.h
@@ -42,29 +42,31 @@
 #include "nsIJARURI.h"
 #include "nsIInputStreamPump.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIProgressEventSink.h"
 #include "nsIStreamListener.h"
 #include "nsIZipReader.h"
 #include "nsIDownloader.h"
 #include "nsILoadGroup.h"
+#include "nsHashPropertyBag.h"
 #include "nsIFile.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "prlog.h"
 
 class nsJARInputThunk;
 
 //-----------------------------------------------------------------------------
 
 class nsJARChannel : public nsIJARChannel
                    , public nsIDownloadObserver
                    , public nsIStreamListener
+                   , public nsHashPropertyBag
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIREQUEST
     NS_DECL_NSICHANNEL
     NS_DECL_NSIJARCHANNEL
     NS_DECL_NSIDOWNLOADOBSERVER
     NS_DECL_NSIREQUESTOBSERVER
--- a/netwerk/base/public/nsChannelProperties.h
+++ b/netwerk/base/public/nsChannelProperties.h
@@ -53,16 +53,26 @@
 /**
  * Content-Length of a channel. Used instead of the nsIChannel.contentLength
  * property.
  * Not available before onStartRequest has been called.
  * Type: PRUint64
  */
 #define NS_CHANNEL_PROP_CONTENT_LENGTH_STR "content-length"
 
+/**
+ * MIME Content-Disposition header of channel.  
+ * Not available before onStartRequest. 
+ * Type: nsACString
+ */
+#define NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR "content-disposition"
+
 #ifdef IMPL_NS_NET
 #define NS_CHANNEL_PROP_CONTENT_LENGTH gNetStrings->kContentLength
+#define NS_CHANNEL_PROP_CONTENT_DISPOSITION gNetStrings->kContentDisposition
 #else
 #define NS_CHANNEL_PROP_CONTENT_LENGTH \
   NS_LITERAL_STRING(NS_CHANNEL_PROP_CONTENT_LENGTH_STR)
+#define NS_CHANNEL_PROP_CONTENT_DISPOSITION \
+  NS_LITERAL_STRING(NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR)
 #endif
 
 #endif
--- a/netwerk/base/public/nsNetStrings.h
+++ b/netwerk/base/public/nsNetStrings.h
@@ -44,14 +44,15 @@
  * wherever these strings are used.
  */
 class nsNetStrings {
 public:
   nsNetStrings();
 
   /** "content-length" */
   const nsLiteralString kContentLength;
+  const nsLiteralString kContentDisposition;
 };
 
 extern NS_HIDDEN_(nsNetStrings*) gNetStrings;
 
 
 #endif
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -57,16 +57,17 @@
 #include "nsIRequestObserverProxy.h"
 #include "nsISimpleStreamListener.h"
 #include "nsILoadGroup.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIIOService.h"
 #include "nsIServiceManager.h"
 #include "nsIChannel.h"
+#include "nsChannelProperties.h"
 #include "nsIInputStreamChannel.h"
 #include "nsITransport.h"
 #include "nsIStreamTransportService.h"
 #include "nsIHttpChannel.h"
 #include "nsIDownloader.h"
 #include "nsIStreamLoader.h"
 #include "nsIUnicharStreamLoader.h"
 #include "nsIPipe.h"
@@ -189,16 +190,29 @@ NS_NewChannel(nsIChannel           **res
                 *result = chan;
             else
                 NS_RELEASE(chan);
         }
     }
     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/nsNetStrings.cpp
+++ b/netwerk/base/src/nsNetStrings.cpp
@@ -36,11 +36,12 @@
 
 #include "nsNetStrings.h"
 #include "nsChannelProperties.h"
 
 NS_HIDDEN_(nsNetStrings*) gNetStrings;
 
 nsNetStrings::nsNetStrings()
   : NS_LITERAL_STRING_INIT(kContentLength, NS_CHANNEL_PROP_CONTENT_LENGTH_STR)
+  : NS_LITERAL_STRING_INIT(kContentDisposition, NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR)
 {}
 
 
--- a/netwerk/protocol/http/src/nsHttpAtomList.h
+++ b/netwerk/protocol/http/src/nsHttpAtomList.h
@@ -57,16 +57,17 @@ HTTP_ATOM(Accept_Language,           "Ac
 HTTP_ATOM(Accept_Ranges,             "Accept-Ranges")
 HTTP_ATOM(Age,                       "Age")
 HTTP_ATOM(Allow,                     "Allow")
 HTTP_ATOM(Authentication,            "Authentication")
 HTTP_ATOM(Authorization,             "Authorization")
 HTTP_ATOM(Cache_Control,             "Cache-Control")
 HTTP_ATOM(Connection,                "Connection")
 HTTP_ATOM(Content_Base,              "Content-Base")
+HTTP_ATOM(Content_Disposition,       "Content-Disposition")
 HTTP_ATOM(Content_Encoding,          "Content-Encoding")
 HTTP_ATOM(Content_Language,          "Content-Language")
 HTTP_ATOM(Content_Length,            "Content-Length")
 HTTP_ATOM(Content_Location,          "Content-Location")
 HTTP_ATOM(Content_MD5,               "Content-MD5")
 HTTP_ATOM(Content_Range,             "Content-Range")
 HTTP_ATOM(Content_Transfer_Encoding, "Content-Transfer-Encoding")
 HTTP_ATOM(Content_Type,              "Content-Type")
--- a/netwerk/streamconv/test/Makefile.in
+++ b/netwerk/streamconv/test/Makefile.in
@@ -68,9 +68,8 @@ LDFLAGS		+= -SUBSYSTEM:CONSOLE
 ifdef MOZ_NO_DEBUG_RTL
 DEFINES		+= -MOZ_NO_DEBUG_RTL
 endif
 ifdef NGPREFS
 DEFINES		+= -DNGPREFS
 endif
 endif # WINNT
 
-DEFINES += -DIMPL_NS_NET
--- a/uriloader/base/nsURILoader.cpp
+++ b/uriloader/base/nsURILoader.cpp
@@ -60,17 +60,17 @@
 #include "netCore.h"
 #include "nsCRT.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeOwner.h"
 
 #include "nsXPIDLString.h"
 #include "nsString.h"
-
+#include "nsNetUtil.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsReadableUtils.h"
 #include "nsDOMError.h"
 
 #include "nsICategoryManager.h"
 #include "nsCExternalHandlerService.h" // contains contractids for the helper app service
 
 #include "nsIMIMEHeaderParam.h"
@@ -375,16 +375,19 @@ nsresult nsDocumentOpenInfo::DispatchCon
     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);
     }
   }
 
   LOG(("  Disposition header: '%s'", disposition.get()));
 
   if (NS_SUCCEEDED(rv) && !disposition.IsEmpty())
   {
     nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar = do_GetService(NS_MIMEHEADERPARAM_CONTRACTID, &rv);