mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 853350 - Implement a notification system to monitor disk space r=bent
This commit is contained in:
parent
49d488cbaa
commit
fbe1832880
@ -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);
|
||||
|
@ -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
|
||||
|
16
hal/Hal.cpp
16
hal/Hal.cpp
@ -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
|
||||
|
24
hal/Hal.h
24
hal/Hal.h
@ -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
|
||||
|
||||
|
@ -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 #}
|
||||
|
||||
|
19
hal/fallback/FallbackDiskSpaceWatcher.cpp
Normal file
19
hal/fallback/FallbackDiskSpaceWatcher.cpp
Normal 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
|
309
hal/gonk/GonkDiskSpaceWatcher.cpp
Normal file
309
hal/gonk/GonkDiskSpaceWatcher.cpp
Normal 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
118
hal/gonk/fanotify.h
Normal 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 */
|
@ -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
|
||||
|
153
toolkit/components/diskspacewatcher/DiskSpaceWatcher.cpp
Normal file
153
toolkit/components/diskspacewatcher/DiskSpaceWatcher.cpp
Normal 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;
|
32
toolkit/components/diskspacewatcher/DiskSpaceWatcher.h
Normal file
32
toolkit/components/diskspacewatcher/DiskSpaceWatcher.h
Normal 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__
|
23
toolkit/components/diskspacewatcher/Makefile.in
Normal file
23
toolkit/components/diskspacewatcher/Makefile.in
Normal 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
|
16
toolkit/components/diskspacewatcher/moz.build
Normal file
16
toolkit/components/diskspacewatcher/moz.build
Normal 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'
|
19
toolkit/components/diskspacewatcher/nsIDiskSpaceWatcher.idl
Normal file
19
toolkit/components/diskspacewatcher/nsIDiskSpaceWatcher.idl
Normal 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"
|
||||
%}
|
@ -16,6 +16,7 @@ PARALLEL_DIRS += [
|
||||
'console',
|
||||
'contentprefs',
|
||||
'cookie',
|
||||
'diskspacewatcher',
|
||||
'downloads',
|
||||
'exthelper',
|
||||
'filepicker',
|
||||
|
@ -179,6 +179,7 @@ COMPONENT_LIBS += \
|
||||
storagecomps \
|
||||
rdf \
|
||||
windowds \
|
||||
diskspacewatcher \
|
||||
$(NULL)
|
||||
|
||||
ifdef BUILD_CTYPES
|
||||
|
@ -242,6 +242,7 @@
|
||||
MODULE(jsdebugger) \
|
||||
PEERCONNECTION_MODULE \
|
||||
GIO_MODULE \
|
||||
MODULE(DiskSpaceWatcherModule) \
|
||||
/* end of list */
|
||||
|
||||
#define MODULE(_name) \
|
||||
|
Loading…
Reference in New Issue
Block a user