Backout of changeset 38d1b321c98b from bug 579846. a=bustage
authorDave Townsend <dtownsend@oxymoronical.com>
Mon, 24 Jan 2011 14:58:20 -0800
changeset 61190 07e249383f3f61d1908d369c27aba94afc55c2be
parent 61189 57db6ae6d83266e95f8d462520e0bc7d7868a9fc
child 61191 ac6c96109dcf468c65912e6677ab8c5f638c7135
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
reviewersbustage
bugs579846
milestone2.0b10pre
Backout of changeset 38d1b321c98b from bug 579846. a=bustage
netwerk/base/public/nsICacheInfoChannel.idl
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
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/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
--- a/netwerk/base/public/nsICacheInfoChannel.idl
+++ b/netwerk/base/public/nsICacheInfoChannel.idl
@@ -62,13 +62,12 @@ interface nsICacheInfoChannel : nsISuppo
 
 [scriptable, uuid(746064fc-8783-4d19-9c5d-6361ed807b39)]
 interface nsICacheInfoChannel_GECKO_2_0 : nsISupports
 {
   /**
    * Return an object that while not released prevents the channel from
    * releasing the cache entry after all work on it has been done.  Used by
    * asynchronous consumers that needs to work with the cache entry long after
-   * onStopRequest has been called.  Must be acquired no later than during
-   * onStopRequest.
+   * onStopRequest has been called.
    */
   readonly attribute nsISupports cacheEntryClosePreventer;
 };
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -59,17 +59,16 @@ namespace net {
 
 HttpBaseChannel::HttpBaseChannel()
   : mStartPos(LL_MAXUINT)
   , mStatus(NS_OK)
   , mLoadFlags(LOAD_NORMAL)
   , mPriority(PRIORITY_NORMAL)
   , mCaps(0)
   , mRedirectionLimit(gHttpHandler->RedirectionLimit())
-  , mCacheEntryClosePreventionCount(0)
   , mApplyConversion(PR_TRUE)
   , mCanceled(PR_FALSE)
   , mIsPending(PR_FALSE)
   , mWasOpened(PR_FALSE)
   , mResponseHeadersModified(PR_FALSE)
   , mAllowPipelining(PR_TRUE)
   , mForceAllowThirdPartyCookie(PR_FALSE)
   , mUploadStreamHasHeaders(PR_FALSE)
@@ -1401,24 +1400,11 @@ HttpBaseChannel::SetupReplacementChannel
   if (bag)
     mPropertyHash.EnumerateRead(CopyProperties, bag.get());
 
   return NS_OK;
 }
 
 //------------------------------------------------------------------------------
 
-NS_IMPL_ISUPPORTS0(HttpBaseChannel::CacheEntryClosePreventer)
-
-HttpBaseChannel::CacheEntryClosePreventer::CacheEntryClosePreventer(
-  HttpBaseChannel* channel)
-: mChannel(channel)
-{
-  mChannel->OnIncreaseCacheEntryClosePreventCount();
-}
-
-HttpBaseChannel::CacheEntryClosePreventer::~CacheEntryClosePreventer()
-{
-  mChannel->OnDecreaseCacheEntryClosePreventCount();
-}
-
 }  // namespace net
 }  // namespace mozilla
+
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -181,40 +181,20 @@ public:
         
         // Hold a ref to our channel so that it can't go away and take the
         // header with it.
         nsCOMPtr<nsIHttpChannel> mChannel;
         
         PRPackedBool mReady;
     };
 
-  nsHttpResponseHead * GetResponseHead() const { return mResponseHead; }
-  nsHttpRequestHead * GetRequestHead() { return &mRequestHead; }
+    nsHttpResponseHead * GetResponseHead() const { return mResponseHead; }
+    nsHttpRequestHead * GetRequestHead() { return &mRequestHead; }
 
 protected:
-  // Increment/decrement counter that, when positive, keeps channel's cache
-  // entry open after OnStopRequest if needed.
-
-  virtual void OnIncreaseCacheEntryClosePreventCount() = 0;
-  virtual void OnDecreaseCacheEntryClosePreventCount() = 0;
-
-  // Object created and returned on every call to cacheEntryClosePreventer
-  // attribute.  Calls the two methods right above in its constructor and
-  // destructor respectively.
-
-  class CacheEntryClosePreventer : public nsISupports
-  {
-  public:
-      NS_DECL_ISUPPORTS
-      CacheEntryClosePreventer(HttpBaseChannel* channel);
-  private:
-      ~CacheEntryClosePreventer();
-      nsRefPtr<HttpBaseChannel> mChannel;
-  };
-
   nsresult ApplyContentConversions();
 
   void AddCookiesToRequest();
   virtual nsresult SetupReplacementChannel(nsIURI *,
                                            nsIChannel *,
                                            PRBool preserveMethod);
 
   // Helper function to simplify getting notification callbacks.
@@ -253,20 +233,16 @@ protected:
   PRUint64                          mStartPos;
 
   nsresult                          mStatus;
   PRUint32                          mLoadFlags;
   PRInt16                           mPriority;
   PRUint8                           mCaps;
   PRUint8                           mRedirectionLimit;
 
-  // Keeps the number of CacheEntryClosePreventer objects being held,
-  // positive value prevents the cache entry from release in OnStopRequest.
-  PRUint32                          mCacheEntryClosePreventionCount;
-
   PRUint32                          mApplyConversion            : 1;
   PRUint32                          mCanceled                   : 1;
   PRUint32                          mIsPending                  : 1;
   PRUint32                          mWasOpened                  : 1;
   PRUint32                          mResponseHeadersModified    : 1;
   PRUint32                          mAllowPipelining            : 1;
   PRUint32                          mForceAllowThirdPartyCookie : 1;
   PRUint32                          mUploadStreamHasHeaders     : 1;
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -61,17 +61,17 @@ namespace net {
 HttpChannelChild::HttpChannelChild()
   : ChannelEventQueue<HttpChannelChild>(this)
   , mIsFromCache(PR_FALSE)
   , mCacheEntryAvailable(PR_FALSE)
   , mCacheExpirationTime(nsICache::NO_EXPIRATION_TIME)
   , mSendResumeAt(false)
   , mSuspendCount(0)
   , mIPCOpen(false)
-  , mDeferredIPDLClose(false)
+  , mKeptAlive(false)
 {
   LOG(("Creating HttpChannelChild @%x\n", this));
 }
 
 HttpChannelChild::~HttpChannelChild()
 {
   LOG(("Destroying HttpChannelChild @%x\n", this));
 }
@@ -85,18 +85,18 @@ NS_IMPL_ADDREF(HttpChannelChild)
 
 NS_IMETHODIMP_(nsrefcnt) HttpChannelChild::Release()
 {
   NS_PRECONDITION(0 != mRefCnt, "dup release");
   NS_ASSERT_OWNINGTHREAD(HttpChannelChild);
   --mRefCnt;
   NS_LOG_RELEASE(this, mRefCnt, "HttpChannelChild");
 
-  if (mRefCnt == 1 && mDeferredIPDLClose && mIPCOpen) {
-    mDeferredIPDLClose = false;
+  if (mRefCnt == 1 && mKeptAlive && mIPCOpen) {
+    mKeptAlive = false;
     // Send_delete calls NeckoChild::DeallocPHttpChannel, which will release
     // again to refcount==0
     PHttpChannelChild::Send__delete__(this);
     return 0;
   }
 
   if (mRefCnt == 0) {
     mRefCnt = 1; /* stabilize */
@@ -107,17 +107,16 @@ NS_IMETHODIMP_(nsrefcnt) HttpChannelChil
 }
 
 NS_INTERFACE_MAP_BEGIN(HttpChannelChild)
   NS_INTERFACE_MAP_ENTRY(nsIRequest)
   NS_INTERFACE_MAP_ENTRY(nsIChannel)
   NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
   NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
   NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)
-  NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel_GECKO_2_0)
   NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
   NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
   NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
   NS_INTERFACE_MAP_ENTRY(nsITraceableChannel)
   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
   NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheChannel)
   NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
   NS_INTERFACE_MAP_ENTRY(nsIChildChannel)
@@ -387,17 +386,26 @@ HttpChannelChild::OnStopRequest(const ns
 
     mListener = 0;
     mListenerContext = 0;
     mCacheEntryAvailable = PR_FALSE;
     if (mLoadGroup)
       mLoadGroup->RemoveRequest(this, nsnull, mStatus);
   }
 
-  MaybeCloseIPDL();
+  if (!(mLoadFlags & LOAD_DOCUMENT_URI)) {
+    // This calls NeckoChild::DeallocPHttpChannel(), which deletes |this| if IPDL
+    // holds the last reference.  Don't rely on |this| existing after here.
+    PHttpChannelChild::Send__delete__(this);
+  } else {
+    // We need to keep the document loading channel alive for further 
+    // communication, mainly for collecting a security state values.
+    mKeptAlive = true;
+    SendDocumentChannelCleanup();
+  }
 }
 
 class ProgressEvent : public ChannelEvent
 {
  public:
   ProgressEvent(HttpChannelChild* child,
                 const PRUint64& progress,
                 const PRUint64& progressMax)
@@ -544,17 +552,18 @@ HttpChannelChild::OnCancel(const nsresul
   if (mListener) {
     mListener->OnStartRequest(this, mListenerContext);
     mListener->OnStopRequest(this, mListenerContext, mStatus);
   }
 
   mListener = NULL;
   mListenerContext = NULL;
 
-  MaybeCloseIPDL(true /* Force document channel deletion */);
+  if (mIPCOpen)
+    PHttpChannelChild::Send__delete__(this);
 }
 
 class DeleteSelfEvent : public ChannelEvent
 {
  public:
   DeleteSelfEvent(HttpChannelChild* child) : mChild(child) {}
   void Run() { mChild->DeleteSelf(); }
  private:
@@ -570,44 +579,17 @@ HttpChannelChild::RecvDeleteSelf()
     DeleteSelf();
   }
   return true;
 }
 
 void
 HttpChannelChild::DeleteSelf()
 {
-  MaybeCloseIPDL(true /* Force document channel deletion */);
-}
-
-void
-HttpChannelChild::MaybeCloseIPDL(bool forceDocumentLoadDeletion)
-{
-  if (mCacheEntryClosePreventionCount) {
-    // Someone is still holding the cache close prevention lock, keep this
-    // channel alive to be able to communicate lock release to the parent.
-    mDeferredIPDLClose = true;
-    return;
-  }
-
-  if ((mLoadFlags & LOAD_DOCUMENT_URI) && !forceDocumentLoadDeletion) {
-    // We need to keep the document loading channel alive for further
-    // communication, mainly for collecting a security state values.
-    mDeferredIPDLClose = true;
-    if (mIPCOpen)
-      SendDocumentChannelCleanup();
-    return;
-  }
-
-  // No need to keep the child channel, delete it.
-  // This calls NeckoChild::DeallocPHttpChannel(), which deletes |this| if IPDL
-  // holds the last reference.  Don't rely on |this| existing after here.
-  mDeferredIPDLClose = false;
-  if (mIPCOpen)
-    PHttpChannelChild::Send__delete__(this);
+  Send__delete__(this);
 }
 
 class Redirect1Event : public ChannelEvent
 {
  public:
   Redirect1Event(HttpChannelChild* child,
                  const PRUint32& newChannelId,
                  const IPC::URI& newURI,
@@ -1009,31 +991,16 @@ HttpChannelChild::SetRequestHeader(const
     return NS_ERROR_OUT_OF_MEMORY;
 
   tuple->mHeader = aHeader;
   tuple->mValue = aValue;
   tuple->mMerge = aMerge;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-HttpChannelChild::SetResponseHeader(const nsACString& aHeader,
-                                    const nsACString& aValue,
-                                    PRBool aMerge)
-{
-  nsresult rv = HttpBaseChannel::SetResponseHeader(aHeader, aValue, aMerge);
-  if (NS_FAILED(rv))
-    return rv;
-
-  nsCString header(aHeader);
-  nsCString value(aValue);
-  SendSetResponseHeader(header, value, aMerge);
-  return NS_OK;
-}
-
 //-----------------------------------------------------------------------------
 // HttpChannelChild::nsIHttpChannelInternal
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey)
 {
   DROP_DEAD();
@@ -1082,46 +1049,16 @@ HttpChannelChild::IsFromCache(PRBool *va
   if (!mIsPending)
     return NS_ERROR_NOT_AVAILABLE;
 
   *value = mIsFromCache;
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
-// nsHttpChannel::nsICacheInfoChannel_GECKO_2_0
-//-----------------------------------------------------------------------------
-
-NS_IMETHODIMP
-HttpChannelChild::GetCacheEntryClosePreventer(nsISupports** _retval)
-{
-  NS_ADDREF(*_retval = new CacheEntryClosePreventer(this));
-  return NS_OK;
-}
-
-void
-HttpChannelChild::OnIncreaseCacheEntryClosePreventCount()
-{
-  LOG(("HttpChannelChild::mCacheEntryClosePreventionCount increased to %d, [this=%x]",
-       mCacheEntryClosePreventionCount, this));
-  ++mCacheEntryClosePreventionCount;
-}
-
-void
-HttpChannelChild::OnDecreaseCacheEntryClosePreventCount()
-{
-  LOG(("HttpChannelChild::mCacheEntryClosePreventionCount decreased to %d, [this=%x]",
-       mCacheEntryClosePreventionCount, this));
-  --mCacheEntryClosePreventionCount;
-
-  if (!mCacheEntryClosePreventionCount && mDeferredIPDLClose)
-    MaybeCloseIPDL();
-}
-
-//-----------------------------------------------------------------------------
 // HttpChannelChild::nsIResumableChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 HttpChannelChild::ResumeAt(PRUint64 startPos, const nsACString& entityID)
 {
   ENSURE_CALLED_BEFORE_ASYNC_OPEN();
   mStartPos = startPos;
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -65,30 +65,28 @@
 #include "nsIHttpChannelChild.h"
 
 namespace mozilla {
 namespace net {
 
 class HttpChannelChild : public PHttpChannelChild
                        , public HttpBaseChannel
                        , public nsICacheInfoChannel
-                       , public nsICacheInfoChannel_GECKO_2_0
                        , public nsIProxiedChannel
                        , public nsITraceableChannel
                        , public nsIApplicationCacheChannel
                        , public nsIAsyncVerifyRedirectCallback
                        , public nsIAssociatedContentSecurity
                        , public nsIChildChannel
                        , public nsIHttpChannelChild
                        , public ChannelEventQueue<HttpChannelChild>
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSICACHEINFOCHANNEL
-  NS_DECL_NSICACHEINFOCHANNEL_GECKO_2_0
   NS_DECL_NSIPROXIEDCHANNEL
   NS_DECL_NSITRACEABLECHANNEL
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
   NS_DECL_NSIAPPLICATIONCACHECHANNEL
   NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
   NS_DECL_NSIASSOCIATEDCONTENTSECURITY
   NS_DECL_NSICHILDCHANNEL
   NS_DECL_NSIHTTPCHANNELCHILD
@@ -104,19 +102,16 @@ public:
   NS_IMETHOD Resume();
   // nsIChannel
   NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
   NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext);
   // HttpBaseChannel::nsIHttpChannel
   NS_IMETHOD SetRequestHeader(const nsACString& aHeader, 
                               const nsACString& aValue, 
                               PRBool aMerge);
-  NS_IMETHOD SetResponseHeader(const nsACString& aHeader,
-                               const nsACString& aValue,
-                               PRBool aMerge);
   // nsIHttpChannelInternal
   NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey);
   // nsISupportsPriority
   NS_IMETHOD SetPriority(PRInt32 value);
   // nsIResumableChannel
   NS_IMETHOD ResumeAt(PRUint64 startPos, const nsACString& entityID);
 
   // IPDL holds a reference while the PHttpChannel protocol is live (starting at
@@ -166,21 +161,17 @@ private:
   nsCString    mCachedCharset;
 
   // If ResumeAt is called before AsyncOpen, we need to send extra data upstream
   bool mSendResumeAt;
   // Current suspension depth for this channel object
   PRUint32 mSuspendCount;
 
   bool mIPCOpen;
-  // Indicates IPDL channel was not deleted during OnStopRequest, because
-  // 1) this a document-level channel (IPDL channel will be deleted during
-  // destructor); or 2) mCacheEntryClosePreventionCount is non-zero (IPDL
-  // channel will be deleted when count hits 0).
-  bool mDeferredIPDLClose;
+  bool mKeptAlive;
 
   void OnStartRequest(const nsHttpResponseHead& responseHead,
                           const PRBool& useResponseHead,
                           const RequestHeaderTuples& requestHeaders,
                           const PRBool& isFromCache,
                           const PRBool& cacheEntryAvailable,
                           const PRUint32& cacheExpirationTime,
                           const nsCString& cachedCharset,
@@ -194,21 +185,16 @@ private:
   void OnCancel(const nsresult& status);
   void Redirect1Begin(const PRUint32& newChannelId,
                       const URI& newUri,
                       const PRUint32& redirectFlags,
                       const nsHttpResponseHead& responseHead);
   void Redirect3Complete();
   void DeleteSelf();
 
-  void MaybeCloseIPDL(bool forceDocumentLoadDeletion = false);
-
-  virtual void OnIncreaseCacheEntryClosePreventCount();
-  virtual void OnDecreaseCacheEntryClosePreventCount();
-
   friend class StartRequestEvent;
   friend class StopRequestEvent;
   friend class DataAvailableEvent;
   friend class ProgressEvent;
   friend class StatusEvent;
   friend class CancelEvent;
   friend class Redirect1Event;
   friend class Redirect3Event;
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -80,19 +80,16 @@ HttpChannelParent::~HttpChannelParent()
 }
 
 void
 HttpChannelParent::ActorDestroy(ActorDestroyReason why)
 {
   // We may still have refcount>0 if nsHttpChannel hasn't called OnStopRequest
   // yet, but we must not send any more msgs to child.
   mIPCClosed = true;
-
-  // As we know the child channel has finished, let the cache entry close.
-  mCacheClosePreventer = 0;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsISupports
 //-----------------------------------------------------------------------------
 
 NS_IMPL_ISUPPORTS6(HttpChannelParent,
                    nsIInterfaceRequestor,
@@ -295,35 +292,19 @@ HttpChannelParent::RecvCancel(const nsre
   }
   return true;
 }
 
 
 bool
 HttpChannelParent::RecvSetCacheTokenCachedCharset(const nsCString& charset)
 {
-  nsHttpChannel *chan = static_cast<nsHttpChannel *>(mChannel.get());
-
-  nsresult rv;
-
-  nsCOMPtr<nsICacheEntryDescriptor> cacheDescriptor;
-  rv = chan->GetCacheToken(getter_AddRefs(cacheDescriptor));
-  if (NS_SUCCEEDED(rv))
-    cacheDescriptor->SetMetaDataElement("charset",
-                                        PromiseFlatCString(charset).get());
-  return true;
-}
-
-bool
-HttpChannelParent::RecvSetResponseHeader(const nsCString& header,
-                                         const nsCString& value,
-                                         const bool& merge)
-{
-  nsHttpChannel *chan = static_cast<nsHttpChannel *>(mChannel.get());
-  chan->SetResponseHeader(header, value, merge);
+  if (mCacheDescriptor)
+    mCacheDescriptor->SetMetaDataElement("charset",
+                                         PromiseFlatCString(charset).get());
   return true;
 }
 
 bool
 HttpChannelParent::RecvUpdateAssociatedContentSecurity(const PRInt32& high,
                                                        const PRInt32& low,
                                                        const PRInt32& broken,
                                                        const PRInt32& no)
@@ -367,17 +348,17 @@ HttpChannelParent::RecvRedirect2Verify(c
   return true;
 }
 
 bool
 HttpChannelParent::RecvDocumentChannelCleanup()
 {
   // We must clear the cache entry here, else we'll block other channels from
   // reading it if we've got it open for writing.  
-  mCacheClosePreventer = 0;
+  mCacheDescriptor = 0;
 
   return true;
 }
 
 bool 
 HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign()
 {
   nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
@@ -419,24 +400,19 @@ HttpChannelParent::OnStartRequest(nsIReq
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(aRequest);
   if (encodedChannel)
     encodedChannel->SetApplyConversion(PR_FALSE);
 
-  // Prevent cache entry from being closed during HttpChannel::OnStopRequest:
-  // - We need the cache entry for RecvSetCacheTokenCachedCharset()
-  // - The child channel may call GetCacheEntryClosePreventer, so we have to
-  //   call it now (otherwise we could hit OnStopRequest and close entry
-  //   before child gets a chance to keep it open).
-  // We close entry either when RecvDocumentChannelCleanup is called, or the
-  // IPDL channel is deleted.
-  chan->GetCacheEntryClosePreventer(getter_AddRefs(mCacheClosePreventer));
+  // Keep the cache entry for future use in RecvSetCacheTokenCachedCharset().
+  // It could be already released by nsHttpChannel at that time.
+  chan->GetCacheToken(getter_AddRefs(mCacheDescriptor));
 
   nsCString secInfoSerialization;
   nsCOMPtr<nsISupports> secInfoSupp;
   chan->GetSecurityInfo(getter_AddRefs(secInfoSupp));
   if (secInfoSupp) {
     nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(secInfoSupp);
     if (secInfoSer)
       NS_SerializeToString(secInfoSer, secInfoSerialization);
@@ -447,25 +423,22 @@ HttpChannelParent::OnStartRequest(nsIReq
 
   for (PRUint32 i = 0; i < harray.Count(); i++) {
     RequestHeaderTuple* tuple = headers.AppendElement();
     tuple->mHeader = harray.Headers()[i].header;
     tuple->mValue  = harray.Headers()[i].value;
     tuple->mMerge  = false;
   }
 
-  nsCOMPtr<nsICacheEntryDescriptor> cacheDescriptor;
-  chan->GetCacheToken(getter_AddRefs(cacheDescriptor));
-
   if (mIPCClosed || 
       !SendOnStartRequest(responseHead ? *responseHead : nsHttpResponseHead(), 
                           !!responseHead,
                           headers,
                           isFromCache,
-                          cacheDescriptor ? PR_TRUE : PR_FALSE,
+                          mCacheDescriptor ? PR_TRUE : PR_FALSE,
                           expirationTime, cachedCharset, secInfoSerialization)) 
   {
     return NS_ERROR_UNEXPECTED; 
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -94,19 +94,16 @@ protected:
                              const PRUint64&            startPos,
                              const nsCString&           entityID,
                              const bool&                chooseApplicationCache,
                              const nsCString&           appCacheClientID);
 
   virtual bool RecvConnectChannel(const PRUint32& channelId);
   virtual bool RecvSetPriority(const PRUint16& priority);
   virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset);
-  virtual bool RecvSetResponseHeader(const nsCString& header,
-                                     const nsCString& value,
-                                     const bool& merge);
   virtual bool RecvSuspend();
   virtual bool RecvResume();
   virtual bool RecvCancel(const nsresult& status);
   virtual bool RecvRedirect2Verify(const nsresult& result,
                                    const RequestHeaderTuples& changedHeaders);
   virtual bool RecvUpdateAssociatedContentSecurity(const PRInt32& high,
                                                    const PRInt32& low,
                                                    const PRInt32& broken,
@@ -117,17 +114,17 @@ protected:
   virtual void ActorDestroy(ActorDestroyReason why);
 
 protected:
   friend class mozilla::net::HttpChannelParentListener;
   nsCOMPtr<nsITabParent> mTabParent;
 
 private:
   nsCOMPtr<nsIChannel> mChannel;
-  nsCOMPtr<nsISupports> mCacheClosePreventer;
+  nsCOMPtr<nsICacheEntryDescriptor> mCacheDescriptor;
   bool mIPCClosed;                // PHttpChannel actor has been Closed()
 
   nsCOMPtr<nsIChannel> mRedirectChannel;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
 };
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -81,17 +81,16 @@ parent:
             bool                chooseApplicationCache,
             nsCString           appCacheClientID);
 
   ConnectChannel(PRUint32 channelId);
 
   SetPriority(PRUint16 priority);
 
   SetCacheTokenCachedCharset(nsCString charset);
-  SetResponseHeader(nsCString header, nsCString value, bool merge);
 
   UpdateAssociatedContentSecurity(PRInt32 high,
                                   PRInt32 low,
                                   PRInt32 broken,
                                   PRInt32 no);
   Suspend();
   Resume();
 
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -116,16 +116,17 @@ nsHttpChannel::nsHttpChannel()
     : mLogicalOffset(0)
     , mCacheAccess(0)
     , mPostID(0)
     , mRequestTime(0)
     , mOnCacheEntryAvailableCallback(nsnull)
     , mAsyncCacheOpen(PR_FALSE)
     , mPendingAsyncCallOnResume(nsnull)
     , mSuspendCount(0)
+    , mCacheEntryClosePreventionCount(0)
     , mCachedContentIsValid(PR_FALSE)
     , mCachedContentIsPartial(PR_FALSE)
     , mTransactionReplaced(PR_FALSE)
     , mAuthRetryPending(PR_FALSE)
     , mResuming(PR_FALSE)
     , mInitedCacheEntry(PR_FALSE)
     , mCacheForOfflineUse(PR_FALSE)
     , mCachingOpportunistically(PR_FALSE)
@@ -4218,43 +4219,56 @@ nsHttpChannel::SetCacheTokenCachedCharse
     return mCacheEntry->SetMetaDataElement("charset",
                                            PromiseFlatCString(aCharset).get());
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIHttpChannelInternal_GECKO_2_0
 //-----------------------------------------------------------------------------
 
+class HttpChannelCacheEntryClosePreventer : public nsISupports
+{
+public:
+    NS_DECL_ISUPPORTS
+
+    HttpChannelCacheEntryClosePreventer(nsHttpChannel* channel)
+    : mChannel(channel)
+    {
+        ++mChannel->mCacheEntryClosePreventionCount;
+        LOG(("mCacheEntryClosePreventionCount increased to %d, [this=%x]",
+             mChannel->mCacheEntryClosePreventionCount,
+             mChannel.get()));
+    }
+
+private:
+    ~HttpChannelCacheEntryClosePreventer()
+    {
+        --mChannel->mCacheEntryClosePreventionCount;
+        LOG(("mCacheEntryClosePreventionCount decreased to %d, [this=%x]",
+             mChannel->mCacheEntryClosePreventionCount,
+             mChannel.get()));
+
+        if (!mChannel->mCacheEntryClosePreventionCount &&
+            mChannel->mDeferredCacheEntryClose) {
+            mChannel->CloseCacheEntryInternal();
+        }
+    }
+
+    nsRefPtr<nsHttpChannel> mChannel;
+};
+
+NS_IMPL_ISUPPORTS0(HttpChannelCacheEntryClosePreventer)
+
 NS_IMETHODIMP
 nsHttpChannel::GetCacheEntryClosePreventer(nsISupports** _retval)
 {
-    NS_ADDREF(*_retval = new CacheEntryClosePreventer(this));
+    NS_ADDREF(*_retval = new HttpChannelCacheEntryClosePreventer(this));
     return NS_OK;
 }
 
-void
-nsHttpChannel::OnIncreaseCacheEntryClosePreventCount()
-{
-    ++mCacheEntryClosePreventionCount;
-    LOG(("nsHttpChannel::mCacheEntryClosePreventionCount increased to %d, [this=%x]",
-         mCacheEntryClosePreventionCount, this));
-}
-
-void
-nsHttpChannel::OnDecreaseCacheEntryClosePreventCount()
-{
-    --mCacheEntryClosePreventionCount;
-    LOG(("nsHttpChannel::mCacheEntryClosePreventionCount decreased to %d, [this=%x]",
-         mCacheEntryClosePreventionCount, this));
-
-    if (!mCacheEntryClosePreventionCount && mDeferredCacheEntryClose) {
-        CloseCacheEntryInternal();
-    }
-}
-
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsICachingChannel
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsHttpChannel::GetCacheToken(nsISupports **token)
 {
     NS_ENSURE_ARG_POINTER(token);
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -271,19 +271,16 @@ private:
     nsresult ProcessSTSHeader();
 
     /**
      * Computes and returns a 64 bit encoded string holding a hash of the
      * input buffer. Input buffer must be a null-terminated string.
      */
     nsresult Hash(const char *buf, nsACString &hash);
 
-    virtual void OnIncreaseCacheEntryClosePreventCount();
-    virtual void OnDecreaseCacheEntryClosePreventCount();
-
 private:
     nsCOMPtr<nsISupports>             mSecurityInfo;
     nsCOMPtr<nsICancelable>           mProxyRequest;
 
     nsRefPtr<nsInputStreamPump>       mTransactionPump;
     nsRefPtr<nsHttpTransaction>       mTransaction;
 
     PRUint64                          mLogicalOffset;
@@ -325,16 +322,20 @@ private:
     // cache entry.
     nsCString                         mFallbackKey;
 
     friend class AutoRedirectVetoNotifier;
     nsCOMPtr<nsIURI>                  mRedirectURI;
     nsCOMPtr<nsIChannel>              mRedirectChannel;
     PRUint32                          mRedirectType;
 
+    // Hold counter, keeps the number of calls to holdCacheEntry(), positive
+    // value prevents the cache entry from release in OnStopRequest.
+    PRUint32                          mCacheEntryClosePreventionCount;
+
     // state flags
     PRUint32                          mCachedContentIsValid     : 1;
     PRUint32                          mCachedContentIsPartial   : 1;
     PRUint32                          mTransactionReplaced      : 1;
     PRUint32                          mAuthRetryPending         : 1;
     PRUint32                          mResuming                 : 1;
     PRUint32                          mInitedCacheEntry         : 1;
     PRUint32                          mCacheForOfflineUse       : 1;
@@ -362,11 +363,13 @@ private:
 
     nsTArray<nsContinueRedirectionFunc> mRedirectFuncStack;
 
     nsCOMPtr<nsICryptoHash>        mHasher;
 
     nsresult WaitForRedirectCallback();
     void PushRedirectAsyncFunc(nsContinueRedirectionFunc func);
     void PopRedirectAsyncFunc(nsContinueRedirectionFunc func);
+
+    friend class HttpChannelCacheEntryClosePreventer;
 };
 
 #endif // nsHttpChannel_h__