diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index 37beb716b3d9..321901926600 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -732,6 +732,54 @@ nsHttpChannel::ProcessNormal() return rv; } +nsresult +nsHttpChannel::GetCallback(const nsIID &aIID, void **aResult) +{ + nsresult rv; + NS_ASSERTION(aResult, "Invalid argument in GetCallback!"); + rv = mCallbacks->GetInterface(aIID, aResult); + if (NS_FAILED(rv)) { + if (mLoadGroup) { + nsCOMPtr cbs; + rv = mLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs)); + if (NS_SUCCEEDED(rv)) + rv = cbs->GetInterface(aIID, aResult); + } + } + + return rv; +} + +nsresult +nsHttpChannel::PromptTempRedirect() +{ + nsresult rv; + nsCOMPtr bundleService = + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr stringBundle; + rv = bundleService->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(stringBundle)); + if (NS_FAILED(rv)) return rv; + + nsXPIDLString messageString; + rv = stringBundle->GetStringFromName(NS_LITERAL_STRING("RepostFormData").get(), getter_Copies(messageString)); + //GetStringFromName can return NS_OK and NULL messageString. + if (NS_SUCCEEDED(rv) && messageString) { + PRBool repost = PR_FALSE; + nsCOMPtr prompt; + rv = GetCallback(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt)); + if (NS_FAILED(rv)) return rv; + if (prompt) { + prompt->Confirm(nsnull, messageString, &repost); + if (!repost) + return NS_ERROR_FAILURE; + } + } + + return rv; +} + //----------------------------------------------------------------------------- // nsHttpChannel //----------------------------------------------------------------------------- @@ -1556,6 +1604,32 @@ nsHttpChannel::ProcessRedirection(PRUint32 redirectType) nsCOMPtr httpChannel = do_QueryInterface(newChannel); if (httpChannel) { + if (redirectType == 307 && mUploadStream) { + //307 is Temporary Redirect response. Redirect the postdata to the new URI. + rv = PromptTempRedirect(); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr seekable = do_QueryInterface(mUploadStream, &rv); + if (NS_FAILED(rv)) return rv; + rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr uploadChannel = do_QueryInterface(httpChannel, &rv); + if (NS_FAILED(rv)) return rv; + + if (mUploadStreamHasHeaders) + uploadChannel->SetUploadStream(mUploadStream, NS_LITERAL_CSTRING(""), -1); + else { + const char *ctype; + ctype = mRequestHead.PeekHeader(nsHttp::Content_Type); + const char *clength; + clength = mRequestHead.PeekHeader(nsHttp::Content_Length); + uploadChannel->SetUploadStream(mUploadStream, nsDependentCString(ctype), atoi(clength)); + } + + httpChannel->SetRequestMethod(nsDependentCString(mRequestHead.Method())); + } + nsCOMPtr httpInternal = do_QueryInterface(newChannel); NS_ENSURE_TRUE(httpInternal, NS_ERROR_UNEXPECTED); @@ -1929,21 +2003,9 @@ nsHttpChannel::PromptForUserPass(const char *host, LOG(("nsHttpChannel::PromptForUserPass [this=%x realm=%s]\n", this, realm)); nsresult rv; - nsCOMPtr authPrompt(do_GetInterface(mCallbacks, &rv)); - if (NS_FAILED(rv)) { - // Ok, perhaps the loadgroup's notification callbacks provide an auth prompt... - if (mLoadGroup) { - nsCOMPtr cbs; - rv = mLoadGroup->GetNotificationCallbacks(getter_AddRefs(cbs)); - if (NS_SUCCEEDED(rv)) - authPrompt = do_GetInterface(cbs, &rv); - } - if (NS_FAILED(rv)) { - // Unable to prompt -- return - NS_WARNING("notification callbacks should provide nsIAuthPrompt"); - return rv; - } - } + nsCOMPtr authPrompt; + rv = GetCallback(NS_GET_IID(nsIAuthPrompt), getter_AddRefs(authPrompt)); + if (NS_FAILED(rv)) return rv; // construct the domain string // we always add the port to domain since it is used diff --git a/netwerk/protocol/http/src/nsHttpChannel.h b/netwerk/protocol/http/src/nsHttpChannel.h index dcc46f90e581..8df7340474f5 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.h +++ b/netwerk/protocol/http/src/nsHttpChannel.h @@ -51,6 +51,7 @@ #include "nsIOutputStream.h" #include "nsIAsyncInputStream.h" #include "nsIInputStreamPump.h" +#include "nsIPrompt.h" class nsHttpResponseHead; class nsHttpAuthCache; @@ -117,6 +118,8 @@ private: nsresult ProcessNotModified(); nsresult ProcessRedirection(PRUint32 httpStatus); nsresult ProcessAuthentication(PRUint32 httpStatus); + nsresult GetCallback(const nsIID &aIID, void **aResult); + nsresult PromptTempRedirect(); // cache specific methods nsresult OpenCacheEntry(PRBool offline, PRBool *delayed); diff --git a/netwerk/resources/locale/en-US/necko.properties b/netwerk/resources/locale/en-US/necko.properties index cefbb406b036..c54a9a3147a2 100644 --- a/netwerk/resources/locale/en-US/necko.properties +++ b/netwerk/resources/locale/en-US/necko.properties @@ -48,6 +48,7 @@ EnterUserPasswordForProxy=Enter username and password for proxy at %1$S EnterUserPasswordFor=Enter username and password for %1$S EnterPasswordFor=Enter password for %1$S on %2$S UnsupportedFTPServer=The FTP server %1$S is currently unsupported. +RepostFormData=This web page is being redirected to a new location. Would you like to resend the form data you have typed to the new location? # Directory listing strings DirTitle=Index of %1$S