Back out 6737ce4d3ce6:599c37ed628c (bug 785124) for b2g Arm xpcshell orange in update tests

This commit is contained in:
Phil Ringnalda 2013-01-07 22:59:32 -08:00
parent c4574bd3fa
commit 69566d191b
36 changed files with 216 additions and 1189 deletions

View File

@ -11,27 +11,12 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const XRE_OS_UPDATE_APPLY_TO_DIR = "OSUpdApplyToD"
const UPDATE_ARCHIVE_DIR = "UpdArchD"
const LOCAL_DIR = "/data/local";
XPCOMUtils.defineLazyServiceGetter(Services, "env",
"@mozilla.org/process/environment;1",
"nsIEnvironment");
XPCOMUtils.defineLazyServiceGetter(Services, "volumeService",
"@mozilla.org/telephony/volume-service;1",
"nsIVolumeService");
XPCOMUtils.defineLazyGetter(this, "gExtStorage", function dp_gExtStorage() {
return Services.env.get("EXTERNAL_STORAGE");
});
const VERBOSE = 1;
let log =
VERBOSE ?
function log_dump(msg) { dump("DirectoryProvider: " + msg + "\n"); } :
function log_noop(msg) { };
function DirectoryProvider() {
}
@ -50,148 +35,36 @@ DirectoryProvider.prototype = {
file.initWithPath(LOCAL_DIR);
persistent.value = true;
return file;
}
if (prop == "coreAppsDir") {
} else if (prop == "coreAppsDir") {
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
file.initWithPath("/system/b2g");
persistent.value = true;
return file;
}
if (prop == XRE_OS_UPDATE_APPLY_TO_DIR ||
prop == UPDATE_ARCHIVE_DIR) {
let file = this.getUpdateDir(persistent);
return file;
} else if (prop == XRE_OS_UPDATE_APPLY_TO_DIR) {
return this.getOSUpdateApplyToDir(persistent);
}
#endif
return null;
},
// The VolumeService only exists on the device, and not on desktop
volumeHasFreeSpace: function dp_volumeHasFreeSpace(volumePath, requiredSpace) {
if (!volumePath) {
return false;
}
if (!Services.volumeService) {
return false;
}
let volume = Services.volumeService.getVolumeByPath(volumePath);
if (!volume || volume.state !== Ci.nsIVolume.STATE_MOUNTED) {
return false;
}
let stat = volume.getStats();
if (!stat) {
return false;
}
return requiredSpace <= stat.freeBytes;
},
findUpdateDirWithFreeSpace: function dp_findUpdateDirWithFreeSpace(requiredSpace) {
if (!Services.volumeService) {
return this.createUpdatesDir(LOCAL_DIR);
}
let activeUpdate = Services.um.activeUpdate;
if (this.volumeHasFreeSpace(gExtStorage, requiredSpace)) {
let extUpdateDir = this.createUpdatesDir(gExtStorage);
if (extUpdateDir !== null) {
return extUpdateDir;
}
log("Warning: " + gExtStorage + " has enough free space for update " +
activeUpdate.name + ", but is not writable");
}
if (this.volumeHasFreeSpace(LOCAL_DIR, requiredSpace)) {
let localUpdateDir = this.createUpdatesDir(LOCAL_DIR);
if (localUpdateDir !== null) {
return localUpdateDir;
}
log("Warning: " + LOCAL_DIR + " has enough free space for update " +
activeUpdate.name + ", but is not writable");
}
return null;
},
getUpdateDir: function dp_getUpdateDir(persistent) {
let defaultUpdateDir = this.getDefaultUpdateDir();
persistent.value = false;
getOSUpdateApplyToDir: function dp_getOSUpdateApplyToDir(persistent) {
// TODO add logic to check available storage space,
// and iterate through pref(s) to find alternative dirs if
// necessary.
let activeUpdate = Services.um.activeUpdate;
if (!activeUpdate) {
log("Warning: No active update found, using default update dir: " +
defaultUpdateDir);
return defaultUpdateDir;
}
let selectedPatch = activeUpdate.selectedPatch;
if (!selectedPatch) {
log("Warning: No selected patch, using default update dir: " +
defaultUpdateDir);
return defaultUpdateDir;
}
let requiredSpace = selectedPatch.size * 2;
let updateDir = this.findUpdateDirWithFreeSpace(requiredSpace, persistent);
if (updateDir) {
return updateDir;
}
// If we've gotten this far, there isn't enough free space to download the patch
// on either external storage or /data/local. All we can do is report the
// error and let upstream code handle it more gracefully.
log("Error: No volume found with " + requiredSpace + " bytes for downloading"+
" update " + activeUpdate.name);
throw Cr.NS_ERROR_FILE_TOO_BIG;
},
createUpdatesDir: function dp_createUpdatesDir(root) {
let dir = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
dir.initWithPath(root);
if (!dir.isWritable()) {
return null;
}
dir.appendRelativePath("updates/0");
if (dir.exists()) {
if (dir.isDirectory() && dir.isWritable()) {
return dir;
}
// updates/0 is either a file or isn't writable. In either case we
// can't use it.
log("Error: " + dir.path + " is a file or isn't writable");
return null;
}
// updates/0 doesn't exist, and the parent is writable, so try to
// create it. This can fail if a file named updates exists.
try {
dir.create(Ci.nsIFile.DIRECTORY_TYPE, 0770);
} catch (e) {
// The create failed for some reason. We can't use it.
log("Error: " + dir.path + " unable to create directory");
return null;
}
return dir;
},
getDefaultUpdateDir: function dp_getDefaultUpdateDir() {
let path = gExtStorage;
let path = Services.env.get("EXTERNAL_STORAGE");
if (!path) {
path = LOCAL_DIR;
}
if (Services.volumeService) {
let extVolume = Services.volumeService.getVolumeByPath(path);
if (!extVolume) {
path = LOCAL_DIR;
}
path = LOCAL_PATH;
}
let dir = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile)
dir.initWithPath(path);
if (!dir.exists() && path != LOCAL_DIR) {
// Fallback to LOCAL_DIR if we didn't fallback earlier
dir.initWithPath(LOCAL_DIR);
if (!dir.exists() && path != LOCAL_PATH) {
// Fallback to LOCAL_PATH if we didn't fallback earlier
dir.initWithPath(LOCAL_PATH);
if (!dir.exists()) {
throw Cr.NS_ERROR_FILE_NOT_FOUND;
@ -199,6 +72,7 @@ DirectoryProvider.prototype = {
}
dir.appendRelativePath("updates");
persistent.value = false;
return dir;
}
};

View File

@ -22,9 +22,6 @@ const PREF_APPLY_PROMPT_TIMEOUT = "b2g.update.apply-prompt-timeout";
const PREF_APPLY_IDLE_TIMEOUT = "b2g.update.apply-idle-timeout";
const NETWORK_ERROR_OFFLINE = 111;
const FILE_ERROR_TOO_BIG = 112;
const STATE_DOWNLOADING = 'downloading';
XPCOMUtils.defineLazyServiceGetter(Services, "aus",
"@mozilla.org/updates/update-service;1",
@ -275,17 +272,8 @@ UpdatePrompt.prototype = {
}
}
let status = Services.aus.downloadUpdate(aUpdate, true);
if (status == STATE_DOWNLOADING) {
Services.aus.addDownloadListener(this);
return;
}
log("Error downloading update " + aUpdate.name + ": " + aUpdate.errorCode);
if (aUpdate.errorCode == FILE_ERROR_TOO_BIG) {
aUpdate.statusText = "file-too-big";
}
this.showUpdateError(aUpdate);
Services.aus.downloadUpdate(aUpdate, true);
Services.aus.addDownloadListener(this);
},
handleDownloadCancel: function UP_handleDownloadCancel() {

View File

@ -30,7 +30,6 @@
#include "mozilla/layers/PCompositorChild.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/Preferences.h"
#include "mozilla/unused.h"
#include "nsIMemoryReporter.h"
#include "nsIMemoryInfoDumper.h"
@ -102,7 +101,6 @@
#include "AudioChannelService.h"
using namespace base;
using namespace mozilla;
using namespace mozilla::docshell;
using namespace mozilla::dom::bluetooth;
using namespace mozilla::dom::devicestorage;
@ -1085,24 +1083,14 @@ ContentChild::RecvFilePathUpdate(const nsString& type, const nsString& path, con
}
bool
ContentChild::RecvFileSystemUpdate(const nsString& aFsName,
const nsString& aName,
const int32_t& aState,
const int32_t& aMountGeneration)
ContentChild::RecvFileSystemUpdate(const nsString& aFsName, const nsString& aName, const int32_t &aState)
{
#ifdef MOZ_WIDGET_GONK
nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aName, aState,
aMountGeneration);
nsRefPtr<nsVolume> volume = new nsVolume(aFsName, aName, aState);
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;
}

View File

@ -183,10 +183,7 @@ 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,
const int32_t& aMountGeneration);
virtual bool RecvFileSystemUpdate(const nsString& aFsName, const nsString& aName, const int32_t& aState);
#ifdef ANDROID
gfxIntSize GetScreenSize() { return mScreenSize; }

View File

@ -102,7 +102,6 @@
#ifdef MOZ_WIDGET_GONK
#include "nsIVolume.h"
#include "nsIVolumeService.h"
using namespace mozilla::system;
#endif
#ifdef MOZ_B2G_BT
@ -236,9 +235,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
@ -1134,22 +1133,6 @@ 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,
@ -1229,15 +1212,12 @@ 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,
mountGeneration);
unused << SendFileSystemUpdate(volName, mountPoint, state);
}
#endif
#ifdef ACCESSIBILITY

View File

@ -326,8 +326,6 @@ 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;

View File

@ -327,8 +327,7 @@ child:
FilePathUpdate(nsString type, nsString filepath, nsCString reasons);
FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState,
int32_t mountGeneration);
FileSystemUpdate(nsString fsName, nsString mountPoint, int32_t fsState);
parent:
/**
@ -440,9 +439,6 @@ 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);
};

View File

@ -96,7 +96,7 @@ static const nsDependentCString sAutoVolumeName[] = { NS_LITERAL_CSTRING("sdcard
**************************************************************************/
static bool
ReadSysFile(const char* aFilename, char* aBuf, size_t aBufSize)
ReadSysFile(const char *aFilename, char *aBuf, size_t aBufSize)
{
int fd = open(aFilename, O_RDONLY);
if (fd < 0) {
@ -117,7 +117,7 @@ ReadSysFile(const char* aFilename, char* aBuf, size_t aBufSize)
}
static bool
ReadSysFile(const char* aFilename, bool* aVal)
ReadSysFile(const char *aFilename, bool *aVal)
{
char valBuf[20];
if (!ReadSysFile(aFilename, valBuf, sizeof(valBuf))) {
@ -133,7 +133,7 @@ ReadSysFile(const char* aFilename, bool* aVal)
/***************************************************************************/
inline const char* SwitchStateStr(const SwitchEvent& aEvent)
inline const char *SwitchStateStr(const SwitchEvent &aEvent)
{
return aEvent.status() == SWITCH_STATE_ON ? "plugged" : "unplugged";
}
@ -168,7 +168,7 @@ IsUsbCablePluggedIn()
class AutoVolumeManagerStateObserver : public VolumeManager::StateObserver
{
public:
virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
virtual void Notify(const VolumeManager::StateChangedEvent &aEvent);
};
// The AutoVolumeEventObserver allows the AutoMounter to know about card
@ -176,7 +176,7 @@ public:
class AutoVolumeEventObserver : public Volume::EventObserver
{
public:
virtual void Notify(Volume * const & aEvent);
virtual void Notify(Volume * const &aEvent);
};
class AutoMounterResponseCallback : public VolumeResponseCallback
@ -188,7 +188,7 @@ public:
}
protected:
virtual void ResponseReceived(const VolumeCommand* aCommand);
virtual void ResponseReceived(const VolumeCommand *aCommand);
private:
const static int kMaxErrorCount = 3; // Max number of errors before we give up
@ -236,7 +236,7 @@ public:
void UpdateState();
const char* ModeStr(int32_t aMode)
const char *ModeStr(int32_t aMode)
{
switch (aMode) {
case AUTOMOUNTER_DISABLE: return "Disable";
@ -313,7 +313,7 @@ AutoVolumeEventObserver::Notify(Volume * const &)
}
void
AutoMounterResponseCallback::ResponseReceived(const VolumeCommand* aCommand)
AutoMounterResponseCallback::ResponseReceived(const VolumeCommand *aCommand)
{
if (WasSuccessful()) {
@ -398,16 +398,8 @@ AutoMounter::UpdateState()
RefPtr<Volume> vol = mAutoVolume[volIndex];
Volume::STATE volState = vol->State();
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");
}
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;
@ -417,24 +409,17 @@ 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; // UpdateState will be called again when the Unmount command completes
return;
}
case nsIVolume::STATE_IDLE: {
// Volume is unmounted. We can go ahead and share.
DBG("UpdateState: Sharing %s", vol->NameStr());
vol->StartShare(mResponseCallback);
return; // UpdateState will be called again when the Share command completes
return;
}
default: {
// Not in a state that we can do anything about.
@ -448,14 +433,14 @@ AutoMounter::UpdateState()
// Volume is shared. We can go ahead and unshare.
DBG("UpdateState: Unsharing %s", vol->NameStr());
vol->StartUnshare(mResponseCallback);
return; // UpdateState will be called again when the Unshare command completes
return;
}
case nsIVolume::STATE_IDLE: {
// Volume is unmounted, try to mount.
DBG("UpdateState: Mounting %s", vol->NameStr());
vol->StartMount(mResponseCallback);
return; // UpdateState will be called again when Mount command completes
return;
}
default: {
// Not in a state that we can do anything about.
@ -487,7 +472,7 @@ ShutdownAutoMounterIOThread()
}
static void
SetAutoMounterModeIOThread(const int32_t& aMode)
SetAutoMounterModeIOThread(const int32_t &aMode)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
MOZ_ASSERT(sAutoMounter);
@ -530,7 +515,7 @@ public:
UnregisterSwitchObserver(SWITCH_USB, this);
}
virtual void Notify(const SwitchEvent& aEvent)
virtual void Notify(const SwitchEvent &aEvent)
{
DBG("UsbCable switch device: %d state: %s\n",
aEvent.device(), SwitchStateStr(aEvent));

View File

@ -35,7 +35,7 @@ public:
SettingsServiceCallback() {}
NS_IMETHOD Handle(const nsAString& aName, const JS::Value& aResult) {
NS_IMETHOD Handle(const nsAString &aName, const JS::Value &aResult) {
if (JSVAL_IS_INT(aResult)) {
int32_t mode = JSVAL_TO_INT(aResult);
SetAutoMounterMode(mode);
@ -43,7 +43,7 @@ public:
return NS_OK;
}
NS_IMETHOD HandleError(const nsAString& aName) {
NS_IMETHOD HandleError(const nsAString &aName) {
ERR("SettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
return NS_OK;
}
@ -95,9 +95,9 @@ AutoMounterSetting::~AutoMounterSetting()
NS_IMPL_ISUPPORTS1(AutoMounterSetting, nsIObserver)
NS_IMETHODIMP
AutoMounterSetting::Observe(nsISupports* aSubject,
const char* aTopic,
const PRUnichar* aData)
AutoMounterSetting::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
return NS_OK;
@ -115,7 +115,7 @@ AutoMounterSetting::Observe(nsISupports* aSubject,
ERR("Failed to get JSContextStack");
return NS_OK;
}
JSContext* cx = stack->GetSafeJSContext();
JSContext *cx = stack->GetSafeJSContext();
if (!cx) {
ERR("Failed to GetSafeJSContext");
return NS_OK;
@ -126,7 +126,7 @@ AutoMounterSetting::Observe(nsISupports* aSubject,
!val.isObject()) {
return NS_OK;
}
JSObject& obj(val.toObject());
JSObject &obj(val.toObject());
JS::Value key;
if (!JS_GetProperty(cx, &obj, "key", &key) ||
!key.isString()) {

View File

@ -39,7 +39,6 @@ XPIDLSRCS = \
nsINetworkManager.idl \
nsIRadioInterfaceLayer.idl \
nsIVolume.idl \
nsIVolumeMountLock.idl \
nsIVolumeService.idl \
nsIVolumeStat.idl \
nsIWorkerHolder.idl \
@ -64,7 +63,6 @@ CPPSRCS += \
GonkGPSGeolocationProvider.cpp \
AudioChannelManager.cpp \
nsVolume.cpp \
nsVolumeMountLock.cpp \
nsVolumeService.cpp \
nsVolumeStat.cpp \
TimeZoneSettingObserver.cpp \
@ -77,8 +75,8 @@ CPPSRCS += \
# for our local copy of AudioSystem.h
LOCAL_INCLUDES += -I$(topsrcdir)/media/libsydneyaudio/src
EXPORTS = \
GonkGPSGeolocationProvider.h \
nsVolume.h \
GonkGPSGeolocationProvider.h \
$(NULL)
endif

View File

@ -16,48 +16,12 @@ 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)
Volume::Volume(const nsCSubstring &aName)
: mMediaPresent(true),
mState(nsIVolume::STATE_INIT),
mName(aName),
mMountGeneration(-1),
mMountLocked(true) // Needs to agree with nsVolume::nsVolume
mName(aName)
{
DBG("Volume %s: created", NameStr());
}
@ -65,9 +29,6 @@ Volume::Volume(const nsCSubstring& aName)
void
Volume::SetMediaPresent(bool aMediaPresent)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
// mMediaPresent is slightly redunant to the state, however
// when media is removed (while Idle), we get the following:
// 631 Volume sdcard /mnt/sdcard disk removed (179:0)
@ -103,19 +64,13 @@ Volume::SetMediaPresent(bool aMediaPresent)
void
Volume::SetState(Volume::STATE aNewState)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (aNewState == mState) {
return;
}
if (aNewState == nsIVolume::STATE_MOUNTED) {
mMountGeneration = ++sMountGeneration;
LOG("Volume %s: changing state from %s to %s @ '%s' (%d observers) "
"mountGeneration = %d, locked = %d",
LOG("Volume %s: changing state from %s to %s @ '%s' (%d observers)",
NameStr(), StateStr(mState),
StateStr(aNewState), mMountPoint.get(), mEventObserverList.Length(),
mMountGeneration, (int)mMountLocked);
StateStr(aNewState), mMountPoint.get(), mEventObserverList.Length());
} else {
LOG("Volume %s: changing state from %s to %s (%d observers)",
NameStr(), StateStr(mState),
@ -131,11 +86,8 @@ Volume::SetState(Volume::STATE aNewState)
}
void
Volume::SetMountPoint(const nsCSubstring& aMountPoint)
Volume::SetMountPoint(const nsCSubstring &aMountPoint)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (mMountPoint.Equals(aMountPoint)) {
return;
}
@ -144,55 +96,39 @@ Volume::SetMountPoint(const nsCSubstring& aMountPoint)
}
void
Volume::StartMount(VolumeResponseCallback* aCallback)
Volume::StartMount(VolumeResponseCallback *aCallback)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
StartCommand(new VolumeActionCommand(this, "mount", "", aCallback));
}
void
Volume::StartUnmount(VolumeResponseCallback* aCallback)
Volume::StartUnmount(VolumeResponseCallback *aCallback)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
StartCommand(new VolumeActionCommand(this, "unmount", "force", aCallback));
}
void
Volume::StartShare(VolumeResponseCallback* aCallback)
Volume::StartShare(VolumeResponseCallback *aCallback)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
StartCommand(new VolumeActionCommand(this, "share", "ums", aCallback));
}
void
Volume::StartUnshare(VolumeResponseCallback* aCallback)
Volume::StartUnshare(VolumeResponseCallback *aCallback)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
StartCommand(new VolumeActionCommand(this, "unshare", "ums", aCallback));
}
void
Volume::StartCommand(VolumeCommand* aCommand)
Volume::StartCommand(VolumeCommand *aCommand)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
VolumeManager::PostCommand(aCommand);
}
//static
void
Volume::RegisterObserver(Volume::EventObserver* aObserver)
Volume::RegisterObserver(Volume::EventObserver *aObserver)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
mEventObserverList.AddObserver(aObserver);
@ -206,40 +142,16 @@ Volume::RegisterObserver(Volume::EventObserver* aObserver)
//static
void
Volume::UnregisterObserver(Volume::EventObserver* aObserver)
Volume::UnregisterObserver(Volume::EventObserver *aObserver)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
mEventObserverList.RemoveObserver(aObserver);
}
//static
void
Volume::UpdateMountLock(const nsACString& aVolumeName,
const int32_t& aMountGeneration,
const bool& aMountLocked)
Volume::HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer &aTokenizer)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
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)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
// The volume name will have already been parsed, and the tokenizer will point
// to the token after the volume name
switch (aResponseCode) {

View File

@ -27,63 +27,54 @@ namespace system {
class Volume : public RefCounted<Volume>
{
public:
Volume(const nsCSubstring& aVolumeName);
Volume(const nsCSubstring &aVolumeName);
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); }
static const char *StateStr(STATE aState) { return NS_VolumeStateStr(aState); }
const char *StateStr() const { return StateStr(mState); }
STATE State() const { return mState; }
const nsCString& Name() const { return mName; }
const char* NameStr() const { return mName.get(); }
const nsCString &Name() const { return mName; }
const char *NameStr() const { return mName.get(); }
// The mount point is the name of the directory where the volume is mounted.
// (i.e. path that leads to the files stored on the volume).
const nsCString& MountPoint() const { return mMountPoint; }
const nsCString &MountPoint() const { return mMountPoint; }
int32_t MountGeneration() const { return mMountGeneration; }
bool IsMountLocked() const { return mMountLocked; }
bool MediaPresent() const { return mMediaPresent; }
bool MediaPresent() const { return mMediaPresent; }
typedef mozilla::Observer<Volume *> EventObserver;
typedef mozilla::ObserverList<Volume *> EventObserverList;
// NOTE: that observers must live in the IOThread.
static void RegisterObserver(EventObserver* aObserver);
static void UnregisterObserver(EventObserver* aObserver);
static void RegisterObserver(EventObserver *aObserver);
static void UnregisterObserver(EventObserver *aObserver);
private:
friend class AutoMounter; // Calls StartXxx
friend class nsVolume; // Calls UpdateMountLock
friend class VolumeManager; // Calls HandleVoldResponse
friend class VolumeListCallback; // Calls SetMountPoint, SetState
// The StartXxx functions will queue up a command to the VolumeManager.
// You can queue up as many commands as you like, and aCallback will
// be called as each one completes.
void StartMount(VolumeResponseCallback* aCallback);
void StartUnmount(VolumeResponseCallback* aCallback);
void StartShare(VolumeResponseCallback* aCallback);
void StartUnshare(VolumeResponseCallback* aCallback);
void StartMount(VolumeResponseCallback *aCallback);
void StartUnmount(VolumeResponseCallback *aCallback);
void StartShare(VolumeResponseCallback *aCallback);
void StartUnshare(VolumeResponseCallback *aCallback);
void SetState(STATE aNewState);
void SetMediaPresent(bool aMediaPresent);
void SetMountPoint(const nsCSubstring& aMountPoint);
void StartCommand(VolumeCommand* aCommand);
void SetMountPoint(const nsCSubstring &aMountPoint);
void StartCommand(VolumeCommand *aCommand);
void HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer& aTokenizer);
static void UpdateMountLock(const nsACString& aVolumeName,
const int32_t& aMountGeneration,
const bool& aMountLocked);
void HandleVoldResponse(int aResponseCode, nsCWhitespaceTokenizer &aTokenizer);
bool mMediaPresent;
STATE mState;
const nsCString mName;
nsCString mMountPoint;
int32_t mMountGeneration;
bool mMountLocked;
static EventObserverList mEventObserverList;
};

View File

@ -39,10 +39,10 @@ namespace system {
*
***************************************************************************/
VolumeActionCommand::VolumeActionCommand(Volume* aVolume,
const char* aAction,
const char* aExtraArgs,
VolumeResponseCallback* aCallback)
VolumeActionCommand::VolumeActionCommand(Volume *aVolume,
const char *aAction,
const char *aExtraArgs,
VolumeResponseCallback *aCallback)
: VolumeCommand(aCallback),
mVolume(aVolume)
{
@ -75,7 +75,7 @@ VolumeActionCommand::VolumeActionCommand(Volume* aVolume,
*
***************************************************************************/
VolumeListCommand::VolumeListCommand(VolumeResponseCallback* aCallback)
VolumeListCommand::VolumeListCommand(VolumeResponseCallback *aCallback)
: VolumeCommand(NS_LITERAL_CSTRING("volume list"), aCallback)
{
}

View File

@ -59,14 +59,14 @@ public:
const nsCString &ResponseStr() const { return mResponseStr; }
protected:
virtual void ResponseReceived(const VolumeCommand* aCommand) = 0;
virtual void ResponseReceived(const VolumeCommand *aCommand) = 0;
private:
friend class VolumeCommand; // Calls HandleResponse and SetPending
void HandleResponse(const VolumeCommand* aCommand,
void HandleResponse(const VolumeCommand *aCommand,
int aResponseCode,
nsACString& aResponseStr)
nsACString &aResponseStr)
{
mResponseCode = aResponseCode;
mResponseStr = aResponseStr;
@ -102,14 +102,14 @@ private:
class VolumeCommand : public RefCounted<VolumeCommand>
{
public:
VolumeCommand(VolumeResponseCallback* aCallback)
VolumeCommand(VolumeResponseCallback *aCallback)
: mBytesConsumed(0),
mCallback(aCallback)
{
SetCmd(NS_LITERAL_CSTRING(""));
}
VolumeCommand(const nsACString& aCommand, VolumeResponseCallback* aCallback)
VolumeCommand(const nsACString &aCommand, VolumeResponseCallback *aCallback)
: mBytesConsumed(0),
mCallback(aCallback)
{
@ -118,7 +118,7 @@ public:
virtual ~VolumeCommand() {}
void SetCmd(const nsACString& aCommand)
void SetCmd(const nsACString &aCommand)
{
mCmd = aCommand;
// Add a null character. We want this to be included in the length since
@ -126,8 +126,8 @@ public:
mCmd.Append('\0');
}
const char* CmdStr() const { return mCmd.get(); }
const char* Data() const { return mCmd.Data() + mBytesConsumed; }
const char *CmdStr() const { return mCmd.get(); }
const char *Data() const { return mCmd.Data() + mBytesConsumed; }
size_t BytesConsumed() const { return mBytesConsumed; }
size_t BytesRemaining() const
@ -150,7 +150,7 @@ private:
}
}
void HandleResponse(int aResponseCode, nsACString& aResponseStr)
void HandleResponse(int aResponseCode, nsACString &aResponseStr)
{
if (mCallback) {
mCallback->HandleResponse(this, aResponseCode, aResponseStr);
@ -167,8 +167,8 @@ private:
class VolumeActionCommand : public VolumeCommand
{
public:
VolumeActionCommand(Volume* aVolume, const char* aAction,
const char* aExtraArgs, VolumeResponseCallback* aCallback);
VolumeActionCommand(Volume *aVolume, const char *aAction,
const char *aExtraArgs, VolumeResponseCallback *aCallback);
private:
RefPtr<Volume> mVolume;
@ -177,7 +177,7 @@ private:
class VolumeListCommand : public VolumeCommand
{
public:
VolumeListCommand(VolumeResponseCallback* aCallback);
VolumeListCommand(VolumeResponseCallback *aCallback);
};
} // system

View File

@ -95,20 +95,20 @@ VolumeManager::SetState(STATE aNewState)
//static
void
VolumeManager::RegisterStateObserver(StateObserver* aObserver)
VolumeManager::RegisterStateObserver(StateObserver *aObserver)
{
mStateObserverList.AddObserver(aObserver);
}
//static
void VolumeManager::UnregisterStateObserver(StateObserver* aObserver)
void VolumeManager::UnregisterStateObserver(StateObserver *aObserver)
{
mStateObserverList.RemoveObserver(aObserver);
}
//static
TemporaryRef<Volume>
VolumeManager::FindVolumeByName(const nsCSubstring& aName)
VolumeManager::FindVolumeByName(const nsCSubstring &aName)
{
if (!sVolumeManager) {
return NULL;
@ -126,7 +126,7 @@ VolumeManager::FindVolumeByName(const nsCSubstring& aName)
//static
TemporaryRef<Volume>
VolumeManager::FindAddVolumeByName(const nsCSubstring& aName)
VolumeManager::FindAddVolumeByName(const nsCSubstring &aName)
{
RefPtr<Volume> vol = FindVolumeByName(aName);
if (vol) {
@ -140,7 +140,7 @@ VolumeManager::FindAddVolumeByName(const nsCSubstring& aName)
class VolumeListCallback : public VolumeResponseCallback
{
virtual void ResponseReceived(const VolumeCommand* aCommand)
virtual void ResponseReceived(const VolumeCommand *aCommand)
{
switch (ResponseCode()) {
case ResponseCode::VolumeListResult: {
@ -206,7 +206,7 @@ VolumeManager::OpenSocket()
//static
void
VolumeManager::PostCommand(VolumeCommand* aCommand)
VolumeManager::PostCommand(VolumeCommand *aCommand)
{
if (!sVolumeManager) {
ERR("VolumeManager not initialized. Dropping command '%s'", aCommand->Data());
@ -241,7 +241,7 @@ VolumeManager::WriteCommandData()
return;
}
VolumeCommand* cmd = mCommands.front();
VolumeCommand *cmd = mCommands.front();
if (cmd->BytesRemaining() == 0) {
// All bytes have been written. We're waiting for a response.
return;
@ -275,7 +275,7 @@ void
VolumeManager::OnLineRead(int aFd, nsDependentCSubstring& aMessage)
{
MOZ_ASSERT(aFd == mSocket.get());
char* endPtr;
char *endPtr;
int responseCode = strtol(aMessage.Data(), &endPtr, 10);
if (*endPtr == ' ') {
endPtr++;
@ -292,7 +292,7 @@ VolumeManager::OnLineRead(int aFd, nsDependentCSubstring& aMessage)
} else {
// Everything else is considered to be part of the command response.
if (mCommands.size() > 0) {
VolumeCommand* cmd = mCommands.front();
VolumeCommand *cmd = mCommands.front();
cmd->HandleResponse(responseCode, responseLine);
if (responseCode >= ResponseCode::CommandOkay) {
// That's a terminating response. We can remove the command.
@ -315,7 +315,7 @@ VolumeManager::OnFileCanWriteWithoutBlocking(int aFd)
}
void
VolumeManager::HandleBroadcast(int aResponseCode, nsCString& aResponseLine)
VolumeManager::HandleBroadcast(int aResponseCode, nsCString &aResponseLine)
{
// Format of the line is something like:
//

View File

@ -103,8 +103,8 @@ public:
};
static STATE State();
static const char* StateStr(STATE aState);
static const char* StateStr() { return StateStr(State()); }
static const char *StateStr(STATE aState);
static const char *StateStr() { return StateStr(State()); }
class StateChangedEvent
{
@ -115,8 +115,8 @@ public:
typedef mozilla::Observer<StateChangedEvent> StateObserver;
typedef mozilla::ObserverList<StateChangedEvent> StateObserverList;
static void RegisterStateObserver(StateObserver* aObserver);
static void UnregisterStateObserver(StateObserver* aObserver);
static void RegisterStateObserver(StateObserver *aObserver);
static void UnregisterStateObserver(StateObserver *aObserver);
//-----------------------------------------------------------------------
@ -124,10 +124,10 @@ public:
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);
static TemporaryRef<Volume> FindVolumeByName(const nsCSubstring &aName);
static TemporaryRef<Volume> FindAddVolumeByName(const nsCSubstring &aName);
static void PostCommand(VolumeCommand* aCommand);
static void PostCommand(VolumeCommand *aCommand);
protected:
@ -144,7 +144,7 @@ private:
void Restart();
void WriteCommandData();
void HandleBroadcast(int aResponseCode, nsCString& aResponseLine);
void HandleBroadcast(int aResponseCode, nsCString &aResponseLine);
typedef std::queue<RefPtr<VolumeCommand> > CommandQueue;

View File

@ -12,8 +12,7 @@
namespace mozilla {
namespace system {
VolumeServiceIOThread::VolumeServiceIOThread(nsVolumeService* aVolumeService)
: mVolumeService(aVolumeService)
VolumeServiceIOThread::VolumeServiceIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
@ -30,17 +29,17 @@ VolumeServiceIOThread::~VolumeServiceIOThread()
}
void
VolumeServiceIOThread::Notify(Volume* const & aVolume)
VolumeServiceIOThread::Notify(Volume * const &aVolume)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
return;
}
mVolumeService->UpdateVolumeIOThread(aVolume);
nsVolumeService::UpdateVolumeIOThread(aVolume);
}
void
VolumeServiceIOThread::Notify(const VolumeManager::StateChangedEvent& aEvent)
VolumeServiceIOThread::Notify(const VolumeManager::StateChangedEvent &aEvent)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
UpdateAllVolumes();
@ -58,17 +57,17 @@ VolumeServiceIOThread::UpdateAllVolumes()
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<Volume> vol = VolumeManager::GetVolume(volIndex);
mVolumeService->UpdateVolumeIOThread(vol);
nsVolumeService::UpdateVolumeIOThread(vol);
}
}
static StaticRefPtr<VolumeServiceIOThread> sVolumeServiceIOThread;
static RefPtr<VolumeServiceIOThread> sVolumeServiceIOThread;
void
InitVolumeServiceIOThread(nsVolumeService* const & aVolumeService)
InitVolumeServiceIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
sVolumeServiceIOThread = new VolumeServiceIOThread(aVolumeService);
sVolumeServiceIOThread = new VolumeServiceIOThread();
}
void

View File

@ -12,8 +12,6 @@
namespace mozilla {
namespace system {
class nsVolumeService;
/***************************************************************************
* The nsVolumeServiceIOThread is a companion class to the nsVolumeService
* class, but whose methods are called from IOThread.
@ -23,19 +21,18 @@ class VolumeServiceIOThread : public VolumeManager::StateObserver,
public RefCounted<VolumeServiceIOThread>
{
public:
VolumeServiceIOThread(nsVolumeService* aVolumeService);
VolumeServiceIOThread();
~VolumeServiceIOThread();
private:
void UpdateAllVolumes();
virtual void Notify(const VolumeManager::StateChangedEvent& aEvent);
virtual void Notify(Volume* const & aVolume);
virtual void Notify(const VolumeManager::StateChangedEvent &aEvent);
virtual void Notify(Volume * const &aVolume);
RefPtr<nsVolumeService> mVolumeService;
};
void InitVolumeServiceIOThread(nsVolumeService* const & aVolumeService);
void InitVolumeServiceIOThread();
void ShutdownVolumeServiceIOThread();
} // system

View File

@ -55,7 +55,7 @@ public:
obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
}
void LogVolume(nsIVolume* vol)
void LogVolume(nsIVolume *vol)
{
nsString volName;
nsString mountPoint;
@ -92,9 +92,9 @@ static nsCOMPtr<VolumeTestObserver> sTestObserver;
NS_IMPL_ISUPPORTS1(VolumeTestObserver, nsIObserver)
NS_IMETHODIMP
VolumeTestObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const PRUnichar* aData)
VolumeTestObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
LOG("TestObserver: topic: %s", aTopic);

View File

@ -5,7 +5,7 @@
#include "nsISupports.idl"
#include "nsIVolumeStat.idl"
[scriptable, uuid(1134f267-7b81-42f2-b64a-6edb91286576)]
[scriptable, uuid(3c9cae8d-9da2-4aa1-b8bf-4db8c8620808)]
interface nsIVolume : nsISupports
{
// These MUST match the states from android's system/vold/Volume.h header
@ -20,31 +20,12 @@ 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();
};
@ -56,7 +37,7 @@ namespace mozilla {
namespace system {
// Convert a state into a loggable/printable string.
const char* NS_VolumeStateStr(int32_t aState);
const char *NS_VolumeStateStr(int32_t aState);
} // system
} // mozilla

View File

@ -1,12 +0,0 @@
/* 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();
};

View File

@ -4,21 +4,16 @@
#include "nsISupports.idl"
#include "nsIVolume.idl"
#include "nsIVolumeMountLock.idl"
[scriptable, uuid(597403c6-5ba4-4e7b-b3f4-ed3f05f775d8)]
[scriptable, uuid(b31bd379-4bd2-4189-a85b-c0927a266a85)]
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 \
{0x597403c6, 0x5ba4, 0x4e7b, {0xb3, 0xf4, 0xed, 0x3f, 0x05, 0xf7, 0x75, 0xd8}}
{0xb31bd379, 0x4bd2, 0x4189, {0xa8, 0x5b, 0xc0, 0x92, 0x7a, 0x26, 0x6a, 0x85}}
#define NS_VOLUMESERVICE_CONTRACTID "@mozilla.org/telephony/volume-service;1"
%}

View File

@ -3,20 +3,11 @@
* 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 {
@ -38,49 +29,28 @@ NS_VolumeStateStr(int32_t aState)
return "???";
}
// While nsVolumes can only be used on the main thread, in the
// UpdateVolumeRunnable constructor (which is called from IOThread) we
// allocate an nsVolume which is then passed to MainThread. Since we
// have a situation where we allocate on one thread and free on another
// we use a thread safe AddRef implementation.
NS_IMPL_THREADSAFE_ISUPPORTS1(nsVolume, nsIVolume)
nsVolume::nsVolume(const Volume* aVolume)
nsVolume::nsVolume(const Volume *aVolume)
: mName(NS_ConvertUTF8toUTF16(aVolume->Name())),
mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
mState(aVolume->State()),
mMountGeneration(aVolume->MountGeneration()),
mMountLocked(aVolume->IsMountLocked())
mState(aVolume->State())
{
}
NS_IMETHODIMP nsVolume::GetName(nsAString& aName)
NS_IMETHODIMP nsVolume::GetName(nsAString &aName)
{
aName = mName;
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)
NS_IMETHODIMP nsVolume::GetMountPoint(nsAString &aMountPoint)
{
aMountPoint = mMountPoint;
return NS_OK;
}
NS_IMETHODIMP nsVolume::GetState(int32_t* aState)
NS_IMETHODIMP nsVolume::GetState(int32_t *aState)
{
*aState = mState;
return NS_OK;
@ -96,80 +66,5 @@ 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)
{
MOZ_ASSERT(NS_IsMainThread());
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)
{
MOZ_ASSERT(NS_IsMainThread());
// 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)
{
MOZ_ASSERT(NS_IsMainThread());
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

View File

@ -5,16 +5,13 @@
#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
{
@ -22,69 +19,51 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIVOLUME
// This constructor is used by the UpdateVolumeRunnable constructor
nsVolume(const Volume* aVolume);
nsVolume(const Volume *aVolume);
// 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)
nsVolume(const nsAString &aName, const nsAString &aMountPoint, const int32_t &aState)
: mName(aName), mMountPoint(aMountPoint), mState(aState)
{
}
// This constructor is used by nsVolumeService::FindAddVolumeByName, and
// will be followed shortly by a Set call.
nsVolume(const nsAString& aName)
nsVolume(const nsAString &aName)
: mName(aName),
mState(STATE_INIT),
mMountGeneration(-1),
mMountLocked(true) // Needs to agree with Volume::Volume
mState(STATE_INIT)
{
}
bool Equals(const nsVolume* aVolume)
bool Equals(const nsVolume *aVolume)
{
return mName.Equals(aVolume->mName)
&& mMountPoint.Equals(aVolume->mMountPoint)
&& (mState == aVolume->mState)
&& (mMountGeneration == aVolume->mMountGeneration)
&& (mMountLocked == aVolume->mMountLocked);
&& (mState == aVolume->mState);
}
void Set(const nsVolume* aVolume);
void Set(const nsVolume *aVolume)
{
mName = aVolume->mName;
mMountPoint = aVolume->mMountPoint;
mState = aVolume->mState;
}
void LogState() const;
const nsString &Name() const { return mName; }
const char *NameStr() const { return NS_LossyConvertUTF16toASCII(mName).get(); }
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(); }
const nsString &MountPoint() const { return mMountPoint; }
const char *MountPointStr() const { return NS_LossyConvertUTF16toASCII(mMountPoint).get(); }
int32_t State() const { return mState; }
const char* StateStr() const { return NS_VolumeStateStr(mState); }
const char *StateStr() const { return NS_VolumeStateStr(mState); }
typedef nsTArray<nsRefPtr<nsVolume> > Array;
private:
~nsVolume() {}
friend class nsVolumeService; // Calls the following XxxMountLock functions
void UpdateMountLock(const nsAString& aMountLockState);
void UpdateMountLock(bool aMountLocked);
protected:
nsString mName;
nsString mMountPoint;
int32_t mState;
int32_t mMountGeneration;
bool mMountLocked;
};
} // system

View File

@ -1,157 +0,0 @@
/* 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

View File

@ -1,53 +0,0 @@
/* 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__

View File

@ -11,10 +11,8 @@
#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"
@ -23,9 +21,7 @@
#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"
@ -33,107 +29,31 @@
#include <stdlib.h>
using namespace mozilla::dom;
using namespace mozilla::services;
namespace mozilla {
namespace system {
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;
}
NS_IMPL_ISUPPORTS1(nsVolumeService, nsIVolumeService)
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, this));
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
if (!pmService) {
return;
}
pmService->AddWakeLockListener(this);
NewRunnableFunction(InitVolumeServiceIOThread));
}
nsVolumeService::~nsVolumeService()
{
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(ShutdownVolumeServiceIOThread));
}
// 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)
/* nsIVolume getVolumeByName (in DOMString volName); */
NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString &aVolName, nsIVolume **aResult)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
@ -147,7 +67,8 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVol
return NS_OK;
}
NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
/* nsIVolume getVolumeByPath (in DOMString path); */
NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString &aPath, nsIVolume **aResult)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath);
@ -184,42 +105,12 @@ 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,
-1 /*generation*/);
aPath, nsIVolume::STATE_MOUNTED);
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)
already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString &aName)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread());
@ -235,8 +126,7 @@ already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString& aN
return NULL;
}
//static
already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString& aName)
already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString &aName)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread());
@ -252,7 +142,7 @@ already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString&
return vol.forget();
}
void nsVolumeService::UpdateVolume(const nsVolume* aVolume)
void nsVolumeService::UpdateVolume(const nsVolume *aVolume)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread());
@ -267,6 +157,13 @@ 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());
}
@ -278,9 +175,8 @@ void nsVolumeService::UpdateVolume(const nsVolume* aVolume)
class UpdateVolumeRunnable : public nsRunnable
{
public:
UpdateVolumeRunnable(nsVolumeService* aVolumeService, const Volume* aVolume)
: mVolumeService(aVolumeService),
mVolume(new nsVolume(aVolume))
UpdateVolumeRunnable(const Volume *aVolume)
: mVolume(new nsVolume(aVolume))
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
}
@ -288,29 +184,34 @@ public:
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
DBG("UpdateVolumeRunnable::Run '%s' state %s gen %d locked %d",
mVolume->NameStr(), mVolume->StateStr(), mVolume->MountGeneration(),
(int)mVolume->IsMountLocked());
DBG("UpdateVolumeRunnable::Run '%s' state %s",
mVolume->NameStr(), mVolume->StateStr());
mVolumeService->UpdateVolume(mVolume);
mVolumeService = NULL;
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<nsVolumeService> mVolumeService;
nsRefPtr<nsVolume> mVolume;
nsRefPtr<nsVolume> mVolume;
};
void nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
//static
void nsVolumeService::UpdateVolumeIOThread(const Volume *aVolume)
{
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d",
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
aVolume->MountGeneration(), (int)aVolume->IsMountLocked());
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s'",
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get());
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
NS_DispatchToMainThread(new UpdateVolumeRunnable(aVolume));
}
} // namespace system
} // namespace mozilla
} // system
} // mozilla

View File

@ -5,10 +5,7 @@
#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"
@ -17,41 +14,29 @@
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 MOZ_FINAL : public nsIVolumeService,
public nsIDOMMozWakeLockListener
class nsVolumeService : public nsIVolumeService
{
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);
void UpdateVolumeIOThread(const Volume* aVolume);
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;
static StaticRefPtr<nsVolumeService> sSingleton;
nsVolume::Array mVolumeArray;
};
} // system

View File

@ -10,7 +10,7 @@ namespace system {
NS_IMPL_ISUPPORTS1(nsVolumeStat, nsIVolumeStat)
nsVolumeStat::nsVolumeStat(const nsAString& aPath)
nsVolumeStat::nsVolumeStat(const nsAString &aPath)
{
nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath);
@ -24,14 +24,14 @@ nsVolumeStat::~nsVolumeStat()
}
/* readonly attribute long long totalBytes; */
NS_IMETHODIMP nsVolumeStat::GetTotalBytes(int64_t* aTotalBytes)
NS_IMETHODIMP nsVolumeStat::GetTotalBytes(int64_t *aTotalBytes)
{
*aTotalBytes = mStat.f_blocks * mStat.f_bsize;
return NS_OK;
}
/* readonly attribute long long freeBytes; */
NS_IMETHODIMP nsVolumeStat::GetFreeBytes(int64_t* aFreeBytes)
NS_IMETHODIMP nsVolumeStat::GetFreeBytes(int64_t *aFreeBytes)
{
*aFreeBytes = mStat.f_bfree * mStat.f_bsize;
return NS_OK;

View File

@ -18,7 +18,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIVOLUMESTAT
nsVolumeStat(const nsAString& aPath);
nsVolumeStat(const nsAString &aPath);
private:
~nsVolumeStat();

View File

@ -296,6 +296,7 @@ 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
@ -324,10 +325,6 @@ 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)

View File

@ -87,11 +87,6 @@
#include "AudioStream.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include "nsVolumeService.h"
using namespace mozilla::system;
#endif
#include "nsError.h"
#include "nsCycleCollector.h"
@ -354,10 +349,6 @@ nsLayoutStatics::Shutdown()
WMFDecoder::UnloadDLLs();
#endif
#ifdef MOZ_WIDGET_GONK
nsVolumeService::Shutdown();
#endif
nsCORSListenerProxy::Shutdown();
nsIPresShell::ReleaseStatics();

View File

@ -74,18 +74,10 @@ const KEY_GRED = "GreD";
#define USE_UPDROOT
#endif
#ifdef MOZ_WIDGET_GONK
#define USE_UPDATE_ARCHIVE_DIR
#endif
#ifdef USE_UPDROOT
const KEY_UPDROOT = "UpdRootD";
#endif
#ifdef USE_UPDATE_ARCHIVE_DIR
const KEY_UPDATE_ARCHIVE_DIR = "UpdArchD"
#endif
#ifdef XP_WIN
#define SKIP_STAGE_UPDATES_TEST
#elifdef MOZ_WIDGET_GONK
@ -107,8 +99,7 @@ const FILE_UPDATE_ARCHIVE = "update.apk";
#else
const FILE_UPDATE_ARCHIVE = "update.mar";
#endif
const FILE_UPDATE_LINK = "update.link";
const FILE_UPDATE_LOG = "update.log";
const FILE_UPDATE_LOG = "update.log"
const FILE_UPDATES_DB = "updates.xml";
const FILE_UPDATE_ACTIVE = "active-update.xml";
const FILE_PERMS_TEST = "update.test";
@ -164,7 +155,6 @@ const CERT_ATTR_CHECK_FAILED_NO_UPDATE = 100;
const CERT_ATTR_CHECK_FAILED_HAS_UPDATE = 101;
const BACKGROUNDCHECK_MULTIPLE_FAILURES = 110;
const NETWORK_ERROR_OFFLINE = 111;
const FILE_ERROR_TOO_BIG = 112;
const DOWNLOAD_CHUNK_SIZE = 300000; // bytes
const DOWNLOAD_BACKGROUND_INTERVAL = 600; // seconds
@ -184,12 +174,6 @@ const DEFAULT_SOCKET_MAX_ERRORS = 10;
const DEFAULT_UPDATE_RETRY_TIMEOUT = 2000;
var gLocale = null;
#ifdef MOZ_B2G
var gVolumeMountLock = null;
XPCOMUtils.defineLazyGetter(this, "gExtStorage", function aus_gExtStorage() {
return Services.env.get("EXTERNAL_STORAGE");
});
#endif
XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
"resource://gre/modules/UpdateChannel.jsm");
@ -747,74 +731,6 @@ function writeStatusFile(dir, state) {
writeStringToFile(statusFile, state);
}
/**
* Reads the link file from the update.link file in the
* specified directory.
* @param dir
* The dir to look for an update.link file in
* @return The contents of the update.link file.
*/
function readLinkFile(dir) {
var linkFile = dir.clone();
linkFile.append(FILE_UPDATE_LINK);
var link = readStringFromFile(linkFile) || STATE_NONE;
LOG("readLinkFile - link: " + link + ", path: " + linkFile.path);
return status;
}
/**
* Creates a link file, which allows the actual patch to live in
* a directory different from the update directory.
* @param dir
* The patch directory where the update.link file
* should be written.
* @param patchFile
* The fully qualified filename of the patchfile.
*/
function writeLinkFile(dir, patchFile) {
var linkFile = dir.clone();
linkFile.append(FILE_UPDATE_LINK);
writeStringToFile(linkFile, patchFile.path);
#ifdef MOZ_B2G
if (patchFile.path.indexOf(gExtStorage) == 0) {
// The patchfile is being stored on external storage. Try to lock it
// so that it doesn't get shared with the PC while we're downloading
// to it.
acquireSDCardMountLock();
}
#endif
}
/**
* Acquires a VolumeMountLock for the sdcard volume.
*
* This prevents the SDCard from being shared with the PC while
* we're downloading the update.
*/
function acquireSDCardMountLock() {
#ifdef MOZ_B2G
let volsvc = Cc["@mozilla.org/telephony/volume-service;1"].
getService(Ci.nsIVolumeService);
if (volsvc) {
gSDCardMountLock = volsvc.createMountLock("sdcard");
}
#endif
}
/**
* Releases any SDCard mount lock that we might have.
*
* This once again allows the SDCard to be shared with the PC.
*/
function releaseSDCardMountLock() {
#ifdef MOZ_B2G
if (gSDCardMountLock) {
gSDCardMountLock.unlock();
gSDCardMountLock = null;
}
#endif
}
/**
* Determines if the service should be used to attempt an update
* or not. For now this is only when PREF_APP_UPDATE_SERVICE_ENABLED
@ -983,7 +899,6 @@ function cleanUpUpdatesDir(aBackgroundUpdate) {
LOG("cleanUpUpdatesDir - failed to remove file " + f.path);
}
}
releaseSDCardMountLock();
}
/**
@ -2883,8 +2798,6 @@ UpdateManager.prototype = {
var prompter = Cc["@mozilla.org/updates/update-prompt;1"].
createInstance(Ci.nsIUpdatePrompt);
prompter.showUpdateDownloaded(update, true);
} else {
releaseSDCardMountLock();
}
},
@ -3233,7 +3146,6 @@ Downloader.prototype = {
if (this._request && this._request instanceof Ci.nsIRequest) {
this._request.cancel(cancelError);
}
releaseSDCardMountLock();
},
/**
@ -3404,28 +3316,6 @@ Downloader.prototype = {
return this._request != null;
},
/**
* Get the nsIFile to use for downloading the active update's selected patch
*/
_getUpdateArchiveFile: function Downloader__getUpdateArchiveFile() {
var updateArchive;
#ifdef USE_UPDATE_ARCHIVE_DIR
try {
updateArchive = FileUtils.getDir(KEY_UPDATE_ARCHIVE_DIR, [], true);
} catch (e) {
if (e == Cr.NS_ERROR_FILE_TOO_BIG) {
this._update.errorCode = FILE_ERROR_TOO_BIG;
}
return null;
}
#else
updateArchive = getUpdatesDir().clone();
#endif
updateArchive.append(FILE_UPDATE_ARCHIVE);
return updateArchive;
},
/**
* Download and stage the given update.
* @param update
@ -3449,16 +3339,8 @@ Downloader.prototype = {
}
this.isCompleteUpdate = this._patch.type == "complete";
var patchFile = this._getUpdateArchiveFile();
if (!patchFile) {
return STATE_NONE;
}
if (patchFile.path.indexOf(updateDir.path) != 0) {
// The patchFile is in a directory which is different from the
// updateDir, create a link file.
writeLinkFile(updateDir, patchFile);
}
var patchFile = updateDir.clone();
patchFile.append(FILE_UPDATE_ARCHIVE);
var uri = Services.io.newURI(this._patch.URL, null, null);

View File

@ -2085,49 +2085,6 @@ ReadMARChannelIDs(const NS_tchar *path, MARChannelStringTable *results)
}
#endif
static int
GetUpdateFileName(NS_tchar *fileName, int maxChars)
{
#if defined(MOZ_WIDGET_GONK) // If an update.link file exists, then it will contain the name
// of the update file (terminated by a newline).
NS_tchar linkFileName[MAXPATHLEN];
NS_tsnprintf(linkFileName, sizeof(linkFileName)/sizeof(linkFileName[0]),
NS_T("%s/update.link"), gSourcePath);
AutoFile linkFile = NS_tfopen(linkFileName, NS_T("rb"));
if (linkFile == NULL) {
NS_tsnprintf(fileName, maxChars,
NS_T("%s/update.mar"), gSourcePath);
return OK;
}
char dataFileName[MAXPATHLEN];
size_t bytesRead;
if ((bytesRead = fread(dataFileName, 1, sizeof(dataFileName)-1, linkFile)) <= 0) {
*fileName = NS_T('\0');
return READ_ERROR;
}
if (dataFileName[bytesRead-1] == '\n') {
// Strip trailing newline (for \n and \r\n)
bytesRead--;
}
if (dataFileName[bytesRead-1] == '\r') {
// Strip trailing CR (for \r, \r\n)
bytesRead--;
}
dataFileName[bytesRead] = '\0';
strncpy(fileName, dataFileName, maxChars-1);
fileName[maxChars-1] = '\0';
#else
// We currently only support update.link files under GONK
NS_tsnprintf(fileName, maxChars,
NS_T("%s/update.mar"), gSourcePath);
#endif
return OK;
}
static void
UpdateThreadFunc(void *param)
{
@ -2137,10 +2094,10 @@ UpdateThreadFunc(void *param)
rv = ProcessReplaceRequest();
} else {
NS_tchar dataFile[MAXPATHLEN];
rv = GetUpdateFileName(dataFile, sizeof(dataFile)/sizeof(dataFile[0]));
if (rv == OK) {
rv = gArchiveReader.Open(dataFile);
}
NS_tsnprintf(dataFile, sizeof(dataFile)/sizeof(dataFile[0]),
NS_T("%s/update.mar"), gSourcePath);
rv = gArchiveReader.Open(dataFile);
#ifdef MOZ_VERIFY_MAR_SIGNATURE
if (rv == OK) {

View File

@ -987,17 +987,8 @@ nsUpdateProcessor::ProcessUpdate(nsIUpdate* aUpdate)
if (dirProvider) { // Normal code path
// Check for and process any available updates
bool persistent;
nsresult rv = NS_ERROR_FAILURE; // Take the NS_FAILED path when non-GONK
#ifdef MOZ_WIDGET_GONK
// Check in the sdcard for updates first, since that's our preferred
// download location.
rv = dirProvider->GetFile(XRE_UPDATE_ARCHIVE_DIR, &persistent,
getter_AddRefs(updRoot));
#endif
if (NS_FAILED(rv)) {
rv = dirProvider->GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
getter_AddRefs(updRoot));
}
nsresult rv = dirProvider->GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
getter_AddRefs(updRoot));
// XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
if (NS_FAILED(rv))
updRoot = dirProvider->GetAppDir();

View File

@ -123,14 +123,6 @@
*/
#define XRE_UPDATE_ROOT_DIR "UpdRootD"
/**
* A directory service key which provides an alternate location
* to UpdRootD to to store large files. This key is currently
* only implemented in the Gonk directory service provider.
*/
#define XRE_UPDATE_ARCHIVE_DIR "UpdArchD"
/**
* A directory service key which provides the directory where an OS update is
* applied.