diff --git a/dom/src/jsurl/nsJSProtocolHandler.cpp b/dom/src/jsurl/nsJSProtocolHandler.cpp index 7dd4b8fe97d..089105efb4b 100644 --- a/dom/src/jsurl/nsJSProtocolHandler.cpp +++ b/dom/src/jsurl/nsJSProtocolHandler.cpp @@ -1007,12 +1007,24 @@ nsJSChannel::GetContentDisposition(uint32_t *aContentDisposition) return mStreamChannel->GetContentDisposition(aContentDisposition); } +NS_IMETHODIMP +nsJSChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return mStreamChannel->SetContentDisposition(aContentDisposition); +} + NS_IMETHODIMP nsJSChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return mStreamChannel->GetContentDispositionFilename(aContentDispositionFilename); } +NS_IMETHODIMP +nsJSChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return mStreamChannel->SetContentDispositionFilename(aContentDispositionFilename); +} + NS_IMETHODIMP nsJSChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/image/decoders/icon/mac/nsIconChannelCocoa.mm b/image/decoders/icon/mac/nsIconChannelCocoa.mm index 69d0b7eb66a..a58c33dd6fa 100644 --- a/image/decoders/icon/mac/nsIconChannelCocoa.mm +++ b/image/decoders/icon/mac/nsIconChannelCocoa.mm @@ -367,12 +367,24 @@ nsIconChannel::GetContentDisposition(uint32_t *aContentDisposition) return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsIconChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsIconChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsIconChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsIconChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/image/decoders/icon/os2/nsIconChannel.cpp b/image/decoders/icon/os2/nsIconChannel.cpp index c9b89bac894..281c83cd4bf 100644 --- a/image/decoders/icon/os2/nsIconChannel.cpp +++ b/image/decoders/icon/os2/nsIconChannel.cpp @@ -605,12 +605,24 @@ nsIconChannel::GetContentDisposition(uint32_t *aContentDisposition) return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsIconChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsIconChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsIconChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsIconChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/image/decoders/icon/win/nsIconChannel.cpp b/image/decoders/icon/win/nsIconChannel.cpp index 885d25a1b41..780db7cdc45 100644 --- a/image/decoders/icon/win/nsIconChannel.cpp +++ b/image/decoders/icon/win/nsIconChannel.cpp @@ -619,12 +619,24 @@ nsIconChannel::GetContentDisposition(uint32_t *aContentDisposition) return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsIconChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsIconChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsIconChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsIconChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/modules/libjar/nsJARChannel.cpp b/modules/libjar/nsJARChannel.cpp index fc4c04d38e3..b40a1ee9595 100644 --- a/modules/libjar/nsJARChannel.cpp +++ b/modules/libjar/nsJARChannel.cpp @@ -610,12 +610,24 @@ nsJARChannel::GetContentDisposition(uint32_t *aContentDisposition) return NS_OK; } +NS_IMETHODIMP +nsJARChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsJARChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsJARChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsJARChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/netwerk/base/public/nsIChannel.idl b/netwerk/base/public/nsIChannel.idl index 78e86b8d721..3b5e3dbdf0d 100644 --- a/netwerk/base/public/nsIChannel.idl +++ b/netwerk/base/public/nsIChannel.idl @@ -24,7 +24,7 @@ interface nsIStreamListener; * * This interface must be used only from the XPCOM main thread. */ -[scriptable, uuid(06f6ada3-7729-4e72-8d3f-bf8ba630ff9b)] +[scriptable, uuid(98f3b51b-bb55-4276-a43c-db636f8d77e3)] interface nsIChannel : nsIRequest { /** @@ -254,11 +254,16 @@ interface nsIChannel : nsIRequest * if available and if applicable. This allows determining inline versus * attachment. * + * Setting contentDisposition provides a hint to the channel about the + * disposition. If a normal Content-Disposition header is present its + * value will always be used. If it is missing the hinted value will + * be used if set. + * * Implementations should throw NS_ERROR_NOT_AVAILABLE if the header either - * doesn't exist for this type of channel or is empty, and + * doesn't exist for this type of channel or is empty, and return * DISPOSITION_ATTACHMENT if an invalid/noncompliant value is present. */ - readonly attribute unsigned long contentDisposition; + attribute unsigned long contentDisposition; const unsigned long DISPOSITION_INLINE = 0; const unsigned long DISPOSITION_ATTACHMENT = 1; @@ -267,12 +272,17 @@ interface nsIChannel : nsIRequest * available and if applicable. This allows getting the preferred filename * without having to parse it out yourself. * + * Setting contentDispositionFilename provides a hint to the channel about + * the disposition. If a normal Content-Disposition header is present its + * value will always be used. If it is missing the hinted value will be + * used if set. + * * Implementations should throw NS_ERROR_NOT_AVAILABLE if the header doesn't * exist for this type of channel, if the header is empty, if the header * doesn't contain a filename portion, or the value of the filename * attribute is empty/missing. */ - readonly attribute AString contentDispositionFilename; + attribute AString contentDispositionFilename; /** * Access to the raw Content-Disposition header if available and applicable. diff --git a/netwerk/base/src/nsBaseChannel.cpp b/netwerk/base/src/nsBaseChannel.cpp index f3252200ee6..2544c3a7d1a 100644 --- a/netwerk/base/src/nsBaseChannel.cpp +++ b/netwerk/base/src/nsBaseChannel.cpp @@ -60,6 +60,7 @@ nsBaseChannel::nsBaseChannel() , mWasOpened(false) , mWaitingOnAsyncRedirect(false) , mStatus(NS_OK) + , mContentDispositionHint(UINT32_MAX) { mContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE); } @@ -490,13 +491,38 @@ nsBaseChannel::SetContentCharset(const nsACString &aContentCharset) NS_IMETHODIMP nsBaseChannel::GetContentDisposition(uint32_t *aContentDisposition) { - return NS_ERROR_NOT_AVAILABLE; + // preserve old behavior, fail unless explicitly set. + if (mContentDispositionHint == UINT32_MAX) { + return NS_ERROR_NOT_AVAILABLE; + } + + *aContentDisposition = mContentDispositionHint; + return NS_OK; +} + +NS_IMETHODIMP +nsBaseChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + mContentDispositionHint = aContentDisposition; + return NS_OK; } NS_IMETHODIMP nsBaseChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { - return NS_ERROR_NOT_AVAILABLE; + if (!mContentDispositionFilename) { + return NS_ERROR_NOT_AVAILABLE; + } + + aContentDispositionFilename = *mContentDispositionFilename; + return NS_OK; +} + +NS_IMETHODIMP +nsBaseChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + mContentDispositionFilename = new nsString(aContentDispositionFilename); + return NS_OK; } NS_IMETHODIMP diff --git a/netwerk/base/src/nsBaseChannel.h b/netwerk/base/src/nsBaseChannel.h index 1df7e746980..a82faf973e4 100644 --- a/netwerk/base/src/nsBaseChannel.h +++ b/netwerk/base/src/nsBaseChannel.h @@ -267,6 +267,8 @@ protected: nsCOMPtr mListener; nsCOMPtr mListenerContext; nsresult mStatus; + uint32_t mContentDispositionHint; + nsAutoPtr mContentDispositionFilename; }; #endif // !nsBaseChannel_h__ diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index a07e44d8643..2d1414abdaa 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -50,6 +50,7 @@ HttpBaseChannel::HttpBaseChannel() , mAllowSpdy(true) , mSuspendCount(0) , mProxyResolveFlags(0) + , mContentDispositionHint(UINT32_MAX) { LOG(("Creating HttpBaseChannel @%x\n", this)); @@ -365,11 +366,22 @@ HttpBaseChannel::GetContentDisposition(uint32_t *aContentDisposition) nsCString header; rv = GetContentDispositionHeader(header); - if (NS_FAILED(rv)) - return rv; + if (NS_FAILED(rv)) { + if (mContentDispositionHint == UINT32_MAX) + return rv; + + *aContentDisposition = mContentDispositionHint; + return NS_OK; + } *aContentDisposition = NS_GetContentDispositionFromHeader(header, this); + return NS_OK; +} +NS_IMETHODIMP +HttpBaseChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + mContentDispositionHint = aContentDisposition; return NS_OK; } @@ -377,18 +389,29 @@ NS_IMETHODIMP HttpBaseChannel::GetContentDispositionFilename(nsAString& aContentDispositionFilename) { aContentDispositionFilename.Truncate(); - nsresult rv; nsCString header; rv = GetContentDispositionHeader(header); - if (NS_FAILED(rv)) - return rv; + if (NS_FAILED(rv)) { + if (!mContentDispositionFilename) + return rv; + + aContentDispositionFilename = *mContentDispositionFilename; + return NS_OK; + } return NS_GetFilenameFromDisposition(aContentDispositionFilename, header, mURI); } +NS_IMETHODIMP +HttpBaseChannel::SetContentDispositionFilename(const nsAString& aContentDispositionFilename) +{ + mContentDispositionFilename = new nsString(aContentDispositionFilename); + return NS_OK; +} + NS_IMETHODIMP HttpBaseChannel::GetContentDispositionHeader(nsACString& aContentDispositionHeader) { diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index 1a8d781af7f..9bc4bdf6dda 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -88,7 +88,9 @@ public: NS_IMETHOD GetContentCharset(nsACString& aContentCharset); NS_IMETHOD SetContentCharset(const nsACString& aContentCharset); NS_IMETHOD GetContentDisposition(uint32_t *aContentDisposition); + NS_IMETHOD SetContentDisposition(uint32_t aContentDisposition); NS_IMETHOD GetContentDispositionFilename(nsAString& aContentDispositionFilename); + NS_IMETHOD SetContentDispositionFilename(const nsAString& aContentDispositionFilename); NS_IMETHOD GetContentDispositionHeader(nsACString& aContentDispositionHeader); NS_IMETHOD GetContentLength(int32_t *aContentLength); NS_IMETHOD SetContentLength(int32_t aContentLength); @@ -278,6 +280,9 @@ protected: uint32_t mProxyResolveFlags; nsCOMPtr mProxyURI; + + uint32_t mContentDispositionHint; + nsAutoPtr mContentDispositionFilename; }; // Share some code while working around C++'s absurd inability to handle casting diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp index 8df5a4bf83b..8fd3f6c04cc 100644 --- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp +++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp @@ -347,6 +347,14 @@ nsViewSourceChannel::GetContentDisposition(uint32_t *aContentDisposition) return mChannel->GetContentDisposition(aContentDisposition); } +NS_IMETHODIMP +nsViewSourceChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); + + return mChannel->SetContentDisposition(aContentDisposition); +} + NS_IMETHODIMP nsViewSourceChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { @@ -355,6 +363,14 @@ nsViewSourceChannel::GetContentDispositionFilename(nsAString &aContentDispositio return mChannel->GetContentDispositionFilename(aContentDispositionFilename); } +NS_IMETHODIMP +nsViewSourceChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); + + return mChannel->SetContentDispositionFilename(aContentDispositionFilename); +} + NS_IMETHODIMP nsViewSourceChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp index 98cc0eea485..f99b60762b0 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp @@ -524,12 +524,24 @@ WyciwygChannelChild::GetContentDisposition(uint32_t *aContentDisposition) return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +WyciwygChannelChild::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP WyciwygChannelChild::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +WyciwygChannelChild::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP WyciwygChannelChild::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp index f40aa36c4d6..1e9f486349b 100644 --- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp +++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp @@ -326,12 +326,24 @@ nsWyciwygChannel::GetContentDisposition(uint32_t *aContentDisposition) return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsWyciwygChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsWyciwygChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP +nsWyciwygChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsWyciwygChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.cpp b/netwerk/streamconv/converters/nsMultiMixedConv.cpp index 0f502e5fb5c..1564dad3b84 100644 --- a/netwerk/streamconv/converters/nsMultiMixedConv.cpp +++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp @@ -324,6 +324,12 @@ nsPartChannel::GetContentDisposition(uint32_t *aContentDisposition) return NS_OK; } +NS_IMETHODIMP +nsPartChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsPartChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { @@ -334,6 +340,13 @@ nsPartChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilen return NS_OK; } +NS_IMETHODIMP +nsPartChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + + NS_IMETHODIMP nsPartChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { diff --git a/uriloader/exthandler/ExternalHelperAppParent.cpp b/uriloader/exthandler/ExternalHelperAppParent.cpp index 90ee3bca59e..8beb4a0d378 100644 --- a/uriloader/exthandler/ExternalHelperAppParent.cpp +++ b/uriloader/exthandler/ExternalHelperAppParent.cpp @@ -284,6 +284,12 @@ ExternalHelperAppParent::GetContentDisposition(uint32_t *aContentDisposition) return NS_OK; } +NS_IMETHODIMP +ExternalHelperAppParent::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP ExternalHelperAppParent::GetContentDispositionFilename(nsAString& aContentDispositionFilename) { @@ -294,6 +300,12 @@ ExternalHelperAppParent::GetContentDispositionFilename(nsAString& aContentDispos return NS_OK; } +NS_IMETHODIMP +ExternalHelperAppParent::SetContentDispositionFilename(const nsAString& aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP ExternalHelperAppParent::GetContentDispositionHeader(nsACString& aContentDispositionHeader) { diff --git a/uriloader/exthandler/nsExternalProtocolHandler.cpp b/uriloader/exthandler/nsExternalProtocolHandler.cpp index 639ac3c4dfd..a9e99410e42 100644 --- a/uriloader/exthandler/nsExternalProtocolHandler.cpp +++ b/uriloader/exthandler/nsExternalProtocolHandler.cpp @@ -218,11 +218,21 @@ NS_IMETHODIMP nsExtProtocolChannel::GetContentDisposition(uint32_t *aContentDisp return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP nsExtProtocolChannel::SetContentDisposition(uint32_t aContentDisposition) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsExtProtocolChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename) { return NS_ERROR_NOT_AVAILABLE; } +NS_IMETHODIMP nsExtProtocolChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) +{ + return NS_ERROR_NOT_AVAILABLE; +} + NS_IMETHODIMP nsExtProtocolChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader) { return NS_ERROR_NOT_AVAILABLE;