mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 785124 - Pt 1 - Add VolumeMountLock which allows SDCard to be locked. r=dougt
From 8e39b8e5f3ab7e6344b0a8a5eeabdcf672de8fb4 Mon Sep 17 00:00:00 2001 --- dom/ipc/ContentChild.cpp | 18 +++- dom/ipc/ContentChild.h | 5 +- dom/ipc/ContentParent.cpp | 22 +++- dom/ipc/ContentParent.h | 2 + dom/ipc/PContent.ipdl | 6 +- dom/system/gonk/AutoMounter.cpp | 19 +++- dom/system/gonk/Makefile.in | 4 +- dom/system/gonk/Volume.cpp | 62 ++++++++++- dom/system/gonk/Volume.h | 11 +- dom/system/gonk/VolumeServiceIOThread.cpp | 11 +- dom/system/gonk/VolumeServiceIOThread.h | 7 +- dom/system/gonk/nsIVolume.idl | 21 +++- dom/system/gonk/nsIVolumeMountLock.idl | 12 +++ dom/system/gonk/nsIVolumeService.idl | 9 +- dom/system/gonk/nsVolume.cpp | 96 ++++++++++++++++- dom/system/gonk/nsVolume.h | 43 ++++++-- dom/system/gonk/nsVolumeMountLock.cpp | 157 +++++++++++++++++++++++++++ dom/system/gonk/nsVolumeMountLock.h | 55 ++++++++++ dom/system/gonk/nsVolumeService.cpp | 168 +++++++++++++++++++++++------ dom/system/gonk/nsVolumeService.h | 20 +++- layout/build/nsLayoutModule.cpp | 5 +- layout/build/nsLayoutStatics.cpp | 9 ++ 22 files changed, 684 insertions(+), 78 deletions(-) create mode 100644 dom/system/gonk/nsIVolumeMountLock.idl create mode 100644 dom/system/gonk/nsVolumeMountLock.cpp create mode 100644 dom/system/gonk/nsVolumeMountLock.h
This commit is contained in:
parent
bb9ec533eb
commit
78d09607c8
@ -30,6 +30,7 @@
|
||||
#include "mozilla/layers/PCompositorChild.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIMemoryInfoDumper.h"
|
||||
@ -101,6 +102,7 @@
|
||||
#include "AudioChannelService.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::docshell;
|
||||
using namespace mozilla::dom::bluetooth;
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
@ -1083,14 +1085,24 @@ ContentChild::RecvFilePathUpdate(const nsString& type, const nsString& path, con
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvFileSystemUpdate(const nsString& aFsName, const nsString& aName, const int32_t &aState)
|
||||
ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
|
||||
const nsString& aName,
|
||||
const int32_t& aState,
|
||||
const int32_t& aMountGeneration)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aName, aState);
|
||||
nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aName, aState,
|
||||
aMountGeneration);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
nsString stateStr(NS_ConvertUTF8toUTF16(volume->StateStr()));
|
||||
obs->NotifyObservers(volume, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
#else
|
||||
// Remove warnings about unused arguments
|
||||
unused << aFsName;
|
||||
unused << aName;
|
||||
unused << aState;
|
||||
unused << aMountGeneration;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -183,7 +183,10 @@ public:
|
||||
virtual bool RecvLastPrivateDocShellDestroyed();
|
||||
|
||||
virtual bool RecvFilePathUpdate(const nsString& type, const nsString& path, const nsCString& reason);
|
||||
virtual bool RecvFileSystemUpdate(const nsString& aFsName, const nsString& aName, const int32_t& aState);
|
||||
virtual bool RecvFileSystemUpdate(const nsString& aFsName,
|
||||
const nsString& aName,
|
||||
const int32_t& aState,
|
||||
const int32_t& aMountGeneration);
|
||||
|
||||
#ifdef ANDROID
|
||||
gfxIntSize GetScreenSize() { return mScreenSize; }
|
||||
|
@ -102,6 +102,7 @@
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsIVolume.h"
|
||||
#include "nsIVolumeService.h"
|
||||
using namespace mozilla::system;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_BT
|
||||
@ -235,9 +236,9 @@ ContentParent::MaybeTakePreallocatedAppProcess()
|
||||
/*static*/ void
|
||||
ContentParent::FirstIdle(void)
|
||||
{
|
||||
// The parent has gone idle for the first time. This would be a good
|
||||
// time to preallocate an app process.
|
||||
ScheduleDelayedPreallocateAppProcess();
|
||||
// The parent has gone idle for the first time. This would be a good
|
||||
// time to preallocate an app process.
|
||||
ScheduleDelayedPreallocateAppProcess();
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
@ -1133,6 +1134,22 @@ ContentParent::RecvAudioChannelUnregisterType(const AudioChannelType& aType)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
|
||||
if (vs) {
|
||||
vs->BroadcastVolume(aVolumeName);
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
NS_WARNING("ContentParent::RecvBroadcastVolume shouldn't be called when MOZ_WIDGET_GONK is not defined");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(ContentParent,
|
||||
nsIObserver,
|
||||
nsIThreadObserver,
|
||||
@ -1212,12 +1229,15 @@ ContentParent::Observe(nsISupports* aSubject,
|
||||
nsString volName;
|
||||
nsString mountPoint;
|
||||
int32_t state;
|
||||
int32_t mountGeneration;
|
||||
|
||||
vol->GetName(volName);
|
||||
vol->GetMountPoint(mountPoint);
|
||||
vol->GetState(&state);
|
||||
vol->GetMountGeneration(&mountGeneration);
|
||||
|
||||
unused << SendFileSystemUpdate(volName, mountPoint, state);
|
||||
unused << SendFileSystemUpdate(volName, mountPoint, state,
|
||||
mountGeneration);
|
||||
}
|
||||
#endif
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -326,6 +326,8 @@ private:
|
||||
virtual bool RecvAudioChannelRegisterType(const AudioChannelType& aType);
|
||||
virtual bool RecvAudioChannelUnregisterType(const AudioChannelType& aType);
|
||||
|
||||
virtual bool RecvBroadcastVolume(const nsString& aVolumeName);
|
||||
|
||||
virtual void ProcessingError(Result what) MOZ_OVERRIDE;
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
|
@ -327,7 +327,8 @@ child:
|
||||
|
||||
FilePathUpdate(nsString type, nsString filepath, nsCString reasons);
|
||||
|
||||
FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState);
|
||||
FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState,
|
||||
int32_t mountGeneration);
|
||||
|
||||
parent:
|
||||
/**
|
||||
@ -439,6 +440,9 @@ parent:
|
||||
async AudioChannelRegisterType(AudioChannelType aType);
|
||||
async AudioChannelUnregisterType(AudioChannelType aType);
|
||||
|
||||
// get nsIVolumeService to broadcast volume information
|
||||
async BroadcastVolume(nsString volumeName);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData);
|
||||
};
|
||||
|
@ -398,8 +398,16 @@ AutoMounter::UpdateState()
|
||||
RefPtr<Volume> vol = mAutoVolume[volIndex];
|
||||
Volume::STATE volState = vol->State();
|
||||
|
||||
LOG("UpdateState: Volume %s is %s and %s", vol->NameStr(), vol->StateStr(),
|
||||
vol->MediaPresent() ? "inserted" : "missing");
|
||||
if (vol->State() == nsIVolume::STATE_MOUNTED) {
|
||||
LOG("UpdateState: Volume %s is %s and %s @ %s gen %d locked %d",
|
||||
vol->NameStr(), vol->StateStr(),
|
||||
vol->MediaPresent() ? "inserted" : "missing",
|
||||
vol->MountPoint().get(), vol->MountGeneration(),
|
||||
(int)vol->IsMountLocked());
|
||||
} else {
|
||||
LOG("UpdateState: Volume %s is %s and %s", vol->NameStr(), vol->StateStr(),
|
||||
vol->MediaPresent() ? "inserted" : "missing");
|
||||
}
|
||||
if (!vol->MediaPresent()) {
|
||||
// No media - nothing we can do
|
||||
continue;
|
||||
@ -409,17 +417,24 @@ AutoMounter::UpdateState()
|
||||
// We're going to try to unmount and share the volumes
|
||||
switch (volState) {
|
||||
case nsIVolume::STATE_MOUNTED: {
|
||||
if (vol->IsMountLocked()) {
|
||||
// The volume is currently locked, so leave it in the mounted
|
||||
// state.
|
||||
DBG("UpdateState: Mounted volume %s is locked, leaving",
|
||||
vol->NameStr());
|
||||
break;
|
||||
}
|
||||
// Volume is mounted, we need to unmount before
|
||||
// we can share.
|
||||
DBG("UpdateState: Unmounting %s", vol->NameStr());
|
||||
vol->StartUnmount(mResponseCallback);
|
||||
return;
|
||||
return; // UpdateState will be called again when the Unmount command completes
|
||||
}
|
||||
case nsIVolume::STATE_IDLE: {
|
||||
// Volume is unmounted. We can go ahead and share.
|
||||
DBG("UpdateState: Sharing %s", vol->NameStr());
|
||||
vol->StartShare(mResponseCallback);
|
||||
return;
|
||||
return; // UpdateState will be called again when the Share command completes
|
||||
}
|
||||
default: {
|
||||
// Not in a state that we can do anything about.
|
||||
@ -433,14 +448,14 @@ AutoMounter::UpdateState()
|
||||
// Volume is shared. We can go ahead and unshare.
|
||||
DBG("UpdateState: Unsharing %s", vol->NameStr());
|
||||
vol->StartUnshare(mResponseCallback);
|
||||
return;
|
||||
return; // UpdateState will be called again when the Unshare command completes
|
||||
}
|
||||
case nsIVolume::STATE_IDLE: {
|
||||
// Volume is unmounted, try to mount.
|
||||
|
||||
DBG("UpdateState: Mounting %s", vol->NameStr());
|
||||
vol->StartMount(mResponseCallback);
|
||||
return;
|
||||
return; // UpdateState will be called again when Mount command completes
|
||||
}
|
||||
default: {
|
||||
// Not in a state that we can do anything about.
|
||||
|
@ -39,6 +39,7 @@ XPIDLSRCS = \
|
||||
nsINetworkManager.idl \
|
||||
nsIRadioInterfaceLayer.idl \
|
||||
nsIVolume.idl \
|
||||
nsIVolumeMountLock.idl \
|
||||
nsIVolumeService.idl \
|
||||
nsIVolumeStat.idl \
|
||||
nsIWorkerHolder.idl \
|
||||
@ -63,6 +64,7 @@ CPPSRCS += \
|
||||
GonkGPSGeolocationProvider.cpp \
|
||||
AudioChannelManager.cpp \
|
||||
nsVolume.cpp \
|
||||
nsVolumeMountLock.cpp \
|
||||
nsVolumeService.cpp \
|
||||
nsVolumeStat.cpp \
|
||||
TimeZoneSettingObserver.cpp \
|
||||
@ -75,8 +77,8 @@ CPPSRCS += \
|
||||
# for our local copy of AudioSystem.h
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src
|
||||
EXPORTS = \
|
||||
nsVolume.h \
|
||||
GonkGPSGeolocationProvider.h \
|
||||
nsVolume.h \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -16,12 +16,48 @@ namespace system {
|
||||
|
||||
Volume::EventObserverList Volume::mEventObserverList;
|
||||
|
||||
// We have a feature where volumes can be locked when mounted. This
|
||||
// is used to prevent a volume from being shared with the PC while
|
||||
// it is actively being used (say for storing an update image)
|
||||
//
|
||||
// We use WakeLocks (a poor choice of name, but it does what we want)
|
||||
// from the PowerManagerService to determine when we're locked.
|
||||
// In particular we'll create a wakelock called volume-NAME-GENERATION
|
||||
// (where NAME is the volume name, and GENERATION is its generation
|
||||
// number), and if this wakelock is locked, then we'll prevent a volume
|
||||
// from being shared.
|
||||
//
|
||||
// Implementation Details:
|
||||
//
|
||||
// Since the AutoMounter can only control when something gets mounted
|
||||
// and not when it gets unmounted (for example: a user pulls the SDCard)
|
||||
// and because Volume and nsVolume data structures are maintained on
|
||||
// separate threads, we have the potential for some race conditions.
|
||||
// We eliminate the race conditions by introducing the concept of a
|
||||
// generation number. Every time a volume transitions to the Mounted
|
||||
// state, it gets assigned a new generation number. Whenever the state
|
||||
// of a Volume changes, we send the updated state and current generation
|
||||
// number to the main thread where it gets updated in the nsVolume.
|
||||
//
|
||||
// Since WakeLocks can only be queried from the main-thread, the
|
||||
// nsVolumeService looks for WakeLock status changes, and forwards
|
||||
// the results to the IOThread.
|
||||
//
|
||||
// If the Volume (IOThread) recieves a volume update where the generation
|
||||
// number mismatches, then the update is simply ignored.
|
||||
//
|
||||
// When a Volume (IOThread) initially becomes mounted, we assume it to
|
||||
// be locked until we get our first update from nsVolume (MainThread).
|
||||
static int32_t sMountGeneration = 0;
|
||||
|
||||
// We don't get media inserted/removed events at startup. So we
|
||||
// assume it's present, and we'll be told that it's missing.
|
||||
Volume::Volume(const nsCSubstring &aName)
|
||||
: mMediaPresent(true),
|
||||
mState(nsIVolume::STATE_INIT),
|
||||
mName(aName)
|
||||
mName(aName),
|
||||
mMountGeneration(-1),
|
||||
mMountLocked(true) // Needs to agree with nsVolume::nsVolume
|
||||
{
|
||||
DBG("Volume %s: created", NameStr());
|
||||
}
|
||||
@ -68,9 +104,12 @@ Volume::SetState(Volume::STATE aNewState)
|
||||
return;
|
||||
}
|
||||
if (aNewState == nsIVolume::STATE_MOUNTED) {
|
||||
LOG("Volume %s: changing state from %s to %s @ '%s' (%d observers)",
|
||||
mMountGeneration = ++sMountGeneration;
|
||||
LOG("Volume %s: changing state from %s to %s @ '%s' (%d observers) "
|
||||
"mountGeneration = %d, locked = %d",
|
||||
NameStr(), StateStr(mState),
|
||||
StateStr(aNewState), mMountPoint.get(), mEventObserverList.Length());
|
||||
StateStr(aNewState), mMountPoint.get(), mEventObserverList.Length(),
|
||||
mMountGeneration, (int)mMountLocked);
|
||||
} else {
|
||||
LOG("Volume %s: changing state from %s to %s (%d observers)",
|
||||
NameStr(), StateStr(mState),
|
||||
@ -149,6 +188,23 @@ Volume::UnregisterObserver(Volume::EventObserver *aObserver)
|
||||
mEventObserverList.RemoveObserver(aObserver);
|
||||
}
|
||||
|
||||
//static
|
||||
void
|
||||
Volume::UpdateMountLock(const nsACString &aVolumeName,
|
||||
const int32_t &aMountGeneration,
|
||||
const bool &aMountLocked)
|
||||
{
|
||||
RefPtr<Volume> vol = VolumeManager::FindVolumeByName(aVolumeName);
|
||||
if (!vol || (vol->mMountGeneration != aMountGeneration)) {
|
||||
return;
|
||||
}
|
||||
if (vol->mMountLocked != aMountLocked) {
|
||||
vol->mMountLocked = aMountLocked;
|
||||
DBG("Volume::UpdateMountLock for '%s' to %d\n", vol->NameStr(), (int)aMountLocked);
|
||||
mEventObserverList.Broadcast(vol);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Volume::HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer &aTokenizer)
|
||||
{
|
||||
|
@ -42,7 +42,9 @@ public:
|
||||
// (i.e. path that leads to the files stored on the volume).
|
||||
const nsCString &MountPoint() const { return mMountPoint; }
|
||||
|
||||
bool MediaPresent() const { return mMediaPresent; }
|
||||
int32_t MountGeneration() const { return mMountGeneration; }
|
||||
bool IsMountLocked() const { return mMountLocked; }
|
||||
bool MediaPresent() const { return mMediaPresent; }
|
||||
|
||||
typedef mozilla::Observer<Volume *> EventObserver;
|
||||
typedef mozilla::ObserverList<Volume *> EventObserverList;
|
||||
@ -53,6 +55,7 @@ public:
|
||||
|
||||
private:
|
||||
friend class AutoMounter; // Calls StartXxx
|
||||
friend class nsVolume; // Calls UpdateMountLock
|
||||
friend class VolumeManager; // Calls HandleVoldResponse
|
||||
friend class VolumeListCallback; // Calls SetMountPoint, SetState
|
||||
|
||||
@ -71,10 +74,16 @@ private:
|
||||
|
||||
void HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer &aTokenizer);
|
||||
|
||||
static void UpdateMountLock(const nsACString &aVolumeName,
|
||||
const int32_t &aMountGeneration,
|
||||
const bool &aMountLocked);
|
||||
|
||||
bool mMediaPresent;
|
||||
STATE mState;
|
||||
const nsCString mName;
|
||||
nsCString mMountPoint;
|
||||
int32_t mMountGeneration;
|
||||
bool mMountLocked;
|
||||
|
||||
static EventObserverList mEventObserverList;
|
||||
};
|
||||
|
@ -12,7 +12,8 @@
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
VolumeServiceIOThread::VolumeServiceIOThread()
|
||||
VolumeServiceIOThread::VolumeServiceIOThread(nsVolumeService *aVolumeService)
|
||||
: mVolumeService(aVolumeService)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
|
||||
@ -35,7 +36,7 @@ VolumeServiceIOThread::Notify(Volume * const &aVolume)
|
||||
if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
|
||||
return;
|
||||
}
|
||||
nsVolumeService::UpdateVolumeIOThread(aVolume);
|
||||
mVolumeService->UpdateVolumeIOThread(aVolume);
|
||||
}
|
||||
|
||||
void
|
||||
@ -57,17 +58,17 @@ VolumeServiceIOThread::UpdateAllVolumes()
|
||||
|
||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
|
||||
nsVolumeService::UpdateVolumeIOThread(vol);
|
||||
mVolumeService->UpdateVolumeIOThread(vol);
|
||||
}
|
||||
}
|
||||
|
||||
static RefPtr<VolumeServiceIOThread> sVolumeServiceIOThread;
|
||||
static StaticRefPtr<VolumeServiceIOThread> sVolumeServiceIOThread;
|
||||
|
||||
void
|
||||
InitVolumeServiceIOThread()
|
||||
InitVolumeServiceIOThread(nsVolumeService * const &aVolumeService)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
sVolumeServiceIOThread = new VolumeServiceIOThread();
|
||||
sVolumeServiceIOThread = new VolumeServiceIOThread(aVolumeService);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -12,6 +12,8 @@
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
class nsVolumeService;
|
||||
|
||||
/***************************************************************************
|
||||
* The nsVolumeServiceIOThread is a companion class to the nsVolumeService
|
||||
* class, but whose methods are called from IOThread.
|
||||
@ -21,7 +23,7 @@ class VolumeServiceIOThread : public VolumeManager::StateObserver,
|
||||
public RefCounted<VolumeServiceIOThread>
|
||||
{
|
||||
public:
|
||||
VolumeServiceIOThread();
|
||||
VolumeServiceIOThread(nsVolumeService *aVolumeService);
|
||||
~VolumeServiceIOThread();
|
||||
|
||||
private:
|
||||
@ -30,9 +32,10 @@ private:
|
||||
virtual void Notify(const VolumeManager::StateChangedEvent &aEvent);
|
||||
virtual void Notify(Volume * const &aVolume);
|
||||
|
||||
RefPtr<nsVolumeService> mVolumeService;
|
||||
};
|
||||
|
||||
void InitVolumeServiceIOThread();
|
||||
void InitVolumeServiceIOThread(nsVolumeService * const &aVolumeService);
|
||||
void ShutdownVolumeServiceIOThread();
|
||||
|
||||
} // system
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIVolumeStat.idl"
|
||||
|
||||
[scriptable, uuid(3c9cae8d-9da2-4aa1-b8bf-4db8c8620808)]
|
||||
[scriptable, uuid(1134f267-7b81-42f2-b64a-6edb91286576)]
|
||||
interface nsIVolume : nsISupports
|
||||
{
|
||||
// These MUST match the states from android's system/vold/Volume.h header
|
||||
@ -20,12 +20,31 @@ interface nsIVolume : nsISupports
|
||||
const long STATE_SHARED = 7;
|
||||
const long STATE_SHAREDMNT = 8;
|
||||
|
||||
// The name of the volume. Often there is only one volume, called sdcard.
|
||||
// But some phones support multiple volumes.
|
||||
readonly attribute DOMString name;
|
||||
|
||||
// The mount point is the path on the system where the volume is mounted
|
||||
// and is only valid when state == STATE_MOUNTED.
|
||||
readonly attribute DOMString mountPoint;
|
||||
|
||||
// Reflects the current state of the volume, using STATE_xxx constants
|
||||
// from above.
|
||||
readonly attribute long state;
|
||||
|
||||
// mountGeneration is a unique number which is used distinguish between
|
||||
// periods of time that a volume is in the mounted state. Each time a
|
||||
// volume transitions to the mounted state, the mountGeneration will
|
||||
// be different from the last time it transitioned to the mounted state.
|
||||
readonly attribute long mountGeneration;
|
||||
|
||||
// While a volume is mounted, it can be locked, preventing it from being
|
||||
// shared with the PC. To lock a volume, acquire an nsIDOMMozWakeLock
|
||||
// using the name of this attribute. Note that mountLockName changes
|
||||
// every time the mountGeneration changes, so you'll need to reacquire
|
||||
// the wakelock every time the volume becomes mounted.
|
||||
readonly attribute DOMString mountLockName;
|
||||
|
||||
nsIVolumeStat getStats();
|
||||
};
|
||||
|
||||
|
12
dom/system/gonk/nsIVolumeMountLock.idl
Normal file
12
dom/system/gonk/nsIVolumeMountLock.idl
Normal file
@ -0,0 +1,12 @@
|
||||
/* 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(44449f34-5ca1-4aff-bce6-22c79263de24)]
|
||||
interface nsIVolumeMountLock : nsISupports
|
||||
{
|
||||
void unlock();
|
||||
};
|
||||
|
@ -4,16 +4,21 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIVolume.idl"
|
||||
#include "nsIVolumeMountLock.idl"
|
||||
|
||||
[scriptable, uuid(b31bd379-4bd2-4189-a85b-c0927a266a85)]
|
||||
[scriptable, uuid(597403c6-5ba4-4e7b-b3f4-ed3f05f775d8)]
|
||||
interface nsIVolumeService : nsISupports
|
||||
{
|
||||
nsIVolume getVolumeByName(in DOMString volName);
|
||||
nsIVolume getVolumeByPath(in DOMString path);
|
||||
|
||||
void BroadcastVolume(in DOMString volName);
|
||||
|
||||
nsIVolumeMountLock createMountLock(in DOMString volName);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_VOLUMESERVICE_CID \
|
||||
{0xb31bd379, 0x4bd2, 0x4189, {0xa8, 0x5b, 0xc0, 0x92, 0x7a, 0x26, 0x6a, 0x85}}
|
||||
{0x597403c6, 0x5ba4, 0x4e7b, {0xb3, 0xf4, 0xed, 0x3f, 0x05, 0xf7, 0x75, 0xd8}}
|
||||
#define NS_VOLUMESERVICE_CONTRACTID "@mozilla.org/telephony/volume-service;1"
|
||||
%}
|
||||
|
@ -3,11 +3,20 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsVolume.h"
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsIVolume.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsVolumeStat.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "Volume.h"
|
||||
|
||||
#define VOLUME_MANAGER_LOG_TAG "nsVolume"
|
||||
#include "VolumeManagerLog.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
@ -34,7 +43,9 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsVolume, nsIVolume)
|
||||
nsVolume::nsVolume(const Volume *aVolume)
|
||||
: mName(NS_ConvertUTF8toUTF16(aVolume->Name())),
|
||||
mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
|
||||
mState(aVolume->State())
|
||||
mState(aVolume->State()),
|
||||
mMountGeneration(aVolume->MountGeneration()),
|
||||
mMountLocked(aVolume->IsMountLocked())
|
||||
{
|
||||
}
|
||||
|
||||
@ -44,6 +55,20 @@ NS_IMETHODIMP nsVolume::GetName(nsAString &aName)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolume::GetMountGeneration(int32_t *aMountGeneration)
|
||||
{
|
||||
*aMountGeneration = mMountGeneration;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolume::GetMountLockName(nsAString &aMountLockName)
|
||||
{
|
||||
aMountLockName = NS_LITERAL_STRING("volume-") + Name();
|
||||
aMountLockName.AppendPrintf("-%d", mMountGeneration);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolume::GetMountPoint(nsAString &aMountPoint)
|
||||
{
|
||||
aMountPoint = mMountPoint;
|
||||
@ -66,5 +91,74 @@ NS_IMETHODIMP nsVolume::GetStats(nsIVolumeStat **aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::LogState() const
|
||||
{
|
||||
if (mState == nsIVolume::STATE_MOUNTED) {
|
||||
LOG("nsVolume: %s state %s @ '%s' gen %d locked %d",
|
||||
NameStr(), StateStr(), MountPointStr(),
|
||||
MountGeneration(), (int)IsMountLocked());
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("nsVolume: %s state %s", NameStr(), StateStr());
|
||||
}
|
||||
|
||||
void nsVolume::Set(const nsVolume *aVolume)
|
||||
{
|
||||
mName = aVolume->mName;
|
||||
mMountPoint = aVolume->mMountPoint;
|
||||
mState = aVolume->mState;
|
||||
|
||||
if (mState != nsIVolume::STATE_MOUNTED) {
|
||||
// Since we're not in the mounted state, we need to
|
||||
// forgot whatever mount generation we may have had.
|
||||
mMountGeneration = -1;
|
||||
return;
|
||||
}
|
||||
if (mMountGeneration == aVolume->mMountGeneration) {
|
||||
// No change in mount generation, nothing else to do
|
||||
return;
|
||||
}
|
||||
|
||||
mMountGeneration = aVolume->mMountGeneration;
|
||||
|
||||
// Notify the Volume on IOThread whether the volume is locked or not.
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
if (!pmService) {
|
||||
return;
|
||||
}
|
||||
nsString mountLockName;
|
||||
GetMountLockName(mountLockName);
|
||||
nsString mountLockState;
|
||||
pmService->GetWakeLockState(mountLockName, mountLockState);
|
||||
UpdateMountLock(mountLockState);
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::UpdateMountLock(const nsAString &aMountLockState)
|
||||
{
|
||||
// There are 3 states, unlocked, locked-background, and locked-foreground
|
||||
// I figured it was easier to use negtive logic and compare for unlocked.
|
||||
UpdateMountLock(!aMountLockState.EqualsLiteral("unlocked"));
|
||||
}
|
||||
|
||||
void
|
||||
nsVolume::UpdateMountLock(bool aMountLocked)
|
||||
{
|
||||
if (aMountLocked == mMountLocked) {
|
||||
return;
|
||||
}
|
||||
// The locked/unlocked state changed. Tell IOThread about it.
|
||||
mMountLocked = aMountLocked;
|
||||
LogState();
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(Volume::UpdateMountLock,
|
||||
NS_LossyConvertUTF16toASCII(Name()),
|
||||
MountGeneration(), aMountLocked));
|
||||
}
|
||||
|
||||
} // system
|
||||
} // mozilla
|
||||
|
@ -5,13 +5,16 @@
|
||||
#ifndef mozilla_system_nsvolume_h__
|
||||
#define mozilla_system_nsvolume_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIVolume.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
class Volume;
|
||||
class VolumeMountLock;
|
||||
|
||||
class nsVolume : public nsIVolume
|
||||
{
|
||||
@ -19,16 +22,27 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIVOLUME
|
||||
|
||||
// This constructor is used by the UpdateVolumeRunnable constructor
|
||||
nsVolume(const Volume *aVolume);
|
||||
|
||||
nsVolume(const nsAString &aName, const nsAString &aMountPoint, const int32_t &aState)
|
||||
: mName(aName), mMountPoint(aMountPoint), mState(aState)
|
||||
// This constructor is used by ContentChild::RecvFileSystemUpdate
|
||||
nsVolume(const nsAString &aName, const nsAString &aMountPoint,
|
||||
const int32_t &aState, const int32_t &aMountGeneration)
|
||||
: mName(aName),
|
||||
mMountPoint(aMountPoint),
|
||||
mState(aState),
|
||||
mMountGeneration(aMountGeneration),
|
||||
mMountLocked(false)
|
||||
{
|
||||
}
|
||||
|
||||
// This constructor is used by nsVolumeService::FindAddVolumeByName, and
|
||||
// will be followed shortly by a Set call.
|
||||
nsVolume(const nsAString &aName)
|
||||
: mName(aName),
|
||||
mState(STATE_INIT)
|
||||
mState(STATE_INIT),
|
||||
mMountGeneration(-1),
|
||||
mMountLocked(true) // Needs to agree with Volume::Volume
|
||||
{
|
||||
}
|
||||
|
||||
@ -36,19 +50,21 @@ public:
|
||||
{
|
||||
return mName.Equals(aVolume->mName)
|
||||
&& mMountPoint.Equals(aVolume->mMountPoint)
|
||||
&& (mState == aVolume->mState);
|
||||
&& (mState == aVolume->mState)
|
||||
&& (mMountGeneration == aVolume->mMountGeneration)
|
||||
&& (mMountLocked == aVolume->mMountLocked);
|
||||
}
|
||||
|
||||
void Set(const nsVolume *aVolume)
|
||||
{
|
||||
mName = aVolume->mName;
|
||||
mMountPoint = aVolume->mMountPoint;
|
||||
mState = aVolume->mState;
|
||||
}
|
||||
void Set(const nsVolume *aVolume);
|
||||
|
||||
void LogState() const;
|
||||
|
||||
const nsString &Name() const { return mName; }
|
||||
const char *NameStr() const { return NS_LossyConvertUTF16toASCII(mName).get(); }
|
||||
|
||||
int32_t MountGeneration() const { return mMountGeneration; }
|
||||
bool IsMountLocked() const { return mMountLocked; }
|
||||
|
||||
const nsString &MountPoint() const { return mMountPoint; }
|
||||
const char *MountPointStr() const { return NS_LossyConvertUTF16toASCII(mMountPoint).get(); }
|
||||
|
||||
@ -60,10 +76,15 @@ public:
|
||||
private:
|
||||
~nsVolume() {}
|
||||
|
||||
protected:
|
||||
friend class nsVolumeService; // Calls the following XxxMountLock functions
|
||||
void UpdateMountLock(const nsAString &aMountLockState);
|
||||
void UpdateMountLock(bool aMountLocked);
|
||||
|
||||
nsString mName;
|
||||
nsString mMountPoint;
|
||||
int32_t mState;
|
||||
int32_t mMountGeneration;
|
||||
bool mMountLocked;
|
||||
};
|
||||
|
||||
} // system
|
||||
|
157
dom/system/gonk/nsVolumeMountLock.cpp
Normal file
157
dom/system/gonk/nsVolumeMountLock.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/* 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 "nsVolumeMountLock.h"
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
#include "nsIVolume.h"
|
||||
#include "nsIVolumeService.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define VOLUME_MANAGER_LOG_TAG "nsVolumeMountLock"
|
||||
#include "VolumeManagerLog.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::services;
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsVolumeMountLock, nsIVolumeMountLock,
|
||||
nsIObserver, nsISupportsWeakReference)
|
||||
|
||||
// static
|
||||
already_AddRefed<nsVolumeMountLock>
|
||||
nsVolumeMountLock::Create(const nsAString &aVolumeName)
|
||||
{
|
||||
DBG("nsVolumeMountLock::Create called");
|
||||
|
||||
nsRefPtr<nsVolumeMountLock> mountLock = new nsVolumeMountLock(aVolumeName);
|
||||
nsresult rv = mountLock->Init();
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
return mountLock.forget();
|
||||
}
|
||||
|
||||
nsVolumeMountLock::nsVolumeMountLock(const nsAString &aVolumeName)
|
||||
: mVolumeName(aVolumeName),
|
||||
mVolumeGeneration(-1),
|
||||
mUnlocked(false)
|
||||
{
|
||||
}
|
||||
|
||||
//virtual
|
||||
nsVolumeMountLock::~nsVolumeMountLock()
|
||||
{
|
||||
Unlock();
|
||||
}
|
||||
|
||||
nsresult nsVolumeMountLock::Init()
|
||||
{
|
||||
LOG("nsVolumeMountLock created for '%s'",
|
||||
NS_LossyConvertUTF16toASCII(mVolumeName).get());
|
||||
|
||||
// Add ourselves as an Observer. It's important that we use a weak
|
||||
// reference here. If we used a strong reference, then that reference
|
||||
// would prevent this object from being destructed.
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, true /*weak*/);
|
||||
|
||||
// Request the sdcard info, so we know the state/generation without having
|
||||
// to wait for a state change.
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
ContentChild::GetSingleton()->SendBroadcastVolume(mVolumeName);
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE);
|
||||
|
||||
vs->BroadcastVolume(mVolumeName);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void unlock (); */
|
||||
NS_IMETHODIMP nsVolumeMountLock::Unlock()
|
||||
{
|
||||
LOG("nsVolumeMountLock released for '%s'",
|
||||
NS_LossyConvertUTF16toASCII(mVolumeName).get());
|
||||
|
||||
mUnlocked = true;
|
||||
mWakeLock = nullptr;
|
||||
|
||||
// While we don't really need to remove weak observers, we do so anyways
|
||||
// since it will reduce the number of times Observe gets called.
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolumeMountLock::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (mUnlocked) {
|
||||
// We're not locked anymore, so we don't need to look at the notifications.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
|
||||
if (!vol) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString volName;
|
||||
vol->GetName(volName);
|
||||
if (!volName.Equals(mVolumeName)) {
|
||||
return NS_OK;
|
||||
}
|
||||
int32_t state;
|
||||
nsresult rv = vol->GetState(&state);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (state != nsIVolume::STATE_MOUNTED) {
|
||||
mWakeLock = nullptr;
|
||||
mVolumeGeneration = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t mountGeneration;
|
||||
rv = vol->GetMountGeneration(&mountGeneration);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
DBG("nsVolumeMountLock::Observe mountGeneration = %d mVolumeGeneration = %d",
|
||||
mountGeneration, mVolumeGeneration);
|
||||
|
||||
if (mVolumeGeneration == mountGeneration) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The generation changed, which means that any wakelock we may have
|
||||
// been holding is now invalid. Grab a new wakelock for the new generation
|
||||
// number.
|
||||
|
||||
mWakeLock = nullptr;
|
||||
mVolumeGeneration = mountGeneration;
|
||||
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE(pmService, NS_ERROR_FAILURE);
|
||||
|
||||
nsString mountLockName;
|
||||
vol->GetMountLockName(mountLockName);
|
||||
rv = pmService->NewWakeLock(mountLockName, nullptr, getter_AddRefs(mWakeLock));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOG("nsVolumeMountLock acquired for '%s' gen %d",
|
||||
NS_LossyConvertUTF16toASCII(mVolumeName).get(), mVolumeGeneration);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace system
|
||||
} // namespace mozilla
|
53
dom/system/gonk/nsVolumeMountLock.h
Normal file
53
dom/system/gonk/nsVolumeMountLock.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* 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_system_nsvolumemountlock_h__
|
||||
#define mozilla_system_nsvolumemountlock_h__
|
||||
|
||||
#include "nsIVolumeMountLock.h"
|
||||
|
||||
#include "nsIDOMWakeLock.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
/* The VolumeMountLock is designed so that it can be used in the Child or
|
||||
* Parent process. While the VolumeMountLock object exists, then the
|
||||
* VolumeManager/AutoMounter will prevent a mounted volume from being
|
||||
* shared with the PC.
|
||||
*/
|
||||
|
||||
class nsVolumeMountLock MOZ_FINAL : public nsIVolumeMountLock,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIVOLUMEMOUNTLOCK
|
||||
|
||||
static already_AddRefed<nsVolumeMountLock> Create(const nsAString &volumeName);
|
||||
|
||||
const nsString &VolumeName() const { return mVolumeName; }
|
||||
|
||||
private:
|
||||
nsVolumeMountLock(const nsAString &aVolumeName);
|
||||
~nsVolumeMountLock();
|
||||
|
||||
nsresult Init();
|
||||
|
||||
nsString mVolumeName;
|
||||
int32_t mVolumeGeneration;
|
||||
nsCOMPtr<nsIDOMMozWakeLock> mWakeLock;
|
||||
bool mUnlocked;
|
||||
};
|
||||
|
||||
} // namespace system
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_system_nsvolumemountlock_h__
|
@ -11,8 +11,10 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDependentSubstring.h"
|
||||
#include "nsIDOMWakeLockListener.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsIVolume.h"
|
||||
#include "nsIVolumeService.h"
|
||||
@ -21,7 +23,9 @@
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsVolumeMountLock.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#define VOLUME_MANAGER_LOG_TAG "nsVolumeService"
|
||||
@ -29,30 +33,106 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::services;
|
||||
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsVolumeService, nsIVolumeService)
|
||||
NS_IMPL_ISUPPORTS2(nsVolumeService, nsIVolumeService, nsIDOMMozWakeLockListener)
|
||||
|
||||
StaticRefPtr<nsVolumeService> nsVolumeService::sSingleton;
|
||||
|
||||
// static
|
||||
already_AddRefed<nsVolumeService>
|
||||
nsVolumeService::GetSingleton()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sSingleton) {
|
||||
sSingleton = new nsVolumeService();
|
||||
}
|
||||
NS_ADDREF(sSingleton.get());
|
||||
return sSingleton.get();
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsVolumeService::Shutdown()
|
||||
{
|
||||
if (!sSingleton || (XRE_GetProcessType() != GeckoProcessType_Default)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
if (pmService) {
|
||||
pmService->RemoveWakeLockListener(sSingleton.get());
|
||||
}
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(ShutdownVolumeServiceIOThread));
|
||||
|
||||
sSingleton = nullptr;
|
||||
}
|
||||
|
||||
nsVolumeService::nsVolumeService()
|
||||
{
|
||||
sSingleton = this;
|
||||
|
||||
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||
// We don't support the nsIVolumeService in the child processes,
|
||||
// but we get constructed due to the way we're registered with
|
||||
// nsLayoutModule.cpp. So we exit early to reduce our memory
|
||||
// impact, and so that we don't start unnecessary IOThread stuff.
|
||||
return;
|
||||
}
|
||||
|
||||
// Startup the IOThread side of things. The actual volume changes
|
||||
// are captured by the IOThread and forwarded to main thread.
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(InitVolumeServiceIOThread));
|
||||
NewRunnableFunction(InitVolumeServiceIOThread, this));
|
||||
|
||||
nsCOMPtr<nsIPowerManagerService> pmService =
|
||||
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
||||
if (!pmService) {
|
||||
return;
|
||||
}
|
||||
pmService->AddWakeLockListener(this);
|
||||
}
|
||||
|
||||
nsVolumeService::~nsVolumeService()
|
||||
{
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(ShutdownVolumeServiceIOThread));
|
||||
}
|
||||
|
||||
/* nsIVolume getVolumeByName (in DOMString volName); */
|
||||
// Callback for nsIDOMMozWakeLockListener
|
||||
NS_IMETHODIMP nsVolumeService::Callback(const nsAString &aTopic, const nsAString &aState)
|
||||
{
|
||||
CheckMountLock(aTopic, aState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolumeService::BroadcastVolume(const nsAString &aVolName)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
|
||||
if (!vol) {
|
||||
ERR("BroadcastVolume: Unable to locate volume '%s'",
|
||||
NS_LossyConvertUTF16toASCII(aVolName).get());
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
NS_ENSURE_TRUE(obs, NS_NOINTERFACE);
|
||||
|
||||
DBG("nsVolumeService::BroadcastVolume for '%s'", vol->NameStr());
|
||||
nsString stateStr(NS_ConvertUTF8toUTF16(vol->StateStr()));
|
||||
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString &aVolName, nsIVolume **aResult)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
@ -67,7 +147,6 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString &aVolName, nsIVol
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIVolume getVolumeByPath (in DOMString path); */
|
||||
NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString &aPath, nsIVolume **aResult)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
@ -105,11 +184,41 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString &aPath, nsIVolume
|
||||
// In order to support queries by DeviceStorage and the updater, we will fabricate
|
||||
// a volume from the pathname, so that the caller can determine the volume size
|
||||
nsRefPtr<nsVolume> vol = new nsVolume(NS_LITERAL_STRING("fake"),
|
||||
aPath, nsIVolume::STATE_MOUNTED);
|
||||
aPath, nsIVolume::STATE_MOUNTED,
|
||||
-1 /*generation*/);
|
||||
NS_ADDREF(*aResult = vol);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsVolumeService::CreateMountLock(const nsAString &aVolumeName, nsIVolumeMountLock **aResult)
|
||||
{
|
||||
nsRefPtr<nsVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName);
|
||||
if (!mountLock) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
NS_ADDREF(*aResult = mountLock);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsVolumeService::CheckMountLock(const nsAString &aMountLockName,
|
||||
const nsAString &aMountLockState)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
|
||||
nsVolume::Array::index_type volIndex;
|
||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
|
||||
nsString mountLockName;
|
||||
vol->GetMountLockName(mountLockName);
|
||||
if (mountLockName.Equals(aMountLockName)) {
|
||||
vol->UpdateMountLock(aMountLockState);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString &aName)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
@ -126,6 +235,7 @@ already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString &aN
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//static
|
||||
already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString &aName)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
@ -157,13 +267,6 @@ void nsVolumeService::UpdateVolume(const nsVolume *aVolume)
|
||||
if (!obs) {
|
||||
return;
|
||||
}
|
||||
if (aVolume->State() == nsIVolume::STATE_MOUNTED) {
|
||||
LOG("UpdateVolume: '%s' state %s @ '%s'",
|
||||
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPointStr());
|
||||
} else {
|
||||
LOG("UpdateVolume: '%s' state %s",
|
||||
aVolume->NameStr(), aVolume->StateStr());
|
||||
}
|
||||
nsString stateStr(NS_ConvertUTF8toUTF16(vol->StateStr()));
|
||||
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
}
|
||||
@ -175,8 +278,9 @@ void nsVolumeService::UpdateVolume(const nsVolume *aVolume)
|
||||
class UpdateVolumeRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
UpdateVolumeRunnable(const Volume *aVolume)
|
||||
: mVolume(new nsVolume(aVolume))
|
||||
UpdateVolumeRunnable(nsVolumeService *aVolumeService, const Volume *aVolume)
|
||||
: mVolumeService(aVolumeService),
|
||||
mVolume(new nsVolume(aVolume))
|
||||
{
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
}
|
||||
@ -184,34 +288,29 @@ public:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DBG("UpdateVolumeRunnable::Run '%s' state %s",
|
||||
mVolume->NameStr(), mVolume->StateStr());
|
||||
DBG("UpdateVolumeRunnable::Run '%s' state %s gen %d locked %d",
|
||||
mVolume->NameStr(), mVolume->StateStr(), mVolume->MountGeneration(),
|
||||
(int)mVolume->IsMountLocked());
|
||||
|
||||
nsCOMPtr<nsIVolumeService> ivs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
|
||||
if (!ivs) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsVolumeService> vs(do_QueryInterface(ivs));
|
||||
if (!vs) {
|
||||
return NS_OK;
|
||||
}
|
||||
vs->UpdateVolume(mVolume);
|
||||
mVolumeService->UpdateVolume(mVolume);
|
||||
mVolumeService = NULL;
|
||||
mVolume = NULL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<nsVolume> mVolume;
|
||||
nsRefPtr<nsVolumeService> mVolumeService;
|
||||
nsRefPtr<nsVolume> mVolume;
|
||||
};
|
||||
|
||||
//static
|
||||
void nsVolumeService::UpdateVolumeIOThread(const Volume *aVolume)
|
||||
{
|
||||
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s'",
|
||||
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get());
|
||||
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d",
|
||||
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
|
||||
aVolume->MountGeneration(), (int)aVolume->IsMountLocked());
|
||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||
NS_DispatchToMainThread(new UpdateVolumeRunnable(aVolume));
|
||||
NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
|
||||
}
|
||||
|
||||
} // system
|
||||
} // mozilla
|
||||
} // namespace system
|
||||
} // namespace mozilla
|
||||
|
@ -5,7 +5,10 @@
|
||||
#ifndef mozilla_system_nsvolumeservice_h__
|
||||
#define mozilla_system_nsvolumeservice_h__
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMWakeLockListener.h"
|
||||
#include "nsIVolume.h"
|
||||
#include "nsIVolumeService.h"
|
||||
#include "nsVolume.h"
|
||||
@ -14,29 +17,41 @@
|
||||
namespace mozilla {
|
||||
namespace system {
|
||||
|
||||
class WakeLockCallback;
|
||||
|
||||
/***************************************************************************
|
||||
* The nsVolumeData class encapsulates the data that is updated/maintained
|
||||
* on the main thread in order to support the nsIVolume and nsIVolumeService
|
||||
* classes.
|
||||
*/
|
||||
|
||||
class nsVolumeService : public nsIVolumeService
|
||||
class nsVolumeService MOZ_FINAL : public nsIVolumeService,
|
||||
public nsIDOMMozWakeLockListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIVOLUMESERVICE
|
||||
NS_DECL_NSIDOMMOZWAKELOCKLISTENER
|
||||
|
||||
nsVolumeService();
|
||||
|
||||
static already_AddRefed<nsVolumeService> GetSingleton();
|
||||
//static nsVolumeService *GetSingleton();
|
||||
static void Shutdown();
|
||||
|
||||
void CheckMountLock(const nsAString &aMountLockName,
|
||||
const nsAString &aMountLockState);
|
||||
already_AddRefed<nsVolume> FindVolumeByName(const nsAString &aName);
|
||||
already_AddRefed<nsVolume> FindAddVolumeByName(const nsAString &aName);
|
||||
void UpdateVolume(const nsVolume *aVolume);
|
||||
static void UpdateVolumeIOThread(const Volume *aVolume);
|
||||
void UpdateVolumeIOThread(const Volume *aVolume);
|
||||
|
||||
private:
|
||||
~nsVolumeService();
|
||||
|
||||
nsVolume::Array mVolumeArray;
|
||||
nsVolume::Array mVolumeArray;
|
||||
|
||||
static StaticRefPtr<nsVolumeService> sSingleton;
|
||||
};
|
||||
|
||||
} // system
|
||||
|
@ -296,7 +296,6 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(BluetoothService,
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(AudioManager)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsVolumeService)
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G_FM
|
||||
@ -325,6 +324,10 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITimeService,
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIGeolocationProvider,
|
||||
GonkGPSGeolocationProvider::GetSingleton)
|
||||
// Since the nsVolumeService constructor calls into nsIPowerManagerService,
|
||||
// we need it to be constructed sometime after nsIPowerManagerService.
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsVolumeService,
|
||||
nsVolumeService::GetSingleton)
|
||||
#endif
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMediaManagerService,
|
||||
MediaManager::GetInstance)
|
||||
|
@ -87,6 +87,11 @@
|
||||
#include "AudioStream.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsVolumeService.h"
|
||||
using namespace mozilla::system;
|
||||
#endif
|
||||
|
||||
#include "nsError.h"
|
||||
|
||||
#include "nsCycleCollector.h"
|
||||
@ -349,6 +354,10 @@ nsLayoutStatics::Shutdown()
|
||||
WMFDecoder::UnloadDLLs();
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsVolumeService::Shutdown();
|
||||
#endif
|
||||
|
||||
nsCORSListenerProxy::Shutdown();
|
||||
|
||||
nsIPresShell::ReleaseStatics();
|
||||
|
Loading…
Reference in New Issue
Block a user