michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "DiskSpaceWatcher.h" michael@0: #include "nsIObserverService.h" michael@0: #include "nsXULAppAPI.h" michael@0: #include "mozilla/Hal.h" michael@0: #include "mozilla/ModuleUtils.h" michael@0: #include "mozilla/Preferences.h" michael@0: #include "mozilla/ClearOnShutdown.h" michael@0: #include "mozilla/Services.h" michael@0: michael@0: #define NS_DISKSPACEWATCHER_CID \ michael@0: { 0xab218518, 0xf197, 0x4fb4, { 0x8b, 0x0f, 0x8b, 0xb3, 0x4d, 0xf2, 0x4b, 0xf4 } } michael@0: michael@0: using namespace mozilla; michael@0: michael@0: StaticRefPtr gDiskSpaceWatcher; michael@0: michael@0: NS_IMPL_ISUPPORTS(DiskSpaceWatcher, nsIDiskSpaceWatcher, nsIObserver) michael@0: michael@0: uint64_t DiskSpaceWatcher::sFreeSpace = 0; michael@0: bool DiskSpaceWatcher::sIsDiskFull = false; michael@0: michael@0: DiskSpaceWatcher::DiskSpaceWatcher() michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: MOZ_ASSERT(!gDiskSpaceWatcher); michael@0: } michael@0: michael@0: DiskSpaceWatcher::~DiskSpaceWatcher() michael@0: { michael@0: MOZ_ASSERT(!gDiskSpaceWatcher); michael@0: } michael@0: michael@0: already_AddRefed michael@0: DiskSpaceWatcher::FactoryCreate() michael@0: { michael@0: if (XRE_GetProcessType() != GeckoProcessType_Default) { michael@0: return nullptr; michael@0: } michael@0: michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: if (!Preferences::GetBool("disk_space_watcher.enabled", false)) { michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!gDiskSpaceWatcher) { michael@0: gDiskSpaceWatcher = new DiskSpaceWatcher(); michael@0: ClearOnShutdown(&gDiskSpaceWatcher); michael@0: } michael@0: michael@0: nsRefPtr service = gDiskSpaceWatcher.get(); michael@0: return service.forget(); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: DiskSpaceWatcher::Observe(nsISupports* aSubject, const char* aTopic, michael@0: const char16_t* aData) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: michael@0: if (!strcmp(aTopic, "profile-after-change")) { michael@0: nsCOMPtr observerService = michael@0: mozilla::services::GetObserverService(); michael@0: observerService->AddObserver(this, "profile-before-change", false); michael@0: mozilla::hal::StartDiskSpaceWatcher(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (!strcmp(aTopic, "profile-before-change")) { michael@0: nsCOMPtr observerService = michael@0: mozilla::services::GetObserverService(); michael@0: observerService->RemoveObserver(this, "profile-before-change"); michael@0: mozilla::hal::StopDiskSpaceWatcher(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: MOZ_ASSERT(false, "DiskSpaceWatcher got unexpected topic!"); michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: /* readonly attribute bool isDiskFull; */ michael@0: NS_IMETHODIMP DiskSpaceWatcher::GetIsDiskFull(bool* aIsDiskFull) michael@0: { michael@0: *aIsDiskFull = sIsDiskFull; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // GetFreeSpace is a macro on windows, and that messes up with the c++ michael@0: // compiler. michael@0: #ifdef XP_WIN michael@0: #undef GetFreeSpace michael@0: #endif michael@0: /* readonly attribute long freeSpace; */ michael@0: NS_IMETHODIMP DiskSpaceWatcher::GetFreeSpace(uint64_t* aFreeSpace) michael@0: { michael@0: *aFreeSpace = sFreeSpace; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // static michael@0: void DiskSpaceWatcher::UpdateState(bool aIsDiskFull, uint64_t aFreeSpace) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: if (!gDiskSpaceWatcher) { michael@0: return; michael@0: } michael@0: michael@0: nsCOMPtr observerService = michael@0: mozilla::services::GetObserverService(); michael@0: michael@0: sIsDiskFull = aIsDiskFull; michael@0: sFreeSpace = aFreeSpace; michael@0: michael@0: if (!observerService) { michael@0: return; michael@0: } michael@0: michael@0: const char16_t stateFull[] = { 'f', 'u', 'l', 'l', 0 }; michael@0: const char16_t stateFree[] = { 'f', 'r', 'e', 'e', 0 }; michael@0: michael@0: nsCOMPtr subject; michael@0: CallQueryInterface(gDiskSpaceWatcher.get(), getter_AddRefs(subject)); michael@0: MOZ_ASSERT(subject); michael@0: observerService->NotifyObservers(subject, michael@0: DISKSPACEWATCHER_OBSERVER_TOPIC, michael@0: sIsDiskFull ? stateFull : stateFree); michael@0: return; michael@0: } michael@0: michael@0: NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DiskSpaceWatcher, michael@0: DiskSpaceWatcher::FactoryCreate) michael@0: michael@0: NS_DEFINE_NAMED_CID(NS_DISKSPACEWATCHER_CID); michael@0: michael@0: static const mozilla::Module::CIDEntry kDiskSpaceWatcherCIDs[] = { michael@0: { &kNS_DISKSPACEWATCHER_CID, false, nullptr, DiskSpaceWatcherConstructor }, michael@0: { nullptr } michael@0: }; michael@0: michael@0: static const mozilla::Module::ContractIDEntry kDiskSpaceWatcherContracts[] = { michael@0: { "@mozilla.org/toolkit/disk-space-watcher;1", &kNS_DISKSPACEWATCHER_CID }, michael@0: { nullptr } michael@0: }; michael@0: michael@0: static const mozilla::Module::CategoryEntry kDiskSpaceWatcherCategories[] = { michael@0: #ifdef MOZ_WIDGET_GONK michael@0: { "profile-after-change", "Disk Space Watcher Service", DISKSPACEWATCHER_CONTRACTID }, michael@0: #endif michael@0: { nullptr } michael@0: }; michael@0: michael@0: static const mozilla::Module kDiskSpaceWatcherModule = { michael@0: mozilla::Module::kVersion, michael@0: kDiskSpaceWatcherCIDs, michael@0: kDiskSpaceWatcherContracts, michael@0: kDiskSpaceWatcherCategories michael@0: }; michael@0: michael@0: NSMODULE_DEFN(DiskSpaceWatcherModule) = &kDiskSpaceWatcherModule;