Bug 787743: Back out bug 722845 and bug 748890; a=lsblakk
☠☠ backed out by d5acbc9f90a6 ☠ ☠
authorEhsan Akhgari <ehsan>
Tue, 04 Sep 2012 08:42:00 -0400
changeset 106727 829a13b9968c0a6938a4a35df7919dd1209061d0
parent 106726 6ee9ade752e43008f8b78f81371000ff091a2527
child 106728 d5acbc9f90a64b133f44df5b9a83717880d28922
push idunknown
push userunknown
push dateunknown
reviewerslsblakk
bugs787743, 722845, 748890
milestone17.0a2
Bug 787743: Back out bug 722845 and bug 748890; a=lsblakk
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
content/base/src/nsContentSink.cpp
docshell/base/nsDocShell.cpp
netwerk/cache/nsCacheEntry.cpp
netwerk/cache/nsCacheEntry.h
netwerk/cache/nsCacheRequest.h
netwerk/cache/nsCacheService.cpp
netwerk/cache/nsCacheService.h
netwerk/cache/nsCacheSession.cpp
netwerk/cache/nsCacheSession.h
netwerk/cache/nsICacheSession.idl
netwerk/cache/nsMemoryCacheDevice.cpp
netwerk/cache/nsMemoryCacheDevice.h
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/nsHttpChannel.cpp
netwerk/protocol/http/nsHttpConnectionInfo.cpp
netwerk/protocol/http/nsHttpConnectionInfo.h
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
netwerk/protocol/wyciwyg/nsWyciwygChannel.h
netwerk/test/unit/test_bug248970_cache.js
xpcom/glue/nsISupportsImpl.h
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
@@ -3,26 +3,32 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   // We need to open a new window for this so that its docshell would get destroyed
   // when clearing the PB mode flag.
   let newWin = window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no");
   waitForExplicitFinish();
   SimpleTest.waitForFocus(function() {
-    let expected = false;
+    let notificationCount = 0;
     let observer = {
       observe: function(aSubject, aTopic, aData) {
         is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched");
-        is(expected, true, "notification not expected yet");
-        Services.obs.removeObserver(observer, "last-pb-context-exited", false);
-        gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
-        finish();
+        ++notificationCount;
       }
     };
     Services.obs.addObserver(observer, "last-pb-context-exited", false);
     setPrivateWindow(newWin, true);
-    expected = true;
-    newWin.close(); // this will cause the docshells to leave PB mode
+    SimpleTest.is(notificationCount, 0, "last-pb-context-exited should not be fired yet");
+    newWin.gPrivateBrowsingUI.privateWindow = false;
+    newWin.close();
     newWin = null;
-    SpecialPowers.forceGC();
+    window.QueryInterface(Ci.nsIInterfaceRequestor)
+          .getInterface(Ci.nsIDOMWindowUtils)
+          .garbageCollect(); // Make sure that the docshell is destroyed
+    SimpleTest.is(notificationCount, 1, "last-pb-context-exited should be fired once");
+    Services.obs.removeObserver(observer, "last-pb-context-exited", false);
+
+    // cleanup
+    gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
+    finish();
   }, newWin);
 }
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -11,17 +11,16 @@
 
 #include "nsContentSink.h"
 #include "nsScriptLoader.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "mozilla/css/Loader.h"
 #include "nsStyleLinkElement.h"
 #include "nsIDocShell.h"
-#include "nsILoadContext.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsCPrefetchService.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsIHttpChannel.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
@@ -1008,23 +1007,16 @@ void
 nsContentSink::ProcessOfflineManifest(const nsAString& aManifestSpec)
 {
   // Don't bother processing offline manifest for documents
   // without a docshell
   if (!mDocShell) {
     return;
   }
 
-  // If the docshell's in private browsing mode, we don't want to do any
-  // manifest processing.
-  nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(mDocShell);
-  if (loadContext->UsePrivateBrowsing()) {
-    return;
-  }
-
   nsresult rv;
 
   // Grab the application cache the document was loaded from, if any.
   nsCOMPtr<nsIApplicationCache> applicationCache;
 
   nsCOMPtr<nsIApplicationCacheChannel> applicationCacheChannel =
     do_QueryInterface(mDocument->GetChannel());
   if (applicationCacheChannel) {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -9072,20 +9072,16 @@ nsDocShell::GetInheritedPrincipal(bool a
     }
 
     return nullptr;
 }
 
 bool
 nsDocShell::ShouldCheckAppCache(nsIURI *aURI)
 {
-    if (mInPrivateBrowsing) {
-        return false;
-    }
-
     nsCOMPtr<nsIOfflineCacheUpdateService> offlineService =
         do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
     if (!offlineService) {
         return false;
     }
 
     bool allowed;
     nsresult rv = offlineService->OfflineAppAllowedForURI(aURI,
--- a/netwerk/cache/nsCacheEntry.cpp
+++ b/netwerk/cache/nsCacheEntry.cpp
@@ -37,18 +37,16 @@ nsCacheEntry::nsCacheEntry(const nsACStr
 {
     MOZ_COUNT_CTOR(nsCacheEntry);
     PR_INIT_CLIST(this);
     PR_INIT_CLIST(&mRequestQ);
     PR_INIT_CLIST(&mDescriptorQ);
 
     if (streamBased) MarkStreamBased();
     SetStoragePolicy(storagePolicy);
-
-    MarkPublic();
 }
 
 
 nsCacheEntry::~nsCacheEntry()
 {
     MOZ_COUNT_DTOR(nsCacheEntry);
     
     if (mData)
--- a/netwerk/cache/nsCacheEntry.h
+++ b/netwerk/cache/nsCacheEntry.h
@@ -111,65 +111,61 @@ public:
         eDoomedMask          = 0x00000100,
         eEntryDirtyMask      = 0x00000200,
         eDataDirtyMask       = 0x00000400,
         eMetaDataDirtyMask   = 0x00000800,
         eStreamDataMask      = 0x00001000,
         eActiveMask          = 0x00002000,
         eInitializedMask     = 0x00004000,
         eValidMask           = 0x00008000,
-        eBindingMask         = 0x00010000,
-        ePrivateMask         = 0x00020000
+        eBindingMask         = 0x00010000
     };
     
     void MarkBinding()         { mFlags |=  eBindingMask; }
     void ClearBinding()        { mFlags &= ~eBindingMask; }
     bool IsBinding()         { return (mFlags & eBindingMask) != 0; }
 
     void MarkEntryDirty()      { mFlags |=  eEntryDirtyMask; }
     void MarkEntryClean()      { mFlags &= ~eEntryDirtyMask; }
     void MarkDataDirty()       { mFlags |=  eDataDirtyMask; }
     void MarkDataClean()       { mFlags &= ~eDataDirtyMask; }
     void MarkMetaDataDirty()   { mFlags |=  eMetaDataDirtyMask; }
     void MarkMetaDataClean()   { mFlags &= ~eMetaDataDirtyMask; }
     void MarkStreamData()      { mFlags |=  eStreamDataMask; }
     void MarkValid()           { mFlags |=  eValidMask; }
     void MarkInvalid()         { mFlags &= ~eValidMask; }
-    void MarkPrivate()         { mFlags |=  ePrivateMask; }
-    void MarkPublic()          { mFlags &= ~ePrivateMask; }
     //    void MarkAllowedInMemory() { mFlags |=  eAllowedInMemoryMask; }
     //    void MarkAllowedOnDisk()   { mFlags |=  eAllowedOnDiskMask; }
 
     bool IsDoomed()          { return (mFlags & eDoomedMask) != 0; }
     bool IsEntryDirty()      { return (mFlags & eEntryDirtyMask) != 0; }
     bool IsDataDirty()       { return (mFlags & eDataDirtyMask) != 0; }
     bool IsMetaDataDirty()   { return (mFlags & eMetaDataDirtyMask) != 0; }
     bool IsStreamData()      { return (mFlags & eStreamDataMask) != 0; }
     bool IsActive()          { return (mFlags & eActiveMask) != 0; }
     bool IsInitialized()     { return (mFlags & eInitializedMask) != 0; }
     bool IsValid()           { return (mFlags & eValidMask) != 0; }
     bool IsInvalid()         { return (mFlags & eValidMask) == 0; }
     bool IsInUse()           { return IsBinding() ||
                                         !(PR_CLIST_IS_EMPTY(&mRequestQ) &&
                                           PR_CLIST_IS_EMPTY(&mDescriptorQ)); }
     bool IsNotInUse()        { return !IsInUse(); }
-    bool IsPrivate()         { return (mFlags & ePrivateMask) != 0; }
 
 
     bool IsAllowedInMemory()
     {
         return (StoragePolicy() ==  nsICache::STORE_ANYWHERE) ||
             (StoragePolicy() == nsICache::STORE_IN_MEMORY);
     }
 
     bool IsAllowedOnDisk()
     {
-        return !IsPrivate() && ((StoragePolicy() == nsICache::STORE_ANYWHERE) ||
+        return (StoragePolicy() == nsICache::STORE_ANYWHERE) ||
             (StoragePolicy() == nsICache::STORE_ON_DISK) ||
-            (StoragePolicy() == nsICache::STORE_ON_DISK_AS_FILE));
+            (StoragePolicy() == nsICache::STORE_ON_DISK_AS_FILE);
     }
 
     bool IsAllowedOffline()
     {
         return (StoragePolicy() == nsICache::STORE_OFFLINE);
     }
 
     nsCacheStoragePolicy  StoragePolicy()
--- a/netwerk/cache/nsCacheRequest.h
+++ b/netwerk/cache/nsCacheRequest.h
@@ -41,17 +41,16 @@ private:
           mProfileDir(session->ProfileDir())
     {
         MOZ_COUNT_CTOR(nsCacheRequest);
         PR_INIT_CLIST(this);
         SetAccessRequested(accessRequested);
         SetStoragePolicy(session->StoragePolicy());
         if (session->IsStreamBased())             MarkStreamBased();
         if (session->WillDoomEntriesIfExpired())  MarkDoomEntriesIfExpired();
-        if (session->IsPrivate())                 MarkPrivate();
         if (blockingMode == nsICache::BLOCKING)    MarkBlockingMode();
         MarkWaitingForValidation();
         NS_IF_ADDREF(mListener);
     }
     
     ~nsCacheRequest()
     {
         MOZ_COUNT_DTOR(nsCacheRequest);
@@ -62,17 +61,16 @@ private:
     }
     
     /**
      * Simple Accessors
      */
     enum CacheRequestInfo {
         eStoragePolicyMask         = 0x000000FF,
         eStreamBasedMask           = 0x00000100,
-        ePrivateMask               = 0x00000200,
         eDoomEntriesIfExpiredMask  = 0x00001000,
         eBlockingModeMask          = 0x00010000,
         eWaitingForValidationMask  = 0x00100000,
         eAccessRequestedMask       = 0xFF000000
     };
 
     void SetAccessRequested(nsCacheAccessMode mode)
     {
@@ -101,23 +99,19 @@ private:
     {
         NS_ASSERTION(policy <= 0xFF, "too many bits in nsCacheStoragePolicy");
         mInfo &= ~eStoragePolicyMask;  // clear storage policy bits
         mInfo |= policy;         // or in new bits
     }
 
     nsCacheStoragePolicy StoragePolicy()
     {
-        return (nsCacheStoragePolicy)(mInfo & eStoragePolicyMask);
+        return (nsCacheStoragePolicy)(mInfo & 0xFF);
     }
 
-    void   MarkPrivate() { mInfo |= ePrivateMask; }
-    void   MarkPublic() { mInfo &= ~ePrivateMask; }
-    bool   IsPrivate() { return (mInfo & ePrivateMask) != 0; }
-
     void   MarkWaitingForValidation() { mInfo |=  eWaitingForValidationMask; }
     void   DoneWaitingForValidation() { mInfo &= ~eWaitingForValidationMask; }
     bool WaitingForValidation()
     {
         return (mInfo & eWaitingForValidationMask) != 0;
     }
 
     nsresult
--- a/netwerk/cache/nsCacheService.cpp
+++ b/netwerk/cache/nsCacheService.cpp
@@ -27,16 +27,17 @@
 #include "nsIFile.h"
 #include "nsIOService.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsThreadUtils.h"
 #include "nsProxyRelease.h"
 #include "nsVoidArray.h"
 #include "nsDeleteDir.h"
+#include "nsIPrivateBrowsingService.h"
 #include "nsNetCID.h"
 #include <math.h>  // for log()
 #include "mozilla/Services.h"
 #include "nsITimer.h"
 
 #include "mozilla/FunctionTimer.h"
 
 #include "mozilla/net/NeckoCommon.h"
@@ -74,17 +75,17 @@ using namespace mozilla;
 
 #define SANITIZE_ON_SHUTDOWN_PREF   "privacy.sanitize.sanitizeOnShutdown"
 #define CLEAR_ON_SHUTDOWN_PREF      "privacy.clearOnShutdown.cache"
 
 static const char * observerList[] = { 
     "profile-before-change",
     "profile-do-change",
     NS_XPCOM_SHUTDOWN_OBSERVER_ID,
-    "last-pb-context-exited"
+    NS_PRIVATE_BROWSING_SWITCH_TOPIC
 };
 static const char * prefList[] = { 
     DISK_CACHE_ENABLE_PREF,
     DISK_CACHE_SMART_SIZE_ENABLED_PREF,
     DISK_CACHE_CAPACITY_PREF,
     DISK_CACHE_DIR_PREF,
     DISK_CACHE_MAX_ENTRY_SIZE_PREF,
     DISK_CACHE_USE_OLD_MAX_SMART_SIZE_PREF,
@@ -125,16 +126,17 @@ public:
         , mDiskCacheMaxEntrySize(-1) // -1 means "no limit"
         , mSmartSizeEnabled(false)
         , mUseOldMaxSmartSize(false)
         , mOfflineCacheEnabled(false)
         , mOfflineCacheCapacity(0)
         , mMemoryCacheEnabled(true)
         , mMemoryCacheCapacity(-1)
         , mMemoryCacheMaxEntrySize(-1) // -1 means "no limit"
+        , mInPrivateBrowsing(false)
         , mCacheCompressionLevel(CACHE_COMPRESSION_LEVEL)
         , mSanitizeOnShutdown(false)
         , mClearCacheOnShutdown(false)
     {
     }
 
     virtual ~nsCacheProfilePrefObserver() {}
     
@@ -183,16 +185,18 @@ private:
     bool                    mOfflineCacheEnabled;
     int32_t                 mOfflineCacheCapacity; // in kilobytes
     nsCOMPtr<nsIFile>       mOfflineCacheParentDirectory;
     
     bool                    mMemoryCacheEnabled;
     int32_t                 mMemoryCacheCapacity; // in kilobytes
     int32_t                 mMemoryCacheMaxEntrySize; // in kilobytes
 
+    bool                    mInPrivateBrowsing;
+
     int32_t                 mCacheCompressionLevel;
 
     bool                    mSanitizeOnShutdown;
     bool                    mClearCacheOnShutdown;
 };
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheProfilePrefObserver, nsIObserver)
 
@@ -318,16 +322,22 @@ nsCacheProfilePrefObserver::Install()
     if (!branch) return NS_ERROR_FAILURE;
 
     for (unsigned int i=0; i<ArrayLength(prefList); i++) {
         rv = branch->AddObserver(prefList[i], this, false);
         if (NS_FAILED(rv))
             rv2 = rv;
     }
 
+    // determine the initial status of the private browsing mode
+    nsCOMPtr<nsIPrivateBrowsingService> pbs =
+      do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
+    if (pbs)
+      pbs->GetPrivateBrowsingEnabled(&mInPrivateBrowsing);
+
     // Determine if we have a profile already
     //     Install() is called *after* the profile-after-change notification
     //     when there is only a single profile, or it is specified on the
     //     commandline at startup.
     //     In that case, we detect the presence of a profile by the existence
     //     of the NS_APP_USER_PROFILE_50_DIR directory.
 
     nsCOMPtr<nsIFile> directory;
@@ -410,19 +420,23 @@ nsCacheProfilePrefObserver::Observe(nsIS
         if (NS_FAILED(rv))  
             return rv;
 
         // which preference changed?
         if (!strcmp(DISK_CACHE_ENABLE_PREF, data.get())) {
 
             rv = branch->GetBoolPref(DISK_CACHE_ENABLE_PREF,
                                      &mDiskCacheEnabled);
-            if (NS_FAILED(rv))  
-                return rv;
-            nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
+            if (!mInPrivateBrowsing) {
+                rv = branch->GetBoolPref(DISK_CACHE_ENABLE_PREF,
+                                         &mDiskCacheEnabled);
+                if (NS_FAILED(rv))  
+                    return rv;
+                nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
+            }
 
         } else if (!strcmp(DISK_CACHE_CAPACITY_PREF, data.get())) {
 
             int32_t capacity = 0;
             rv = branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &capacity);
             if (NS_FAILED(rv))  
                 return rv;
             mDiskCacheCapacity = NS_MAX(0, capacity);
@@ -468,20 +482,22 @@ nsCacheProfilePrefObserver::Observe(nsIS
             // XXX notification that the pref change won't take effect until
             // XXX the next time the profile changes (browser launch)
 #endif            
         } else
 
         // which preference changed?
         if (!strcmp(OFFLINE_CACHE_ENABLE_PREF, data.get())) {
 
-            rv = branch->GetBoolPref(OFFLINE_CACHE_ENABLE_PREF,
-                                     &mOfflineCacheEnabled);
-            if (NS_FAILED(rv))  return rv;
-            nsCacheService::SetOfflineCacheEnabled(OfflineCacheEnabled());
+            if (!mInPrivateBrowsing) {
+                rv = branch->GetBoolPref(OFFLINE_CACHE_ENABLE_PREF,
+                                         &mOfflineCacheEnabled);
+                if (NS_FAILED(rv))  return rv;
+                nsCacheService::SetOfflineCacheEnabled(OfflineCacheEnabled());
+            }
 
         } else if (!strcmp(OFFLINE_CACHE_CAPACITY_PREF, data.get())) {
 
             int32_t capacity = 0;
             rv = branch->GetIntPref(OFFLINE_CACHE_CAPACITY_PREF, &capacity);
             if (NS_FAILED(rv))  return rv;
             mOfflineCacheCapacity = NS_MAX(0, capacity);
             nsCacheService::SetOfflineCacheCapacity(mOfflineCacheCapacity);
@@ -531,18 +547,46 @@ nsCacheProfilePrefObserver::Observe(nsIS
             nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
         } else if (!strcmp(CLEAR_ON_SHUTDOWN_PREF, data.get())) {
             rv = branch->GetBoolPref(CLEAR_ON_SHUTDOWN_PREF,
                                      &mClearCacheOnShutdown);
             if (NS_FAILED(rv))
                 return rv;
             nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
         }
-    } else if (!strcmp("last-pb-context-exited", topic)) {
-        nsCacheService::LeavePrivateBrowsing();
+    } else if (!strcmp(NS_PRIVATE_BROWSING_SWITCH_TOPIC, topic)) {
+        if (!strcmp(NS_PRIVATE_BROWSING_ENTER, data.get())) {
+            mInPrivateBrowsing = true;
+
+            nsCacheService::OnEnterExitPrivateBrowsing();
+
+            mDiskCacheEnabled = false;
+            nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
+
+            mOfflineCacheEnabled = false;
+            nsCacheService::SetOfflineCacheEnabled(OfflineCacheEnabled());
+        } else if (!strcmp(NS_PRIVATE_BROWSING_LEAVE, data.get())) {
+            mInPrivateBrowsing = false;
+
+            nsCacheService::OnEnterExitPrivateBrowsing();
+
+            nsCOMPtr<nsIPrefBranch> branch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+            if (NS_FAILED(rv))  
+                return rv;
+
+            mDiskCacheEnabled = true; // by default enabled
+            (void) branch->GetBoolPref(DISK_CACHE_ENABLE_PREF,
+                                       &mDiskCacheEnabled);
+            nsCacheService::SetDiskCacheEnabled(DiskCacheEnabled());
+
+            mOfflineCacheEnabled = true; // by default enabled
+            (void) branch->GetBoolPref(OFFLINE_CACHE_ENABLE_PREF,
+                                       &mOfflineCacheEnabled);
+            nsCacheService::SetOfflineCacheEnabled(OfflineCacheEnabled());
+        }
     }
 
     return NS_OK;
 }
 
 // Returns default ("smart") size (in KB) of cache, given available disk space
 // (also in KB)
 static uint32_t
@@ -665,18 +709,20 @@ nsCacheProfilePrefObserver::PermittedToS
 
 
 nsresult
 nsCacheProfilePrefObserver::ReadPrefs(nsIPrefBranch* branch)
 {
     nsresult rv = NS_OK;
 
     // read disk cache device prefs
-    mDiskCacheEnabled = true;  // presume disk cache is enabled
-    (void) branch->GetBoolPref(DISK_CACHE_ENABLE_PREF, &mDiskCacheEnabled);
+    if (!mInPrivateBrowsing) {
+        mDiskCacheEnabled = true;  // presume disk cache is enabled
+        (void) branch->GetBoolPref(DISK_CACHE_ENABLE_PREF, &mDiskCacheEnabled);
+    }
 
     mDiskCacheCapacity = DISK_CACHE_CAPACITY;
     (void)branch->GetIntPref(DISK_CACHE_CAPACITY_PREF, &mDiskCacheCapacity);
     mDiskCacheCapacity = NS_MAX(0, mDiskCacheCapacity);
 
     (void) branch->GetIntPref(DISK_CACHE_MAX_ENTRY_SIZE_PREF,
                               &mDiskCacheMaxEntrySize);
     mDiskCacheMaxEntrySize = NS_MAX(-1, mDiskCacheMaxEntrySize);
@@ -747,19 +793,21 @@ nsCacheProfilePrefObserver::ReadPrefs(ns
             rv = branch->SetBoolPref(DISK_CACHE_SMART_SIZE_FIRST_RUN_PREF, 
                                      false);
             if (NS_FAILED(rv)) 
                 NS_WARNING("Failed setting first_run pref in ReadPrefs.");
         }
     }
 
     // read offline cache device prefs
-    mOfflineCacheEnabled = true;  // presume offline cache is enabled
-    (void) branch->GetBoolPref(OFFLINE_CACHE_ENABLE_PREF,
-                              &mOfflineCacheEnabled);
+    if (!mInPrivateBrowsing) {
+        mOfflineCacheEnabled = true;  // presume offline cache is enabled
+        (void) branch->GetBoolPref(OFFLINE_CACHE_ENABLE_PREF,
+                                   &mOfflineCacheEnabled);
+    }
 
     mOfflineCacheCapacity = OFFLINE_CACHE_CAPACITY;
     (void)branch->GetIntPref(OFFLINE_CACHE_CAPACITY_PREF,
                              &mOfflineCacheCapacity);
     mOfflineCacheCapacity = NS_MAX(0, mOfflineCacheCapacity);
 
     (void) branch->GetComplexValue(OFFLINE_CACHE_DIR_PREF,     // ignore error
                                    NS_GET_IID(nsIFile),
@@ -2103,19 +2151,16 @@ nsCacheService::ActivateEntry(nsCacheReq
             goto error;
         }
 
         entry = new nsCacheEntry(request->mKey,
                                  request->IsStreamBased(),
                                  request->StoragePolicy());
         if (!entry)
             return NS_ERROR_OUT_OF_MEMORY;
-
-        if (request->IsPrivate())
-            entry->MarkPrivate();
         
         entry->Fetched();
         ++mTotalEntries;
 
         // XXX  we could perform an early bind in some cases based on storage policy
     }
 
     if (!entry->IsActive()) {
@@ -2324,17 +2369,17 @@ nsCacheService::OnProfileShutdown(bool c
     if (!gService->mInitialized) {
         // The cache service has been shut down, but someone is still holding
         // a reference to it. Ignore this call.
         return;
     }
     nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHESERVICE_ONPROFILESHUTDOWN));
     gService->mClearingEntries = true;
 
-    gService->DoomActiveEntries(nullptr);
+    gService->DoomActiveEntries();
     gService->ClearDoomList();
 
     // Make sure to wait for any pending cache-operations before
     // proceeding with destructive actions (bug #620660)
     (void) SyncWithCacheIOThread();
 
     if (gService->mDiskDevice && gService->mEnableDiskDevice) {
         if (cleanse)
@@ -2895,50 +2940,41 @@ nsCacheService::DeactivateAndClearEntry(
     entry->DetachDescriptors();
     
     entry->MarkInactive();  // so we don't call Remove() while we're enumerating
     gService->DeactivateEntry(entry);
     
     return PL_DHASH_REMOVE; // and continue enumerating
 }
 
-struct ActiveEntryArgs
-{
-    nsTArray<nsCacheEntry*>* mActiveArray;
-    nsCacheService::DoomCheckFn mCheckFn;
-};
-
 void
-nsCacheService::DoomActiveEntries(DoomCheckFn check)
+nsCacheService::DoomActiveEntries()
 {
     nsAutoTArray<nsCacheEntry*, 8> array;
-    ActiveEntryArgs args = { &array, check };
-
-    mActiveEntries.VisitEntries(RemoveActiveEntry, &args);
+
+    mActiveEntries.VisitEntries(RemoveActiveEntry, &array);
 
     uint32_t count = array.Length();
     for (uint32_t i=0; i < count; ++i)
         DoomEntry_Internal(array[i], true);
 }
 
+
 PLDHashOperator
 nsCacheService::RemoveActiveEntry(PLDHashTable *    table,
                                   PLDHashEntryHdr * hdr,
                                   uint32_t          number,
                                   void *            arg)
 {
     nsCacheEntry * entry = ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry;
     NS_ASSERTION(entry, "### active entry = nullptr!");
 
-    ActiveEntryArgs* args = static_cast<ActiveEntryArgs*>(arg);
-    if (args->mCheckFn && !args->mCheckFn(entry))
-        return PL_DHASH_NEXT;
-
-    NS_ASSERTION(args->mActiveArray, "### array = nullptr!");
-    args->mActiveArray->AppendElement(entry);
+    nsTArray<nsCacheEntry*> * array = (nsTArray<nsCacheEntry*> *) arg;
+    NS_ASSERTION(array, "### array = nsnull!");
+    array->AppendElement(entry);
 
     // entry is being removed from the active entry list
     entry->MarkInactive();
     return PL_DHASH_REMOVE; // and continue enumerating
 }
 
 
 #if defined(PR_LOGGING)
@@ -2958,16 +2994,30 @@ nsCacheService::LogCacheStatistics()
     CACHE_LOG_ALWAYS(("\n"));
     CACHE_LOG_ALWAYS(("    Deactivate Failures         = %d\n",
                       mDeactivateFailures));
     CACHE_LOG_ALWAYS(("    Deactivated Unbound Entries = %d\n",
                       mDeactivatedUnboundEntries));
 }
 #endif
 
+void
+nsCacheService::OnEnterExitPrivateBrowsing()
+{
+    if (!gService)  return;
+    nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHESERVICE_LEAVEPRIVATEBROWSING));
+
+    gService->DoomActiveEntries();
+
+    if (gService->mMemoryDevice) {
+        // clear memory cache
+        gService->mMemoryDevice->EvictEntries(nullptr);
+    }
+}
+
 nsresult
 nsCacheService::SetDiskSmartSize()
 {
     nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHESERVICE_SETDISKSMARTSIZE));
 
     if (!gService) return NS_ERROR_NOT_AVAILABLE;
 
     return gService->SetDiskSmartSize_Locked();
@@ -2995,27 +3045,8 @@ nsCacheService::SetDiskSmartSize_Locked(
                                     mObserver->UseOldMaxSmartSize());
         DispatchToCacheIOThread(event);
     } else {
         return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
-
-static bool
-IsEntryPrivate(nsCacheEntry* entry)
-{
-    return entry->IsPrivate();
-}
-
-void
-nsCacheService::LeavePrivateBrowsing()
-{
-    nsCacheServiceAutoLock lock(LOCK_TELEM(NSCACHESERVICE_LEAVEPRIVATEBROWSING));
-
-    gService->DoomActiveEntries(IsEntryPrivate);
-
-    if (gService->mMemoryDevice) {
-        // clear memory cache
-        gService->mMemoryDevice->EvictPrivateEntries();
-    }
-}
--- a/netwerk/cache/nsCacheService.h
+++ b/netwerk/cache/nsCacheService.h
@@ -163,30 +163,29 @@ public:
     static void      SetOfflineCacheEnabled(bool    enabled);
     // Sets the offline cache capacity (in kilobytes)
     static void      SetOfflineCacheCapacity(int32_t  capacity);
 
     static void      SetMemoryCache();
 
     static void      SetCacheCompressionLevel(int32_t level);
 
+    static void      OnEnterExitPrivateBrowsing();
+
     // Starts smart cache size computation if disk device is available
     static nsresult  SetDiskSmartSize();
 
     nsresult         Init();
     void             Shutdown();
 
     static void      AssertOwnsLock()
     { gService->mLock.AssertCurrentThreadOwns(); }
 
-    static void      LeavePrivateBrowsing();
     bool             IsDoomListEmpty();
 
-    typedef bool (*DoomCheckFn)(nsCacheEntry* entry);
-
 private:
     friend class nsCacheServiceAutoLock;
     friend class nsOfflineCacheDevice;
     friend class nsProcessRequestEvent;
     friend class nsSetSmartSizeEvent;
     friend class nsBlockOnCacheThreadEvent;
     friend class nsSetDiskSmartSizeCallback;
     friend class nsDoomEvent;
@@ -244,17 +243,17 @@ private:
                                     bool                       calledFromOpenCacheEntry,
                                     nsICacheEntryDescriptor ** result);
 
     nsresult         ProcessPendingRequests(nsCacheEntry * entry);
 
     void             ClearPendingRequests(nsCacheEntry * entry);
     void             ClearDoomList(void);
     void             ClearActiveEntries(void);
-    void             DoomActiveEntries(DoomCheckFn check);
+    void             DoomActiveEntries(void);
 
     static
     PLDHashOperator  DeactivateAndClearEntry(PLDHashTable *    table,
                                              PLDHashEntryHdr * hdr,
                                              uint32_t          number,
                                              void *            arg);
     static
     PLDHashOperator  RemoveActiveEntry(PLDHashTable *    table,
--- a/netwerk/cache/nsCacheSession.cpp
+++ b/netwerk/cache/nsCacheSession.cpp
@@ -16,18 +16,16 @@ nsCacheSession::nsCacheSession(const cha
     : mClientID(clientID),
       mInfo(0)
 {
   SetStoragePolicy(storagePolicy);
 
   if (streamBased) MarkStreamBased();
   else SetStoragePolicy(nsICache::STORE_IN_MEMORY);
 
-  MarkPublic();
-
   MarkDoomEntriesIfExpired();
 }
 
 nsCacheSession::~nsCacheSession()
 {
   /* destructor code */
     // notify service we are going away?
 }
@@ -120,23 +118,8 @@ NS_IMETHODIMP nsCacheSession::IsStorageE
     return nsCacheService::IsStorageEnabledForPolicy(StoragePolicy(), result);
 }
 
 NS_IMETHODIMP nsCacheSession::DoomEntry(const nsACString &key,
                                         nsICacheListener *listener)
 {
     return nsCacheService::DoomEntry(this, key, listener);
 }
-
-NS_IMETHODIMP nsCacheSession::GetIsPrivate(bool* aPrivate)
-{
-    *aPrivate = IsPrivate();
-    return NS_OK;
-}
-
-NS_IMETHODIMP nsCacheSession::SetIsPrivate(bool aPrivate)
-{
-    if (aPrivate)
-        MarkPrivate();
-    else
-        MarkPublic();
-    return NS_OK;
-}
--- a/netwerk/cache/nsCacheSession.h
+++ b/netwerk/cache/nsCacheSession.h
@@ -23,31 +23,27 @@ public:
     nsCacheSession(const char * clientID, nsCacheStoragePolicy storagePolicy, bool streamBased);
     virtual ~nsCacheSession();
     
     nsCString *           ClientID()      { return &mClientID; }
 
     enum SessionInfo {
         eStoragePolicyMask        = 0x000000FF,
         eStreamBasedMask          = 0x00000100,
-        eDoomEntriesIfExpiredMask = 0x00001000,
-        ePrivateMask              = 0x00010000
+        eDoomEntriesIfExpiredMask = 0x00001000
     };
 
     void   MarkStreamBased()  { mInfo |=  eStreamBasedMask; }
     void   ClearStreamBased() { mInfo &= ~eStreamBasedMask; }
     bool IsStreamBased()    { return (mInfo & eStreamBasedMask) != 0; }
 
     void   MarkDoomEntriesIfExpired()  { mInfo |=  eDoomEntriesIfExpiredMask; }
     void   ClearDoomEntriesIfExpired() { mInfo &= ~eDoomEntriesIfExpiredMask; }
     bool WillDoomEntriesIfExpired()  { return (0 != (mInfo & eDoomEntriesIfExpiredMask)); }
 
-    void   MarkPrivate() { mInfo |= ePrivateMask; }
-    void   MarkPublic() { mInfo &= ~ePrivateMask; }
-    bool IsPrivate() { return (mInfo & ePrivateMask) != 0; }
     nsCacheStoragePolicy  StoragePolicy()
     {
         return (nsCacheStoragePolicy)(mInfo & eStoragePolicyMask);
     }
 
     void SetStoragePolicy(nsCacheStoragePolicy policy)
     {
         NS_ASSERTION(policy <= 0xFF, "too many bits in nsCacheStoragePolicy");
--- a/netwerk/cache/nsICacheSession.idl
+++ b/netwerk/cache/nsICacheSession.idl
@@ -73,15 +73,9 @@ interface nsICacheSession : nsISupports
     boolean isStorageEnabled();
 
     /**
      * Asynchronously doom an entry specified by the key. Listener will be
      * notified about the status of the operation. Null may be passed if caller
      * doesn't care about the result.
      */
     void doomEntry(in ACString key, in nsICacheListener listener);
-
-    /**
-     * Private entries will be doomed when the last private browsing session
-     * finishes.
-     */
-    attribute boolean isPrivate;
 };
--- a/netwerk/cache/nsMemoryCacheDevice.cpp
+++ b/netwerk/cache/nsMemoryCacheDevice.cpp
@@ -437,78 +437,47 @@ nsMemoryCacheDevice::Visit(nsICacheVisit
 
             entry = (nsCacheEntry *)PR_NEXT_LINK(entry);
         }
     }
     return NS_OK;
 }
 
 
-static bool
-IsEntryPrivate(nsCacheEntry* entry, void* args)
-{
-    return entry->IsPrivate();
-}
-
-struct ClientIDArgs {
-    const char* clientID;
-    uint32_t prefixLength;
-};
-
-static bool
-EntryMatchesClientID(nsCacheEntry* entry, void* args)
-{
-    const char * clientID = static_cast<ClientIDArgs*>(args)->clientID;
-    uint32_t prefixLength = static_cast<ClientIDArgs*>(args)->prefixLength;
-    const char * key = entry->Key()->get();
-    return !clientID || nsCRT::strncmp(clientID, key, prefixLength) == 0;
-}
-
 nsresult
-nsMemoryCacheDevice::DoEvictEntries(bool (*matchFn)(nsCacheEntry* entry, void* args), void* args)
+nsMemoryCacheDevice::EvictEntries(const char * clientID)
 {
     nsCacheEntry * entry;
+    uint32_t prefixLength = (clientID ? strlen(clientID) : 0);
 
     for (int i = kQueueCount - 1; i >= 0; --i) {
         PRCList * elem = PR_LIST_HEAD(&mEvictionList[i]);
         while (elem != &mEvictionList[i]) {
             entry = (nsCacheEntry *)elem;
             elem = PR_NEXT_LINK(elem);
 
-            if (!matchFn(entry, args))
+            const char * key = entry->Key()->get();
+            if (clientID && nsCRT::strncmp(clientID, key, prefixLength) != 0)
                 continue;
             
             if (entry->IsInUse()) {
                 nsresult rv = nsCacheService::DoomEntry(entry);
                 if (NS_FAILED(rv)) {
-                    CACHE_LOG_WARNING(("memCache->DoEvictEntries() aborted: rv =%x", rv));
+                    CACHE_LOG_WARNING(("memCache->EvictEntries() aborted: rv =%x", rv));
                     return rv;
                 }
             } else {
                 EvictEntry(entry, DELETE_ENTRY);
             }
         }
     }
 
     return NS_OK;
 }
 
-nsresult
-nsMemoryCacheDevice::EvictEntries(const char * clientID)
-{
-    ClientIDArgs args = {clientID, clientID ? uint32_t(strlen(clientID)) : 0};
-    return DoEvictEntries(&EntryMatchesClientID, &args);
-}
-
-nsresult
-nsMemoryCacheDevice::EvictPrivateEntries()
-{
-    return DoEvictEntries(&IsEntryPrivate, NULL);
-}
-
 
 // WARNING: SetCapacity can get called before Init()
 void
 nsMemoryCacheDevice::SetCapacity(int32_t  capacity)
 {
     int32_t hardLimit = capacity * 1024;  // convert k into bytes
     int32_t softLimit = (hardLimit * 9) / 10;
     AdjustMemoryLimits(softLimit, hardLimit);
--- a/netwerk/cache/nsMemoryCacheDevice.h
+++ b/netwerk/cache/nsMemoryCacheDevice.h
@@ -46,17 +46,16 @@ public:
     virtual nsresult GetFileForEntry( nsCacheEntry *    entry,
                                       nsIFile **        result );
 
     virtual nsresult OnDataSizeChange( nsCacheEntry * entry, int32_t deltaSize );
 
     virtual nsresult Visit( nsICacheVisitor * visitor );
 
     virtual nsresult EvictEntries(const char * clientID);
-    nsresult EvictPrivateEntries();
     
     void             SetCapacity(int32_t  capacity);
     void             SetMaxEntrySize(int32_t  maxSizeInKilobytes);
 
     bool             EntryIsTooBig(int64_t entrySize);
 
     size_t           TotalSize();
 
@@ -65,19 +64,16 @@ private:
     enum      { DELETE_ENTRY        = true,
                 DO_NOT_DELETE_ENTRY = false };
 
     void      AdjustMemoryLimits( int32_t  softLimit, int32_t  hardLimit);
     void      EvictEntry( nsCacheEntry * entry , bool deleteEntry);
     void      EvictEntriesIfNecessary();
     int       EvictionList(nsCacheEntry * entry, int32_t  deltaSize);
 
-    typedef bool (*EvictionMatcherFn)(nsCacheEntry* entry, void* args);
-    nsresult DoEvictEntries(EvictionMatcherFn matchFn, void* args);
-
 #ifdef DEBUG
     void      CheckEntryCount();
 #endif
     /*
      *  Data members
      */
     enum {
         kQueueCount = 24   // entries > 2^23 (8Mb) start in last queue
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -2216,29 +2216,24 @@ nsFtpState::CheckCache()
     // In some cases, we don't want to use the cache:
     if (mChannel->UploadStream() || mChannel->ResumeRequested())
         return false;
 
     nsCOMPtr<nsICacheService> cache = do_GetService(NS_CACHESERVICE_CONTRACTID);
     if (!cache)
         return false;
 
-    bool isPrivate = NS_UsePrivateBrowsing(mChannel);
-    const char* sessionName = isPrivate ? "FTP-private" : "FTP";
-    nsCacheStoragePolicy policy =
-        isPrivate ? nsICache::STORE_IN_MEMORY : nsICache::STORE_ANYWHERE;
     nsCOMPtr<nsICacheSession> session;
-    cache->CreateSession(sessionName,
-                         policy,
+    cache->CreateSession("FTP",
+                         nsICache::STORE_ANYWHERE,
                          nsICache::STREAM_BASED,
                          getter_AddRefs(session));
     if (!session)
         return false;
     session->SetDoomEntriesIfExpired(false);
-    session->SetIsPrivate(isPrivate);
 
     // Set cache access requested:
     nsCacheAccessMode accessReq;
     if (NS_IsOffline()) {
         accessReq = nsICache::ACCESS_READ; // can only read
     } else if (mChannel->HasLoadFlag(nsIRequest::LOAD_BYPASS_CACHE)) {
         accessReq = nsICache::ACCESS_WRITE; // replace cache entry
     } else {
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -12,17 +12,16 @@
 #include "nsNetUtil.h"
 
 #include "nsICachingChannel.h"
 #include "nsISeekableStream.h"
 #include "nsITimedChannel.h"
 #include "nsIEncodedChannel.h"
 #include "nsIResumableChannel.h"
 #include "nsIApplicationCacheChannel.h"
-#include "nsILoadContext.h"
 #include "nsEscape.h"
 #include "nsStreamListenerWrapper.h"
 
 #include "prnetdb.h"
 
 namespace mozilla {
 namespace net {
 
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -74,24 +74,21 @@ AccumulateCacheHitTelemetry(mozilla::Tel
     mozilla::Telemetry::Accumulate(
             mozilla::Telemetry::HTTP_CACHE_DISPOSITION_2, hitOrMiss);
     if (deviceHistogram != UNKNOWN_DEVICE) {
         mozilla::Telemetry::Accumulate(deviceHistogram, hitOrMiss);
     }
 }
 
 const char *
-GetCacheSessionNameForStoragePolicy(nsCacheStoragePolicy storagePolicy,
-                                    bool isPrivate)
+GetCacheSessionNameForStoragePolicy(nsCacheStoragePolicy storagePolicy)
 {
-    MOZ_ASSERT(!isPrivate || storagePolicy == nsICache::STORE_IN_MEMORY);
-
     switch (storagePolicy) {
     case nsICache::STORE_IN_MEMORY:
-        return isPrivate ? "HTTP-memory-only-PB" : "HTTP-memory-only";
+        return "HTTP-memory-only";
     case nsICache::STORE_OFFLINE:
         return "HTTP-offline";
     default:
         return "HTTP";
     }
 }
 
 // Computes and returns a SHA1 hash of the input buffer. The input buffer
@@ -185,32 +182,30 @@ AutoRedirectVetoNotifier::ReportRedirect
 }
 
 class HttpCacheQuery : public nsRunnable, public nsICacheListener
 {
 public:
     HttpCacheQuery(nsHttpChannel * channel,
                    const nsACString & clientID,
                    nsCacheStoragePolicy storagePolicy,
-                   bool usingPrivateBrowsing,
                    const nsACString & cacheKey,
                    nsCacheAccessMode accessToRequest,
                    bool noWait,
                    bool usingSSL,
                    bool loadedFromApplicationCache)
         // in
         : mChannel(channel)
         , mHasQueryString(HasQueryString(channel->mRequestHead.Method(),
                                          channel->mURI))
         , mLoadFlags(channel->mLoadFlags)
         , mCacheForOfflineUse(!!channel->mApplicationCacheForWrite)
         , mFallbackChannel(channel->mFallbackChannel)
         , mClientID(clientID)
         , mStoragePolicy(storagePolicy)
-        , mUsingPrivateBrowsing(usingPrivateBrowsing)
         , mCacheKey(cacheKey)
         , mAccessToRequest(accessToRequest)
         , mNoWait(noWait)
         , mUsingSSL(usingSSL)
         , mLoadedFromApplicationCache(loadedFromApplicationCache)
         // internal
         , mCacheAccess(0)
         , mStatus(NS_ERROR_NOT_INITIALIZED)
@@ -255,17 +250,16 @@ private:
 
     nsCOMPtr<nsICacheListener> mChannel;
     const bool mHasQueryString;
     const uint32_t mLoadFlags;
     const bool mCacheForOfflineUse;
     const bool mFallbackChannel;
     const InfallableCopyCString mClientID;
     const nsCacheStoragePolicy mStoragePolicy;
-    const bool mUsingPrivateBrowsing;
     const InfallableCopyCString mCacheKey;
     const nsCacheAccessMode mAccessToRequest;
     const bool mNoWait;
     const bool mUsingSSL;
     const bool mLoadedFromApplicationCache;
 
     // Used only internally 
     nsCOMPtr<nsIEventTarget> mCacheThread;
@@ -539,17 +533,16 @@ nsHttpChannel::SpeculativeConnect()
     
     nsCOMPtr<nsIInterfaceRequestor> callbacks;
     NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
                                            getter_AddRefs(callbacks));
     if (!callbacks)
         return;
 
     mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
-    mConnectionInfo->SetPrivate(mPrivateBrowsing);
     gHttpHandler->SpeculativeConnect(mConnectionInfo,
                                      callbacks, NS_GetCurrentThread());
 }
 
 void
 nsHttpChannel::DoNotifyListenerCleanup()
 {
     // We don't need this info anymore
@@ -834,17 +827,16 @@ nsHttpChannel::SetupTransaction()
     // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
     if (mLoadFlags & LOAD_ANONYMOUS)
         mCaps |= NS_HTTP_LOAD_ANONYMOUS;
 
     if (mTimingEnabled)
         mCaps |= NS_HTTP_TIMING_ENABLED;
 
     mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
-    mConnectionInfo->SetPrivate(mPrivateBrowsing);
 
     if (mUpgradeProtocolCallback) {
         mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, false);
         mRequestHead.SetHeader(nsHttp::Connection,
                                nsDependentCString(nsHttp::Upgrade.get()),
                                true);
         mCaps |=  NS_HTTP_STICKY_CONNECTION;
         mCaps &= ~NS_HTTP_ALLOW_PIPELINING;
@@ -2435,17 +2427,17 @@ nsHttpChannel::OpenCacheEntry(bool using
         nsCAutoString appCacheClientID;
         rv = mApplicationCache->GetClientID(appCacheClientID);
         if (NS_SUCCEEDED(rv)) {
             // We open with ACCESS_READ only, because we don't want to overwrite
             // the offline cache entry non-atomically. ACCESS_READ will prevent
             // us from writing to the offline cache as a normal cache entry.
             mCacheQuery = new HttpCacheQuery(
                                 this, appCacheClientID,
-                                nsICache::STORE_OFFLINE, mPrivateBrowsing,
+                                nsICache::STORE_OFFLINE,
                                 cacheKey, nsICache::ACCESS_READ,
                                 mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY,
                                 usingSSL, true);
 
             mOnCacheEntryAvailableCallback =
                 &nsHttpChannel::OnOfflineCacheEntryAvailable;
 
             rv = mCacheQuery->Dispatch();
@@ -2538,29 +2530,29 @@ nsresult
 nsHttpChannel::OpenNormalCacheEntry(bool usingSSL)
 {
     NS_ASSERTION(!mCacheEntry, "We have already mCacheEntry");
 
     nsresult rv;
 
     nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
     nsDependentCString clientID(
-        GetCacheSessionNameForStoragePolicy(storagePolicy, mPrivateBrowsing));
+        GetCacheSessionNameForStoragePolicy(storagePolicy));
 
     nsCAutoString cacheKey;
     GenerateCacheKey(mPostID, cacheKey);
 
     nsCacheAccessMode accessRequested;
     rv = DetermineCacheAccess(&accessRequested);
     if (NS_FAILED(rv))
         return rv;
  
     mCacheQuery = new HttpCacheQuery(
                                 this, clientID, storagePolicy,
-                                mPrivateBrowsing, cacheKey, accessRequested,
+                                cacheKey, accessRequested,
                                 mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY,
                                 usingSSL, false);
 
     mOnCacheEntryAvailableCallback =
         &nsHttpChannel::OnNormalCacheEntryAvailable;
 
     rv = mCacheQuery->Dispatch();
     if (NS_SUCCEEDED(rv))
@@ -2843,19 +2835,16 @@ HttpCacheQuery::Run()
             do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
         nsCOMPtr<nsICacheSession> session;
         if (NS_SUCCEEDED(rv)) {
             rv = serv->CreateSession(mClientID.get(), mStoragePolicy,
                                      nsICache::STREAM_BASED,
                                      getter_AddRefs(session));
         }
         if (NS_SUCCEEDED(rv)) {
-            rv = session->SetIsPrivate(mUsingPrivateBrowsing);
-        }
-        if (NS_SUCCEEDED(rv)) {
             rv = session->SetDoomEntriesIfExpired(false);
         }
         if (NS_SUCCEEDED(rv)) {
             // AsyncOpenCacheEntry isn't really async when its called on the
             // cache service thread.
             rv = session->AsyncOpenCacheEntry(mCacheKey, mAccessToRequest, this,
                                               mNoWait);
         }
@@ -5847,48 +5836,43 @@ nsHttpChannel::DoInvalidateCacheEntry(co
     // Following comments 24,32 and 33 in bug #327765, we only care about
     // the cache in the protocol-handler, not the application cache.
     // The logic below deviates from the original logic in OpenCacheEntry on
     // one point by using only READ_ONLY access-policy. I think this is safe.
 
     // First, find session holding the cache-entry - use current storage-policy
     nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
     const char * clientID =
-        GetCacheSessionNameForStoragePolicy(storagePolicy, mPrivateBrowsing);
+        GetCacheSessionNameForStoragePolicy(storagePolicy);
 
     LOG(("DoInvalidateCacheEntry [channel=%p session=%s policy=%d key=%s]",
          this, clientID, int(storagePolicy), key.get()));
 
     nsresult rv;
     nsCOMPtr<nsICacheService> serv =
         do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
     nsCOMPtr<nsICacheSession> session;
     if (NS_SUCCEEDED(rv)) {
         rv = serv->CreateSession(clientID, storagePolicy,  
                                  nsICache::STREAM_BASED,
                                  getter_AddRefs(session));
     }
     if (NS_SUCCEEDED(rv)) {
-        rv = session->SetIsPrivate(mPrivateBrowsing);
-    }
-    if (NS_SUCCEEDED(rv)) {
         rv = session->DoomEntry(key, nullptr);
     }
 
     LOG(("DoInvalidateCacheEntry [channel=%p session=%s policy=%d key=%s rv=%d]",
          this, clientID, int(storagePolicy), key.get(), int(rv)));
 }
 
 nsCacheStoragePolicy
 nsHttpChannel::DetermineStoragePolicy()
 {
     nsCacheStoragePolicy policy = nsICache::STORE_ANYWHERE;
-    if (mPrivateBrowsing)
-        policy = nsICache::STORE_IN_MEMORY;
-    else if (mLoadFlags & INHIBIT_PERSISTENT_CACHING)
+    if (mLoadFlags & INHIBIT_PERSISTENT_CACHING)
         policy = nsICache::STORE_IN_MEMORY;
 
     return policy;
 }
 
 nsresult
 nsHttpChannel::DetermineCacheAccess(nsCacheAccessMode *_retval)
 {
@@ -5909,12 +5893,11 @@ nsHttpChannel::DetermineCacheAccess(nsCa
 
     return NS_OK;
 }
 
 void
 nsHttpChannel::AsyncOnExamineCachedResponse()
 {
     gHttpHandler->OnExamineCachedResponse(this);
-
 }
 
 } } // namespace mozilla::net
--- a/netwerk/protocol/http/nsHttpConnectionInfo.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp
@@ -28,17 +28,17 @@ nsHttpConnectionInfo::SetOriginServer(co
         keyHost = ProxyHost();
         keyPort = ProxyPort();
     }
     else {
         keyHost = Host();
         keyPort = Port();
     }
 
-    mHashKey.AssignLiteral("....");
+    mHashKey.AssignLiteral("...");
     mHashKey.Append(keyHost);
     mHashKey.Append(':');
     mHashKey.AppendInt(keyPort);
 
     if (mUsingHttpProxy)
         mHashKey.SetCharAt('P', 0);
     if (mUsingSSL)
         mHashKey.SetCharAt('S', 1);
@@ -53,15 +53,14 @@ nsHttpConnectionInfo::SetOriginServer(co
     }
 }
 
 nsHttpConnectionInfo*
 nsHttpConnectionInfo::Clone() const
 {
     nsHttpConnectionInfo* clone = new nsHttpConnectionInfo(mHost, mPort, mProxyInfo, mUsingSSL);
 
-    // Make sure the anonymous and private flags are transferred!
-    clone->SetAnonymous(GetAnonymous());
-    clone->SetPrivate(GetPrivate());
+    // Make sure the anonymous flag is transferred!
+    clone->SetAnonymous(mHashKey.CharAt(2) == 'A');
 
     return clone;
 }
 
--- a/netwerk/protocol/http/nsHttpConnectionInfo.h
+++ b/netwerk/protocol/http/nsHttpConnectionInfo.h
@@ -100,18 +100,16 @@ public:
     nsProxyInfo  *ProxyInfo()            { return mProxyInfo; }
     bool          UsingHttpProxy() const { return mUsingHttpProxy; }
     bool          UsingSSL() const       { return mUsingSSL; }
     bool          UsingConnect() const   { return mUsingConnect; }
     int32_t       DefaultPort() const    { return mUsingSSL ? NS_HTTPS_DEFAULT_PORT : NS_HTTP_DEFAULT_PORT; }
     void          SetAnonymous(bool anon)         
                                          { mHashKey.SetCharAt(anon ? 'A' : '.', 2); }
     bool          GetAnonymous() const   { return mHashKey.CharAt(2) == 'A'; }
-    void          SetPrivate(bool priv)  { mHashKey.SetCharAt(priv ? 'P' : '.', 3); }
-    bool          GetPrivate() const     { return mHashKey.CharAt(3) == 'P'; }
 
     const nsCString &GetHost() { return mHost; }
 
 private:
     nsrefcnt               mRef;
     nsCString              mHashKey;
     nsCString              mHost;
     int32_t                mPort;
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -1051,37 +1051,25 @@ nsHttpConnectionMgr::ReportFailedToProce
         rv = uri->SchemeIs("http", &isHttp);
     if (NS_SUCCEEDED(rv))
         rv = uri->GetAsciiHost(host);
     if (NS_SUCCEEDED(rv))
         rv = uri->GetPort(&port);
     if (NS_FAILED(rv) || !isHttp || host.IsEmpty())
         return;
 
-    // report the event for all the permutations of anonymous and
-    // private versions of this host
+    // report the event for both the anonymous and non-anonymous
+    // versions of this host
     nsRefPtr<nsHttpConnectionInfo> ci =
         new nsHttpConnectionInfo(host, port, nullptr, usingSSL);
     ci->SetAnonymous(false);
-    ci->SetPrivate(false);
     PipelineFeedbackInfo(ci, RedCorruptedContent, nullptr, 0);
 
-    ci = ci->Clone();
-    ci->SetAnonymous(false);
-    ci->SetPrivate(true);
-    PipelineFeedbackInfo(ci, RedCorruptedContent, nullptr, 0);
-
-    ci = ci->Clone();
+    ci = new nsHttpConnectionInfo(host, port, nullptr, usingSSL);
     ci->SetAnonymous(true);
-    ci->SetPrivate(false);
-    PipelineFeedbackInfo(ci, RedCorruptedContent, nullptr, 0);
-
-    ci = ci->Clone();
-    ci->SetAnonymous(true);
-    ci->SetPrivate(true);
     PipelineFeedbackInfo(ci, RedCorruptedContent, nullptr, 0);
 }
 
 // we're at the active connection limit if any one of the following conditions is true:
 //  (1) at max-connections
 //  (2) keep-alive enabled and at max-persistent-connections-per-server/proxy
 //  (3) keep-alive disabled and at max-connections-per-server
 bool
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -149,16 +149,17 @@ nsHttpHandler::nsHttpHandler()
     , mPipelineRescheduleOnTimeout(true)
     , mPipelineRescheduleTimeout(PR_MillisecondsToInterval(1500))
     , mPipelineReadTimeout(PR_MillisecondsToInterval(30000))
     , mRedirectionLimit(10)
     , mPhishyUserPassLength(1)
     , mQoSBits(0x00)
     , mPipeliningOverSSL(false)
     , mEnforceAssocReq(false)
+    , mInPrivateBrowsingMode(PRIVATE_BROWSING_UNKNOWN)
     , mLastUniqueID(NowInSeconds())
     , mSessionStartTime(0)
     , mLegacyAppName("Mozilla")
     , mLegacyAppVersion("5.0")
     , mProduct("Gecko")
     , mUserAgentIsDirty(true)
     , mUseCache(true)
     , mPromptTempRedirect(true)
@@ -295,16 +296,17 @@ nsHttpHandler::Init()
                                   NS_HTTP_STARTUP_TOPIC);    
     
     mObserverService = mozilla::services::GetObserverService();
     if (mObserverService) {
         mObserverService->AddObserver(this, "profile-change-net-teardown", true);
         mObserverService->AddObserver(this, "profile-change-net-restore", true);
         mObserverService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
         mObserverService->AddObserver(this, "net:clear-active-logins", true);
+        mObserverService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
         mObserverService->AddObserver(this, "net:prune-dead-connections", true);
         mObserverService->AddObserver(this, "net:failed-to-process-uri-content", true);
     }
  
     return NS_OK;
 }
 
 nsresult
@@ -401,16 +403,33 @@ nsHttpHandler::IsAcceptableEncoding(cons
     // an "x-" prefix before matching the encoding to one we claim
     // to accept.
     if (!PL_strncasecmp(enc, "x-", 2))
         enc += 2;
 
     return nsHttp::FindToken(mAcceptEncodings.get(), enc, HTTP_LWS ",") != nullptr;
 }
 
+bool
+nsHttpHandler::InPrivateBrowsingMode()
+{
+    if (PRIVATE_BROWSING_UNKNOWN == mInPrivateBrowsingMode) {
+        // figure out if we're starting in private browsing mode
+        nsCOMPtr<nsIPrivateBrowsingService> pbs =
+            do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
+        if (!pbs)
+            return PRIVATE_BROWSING_OFF;
+
+        bool p = false;
+        pbs->GetPrivateBrowsingEnabled(&p);
+        mInPrivateBrowsingMode = p ? PRIVATE_BROWSING_ON : PRIVATE_BROWSING_OFF;
+    }
+    return PRIVATE_BROWSING_ON == mInPrivateBrowsingMode;
+}
+
 nsresult
 nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
 {
     if (!mStreamConvSvc) {
         nsresult rv;
         mStreamConvSvc = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
         if (NS_FAILED(rv)) return rv;
     }
@@ -1517,16 +1536,24 @@ nsHttpHandler::Observe(nsISupports *subj
     }
     else if (strcmp(topic, "profile-change-net-restore") == 0) {
         // initialize connection manager
         InitConnectionMgr();
     }
     else if (strcmp(topic, "net:clear-active-logins") == 0) {
         mAuthCache.ClearAll();
     }
+    else if (strcmp(topic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
+        if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(data))
+            mInPrivateBrowsingMode = PRIVATE_BROWSING_ON;
+        else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(data))
+            mInPrivateBrowsingMode = PRIVATE_BROWSING_OFF;
+        if (mConnMgr)
+            mConnMgr->ClosePersistentConnections();
+    }
     else if (strcmp(topic, "net:prune-dead-connections") == 0) {
         if (mConnMgr) {
             mConnMgr->PruneDeadConnections();
         }
     }
     else if (strcmp(topic, "net:failed-to-process-uri-content") == 0) {
         nsCOMPtr<nsIURI> uri = do_QueryInterface(subject);
         if (uri && mConnMgr)
--- a/netwerk/protocol/http/nsHttpHandler.h
+++ b/netwerk/protocol/http/nsHttpHandler.h
@@ -17,16 +17,17 @@
 #include "nsCOMPtr.h"
 #include "nsWeakReference.h"
 
 #include "nsIHttpProtocolHandler.h"
 #include "nsIProtocolProxyService.h"
 #include "nsIIOService.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
+#include "nsIPrivateBrowsingService.h"
 #include "nsIStreamConverterService.h"
 #include "nsICacheSession.h"
 #include "nsICookieService.h"
 #include "nsIIDNService.h"
 #include "nsITimer.h"
 #include "nsIStrictTransportSecurityService.h"
 #include "nsISpeculativeConnect.h"
 
@@ -157,16 +158,19 @@ public:
 
     nsresult SpeculativeConnect(nsHttpConnectionInfo *ci,
                                 nsIInterfaceRequestor *callbacks,
                                 nsIEventTarget *target)
     {
         return mConnMgr->SpeculativeConnect(ci, callbacks, target);
     }
 
+    // for anything that wants to know if we're in private browsing mode.
+    bool InPrivateBrowsingMode();
+
     //
     // The HTTP handler caches pointers to specific XPCOM services, and
     // provides the following helper routines for accessing those services:
     //
     nsresult GetStreamConverterService(nsIStreamConverterService **);
     nsresult GetIOService(nsIIOService** service);
     nsICookieService * GetCookieService(); // not addrefed
     nsIStrictTransportSecurityService * GetSTSService();
@@ -305,16 +309,23 @@ private:
     // the userpass field of the URL to obscure the actual origin server.
     uint8_t  mPhishyUserPassLength;
 
     uint8_t  mQoSBits;
 
     bool mPipeliningOverSSL;
     bool mEnforceAssocReq;
 
+    // cached value of whether or not the browser is in private browsing mode.
+    enum {
+        PRIVATE_BROWSING_OFF = false,
+        PRIVATE_BROWSING_ON = true,
+        PRIVATE_BROWSING_UNKNOWN = 2
+    } mInPrivateBrowsingMode;
+
     nsCString mAccept;
     nsCString mAcceptLanguages;
     nsCString mAcceptEncodings;
 
     nsXPIDLCString mDefaultSocketType;
 
     // cache support
     uint32_t                  mLastUniqueID;
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp
@@ -31,17 +31,17 @@ WyciwygChannelChild::WyciwygChannelChild
   : mStatus(NS_OK)
   , mIsPending(false)
   , mCanceled(false)
   , mLoadFlags(LOAD_NORMAL)
   , mContentLength(-1)
   , mCharsetSource(kCharsetUninitialized)
   , mState(WCC_NEW)
   , mIPCOpen(false)
-  , mEventQ(NS_ISUPPORTS_CAST(nsIWyciwygChannel*, this))
+  , mEventQ(this)
 {
   LOG(("Creating WyciwygChannelChild @%x\n", this));
 }
 
 WyciwygChannelChild::~WyciwygChannelChild()
 {
   LOG(("Destroying WyciwygChannelChild @%x\n", this));
 }
--- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
+++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp
@@ -78,17 +78,16 @@ private:
 
 
 // nsWyciwygChannel methods 
 nsWyciwygChannel::nsWyciwygChannel()
   : mStatus(NS_OK),
     mIsPending(false),
     mCharsetAndSourceSet(false),
     mNeedToWriteCharset(false),
-    mPrivateBrowsing(false),
     mCharsetSource(kCharsetUninitialized),
     mContentLength(-1),
     mLoadFlags(LOAD_NORMAL)
 {
 }
 
 nsWyciwygChannel::~nsWyciwygChannel() 
 {
@@ -267,19 +266,16 @@ NS_IMETHODIMP
 nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
 {
   mCallbacks = aNotificationCallbacks;
   NS_QueryNotificationCallbacks(mCallbacks,
                                 mLoadGroup,
                                 NS_GET_IID(nsIProgressEventSink),
                                 getter_AddRefs(mProgressSink));
 
-  // Will never change unless SetNotificationCallbacks called again, so cache
-  mPrivateBrowsing = NS_UsePrivateBrowsing(this);
-
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsWyciwygChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
 {
   NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo);
 
@@ -662,31 +658,28 @@ nsWyciwygChannel::OpenCacheEntry(const n
   nsresult rv = NS_ERROR_FAILURE;
   // Get cache service
   nsCOMPtr<nsICacheService> cacheService =
     do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // honor security settings
   nsCacheStoragePolicy storagePolicy;
-  if (mPrivateBrowsing || mLoadFlags & INHIBIT_PERSISTENT_CACHING)
+  if (mLoadFlags & INHIBIT_PERSISTENT_CACHING)
     storagePolicy = nsICache::STORE_IN_MEMORY;
   else
     storagePolicy = nsICache::STORE_ANYWHERE;
 
   nsCOMPtr<nsICacheSession> cacheSession;
   // Open a stream based cache session.
-  const char* sessionName = mPrivateBrowsing ? "wyciwyg-private" : "wyciwyg";
-  rv = cacheService->CreateSession(sessionName, storagePolicy, true,
+  rv = cacheService->CreateSession("wyciwyg", storagePolicy, true,
                                    getter_AddRefs(cacheSession));
   if (!cacheSession) 
     return NS_ERROR_FAILURE;
 
-  cacheSession->SetIsPrivate(mPrivateBrowsing);
-
   if (aAccessMode == nsICache::ACCESS_WRITE)
     rv = cacheSession->OpenCacheEntry(aCacheKey, aAccessMode, false,
                                       getter_AddRefs(mCacheEntry));
   else
     rv = cacheSession->AsyncOpenCacheEntry(aCacheKey, aAccessMode, this, false);
 
   return rv;
 }
--- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.h
+++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.h
@@ -67,17 +67,16 @@ protected:
 
     void NotifyListener();
     bool IsOnCacheIOThread();
 
     nsresult                            mStatus;
     bool                                mIsPending;
     bool                                mCharsetAndSourceSet;
     bool                                mNeedToWriteCharset;
-    bool                                mPrivateBrowsing;
     int32_t                             mCharsetSource;
     nsCString                           mCharset;
     int32_t                             mContentLength;
     uint32_t                            mLoadFlags;
     nsCOMPtr<nsIURI>                    mURI;
     nsCOMPtr<nsIURI>                    mOriginalURI;
     nsCOMPtr<nsISupports>               mOwner;
     nsCOMPtr<nsIInterfaceRequestor>     mCallbacks;
--- a/netwerk/test/unit/test_bug248970_cache.js
+++ b/netwerk/test/unit/test_bug248970_cache.js
@@ -5,27 +5,46 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
 // names for cache devices
 const kDiskDevice = "disk";
 const kMemoryDevice = "memory";
 const kOfflineDevice = "offline";
-const kPrivate = "private";
 
 const kCacheA = "cache-A";
 const kCacheA2 = "cache-A2";
 const kCacheB = "cache-B";
 const kCacheC = "cache-C";
 const kTestContent = "test content";
 
 // the name for our cache session
 const kPrivateBrowsing = "PrivateBrowsing";
 
+var _PBSvc;
+function get_privatebrowsing_service() {
+  if (_PBSvc)
+    return _PBSvc;
+
+  try {
+    _PBSvc = Cc["@mozilla.org/privatebrowsing;1"].
+             getService(Ci.nsIPrivateBrowsingService);
+    return _PBSvc;
+  } catch (e) {}
+
+  return null;
+}
+
+
+
+
+
+
+
 function check_devices_available(devices) {
   var cs = get_cache_service();
   var found_devices = [];
 
   var visitor = {
     visitDevice: function (deviceID, deviceInfo) {
       found_devices.push(deviceID);
       return false;
@@ -78,31 +97,29 @@ function make_input_stream_scriptable(in
   var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].
                 createInstance(Ci.nsIScriptableInputStream);
   wrapper.init(input);
   return wrapper;
 }
 
 const entries = [
 // key       content       device          should exist after leaving PB
-  [kCacheA,  kTestContent, kMemoryDevice,  true],
-  [kCacheA2, kTestContent, kPrivate,       false],
+  [kCacheA,  kTestContent, kMemoryDevice,  false],
   [kCacheB,  kTestContent, kDiskDevice,    true],
   [kCacheC,  kTestContent, kOfflineDevice, true]
 ]
 
 function get_storage_policy(device)
 {
   switch (device) {
     case kDiskDevice:
       return Ci.nsICache.STORE_ON_DISK;
     case kOfflineDevice:
       return Ci.nsICache.STORE_OFFLINE;
     case kMemoryDevice:
-    case kPrivate:
       return Ci.nsICache.STORE_IN_MEMORY;
   }
   do_throw("unknown device");
 }
 
 var store_idx;
 var store_cb = null;
 function store_entries(cb)
@@ -116,19 +133,16 @@ function store_entries(cb)
     do_execute_soon(store_cb);
     return;
   }
 
   var cache = get_cache_service();
   var session = cache.createSession(kPrivateBrowsing,
                                     get_storage_policy(entries[store_idx][2]),
                                     Ci.nsICache.STREAM_BASED);
-  if (entries[store_idx][2] == kPrivate) {
-    session.isPrivate = true;
-  }
 
   session.asyncOpenCacheEntry(entries[store_idx][0],
                               Ci.nsICache.ACCESS_WRITE,
                               store_data);
 }
 
 var store_data = {
   onCacheEntryAvailable: function oCEA(entry, access, status) {
@@ -163,19 +177,16 @@ function check_entries(cb, pbExited)
     do_execute_soon(check_cb);
     return;
   }
 
   var cache = get_cache_service();
   var session = cache.createSession(kPrivateBrowsing,
                                     get_storage_policy(entries[check_idx][2]),
                                     Ci.nsICache.STREAM_BASED);
-  if (entries[check_idx][2] == kPrivate) {
-    session.isPrivate = true;
-  }
 
   session.asyncOpenCacheEntry(entries[check_idx][0],
                               Ci.nsICache.ACCESS_READ,
                               check_data);
 }
 
 var check_data = {
   onCacheEntryAvailable: function oCEA(entry, access, status) {
@@ -212,22 +223,38 @@ function run_test2() {
   // Make sure all three cache devices are available initially
   check_devices_available([kMemoryDevice, kDiskDevice, kOfflineDevice]);
 
   // Check if cache-A, cache-A2, cache-B and cache-C are available
   check_entries(run_test3, false);
 }
 
 function run_test3() {
-  // Simulate all private browsing instances being closed
-  var obsvc = Cc["@mozilla.org/observer-service;1"].
-    getService(Ci.nsIObserverService);
-  obsvc.notifyObservers(null, "last-pb-context-exited", null);
+  var pb = get_privatebrowsing_service();
+  if (pb) { // Private Browsing might not be available
+    var prefBranch = Cc["@mozilla.org/preferences-service;1"].
+                     getService(Ci.nsIPrefBranch);
+    prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
+
+    // Enter private browsing mode
+    pb.privateBrowsingEnabled = true;
+
+    // Make sure only the memory device is available
+    check_devices_available([kMemoryDevice]);
+
+    // Make sure the memory device is empty
+    do_check_eq(get_device_entry_count(kMemoryDevice), 0);
 
-  // Make sure all three cache devices are still available
-  check_devices_available([kMemoryDevice, kDiskDevice, kOfflineDevice]);
+    // Exit private browsing mode
+    pb.privateBrowsingEnabled = false;
+
+    // Make sure all three cache devices are available after leaving the private mode
+    check_devices_available([kMemoryDevice, kDiskDevice, kOfflineDevice]);
 
-  // Make sure the memory device is not empty
-  do_check_eq(get_device_entry_count(kMemoryDevice), 1);
+    // Make sure the memory device is empty
+    do_check_eq(get_device_entry_count(kMemoryDevice), 0);
 
-  // Check if cache-A is gone, and cache-B and cache-C are still available
-  check_entries(do_test_finished, true);
+    // Check if cache-A is gone, and cache-B and cache-C are still available
+    check_entries(do_test_finished, true);
+    
+    prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
+  }
 }
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -1178,22 +1178,16 @@ NS_IMETHODIMP_(nsrefcnt) Class::Release(
   NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
 
 #define NS_IMPL_QUERY_INTERFACE_INHERITED9(Class,Super,i1,i2,i3,i4,i5,i6,     \
                                            i7,i8,i9)                          \
   NS_INTERFACE_TABLE_HEAD(Class)                                              \
   NS_INTERFACE_TABLE_INHERITED9(Class, i1, i2, i3, i4, i5, i6, i7, i8, i9)    \
   NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
 
-#define NS_IMPL_QUERY_INTERFACE_INHERITED10(Class,Super,i1,i2,i3,i4,i5,i6,       \
-                                            i7,i8,i9,i10)                        \
-  NS_INTERFACE_TABLE_HEAD(Class)                                                 \
-  NS_INTERFACE_TABLE_INHERITED10(Class, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10) \
-  NS_INTERFACE_TABLE_TAIL_INHERITING(Super)
-
 /**
  * Convenience macros for implementing all nsISupports methods for
  * a simple class.
  * @param _class The name of the class implementing the method
  * @param _classiiddef The name of the #define symbol that defines the IID
  * for the class (e.g. NS_ISUPPORTS_IID)
  */
 
@@ -1306,21 +1300,16 @@ NS_IMETHODIMP_(nsrefcnt) Class::Release(
     NS_IMPL_QUERY_INTERFACE_INHERITED8(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8) \
     NS_IMPL_ADDREF_INHERITED(Class, Super)                                    \
     NS_IMPL_RELEASE_INHERITED(Class, Super)                                   \
 
 #define NS_IMPL_ISUPPORTS_INHERITED9(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8, i9) \
     NS_IMPL_QUERY_INTERFACE_INHERITED9(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8, i9) \
     NS_IMPL_ADDREF_INHERITED(Class, Super)                                    \
     NS_IMPL_RELEASE_INHERITED(Class, Super)                                   \
-
-#define NS_IMPL_ISUPPORTS_INHERITED10(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10) \
-    NS_IMPL_QUERY_INTERFACE_INHERITED10(Class, Super, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10) \
-    NS_IMPL_ADDREF_INHERITED(Class, Super)                                    \
-    NS_IMPL_RELEASE_INHERITED(Class, Super)                                   \
 /*
  * Macro to glue together a QI that starts with an interface table
  * and segues into an interface map (e.g. it uses singleton classinfo
  * or tearoffs).
  */
 #define NS_INTERFACE_TABLE_TO_MAP_SEGUE \
   if (rv == NS_OK) return rv; \
   nsISupports* foundInterface;