mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 766324 - Add a volume IDL to make volumes scriptable r=qdot
This commit is contained in:
parent
177b3c4fdd
commit
6c49401e4b
@ -208,10 +208,11 @@ public:
|
|||||||
mMode(AUTOMOUNTER_DISABLE)
|
mMode(AUTOMOUNTER_DISABLE)
|
||||||
{
|
{
|
||||||
VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
|
VolumeManager::RegisterStateObserver(&mVolumeManagerStateObserver);
|
||||||
|
Volume::RegisterObserver(&mVolumeEventObserver);
|
||||||
|
|
||||||
for (size_t i = 0; i < NS_ARRAY_LENGTH(sAutoVolumeName); i++) {
|
for (size_t i = 0; i < NS_ARRAY_LENGTH(sAutoVolumeName); i++) {
|
||||||
RefPtr<Volume> vol = VolumeManager::FindAddVolumeByName(sAutoVolumeName[i]);
|
RefPtr<Volume> vol = VolumeManager::FindAddVolumeByName(sAutoVolumeName[i]);
|
||||||
if (vol != NULL) {
|
if (vol) {
|
||||||
vol->RegisterObserver(&mVolumeEventObserver);
|
vol->RegisterObserver(&mVolumeEventObserver);
|
||||||
mAutoVolume.AppendElement(vol);
|
mAutoVolume.AppendElement(vol);
|
||||||
}
|
}
|
||||||
@ -228,6 +229,7 @@ public:
|
|||||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||||
mAutoVolume[volIndex]->UnregisterObserver(&mVolumeEventObserver);
|
mAutoVolume[volIndex]->UnregisterObserver(&mVolumeEventObserver);
|
||||||
}
|
}
|
||||||
|
Volume::UnregisterObserver(&mVolumeEventObserver);
|
||||||
VolumeManager::UnregisterStateObserver(&mVolumeManagerStateObserver);
|
VolumeManager::UnregisterStateObserver(&mVolumeManagerStateObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,14 +379,14 @@ AutoMounter::UpdateState()
|
|||||||
if (tryToShare) {
|
if (tryToShare) {
|
||||||
// We're going to try to unmount and share the volumes
|
// We're going to try to unmount and share the volumes
|
||||||
switch (volState) {
|
switch (volState) {
|
||||||
case Volume::STATE_MOUNTED: {
|
case nsIVolume::STATE_MOUNTED: {
|
||||||
// Volume is mounted, we need to unmount before
|
// Volume is mounted, we need to unmount before
|
||||||
// we can share.
|
// we can share.
|
||||||
DBG("UpdateState: Unmounting %s", vol->NameStr());
|
DBG("UpdateState: Unmounting %s", vol->NameStr());
|
||||||
vol->StartUnmount(mResponseCallback);
|
vol->StartUnmount(mResponseCallback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Volume::STATE_IDLE: {
|
case nsIVolume::STATE_IDLE: {
|
||||||
// Volume is unmounted. We can go ahead and share.
|
// Volume is unmounted. We can go ahead and share.
|
||||||
DBG("UpdateState: Sharing %s", vol->NameStr());
|
DBG("UpdateState: Sharing %s", vol->NameStr());
|
||||||
vol->StartShare(mResponseCallback);
|
vol->StartShare(mResponseCallback);
|
||||||
@ -398,13 +400,13 @@ AutoMounter::UpdateState()
|
|||||||
} else {
|
} else {
|
||||||
// We're going to try and unshare and remount the volumes
|
// We're going to try and unshare and remount the volumes
|
||||||
switch (volState) {
|
switch (volState) {
|
||||||
case Volume::STATE_SHARED: {
|
case nsIVolume::STATE_SHARED: {
|
||||||
// Volume is shared. We can go ahead and unshare.
|
// Volume is shared. We can go ahead and unshare.
|
||||||
DBG("UpdateState: Unsharing %s", vol->NameStr());
|
DBG("UpdateState: Unsharing %s", vol->NameStr());
|
||||||
vol->StartUnshare(mResponseCallback);
|
vol->StartUnshare(mResponseCallback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Volume::STATE_IDLE: {
|
case nsIVolume::STATE_IDLE: {
|
||||||
// Volume is unmounted, try to mount.
|
// Volume is unmounted, try to mount.
|
||||||
|
|
||||||
DBG("UpdateState: Mounting %s", vol->NameStr());
|
DBG("UpdateState: Mounting %s", vol->NameStr());
|
||||||
|
@ -27,6 +27,9 @@ XPIDLSRCS = \
|
|||||||
nsIAudioManager.idl \
|
nsIAudioManager.idl \
|
||||||
nsINetworkManager.idl \
|
nsINetworkManager.idl \
|
||||||
nsIRadioInterfaceLayer.idl \
|
nsIRadioInterfaceLayer.idl \
|
||||||
|
nsIVolume.idl \
|
||||||
|
nsIVolumeService.idl \
|
||||||
|
nsIVolumeStat.idl \
|
||||||
nsIWorkerHolder.idl \
|
nsIWorkerHolder.idl \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
@ -45,9 +48,14 @@ CPPSRCS += \
|
|||||||
AutoMounter.cpp \
|
AutoMounter.cpp \
|
||||||
AutoMounterSetting.cpp \
|
AutoMounterSetting.cpp \
|
||||||
GonkGPSGeolocationProvider.cpp \
|
GonkGPSGeolocationProvider.cpp \
|
||||||
|
nsVolume.cpp \
|
||||||
|
nsVolumeService.cpp \
|
||||||
|
nsVolumeStat.cpp \
|
||||||
Volume.cpp \
|
Volume.cpp \
|
||||||
VolumeCommand.cpp \
|
VolumeCommand.cpp \
|
||||||
VolumeManager.cpp \
|
VolumeManager.cpp \
|
||||||
|
VolumeServiceIOThread.cpp \
|
||||||
|
VolumeServiceTest.cpp \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
# for our local copy of AudioSystem.h
|
# for our local copy of AudioSystem.h
|
||||||
LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src
|
LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "VolumeCommand.h"
|
#include "VolumeCommand.h"
|
||||||
#include "VolumeManager.h"
|
#include "VolumeManager.h"
|
||||||
#include "VolumeManagerLog.h"
|
#include "VolumeManagerLog.h"
|
||||||
|
#include "nsIVolume.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
|
|
||||||
#include <vold/ResponseCode.h>
|
#include <vold/ResponseCode.h>
|
||||||
@ -13,11 +14,13 @@
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace system {
|
namespace system {
|
||||||
|
|
||||||
|
Volume::EventObserverList Volume::mEventObserverList;
|
||||||
|
|
||||||
// We don't get media inserted/removed events at startup. So we
|
// 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.
|
// assume it's present, and we'll be told that it's missing.
|
||||||
Volume::Volume(const nsCSubstring &aName)
|
Volume::Volume(const nsCSubstring &aName)
|
||||||
: mMediaPresent(true),
|
: mMediaPresent(true),
|
||||||
mState(STATE_INIT),
|
mState(nsIVolume::STATE_INIT),
|
||||||
mName(aName)
|
mName(aName)
|
||||||
{
|
{
|
||||||
DBG("Volume %s: created", NameStr());
|
DBG("Volume %s: created", NameStr());
|
||||||
@ -67,7 +70,7 @@ Volume::SetState(Volume::STATE aNewState)
|
|||||||
NameStr(), StateStr(mState),
|
NameStr(), StateStr(mState),
|
||||||
StateStr(aNewState), mEventObserverList.Length());
|
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
|
// Cover the startup case where we don't get insertion/removal events
|
||||||
mMediaPresent = false;
|
mMediaPresent = false;
|
||||||
}
|
}
|
||||||
@ -115,16 +118,22 @@ Volume::StartCommand(VolumeCommand *aCommand)
|
|||||||
VolumeManager::PostCommand(aCommand);
|
VolumeManager::PostCommand(aCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
void
|
void
|
||||||
Volume::RegisterObserver(Volume::EventObserver *aObserver)
|
Volume::RegisterObserver(Volume::EventObserver *aObserver)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
|
||||||
|
|
||||||
mEventObserverList.AddObserver(aObserver);
|
mEventObserverList.AddObserver(aObserver);
|
||||||
// Send an initial event to the observer
|
// Send an initial event to the observer (for each volume)
|
||||||
aObserver->Notify(this);
|
size_t numVolumes = VolumeManager::NumVolumes();
|
||||||
|
for (size_t volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||||
|
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
|
||||||
|
aObserver->Notify(vol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
void
|
void
|
||||||
Volume::UnregisterObserver(Volume::EventObserver *aObserver)
|
Volume::UnregisterObserver(Volume::EventObserver *aObserver)
|
||||||
{
|
{
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
#define mozilla_system_volume_h__
|
#define mozilla_system_volume_h__
|
||||||
|
|
||||||
#include "VolumeCommand.h"
|
#include "VolumeCommand.h"
|
||||||
|
#include "nsIVolume.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsWhitespaceTokenizer.h"
|
|
||||||
#include "mozilla/Observer.h"
|
#include "mozilla/Observer.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "nsWhitespaceTokenizer.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace system {
|
namespace system {
|
||||||
@ -26,39 +27,11 @@ namespace system {
|
|||||||
class Volume : public RefCounted<Volume>
|
class Volume : public RefCounted<Volume>
|
||||||
{
|
{
|
||||||
public:
|
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);
|
Volume(const nsCSubstring &aVolumeName);
|
||||||
|
|
||||||
const char *StateStr(STATE aState) const
|
typedef long STATE; // States are now defined in nsIVolume.idl
|
||||||
{
|
|
||||||
switch (aState) {
|
static const char *StateStr(STATE aState) { return NS_VolumeStateStr(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 "???";
|
|
||||||
}
|
|
||||||
const char *StateStr() const { return StateStr(mState); }
|
const char *StateStr() const { return StateStr(mState); }
|
||||||
STATE State() const { return mState; }
|
STATE State() const { return mState; }
|
||||||
|
|
||||||
@ -75,8 +48,8 @@ public:
|
|||||||
typedef mozilla::ObserverList<Volume *> EventObserverList;
|
typedef mozilla::ObserverList<Volume *> EventObserverList;
|
||||||
|
|
||||||
// NOTE: that observers must live in the IOThread.
|
// NOTE: that observers must live in the IOThread.
|
||||||
void RegisterObserver(EventObserver *aObserver);
|
static void RegisterObserver(EventObserver *aObserver);
|
||||||
void UnregisterObserver(EventObserver *aObserver);
|
static void UnregisterObserver(EventObserver *aObserver);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class AutoMounter; // Calls StartXxx
|
friend class AutoMounter; // Calls StartXxx
|
||||||
@ -102,7 +75,8 @@ private:
|
|||||||
STATE mState;
|
STATE mState;
|
||||||
const nsCString mName;
|
const nsCString mName;
|
||||||
nsCString mMountPoint;
|
nsCString mMountPoint;
|
||||||
EventObserverList mEventObserverList;
|
|
||||||
|
static EventObserverList mEventObserverList;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // system
|
} // system
|
||||||
|
@ -2,22 +2,24 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/. */
|
* 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 <android/log.h>
|
||||||
#include <cutils/sockets.h>
|
#include <cutils/sockets.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/socket.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 mozilla {
|
||||||
namespace system {
|
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
|
//static
|
||||||
VolumeManager::STATE
|
VolumeManager::STATE
|
||||||
VolumeManager::State()
|
VolumeManager::State()
|
||||||
@ -94,11 +114,12 @@ VolumeManager::FindVolumeByName(const nsCSubstring &aName)
|
|||||||
if (!sVolumeManager) {
|
if (!sVolumeManager) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (VolumeArray::iterator volIter = sVolumeManager->mVolumeArray.begin();
|
VolumeArray::size_type numVolumes = NumVolumes();
|
||||||
volIter != sVolumeManager->mVolumeArray.end();
|
VolumeArray::index_type volIndex;
|
||||||
volIter++) {
|
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||||
if ((*volIter)->Name().Equals(aName)) {
|
RefPtr<Volume> vol = GetVolume(volIndex);
|
||||||
return *volIter;
|
if (vol->Name().Equals(aName)) {
|
||||||
|
return vol;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -114,7 +135,7 @@ VolumeManager::FindAddVolumeByName(const nsCSubstring &aName)
|
|||||||
}
|
}
|
||||||
// No volume found, create and add a new one.
|
// No volume found, create and add a new one.
|
||||||
vol = new Volume(aName);
|
vol = new Volume(aName);
|
||||||
sVolumeManager->mVolumeArray.push_back(vol);
|
sVolumeManager->mVolumeArray.AppendElement(vol);
|
||||||
return vol;
|
return vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,6 +415,8 @@ InitVolumeManagerIOThread()
|
|||||||
|
|
||||||
sVolumeManager = new VolumeManager();
|
sVolumeManager = new VolumeManager();
|
||||||
VolumeManager::Start();
|
VolumeManager::Start();
|
||||||
|
|
||||||
|
InitVolumeServiceTestIOThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -424,6 +447,8 @@ InitVolumeManager()
|
|||||||
void
|
void
|
||||||
ShutdownVolumeManager()
|
ShutdownVolumeManager()
|
||||||
{
|
{
|
||||||
|
ShutdownVolumeServiceTest();
|
||||||
|
|
||||||
XRE_GetIOMessageLoop()->PostTask(
|
XRE_GetIOMessageLoop()->PostTask(
|
||||||
FROM_HERE,
|
FROM_HERE,
|
||||||
NewRunnableFunction(ShutdownVolumeManagerIOThread));
|
NewRunnableFunction(ShutdownVolumeManagerIOThread));
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "mozilla/Observer.h"
|
#include "mozilla/Observer.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "VolumeCommand.h"
|
#include "VolumeCommand.h"
|
||||||
@ -77,7 +78,7 @@ class VolumeManager : public MessageLoopForIO::Watcher,
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::vector<RefPtr<Volume> > VolumeArray;
|
typedef nsTArray<RefPtr<Volume> > VolumeArray;
|
||||||
|
|
||||||
VolumeManager();
|
VolumeManager();
|
||||||
virtual ~VolumeManager();
|
virtual ~VolumeManager();
|
||||||
@ -120,6 +121,8 @@ public:
|
|||||||
|
|
||||||
static void Start();
|
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> FindVolumeByName(const nsCSubstring &aName);
|
||||||
static TemporaryRef<Volume> FindAddVolumeByName(const nsCSubstring &aName);
|
static TemporaryRef<Volume> FindAddVolumeByName(const nsCSubstring &aName);
|
||||||
|
|
||||||
|
@ -7,12 +7,16 @@
|
|||||||
|
|
||||||
#define USE_DEBUG 0
|
#define USE_DEBUG 0
|
||||||
|
|
||||||
|
#if !defined(VOLUME_MANAGER_LOG_TAG)
|
||||||
|
#define VOLUME_MANAGER_LOG_TAG "VolumeManager"
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef LOG
|
#undef LOG
|
||||||
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "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, "VolumeManager" , ## args)
|
#define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, VOLUME_MANAGER_LOG_TAG, ## args)
|
||||||
|
|
||||||
#if USE_DEBUG
|
#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
|
#else
|
||||||
#define DBG(args...)
|
#define DBG(args...)
|
||||||
#endif
|
#endif
|
||||||
|
78
dom/system/gonk/VolumeServiceIOThread.cpp
Normal file
78
dom/system/gonk/VolumeServiceIOThread.cpp
Normal 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
|
41
dom/system/gonk/VolumeServiceIOThread.h
Normal file
41
dom/system/gonk/VolumeServiceIOThread.h
Normal 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__
|
201
dom/system/gonk/VolumeServiceTest.cpp
Normal file
201
dom/system/gonk/VolumeServiceTest.cpp
Normal 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
|
19
dom/system/gonk/VolumeServiceTest.h
Normal file
19
dom/system/gonk/VolumeServiceTest.h
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/. */
|
||||||
|
|
||||||
|
#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__
|
||||||
|
|
44
dom/system/gonk/nsIVolume.idl
Normal file
44
dom/system/gonk/nsIVolume.idl
Normal 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
|
||||||
|
%}
|
19
dom/system/gonk/nsIVolumeService.idl
Normal file
19
dom/system/gonk/nsIVolumeService.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"
|
||||||
|
#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"
|
||||||
|
%}
|
12
dom/system/gonk/nsIVolumeStat.idl
Normal file
12
dom/system/gonk/nsIVolumeStat.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(b4c050d0-c57a-11e1-9b21-0800200c9a66)]
|
||||||
|
interface nsIVolumeStat : nsISupports
|
||||||
|
{
|
||||||
|
readonly attribute long long totalBytes;
|
||||||
|
readonly attribute long long freeBytes;
|
||||||
|
};
|
62
dom/system/gonk/nsVolume.cpp
Normal file
62
dom/system/gonk/nsVolume.cpp
Normal 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
|
70
dom/system/gonk/nsVolume.h
Normal file
70
dom/system/gonk/nsVolume.h
Normal 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__
|
194
dom/system/gonk/nsVolumeService.cpp
Normal file
194
dom/system/gonk/nsVolumeService.cpp
Normal 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
|
45
dom/system/gonk/nsVolumeService.h
Normal file
45
dom/system/gonk/nsVolumeService.h
Normal 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__
|
41
dom/system/gonk/nsVolumeStat.cpp
Normal file
41
dom/system/gonk/nsVolumeStat.cpp
Normal 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
|
32
dom/system/gonk/nsVolumeStat.h
Normal file
32
dom/system/gonk/nsVolumeStat.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 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__
|
@ -106,6 +106,8 @@ using mozilla::dom::gonk::SystemWorkerManager;
|
|||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
#include "AudioManager.h"
|
#include "AudioManager.h"
|
||||||
using mozilla::dom::gonk::AudioManager;
|
using mozilla::dom::gonk::AudioManager;
|
||||||
|
#include "nsVolumeService.h"
|
||||||
|
using mozilla::system::nsVolumeService;
|
||||||
#endif
|
#endif
|
||||||
#include "nsDOMMutationObserver.h"
|
#include "nsDOMMutationObserver.h"
|
||||||
|
|
||||||
@ -265,6 +267,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMMutationObserver)
|
|||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(AudioManager)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(AudioManager)
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsVolumeService)
|
||||||
#endif
|
#endif
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceSensors)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceSensors)
|
||||||
|
|
||||||
@ -742,6 +745,7 @@ NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID);
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
NS_DEFINE_NAMED_CID(NS_AUDIOMANAGER_CID);
|
NS_DEFINE_NAMED_CID(NS_AUDIOMANAGER_CID);
|
||||||
|
NS_DEFINE_NAMED_CID(NS_VOLUMESERVICE_CID);
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_EDITOR_API_LOG
|
#ifdef ENABLE_EDITOR_API_LOG
|
||||||
NS_DEFINE_NAMED_CID(NS_HTMLEDITOR_CID);
|
NS_DEFINE_NAMED_CID(NS_HTMLEDITOR_CID);
|
||||||
@ -1012,6 +1016,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
{ &kNS_AUDIOMANAGER_CID, true, NULL, AudioManagerConstructor },
|
{ &kNS_AUDIOMANAGER_CID, true, NULL, AudioManagerConstructor },
|
||||||
|
{ &kNS_VOLUMESERVICE_CID, true, NULL, nsVolumeServiceConstructor },
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_EDITOR_API_LOG
|
#ifdef ENABLE_EDITOR_API_LOG
|
||||||
{ &kNS_HTMLEDITOR_CID, false, NULL, nsHTMLEditorLogConstructor },
|
{ &kNS_HTMLEDITOR_CID, false, NULL, nsHTMLEditorLogConstructor },
|
||||||
@ -1147,6 +1152,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
{ NS_AUDIOMANAGER_CONTRACTID, &kNS_AUDIOMANAGER_CID },
|
{ NS_AUDIOMANAGER_CONTRACTID, &kNS_AUDIOMANAGER_CID },
|
||||||
|
{ NS_VOLUMESERVICE_CONTRACTID, &kNS_VOLUMESERVICE_CID },
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_EDITOR_API_LOG
|
#ifdef ENABLE_EDITOR_API_LOG
|
||||||
{ "@mozilla.org/editor/htmleditor;1", &kNS_HTMLEDITOR_CID },
|
{ "@mozilla.org/editor/htmleditor;1", &kNS_HTMLEDITOR_CID },
|
||||||
|
Loading…
Reference in New Issue
Block a user