diff options
Diffstat (limited to 'dom/cache')
-rw-r--r-- | dom/cache/CacheChild.cpp | 2 | ||||
-rw-r--r-- | dom/cache/CacheStorageChild.cpp | 2 | ||||
-rw-r--r-- | dom/cache/CacheStreamControlParent.cpp | 4 | ||||
-rw-r--r-- | dom/cache/CacheStreamControlParent.h | 5 | ||||
-rw-r--r-- | dom/cache/Connection.cpp | 3 | ||||
-rw-r--r-- | dom/cache/StreamList.cpp | 10 | ||||
-rw-r--r-- | dom/cache/test/marionette/test_caches_delete_cleanup_after_shutdown.py | 116 |
7 files changed, 77 insertions, 65 deletions
diff --git a/dom/cache/CacheChild.cpp b/dom/cache/CacheChild.cpp index c822653fea..05f25ec838 100644 --- a/dom/cache/CacheChild.cpp +++ b/dom/cache/CacheChild.cpp @@ -112,7 +112,7 @@ void CacheChild::NoteDeletedActor() { // CacheOpChilds when StartDestroy was called from WorkerRef notification. If // the last CacheOpChild is getting destructed; it's the time for us to // SendTearDown to the other side. - if (NumChildActors() == 1 && mDelayedDestroy && !mLocked) DestroyInternal(); + if (NumChildActors() == 0 && mDelayedDestroy && !mLocked) DestroyInternal(); } already_AddRefed<PCacheOpChild> CacheChild::AllocPCacheOpChild( diff --git a/dom/cache/CacheStorageChild.cpp b/dom/cache/CacheStorageChild.cpp index e7918bbf88..e344e2c272 100644 --- a/dom/cache/CacheStorageChild.cpp +++ b/dom/cache/CacheStorageChild.cpp @@ -88,7 +88,7 @@ void CacheStorageChild::NoteDeletedActor() { // when StartDestroy was called from WorkerRef notification. If the last // CacheOpChild is getting destructed; it's the time for us to SendTearDown to // the other side. - if (NumChildActors() == 1 && mDelayedDestroy) DestroyInternal(); + if (NumChildActors() == 0 && mDelayedDestroy) DestroyInternal(); } void CacheStorageChild::ActorDestroy(ActorDestroyReason aReason) { diff --git a/dom/cache/CacheStreamControlParent.cpp b/dom/cache/CacheStreamControlParent.cpp index aaab59f944..8441d5cee4 100644 --- a/dom/cache/CacheStreamControlParent.cpp +++ b/dom/cache/CacheStreamControlParent.cpp @@ -149,9 +149,11 @@ void CacheStreamControlParent::SetStreamList( void CacheStreamControlParent::CloseAll() { NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent); - NotifyCloseAll(); QM_WARNONLY_TRY(OkIf(SendCloseAll())); + + // Attention: NotifyCloseAll potentially destroys our this synchronously! + NotifyCloseAll(); } void CacheStreamControlParent::Shutdown() { diff --git a/dom/cache/CacheStreamControlParent.h b/dom/cache/CacheStreamControlParent.h index 46fe834309..332c08487b 100644 --- a/dom/cache/CacheStreamControlParent.h +++ b/dom/cache/CacheStreamControlParent.h @@ -25,7 +25,12 @@ class CacheStreamControlParent final : public PCacheStreamControlParent, CacheStreamControlParent(); void SetStreamList(SafeRefPtr<StreamList> aStreamList); + + // Will close all streams. May synchronously free our this, see + // inherited StreamControl::CloseAllReadStreams. void CloseAll(); + + // Implicitly called when the last stream goes away. void Shutdown(); // StreamControl methods diff --git a/dom/cache/Connection.cpp b/dom/cache/Connection.cpp index e9c9becebc..f7afca0d7a 100644 --- a/dom/cache/Connection.cpp +++ b/dom/cache/Connection.cpp @@ -288,7 +288,8 @@ uint32_t Connection::DecreaseTransactionNestingLevel( NS_IMETHODIMP Connection::BackupToFileAsync(nsIFile* aDestinationFile, - mozIStorageCompletionCallback* aCallback) { + mozIStorageCompletionCallback* aCallback, + uint32_t aPagesPerStep, uint32_t aStepDelayMs) { // async methods are not supported return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/dom/cache/StreamList.cpp b/dom/cache/StreamList.cpp index cbce695b60..00dd3b585f 100644 --- a/dom/cache/StreamList.cpp +++ b/dom/cache/StreamList.cpp @@ -136,13 +136,9 @@ void StreamList::CloseAll() { NS_ASSERT_OWNINGTHREAD(StreamList); if (mStreamControl && mStreamControl->CanSend()) { - auto* streamControl = std::exchange(mStreamControl, nullptr); - - streamControl->CloseAll(); - - mStreamControl = std::exchange(streamControl, nullptr); - - mStreamControl->Shutdown(); + // CloseAll will kick off everything needed for shutdown. + // mStreamControl may go away immediately or async. + mStreamControl->CloseAll(); } else { // We cannot interact with the child, let's just clear our lists of // streams to unblock shutdown. diff --git a/dom/cache/test/marionette/test_caches_delete_cleanup_after_shutdown.py b/dom/cache/test/marionette/test_caches_delete_cleanup_after_shutdown.py index 4db7606b08..2923deeffe 100644 --- a/dom/cache/test/marionette/test_caches_delete_cleanup_after_shutdown.py +++ b/dom/cache/test/marionette/test_caches_delete_cleanup_after_shutdown.py @@ -2,6 +2,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +import os + from marionette_driver import Wait from marionette_harness import MarionetteTestCase @@ -13,6 +15,8 @@ from marionette_harness import MarionetteTestCase fail if we fail to delete all of the 5,000 1k files we create on disk as part of the test. """ +QM_TESTING_PREF = "dom.quotaManager.testing" + EXPECTED_CACHEDIR_SIZE_AFTER_CLEANUP = 128 * 1024 # 128KB CACHE_ID = "data" @@ -31,10 +35,12 @@ class CachesDeleteCleanupAtShutdownTestCase(MarionetteTestCase): def setUp(self): super(CachesDeleteCleanupAtShutdownTestCase, self).setUp() self.marionette.restart(in_app=False, clean=True) + self.marionette.set_pref(QM_TESTING_PREF, True) def tearDown(self): self.marionette.restart(in_app=False, clean=True) super(CachesDeleteCleanupAtShutdownTestCase, self).tearDown() + self.marionette.set_pref(QM_TESTING_PREF, False) def getUsage(self): return self.marionette.execute_script( @@ -71,56 +77,45 @@ class CachesDeleteCleanupAtShutdownTestCase(MarionetteTestCase): script_args=(CACHE_ID,), ) + def countBodies(self): + profile = self.marionette.instance.profile.profile + originDir = ( + self.marionette.absolute_url("")[:-1].replace(":", "+").replace("/", "+") + ) + morgueDir = f"{profile}/storage/default/{originDir}/cache/morgue" + print("morgueDir path = ", morgueDir) + + bodyCount = -1 + if os.path.exists(morgueDir): + bodyCount = 0 + for elem in os.listdir(morgueDir): + absPathElem = os.path.join(morgueDir, elem) + if os.path.isdir(absPathElem): + bodyCount += sum( + 1 + for e in os.listdir(absPathElem) + if os.path.isfile(os.path.join(absPathElem, e)) + ) + return bodyCount + def ensureCleanDirectory(self): + orphanedBodiesCount = self.countBodies() + return orphanedBodiesCount <= 0 + + def isStorageInitialized(self, temporary=False): with self.marionette.using_context("chrome"): - return self.marionette.execute_script( + return self.marionette.execute_async_script( + """ + const [resolve] = arguments; + const req = %s; + req.callback = () => { + resolve(req.resultCode == Cr.NS_OK && req.result) + }; """ - let originDir = arguments[0]; - const pathDelimiter = "/"; - - function getRelativeFile(relativePath) { - let file = Services.dirsvc - .get("ProfD", Ci.nsIFile) - .clone(); - - relativePath.split(pathDelimiter).forEach(function(component) { - if (component == "..") { - file = file.parent; - } else { - file.append(component); - } - }); - - return file; - } - - function getCacheDir() { - - const storageDirName = "storage"; - const defaultPersistenceDirName = "default"; - - return getRelativeFile( - `${storageDirName}/${defaultPersistenceDirName}/${originDir}/cache` - ); - } - - const cacheDir = getCacheDir(); - let morgueDir = cacheDir.clone(); - - // morgue directory should be empty - // or atleast directories under morgue should be empty - morgueDir.append("morgue"); - for (let dir of morgueDir.directoryEntries) { - for (let file of dir.directoryEntries) { - return false; - } - } - return true; - """, - script_args=( - self.marionette.absolute_url("")[:-1] - .replace(":", "+") - .replace("/", "+"), + % ( + "Services.qms.temporaryStorageInitialized()" + if temporary + else "Services.qms.storageInitialized()" ), new_sandbox=False, ) @@ -128,6 +123,7 @@ class CachesDeleteCleanupAtShutdownTestCase(MarionetteTestCase): def create_and_cleanup_cache(self, ensureCleanCallback, in_app): # create 640 cache entries self.doCacheWork(640) + print("usage after doCacheWork = ", self.getUsage()) self.marionette.restart(in_app=in_app) print("restart successful") @@ -137,6 +133,14 @@ class CachesDeleteCleanupAtShutdownTestCase(MarionetteTestCase): ) return ensureCleanCallback() + def afterCleanupClosure(self, usage): + print( + f"Storage initialized = {self.isStorageInitialized()}, temporary storage initialized = {self.isStorageInitialized(True)}" + ) + + print(f"Usage = {usage} and number of orphaned bodies = {self.countBodies()}") + return usage < EXPECTED_CACHEDIR_SIZE_AFTER_CLEANUP + def test_ensure_cache_cleanup_after_clean_restart(self): self.marionette.navigate( self.marionette.absolute_url("dom/cache/cacheUsage.html") @@ -144,9 +148,8 @@ class CachesDeleteCleanupAtShutdownTestCase(MarionetteTestCase): beforeUsage = self.getUsage() def ensureCleanCallback(): - Wait(self.marionette, timeout=60).until( - lambda x: (self.getUsage() - beforeUsage) - < EXPECTED_CACHEDIR_SIZE_AFTER_CLEANUP, + Wait(self.marionette, interval=1, timeout=60).until( + lambda _: self.afterCleanupClosure(self.getUsage() - beforeUsage), message="Cache directory is not cleaned up properly", ) @@ -164,14 +167,19 @@ class CachesDeleteCleanupAtShutdownTestCase(MarionetteTestCase): self.marionette.navigate( self.marionette.absolute_url("dom/cache/cacheUsage.html") ) + + print(f"profile path = {self.marionette.instance.profile.profile}") + beforeUsage = self.getUsage() def ensureCleanCallback(): - self.openCache() + print( + f"ensureCleanCallback, profile path = {self.marionette.instance.profile.profile}" + ) - Wait(self.marionette, timeout=60).until( - lambda x: (self.getUsage() - beforeUsage) - < EXPECTED_CACHEDIR_SIZE_AFTER_CLEANUP, + self.openCache() + Wait(self.marionette, interval=1, timeout=60).until( + lambda _: self.afterCleanupClosure(self.getUsage() - beforeUsage), message="Cache directory is not cleaned up properly", ) |