Bug 795442 - Allow nsIChannel.contentDispositionFilename to be writable. r=jduell, sr=biesi

This commit is contained in:
Tom Schuster 2012-10-02 09:43:00 -07:00
parent f6499768c2
commit e1dc8d9cc1
16 changed files with 212 additions and 11 deletions

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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.

View File

@ -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

View File

@ -267,6 +267,8 @@ protected:
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsISupports> mListenerContext;
nsresult mStatus;
uint32_t mContentDispositionHint;
nsAutoPtr<nsString> mContentDispositionFilename;
};
#endif // !nsBaseChannel_h__

View File

@ -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)
{

View File

@ -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<nsIURI> mProxyURI;
uint32_t mContentDispositionHint;
nsAutoPtr<nsString> mContentDispositionFilename;
};
// Share some code while working around C++'s absurd inability to handle casting

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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;