mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 536294 - e10s HTTP: redirects. r=jduell
--HG-- rename : netwerk/protocol/http/HttpChannelParent.cpp => netwerk/protocol/http/HttpChannelParentListener.cpp rename : netwerk/protocol/http/HttpChannelParent.h => netwerk/protocol/http/HttpChannelParentListener.h
This commit is contained in:
parent
82e0af39d5
commit
9eb088087e
@ -139,6 +139,7 @@ XPIDLSRCS = \
|
||||
nsIRandomGenerator.idl \
|
||||
nsIURIWithPrincipal.idl \
|
||||
nsIURIClassifier.idl \
|
||||
nsIRedirectResultListener.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
55
netwerk/base/public/nsIRedirectResultListener.idl
Normal file
55
netwerk/base/public/nsIRedirectResultListener.idl
Normal file
@ -0,0 +1,55 @@
|
||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsIApplicationCache.idl.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* 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 "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(85cd2640-e91e-41ac-bdca-1dbf10dc131e)]
|
||||
interface nsIRedirectResultListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* When an HTTP redirect has been processed (either successfully or not)
|
||||
* nsIHttpChannel will call this function if its callbacks implement this
|
||||
* interface.
|
||||
*
|
||||
* @param proceeding
|
||||
* Indicated whether the redirect will be proceeding, or not (i.e.
|
||||
* has been canceled, or failed).
|
||||
*/
|
||||
void onRedirectResult(in PRBool proceeding);
|
||||
};
|
@ -23,6 +23,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -87,11 +88,17 @@ void NeckoChild::DestroyNeckoChild()
|
||||
}
|
||||
|
||||
PHttpChannelChild*
|
||||
NeckoChild::AllocPHttpChannel(PBrowserChild* iframeEmbedding)
|
||||
NeckoChild::AllocPHttpChannel(PBrowserChild* browser)
|
||||
{
|
||||
// We don't allocate here: see HttpChannelChild::AsyncOpen()
|
||||
NS_RUNTIMEABORT("AllocPHttpChannel should not be called");
|
||||
return nsnull;
|
||||
// This constructor is only used when PHttpChannel is constructed by
|
||||
// the parent process, e.g. during a redirect. (Normally HttpChannelChild is
|
||||
// created by nsHttpHandler::NewProxiedChannel(), and then creates the
|
||||
// PHttpChannel in HttpChannelChild::AsyncOpen().)
|
||||
|
||||
// No need to store PBrowser. It is only needed by the parent.
|
||||
HttpChannelChild* httpChannel = new HttpChannelChild();
|
||||
httpChannel->AddIPDLReference();
|
||||
return httpChannel;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -58,9 +58,9 @@ NeckoParent::~NeckoParent()
|
||||
}
|
||||
|
||||
PHttpChannelParent*
|
||||
NeckoParent::AllocPHttpChannel(PBrowserParent* iframeEmbedding)
|
||||
NeckoParent::AllocPHttpChannel(PBrowserParent* browser)
|
||||
{
|
||||
HttpChannelParent *p = new HttpChannelParent(iframeEmbedding);
|
||||
HttpChannelParent *p = new HttpChannelParent(browser);
|
||||
p->AddRef();
|
||||
return p;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
virtual ~NeckoParent();
|
||||
|
||||
protected:
|
||||
virtual PHttpChannelParent* AllocPHttpChannel(PBrowserParent* iframeEmbedding);
|
||||
virtual PHttpChannelParent* AllocPHttpChannel(PBrowserParent* browser);
|
||||
virtual bool DeallocPHttpChannel(PHttpChannelParent*);
|
||||
virtual PCookieServiceParent* AllocPCookieService();
|
||||
virtual bool DeallocPCookieService(PCookieServiceParent*);
|
||||
|
@ -57,10 +57,12 @@ sync protocol PNecko
|
||||
parent:
|
||||
__delete__();
|
||||
|
||||
PHttpChannel(nullable PBrowser iframeEmbedding);
|
||||
PCookieService();
|
||||
|
||||
HTMLDNSPrefetch(nsString hostname, PRUint16 flags);
|
||||
|
||||
both:
|
||||
PHttpChannel(nullable PBrowser browser);
|
||||
};
|
||||
|
||||
|
||||
|
@ -46,6 +46,12 @@
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsISeekableStream.h"
|
||||
#include "nsIEncodedChannel.h"
|
||||
#include "nsIResumableChannel.h"
|
||||
#include "nsIApplicationCacheChannel.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
@ -62,6 +68,9 @@ HttpBaseChannel::HttpBaseChannel()
|
||||
, mAllowPipelining(PR_TRUE)
|
||||
, mForceAllowThirdPartyCookie(PR_FALSE)
|
||||
, mUploadStreamHasHeaders(PR_FALSE)
|
||||
, mInheritApplicationCache(PR_TRUE)
|
||||
, mChooseApplicationCache(PR_FALSE)
|
||||
, mLoadedFromApplicationCache(PR_FALSE)
|
||||
{
|
||||
LOG(("Creating HttpBaseChannel @%x\n", this));
|
||||
|
||||
@ -980,6 +989,135 @@ HttpBaseChannel::AddCookiesToRequest()
|
||||
SetRequestHeader(nsDependentCString(nsHttp::Cookie), cookie, PR_FALSE);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
CopyProperties(const nsAString& aKey, nsIVariant *aData, void *aClosure)
|
||||
{
|
||||
nsIWritablePropertyBag* bag = static_cast<nsIWritablePropertyBag*>
|
||||
(aClosure);
|
||||
bag->SetProperty(aKey, aData);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
nsIChannel *newChannel,
|
||||
PRBool preserveMethod)
|
||||
{
|
||||
LOG(("HttpBaseChannel::SetupReplacementChannel "
|
||||
"[this=%p newChannel=%p preserveMethod=%d]",
|
||||
this, newChannel, preserveMethod));
|
||||
PRUint32 newLoadFlags = mLoadFlags | LOAD_REPLACE;
|
||||
// if the original channel was using SSL and this channel is not using
|
||||
// SSL, then no need to inhibit persistent caching. however, if the
|
||||
// original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
|
||||
// set, then allow the flag to apply to the redirected channel as well.
|
||||
// since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
|
||||
// we only need to check if the original channel was using SSL.
|
||||
if (mConnectionInfo->UsingSSL())
|
||||
newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
|
||||
|
||||
// Do not pass along LOAD_CHECK_OFFLINE_CACHE
|
||||
newLoadFlags &= ~nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE;
|
||||
|
||||
newChannel->SetLoadGroup(mLoadGroup);
|
||||
newChannel->SetNotificationCallbacks(mCallbacks);
|
||||
newChannel->SetLoadFlags(newLoadFlags);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
|
||||
if (!httpChannel)
|
||||
return NS_OK; // no other options to set
|
||||
|
||||
if (preserveMethod) {
|
||||
nsCOMPtr<nsIUploadChannel> uploadChannel =
|
||||
do_QueryInterface(httpChannel);
|
||||
nsCOMPtr<nsIUploadChannel2> uploadChannel2 =
|
||||
do_QueryInterface(httpChannel);
|
||||
if (mUploadStream && (uploadChannel2 || uploadChannel)) {
|
||||
// rewind upload stream
|
||||
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
|
||||
if (seekable)
|
||||
seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
||||
|
||||
// replicate original call to SetUploadStream...
|
||||
if (uploadChannel2) {
|
||||
const char *ctype = mRequestHead.PeekHeader(nsHttp::Content_Type);
|
||||
if (!ctype)
|
||||
ctype = "";
|
||||
const char *clen = mRequestHead.PeekHeader(nsHttp::Content_Length);
|
||||
PRInt64 len = clen ? nsCRT::atoll(clen) : -1;
|
||||
uploadChannel2->ExplicitSetUploadStream(
|
||||
mUploadStream,
|
||||
nsDependentCString(ctype),
|
||||
len,
|
||||
nsDependentCString(mRequestHead.Method()),
|
||||
mUploadStreamHasHeaders);
|
||||
} else {
|
||||
if (mUploadStreamHasHeaders) {
|
||||
uploadChannel->SetUploadStream(mUploadStream, EmptyCString(),
|
||||
-1);
|
||||
} else {
|
||||
const char *ctype =
|
||||
mRequestHead.PeekHeader(nsHttp::Content_Type);
|
||||
const char *clen =
|
||||
mRequestHead.PeekHeader(nsHttp::Content_Length);
|
||||
if (!ctype) {
|
||||
ctype = "application/octet-stream";
|
||||
}
|
||||
if (clen) {
|
||||
uploadChannel->SetUploadStream(mUploadStream,
|
||||
nsDependentCString(ctype),
|
||||
atoi(clen));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// since preserveMethod is true, we need to ensure that the appropriate
|
||||
// request method gets set on the channel, regardless of whether or not
|
||||
// we set the upload stream above. This means SetRequestMethod() will
|
||||
// be called twice if ExplicitSetUploadStream() gets called above.
|
||||
|
||||
httpChannel->SetRequestMethod(nsDependentCString(mRequestHead.Method()));
|
||||
}
|
||||
// convey the referrer if one was used for this channel to the next one
|
||||
if (mReferrer)
|
||||
httpChannel->SetReferrer(mReferrer);
|
||||
// convey the mAllowPipelining flag
|
||||
httpChannel->SetAllowPipelining(mAllowPipelining);
|
||||
// convey the new redirection limit
|
||||
httpChannel->SetRedirectionLimit(mRedirectionLimit - 1);
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
|
||||
if (httpInternal) {
|
||||
// convey the mForceAllowThirdPartyCookie flag
|
||||
httpInternal->SetForceAllowThirdPartyCookie(mForceAllowThirdPartyCookie);
|
||||
|
||||
// update the DocumentURI indicator since we are being redirected.
|
||||
// if this was a top-level document channel, then the new channel
|
||||
// should have its mDocumentURI point to newURI; otherwise, we
|
||||
// just need to pass along our mDocumentURI to the new channel.
|
||||
if (newURI && (mURI == mDocumentURI))
|
||||
httpInternal->SetDocumentURI(newURI);
|
||||
else
|
||||
httpInternal->SetDocumentURI(mDocumentURI);
|
||||
}
|
||||
|
||||
// transfer application cache information
|
||||
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
|
||||
do_QueryInterface(newChannel);
|
||||
if (appCacheChannel) {
|
||||
appCacheChannel->SetApplicationCache(mApplicationCache);
|
||||
appCacheChannel->SetInheritApplicationCache(mInheritApplicationCache);
|
||||
// We purposely avoid transfering mChooseApplicationCache.
|
||||
}
|
||||
|
||||
// transfer any properties
|
||||
nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
|
||||
if (bag)
|
||||
mPropertyHash.EnumerateRead(CopyProperties, bag.get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace net
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
|
||||
#define DIE_WITH_ASYNC_OPEN_MSG() \
|
||||
do { \
|
||||
@ -169,6 +170,9 @@ public:
|
||||
|
||||
protected:
|
||||
void AddCookiesToRequest();
|
||||
virtual nsresult SetupReplacementChannel(nsIURI *,
|
||||
nsIChannel *,
|
||||
PRBool preserveMethod);
|
||||
|
||||
// Helper function to simplify getting notification callbacks.
|
||||
template <class T>
|
||||
@ -189,6 +193,7 @@ protected:
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
nsCOMPtr<nsIProgressEventSink> mProgressSink;
|
||||
nsCOMPtr<nsIURI> mReferrer;
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
|
||||
nsHttpRequestHead mRequestHead;
|
||||
nsCOMPtr<nsIInputStream> mUploadStream;
|
||||
@ -206,13 +211,16 @@ protected:
|
||||
PRUint8 mCaps;
|
||||
PRUint8 mRedirectionLimit;
|
||||
|
||||
PRUint8 mCanceled : 1;
|
||||
PRUint8 mIsPending : 1;
|
||||
PRUint8 mWasOpened : 1;
|
||||
PRUint8 mResponseHeadersModified : 1;
|
||||
PRUint8 mAllowPipelining : 1;
|
||||
PRUint8 mForceAllowThirdPartyCookie : 1;
|
||||
PRUint8 mUploadStreamHasHeaders : 1;
|
||||
PRUint32 mCanceled : 1;
|
||||
PRUint32 mIsPending : 1;
|
||||
PRUint32 mWasOpened : 1;
|
||||
PRUint32 mResponseHeadersModified : 1;
|
||||
PRUint32 mAllowPipelining : 1;
|
||||
PRUint32 mForceAllowThirdPartyCookie : 1;
|
||||
PRUint32 mUploadStreamHasHeaders : 1;
|
||||
PRUint32 mInheritApplicationCache : 1;
|
||||
PRUint32 mChooseApplicationCache : 1;
|
||||
PRUint32 mLoadedFromApplicationCache : 1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Daniel Witte <dwitte@mozilla.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -75,7 +76,11 @@ private:
|
||||
HttpChannelChild *mChannel;
|
||||
};
|
||||
|
||||
// C++ file contents
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelChild
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
HttpChannelChild::HttpChannelChild()
|
||||
: mIsFromCache(PR_FALSE)
|
||||
, mCacheEntryAvailable(PR_FALSE)
|
||||
@ -113,6 +118,7 @@ NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -473,6 +479,160 @@ HttpChannelChild::OnStatus(const nsresult& status,
|
||||
}
|
||||
}
|
||||
|
||||
class Redirect1Event : public ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
Redirect1Event(HttpChannelChild* child,
|
||||
PHttpChannelChild* newChannel,
|
||||
const IPC::URI& newURI,
|
||||
const PRUint32& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead)
|
||||
: mChild(child)
|
||||
, mNewChannel(newChannel)
|
||||
, mNewURI(newURI)
|
||||
, mRedirectFlags(redirectFlags)
|
||||
, mResponseHead(responseHead) {}
|
||||
|
||||
void Run()
|
||||
{
|
||||
mChild->Redirect1Begin(mNewChannel, mNewURI, mRedirectFlags,
|
||||
mResponseHead);
|
||||
}
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
PHttpChannelChild* mNewChannel;
|
||||
IPC::URI mNewURI;
|
||||
PRUint32 mRedirectFlags;
|
||||
nsHttpResponseHead mResponseHead;
|
||||
};
|
||||
|
||||
bool
|
||||
HttpChannelChild::RecvRedirect1Begin(PHttpChannelChild* newChannel,
|
||||
const IPC::URI& newURI,
|
||||
const PRUint32& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead)
|
||||
{
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new Redirect1Event(this, newChannel, newURI, redirectFlags,
|
||||
responseHead));
|
||||
} else {
|
||||
Redirect1Begin(newChannel, newURI, redirectFlags, responseHead);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::Redirect1Begin(PHttpChannelChild* newChannel,
|
||||
const IPC::URI& newURI,
|
||||
const PRUint32& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead)
|
||||
{
|
||||
HttpChannelChild*
|
||||
newHttpChannelChild = static_cast<HttpChannelChild*>(newChannel);
|
||||
nsCOMPtr<nsIURI> uri(newURI);
|
||||
|
||||
nsresult rv =
|
||||
newHttpChannelChild->HttpBaseChannel::Init(uri, mCaps,
|
||||
mConnectionInfo->ProxyInfo());
|
||||
if (NS_FAILED(rv))
|
||||
return; // TODO Bug 536317
|
||||
|
||||
// We won't get OnStartRequest, set cookies here.
|
||||
mResponseHead = new nsHttpResponseHead(responseHead);
|
||||
SetCookie(mResponseHead->PeekHeader(nsHttp::Set_Cookie));
|
||||
|
||||
PRBool preserveMethod = (mResponseHead->Status() == 307);
|
||||
rv = SetupReplacementChannel(uri, newHttpChannelChild, preserveMethod);
|
||||
if (NS_FAILED(rv))
|
||||
return; // TODO Bug 536317
|
||||
|
||||
mRedirectChannelChild = newHttpChannelChild;
|
||||
|
||||
nsresult result = gHttpHandler->AsyncOnChannelRedirect(this,
|
||||
newHttpChannelChild,
|
||||
redirectFlags);
|
||||
if (NS_FAILED(result))
|
||||
OnRedirectVerifyCallback(result);
|
||||
}
|
||||
|
||||
class Redirect3Event : public ChildChannelEvent
|
||||
{
|
||||
public:
|
||||
Redirect3Event(HttpChannelChild* child) : mChild(child) {}
|
||||
void Run() { mChild->Redirect3Complete(); }
|
||||
private:
|
||||
HttpChannelChild* mChild;
|
||||
};
|
||||
|
||||
bool
|
||||
HttpChannelChild::RecvRedirect3Complete()
|
||||
{
|
||||
if (ShouldEnqueue()) {
|
||||
EnqueueEvent(new Redirect3Event(this));
|
||||
} else {
|
||||
Redirect3Complete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelChild::Redirect3Complete()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Redirecting to new channel: shut this down and init new channel
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->RemoveRequest(this, nsnull, NS_BINDING_ABORTED);
|
||||
|
||||
// Chrome channel has been AsyncOpen'd. Reflect this in child.
|
||||
rv = mRedirectChannelChild->CompleteRedirectSetup(mListener,
|
||||
mListenerContext);
|
||||
if (NS_FAILED(rv))
|
||||
; // TODO Cancel: Bug 536317
|
||||
}
|
||||
|
||||
nsresult
|
||||
HttpChannelChild::CompleteRedirectSetup(nsIStreamListener *listener,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
LOG(("HttpChannelChild::FinishRedirectSetup [this=%x]\n", this));
|
||||
|
||||
NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS);
|
||||
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
|
||||
|
||||
// notify "http-on-modify-request" observers
|
||||
gHttpHandler->OnModifyRequest(this);
|
||||
|
||||
mIsPending = PR_TRUE;
|
||||
mWasOpened = PR_TRUE;
|
||||
mListener = listener;
|
||||
mListenerContext = aContext;
|
||||
|
||||
// add ourselves to the load group.
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->AddRequest(this, nsnull);
|
||||
|
||||
// TODO: may have been canceled by on-modify-request observers: bug 536317
|
||||
|
||||
mState = HCC_OPENED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelChild::nsIAsyncVerifyRedirectCallback
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelChild::OnRedirectVerifyCallback(nsresult result)
|
||||
{
|
||||
// Cookies may have been changed by redirect observers
|
||||
mRedirectChannelChild->AddCookiesToRequest();
|
||||
// Must not be called until after redirect observers called.
|
||||
mRedirectChannelChild->SetOriginalURI(mRedirectOriginalURI);
|
||||
|
||||
return SendRedirect2Result(result, mRedirectChannelChild->mRequestHeaders);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelChild::nsIRequest
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -600,16 +760,16 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
|
||||
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
|
||||
}
|
||||
|
||||
// The socket transport layer in the chrome process now has a logical ref to
|
||||
// us, until either OnStopRequest or OnRedirect is called.
|
||||
// The socket transport in the chrome process now holds a logical ref to us
|
||||
// until OnStopRequest, or we do a redirect, or we hit an IPDL error.
|
||||
AddIPDLReference();
|
||||
|
||||
gNeckoChild->SendPHttpChannelConstructor(this, tabChild);
|
||||
|
||||
SendAsyncOpen(IPC::URI(mURI), IPC::URI(mOriginalURI), IPC::URI(mDocumentURI),
|
||||
IPC::URI(mReferrer), mLoadFlags, mRequestHeaders,
|
||||
mRequestHead.Method(), uploadStreamData,
|
||||
uploadStreamInfo, mPriority, mRedirectionLimit,
|
||||
SendAsyncOpen(IPC::URI(mURI), IPC::URI(mOriginalURI),
|
||||
IPC::URI(mDocumentURI), IPC::URI(mReferrer), mLoadFlags,
|
||||
mRequestHeaders, mRequestHead.Method(), uploadStreamData,
|
||||
uploadStreamInfo, mPriority, mRedirectionLimit,
|
||||
mAllowPipelining, mForceAllowThirdPartyCookie);
|
||||
|
||||
mState = HCC_OPENED;
|
||||
@ -784,7 +944,8 @@ HttpChannelChild::GetApplicationCache(nsIApplicationCache **aApplicationCache)
|
||||
NS_IMETHODIMP
|
||||
HttpChannelChild::SetApplicationCache(nsIApplicationCache *aApplicationCache)
|
||||
{
|
||||
DROP_DEAD();
|
||||
// FIXME: redirects call. so stub OK for now. Fix in bug 536295.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -825,5 +986,6 @@ HttpChannelChild::SetChooseApplicationCache(PRBool aChooseApplicationCache)
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
}} // mozilla::net
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Daniel Witte <dwitte@mozilla.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -58,6 +59,7 @@
|
||||
#include "nsIResumableChannel.h"
|
||||
#include "nsIProxiedChannel.h"
|
||||
#include "nsITraceableChannel.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
@ -73,7 +75,6 @@ enum HttpChannelChildState {
|
||||
HCC_ONSTOP
|
||||
};
|
||||
|
||||
// Header file contents
|
||||
class HttpChannelChild : public PHttpChannelChild
|
||||
, public HttpBaseChannel
|
||||
, public nsICacheInfoChannel
|
||||
@ -82,6 +83,7 @@ class HttpChannelChild : public PHttpChannelChild
|
||||
, public nsIProxiedChannel
|
||||
, public nsITraceableChannel
|
||||
, public nsIApplicationCacheChannel
|
||||
, public nsIAsyncVerifyRedirectCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -92,6 +94,7 @@ public:
|
||||
NS_DECL_NSITRACEABLECHANNEL
|
||||
NS_DECL_NSIAPPLICATIONCACHECONTAINER
|
||||
NS_DECL_NSIAPPLICATIONCACHECHANNEL
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
||||
|
||||
HttpChannelChild();
|
||||
virtual ~HttpChannelChild();
|
||||
@ -114,6 +117,10 @@ public:
|
||||
// nsISupportsPriority
|
||||
NS_IMETHOD SetPriority(PRInt32 value);
|
||||
|
||||
// Final setup when redirect has proceeded successfully in chrome
|
||||
nsresult CompleteRedirectSetup(nsIStreamListener *listener,
|
||||
nsISupports *aContext);
|
||||
|
||||
// IPDL holds a reference while the PHttpChannel protocol is live (starting at
|
||||
// AsyncOpen, and ending at either OnStopRequest or any IPDL error, either of
|
||||
// which call NeckoChild::DeallocPHttpChannel()).
|
||||
@ -133,9 +140,16 @@ protected:
|
||||
bool RecvOnStopRequest(const nsresult& statusCode);
|
||||
bool RecvOnProgress(const PRUint64& progress, const PRUint64& progressMax);
|
||||
bool RecvOnStatus(const nsresult& status, const nsString& statusArg);
|
||||
bool RecvRedirect1Begin(PHttpChannelChild* newChannel,
|
||||
const URI& newURI,
|
||||
const PRUint32& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead);
|
||||
bool RecvRedirect3Complete();
|
||||
|
||||
private:
|
||||
RequestHeaderTuples mRequestHeaders;
|
||||
nsRefPtr<HttpChannelChild> mRedirectChannelChild;
|
||||
nsCOMPtr<nsIURI> mRedirectOriginalURI;
|
||||
|
||||
PRPackedBool mIsFromCache;
|
||||
PRPackedBool mCacheEntryAvailable;
|
||||
@ -175,6 +189,10 @@ private:
|
||||
void OnStopRequest(const nsresult& statusCode);
|
||||
void OnProgress(const PRUint64& progress, const PRUint64& progressMax);
|
||||
void OnStatus(const nsresult& status, const nsString& statusArg);
|
||||
void Redirect1Begin(PHttpChannelChild* newChannel, const URI& newURI,
|
||||
const PRUint32& redirectFlags,
|
||||
const nsHttpResponseHead& responseHead);
|
||||
void Redirect3Complete();
|
||||
|
||||
friend class AutoEventEnqueuer;
|
||||
friend class StartRequestEvent;
|
||||
@ -182,6 +200,8 @@ private:
|
||||
friend class DataAvailableEvent;
|
||||
friend class ProgressEvent;
|
||||
friend class StatusEvent;
|
||||
friend class Redirect1Event;
|
||||
friend class Redirect3Event;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -23,6 +23,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -40,6 +41,8 @@
|
||||
|
||||
#include "mozilla/net/HttpChannelParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "HttpChannelParentListener.h"
|
||||
#include "nsHttpChannel.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
@ -52,7 +55,6 @@
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// C++ file contents
|
||||
HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding)
|
||||
: mIPCClosed(false)
|
||||
{
|
||||
@ -82,11 +84,8 @@ HttpChannelParent::ActorDestroy(ActorDestroyReason why)
|
||||
// HttpChannelParent::nsISupports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS4(HttpChannelParent,
|
||||
nsIRequestObserver,
|
||||
nsIStreamListener,
|
||||
nsIInterfaceRequestor,
|
||||
nsIProgressEventSink);
|
||||
NS_IMPL_ISUPPORTS1(HttpChannelParent,
|
||||
nsIProgressEventSink)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParent::PHttpChannelParent
|
||||
@ -145,7 +144,9 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI,
|
||||
requestHeaders[i].mMerge);
|
||||
}
|
||||
|
||||
httpChan->SetNotificationCallbacks(this);
|
||||
mChannelListener = new HttpChannelParentListener(this);
|
||||
|
||||
httpChan->SetNotificationCallbacks(mChannelListener);
|
||||
|
||||
httpChan->SetRequestMethod(nsDependentCString(requestMethod.get()));
|
||||
|
||||
@ -167,7 +168,7 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI,
|
||||
httpChan->SetAllowPipelining(allowPipelining);
|
||||
httpChan->SetForceAllowThirdPartyCookie(forceAllowThirdPartyCookie);
|
||||
|
||||
rv = httpChan->AsyncOpen(this, nsnull);
|
||||
rv = httpChan->AsyncOpen(mChannelListener, nsnull);
|
||||
if (NS_FAILED(rv))
|
||||
return false; // TODO: cancel request (bug 536317), return true
|
||||
|
||||
@ -191,15 +192,28 @@ HttpChannelParent::RecvSetCacheTokenCachedCharset(const nsCString& charset)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HttpChannelParent::RecvRedirect2Result(const nsresult& result,
|
||||
const RequestHeaderTuples& changedHeaders)
|
||||
{
|
||||
if (mChannelListener)
|
||||
mChannelListener->OnContentRedirectResultReceived(result, changedHeaders);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParent::nsIRequestObserver
|
||||
// nsIRequestObserver and nsIStreamListener methods equivalents
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
||||
{
|
||||
LOG(("HttpChannelParent::OnStartRequest [this=%x]\n", this));
|
||||
|
||||
// We need this member only to call OnContentRedirectResultReceived on it,
|
||||
// that will for sure not happen when we get here. Throw it away ASAP.
|
||||
mChannelListener = nsnull;
|
||||
|
||||
nsHttpChannel *chan = static_cast<nsHttpChannel *>(aRequest);
|
||||
nsHttpResponseHead *responseHead = chan->GetResponseHead();
|
||||
|
||||
@ -224,7 +238,7 @@ HttpChannelParent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aStatusCode)
|
||||
@ -237,11 +251,7 @@ HttpChannelParent::OnStopRequest(nsIRequest *aRequest,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParent::nsIStreamListener
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsIInputStream *aInputStream,
|
||||
@ -267,63 +277,10 @@ HttpChannelParent::OnDataAvailable(nsIRequest *aRequest,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParent::nsIInterfaceRequestor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParent::GetInterface(const nsIID& aIID, void **result)
|
||||
{
|
||||
if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider))) {
|
||||
if (!mTabParent)
|
||||
return NS_NOINTERFACE;
|
||||
return mTabParent->QueryInterface(aIID, result);
|
||||
}
|
||||
|
||||
// TODO: 575494: once we're confident we're handling all needed interfaces,
|
||||
// remove all code below and simply "return QueryInterface(aIID, result)"
|
||||
if (// Known interface calls:
|
||||
|
||||
// FIXME: HTTP Authorization (bug 537782):
|
||||
// nsHttpChannel first tries to get this as an nsIAuthPromptProvider; if that
|
||||
// fails, it tries as an nsIAuthPrompt2, and if that fails, an nsIAuthPrompt.
|
||||
// See nsHttpChannel::GetAuthPrompt(). So if we can return any one of these,
|
||||
// HTTP auth should be all set. The other two if checks can be eventually
|
||||
// deleted.
|
||||
aIID.Equals(NS_GET_IID(nsIAuthPrompt2)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
|
||||
// FIXME: redirects (bug 536294):
|
||||
// The likely solution here is for this class to implement nsIChannelEventSink
|
||||
// and nsIHttpEventSink (and forward calls to any real sinks in the child), in
|
||||
// which case QueryInterface() will do the work here and these if statements
|
||||
// can be eventually discarded.
|
||||
aIID.Equals(NS_GET_IID(nsIChannelEventSink)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIHttpEventSink)) ||
|
||||
// FIXME: application cache (bug 536295):
|
||||
aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIProgressEventSink)) ||
|
||||
// FIXME: bug 561830: when fixed, we shouldn't be asked for this interface
|
||||
aIID.Equals(NS_GET_IID(nsIDocShellTreeItem)) ||
|
||||
// Let this return NS_ERROR_NO_INTERFACE: it's OK to not provide it.
|
||||
aIID.Equals(NS_GET_IID(nsIBadCertListener2)))
|
||||
{
|
||||
return QueryInterface(aIID, result);
|
||||
} else {
|
||||
nsPrintfCString msg(2000,
|
||||
"HttpChannelParent::GetInterface: interface UUID=%s not yet supported! "
|
||||
"Use 'grep -ri UUID <mozilla_src>' to find the name of the interface, "
|
||||
"check http://tinyurl.com/255ojvu to see if a bug has already been "
|
||||
"filed, and if not, add one and make it block bug 516730. Thanks!",
|
||||
aIID.ToString());
|
||||
NECKO_MAYBE_ABORT(msg);
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParent::nsIProgressEventSink
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParent::OnProgress(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
@ -346,6 +303,5 @@ HttpChannelParent::OnStatus(nsIRequest *aRequest,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
}} // mozilla::net
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -45,8 +46,6 @@
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
#include "mozilla/net/PHttpChannelParent.h"
|
||||
#include "mozilla/net/NeckoCommon.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsITabParent.h"
|
||||
|
||||
@ -57,19 +56,27 @@ class nsICacheEntryDescriptor;
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// Header file contents
|
||||
class HttpChannelParentListener;
|
||||
|
||||
class HttpChannelParent : public PHttpChannelParent
|
||||
, public nsIStreamListener
|
||||
, public nsIInterfaceRequestor
|
||||
, public nsIProgressEventSink
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIPROGRESSEVENTSINK
|
||||
|
||||
// Make these non-virtual for a little performance benefit
|
||||
nsresult OnStartRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext);
|
||||
nsresult OnStopRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aStatusCode);
|
||||
nsresult OnDataAvailable(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsIInputStream *aInputStream,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aCount);
|
||||
|
||||
HttpChannelParent(PBrowserParent* iframeEmbedding);
|
||||
virtual ~HttpChannelParent();
|
||||
|
||||
@ -90,12 +97,18 @@ protected:
|
||||
|
||||
virtual bool RecvSetPriority(const PRUint16& priority);
|
||||
virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset);
|
||||
virtual bool RecvRedirect2Result(const nsresult& result,
|
||||
const RequestHeaderTuples& changedHeaders);
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
||||
private:
|
||||
protected:
|
||||
friend class mozilla::net::HttpChannelParentListener;
|
||||
nsCOMPtr<nsITabParent> mTabParent;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIChannel> mChannel;
|
||||
nsRefPtr<HttpChannelParentListener> mChannelListener;
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheDescriptor;
|
||||
bool mIPCClosed; // PHttpChannel actor has been Closed()
|
||||
};
|
||||
|
289
netwerk/protocol/http/HttpChannelParentListener.cpp
Normal file
289
netwerk/protocol/http/HttpChannelParentListener.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* 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 "HttpChannelParentListener.h"
|
||||
#include "mozilla/net/HttpChannelParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "nsHttpChannel.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
#include "nsIDocShellTreeItem.h"
|
||||
#include "nsIBadCertListener2.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "nsISerializable.h"
|
||||
#include "nsIAssociatedContentSecurity.h"
|
||||
#include "nsISecureBrowserUI.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
HttpChannelParentListener::HttpChannelParentListener(HttpChannelParent* aInitialChannel)
|
||||
: mActiveChannel(aInitialChannel)
|
||||
{
|
||||
}
|
||||
|
||||
HttpChannelParentListener::~HttpChannelParentListener()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParentListener::nsISupports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS5(HttpChannelParentListener,
|
||||
nsIInterfaceRequestor,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver,
|
||||
nsIChannelEventSink,
|
||||
nsIRedirectResultListener)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParentListener::nsIRequestObserver
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParentListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
|
||||
{
|
||||
if (!mActiveChannel)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
LOG(("HttpChannelParentListener::OnStartRequest [this=%x]\n", this));
|
||||
return mActiveChannel->OnStartRequest(aRequest, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParentListener::OnStopRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aStatusCode)
|
||||
{
|
||||
if (!mActiveChannel)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
LOG(("HttpChannelParentListener::OnStopRequest: [this=%x status=%ul]\n",
|
||||
this, aStatusCode));
|
||||
nsresult rv = mActiveChannel->OnStopRequest(aRequest, aContext, aStatusCode);
|
||||
|
||||
mActiveChannel = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParentListener::nsIStreamListener
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParentListener::OnDataAvailable(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsIInputStream *aInputStream,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
if (!mActiveChannel)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
LOG(("HttpChannelParentListener::OnDataAvailable [this=%x]\n", this));
|
||||
return mActiveChannel->OnDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParentListener::nsIInterfaceRequestor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParentListener::GetInterface(const nsIID& aIID, void **result)
|
||||
{
|
||||
if (aIID.Equals(NS_GET_IID(nsIAuthPromptProvider))) {
|
||||
if (!mActiveChannel || !mActiveChannel->mTabParent)
|
||||
return NS_NOINTERFACE;
|
||||
return mActiveChannel->mTabParent->QueryInterface(aIID, result);
|
||||
}
|
||||
|
||||
if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
|
||||
if (!mActiveChannel)
|
||||
return NS_NOINTERFACE;
|
||||
return mActiveChannel->QueryInterface(aIID, result);
|
||||
}
|
||||
|
||||
// TODO: 575494: once we're confident we're handling all needed interfaces,
|
||||
// remove all code below and simply "return QueryInterface(aIID, result)"
|
||||
if (// Known interface calls:
|
||||
|
||||
// FIXME: HTTP Authorization (bug 537782):
|
||||
// nsHttpChannel first tries to get this as an nsIAuthPromptProvider; if that
|
||||
// fails, it tries as an nsIAuthPrompt2, and if that fails, an nsIAuthPrompt.
|
||||
// See nsHttpChannel::GetAuthPrompt(). So if we can return any one of these,
|
||||
// HTTP auth should be all set. The other two if checks can be eventually
|
||||
// deleted.
|
||||
aIID.Equals(NS_GET_IID(nsIAuthPrompt2)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
|
||||
// FIXME: redirects (bug 536294):
|
||||
// The likely solution here is for this class to implement nsIChannelEventSink
|
||||
// and nsIHttpEventSink (and forward calls to any real sinks in the child), in
|
||||
// which case QueryInterface() will do the work here and these if statements
|
||||
// can be eventually discarded.
|
||||
aIID.Equals(NS_GET_IID(nsIChannelEventSink)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIHttpEventSink)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIRedirectResultListener)) ||
|
||||
// FIXME: application cache (bug 536295):
|
||||
aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer)) ||
|
||||
// FIXME: bug 561830: when fixed, we shouldn't be asked for this interface
|
||||
aIID.Equals(NS_GET_IID(nsIDocShellTreeItem)) ||
|
||||
// Let this return NS_ERROR_NO_INTERFACE: it's OK to not provide it.
|
||||
aIID.Equals(NS_GET_IID(nsIBadCertListener2)))
|
||||
{
|
||||
return QueryInterface(aIID, result);
|
||||
} else {
|
||||
nsPrintfCString msg(2000,
|
||||
"HttpChannelParentListener::GetInterface: interface UUID=%s not yet supported! "
|
||||
"Use 'grep -ri UUID <mozilla_src>' to find the name of the interface, "
|
||||
"check http://tinyurl.com/255ojvu to see if a bug has already been "
|
||||
"filed, and if not, add one and make it block bug 516730. Thanks!",
|
||||
aIID.ToString());
|
||||
NECKO_MAYBE_ABORT(msg);
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParentListener::nsIChannelEventSink
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParentListener::AsyncOnChannelRedirect(
|
||||
nsIChannel *oldChannel,
|
||||
nsIChannel *newChannel,
|
||||
PRUint32 redirectFlags,
|
||||
nsIAsyncVerifyRedirectCallback* callback)
|
||||
{
|
||||
if (mActiveChannel->mIPCClosed)
|
||||
return NS_BINDING_ABORTED;
|
||||
|
||||
// Create new PHttpChannel
|
||||
PBrowserParent* browser = mActiveChannel->mTabParent ?
|
||||
static_cast<TabParent*>(mActiveChannel->mTabParent.get()) : nsnull;
|
||||
mRedirectChannel = static_cast<HttpChannelParent *>
|
||||
(mActiveChannel->Manager()->SendPHttpChannelConstructor(browser));
|
||||
|
||||
// Join it with the correct channel
|
||||
mRedirectChannel->mChannel = newChannel;
|
||||
|
||||
// Let the new channel also keep the wrapper in case we get another redirect
|
||||
// response, it wouldn't be able to send back the redirect result.
|
||||
mRedirectChannel->mChannelListener = this;
|
||||
|
||||
// And finally, let the content process decide to redirect or not.
|
||||
mRedirectCallback = callback;
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
newChannel->GetURI(getter_AddRefs(newURI));
|
||||
|
||||
nsHttpChannel *oldHttpChannel = static_cast<nsHttpChannel *>(oldChannel);
|
||||
// TODO: check mActiveChannel->mIPCClosed and return val from Send function
|
||||
mActiveChannel->SendRedirect1Begin(mRedirectChannel,
|
||||
IPC::URI(newURI),
|
||||
redirectFlags,
|
||||
*oldHttpChannel->GetResponseHead());
|
||||
|
||||
// mActiveChannel gets the response in RecvRedirect2Result and forwards it
|
||||
// to this wrapper through OnContentRedirectResultReceived
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HttpChannelParentListener::OnContentRedirectResultReceived(
|
||||
const nsresult result,
|
||||
const RequestHeaderTuples& changedHeaders)
|
||||
{
|
||||
nsHttpChannel* newHttpChannel =
|
||||
static_cast<nsHttpChannel*>(mRedirectChannel->mChannel.get());
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
for (PRUint32 i = 0; i < changedHeaders.Length(); i++) {
|
||||
newHttpChannel->SetRequestHeader(changedHeaders[i].mHeader,
|
||||
changedHeaders[i].mValue,
|
||||
changedHeaders[i].mMerge);
|
||||
}
|
||||
}
|
||||
|
||||
mRedirectCallback->OnRedirectVerifyCallback(result);
|
||||
mRedirectCallback = nsnull;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpChannelParentListener::nsIRedirectResultListener
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpChannelParentListener::OnRedirectResult(PRBool succeeded)
|
||||
{
|
||||
if (!mRedirectChannel) {
|
||||
// Redirect might get canceled before we got AsyncOnChannelRedirect
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (succeeded && !mActiveChannel->mIPCClosed) {
|
||||
// TODO: check return value: assume child dead if failed
|
||||
mActiveChannel->SendRedirect3Complete();
|
||||
}
|
||||
|
||||
HttpChannelParent* channelToDelete;
|
||||
if (succeeded) {
|
||||
// Switch to redirect channel and delete the old one.
|
||||
channelToDelete = mActiveChannel;
|
||||
mActiveChannel = mRedirectChannel;
|
||||
} else {
|
||||
// Delete the redirect target channel: continue using old channel
|
||||
channelToDelete = mRedirectChannel;
|
||||
}
|
||||
|
||||
if (!channelToDelete->mIPCClosed)
|
||||
HttpChannelParent::Send__delete__(channelToDelete);
|
||||
mRedirectChannel = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
}} // mozilla::net
|
94
netwerk/protocol/http/HttpChannelParentListener.h
Normal file
94
netwerk/protocol/http/HttpChannelParentListener.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef mozilla_net_HttpChannelCallbackWrapper_h
|
||||
#define mozilla_net_HttpChannelCallbackWrapper_h
|
||||
|
||||
#include "nsHttp.h"
|
||||
#include "mozilla/net/NeckoCommon.h"
|
||||
#include "PHttpChannelParams.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIRedirectResultListener.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
class nsICacheEntryDescriptor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class HttpChannelParent;
|
||||
|
||||
class HttpChannelParentListener : public nsIInterfaceRequestor
|
||||
, public nsIChannelEventSink
|
||||
, public nsIRedirectResultListener
|
||||
, public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIREDIRECTRESULTLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
HttpChannelParentListener(HttpChannelParent* aInitialChannel);
|
||||
virtual ~HttpChannelParentListener();
|
||||
|
||||
protected:
|
||||
friend class HttpChannelParent;
|
||||
void OnContentRedirectResultReceived(
|
||||
const nsresult result,
|
||||
const RequestHeaderTuples& changedHeaders);
|
||||
|
||||
private:
|
||||
nsRefPtr<HttpChannelParent> mActiveChannel;
|
||||
nsRefPtr<HttpChannelParent> mRedirectChannel;
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_HttpChannelParent_h
|
@ -114,6 +114,7 @@ ifdef MOZ_IPC
|
||||
CPPSRCS += \
|
||||
HttpChannelParent.cpp \
|
||||
HttpChannelChild.cpp \
|
||||
HttpChannelParentListener.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Duell <jduell.mcbugs@gmail.com>
|
||||
* Honza Bambas <honzab@firemni.cz>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -57,8 +58,6 @@ protocol PHttpChannel
|
||||
manager PNecko;
|
||||
|
||||
parent:
|
||||
__delete__();
|
||||
|
||||
AsyncOpen(URI uri,
|
||||
// - TODO: bug 571161: unclear if any HTTP channel clients ever
|
||||
// set originalURI != uri (about:credits?); also not clear if
|
||||
@ -80,6 +79,9 @@ parent:
|
||||
|
||||
SetCacheTokenCachedCharset(nsCString charset);
|
||||
|
||||
// Reports approval/veto of redirect by child process redirect observers
|
||||
Redirect2Result(nsresult result, RequestHeaderTuples changedHeaders);
|
||||
|
||||
child:
|
||||
OnStartRequest(nsHttpResponseHead responseHead,
|
||||
PRBool useResponseHead,
|
||||
@ -97,6 +99,18 @@ child:
|
||||
OnProgress(PRUint64 progress, PRUint64 progressMax);
|
||||
|
||||
OnStatus(nsresult status, nsString statusArg);
|
||||
|
||||
// Called to initiate content channel redirect, starts talking to sinks
|
||||
// on the content process and reports result via OnRedirect2Result above
|
||||
Redirect1Begin(PHttpChannel newChannel,
|
||||
URI newUri,
|
||||
PRUint32 redirectFlags,
|
||||
nsHttpResponseHead responseHead);
|
||||
// Called if redirect successful so that child can complete setup.
|
||||
Redirect3Complete();
|
||||
|
||||
both:
|
||||
__delete__();
|
||||
};
|
||||
|
||||
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "nsICacheService.h"
|
||||
#include "nsDNSPrefetch.h"
|
||||
#include "nsChannelClassifier.h"
|
||||
#include "nsIRedirectResultListener.h"
|
||||
|
||||
// True if the local cache should be bypassed when processing a request.
|
||||
#define BYPASS_LOCAL_CACHE(loadFlags) \
|
||||
@ -77,6 +78,34 @@
|
||||
|
||||
static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID);
|
||||
|
||||
class AutoRedirectVetoNotifier
|
||||
{
|
||||
public:
|
||||
AutoRedirectVetoNotifier(nsHttpChannel* channel) : mChannel(channel) {}
|
||||
~AutoRedirectVetoNotifier() {ReportRedirectResult(false);}
|
||||
void DontReport() {mChannel = nsnull;}
|
||||
void RedirectSucceeded() {ReportRedirectResult(true);}
|
||||
|
||||
private:
|
||||
nsHttpChannel* mChannel;
|
||||
void ReportRedirectResult(bool succeeded);
|
||||
};
|
||||
|
||||
void
|
||||
AutoRedirectVetoNotifier::ReportRedirectResult(bool succeeded)
|
||||
{
|
||||
if (!mChannel)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIRedirectResultListener> vetoHook;
|
||||
NS_QueryNotificationCallbacks(mChannel,
|
||||
NS_GET_IID(nsIRedirectResultListener),
|
||||
getter_AddRefs(vetoHook));
|
||||
mChannel = nsnull;
|
||||
if (vetoHook)
|
||||
vetoHook->OnRedirectResult(succeeded);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel <public>
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -99,9 +128,6 @@ nsHttpChannel::nsHttpChannel()
|
||||
, mCacheForOfflineUse(PR_FALSE)
|
||||
, mCachingOpportunistically(PR_FALSE)
|
||||
, mFallbackChannel(PR_FALSE)
|
||||
, mInheritApplicationCache(PR_TRUE)
|
||||
, mChooseApplicationCache(PR_FALSE)
|
||||
, mLoadedFromApplicationCache(PR_FALSE)
|
||||
, mTracingEnabled(PR_TRUE)
|
||||
, mCustomConditionalRequest(PR_FALSE)
|
||||
, mFallingBack(PR_FALSE)
|
||||
@ -1230,6 +1256,7 @@ nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi)
|
||||
rv = WaitForRedirectCallback();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
AutoRedirectVetoNotifier notifier(this);
|
||||
PopRedirectAsyncFunc(&nsHttpChannel::ContinueDoReplaceWithProxy);
|
||||
mRedirectChannel = nsnull;
|
||||
}
|
||||
@ -1240,6 +1267,8 @@ nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi)
|
||||
nsresult
|
||||
nsHttpChannel::ContinueDoReplaceWithProxy(nsresult rv)
|
||||
{
|
||||
AutoRedirectVetoNotifier notifier(this);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -1256,6 +1285,8 @@ nsHttpChannel::ContinueDoReplaceWithProxy(nsresult rv)
|
||||
|
||||
mStatus = NS_BINDING_REDIRECTED;
|
||||
|
||||
notifier.RedirectSucceeded();
|
||||
|
||||
// disconnect from the old listeners...
|
||||
mListener = nsnull;
|
||||
mListenerContext = nsnull;
|
||||
@ -1593,6 +1624,7 @@ nsHttpChannel::ProcessFallback(PRBool *waitingForRedirectCallback)
|
||||
rv = WaitForRedirectCallback();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
AutoRedirectVetoNotifier notifier(this);
|
||||
PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessFallback);
|
||||
mRedirectChannel = nsnull;
|
||||
return rv;
|
||||
@ -1607,6 +1639,8 @@ nsHttpChannel::ProcessFallback(PRBool *waitingForRedirectCallback)
|
||||
nsresult
|
||||
nsHttpChannel::ContinueProcessFallback(nsresult rv)
|
||||
{
|
||||
AutoRedirectVetoNotifier notifier(this);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -1617,14 +1651,18 @@ nsHttpChannel::ContinueProcessFallback(nsresult rv)
|
||||
|
||||
rv = mRedirectChannel->AsyncOpen(mListener, mListenerContext);
|
||||
mRedirectChannel = nsnull;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// close down this channel
|
||||
Cancel(NS_BINDING_REDIRECTED);
|
||||
|
||||
notifier.RedirectSucceeded();
|
||||
|
||||
// disconnect from our listener
|
||||
mListener = 0;
|
||||
mListenerContext = 0;
|
||||
|
||||
// and from our callbacks
|
||||
mCallbacks = nsnull;
|
||||
mProgressSink = nsnull;
|
||||
@ -2752,15 +2790,6 @@ nsHttpChannel::ClearBogusContentEncodingIfNeeded()
|
||||
// nsHttpChannel <redirect>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static PLDHashOperator
|
||||
CopyProperties(const nsAString& aKey, nsIVariant *aData, void *aClosure)
|
||||
{
|
||||
nsIWritablePropertyBag* bag = static_cast<nsIWritablePropertyBag*>
|
||||
(aClosure);
|
||||
bag->SetProperty(aKey, aData);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
nsIChannel *newChannel,
|
||||
@ -2769,105 +2798,19 @@ nsHttpChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
LOG(("nsHttpChannel::SetupReplacementChannel "
|
||||
"[this=%p newChannel=%p preserveMethod=%d]",
|
||||
this, newChannel, preserveMethod));
|
||||
PRUint32 newLoadFlags = mLoadFlags | LOAD_REPLACE;
|
||||
// if the original channel was using SSL and this channel is not using
|
||||
// SSL, then no need to inhibit persistent caching. however, if the
|
||||
// original channel was not using SSL and has INHIBIT_PERSISTENT_CACHING
|
||||
// set, then allow the flag to apply to the redirected channel as well.
|
||||
// since we force set INHIBIT_PERSISTENT_CACHING on all HTTPS channels,
|
||||
// we only need to check if the original channel was using SSL.
|
||||
if (mConnectionInfo->UsingSSL())
|
||||
newLoadFlags &= ~INHIBIT_PERSISTENT_CACHING;
|
||||
|
||||
// Do not pass along LOAD_CHECK_OFFLINE_CACHE
|
||||
newLoadFlags &= ~LOAD_CHECK_OFFLINE_CACHE;
|
||||
|
||||
newChannel->SetLoadGroup(mLoadGroup);
|
||||
newChannel->SetNotificationCallbacks(mCallbacks);
|
||||
newChannel->SetLoadFlags(newLoadFlags);
|
||||
nsresult rv = HttpBaseChannel::SetupReplacementChannel(newURI, newChannel, preserveMethod);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
|
||||
if (!httpChannel)
|
||||
return NS_OK; // no other options to set
|
||||
|
||||
if (preserveMethod) {
|
||||
nsCOMPtr<nsIUploadChannel> uploadChannel =
|
||||
do_QueryInterface(httpChannel);
|
||||
nsCOMPtr<nsIUploadChannel2> uploadChannel2 =
|
||||
do_QueryInterface(httpChannel);
|
||||
if (mUploadStream && (uploadChannel2 || uploadChannel)) {
|
||||
// rewind upload stream
|
||||
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
|
||||
if (seekable)
|
||||
seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
|
||||
|
||||
// replicate original call to SetUploadStream...
|
||||
if (uploadChannel2) {
|
||||
const char *ctype = mRequestHead.PeekHeader(nsHttp::Content_Type);
|
||||
if (!ctype)
|
||||
ctype = "";
|
||||
const char *clen = mRequestHead.PeekHeader(nsHttp::Content_Length);
|
||||
PRInt64 len = clen ? nsCRT::atoll(clen) : -1;
|
||||
uploadChannel2->ExplicitSetUploadStream(
|
||||
mUploadStream,
|
||||
nsDependentCString(ctype),
|
||||
len,
|
||||
nsDependentCString(mRequestHead.Method()),
|
||||
mUploadStreamHasHeaders);
|
||||
}
|
||||
else {
|
||||
if (mUploadStreamHasHeaders)
|
||||
uploadChannel->SetUploadStream(mUploadStream, EmptyCString(),
|
||||
-1);
|
||||
else {
|
||||
const char *ctype =
|
||||
mRequestHead.PeekHeader(nsHttp::Content_Type);
|
||||
const char *clen =
|
||||
mRequestHead.PeekHeader(nsHttp::Content_Length);
|
||||
if (!ctype) {
|
||||
ctype = "application/octet-stream";
|
||||
}
|
||||
if (clen) {
|
||||
uploadChannel->SetUploadStream(mUploadStream,
|
||||
nsDependentCString(ctype),
|
||||
atoi(clen));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// since preserveMethod is true, we need to ensure that the appropriate
|
||||
// request method gets set on the channel, regardless of whether or not
|
||||
// we set the upload stream above. This means SetRequestMethod() will
|
||||
// be called twice if ExplicitSetUploadStream() gets called above.
|
||||
|
||||
httpChannel->SetRequestMethod(nsDependentCString(mRequestHead.Method()));
|
||||
}
|
||||
// convey the referrer if one was used for this channel to the next one
|
||||
if (mReferrer)
|
||||
httpChannel->SetReferrer(mReferrer);
|
||||
// convey the mAllowPipelining flag
|
||||
httpChannel->SetAllowPipelining(mAllowPipelining);
|
||||
// convey the new redirection limit
|
||||
httpChannel->SetRedirectionLimit(mRedirectionLimit - 1);
|
||||
|
||||
// transfer the remote flag
|
||||
nsHttpChannel *httpChannelImpl = static_cast<nsHttpChannel*>(httpChannel.get());
|
||||
httpChannelImpl->SetRemoteChannel(mRemoteChannel);
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(newChannel);
|
||||
if (httpInternal) {
|
||||
// convey the mForceAllowThirdPartyCookie flag
|
||||
httpInternal->SetForceAllowThirdPartyCookie(mForceAllowThirdPartyCookie);
|
||||
|
||||
// update the DocumentURI indicator since we are being redirected.
|
||||
// if this was a top-level document channel, then the new channel
|
||||
// should have its mDocumentURI point to newURI; otherwise, we
|
||||
// just need to pass along our mDocumentURI to the new channel.
|
||||
if (newURI && (mURI == mDocumentURI))
|
||||
httpInternal->SetDocumentURI(newURI);
|
||||
else
|
||||
httpInternal->SetDocumentURI(mDocumentURI);
|
||||
}
|
||||
|
||||
// convey the mApplyConversion flag (bug 91862)
|
||||
nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
|
||||
if (encodedChannel)
|
||||
@ -2883,20 +2826,6 @@ nsHttpChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
resumableChannel->ResumeAt(mStartPos, mEntityID);
|
||||
}
|
||||
|
||||
// transfer application cache information
|
||||
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
|
||||
do_QueryInterface(newChannel);
|
||||
if (appCacheChannel) {
|
||||
appCacheChannel->SetApplicationCache(mApplicationCache);
|
||||
appCacheChannel->SetInheritApplicationCache(mInheritApplicationCache);
|
||||
// We purposely avoid transfering mChooseApplicationCache.
|
||||
}
|
||||
|
||||
// transfer any properties
|
||||
nsCOMPtr<nsIWritablePropertyBag> bag(do_QueryInterface(newChannel));
|
||||
if (bag)
|
||||
mPropertyHash.EnumerateRead(CopyProperties, bag.get());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3034,6 +2963,7 @@ nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv)
|
||||
rv = WaitForRedirectCallback();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
AutoRedirectVetoNotifier notifier(this);
|
||||
PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
|
||||
mRedirectChannel = nsnull;
|
||||
}
|
||||
@ -3044,6 +2974,8 @@ nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv)
|
||||
nsresult
|
||||
nsHttpChannel::ContinueProcessRedirection(nsresult rv)
|
||||
{
|
||||
AutoRedirectVetoNotifier notifier(this);
|
||||
|
||||
LOG(("ContinueProcessRedirection [rv=%x]\n", rv));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
@ -3076,9 +3008,12 @@ nsHttpChannel::ContinueProcessRedirection(nsresult rv)
|
||||
// close down this channel
|
||||
Cancel(NS_BINDING_REDIRECTED);
|
||||
|
||||
notifier.RedirectSucceeded();
|
||||
|
||||
// disconnect from our listener
|
||||
mListener = 0;
|
||||
mListenerContext = 0;
|
||||
|
||||
// and from our callbacks
|
||||
mCallbacks = nsnull;
|
||||
mProgressSink = nsnull;
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsICacheListener.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheChannel.h"
|
||||
#include "nsIEncodedChannel.h"
|
||||
#include "nsIStringEnumerator.h"
|
||||
@ -206,7 +205,7 @@ private:
|
||||
void HandleAsyncFallback();
|
||||
nsresult ContinueHandleAsyncFallback(nsresult);
|
||||
nsresult PromptTempRedirect();
|
||||
nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, PRBool preserveMethod);
|
||||
virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, PRBool preserveMethod);
|
||||
|
||||
// proxy specific methods
|
||||
nsresult ProxyFailover();
|
||||
@ -269,8 +268,6 @@ private:
|
||||
nsCacheAccessMode mOfflineCacheAccess;
|
||||
nsCString mOfflineCacheClientID;
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
|
||||
// auth specific data
|
||||
nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
|
||||
|
||||
@ -314,9 +311,6 @@ private:
|
||||
// True if we are loading a fallback cache entry from the
|
||||
// application cache.
|
||||
PRUint32 mFallbackChannel : 1;
|
||||
PRUint32 mInheritApplicationCache : 1;
|
||||
PRUint32 mChooseApplicationCache : 1;
|
||||
PRUint32 mLoadedFromApplicationCache : 1;
|
||||
PRUint32 mTracingEnabled : 1;
|
||||
// True if consumer added its own If-None-Match or If-Modified-Since
|
||||
// headers. In such a case we must not override them in the cache code
|
||||
|
7
netwerk/test/unit_ipc/test_event_sink_wrap.js
Normal file
7
netwerk/test/unit_ipc/test_event_sink_wrap.js
Normal file
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_event_sink.js");
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
//
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_redirect-caching_canceled.js");
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
//
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_redirect-caching_failure.js");
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
//
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_redirect-caching_passing.js");
|
||||
}
|
7
netwerk/test/unit_ipc/test_redirect_canceled_wrap.js
Normal file
7
netwerk/test/unit_ipc/test_redirect_canceled_wrap.js
Normal file
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
//
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_redirect_canceled.js");
|
||||
}
|
7
netwerk/test/unit_ipc/test_redirect_failure_wrap.js
Normal file
7
netwerk/test/unit_ipc/test_redirect_failure_wrap.js
Normal file
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_redirect_failure.js");
|
||||
}
|
7
netwerk/test/unit_ipc/test_redirect_passing_wrap.js
Normal file
7
netwerk/test/unit_ipc/test_redirect_passing_wrap.js
Normal file
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_redirect_passing.js");
|
||||
}
|
Loading…
Reference in New Issue
Block a user