Bug 646512 HttpChannelParent::OnStartRequest deep-copies nsHttpHeaderArray. r=jduell
authorJosh Aas <joshmoz@gmail.com>
Thu, 19 Jan 2012 14:26:43 -0800
changeset 86185 a6e3185f8aa9cc202ba77fdf5981486e1340ebf8
parent 86184 eb09304af438ae482b9ec98218700fa35d2fafe8
child 86186 e70f6f04cf0f551503e7223e6ec51c7094bfbd09
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell
bugs646512
milestone12.0a1
Bug 646512 HttpChannelParent::OnStartRequest deep-copies nsHttpHeaderArray. r=jduell
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
netwerk/protocol/http/PHttpChannel.ipdl
netwerk/protocol/http/nsIHttpChannelChild.idl
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -191,17 +191,17 @@ HttpChannelChild::AssociateApplicationCa
 }
 
 class StartRequestEvent : public ChannelEvent
 {
  public:
   StartRequestEvent(HttpChannelChild* child,
                     const nsHttpResponseHead& responseHead,
                     const bool& useResponseHead,
-                    const RequestHeaderTuples& requestHeaders,
+                    const nsHttpHeaderArray& requestHeaders,
                     const bool& isFromCache,
                     const bool& cacheEntryAvailable,
                     const PRUint32& cacheExpirationTime,
                     const nsCString& cachedCharset,
                     const nsCString& securityInfoSerialization,
                     const PRNetAddr& selfAddr,
                     const PRNetAddr& peerAddr)
   : mChild(child)
@@ -222,31 +222,31 @@ class StartRequestEvent : public Channel
     mChild->OnStartRequest(mResponseHead, mUseResponseHead, mRequestHeaders,
                            mIsFromCache, mCacheEntryAvailable,
                            mCacheExpirationTime, mCachedCharset,
                            mSecurityInfoSerialization, mSelfAddr, mPeerAddr);
   }
  private:
   HttpChannelChild* mChild;
   nsHttpResponseHead mResponseHead;
-  RequestHeaderTuples mRequestHeaders;
+  nsHttpHeaderArray mRequestHeaders;
   bool mUseResponseHead;
   bool mIsFromCache;
   bool mCacheEntryAvailable;
   PRUint32 mCacheExpirationTime;
   nsCString mCachedCharset;
   nsCString mSecurityInfoSerialization;
   PRNetAddr mSelfAddr;
   PRNetAddr mPeerAddr;
 };
 
 bool 
 HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
                                      const bool& useResponseHead,
-                                     const RequestHeaderTuples& requestHeaders,
+                                     const nsHttpHeaderArray& requestHeaders,
                                      const bool& isFromCache,
                                      const bool& cacheEntryAvailable,
                                      const PRUint32& cacheExpirationTime,
                                      const nsCString& cachedCharset,
                                      const nsCString& securityInfoSerialization,
                                      const PRNetAddr& selfAddr,
                                      const PRNetAddr& peerAddr)
 {
@@ -263,17 +263,17 @@ HttpChannelChild::RecvOnStartRequest(con
                    securityInfoSerialization, selfAddr, peerAddr);
   }
   return true;
 }
 
 void 
 HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead,
                                  const bool& useResponseHead,
-                                 const RequestHeaderTuples& requestHeaders,
+                                 const nsHttpHeaderArray& requestHeaders,
                                  const bool& isFromCache,
                                  const bool& cacheEntryAvailable,
                                  const PRUint32& cacheExpirationTime,
                                  const nsCString& cachedCharset,
                                  const nsCString& securityInfoSerialization,
                                  const PRNetAddr& selfAddr,
                                  const PRNetAddr& peerAddr)
 {
@@ -290,21 +290,17 @@ HttpChannelChild::OnStartRequest(const n
   mIsFromCache = isFromCache;
   mCacheEntryAvailable = cacheEntryAvailable;
   mCacheExpirationTime = cacheExpirationTime;
   mCachedCharset = cachedCharset;
 
   AutoEventEnqueuer ensureSerialDispatch(mEventQ);
 
   // replace our request headers with what actually got sent in the parent
-  mRequestHead.ClearHeaders();
-  for (PRUint32 i = 0; i < requestHeaders.Length(); i++) {
-    mRequestHead.Headers().SetHeader(nsHttp::ResolveAtom(requestHeaders[i].mHeader),
-                                     requestHeaders[i].mValue);
-  }
+  mRequestHead.Headers() = requestHeaders;
 
   // notify "http-on-examine-response" observers
   gHttpHandler->OnExamineResponse(this);
   mTracingEnabled = false;
 
   nsresult rv = mListener->OnStartRequest(this, mListenerContext);
   if (NS_FAILED(rv)) {
     Cancel(rv);
@@ -897,17 +893,17 @@ HttpChannelChild::OnRedirectVerifyCallba
 
   RequestHeaderTuples emptyHeaders;
   RequestHeaderTuples* headerTuples = &emptyHeaders;
 
   nsCOMPtr<nsIHttpChannelChild> newHttpChannelChild =
       do_QueryInterface(mRedirectChannelChild);
   if (newHttpChannelChild && NS_SUCCEEDED(result)) {
     newHttpChannelChild->AddCookiesToRequest();
-    newHttpChannelChild->GetHeaderTuples(&headerTuples);
+    newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples);
   }
 
   // After we verify redirect, nsHttpChannel may hit the network: must give
   // "http-on-modify-request" observers the chance to cancel before that.
   if (NS_SUCCEEDED(result))
     gHttpHandler->OnModifyRequest(newHttpChannel);
 
   if (mIPCOpen)
@@ -1069,17 +1065,17 @@ HttpChannelChild::AsyncOpen(nsIStreamLis
   // 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(),
+                mClientSetRequestHeaders, mRequestHead.Method(),
                 IPC::InputStream(mUploadStream), mUploadStreamHasHeaders,
                 mPriority, mRedirectionLimit, mAllowPipelining,
                 mForceAllowThirdPartyCookie, mSendResumeAt,
                 mStartPos, mEntityID, mChooseApplicationCache, 
                 appCacheClientId, mAllowSpdy);
 
   return NS_OK;
 }
@@ -1092,17 +1088,17 @@ NS_IMETHODIMP
 HttpChannelChild::SetRequestHeader(const nsACString& aHeader, 
                                    const nsACString& aValue, 
                                    bool aMerge)
 {
   nsresult rv = HttpBaseChannel::SetRequestHeader(aHeader, aValue, aMerge);
   if (NS_FAILED(rv))
     return rv;
 
-  RequestHeaderTuple* tuple = mRequestHeaders.AppendElement();
+  RequestHeaderTuple* tuple = mClientSetRequestHeaders.AppendElement();
   if (!tuple)
     return NS_ERROR_OUT_OF_MEMORY;
 
   tuple->mHeader = aHeader;
   tuple->mValue = aValue;
   tuple->mMerge = aMerge;
   return NS_OK;
 }
@@ -1437,17 +1433,17 @@ HttpChannelChild::Flush()
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP HttpChannelChild::AddCookiesToRequest()
 {
   HttpBaseChannel::AddCookiesToRequest();
   return NS_OK;
 }
 
-NS_IMETHODIMP HttpChannelChild::GetHeaderTuples(RequestHeaderTuples **aHeaderTuples)
+NS_IMETHODIMP HttpChannelChild::GetClientSetRequestHeaders(RequestHeaderTuples **aRequestHeaders)
 {
-  *aHeaderTuples = &mRequestHeaders;
+  *aRequestHeaders = &mClientSetRequestHeaders;
   return NS_OK;
 }
 
 //------------------------------------------------------------------------------
 
 }} // mozilla::net
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -121,17 +121,17 @@ public:
   void AddIPDLReference();
   void ReleaseIPDLReference();
 
   bool IsSuspended();
 
 protected:
   bool RecvOnStartRequest(const nsHttpResponseHead& responseHead,
                           const bool& useResponseHead,
-                          const RequestHeaderTuples& requestHeaders,
+                          const nsHttpHeaderArray& requestHeaders,
                           const bool& isFromCache,
                           const bool& cacheEntryAvailable,
                           const PRUint32& cacheExpirationTime,
                           const nsCString& cachedCharset,
                           const nsCString& securityInfoSerialization,
                           const PRNetAddr& selfAddr,
                           const PRNetAddr& peerAddr);
   bool RecvOnTransportAndData(const nsresult& status,
@@ -152,17 +152,17 @@ protected:
   bool RecvAssociateApplicationCache(const nsCString& groupID,
                                      const nsCString& clientID);
   bool RecvDeleteSelf();
 
   bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nsnull);
   virtual void DoNotifyListenerCleanup();
 
 private:
-  RequestHeaderTuples mRequestHeaders;
+  RequestHeaderTuples mClientSetRequestHeaders;
   nsCOMPtr<nsIChildChannel> mRedirectChannelChild;
   nsCOMPtr<nsISupports> mSecurityInfo;
 
   bool mIsFromCache;
   bool mCacheEntryAvailable;
   PRUint32     mCacheExpirationTime;
   nsCString    mCachedCharset;
 
@@ -175,17 +175,17 @@ private:
 
   // true after successful AsyncOpen until OnStopRequest completes.
   bool RemoteChannelExists() { return mIPCOpen && !mKeptAlive; }
 
   void AssociateApplicationCache(const nsCString &groupID,
                                  const nsCString &clientID);
   void OnStartRequest(const nsHttpResponseHead& responseHead,
                       const bool& useResponseHead,
-                      const RequestHeaderTuples& requestHeaders,
+                      const nsHttpHeaderArray& requestHeaders,
                       const bool& isFromCache,
                       const bool& cacheEntryAvailable,
                       const PRUint32& cacheExpirationTime,
                       const nsCString& cachedCharset,
                       const nsCString& securityInfoSerialization,
                       const PRNetAddr& selfAddr,
                       const PRNetAddr& peerAddr);
   void OnTransportAndData(const nsresult& status,
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -62,17 +62,16 @@
 namespace mozilla {
 namespace net {
 
 HttpChannelParent::HttpChannelParent(PBrowserParent* iframeEmbedding)
   : mIPCClosed(false)
   , mStoredStatus(0)
   , mStoredProgress(0)
   , mStoredProgressMax(0)
-  , mHeadersToSyncToChild(nsnull)
   , mSentRedirect1Begin(false)
   , mSentRedirect1BeginFailed(false)
   , mReceivedRedirect2Verify(false)
 {
   // 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");
@@ -93,24 +92,23 @@ HttpChannelParent::ActorDestroy(ActorDes
   // to child, or IPDL will kill chrome process, too.
   mIPCClosed = true;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsISupports
 //-----------------------------------------------------------------------------
 
-NS_IMPL_ISUPPORTS7(HttpChannelParent,
+NS_IMPL_ISUPPORTS6(HttpChannelParent,
                    nsIInterfaceRequestor,
                    nsIProgressEventSink,
                    nsIRequestObserver,
                    nsIStreamListener,
                    nsIParentChannel,
-                   nsIParentRedirectingChannel,
-                   nsIHttpHeaderVisitor)
+                   nsIParentRedirectingChannel)
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIInterfaceRequestor
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelParent::GetInterface(const nsIID& aIID, void **result)
 {
@@ -444,27 +442,21 @@ HttpChannelParent::OnStartRequest(nsIReq
   chan->GetSecurityInfo(getter_AddRefs(secInfoSupp));
   if (secInfoSupp) {
     mAssociatedContentSecurity = do_QueryInterface(secInfoSupp);
     nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
     if (secInfoSer)
       NS_SerializeToString(secInfoSer, secInfoSerialization);
   }
 
-  // sync request headers to child, in case they've changed
-  RequestHeaderTuples headers;
-  mHeadersToSyncToChild = &headers;
-  requestHead->Headers().VisitHeaders(this);
-  mHeadersToSyncToChild = 0;
-
   nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
   if (mIPCClosed || 
       !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(), 
                           !!responseHead,
-                          headers,
+                          requestHead->Headers(),
                           isFromCache,
                           mCacheDescriptor ? true : false,
                           expirationTime, cachedCharset, secInfoSerialization,
                           httpChan->GetSelfAddr(), httpChan->GetPeerAddr())) 
   {
     return NS_ERROR_UNEXPECTED; 
   }
   return NS_OK;
@@ -619,26 +611,9 @@ HttpChannelParent::CompleteRedirect(bool
     // TODO: check return value: assume child dead if failed
     unused << SendRedirect3Complete();
   }
 
   mRedirectChannel = nsnull;
   return NS_OK;
 }
 
-//-----------------------------------------------------------------------------
-// HttpChannelParent::nsIHttpHeaderVisitor
-//-----------------------------------------------------------------------------
-
-nsresult
-HttpChannelParent::VisitHeader(const nsACString &header, const nsACString &value)
-{
-  // Will be set unless some random code QI's us to nsIHttpHeaderVisitor
-  NS_ENSURE_STATE(mHeadersToSyncToChild);
-
-  RequestHeaderTuple* tuple = mHeadersToSyncToChild->AppendElement();
-  tuple->mHeader = header;
-  tuple->mValue  = value;
-  tuple->mMerge  = false;  // headers already merged:
-  return NS_OK;
-}
-
 }} // mozilla::net
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -59,27 +59,25 @@ namespace mozilla {
 namespace net {
 
 class HttpChannelParentListener;
 
 class HttpChannelParent : public PHttpChannelParent
                         , public nsIParentRedirectingChannel
                         , public nsIProgressEventSink
                         , public nsIInterfaceRequestor
-                        , public nsIHttpHeaderVisitor
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIPARENTCHANNEL
   NS_DECL_NSIPARENTREDIRECTINGCHANNEL
   NS_DECL_NSIPROGRESSEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
-  NS_DECL_NSIHTTPHEADERVISITOR
 
   HttpChannelParent(PBrowserParent* iframeEmbedding);
   virtual ~HttpChannelParent();
 
 protected:
   virtual bool RecvAsyncOpen(const IPC::URI&            uri,
                              const IPC::URI&            originalUri,
                              const IPC::URI&            docUri,
@@ -131,19 +129,16 @@ private:
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
 
   // state for combining OnStatus/OnProgress with OnDataAvailable
   // into one IPDL call to child.
   nsresult mStoredStatus;
   PRUint64 mStoredProgress;
   PRUint64 mStoredProgressMax;
 
-  // used while visiting headers, to send them to child: else null
-  RequestHeaderTuples *mHeadersToSyncToChild;
-
   bool mSentRedirect1Begin : 1;
   bool mSentRedirect1BeginFailed : 1;
   bool mReceivedRedirect2Verify : 1;
 };
 
 } // namespace net
 } // namespace mozilla
 
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -41,16 +41,17 @@
 
 include protocol PNecko;
 
 include "mozilla/net/PHttpChannelParams.h";
 include "mozilla/net/NeckoMessageUtils.h";
 include "prio.h";
 
 using RequestHeaderTuples;
+using nsHttpHeaderArray;
 using nsHttpResponseHead;
 using nsHttpAtom;
 using IPC::URI;
 using IPC::InputStream;
 using PRNetAddr;
 
 namespace mozilla {
 namespace net {
@@ -124,17 +125,17 @@ parent:
   // again, indefinitely.
   MarkOfflineCacheEntryAsForeign();
 
   __delete__();
 
 child:
   OnStartRequest(nsHttpResponseHead  responseHead,
                  bool                useResponseHead,
-                 RequestHeaderTuples requestHeaders,
+                 nsHttpHeaderArray   requestHeaders,
                  bool                isFromCache,
                  bool                cacheEntryAvailable,
                  PRUint32            cacheExpirationTime,
                  nsCString           cachedCharset,
                  nsCString           securityInfoSerialization,
                  PRNetAddr           selfAddr,
                  PRNetAddr           peerAddr);
 
--- a/netwerk/protocol/http/nsIHttpChannelChild.idl
+++ b/netwerk/protocol/http/nsIHttpChannelChild.idl
@@ -35,14 +35,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 [ptr] native RequestHeaderTuples(mozilla::net::RequestHeaderTuples);
 
-[uuid(40192377-f83c-4b31-92c6-dbc6c767c860)]
+[uuid(306ACF4D-C6DF-4EF6-BDA9-5CB92E83EDD9)]
 interface nsIHttpChannelChild : nsISupports
 {
   void addCookiesToRequest();
-  readonly attribute RequestHeaderTuples headerTuples;
+
+  // Headers that the channel client has set via SetRequestHeader.
+  readonly attribute RequestHeaderTuples clientSetRequestHeaders;
 };