Bug 1266196 - Make about:cache handler be multiple-instance capable. r=michal, a=sledru
authorHonza Bambas <honzab.moz@firemni.cz>
Mon, 30 May 2016 09:54:00 -0400
changeset 333173 db6a952a98f8933de30705edb0068c6bcfc3f8c9
parent 333172 378c67747196158ebeebba9e2bc0528d9159b11b
child 333174 be0703a058c65df02b8937f5b93417301f208688
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal, sledru
bugs1266196
milestone48.0a2
Bug 1266196 - Make about:cache handler be multiple-instance capable. r=michal, a=sledru
netwerk/protocol/about/nsAboutCache.cpp
netwerk/protocol/about/nsAboutCache.h
netwerk/protocol/about/nsAboutCacheEntry.cpp
netwerk/protocol/about/nsAboutCacheEntry.h
--- a/netwerk/protocol/about/nsAboutCache.cpp
+++ b/netwerk/protocol/about/nsAboutCache.cpp
@@ -20,28 +20,41 @@
 #include "nsICacheStorage.h"
 #include "CacheFileUtils.h"
 #include "CacheObserver.h"
 
 #include "nsThreadUtils.h"
 
 using namespace mozilla::net;
 
-NS_IMPL_ISUPPORTS(nsAboutCache, nsIAboutModule, nsICacheStorageVisitor)
+NS_IMPL_ISUPPORTS(nsAboutCache, nsIAboutModule)
+NS_IMPL_ISUPPORTS(nsAboutCache::Channel, nsIChannel, nsIRequest, nsICacheStorageVisitor)
 
 NS_IMETHODIMP
 nsAboutCache::NewChannel(nsIURI* aURI,
                          nsILoadInfo* aLoadInfo,
                          nsIChannel** result)
 {
+    nsresult rv;
+
     NS_ENSURE_ARG_POINTER(aURI);
 
-    nsresult rv;
+    RefPtr<Channel> channel = new Channel();
+    rv = channel->Init(aURI, aLoadInfo);
+    if (NS_FAILED(rv)) return rv;
+
+    channel.forget(result);
 
-    *result = nullptr;
+    return NS_OK;
+}
+
+nsresult
+nsAboutCache::Channel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo)
+{
+    nsresult rv;
 
     nsCOMPtr<nsIInputStream> inputStream;
     rv = NS_NewPipe(getter_AddRefs(inputStream), getter_AddRefs(mStream),
                     16384, (uint32_t)-1,
                     true, // non-blocking input
                     false // blocking output
     );
     if (NS_FAILED(rv)) return rv;
@@ -59,18 +72,17 @@ nsAboutCache::NewChannel(nsIURI* aURI,
     } else {
         // ...and visit just the specified storage, entries will output too
         mStorageList.AppendElement(storageName);
     }
 
     // The entries header is added on encounter of the first entry
     mEntriesHeaderAdded = false;
 
-    nsCOMPtr<nsIChannel> channel;
-    rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
+    rv = NS_NewInputStreamChannelInternal(getter_AddRefs(mChannel),
                                           aURI,
                                           inputStream,
                                           NS_LITERAL_CSTRING("text/html"),
                                           NS_LITERAL_CSTRING("utf-8"),
                                           aLoadInfo);
     if (NS_FAILED(rv)) return rv;
 
     mBuffer.AssignLiteral(
@@ -116,22 +128,21 @@ nsAboutCache::NewChannel(nsIURI* aURI,
     }
 
     FlushBuffer();
 
     // Kick it, this goes async.
     rv = VisitNextStorage();
     if (NS_FAILED(rv)) return rv;
 
-    channel.forget(result);
     return NS_OK;
 }
 
 nsresult
-nsAboutCache::ParseURI(nsIURI * uri, nsACString & storage)
+nsAboutCache::Channel::ParseURI(nsIURI * uri, nsACString & storage)
 {
     //
     // about:cache[?storage=<storage-name>[&context=<context-key>]]
     //
     nsresult rv;
 
     nsAutoCString path;
     rv = uri->GetPath(path);
@@ -162,35 +173,35 @@ nsAboutCache::ParseURI(nsIURI * uri, nsA
     mContextString = Substring(valueStart, end);
     mLoadInfo = CacheFileUtils::ParseKey(mContextString);
     storage.Assign(Substring(storageNameBegin, storageNameEnd));
 
     return NS_OK;
 }
 
 nsresult
-nsAboutCache::VisitNextStorage()
+nsAboutCache::Channel::VisitNextStorage()
 {
     if (!mStorageList.Length())
         return NS_ERROR_NOT_AVAILABLE;
 
     mStorageName = mStorageList[0];
     mStorageList.RemoveElementAt(0);
 
     // Must re-dispatch since we cannot start another visit cycle
     // from visitor callback.  The cache v1 service doesn't like it.
     // TODO - mayhemer, bug 913828, remove this dispatch and call
     // directly.
     nsCOMPtr<nsIRunnable> event =
-        NS_NewRunnableMethod(this, &nsAboutCache::FireVisitStorage);
+        NS_NewRunnableMethod(this, &nsAboutCache::Channel::FireVisitStorage);
     return NS_DispatchToMainThread(event);
 }
 
 void
-nsAboutCache::FireVisitStorage()
+nsAboutCache::Channel::FireVisitStorage()
 {
     nsresult rv;
 
     rv = VisitStorage(mStorageName);
     if (NS_FAILED(rv)) {
         if (mLoadInfo) {
             char* escaped = nsEscapeHTML(mStorageName.get());
             mBuffer.Append(
@@ -209,17 +220,17 @@ nsAboutCache::FireVisitStorage()
 
         // Simulate finish of a visit cycle, this tries the next storage
         // or closes the output stream (i.e. the UI loader will stop spinning)
         OnCacheEntryVisitCompleted();
     }
 }
 
 nsresult
-nsAboutCache::VisitStorage(nsACString const & storageName)
+nsAboutCache::Channel::VisitStorage(nsACString const & storageName)
 {
     nsresult rv;
 
     rv = GetStorage(storageName, mLoadInfo, getter_AddRefs(mStorage));
     if (NS_FAILED(rv)) return rv;
 
     rv = mStorage->AsyncVisitStorage(this, !mOverview);
     if (NS_FAILED(rv)) return rv;
@@ -254,18 +265,18 @@ nsAboutCache::GetStorage(nsACString cons
     }
     if (NS_FAILED(rv)) return rv;
 
     cacheStorage.forget(storage);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsAboutCache::OnCacheStorageInfo(uint32_t aEntryCount, uint64_t aConsumption,
-                                 uint64_t aCapacity, nsIFile * aDirectory)
+nsAboutCache::Channel::OnCacheStorageInfo(uint32_t aEntryCount, uint64_t aConsumption,
+                                          uint64_t aCapacity, nsIFile * aDirectory)
 {
     // We need mStream for this
     if (!mStream) {
         return NS_ERROR_FAILURE;
     }
 
     mBuffer.AssignLiteral("<h2>");
     mBuffer.Append(mStorageName);
@@ -339,20 +350,20 @@ nsAboutCache::OnCacheStorageInfo(uint32_
         // the list we want to visit, artificially call it here.
         OnCacheEntryVisitCompleted();
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsAboutCache::OnCacheEntryInfo(nsIURI *aURI, const nsACString & aIdEnhance,
-                               int64_t aDataSize, int32_t aFetchCount,
-                               uint32_t aLastModified, uint32_t aExpirationTime,
-                               bool aPinned)
+nsAboutCache::Channel::OnCacheEntryInfo(nsIURI *aURI, const nsACString & aIdEnhance,
+                                        int64_t aDataSize, int32_t aFetchCount,
+                                        uint32_t aLastModified, uint32_t aExpirationTime,
+                                        bool aPinned)
 {
     // We need mStream for this
     if (!mStream) {
         return NS_ERROR_FAILURE;
     }
 
     if (!mEntriesHeaderAdded) {
         mBuffer.AppendLiteral("<hr/>\n"
@@ -461,17 +472,17 @@ nsAboutCache::OnCacheEntryInfo(nsIURI *a
     // Entry is done...
     mBuffer.AppendLiteral("  </tr>\n");
 
     FlushBuffer();
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsAboutCache::OnCacheEntryVisitCompleted()
+nsAboutCache::Channel::OnCacheEntryVisitCompleted()
 {
     if (!mStream) {
         return NS_ERROR_FAILURE;
     }
 
     if (mEntriesHeaderAdded) {
         mBuffer.AppendLiteral("</table>\n");
     }
@@ -490,17 +501,17 @@ nsAboutCache::OnCacheEntryVisitCompleted
                           "</html>\n");
     FlushBuffer();
     mStream->Close();
 
     return NS_OK;
 }
 
 void
-nsAboutCache::FlushBuffer()
+nsAboutCache::Channel::FlushBuffer()
 {
     uint32_t bytesWritten;
     mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
     mBuffer.Truncate();
 }
 
 NS_IMETHODIMP
 nsAboutCache::GetURIFlags(nsIURI *aURI, uint32_t *result)
--- a/netwerk/protocol/about/nsAboutCache.h
+++ b/netwerk/protocol/about/nsAboutCache.h
@@ -13,74 +13,89 @@
 #include "nsString.h"
 #include "nsIOutputStream.h"
 #include "nsILoadContextInfo.h"
 
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 
 class nsAboutCache final : public nsIAboutModule
-                         , public nsICacheStorageVisitor
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIABOUTMODULE
-    NS_DECL_NSICACHESTORAGEVISITOR
 
     nsAboutCache() {}
 
     static nsresult
     Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
 
     static nsresult
     GetStorage(nsACString const & storageName, nsILoadContextInfo* loadInfo,
                nsICacheStorage **storage);
 
 protected:
     virtual ~nsAboutCache() {}
 
-    nsresult ParseURI(nsIURI * uri, nsACString & storage);
+    class Channel final : public nsIChannel
+                        , public nsICacheStorageVisitor
+    {
+        NS_DECL_ISUPPORTS
+        NS_DECL_NSICACHESTORAGEVISITOR
+        NS_FORWARD_SAFE_NSICHANNEL(mChannel)
+        NS_FORWARD_SAFE_NSIREQUEST(mChannel)
+
+    private:
+        virtual ~Channel() {}
 
-    // Finds a next storage we wish to visit (we use this method
-    // even there is a specified storage name, which is the only
-    // one in the list then.)  Posts FireVisitStorage() when found.
-    nsresult VisitNextStorage();
-    // Helper method that calls VisitStorage() for the current storage.
-    // When it fails, OnCacheEntryVisitCompleted is simlated to close
-    // the output stream and thus the about:cache channel.
-    void FireVisitStorage();
-    // Kiks the visit cycle for the given storage, names can be:
-    // "disk", "memory", "appcache"
-    // Note: any newly added storage type has to be manually handled here.
-    nsresult VisitStorage(nsACString const & storageName);
+    public:
+        nsresult Init(nsIURI* aURI, nsILoadInfo* aLoadInfo);
+        nsresult ParseURI(nsIURI * uri, nsACString & storage);
 
-    // Writes content of mBuffer to mStream and truncates
-    // the buffer.
-    void FlushBuffer();
+        // Finds a next storage we wish to visit (we use this method
+        // even there is a specified storage name, which is the only
+        // one in the list then.)  Posts FireVisitStorage() when found.
+        nsresult VisitNextStorage();
+        // Helper method that calls VisitStorage() for the current storage.
+        // When it fails, OnCacheEntryVisitCompleted is simlated to close
+        // the output stream and thus the about:cache channel.
+        void FireVisitStorage();
+        // Kiks the visit cycle for the given storage, names can be:
+        // "disk", "memory", "appcache"
+        // Note: any newly added storage type has to be manually handled here.
+        nsresult VisitStorage(nsACString const & storageName);
 
-    // Whether we are showing overview status of all available
-    // storages.
-    bool mOverview;
+        // Writes content of mBuffer to mStream and truncates
+        // the buffer.
+        void FlushBuffer();
 
-    // Flag initially false, that indicates the entries header has
-    // been added to the output HTML.
-    bool mEntriesHeaderAdded;
+        // Whether we are showing overview status of all available
+        // storages.
+        bool mOverview;
+
+        // Flag initially false, that indicates the entries header has
+        // been added to the output HTML.
+        bool mEntriesHeaderAdded;
 
-    // The context we are working with.
-    nsCOMPtr<nsILoadContextInfo> mLoadInfo;
-    nsCString mContextString;
+        // The context we are working with.
+        nsCOMPtr<nsILoadContextInfo> mLoadInfo;
+        nsCString mContextString;
 
-    // The list of all storage names we want to visit
-    nsTArray<nsCString> mStorageList;
-    nsCString mStorageName;
-    nsCOMPtr<nsICacheStorage> mStorage;
+        // The list of all storage names we want to visit
+        nsTArray<nsCString> mStorageList;
+        nsCString mStorageName;
+        nsCOMPtr<nsICacheStorage> mStorage;
 
-    // Output data buffering and streaming output
-    nsCString mBuffer;
-    nsCOMPtr<nsIOutputStream> mStream;
+        // Output data buffering and streaming output
+        nsCString mBuffer;
+        nsCOMPtr<nsIOutputStream> mStream;
+
+        // The input stream channel, the one that actually does the job
+        nsCOMPtr<nsIChannel> mChannel;
+    };
 };
 
 #define NS_ABOUT_CACHE_MODULE_CID                    \
 { /* 9158c470-86e4-11d4-9be2-00e09872a416 */         \
     0x9158c470,                                      \
     0x86e4,                                          \
     0x11d4,                                          \
     {0x9b, 0xe2, 0x00, 0xe0, 0x98, 0x72, 0xa4, 0x16} \
--- a/netwerk/protocol/about/nsAboutCacheEntry.cpp
+++ b/netwerk/protocol/about/nsAboutCacheEntry.cpp
@@ -76,41 +76,41 @@ HexDump(uint32_t *state, const char *buf
     n -= row_max;
   }
 }
 
 //-----------------------------------------------------------------------------
 // nsAboutCacheEntry::nsISupports
 
 NS_IMPL_ISUPPORTS(nsAboutCacheEntry,
-                  nsIAboutModule,
+                  nsIAboutModule)
+NS_IMPL_ISUPPORTS(nsAboutCacheEntry::Channel,
                   nsICacheEntryOpenCallback,
                   nsICacheEntryMetaDataVisitor,
-                  nsIStreamListener)
+                  nsIStreamListener,
+                  nsIChannel)
 
 //-----------------------------------------------------------------------------
 // nsAboutCacheEntry::nsIAboutModule
 
 NS_IMETHODIMP
 nsAboutCacheEntry::NewChannel(nsIURI* uri,
                               nsILoadInfo* aLoadInfo,
                               nsIChannel** result)
 {
     NS_ENSURE_ARG_POINTER(uri);
     nsresult rv;
 
-    nsCOMPtr<nsIInputStream> stream;
-    rv = GetContentStream(uri, getter_AddRefs(stream));
+    RefPtr<Channel> channel = new Channel();
+    rv = channel->Init(uri, aLoadInfo);
     if (NS_FAILED(rv)) return rv;
-    return NS_NewInputStreamChannelInternal(result,
-                                            uri,
-                                            stream,
-                                            NS_LITERAL_CSTRING("text/html"),
-                                            NS_LITERAL_CSTRING("utf-8"),
-                                            aLoadInfo);
+
+    channel.forget(result);
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAboutCacheEntry::GetURIFlags(nsIURI *aURI, uint32_t *result)
 {
     *result = nsIAboutModule::HIDE_FROM_ABOUTABOUT;
     return NS_OK;
 }
@@ -118,20 +118,40 @@ nsAboutCacheEntry::GetURIFlags(nsIURI *a
 NS_IMETHODIMP
 nsAboutCacheEntry::GetIndexedDBOriginPostfix(nsIURI *aURI, nsAString &result)
 {
     SetDOMStringToNull(result);
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 //-----------------------------------------------------------------------------
-// nsAboutCacheEntry
+// nsAboutCacheEntry::Channel
 
 nsresult
-nsAboutCacheEntry::GetContentStream(nsIURI *uri, nsIInputStream **result)
+nsAboutCacheEntry::Channel::Init(nsIURI* uri, nsILoadInfo* aLoadInfo)
+{
+    nsresult rv;
+
+    nsCOMPtr<nsIInputStream> stream;
+    rv = GetContentStream(uri, getter_AddRefs(stream));
+    if (NS_FAILED(rv)) return rv;
+
+    rv =  NS_NewInputStreamChannelInternal(getter_AddRefs(mChannel),
+                                           uri,
+                                           stream,
+                                           NS_LITERAL_CSTRING("text/html"),
+                                           NS_LITERAL_CSTRING("utf-8"),
+                                           aLoadInfo);
+    if (NS_FAILED(rv)) return rv;
+
+    return NS_OK;
+}
+
+nsresult
+nsAboutCacheEntry::Channel::GetContentStream(nsIURI *uri, nsIInputStream **result)
 {
     nsresult rv;
 
     // Init: (block size, maximum length)
     nsCOMPtr<nsIAsyncInputStream> inputStream;
     rv = NS_NewPipe2(getter_AddRefs(inputStream),
                      getter_AddRefs(mOutputStream),
                      true, false,
@@ -159,17 +179,17 @@ nsAboutCacheEntry::GetContentStream(nsIU
     rv = OpenCacheEntry(uri);
     if (NS_FAILED(rv)) return rv;
 
     inputStream.forget(result);
     return NS_OK;
 }
 
 nsresult
-nsAboutCacheEntry::OpenCacheEntry(nsIURI *uri)
+nsAboutCacheEntry::Channel::OpenCacheEntry(nsIURI *uri)
 {
     nsresult rv;
 
     rv = ParseURI(uri, mStorageName, getter_AddRefs(mLoadInfo),
                        mEnhanceId, getter_AddRefs(mCacheURI));
     if (NS_FAILED(rv)) return rv;
 
     if (!CacheObserver::UseNewCache() &&
@@ -179,38 +199,38 @@ nsAboutCacheEntry::OpenCacheEntry(nsIURI
         // cache, so it would not be found in the v1 disk cache.
         mStorageName = NS_LITERAL_CSTRING("memory");
     }
 
     return OpenCacheEntry();
 }
 
 nsresult
-nsAboutCacheEntry::OpenCacheEntry()
+nsAboutCacheEntry::Channel::OpenCacheEntry()
 {
     nsresult rv;
 
     nsCOMPtr<nsICacheStorage> storage;
     rv = nsAboutCache::GetStorage(mStorageName, mLoadInfo, getter_AddRefs(storage));
     if (NS_FAILED(rv)) return rv;
 
     // Invokes OnCacheEntryAvailable()
     rv = storage->AsyncOpenURI(mCacheURI, mEnhanceId,
                                nsICacheStorage::OPEN_READONLY, this);
     if (NS_FAILED(rv)) return rv;
 
     return NS_OK;
 }
 
 nsresult
-nsAboutCacheEntry::ParseURI(nsIURI *uri,
-                            nsACString &storageName,
-                            nsILoadContextInfo **loadInfo,
-                            nsCString &enahnceID,
-                            nsIURI **cacheUri)
+nsAboutCacheEntry::Channel::ParseURI(nsIURI *uri,
+                                     nsACString &storageName,
+                                     nsILoadContextInfo **loadInfo,
+                                     nsCString &enahnceID,
+                                     nsIURI **cacheUri)
 {
     //
     // about:cache-entry?storage=[string]&contenxt=[string]&eid=[string]&uri=[string]
     //
     nsresult rv;
 
     nsAutoCString path;
     rv = uri->GetPath(path);
@@ -265,29 +285,29 @@ nsAboutCacheEntry::ParseURI(nsIURI *uri,
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsICacheEntryOpenCallback implementation
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsAboutCacheEntry::OnCacheEntryCheck(nsICacheEntry *aEntry,
-                                     nsIApplicationCache *aApplicationCache,
-                                     uint32_t *result)
+nsAboutCacheEntry::Channel::OnCacheEntryCheck(nsICacheEntry *aEntry,
+                                              nsIApplicationCache *aApplicationCache,
+                                              uint32_t *result)
 {
     *result = nsICacheEntryOpenCallback::ENTRY_WANTED;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsAboutCacheEntry::OnCacheEntryAvailable(nsICacheEntry *entry,
-                                         bool isNew,
-                                         nsIApplicationCache *aApplicationCache,
-                                         nsresult status)
+nsAboutCacheEntry::Channel::OnCacheEntryAvailable(nsICacheEntry *entry,
+                                                  bool isNew,
+                                                  nsIApplicationCache *aApplicationCache,
+                                                  nsresult status)
 {
     nsresult rv;
 
     mWaitingForData = false;
     if (entry) {
         rv = WriteCacheEntryDescription(entry);
     } else if (!CacheObserver::UseNewCache() &&
                !mLoadInfo->IsPrivate() &&
@@ -329,17 +349,17 @@ nsAboutCacheEntry::OnCacheEntryAvailable
     buffer.AppendLiteral(":</th>\n" \
                          "    <td>"); \
     buffer.Append(value); \
     buffer.AppendLiteral("</td>\n" \
                          "  </tr>\n"); \
     PR_END_MACRO
 
 nsresult
-nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntry *entry)
+nsAboutCacheEntry::Channel::WriteCacheEntryDescription(nsICacheEntry *entry)
 {
     nsresult rv;
     nsCString buffer;
     uint32_t n;
 
     nsAutoCString str;
 
     rv = entry->GetKey(str);
@@ -479,31 +499,31 @@ nsAboutCacheEntry::WriteCacheEntryDescri
         return NS_OK; // just ignore
     }
 
     mWaitingForData = true;
     return NS_OK;
 }
 
 nsresult
-nsAboutCacheEntry::WriteCacheEntryUnavailable()
+nsAboutCacheEntry::Channel::WriteCacheEntryUnavailable()
 {
     uint32_t n;
     NS_NAMED_LITERAL_CSTRING(buffer,
         "The cache entry you selected is not available.");
     mOutputStream->Write(buffer.get(), buffer.Length(), &n);
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsICacheEntryMetaDataVisitor implementation
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsAboutCacheEntry::OnMetaDataElement(char const * key, char const * value)
+nsAboutCacheEntry::Channel::OnMetaDataElement(char const * key, char const * value)
 {
     mBuffer->AppendLiteral("  <tr>\n"
                            "    <th>");
     mBuffer->Append(key);
     mBuffer->AppendLiteral(":</th>\n"
                            "    <td>");
     char* escapedValue = nsEscapeHTML(value);
     mBuffer->Append(escapedValue);
@@ -514,73 +534,74 @@ nsAboutCacheEntry::OnMetaDataElement(cha
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // nsIStreamListener implementation
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
-nsAboutCacheEntry::OnStartRequest(nsIRequest *request, nsISupports *ctx)
+nsAboutCacheEntry::Channel::OnStartRequest(nsIRequest *request, nsISupports *ctx)
 {
     mHexDumpState = 0;
 
     NS_NAMED_LITERAL_CSTRING(buffer, "<hr/>\n<pre>");
     uint32_t n;
     return mOutputStream->Write(buffer.get(), buffer.Length(), &n);
 }
 
 NS_IMETHODIMP
-nsAboutCacheEntry::OnDataAvailable(nsIRequest *request, nsISupports *ctx,
+nsAboutCacheEntry::Channel::OnDataAvailable(nsIRequest *request, nsISupports *ctx,
                                    nsIInputStream *aInputStream,
                                    uint64_t aOffset,
                                    uint32_t aCount)
 {
     uint32_t n;
     return aInputStream->ReadSegments(
-        &nsAboutCacheEntry::PrintCacheData, this, aCount, &n);
+        &nsAboutCacheEntry::Channel::PrintCacheData, this, aCount, &n);
 }
 
 // static
 NS_METHOD
-nsAboutCacheEntry::PrintCacheData(nsIInputStream *aInStream,
-                                  void *aClosure,
-                                  const char *aFromSegment,
-                                  uint32_t aToOffset,
-                                  uint32_t aCount,
-                                  uint32_t *aWriteCount)
+nsAboutCacheEntry::Channel::PrintCacheData(nsIInputStream *aInStream,
+                                           void *aClosure,
+                                           const char *aFromSegment,
+                                           uint32_t aToOffset,
+                                           uint32_t aCount,
+                                           uint32_t *aWriteCount)
 {
-    nsAboutCacheEntry *a = static_cast<nsAboutCacheEntry*>(aClosure);
+    nsAboutCacheEntry::Channel *a =
+      static_cast<nsAboutCacheEntry::Channel*>(aClosure);
 
     nsCString buffer;
     HexDump(&a->mHexDumpState, aFromSegment, aCount, buffer);
 
     uint32_t n;
     a->mOutputStream->Write(buffer.get(), buffer.Length(), &n);
 
     *aWriteCount = aCount;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsAboutCacheEntry::OnStopRequest(nsIRequest *request, nsISupports *ctx,
-                                 nsresult result)
+nsAboutCacheEntry::Channel::OnStopRequest(nsIRequest *request, nsISupports *ctx,
+                                          nsresult result)
 {
     NS_NAMED_LITERAL_CSTRING(buffer, "</pre>\n");
     uint32_t n;
     mOutputStream->Write(buffer.get(), buffer.Length(), &n);
 
     CloseContent();
 
     return NS_OK;
 }
 
 void
-nsAboutCacheEntry::CloseContent()
+nsAboutCacheEntry::Channel::CloseContent()
 {
     NS_NAMED_LITERAL_CSTRING(buffer, "</body>\n</html>\n");
     uint32_t n;
     mOutputStream->Write(buffer.get(), buffer.Length(), &n);
 
     mOutputStream->Close();
     mOutputStream = nullptr;
 }
--- a/netwerk/protocol/about/nsAboutCacheEntry.h
+++ b/netwerk/protocol/about/nsAboutCacheEntry.h
@@ -14,65 +14,81 @@
 #include "nsCOMPtr.h"
 
 class nsIAsyncOutputStream;
 class nsIInputStream;
 class nsILoadContextInfo;
 class nsIURI;
 class nsCString;
 
-class nsAboutCacheEntry : public nsIAboutModule
-                        , public nsICacheEntryOpenCallback
-                        , public nsICacheEntryMetaDataVisitor
-                        , public nsIStreamListener
+class nsAboutCacheEntry final : public nsIAboutModule
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIABOUTMODULE
-    NS_DECL_NSICACHEENTRYOPENCALLBACK
-    NS_DECL_NSICACHEENTRYMETADATAVISITOR
-    NS_DECL_NSIREQUESTOBSERVER
-    NS_DECL_NSISTREAMLISTENER
-
-    nsAboutCacheEntry()
-        : mBuffer(nullptr)
-        , mWaitingForData(false)
-        , mHexDumpState(0)
-    {}
 
 private:
     virtual ~nsAboutCacheEntry() {}
 
-    nsresult GetContentStream(nsIURI *, nsIInputStream **);
-    nsresult OpenCacheEntry(nsIURI *);
-    nsresult OpenCacheEntry();
-    nsresult WriteCacheEntryDescription(nsICacheEntry *);
-    nsresult WriteCacheEntryUnavailable();
-    nsresult ParseURI(nsIURI *uri, nsACString &storageName,
-                      nsILoadContextInfo **loadInfo,
-                      nsCString &enahnceID, nsIURI **cacheUri);
-    void CloseContent();
+    class Channel final : public nsICacheEntryOpenCallback
+                        , public nsICacheEntryMetaDataVisitor
+                        , public nsIStreamListener
+                        , public nsIChannel
+    {
+    public:
+        NS_DECL_ISUPPORTS
+        NS_DECL_NSICACHEENTRYOPENCALLBACK
+        NS_DECL_NSICACHEENTRYMETADATAVISITOR
+        NS_DECL_NSIREQUESTOBSERVER
+        NS_DECL_NSISTREAMLISTENER
+        NS_FORWARD_SAFE_NSICHANNEL(mChannel)
+        NS_FORWARD_SAFE_NSIREQUEST(mChannel)
+
+        Channel()
+            : mBuffer(nullptr)
+            , mWaitingForData(false)
+            , mHexDumpState(0)
+        {}
+
+    private:
+        virtual ~Channel() {}
+
+    public:
+        nsresult Init(nsIURI* uri, nsILoadInfo* aLoadInfo);
 
-    static NS_METHOD
-    PrintCacheData(nsIInputStream *aInStream,
-                   void *aClosure,
-                   const char *aFromSegment,
-                   uint32_t aToOffset,
-                   uint32_t aCount,
-                   uint32_t *aWriteCount);
+        nsresult GetContentStream(nsIURI *, nsIInputStream **);
+        nsresult OpenCacheEntry(nsIURI *);
+        nsresult OpenCacheEntry();
+        nsresult WriteCacheEntryDescription(nsICacheEntry *);
+        nsresult WriteCacheEntryUnavailable();
+        nsresult ParseURI(nsIURI *uri, nsACString &storageName,
+                          nsILoadContextInfo **loadInfo,
+                          nsCString &enahnceID, nsIURI **cacheUri);
+        void CloseContent();
 
-private:
-    nsCString mStorageName, mEnhanceId;
-    nsCOMPtr<nsILoadContextInfo> mLoadInfo;
-    nsCOMPtr<nsIURI> mCacheURI;
+        static NS_METHOD
+        PrintCacheData(nsIInputStream *aInStream,
+                       void *aClosure,
+                       const char *aFromSegment,
+                       uint32_t aToOffset,
+                       uint32_t aCount,
+                       uint32_t *aWriteCount);
 
-    nsCString *mBuffer;
-    nsCOMPtr<nsIAsyncOutputStream> mOutputStream;
-    bool mWaitingForData;
-    uint32_t mHexDumpState;
+    private:
+        nsCString mStorageName, mEnhanceId;
+        nsCOMPtr<nsILoadContextInfo> mLoadInfo;
+        nsCOMPtr<nsIURI> mCacheURI;
+
+        nsCString *mBuffer;
+        nsCOMPtr<nsIAsyncOutputStream> mOutputStream;
+        bool mWaitingForData;
+        uint32_t mHexDumpState;
+
+        nsCOMPtr<nsIChannel> mChannel;
+    };
 };
 
 #define NS_ABOUT_CACHE_ENTRY_MODULE_CID              \
 { /* 7fa5237d-b0eb-438f-9e50-ca0166e63788 */         \
     0x7fa5237d,                                      \
     0xb0eb,                                          \
     0x438f,                                          \
     {0x9e, 0x50, 0xca, 0x01, 0x66, 0xe6, 0x37, 0x88} \