Bug 853350 - Implement a notification system to monitor disk space r=bent

This commit is contained in:
Fabrice Desré 2013-05-09 15:57:31 -07:00
parent 4bd84cc89b
commit 559e6dfd4a
17 changed files with 745 additions and 5 deletions

View File

@ -717,3 +717,6 @@ pref("captivedetect.canonicalContent", "success\n");
// The url of the manifest we use for ADU pings.
pref("ping.manifestURL", "https://marketplace.firefox.com/packaged.webapp");
// Enable the disk space watcher
pref("disk_space_watcher.enabled", true);

View File

@ -155,6 +155,7 @@
@BINPATH@/components/content_xslt.xpt
@BINPATH@/components/cookie.xpt
@BINPATH@/components/directory.xpt
@BINPATH@/components/diskspacewatcher.xpt
@BINPATH@/components/docshell.xpt
@BINPATH@/components/dom.xpt
@BINPATH@/components/dom_activities.xpt

View File

@ -1158,5 +1158,21 @@ void FactoryReset()
PROXY_IF_SANDBOXED(FactoryReset());
}
void
StartDiskSpaceWatcher()
{
AssertMainProcess();
AssertMainThread();
PROXY_IF_SANDBOXED(StartDiskSpaceWatcher());
}
void
StopDiskSpaceWatcher()
{
AssertMainProcess();
AssertMainThread();
PROXY_IF_SANDBOXED(StopDiskSpaceWatcher());
}
} // namespace hal
} // namespace mozilla

View File

@ -249,7 +249,7 @@ void AdjustSystemClock(int64_t aDeltaMilliseconds);
/**
* Set timezone
* @param aTimezoneSpec The definition can be found in
* @param aTimezoneSpec The definition can be found in
* http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
*/
void SetTimezone(const nsCString& aTimezoneSpec);
@ -303,14 +303,14 @@ void NotifySystemTimezoneChange(
/**
* Reboot the device.
*
*
* This API is currently only allowed to be used from the main process.
*/
void Reboot();
/**
* Power off the device.
*
*
* This API is currently only allowed to be used from the main process.
*/
void PowerOff();
@ -423,7 +423,7 @@ void RegisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aSwi
void UnregisterSwitchObserver(hal::SwitchDevice aDevice, hal::SwitchObserver *aSwitchObserver);
/**
* Notify the state of the switch.
* Notify the state of the switch.
*
* This API is internal to hal; clients shouldn't call it directly.
*/
@ -557,7 +557,7 @@ hal::FMRadioSettings GetFMBandSettings(hal::FMRadioCountry aCountry);
* Start a watchdog to compulsively shutdown the system if it hangs.
* @param aMode Specify how to shutdown the system.
* @param aTimeoutSecs Specify the delayed seconds to shutdown the system.
*
*
* This API is currently only allowed to be used from the main process.
*/
void StartForceQuitWatchdog(hal::ShutdownMode aMode, int32_t aTimeoutSecs);
@ -577,6 +577,20 @@ void StartMonitoringGamepadStatus();
*/
void StopMonitoringGamepadStatus();
/**
* Start monitoring disk space for low space situations.
*
* This API is currently only allowed to be used from the main process.
*/
void StartDiskSpaceWatcher();
/**
* Stop monitoring disk space for low space situations.
*
* This API is currently only allowed to be used from the main process.
*/
void StopDiskSpaceWatcher();
} // namespace MOZ_HAL_NAMESPACE
} // namespace mozilla

View File

@ -60,6 +60,7 @@ CPPSRCS += \
UeventPoller.cpp \
GonkSwitch.cpp \
GonkFMRadio.cpp \
GonkDiskSpaceWatcher.cpp \
$(NULL)
else ifeq (Linux,$(OS_TARGET))
CPPSRCS += \
@ -134,6 +135,7 @@ CPPSRCS += \
FallbackProcessPriority.cpp \
FallbackFMRadio.cpp \
FallbackFactoryReset.cpp \
FallbackDiskSpaceWatcher.cpp \
$(NULL)
endif #}

View File

@ -0,0 +1,19 @@
/* 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/. */
namespace mozilla {
namespace hal_impl {
void
StartDiskSpaceWatcher()
{
}
void
StopDiskSpaceWatcher()
{
}
} // namespace hal_impl
} // namespace mozilla

View File

@ -0,0 +1,309 @@
/* 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 "Hal.h"
#include <sys/syscall.h>
#include <sys/vfs.h>
#include <fcntl.h>
#include <errno.h>
#include "nsIObserverService.h"
#include "nsIDiskSpaceWatcher.h"
#include "mozilla/ModuleUtils.h"
#include "nsAutoPtr.h"
#include "nsThreadUtils.h"
#include "base/message_loop.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "nsXULAppAPI.h"
#include "fanotify.h"
#include "DiskSpaceWatcher.h"
using namespace mozilla;
namespace mozilla { namespace hal_impl { class GonkDiskSpaceWatcher; } }
using namespace mozilla::hal_impl;
template<>
struct RunnableMethodTraits<GonkDiskSpaceWatcher>
{
static void RetainCallee(GonkDiskSpaceWatcher* obj) { }
static void ReleaseCallee(GonkDiskSpaceWatcher* obj) { }
};
namespace mozilla {
namespace hal_impl {
// fanotify_init and fanotify_mark functions are syscalls.
// The user space bits are not part of bionic so we add them here
// as well as fanotify.h
int fanotify_init (unsigned int flags, unsigned int event_f_flags)
{
return syscall(367, flags, event_f_flags);
}
// Add, remove, or modify an fanotify mark on a filesystem object.
int fanotify_mark (int fanotify_fd, unsigned int flags,
uint64_t mask, int dfd, const char *pathname)
{
// On 32 bits platforms we have to convert the 64 bits mask into
// two 32 bits ints.
if (sizeof(void *) == 4) {
union {
uint64_t _64;
uint32_t _32[2];
} _mask;
_mask._64 = mask;
return syscall(368, fanotify_fd, flags, _mask._32[0], _mask._32[1],
dfd, pathname);
}
return syscall(368, fanotify_fd, flags, mask, dfd, pathname);
}
class GonkDiskSpaceWatcher MOZ_FINAL : public MessageLoopForIO::Watcher
{
public:
GonkDiskSpaceWatcher();
~GonkDiskSpaceWatcher() {};
virtual void OnFileCanReadWithoutBlocking(int aFd);
// We should never write to the fanotify fd.
virtual void OnFileCanWriteWithoutBlocking(int aFd)
{
MOZ_NOT_REACHED("Must not write to fanotify fd");
MOZ_CRASH();
}
void DoStart();
void DoStop();
private:
void NotifyUpdate();
uint64_t mLowThreshold;
uint64_t mHighThreshold;
TimeDuration mTimeout;
TimeStamp mLastTimestamp;
uint64_t mLastFreeSpace;
uint32_t mSizeDelta;
bool mIsDiskFull;
uint64_t mFreeSpace;
int mFd;
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
};
static GonkDiskSpaceWatcher* gHalDiskSpaceWatcher = nullptr;
#define WATCHER_PREF_LOW "disk_space_watcher.low_threshold"
#define WATCHER_PREF_HIGH "disk_space_watcher.high_threshold"
#define WATCHER_PREF_TIMEOUT "disk_space_watcher.timeout"
#define WATCHER_PREF_SIZE_DELTA "disk_space_watcher.size_delta"
static const char kWatchedPath[] = "/data";
// Helper class to dispatch calls to xpcom on the main thread.
class DiskSpaceNotifier : public nsRunnable
{
public:
DiskSpaceNotifier(const bool aIsDiskFull, const uint64_t aFreeSpace) :
mIsDiskFull(aIsDiskFull),
mFreeSpace(aFreeSpace) {}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
DiskSpaceWatcher::UpdateState(mIsDiskFull, mFreeSpace);
return NS_OK;
}
private:
bool mIsDiskFull;
uint64_t mFreeSpace;
};
// Helper runnable to delete the watcher on the main thread.
class DiskSpaceCleaner : public nsRunnable
{
public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
delete gHalDiskSpaceWatcher;
return NS_OK;
}
};
GonkDiskSpaceWatcher::GonkDiskSpaceWatcher() :
mLastFreeSpace(UINT64_MAX),
mIsDiskFull(false),
mFreeSpace(UINT64_MAX),
mFd(-1)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(gHalDiskSpaceWatcher == nullptr);
// Default values: 5MB for low threshold, 10MB for high threshold, and
// a timeout of 5 seconds.
mLowThreshold = Preferences::GetInt(WATCHER_PREF_LOW, 5) * 1024 * 1024;
mHighThreshold = Preferences::GetInt(WATCHER_PREF_HIGH, 10) * 1024 * 1024;
mTimeout = TimeDuration::FromSeconds(Preferences::GetInt(WATCHER_PREF_TIMEOUT, 5));
mSizeDelta = Preferences::GetInt(WATCHER_PREF_SIZE_DELTA, 1) * 1024 * 1024;
}
void
GonkDiskSpaceWatcher::DoStart()
{
NS_ASSERTION(XRE_GetIOMessageLoop() == MessageLoopForIO::current(),
"Not on the correct message loop");
mFd = fanotify_init(FAN_CLASS_NOTIF, FAN_CLOEXEC);
if (mFd == -1) {
NS_WARNING("Error calling inotify_init()");
if (errno == ENOSYS) {
printf_stderr("Warning: No fanotify support in this device's kernel.\n");
}
return;
}
if (fanotify_mark(mFd, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_CLOSE,
0, kWatchedPath) < 0) {
NS_WARNING("Error calling fanotify_mark");
close(mFd);
mFd = -1;
return;
}
if (!MessageLoopForIO::current()->WatchFileDescriptor(
mFd, /* persistent = */ true,
MessageLoopForIO::WATCH_READ,
&mReadWatcher, gHalDiskSpaceWatcher)) {
NS_WARNING("Unable to watch fanotify fd.");
close(mFd);
mFd = -1;
}
}
void
GonkDiskSpaceWatcher::DoStop()
{
NS_ASSERTION(XRE_GetIOMessageLoop() == MessageLoopForIO::current(),
"Not on the correct message loop");
if (mFd != -1) {
mReadWatcher.StopWatchingFileDescriptor();
fanotify_mark(mFd, FAN_MARK_FLUSH, 0, 0, kWatchedPath);
close(mFd);
mFd = -1;
}
// Dispatch the cleanup to the main thread.
nsCOMPtr<nsIRunnable> runnable = new DiskSpaceCleaner();
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
}
// We are called off the main thread, so we proxy first to the main thread
// before calling the xpcom object.
void
GonkDiskSpaceWatcher::NotifyUpdate()
{
mLastTimestamp = TimeStamp::Now();
mLastFreeSpace = mFreeSpace;
nsCOMPtr<nsIRunnable> runnable =
new DiskSpaceNotifier(mIsDiskFull, mFreeSpace);
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
}
void
GonkDiskSpaceWatcher::OnFileCanReadWithoutBlocking(int aFd)
{
struct fanotify_event_metadata* fem = nullptr;
char buf[4096];
struct statfs sfs;
int32_t len, rc;
do {
len = read(aFd, buf, sizeof(buf));
} while(len == -1 && errno == EINTR);
// We should get an exact multiple of fanotify_event_metadata
if (len <= 0 || (len % sizeof(*fem) != 0)) {
printf_stderr("About to crash: fanotify_event_metadata read error.");
MOZ_CRASH();
}
fem = reinterpret_cast<fanotify_event_metadata *>(buf);
while (FAN_EVENT_OK(fem, len)) {
rc = fstatfs(fem->fd, &sfs);
if (rc < 0) {
NS_WARNING("Unable to stat fan_notify fd");
} else {
bool firstRun = mFreeSpace == UINT64_MAX;
mFreeSpace = sfs.f_bavail * sfs.f_bsize;
// We change from full <-> free depending on the free space and the
// low and high thresholds.
// Once we are in 'full' mode we send updates for all size changes with
// a minimum of time between messages or when we cross a size change
// threshold.
if (firstRun) {
mIsDiskFull = mFreeSpace <= mLowThreshold;
// Always notify the current state at first run.
NotifyUpdate();
} else if (!mIsDiskFull && (mFreeSpace <= mLowThreshold)) {
mIsDiskFull = true;
NotifyUpdate();
} else if (mIsDiskFull && (mFreeSpace > mHighThreshold)) {
mIsDiskFull = false;
NotifyUpdate();
} else if (mIsDiskFull) {
if (mTimeout < TimeStamp::Now() - mLastTimestamp ||
mSizeDelta < llabs(mFreeSpace - mLastFreeSpace)) {
NotifyUpdate();
}
}
}
close(fem->fd);
fem = FAN_EVENT_NEXT(fem, len);
}
}
void
StartDiskSpaceWatcher()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aService);
// Bail out if called several times.
if (gHalDiskSpaceWatcher != nullptr) {
return;
}
gHalDiskSpaceWatcher = new GonkDiskSpaceWatcher();
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(gHalDiskSpaceWatcher, &GonkDiskSpaceWatcher::DoStart));
}
void
StopDiskSpaceWatcher()
{
MOZ_ASSERT(NS_IsMainThread());
if (!gHalDiskSpaceWatcher) {
return;
}
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableMethod(gHalDiskSpaceWatcher, &GonkDiskSpaceWatcher::DoStop));
}
} // namespace hal_impl
} // namespace mozilla

118
hal/gonk/fanotify.h Normal file
View File

@ -0,0 +1,118 @@
#ifndef _LINUX_FANOTIFY_H
#define _LINUX_FANOTIFY_H
/* This is a Linux header generated by "make headers_install" */
#include <linux/types.h>
/* the following events that user-space can register for */
#define FAN_ACCESS 0x00000001 /* File was accessed */
#define FAN_MODIFY 0x00000002 /* File was modified */
#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */
#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
#define FAN_OPEN 0x00000020 /* File was opened */
#define FAN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
#define FAN_OPEN_PERM 0x00010000 /* File open in perm check */
#define FAN_ACCESS_PERM 0x00020000 /* File accessed in perm check */
#define FAN_ONDIR 0x40000000 /* event occurred against dir */
#define FAN_EVENT_ON_CHILD 0x08000000 /* interested in child events */
/* helper events */
#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) /* close */
/* flags used for fanotify_init() */
#define FAN_CLOEXEC 0x00000001
#define FAN_NONBLOCK 0x00000002
/* These are NOT bitwise flags. Both bits are used togther. */
#define FAN_CLASS_NOTIF 0x00000000
#define FAN_CLASS_CONTENT 0x00000004
#define FAN_CLASS_PRE_CONTENT 0x00000008
#define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | \
FAN_CLASS_PRE_CONTENT)
#define FAN_UNLIMITED_QUEUE 0x00000010
#define FAN_UNLIMITED_MARKS 0x00000020
#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | \
FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\
FAN_UNLIMITED_MARKS)
/* flags used for fanotify_modify_mark() */
#define FAN_MARK_ADD 0x00000001
#define FAN_MARK_REMOVE 0x00000002
#define FAN_MARK_DONT_FOLLOW 0x00000004
#define FAN_MARK_ONLYDIR 0x00000008
#define FAN_MARK_MOUNT 0x00000010
#define FAN_MARK_IGNORED_MASK 0x00000020
#define FAN_MARK_IGNORED_SURV_MODIFY 0x00000040
#define FAN_MARK_FLUSH 0x00000080
#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD |\
FAN_MARK_REMOVE |\
FAN_MARK_DONT_FOLLOW |\
FAN_MARK_ONLYDIR |\
FAN_MARK_MOUNT |\
FAN_MARK_IGNORED_MASK |\
FAN_MARK_IGNORED_SURV_MODIFY |\
FAN_MARK_FLUSH)
/*
* All of the events - we build the list by hand so that we can add flags in
* the future and not break backward compatibility. Apps will get only the
* events that they originally wanted. Be sure to add new events here!
*/
#define FAN_ALL_EVENTS (FAN_ACCESS |\
FAN_MODIFY |\
FAN_CLOSE |\
FAN_OPEN)
/*
* All events which require a permission response from userspace
*/
#define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM |\
FAN_ACCESS_PERM)
#define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS |\
FAN_ALL_PERM_EVENTS |\
FAN_Q_OVERFLOW)
#define FANOTIFY_METADATA_VERSION 3
struct fanotify_event_metadata {
__u32 event_len;
__u8 vers;
__u8 reserved;
__u16 metadata_len;
__u64 mask;
__s32 fd;
__s32 pid;
};
struct fanotify_response {
__s32 fd;
__u32 response;
};
/* Legit userspace responses to a _PERM event */
#define FAN_ALLOW 0x01
#define FAN_DENY 0x02
/* No fd set in event */
#define FAN_NOFD -1
/* Helper functions to deal with fanotify_event_metadata buffers */
#define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
#define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, \
(struct fanotify_event_metadata*)(((char *)(meta)) + \
(meta)->event_len))
#define FAN_EVENT_OK(meta, len) ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && \
(long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \
(long)(meta)->event_len <= (long)(len))
#endif /* _LINUX_FANOTIFY_H */

View File

@ -409,6 +409,18 @@ FactoryReset()
Hal()->SendFactoryReset();
}
void
StartDiskSpaceWatcher()
{
NS_RUNTIMEABORT("StartDiskSpaceWatcher() can't be called from sandboxed contexts.");
}
void
StopDiskSpaceWatcher()
{
NS_RUNTIMEABORT("StopDiskSpaceWatcher() can't be called from sandboxed contexts.");
}
class HalParent : public PHalParent
, public BatteryObserver
, public NetworkObserver

View File

@ -0,0 +1,153 @@
/* 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 "DiskSpaceWatcher.h"
#include "mozilla/Hal.h"
#include "mozilla/ModuleUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/ClearOnShutdown.h"
#define NS_DISKSPACEWATCHER_CID \
{ 0xab218518, 0xf197, 0x4fb4, { 0x8b, 0x0f, 0x8b, 0xb3, 0x4d, 0xf2, 0x4b, 0xf4 } }
using namespace mozilla;
StaticRefPtr<DiskSpaceWatcher> gDiskSpaceWatcher;
NS_IMPL_ISUPPORTS2(DiskSpaceWatcher, nsIDiskSpaceWatcher, nsIObserver)
uint64_t DiskSpaceWatcher::sFreeSpace = 0;
bool DiskSpaceWatcher::sIsDiskFull = false;
DiskSpaceWatcher::DiskSpaceWatcher()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!gDiskSpaceWatcher);
}
DiskSpaceWatcher::~DiskSpaceWatcher()
{
MOZ_ASSERT(!gDiskSpaceWatcher);
}
already_AddRefed<DiskSpaceWatcher>
DiskSpaceWatcher::FactoryCreate()
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
return nullptr;
}
MOZ_ASSERT(NS_IsMainThread());
if (!Preferences::GetBool("disk_space_watcher.enabled", false)) {
return nullptr;
}
if (!gDiskSpaceWatcher) {
gDiskSpaceWatcher = new DiskSpaceWatcher();
ClearOnShutdown(&gDiskSpaceWatcher);
}
nsRefPtr<DiskSpaceWatcher> service = gDiskSpaceWatcher.get();
return service.forget();
}
NS_IMETHODIMP
DiskSpaceWatcher::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
MOZ_ASSERT(NS_IsMainThread());
if (!strcmp(aTopic, "profile-after-change")) {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
observerService->AddObserver(this, "profile-before-change", false);
mozilla::hal::StartDiskSpaceWatcher();
return NS_OK;
}
if (!strcmp(aTopic, "profile-before-change")) {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
observerService->RemoveObserver(this, "profile-before-change");
mozilla::hal::StopDiskSpaceWatcher();
return NS_OK;
}
MOZ_ASSERT(false, "DiskSpaceWatcher got unexpected topic!");
return NS_ERROR_UNEXPECTED;
}
/* readonly attribute bool isDiskFull; */
NS_IMETHODIMP DiskSpaceWatcher::GetIsDiskFull(bool* aIsDiskFull)
{
*aIsDiskFull = sIsDiskFull;
return NS_OK;
}
/* readonly attribute long freeSpace; */
NS_IMETHODIMP DiskSpaceWatcher::GetFreeSpace(uint64_t* aFreeSpace)
{
*aFreeSpace = sFreeSpace;
return NS_OK;
}
// static
void DiskSpaceWatcher::UpdateState(bool aIsDiskFull, uint64_t aFreeSpace)
{
MOZ_ASSERT(NS_IsMainThread());
if (!gDiskSpaceWatcher) {
return;
}
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
sIsDiskFull = aIsDiskFull;
sFreeSpace = aFreeSpace;
if (!observerService) {
return;
}
const PRUnichar stateFull[] = { 'f', 'u', 'l', 'l', 0 };
const PRUnichar stateFree[] = { 'f', 'r', 'e', 'e', 0 };
nsCOMPtr<nsISupports> subject;
CallQueryInterface(gDiskSpaceWatcher.get(), getter_AddRefs(subject));
MOZ_ASSERT(subject);
observerService->NotifyObservers(subject,
DISKSPACEWATCHER_OBSERVER_TOPIC,
sIsDiskFull ? stateFull : stateFree);
return;
}
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DiskSpaceWatcher,
DiskSpaceWatcher::FactoryCreate)
NS_DEFINE_NAMED_CID(NS_DISKSPACEWATCHER_CID);
static const mozilla::Module::CIDEntry kDiskSpaceWatcherCIDs[] = {
{ &kNS_DISKSPACEWATCHER_CID, false, nullptr, DiskSpaceWatcherConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kDiskSpaceWatcherContracts[] = {
{ "@mozilla.org/toolkit/disk-space-watcher;1", &kNS_DISKSPACEWATCHER_CID },
{ nullptr }
};
static const mozilla::Module::CategoryEntry kDiskSpaceWatcherCategories[] = {
{ "profile-after-change", "Disk Space Watcher Service", DISKSPACEWATCHER_CONTRACTID },
{ nullptr }
};
static const mozilla::Module kDiskSpaceWatcherModule = {
mozilla::Module::kVersion,
kDiskSpaceWatcherCIDs,
kDiskSpaceWatcherContracts,
kDiskSpaceWatcherCategories
};
NSMODULE_DEFN(DiskSpaceWatcherModule) = &kDiskSpaceWatcherModule;

View File

@ -0,0 +1,32 @@
/* 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 __DISKSPACEWATCHER_H__
#include "nsIDiskSpaceWatcher.h"
#include "nsIObserver.h"
#include "nsCOMPtr.h"
class DiskSpaceWatcher MOZ_FINAL : public nsIDiskSpaceWatcher,
public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDISKSPACEWATCHER
NS_DECL_NSIOBSERVER
static already_AddRefed<DiskSpaceWatcher>
FactoryCreate();
static void UpdateState(bool aIsDiskFull, uint64_t aFreeSpace);
private:
DiskSpaceWatcher();
~DiskSpaceWatcher();
static uint64_t sFreeSpace;
static bool sIsDiskFull;
};
#endif // __DISKSPACEWATCHER_H__

View File

@ -0,0 +1,23 @@
# 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/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = diskspacewatcher
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = DiskSpaceWatcherModule
LIBXUL_LIBRARY = 1
CPPSRCS = \
DiskSpaceWatcher.cpp \
$(NULL)
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk

View File

@ -0,0 +1,16 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsIDiskSpaceWatcher.idl',
]
EXPORTS += [
'DiskSpaceWatcher.h'
]
XPIDL_MODULE = 'diskspacewatcher'
MODULE = 'toolkitcomps'

View File

@ -0,0 +1,19 @@
/* 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"
[scriptable, uuid(3aceba74-2ed5-4e99-8fe4-06e90e2b8ef0)]
interface nsIDiskSpaceWatcher : nsISupports
{
readonly attribute bool isDiskFull; // True if we are low on disk space.
readonly attribute unsigned long long freeSpace; // The free space currently available.
};
%{ C++
#define DISKSPACEWATCHER_CONTRACTID "@mozilla.org/toolkit/disk-space-watcher;1"
// The data for this notification will be either 'free' or 'full'.
#define DISKSPACEWATCHER_OBSERVER_TOPIC "disk-space-watcher"
%}

View File

@ -16,6 +16,7 @@ PARALLEL_DIRS += [
'console',
'contentprefs',
'cookie',
'diskspacewatcher',
'downloads',
'exthelper',
'filepicker',

View File

@ -179,6 +179,7 @@ COMPONENT_LIBS += \
storagecomps \
rdf \
windowds \
diskspacewatcher \
$(NULL)
ifdef BUILD_CTYPES

View File

@ -242,6 +242,7 @@
MODULE(jsdebugger) \
PEERCONNECTION_MODULE \
GIO_MODULE \
MODULE(DiskSpaceWatcherModule) \
/* end of list */
#define MODULE(_name) \