diff --git a/netwerk/build/components.conf b/netwerk/build/components.conf index d5b651a54644..ff673a4f64de 100644 --- a/netwerk/build/components.conf +++ b/netwerk/build/components.conf @@ -675,3 +675,13 @@ if link_service: 'singleton': True, }, **link_service) ] + +if toolkit != 'android': + Classes += [ + { + 'cid': '{72da39cc-0b9b-4fff-8ff9-d3b9a41d0dc4}', + 'contract_ids': ['@mozilla.org/net/CachePurgeLock;1'], + 'type': 'mozilla::net::CachePurgeLock', + 'headers': ['mozilla/net/CachePurgeLock.h'], + }, + ] diff --git a/netwerk/cache2/CachePurgeLock.cpp b/netwerk/cache2/CachePurgeLock.cpp new file mode 100644 index 000000000000..6da0ddc0ddeb --- /dev/null +++ b/netwerk/cache2/CachePurgeLock.cpp @@ -0,0 +1,76 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "CachePurgeLock.h" +#include "nsCOMPtr.h" +#include "nsIFile.h" +#include "nsAppRunner.h" +#include "mozilla/MultiInstanceLock.h" + +namespace mozilla::net { + +NS_IMPL_ISUPPORTS(CachePurgeLock, nsICachePurgeLock) + +NS_IMETHODIMP +CachePurgeLock::Lock(const nsACString& profileName) { + nsresult rv; + if (mLock != MULTI_INSTANCE_LOCK_HANDLE_ERROR) { + // Lock is already open. + return NS_OK; + } + + nsCOMPtr appFile = mozilla::GetNormalizedAppFile(nullptr); + if (!appFile) { + return NS_ERROR_NOT_AVAILABLE; + } + + nsCOMPtr appDirFile; + rv = appFile->GetParent(getter_AddRefs(appDirFile)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString appDirPath; + rv = appDirFile->GetPath(appDirPath); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString lockName(profileName); + lockName.Append("-cachePurge"); + + mLock = mozilla::OpenMultiInstanceLock(lockName.get(), appDirPath.get()); + if (mLock == MULTI_INSTANCE_LOCK_HANDLE_ERROR) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +NS_IMETHODIMP +CachePurgeLock::IsOtherInstanceRunning(bool* aResult) { + if (NS_WARN_IF(XRE_GetProcessType() != GeckoProcessType_Default)) { + return NS_ERROR_SERVICE_NOT_AVAILABLE; + } + + if (mLock == MULTI_INSTANCE_LOCK_HANDLE_ERROR) { + return NS_ERROR_NOT_INITIALIZED; + } + + bool rv = mozilla::IsOtherInstanceRunning(mLock, aResult); + NS_ENSURE_TRUE(rv, NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMETHODIMP +CachePurgeLock::Unlock() { + if (mLock == MULTI_INSTANCE_LOCK_HANDLE_ERROR) { + // Lock is already released. + return NS_OK; + } + + mozilla::ReleaseMultiInstanceLock(mLock); + mLock = MULTI_INSTANCE_LOCK_HANDLE_ERROR; + + return NS_OK; +} + +} // namespace mozilla::net diff --git a/netwerk/cache2/CachePurgeLock.h b/netwerk/cache2/CachePurgeLock.h new file mode 100644 index 000000000000..464b4e681d9f --- /dev/null +++ b/netwerk/cache2/CachePurgeLock.h @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#ifndef mozilla_net_CachePurgeLock_h__ +#define mozilla_net_CachePurgeLock_h__ + +#include "nsICachePurgeLock.h" +#include "mozilla/MultiInstanceLock.h" + +namespace mozilla::net { + +class CachePurgeLock : public nsICachePurgeLock { + NS_DECL_ISUPPORTS + NS_DECL_NSICACHEPURGELOCK + private: + virtual ~CachePurgeLock() = default; + + MultiInstLockHandle mLock = MULTI_INSTANCE_LOCK_HANDLE_ERROR; +}; + +} // namespace mozilla::net + +#endif // mozilla_net_CachePurgeLock_h__ diff --git a/netwerk/cache2/moz.build b/netwerk/cache2/moz.build index 3a3cfd4b65c9..a75ee849e636 100644 --- a/netwerk/cache2/moz.build +++ b/netwerk/cache2/moz.build @@ -11,6 +11,7 @@ XPIDL_SOURCES += [ "nsICacheEntry.idl", "nsICacheEntryDoomCallback.idl", "nsICacheEntryOpenCallback.idl", + "nsICachePurgeLock.idl", "nsICacheStorage.idl", "nsICacheStorageService.idl", "nsICacheStorageVisitor.idl", @@ -24,6 +25,8 @@ EXPORTS += [ "CacheStorageService.h", ] +EXPORTS.mozilla.net += ["CachePurgeLock.h"] + SOURCES += [ "CacheStorage.cpp", ] @@ -49,6 +52,11 @@ UNIFIED_SOURCES += [ "CacheStorageService.cpp", ] +if CONFIG["MOZ_WIDGET_TOOLKIT"] != "android": + UNIFIED_SOURCES += [ + "CachePurgeLock.cpp", + ] + LOCAL_INCLUDES += [ "/netwerk/base", "/netwerk/cache", diff --git a/netwerk/cache2/nsICachePurgeLock.idl b/netwerk/cache2/nsICachePurgeLock.idl new file mode 100644 index 000000000000..fcd4b4afee4a --- /dev/null +++ b/netwerk/cache2/nsICachePurgeLock.idl @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "nsISupports.idl" + +/** + * This object is a wrapper of MultiInstanceLock. + * It's intended to be used to ensure exclusive access to folders being + * deleted by the purgeHTTPCache background task. + */ +[scriptable,uuid(8abb21e3-c6a0-4b4d-9333-cc0d72f2c23b)] +interface nsICachePurgeLock : nsISupports { + /** + * Initializes the lock using the profile name and the current process's + * path. + * Will throw if a lock was already acquired successfully. + */ + void lock(in AUTF8String profileName); + + /** + * Returns true if another instance also holds the lock. + * Throws if called before lock was called, or after unlock was called. + */ + bool isOtherInstanceRunning(); + + /** + * Releases the lock. + * This object may be locked again, potentially using a different path + * after unlocking. + */ + void unlock(); +};