Bug 715837 - Crash @ mozilla::net::HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign, r=jduell
authorHonza Bambas <honzab.moz@firemni.cz>
Mon, 07 May 2012 13:20:21 +0200
changeset 93406 f63a2c79ad1b8b92dc11372a8cf55ba5f296631d
parent 93405 e763ef9f3d5d08b01168a6db2ddab4d6f839db89
child 93407 4b9a76ac2df38adfb2ef0860f3700ef8a9e3ac5f
push id22634
push useremorley@mozilla.com
push dateTue, 08 May 2012 09:48:43 +0000
treeherdermozilla-central@e4f9e2eab6b1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell
bugs715837
milestone15.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 715837 - Crash @ mozilla::net::HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign, r=jduell
netwerk/protocol/http/HttpChannelParent.cpp
netwerk/protocol/http/HttpChannelParent.h
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpChannel.h
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -38,17 +38,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/net/HttpChannelParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/unused.h"
 #include "HttpChannelParentListener.h"
-#include "nsHttpChannel.h"
 #include "nsHttpHandler.h"
 #include "nsNetUtil.h"
 #include "nsISupportsPriority.h"
 #include "nsIAuthPromptProvider.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIBadCertListener2.h"
 #include "nsICacheEntryDescriptor.h"
 #include "nsSerializationHelper.h"
@@ -389,18 +388,21 @@ HttpChannelParent::RecvDocumentChannelCl
   mChannel = 0;          // Reclaim some memory sooner.
   mCacheDescriptor = 0;  // Else we'll block other channels reading same URI
   return true;
 }
 
 bool 
 HttpChannelParent::RecvMarkOfflineCacheEntryAsForeign()
 {
-  nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get());
-  httpChan->MarkOfflineCacheEntryAsForeign();
+  if (mOfflineForeignMarker) {
+    mOfflineForeignMarker->MarkAsForeign();
+    mOfflineForeignMarker = 0;
+  }
+
   return true;
 }
 
 //-----------------------------------------------------------------------------
 // HttpChannelParent::nsIRequestObserver
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
@@ -416,16 +418,17 @@ HttpChannelParent::OnStartRequest(nsIReq
   PRUint32 expirationTime = nsICache::NO_EXPIRATION_TIME;
   chan->GetCacheTokenExpirationTime(&expirationTime);
   nsCString cachedCharset;
   chan->GetCacheTokenCachedCharset(cachedCharset);
 
   bool loadedFromApplicationCache;
   chan->GetLoadedFromApplicationCache(&loadedFromApplicationCache);
   if (loadedFromApplicationCache) {
+    mOfflineForeignMarker = chan->GetOfflineCacheEntryAsForeignMarker();
     nsCOMPtr<nsIApplicationCache> appCache;
     chan->GetApplicationCache(getter_AddRefs(appCache));
     nsCString appCacheGroupId;
     nsCString appCacheClientId;
     appCache->GetGroupID(appCacheGroupId);
     appCache->GetClientID(appCacheClientId);
     if (mIPCClosed || 
         !SendAssociateApplicationCache(appCacheGroupId, appCacheClientId))
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -44,16 +44,17 @@
 
 #include "nsHttp.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/net/PHttpChannelParent.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "nsIParentRedirectingChannel.h"
 #include "nsIProgressEventSink.h"
 #include "nsITabParent.h"
+#include "nsHttpChannel.h"
 
 using namespace mozilla::dom;
 
 class nsICacheEntryDescriptor;
 class nsIAssociatedContentSecurity;
 
 namespace mozilla {
 namespace net {
@@ -123,16 +124,18 @@ private:
   nsCOMPtr<nsIChannel>                    mChannel;
   nsCOMPtr<nsICacheEntryDescriptor>       mCacheDescriptor;
   nsCOMPtr<nsIAssociatedContentSecurity>  mAssociatedContentSecurity;
   bool mIPCClosed;                // PHttpChannel actor has been Closed()
 
   nsCOMPtr<nsIChannel> mRedirectChannel;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
 
+  nsAutoPtr<class nsHttpChannel::OfflineCacheEntryAsForeignMarker> mOfflineForeignMarker;
+
   // state for combining OnStatus/OnProgress with OnDataAvailable
   // into one IPDL call to child.
   nsresult mStoredStatus;
   PRUint64 mStoredProgress;
   PRUint64 mStoredProgressMax;
 
   bool mSentRedirect1Begin : 1;
   bool mSentRedirect1BeginFailed : 1;
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -5171,30 +5171,50 @@ NS_IMETHODIMP
 nsHttpChannel::SetChooseApplicationCache(bool aChoose)
 {
     NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
 
     mChooseApplicationCache = aChoose;
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHttpChannel::MarkOfflineCacheEntryAsForeign()
+nsHttpChannel::OfflineCacheEntryAsForeignMarker*
+nsHttpChannel::GetOfflineCacheEntryAsForeignMarker()
 {
     if (!mApplicationCache)
-        return NS_ERROR_NOT_AVAILABLE;
+        return nsnull;
 
     nsresult rv;
 
     nsCAutoString cacheKey;
     rv = GenerateCacheKey(mPostID, cacheKey);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = mApplicationCache->MarkEntry(cacheKey,
-                                      nsIApplicationCache::ITEM_FOREIGN);
+    NS_ENSURE_SUCCESS(rv, nsnull);
+
+    return new OfflineCacheEntryAsForeignMarker(mApplicationCache, cacheKey);
+}
+
+nsresult
+nsHttpChannel::OfflineCacheEntryAsForeignMarker::MarkAsForeign()
+{
+    return mApplicationCache->MarkEntry(mCacheKey,
+                                        nsIApplicationCache::ITEM_FOREIGN);
+}
+
+NS_IMETHODIMP
+nsHttpChannel::MarkOfflineCacheEntryAsForeign()
+{
+    nsresult rv;
+
+    nsAutoPtr<OfflineCacheEntryAsForeignMarker> marker(
+        GetOfflineCacheEntryAsForeignMarker());
+
+    if (!marker)
+        return NS_ERROR_NOT_AVAILABLE;
+
+    rv = marker->MarkAsForeign();
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsHttpChannel::nsIAsyncVerifyRedirectCallback
 //-----------------------------------------------------------------------------
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -156,16 +156,33 @@ public: /* internal necko use only */
         nsCAutoString spec;
         nsresult rv = referrer->GetAsciiSpec(spec);
         if (NS_FAILED(rv)) return rv;
         mReferrer = referrer;
         mRequestHead.SetHeader(nsHttp::Referer, spec);
         return NS_OK;
     }
 
+    // This allows cache entry to be marked as foreign even after channel itself
+    // is gone.  Needed for e10s (see HttpChannelParent::RecvDocumentChannelCleanup)
+    class OfflineCacheEntryAsForeignMarker {
+        nsCOMPtr<nsIApplicationCache> mApplicationCache;
+        nsCString mCacheKey;
+    public:
+        OfflineCacheEntryAsForeignMarker(nsIApplicationCache* appCache,
+                                         const nsCSubstring& key)
+             : mApplicationCache(appCache)
+             , mCacheKey(key)
+        {}
+
+        nsresult MarkAsForeign();
+    };
+
+    OfflineCacheEntryAsForeignMarker* GetOfflineCacheEntryAsForeignMarker();
+
 private:
     typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
 
     bool     RequestIsConditional();
     nsresult Connect(bool firstTime = true);
     void     SpeculativeConnect();
     nsresult SetupTransaction();
     nsresult CallOnStartRequest();