Bug 794597 - mozbrowser doesn't send auth request off a redirect. r=jdm
authorJason Duell <jduell.mcbugs@gmail.com>
Tue, 09 Oct 2012 16:46:24 -0700
changeset 109819 30f9ca7f991cbd5891d297c1c56eed808894b1ec
parent 109818 b310e265f26c59f23801b6de2439e10533b6e9c2
child 109820 7dbbd31904228df0934e64bc269b9df43511ff1a
push id23657
push useremorley@mozilla.com
push dateThu, 11 Oct 2012 13:47:00 +0000
treeherdermozilla-central@2fae8bd461da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
bugs794597
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 794597 - mozbrowser doesn't send auth request off a redirect. r=jdm
netwerk/ipc/NeckoChild.cpp
netwerk/ipc/NeckoChild.h
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
netwerk/ipc/PNecko.ipdl
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
netwerk/protocol/http/PHttpChannel.ipdl
--- 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);