Bug 766324 - Add a volume IDL to make volumes scriptable r=qdot

This commit is contained in:
Dave Hylands 2012-07-16 12:38:18 -04:00
parent 177b3c4fdd
commit 6c49401e4b
21 changed files with 954 additions and 65 deletions

View File

@ -208,10 +208,11 @@ public:
mMode(AUTOMOUNTER_DISABLE)
{
VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
Volume::RegisterObserver(&mVolumeEventObserver);
for (size_t i = 0; i < NS_ARRAY_LENGTH(sAutoVolumeName); i++) {
RefPtr<Volume> vol = VolumeManager::FindAddVolumeByName(sAutoVolumeName[i]);
if (vol != NULL) {
if (vol) {
vol->RegisterObserver(&mVolumeEventObserver);
mAutoVolume.AppendElement(vol);
}
@ -228,6 +229,7 @@ public:
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
mAutoVolume[volIndex]->UnregisterObserver(&mVolumeEventObserver);
}
Volume::UnregisterObserver(&mVolumeEventObserver);
VolumeManager::UnregisterStateObserver(&mVolumeManagerStateObserver);
}
@ -377,14 +379,14 @@ AutoMounter::UpdateState()
if (tryToShare) {
// We're going to try to unmount and share the volumes
switch (volState) {
case Volume::STATE_MOUNTED: {
case nsIVolume::STATE_MOUNTED: {
// Volume is mounted, we need to unmount before
// we can share.
DBG("UpdateState: Unmounting %s", vol->NameStr());
vol->StartUnmount(mResponseCallback);
return;
}
case Volume::STATE_IDLE: {
case nsIVolume::STATE_IDLE: {
// Volume is unmounted. We can go ahead and share.
DBG("UpdateState: Sharing %s", vol->NameStr());
vol->StartShare(mResponseCallback);
@ -398,13 +400,13 @@ AutoMounter::UpdateState()
} else {
// We're going to try and unshare and remount the volumes
switch (volState) {
case Volume::STATE_SHARED: {
case nsIVolume::STATE_SHARED: {
// Volume is shared. We can go ahead and unshare.
DBG("UpdateState: Unsharing %s", vol->NameStr());
vol->StartUnshare(mResponseCallback);
return;
}
case Volume::STATE_IDLE: {
case nsIVolume::STATE_IDLE: {
// Volume is unmounted, try to mount.
DBG("UpdateState: Mounting %s", vol->NameStr());

View File

@ -27,6 +27,9 @@ XPIDLSRCS = \
nsIAudioManager.idl \
nsINetworkManager.idl \
nsIRadioInterfaceLayer.idl \
nsIVolume.idl \
nsIVolumeService.idl \
nsIVolumeStat.idl \
nsIWorkerHolder.idl \
$(NULL)
@ -45,9 +48,14 @@ CPPSRCS += \
AutoMounter.cpp \
AutoMounterSetting.cpp \
GonkGPSGeolocationProvider.cpp \
nsVolume.cpp \
nsVolumeService.cpp \
nsVolumeStat.cpp \
Volume.cpp \
VolumeCommand.cpp \
VolumeManager.cpp \
VolumeServiceIOThread.cpp \
VolumeServiceTest.cpp \
$(NULL)
# for our local copy of AudioSystem.h
LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src

View File

@ -6,6 +6,7 @@
#include "VolumeCommand.h"
#include "VolumeManager.h"
#include "VolumeManagerLog.h"
#include "nsIVolume.h"
#include "nsXULAppAPI.h"
#include <vold/ResponseCode.h>
@ -13,11 +14,13 @@
namespace mozilla {
namespace system {
Volume::EventObserverList Volume::mEventObserverList;
// 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(STATE_INIT),
mState(nsIVolume::STATE_INIT),
mName(aName)
{
DBG("Volume %s: created", NameStr());
@ -67,7 +70,7 @@ Volume::SetState(Volume::STATE aNewState)
NameStr(), StateStr(mState),
StateStr(aNewState), mEventObserverList.Length());
if (aNewState == STATE_NOMEDIA) {
if (aNewState == nsIVolume::STATE_NOMEDIA) {
// Cover the startup case where we don't get insertion/removal events
mMediaPresent = false;
}
@ -115,16 +118,22 @@ Volume::StartCommand(VolumeCommand *aCommand)
VolumeManager::PostCommand(aCommand);
}
//static
void
Volume::RegisterObserver(Volume::EventObserver *aObserver)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
mEventObserverList.AddObserver(aObserver);
// Send an initial event to the observer
aObserver->Notify(this);
// Send an initial event to the observer (for each volume)
size_t numVolumes = VolumeManager::NumVolumes();
for (size_t volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
aObserver->Notify(vol);
}
}
//static
void
Volume::UnregisterObserver(Volume::EventObserver *aObserver)
{

View File

@ -6,10 +6,11 @@
#define mozilla_system_volume_h__
#include "VolumeCommand.h"
#include "nsIVolume.h"
#include "nsString.h"
#include "nsWhitespaceTokenizer.h"
#include "mozilla/Observer.h"
#include "mozilla/RefPtr.h"
#include "nsWhitespaceTokenizer.h"
namespace mozilla {
namespace system {
@ -26,39 +27,11 @@ namespace system {
class Volume : public RefCounted<Volume>
{
public:
// These MUST match the states from android's system/vold/Volume.h header
enum STATE
{
STATE_INIT = -1,
STATE_NOMEDIA = 0,
STATE_IDLE = 1,
STATE_PENDING = 2,
STATE_CHECKING = 3,
STATE_MOUNTED = 4,
STATE_UNMOUNTING = 5,
STATE_FORMATTING = 6,
STATE_SHARED = 7,
STATE_SHAREDMNT = 8
};
Volume(const nsCSubstring &aVolumeName);
const char *StateStr(STATE aState) const
{
switch (aState) {
case STATE_INIT: return "Init";
case STATE_NOMEDIA: return "NoMedia";
case STATE_IDLE: return "Idle";
case STATE_PENDING: return "Pending";
case STATE_CHECKING: return "Checking";
case STATE_MOUNTED: return "Mounted";
case STATE_UNMOUNTING: return "Unmounting";
case STATE_FORMATTING: return "Formatting";
case STATE_SHARED: return "Shared";
case STATE_SHAREDMNT: return "Shared-Mounted";
}
return "???";
}
typedef long STATE; // States are now defined in nsIVolume.idl
static const char *StateStr(STATE aState) { return NS_VolumeStateStr(aState); }
const char *StateStr() const { return StateStr(mState); }
STATE State() const { return mState; }
@ -75,8 +48,8 @@ public:
typedef mozilla::ObserverList<Volume *> EventObserverList;
// NOTE: that observers must live in the IOThread.
void RegisterObserver(EventObserver *aObserver);
void UnregisterObserver(EventObserver *aObserver);
static void RegisterObserver(EventObserver *aObserver);
static void UnregisterObserver(EventObserver *aObserver);
private:
friend class AutoMounter; // Calls StartXxx
@ -102,7 +75,8 @@ private:
STATE mState;
const nsCString mName;
nsCString mMountPoint;
EventObserverList mEventObserverList;
static EventObserverList mEventObserverList;
};
} // system

View File

@ -2,22 +2,24 @@
* 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 "VolumeManager.h"
#include "Volume.h"
#include "VolumeCommand.h"
#include "VolumeManagerLog.h"
#include "VolumeServiceTest.h"
#include "nsWhitespaceTokenizer.h"
#include "nsXULAppAPI.h"
#include "base/message_loop.h"
#include "mozilla/Scoped.h"
#include <android/log.h>
#include <cutils/sockets.h>
#include <fcntl.h>
#include <sys/socket.h>
#include "base/message_loop.h"
#include "nsWhitespaceTokenizer.h"
#include "nsXULAppAPI.h"
#include "Volume.h"
#include "VolumeCommand.h"
#include "VolumeManager.h"
#include "VolumeManagerLog.h"
//using namespace mozilla::dom::gonk;
namespace mozilla {
namespace system {
@ -38,6 +40,24 @@ VolumeManager::~VolumeManager()
{
}
//static
size_t
VolumeManager::NumVolumes()
{
if (!sVolumeManager) {
return 0;
}
return sVolumeManager->mVolumeArray.Length();
}
//static
TemporaryRef<Volume>
VolumeManager::GetVolume(size_t aIndex)
{
MOZ_ASSERT(aIndex < NumVolumes());
return sVolumeManager->mVolumeArray[aIndex];
}
//static
VolumeManager::STATE
VolumeManager::State()
@ -94,11 +114,12 @@ VolumeManager::FindVolumeByName(const nsCSubstring &aName)
if (!sVolumeManager) {
return NULL;
}
for (VolumeArray::iterator volIter = sVolumeManager->mVolumeArray.begin();
volIter != sVolumeManager->mVolumeArray.end();
volIter++) {
if ((*volIter)->Name().Equals(aName)) {
return *volIter;
VolumeArray::size_type numVolumes = NumVolumes();
VolumeArray::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<Volume> vol = GetVolume(volIndex);
if (vol->Name().Equals(aName)) {
return vol;
}
}
return NULL;
@ -114,7 +135,7 @@ VolumeManager::FindAddVolumeByName(const nsCSubstring &aName)
}
// No volume found, create and add a new one.
vol = new Volume(aName);
sVolumeManager->mVolumeArray.push_back(vol);
sVolumeManager->mVolumeArray.AppendElement(vol);
return vol;
}
@ -394,6 +415,8 @@ InitVolumeManagerIOThread()
sVolumeManager = new VolumeManager();
VolumeManager::Start();
InitVolumeServiceTestIOThread();
}
static void
@ -424,6 +447,8 @@ InitVolumeManager()
void
ShutdownVolumeManager()
{
ShutdownVolumeServiceTest();
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(ShutdownVolumeManagerIOThread));

View File

@ -13,6 +13,7 @@
#include "mozilla/Observer.h"
#include "mozilla/RefPtr.h"
#include "nsString.h"
#include "nsTArray.h"
#include "Volume.h"
#include "VolumeCommand.h"
@ -77,7 +78,7 @@ class VolumeManager : public MessageLoopForIO::Watcher,
{
public:
typedef std::vector<RefPtr<Volume> > VolumeArray;
typedef nsTArray<RefPtr<Volume> > VolumeArray;
VolumeManager();
virtual ~VolumeManager();
@ -120,6 +121,8 @@ public:
static void Start();
static VolumeArray::size_type NumVolumes();
static TemporaryRef<Volume> GetVolume(VolumeArray::index_type aIndex);
static TemporaryRef<Volume> FindVolumeByName(const nsCSubstring &aName);
static TemporaryRef<Volume> FindAddVolumeByName(const nsCSubstring &aName);

View File

@ -7,12 +7,16 @@
#define USE_DEBUG 0
#if !defined(VOLUME_MANAGER_LOG_TAG)
#define VOLUME_MANAGER_LOG_TAG "VolumeManager"
#endif
#undef LOG
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "VolumeManager" , ## args)
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "VolumeManager" , ## args)
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, VOLUME_MANAGER_LOG_TAG, ## args)
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, VOLUME_MANAGER_LOG_TAG, ## args)
#if USE_DEBUG
#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, "VolumeManager" , ## args)
#define DBG(args...) __android_log_print(ANDROID_LOG_DEBUG, VOLUME_MANAGER_LOG_TAG, ## args)
#else
#define DBG(args...)
#endif

View File

@ -0,0 +1,78 @@
/* 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 "VolumeServiceIOThread.h"
#include "base/message_loop.h"
#include "nsVolumeService.h"
#include "nsXULAppAPI.h"
#include "Volume.h"
#include "VolumeManager.h"
namespace mozilla {
namespace system {
VolumeServiceIOThread::VolumeServiceIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
VolumeManager::RegisterStateObserver(this);
Volume::RegisterObserver(this);
UpdateAllVolumes();
}
VolumeServiceIOThread::~VolumeServiceIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
Volume::UnregisterObserver(this);
VolumeManager::UnregisterStateObserver(this);
}
void
VolumeServiceIOThread::Notify(Volume * const &aVolume)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
nsVolumeService::UpdateVolumeIOThread(aVolume);
}
void
VolumeServiceIOThread::Notify(const VolumeManager::StateChangedEvent &aEvent)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
UpdateAllVolumes();
}
void
VolumeServiceIOThread::UpdateAllVolumes()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
return;
}
VolumeManager::VolumeArray::size_type numVolumes = VolumeManager::NumVolumes();
VolumeManager::VolumeArray::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
nsVolumeService::UpdateVolumeIOThread(vol);
}
}
static RefPtr<VolumeServiceIOThread> sVolumeServiceIOThread;
void
InitVolumeServiceIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
sVolumeServiceIOThread = new VolumeServiceIOThread();
}
void
ShutdownVolumeServiceIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
sVolumeServiceIOThread = NULL;
}
} // system
} // mozilla

View File

@ -0,0 +1,41 @@
/* 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_volumeserviceiothread_h__
#define mozilla_system_volumeserviceiothread_h__
#include "Volume.h"
#include "VolumeManager.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
namespace system {
/***************************************************************************
* The nsVolumeServiceIOThread is a companion class to the nsVolumeService
* class, but whose methods are called from IOThread.
*/
class VolumeServiceIOThread : public VolumeManager::StateObserver,
public Volume::EventObserver,
public RefCounted<VolumeServiceIOThread>
{
public:
VolumeServiceIOThread();
~VolumeServiceIOThread();
private:
void UpdateAllVolumes();
virtual void Notify(const VolumeManager::StateChangedEvent &aEvent);
virtual void Notify(Volume * const &aVolume);
};
void InitVolumeServiceIOThread();
void ShutdownVolumeServiceIOThread();
} // system
} // mozilla
#endif // mozilla_system_volumeserviceiothread_h__

View File

@ -0,0 +1,201 @@
/* 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 "VolumeServiceTest.h"
#include "base/message_loop.h"
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "nsIVolume.h"
#include "nsIVolumeService.h"
#include "nsIVolumeStat.h"
#include "nsXULAppAPI.h"
#include "mozilla/Services.h"
#define VOLUME_MANAGER_LOG_TAG "VolumeServiceTest"
#include "VolumeManagerLog.h"
using namespace mozilla::services;
namespace mozilla {
namespace system {
#define TEST_NSVOLUME_OBSERVER 1
#if TEST_NSVOLUME_OBSERVER
/***************************************************************************
* A test class to verify that the Observer stuff is working properly.
*/
class VolumeTestObserver : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
VolumeTestObserver()
{
nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (!obs) {
return;
}
obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false);
}
~VolumeTestObserver()
{
nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (!obs) {
return;
}
obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
}
void LogVolume(nsIVolume *vol)
{
nsString volName;
nsString mountPoint;
PRInt32 volState;
vol->GetName(volName);
vol->GetMountPoint(mountPoint);
vol->GetState(&volState);
LOG(" Volume: %s MountPoint: %s State: %s",
NS_LossyConvertUTF16toASCII(volName).get(),
NS_LossyConvertUTF16toASCII(mountPoint).get(),
NS_VolumeStateStr(volState));
nsCOMPtr<nsIVolumeStat> stat;
nsresult rv = vol->GetStats(getter_AddRefs(stat));
if (NS_SUCCEEDED(rv)) {
PRInt64 totalBytes;
PRInt64 freeBytes;
stat->GetTotalBytes(&totalBytes);
stat->GetFreeBytes(&freeBytes);
LOG(" Total Space: %llu Mb Free Bytes: %llu Mb",
totalBytes / (1024LL * 1024LL), freeBytes / (1024LL * 1024LL));
}
else {
LOG(" Unable to retrieve stats");
}
}
};
static nsCOMPtr<VolumeTestObserver> sTestObserver;
NS_IMPL_ISUPPORTS1(VolumeTestObserver, nsIObserver)
NS_IMETHODIMP
VolumeTestObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
LOG("TestObserver: topic: %s", aTopic);
if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
return NS_OK;
}
nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
if (vol) {
LogVolume(vol);
}
// Since this observe method was called then we know that the service
// has been initialized so we can do the VolumeService tests.
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
if (!vs) {
ERR("do_GetService('%s') failed", NS_VOLUMESERVICE_CONTRACTID);
return NS_ERROR_FAILURE;
}
nsresult rv = vs->GetVolumeByName(NS_LITERAL_STRING("sdcard"), getter_AddRefs(vol));
if (NS_SUCCEEDED(rv)) {
LOG("GetVolumeByName( 'sdcard' ) succeeded (expected)");
LogVolume(vol);
} else {
ERR("GetVolumeByName( 'sdcard' ) failed (unexpected)");
}
rv = vs->GetVolumeByName(NS_LITERAL_STRING("foo"), getter_AddRefs(vol));
if (NS_SUCCEEDED(rv)) {
ERR("GetVolumeByName( 'foo' ) succeeded (unexpected)");
} else {
LOG("GetVolumeByName( 'foo' ) failed (expected)");
}
rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcard"), getter_AddRefs(vol));
if (NS_SUCCEEDED(rv)) {
LOG("GetVolumeByPath( '/mnt/sdcard' ) succeeded (expected)");
LogVolume(vol);
} else {
ERR("GetVolumeByPath( '/mnt/sdcard' ) failed (unexpected");
}
rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcard/foo"), getter_AddRefs(vol));
if (NS_SUCCEEDED(rv)) {
LOG("GetVolumeByPath( '/mnt/sdcard/foo' ) succeeded (expected)");
LogVolume(vol);
} else {
LOG("GetVolumeByPath( '/mnt/sdcard/foo' ) failed (unexpected)");
}
rv = vs->GetVolumeByPath(NS_LITERAL_STRING("/mnt/sdcardfoo"), getter_AddRefs(vol));
if (NS_SUCCEEDED(rv)) {
ERR("GetVolumeByPath( '/mnt/sdcardfoo' ) succeeded (unexpected)");
} else {
LOG("GetVolumeByPath( '/mnt/sdcardfoo' ) failed (expected)");
}
return NS_OK;
}
class InitVolumeServiceTestIO : public nsRunnable
{
public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
DBG("InitVolumeServiceTest called");
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
if (!vs) {
ERR("do_GetService('%s') failed", NS_VOLUMESERVICE_CONTRACTID);
return NS_ERROR_FAILURE;
}
sTestObserver = new VolumeTestObserver();
return NS_OK;
}
};
#endif // TEST_NSVOLUME_OBSERVER
void
InitVolumeServiceTestIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
#if TEST_NSVOLUME_OBSERVER
// Now that the volume manager is initialized we can go
// ahead and do our test (on main thread).
NS_DispatchToMainThread(new InitVolumeServiceTestIO());
#endif
}
void
ShutdownVolumeServiceTest()
{
#if TEST_NSVOLUME_OBSERVER
DBG("ShutdownVolumeServiceTestIOThread called");
sTestObserver = NULL;
#endif
}
} // system
} // mozilla

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/. */
#ifndef mozilla_system_volumeservicetest_h__
#define mozilla_system_volumeservicetest_h__
namespace mozilla {
namespace system {
void InitVolumeServiceTestIOThread();
void ShutdownVolumeServiceTest();
} // system
} // mozilla
#endif // mozilla_system_volumeservicetest_h__

View File

@ -0,0 +1,44 @@
/* 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"
#include "nsIVolumeStat.idl"
[scriptable, uuid(3c9cae8d-9da2-4aa1-b8bf-4db8c8620808)]
interface nsIVolume : nsISupports
{
// These MUST match the states from android's system/vold/Volume.h header
const long STATE_INIT = -1;
const long STATE_NOMEDIA = 0;
const long STATE_IDLE = 1;
const long STATE_PENDING = 2;
const long STATE_CHECKING = 3;
const long STATE_MOUNTED = 4;
const long STATE_UNMOUNTING = 5;
const long STATE_FORMATTING = 6;
const long STATE_SHARED = 7;
const long STATE_SHAREDMNT = 8;
readonly attribute DOMString name;
readonly attribute DOMString mountPoint;
readonly attribute long state;
nsIVolumeStat getStats();
};
%{C++
// For use with the ObserverService
#define NS_VOLUME_STATE_CHANGED "volume-state-changed"
namespace mozilla {
namespace system {
// Convert a state into a loggable/printable string.
const char *NS_VolumeStateStr(PRInt32 aState);
} // system
} // mozilla
%}

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"
#include "nsIVolume.idl"
[scriptable, uuid(b31bd379-4bd2-4189-a85b-c0927a266a85)]
interface nsIVolumeService : nsISupports
{
nsIVolume getVolumeByName(in DOMString volName);
nsIVolume getVolumeByPath(in DOMString path);
};
%{C++
#define NS_VOLUMESERVICE_CID \
{0xb31bd379, 0x4bd2, 0x4189, {0xa8, 0x5b, 0xc0, 0x92, 0x7a, 0x26, 0x6a, 0x85}}
#define NS_VOLUMESERVICE_CONTRACTID "@mozilla.org/telephony/volume-service;1"
%}

View 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(b4c050d0-c57a-11e1-9b21-0800200c9a66)]
interface nsIVolumeStat : nsISupports
{
readonly attribute long long totalBytes;
readonly attribute long long freeBytes;
};

View File

@ -0,0 +1,62 @@
/* 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 "nsVolume.h"
#include "nsISupportsUtils.h"
#include "nsIVolume.h"
#include "nsVolumeStat.h"
namespace mozilla {
namespace system {
const char *
NS_VolumeStateStr(PRInt32 aState)
{
switch (aState) {
case nsIVolume::STATE_INIT: return "Init";
case nsIVolume::STATE_NOMEDIA: return "NoMedia";
case nsIVolume::STATE_IDLE: return "Idle";
case nsIVolume::STATE_PENDING: return "Pending";
case nsIVolume::STATE_CHECKING: return "Checking";
case nsIVolume::STATE_MOUNTED: return "Mounted";
case nsIVolume::STATE_UNMOUNTING: return "Unmounting";
case nsIVolume::STATE_FORMATTING: return "Formatting";
case nsIVolume::STATE_SHARED: return "Shared";
case nsIVolume::STATE_SHAREDMNT: return "Shared-Mounted";
}
return "???";
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsVolume, nsIVolume)
NS_IMETHODIMP nsVolume::GetName(nsAString &aName)
{
aName = mName;
return NS_OK;
}
NS_IMETHODIMP nsVolume::GetMountPoint(nsAString &aMountPoint)
{
aMountPoint = mMountPoint;
return NS_OK;
}
NS_IMETHODIMP nsVolume::GetState(PRInt32 *aState)
{
*aState = mState;
return NS_OK;
}
NS_IMETHODIMP nsVolume::GetStats(nsIVolumeStat **aResult NS_OUTPARAM)
{
if (mState != STATE_MOUNTED) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_IF_ADDREF(*aResult = new nsVolumeStat(mMountPoint));
return NS_OK;
}
} // system
} // mozilla

View File

@ -0,0 +1,70 @@
/* 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_nsvolume_h__
#define mozilla_system_nsvolume_h__
#include "Volume.h"
#include "nsIVolume.h"
namespace mozilla {
namespace system {
class nsVolume : public nsIVolume
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIVOLUME
nsVolume(const Volume *aVolume)
: mName(NS_ConvertUTF8toUTF16(aVolume->Name())),
mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
mState(aVolume->State())
{
}
nsVolume(const nsAString &aName)
: mName(aName),
mState(STATE_INIT)
{
}
bool Equals(const nsVolume *aVolume)
{
return mName.Equals(aVolume->mName)
&& mMountPoint.Equals(aVolume->mMountPoint)
&& (mState == aVolume->mState);
}
void Set(const nsVolume *aVolume)
{
mName = aVolume->mName;
mMountPoint = aVolume->mMountPoint;
mState = aVolume->mState;
}
const nsString &Name() const { return mName; }
const char *NameStr() const { return NS_LossyConvertUTF16toASCII(mName).get(); }
const nsString &MountPoint() const { return mMountPoint; }
const char *MountPointStr() const { return NS_LossyConvertUTF16toASCII(mMountPoint).get(); }
long State() const { return mState; }
const char *StateStr() const { return Volume::StateStr((Volume::STATE)mState); }
typedef nsTArray<nsRefPtr<nsVolume> > Array;
private:
~nsVolume() {}
protected:
nsString mName;
nsString mMountPoint;
long mState;
};
} // system
} // mozilla
#endif // mozilla_system_nsvolume_h__

View File

@ -0,0 +1,194 @@
/* 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 "nsVolumeService.h"
#include "Volume.h"
#include "VolumeManager.h"
#include "VolumeServiceIOThread.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsDependentSubstring.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsISupportsUtils.h"
#include "nsIVolume.h"
#include "nsIVolumeService.h"
#include "nsLocalFile.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "mozilla/Services.h"
#define VOLUME_MANAGER_LOG_TAG "nsVolumeService"
#include "VolumeManagerLog.h"
#include <stdlib.h>
using namespace mozilla::services;
namespace mozilla {
namespace system {
NS_IMPL_ISUPPORTS1(nsVolumeService, nsIVolumeService)
nsVolumeService::nsVolumeService()
{
// 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));
}
nsVolumeService::~nsVolumeService()
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(ShutdownVolumeServiceIOThread));
}
/* nsIVolume getVolumeByName (in DOMString volName); */
NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString &aVolName, nsIVolume **aResult NS_OUTPARAM)
{
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
if (!vol) {
return NS_ERROR_NOT_AVAILABLE;
}
NS_ADDREF(*aResult = vol);
return NS_OK;
}
/* nsIVolume getVolumeByPath (in DOMString path); */
NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString &aPath, nsIVolume **aResult NS_OUTPARAM)
{
nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath);
char realPathBuf[PATH_MAX];
if (!realpath(utf8Path.get(), realPathBuf)) {
return NSRESULT_FOR_ERRNO();
}
// The volume mount point is always a directory. Something like /mnt/sdcard
// Once we have a full qualified pathname with symlinks removed (which is
// what realpath does), we basically check if aPath starts with the mount
// point, but we don't want to have /mnt/sdcard match /mnt/sdcardfoo but we
// do want it to match /mnt/sdcard/foo
// So we add a trailing slash to the mount point and the pathname passed in
// prior to doing the comparison.
strlcat(realPathBuf, "/", sizeof(realPathBuf));
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
nsCAutoString volMountPointSlash = NS_ConvertUTF16toUTF8(vol->MountPoint());
volMountPointSlash.Append(NS_LITERAL_CSTRING("/"));
nsDependentCSubstring testStr(realPathBuf, volMountPointSlash.Length());
if (volMountPointSlash.Equals(testStr)) {
NS_ADDREF(*aResult = vol);
return NS_OK;
}
}
return NS_ERROR_NOT_AVAILABLE;
}
already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString &aName)
{
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];
if (vol->Name().Equals(aName)) {
return vol.forget();
}
}
return NULL;
}
already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString &aName)
{
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<nsVolume> vol;
vol = FindVolumeByName(aName);
if (vol) {
return vol.forget();
}
// Volume not found - add a new one
vol = new nsVolume(aName);
mVolumeArray.AppendElement(vol);
return vol.forget();
}
void nsVolumeService::UpdateVolume(const nsVolume *aVolume)
{
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<nsVolume> vol = FindAddVolumeByName(aVolume->Name());
if (vol->Equals(aVolume)) {
// Nothing has really changed. Don't bother telling anybody.
return;
}
vol->Set(aVolume);
nsRefPtr<nsIObserverService> obs = GetObserverService();
if (!obs) {
return;
}
nsString stateStr(NS_ConvertUTF8toUTF16(vol->StateStr()));
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
}
/***************************************************************************
* The UpdateVolumeRunnable creates an nsVolume and updates the main thread
* data structure while running on the main thread.
*/
class UpdateVolumeRunnable : public nsRunnable
{
public:
UpdateVolumeRunnable(const Volume *aVolume)
: mVolume(new nsVolume(aVolume))
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
DBG("UpdateVolumeRunnable::Run '%s' state %s",
mVolume->NameStr(), mVolume->StateStr());
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);
mVolume = NULL;
return NS_OK;
}
private:
nsRefPtr<nsVolume> mVolume;
};
//static
void nsVolumeService::UpdateVolumeIOThread(const Volume *aVolume)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
NS_DispatchToMainThread(new UpdateVolumeRunnable(aVolume));
}
} // system
} // mozilla

View File

@ -0,0 +1,45 @@
/* 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_nsvolumeservice_h__
#define mozilla_system_nsvolumeservice_h__
#include "nsCOMPtr.h"
#include "nsIVolume.h"
#include "nsIVolumeService.h"
#include "nsVolume.h"
#include "Volume.h"
namespace mozilla {
namespace system {
/***************************************************************************
* 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
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIVOLUMESERVICE
nsVolumeService();
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);
private:
~nsVolumeService();
nsVolume::Array mVolumeArray;
};
} // system
} // mozilla
#endif // mozilla_system_nsvolumeservice_h__

View File

@ -0,0 +1,41 @@
/* 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 "nsVolumeStat.h"
#include "nsString.h"
namespace mozilla {
namespace system {
NS_IMPL_ISUPPORTS1(nsVolumeStat, nsIVolumeStat)
nsVolumeStat::nsVolumeStat(const nsAString &aPath)
{
nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath);
if (statfs(utf8Path.get(), &mStat) != 0) {
memset(&mStat, 0, sizeof(mStat));
}
}
nsVolumeStat::~nsVolumeStat()
{
}
/* readonly attribute long long totalBytes; */
NS_IMETHODIMP nsVolumeStat::GetTotalBytes(PRInt64 *aTotalBytes)
{
*aTotalBytes = mStat.f_blocks * mStat.f_bsize;
return NS_OK;
}
/* readonly attribute long long freeBytes; */
NS_IMETHODIMP nsVolumeStat::GetFreeBytes(PRInt64 *aFreeBytes)
{
*aFreeBytes = mStat.f_bfree * mStat.f_bsize;
return NS_OK;
}
} // system
} // mozilla

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 mozilla_system_nsvolumestat_h__
#define mozilla_system_nsvolumestat_h__
#include "nsIVolumeStat.h"
#include "nsString.h"
#include <sys/statfs.h>
namespace mozilla {
namespace system {
class nsVolumeStat : public nsIVolumeStat
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIVOLUMESTAT
nsVolumeStat(const nsAString &aPath);
private:
~nsVolumeStat();
struct statfs mStat;
};
} // system
} // mozilla
#endif // mozilla_system_nsvolumestat_h__

View File

@ -106,6 +106,8 @@ using mozilla::dom::gonk::SystemWorkerManager;
#ifdef MOZ_WIDGET_GONK
#include "AudioManager.h"
using mozilla::dom::gonk::AudioManager;
#include "nsVolumeService.h"
using mozilla::system::nsVolumeService;
#endif
#include "nsDOMMutationObserver.h"
@ -265,6 +267,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMMutationObserver)
#ifdef MOZ_WIDGET_GONK
NS_GENERIC_FACTORY_CONSTRUCTOR(AudioManager)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsVolumeService)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceSensors)
@ -742,6 +745,7 @@ NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
#endif
#ifdef MOZ_WIDGET_GONK
NS_DEFINE_NAMED_CID(NS_AUDIOMANAGER_CID);
NS_DEFINE_NAMED_CID(NS_VOLUMESERVICE_CID);
#endif
#ifdef ENABLE_EDITOR_API_LOG
NS_DEFINE_NAMED_CID(NS_HTMLEDITOR_CID);
@ -1012,6 +1016,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
#endif
#ifdef MOZ_WIDGET_GONK
{ &kNS_AUDIOMANAGER_CID, true, NULL, AudioManagerConstructor },
{ &kNS_VOLUMESERVICE_CID, true, NULL, nsVolumeServiceConstructor },
#endif
#ifdef ENABLE_EDITOR_API_LOG
{ &kNS_HTMLEDITOR_CID, false, NULL, nsHTMLEditorLogConstructor },
@ -1147,6 +1152,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
#endif
#ifdef MOZ_WIDGET_GONK
{ NS_AUDIOMANAGER_CONTRACTID, &kNS_AUDIOMANAGER_CID },
{ NS_VOLUMESERVICE_CONTRACTID, &kNS_VOLUMESERVICE_CID },
#endif
#ifdef ENABLE_EDITOR_API_LOG
{ "@mozilla.org/editor/htmleditor;1", &kNS_HTMLEDITOR_CID },