Bug 794597 - mozbrowser doesn't send auth request off a redirect. r=jdm a=blocking-basecamp
authorJason Duell <jduell.mcbugs@gmail.com>
Tue, 09 Oct 2012 19:44:01 -0700
changeset 116555 2217b510b28a9ec9e8c3685cb19fd21561da6f24
parent 116554 c81cbb2cd9893707420737d0a49653c62e66796f
child 116556 fa9a4d400949bd3f97f5d9d271f90e6648e2086d
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm, blocking-basecamp
bugs794597
milestone18.0a2
Bug 794597 - mozbrowser doesn't send auth request off a redirect. r=jdm a=blocking-basecamp
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);