Bug 794597 - mozbrowser doesn't send auth request off a redirect. r=jdm a=blocking-basecamp
--- a/netwerk/ipc/NeckoChild.cpp
+++ b/netwerk/ipc/NeckoChild.cpp
@@ -54,28 +54,24 @@ void NeckoChild::DestroyNeckoChild()
if (!alreadyDestroyed) {
Send__delete__(gNeckoChild);
gNeckoChild = nullptr;
alreadyDestroyed = true;
}
}
-PHttpChannelChild*
-NeckoChild::AllocPHttpChannel(PBrowserChild* browser)
+PHttpChannelChild*
+NeckoChild::AllocPHttpChannel(PBrowserChild* browser,
+ const SerializedLoadContext& loadContext)
{
- // 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;
+ // We don't allocate here: instead we always use IPDL constructor that takes
+ // an existing HttpChildChannel
+ NS_NOTREACHED("AllocPHttpChannel should not be called on child");
+ return nullptr;
}
bool
NeckoChild::DeallocPHttpChannel(PHttpChannelChild* channel)
{
NS_ABORT_IF_FALSE(IsNeckoChild(), "DeallocPHttpChannel called by non-child!");
HttpChannelChild* child = static_cast<HttpChannelChild*>(channel);
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -21,17 +21,18 @@ class NeckoChild :
public:
NeckoChild();
virtual ~NeckoChild();
static void InitNeckoChild();
static void DestroyNeckoChild();
protected:
- virtual PHttpChannelChild* AllocPHttpChannel(PBrowserChild* iframeEmbedding);
+ virtual PHttpChannelChild* AllocPHttpChannel(PBrowserChild*,
+ const SerializedLoadContext&);
virtual bool DeallocPHttpChannel(PHttpChannelChild*);
virtual PCookieServiceChild* AllocPCookieService();
virtual bool DeallocPCookieService(PCookieServiceChild*);
virtual PWyciwygChannelChild* AllocPWyciwygChannel();
virtual bool DeallocPWyciwygChannel(PWyciwygChannelChild*);
virtual PFTPChannelChild* AllocPFTPChannel();
virtual bool DeallocPFTPChannel(PFTPChannelChild*);
virtual PWebSocketChild* AllocPWebSocket(PBrowserChild*);
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -28,25 +28,26 @@ namespace net {
NeckoParent::NeckoParent()
{
}
NeckoParent::~NeckoParent()
{
}
-PHttpChannelParent*
-NeckoParent::AllocPHttpChannel(PBrowserParent* browser)
+PHttpChannelParent*
+NeckoParent::AllocPHttpChannel(PBrowserParent* browser,
+ const SerializedLoadContext& loadContext)
{
- HttpChannelParent *p = new HttpChannelParent(browser);
+ HttpChannelParent *p = new HttpChannelParent(browser, loadContext);
p->AddRef();
return p;
}
-bool
+bool
NeckoParent::DeallocPHttpChannel(PHttpChannelParent* channel)
{
HttpChannelParent *p = static_cast<HttpChannelParent *>(channel);
p->Release();
return true;
}
PFTPChannelParent*
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -18,17 +18,18 @@ namespace net {
class NeckoParent :
public PNeckoParent
{
public:
NeckoParent();
virtual ~NeckoParent();
protected:
- virtual PHttpChannelParent* AllocPHttpChannel(PBrowserParent* browser);
+ virtual PHttpChannelParent* AllocPHttpChannel(PBrowserParent*,
+ const SerializedLoadContext&);
virtual bool DeallocPHttpChannel(PHttpChannelParent*);
virtual PCookieServiceParent* AllocPCookieService();
virtual bool DeallocPCookieService(PCookieServiceParent*);
virtual PWyciwygChannelParent* AllocPWyciwygChannel();
virtual bool DeallocPWyciwygChannel(PWyciwygChannelParent*);
virtual PFTPChannelParent* AllocPFTPChannel();
virtual bool DeallocPFTPChannel(PFTPChannelParent*);
virtual PWebSocketParent* AllocPWebSocket(PBrowserParent* browser);
--- a/netwerk/ipc/PNecko.ipdl
+++ b/netwerk/ipc/PNecko.ipdl
@@ -9,16 +9,20 @@ include protocol PContent;
include protocol PHttpChannel;
include protocol PCookieService;
include protocol PBrowser;
include protocol PWyciwygChannel;
include protocol PFTPChannel;
include protocol PWebSocket;
include protocol PTCPSocket;
+include "SerializedLoadContext.h";
+
+using IPC::SerializedLoadContext;
+
namespace mozilla {
namespace net {
//-------------------------------------------------------------------
sync protocol PNecko
{
manager PContent;
@@ -28,24 +32,24 @@ sync protocol PNecko
manages PFTPChannel;
manages PWebSocket;
manages PTCPSocket;
parent:
__delete__();
PCookieService();
+ PHttpChannel(nullable PBrowser browser,
+ SerializedLoadContext loadContext);
PWyciwygChannel();
PFTPChannel();
PWebSocket(PBrowser browser);
PTCPSocket(nsString host, uint16_t port, bool useSSL, nsString binaryType,
nullable PBrowser browser);
HTMLDNSPrefetch(nsString hostname, uint16_t flags);
CancelHTMLDNSPrefetch(nsString hostname, uint16_t flags, nsresult reason);
-both:
- PHttpChannel(nullable PBrowser browser);
};
} // namespace net
} // namespace mozilla
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -802,18 +802,20 @@ HttpChannelChild::ConnectParent(uint32_t
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
// 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();
- if (!gNeckoChild->SendPHttpChannelConstructor(this, tabChild))
+ if (!gNeckoChild->SendPHttpChannelConstructor(
+ this, tabChild, IPC::SerializedLoadContext(this))) {
return NS_ERROR_FAILURE;
+ }
if (!SendConnectChannel(id))
return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
@@ -1032,17 +1034,18 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
if (iTabChild) {
tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get());
}
// 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);
+ gNeckoChild->SendPHttpChannelConstructor(this, tabChild,
+ IPC::SerializedLoadContext(this));
URIParams uri;
SerializeURI(mURI, uri);
OptionalURIParams originalURI, documentURI, referrer;
SerializeURI(mOriginalURI, originalURI);
SerializeURI(mDocumentURI, documentURI);
SerializeURI(mReferrer, referrer);
@@ -1050,17 +1053,17 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
OptionalInputStreamParams uploadStream;
SerializeInputStream(mUploadStream, uploadStream);
SendAsyncOpen(uri, originalURI, documentURI, referrer, mLoadFlags,
mClientSetRequestHeaders, mRequestHead.Method(), uploadStream,
mUploadStreamHasHeaders, mPriority, mRedirectionLimit,
mAllowPipelining, mForceAllowThirdPartyCookie, mSendResumeAt,
mStartPos, mEntityID, mChooseApplicationCache,
- appCacheClientId, mAllowSpdy, IPC::SerializedLoadContext(this));
+ appCacheClientId, mAllowSpdy);
return NS_OK;
}
//-----------------------------------------------------------------------------
// HttpChannelChild::nsIHttpChannel
//-----------------------------------------------------------------------------
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -28,31 +28,45 @@
#include "mozilla/ipc/URIUtils.h"
using namespace mozilla::dom;
using namespace mozilla::ipc;
namespace mozilla {
namespace net {
-HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding)
+HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding,
+ const IPC::SerializedLoadContext& loadContext)
: mIPCClosed(false)
, mStoredStatus(NS_OK)
, mStoredProgress(0)
, mStoredProgressMax(0)
, mSentRedirect1Begin(false)
, mSentRedirect1BeginFailed(false)
, mReceivedRedirect2Verify(false)
+ , mPBOverride(kPBOverride_Unset)
{
// Ensure gHttpHandler is initialized: we need the atom table up and running.
nsIHttpProtocolHandler* handler;
CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &handler);
NS_ASSERTION(handler, "no http handler");
mTabParent = static_cast<mozilla::dom::TabParent*>(iframeEmbedding);
+
+ if (loadContext.IsNotNull()) {
+ if (mTabParent) {
+ mLoadContext = new LoadContext(loadContext, mTabParent->GetOwnerElement());
+ } else {
+ mLoadContext = new LoadContext(loadContext);
+ }
+ } else if (loadContext.IsPrivateBitValid()) {
+ // Don't have channel yet: override PB status after we create it.
+ mPBOverride = loadContext.mUsePrivateBrowsing ? kPBOverride_Private
+ : kPBOverride_NotPrivate;
+ }
}
HttpChannelParent::~HttpChannelParent()
{
gHttpHandler->Release();
}
void
@@ -119,18 +133,17 @@ HttpChannelParent::RecvAsyncOpen(const U
const uint8_t& redirectionLimit,
const bool& allowPipelining,
const bool& forceAllowThirdPartyCookie,
const bool& doResumeAt,
const uint64_t& startPos,
const nsCString& entityID,
const bool& chooseApplicationCache,
const nsCString& appCacheClientID,
- const bool& allowSpdy,
- const IPC::SerializedLoadContext& loadContext)
+ const bool& allowSpdy)
{
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
nsCOMPtr<nsIURI> originalUri = DeserializeURI(aOriginalURI);
nsCOMPtr<nsIURI> docUri = DeserializeURI(aDocURI);
nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aReferrerURI);
nsCString uriSpec;
uri->GetSpec(uriSpec);
@@ -142,29 +155,21 @@ HttpChannelParent::RecvAsyncOpen(const U
nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
if (NS_FAILED(rv))
return SendFailedAsyncOpen(rv);
rv = NS_NewChannel(getter_AddRefs(mChannel), uri, ios, nullptr, nullptr, loadFlags);
if (NS_FAILED(rv))
return SendFailedAsyncOpen(rv);
- if (loadContext.IsNotNull()) {
- if (mTabParent)
- mLoadContext = new LoadContext(loadContext, mTabParent->GetOwnerElement());
- else
- mLoadContext = new LoadContext(loadContext);
- } else if (loadContext.IsPrivateBitValid()) {
- nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel);
- if (pbChannel)
- pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing);
+ nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
+ if (mPBOverride != kPBOverride_Unset) {
+ httpChan->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
}
- nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
-
if (doResumeAt)
httpChan->ResumeAt(startPos, entityID);
if (originalUri)
httpChan->SetOriginalURI(originalUri);
if (docUri)
httpChan->SetDocumentURI(docUri);
if (referrerUri)
@@ -244,16 +249,24 @@ bool
HttpChannelParent::RecvConnectChannel(const uint32_t& channelId)
{
nsresult rv;
LOG(("Looking for a registered channel [this=%p, id=%d]", this, channelId));
rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(mChannel));
LOG((" found channel %p, rv=%08x", mChannel.get(), rv));
+ if (mPBOverride != kPBOverride_Unset) {
+ // redirected-to channel may not support PB
+ nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel);
+ if (pbChannel) {
+ pbChannel->SetPrivate(mPBOverride == kPBOverride_Private ? true : false);
+ }
+ }
+
return true;
}
bool
HttpChannelParent::RecvSetPriority(const uint16_t& priority)
{
if (mChannel) {
nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -38,17 +38,18 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIPARENTCHANNEL
NS_DECL_NSIPARENTREDIRECTINGCHANNEL
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
- HttpChannelParent(mozilla::dom::PBrowserParent* iframeEmbedding);
+ HttpChannelParent(mozilla::dom::PBrowserParent* iframeEmbedding,
+ const IPC::SerializedLoadContext& loadContext);
virtual ~HttpChannelParent();
protected:
virtual bool RecvAsyncOpen(const URIParams& uri,
const OptionalURIParams& originalUri,
const OptionalURIParams& docUri,
const OptionalURIParams& referrerUri,
const uint32_t& loadFlags,
@@ -60,18 +61,17 @@ protected:
const uint8_t& redirectionLimit,
const bool& allowPipelining,
const bool& forceAllowThirdPartyCookie,
const bool& doResumeAt,
const uint64_t& startPos,
const nsCString& entityID,
const bool& chooseApplicationCache,
const nsCString& appCacheClientID,
- const bool& allowSpdy,
- const IPC::SerializedLoadContext& loadContext) MOZ_OVERRIDE;
+ const bool& allowSpdy) MOZ_OVERRIDE;
virtual bool RecvConnectChannel(const uint32_t& channelId);
virtual bool RecvSetPriority(const uint16_t& priority);
virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset);
virtual bool RecvSuspend();
virtual bool RecvResume();
virtual bool RecvCancel(const nsresult& status);
virtual bool RecvRedirect2Verify(const nsresult& result,
@@ -105,15 +105,23 @@ private:
nsresult mStoredStatus;
uint64_t mStoredProgress;
uint64_t mStoredProgressMax;
bool mSentRedirect1Begin : 1;
bool mSentRedirect1BeginFailed : 1;
bool mReceivedRedirect2Verify : 1;
+ // Used to override channel Private Browsing status if needed.
+ enum PBOverrideStatus {
+ kPBOverride_Unset = 0,
+ kPBOverride_Private,
+ kPBOverride_NotPrivate
+ };
+ PBOverrideStatus mPBOverride;
+
nsCOMPtr<nsILoadContext> mLoadContext;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_HttpChannelParent_h
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -9,23 +9,21 @@ include protocol PNecko;
include InputStreamParams;
include URIParams;
include protocol PBlob; //FIXME: bug #792908
include "mozilla/net/PHttpChannelParams.h";
include "mozilla/net/NeckoMessageUtils.h";
include "prio.h";
-include "SerializedLoadContext.h";
using RequestHeaderTuples;
using nsHttpHeaderArray;
using nsHttpResponseHead;
using nsHttpAtom;
-using IPC::SerializedLoadContext;
using PRNetAddr;
namespace mozilla {
namespace net {
//-------------------------------------------------------------------
protocol PHttpChannel
{
@@ -48,18 +46,17 @@ parent:
uint8_t redirectionLimit,
bool allowPipelining,
bool forceAllowThirdPartyCookie,
bool resumeAt,
uint64_t startPos,
nsCString entityID,
bool chooseApplicationCache,
nsCString appCacheClientID,
- bool allowSpdy,
- SerializedLoadContext loadContext);
+ bool allowSpdy);
// Used to connect redirected-to channel on the parent with redirected-to
// channel on the child.
ConnectChannel(uint32_t channelId);
SetPriority(uint16_t priority);
SetCacheTokenCachedCharset(nsCString charset);