Files
palemoon27/dom/system/gonk/nsVolumeService.cpp
T
roytam1 7edec4880a import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 859764 - Part 5: Changes in Test Cases. r=echen (f1a5cd4fd3)
- Bug 859764 - Part 6: Changes in Payment. r=ferjm, r=smaug (2b47641375)
- Bug 1010756 - Helpful errors for using nsCOMPtr on non-XPCOM types; r=froydnj (6b1521c482)
- leftover (e1a24351e9)
- Bug 1192102 - Remove unused file embedded/android/GeckoSmsManager.java. r=blassey (ac05ae649d)
- var-let (8ddb529f96)
- Bug 1181466 - Fix observe function in SmsService/MmsService. r=btseng (ca93122404)
- Bug 733331 - Part 2: Update enabledGsmTableTuples when MCC changes in SmsService.js and fix segmentChars in SmsSegmentHelper.jsm. r=btseng (24fa23e4be)
- Bug 1173156 - Fix typo and add a Marionette test case. r=btseng (e7199eb55a)
- Bug 1132774 - [B2G][SMS] Enable DEBUG Flag in SmsService if the default value of "ril.debugging.enabled" is true. r=btseng (7300d24fb7)
- Bug 1169160 - [MobileConnection] Support more call barring program: all service, outgoing service and incoming service. r=hsinyi,aknow (872c2cc056)
- Bug 1169225 - [MobileConnectionService] Support setting/getting call waiting on all serviceClass. r=aknow (14c546a9ca)
- Bug 1110619 - Part 1: IDL Interface Changes. r=echen (beae2b4b77)
- Bug 1168064 - B2G RIL: filter out cell info with unknown values. r=echen (11dfc5a7e8)
- Bug 1159591 - Part 2: Move MMI logic from ril_worker to telephonyService (Call Forwarding). r=aknow (b4edb76863)
- Bug 1159591 - Part 3: Move MMI logic from ril_worker to telephonyService (Icc Lock). r=aknow (3faba76808)
- Bug 1138263 - Make TelephonyService.js JSHint friendly. r=hsinyi (454bd4c765)
- Bug 1159591 - Part 4: Move MMI logic from ril_worker to telephonyService (IMEI). r=aknow (57f423ecdd)
- Bug 1159591 - Part 5: Move MMI logic from ril_worker to telephonyService (CLIP). r=aknow (c6611dbcb8)
- Bug 1159591 - Part 6: Move MMI logic from ril_worker to telephonyService (CLIR). r=aknow (8c1fc03edb)
- Bug 1159591 - Part 7: Move MMI logic from ril_worker to telephonyService (Call Barring Password). r=aknow (5d8bcbf177)
- Bug 1159591 - Part 8: Move MMI logic from ril_worker to telephonyService (Call Barring). r=aknow (aa0b89aea1)
- Bug 1159591 - Part 9: Move MMI logic from ril_worker to telephonyService (Call Waiting). r=aknow (1d14d2b864)
- Bug 1159591 - Part 10: Move MMI logic from ril_worker to telephonyService (USSD). r=aknow (c92130b5b2)
- Bug 1159591 - Part 11: Move MMI consts from ril_consts to telephonyService. r=aknow (0e7b3fea9a)
- Bug 1159591 - Part 12: Move radio check for MMI to a common place. r=aknow (dcdc3178ad)
- Bug 1110619 - Part 2: Implementation Changes. r=echen (6d8e78d684)
- Bug 1110619 - Part 3: Bluetooth Changes. r=btian (9787727be0)
- Bug 1147736 - Part 1: Extend TelephonyCallInfo. r=aknow (2a426cc99f)
- Bug 1147736 - Part 2: Bypass NotifyError. r=aknow (6cd6fd6867)
- Bug 1147736 - Part 3: Deprecate NotifyError. r=aknow (e41c719442)
- Bug 1147736 - Part 4: Deprecate NotifyError(Bluetooth). r=btian (9c8f97bb22)
- Bug 1204817 - Delete the child property of a parent call only when the parent call exists. r=btseng (d35dc6b08f)
- Bug 1191205 - Cancel USSD sessions only when needed. r=edgar (01a72dbacb)
- Bug 1200134 - Control USSD Sessions with State-Transitions instead of Boolean. r=echen (a4e55b3d9d)
- Bug 1163511 - Use defineLazyModuleGetter. r=hsinyi (8a97a4912c)
- Bug 991582 - Part 2: Handle the result of RIL request in a consistent way. r=aknow (914ecc2bbb)
- Bug 1164248 - Handling of session/sessionEnded for notifyUssdReceived. r=edgar (a79df75d38)
- Bug 1223662 - Part 1: Check mmiServiceCode with correct constant. r=echen (abeb286050)
- Bug 1174673 - Part 1: Automatically resume the held call. r=hsinyi (280543af7d)
- Bug 1174673 - Part 2: Update test case. r=hsinyi (cfe19f1a52)
- Bug 1185156 - Fix bug in resuming held call. r=hsinyi (b96346d319)
- Bug 1162426 - Part 1: Provide TelephonyUtils. r=hsinyi (62b71e6e83)
- Bug 1162426 - Part 2: Test case. r=hsniyi (13a0b3c6f5)
- Bug 1171807 - Part 1: Add enums for TelephonyCall::State and TelephonyCallGroup::State (WebIDL). r=hsinyi (0b698eecc4)
- Bug 1145551 - DTMF should be sent using the active SIM, the given or the default one (in that order). r=aknow (6157636493)
- Bug 1171807 - Part 2: Move to enums and deprecate TelephonyCall.mCallState and TelephonyCallGroup.mCallState (DOM). r=btseng (5faef22d91)
- Bug 1168515 - do not block incall MMI requests on alerting state. r=aknow (b1f85c5789)
- Bug 1155072 - Part 1: Deprecate nsITelephonyListener.conferenceCallStateChanged (Telephony). r=btseng (e41d1a4bc9)
- Bug 1155072 - Part 2: Deprecate nsITelephonyListener.conferenceCallStateChanged (Bluetooth). r=btian (27e69fa89b)
- Bug 1166936 - JS Warning in TelephonyService.js r=aknow (3559d3ad3d)
- Bug 1191237 - Part 1: Enhance |TelephonyService.js|. r=aknow (86576a6d32)
- Bug 1202902 - Fix the world. (0dc256d67d)
- Bug 1161438 - Part 1 - Exporting contact to SIM should also return updated contact. r=echen (505d7d7f83)
- Bug 1159622 - Split test_icc_contact.js into read contact and add contact. r=echen (fec0c428df)
- Bug 1122376 - Support read SIM contact dialling number exceed 20 digits. r=echen (5d0599e93c)
- Bug 1161438 - Part 2 - marionette testcase. r=echen (1f0d18a479)
- Bug 1114937 - Part 5: Fix Test Case to Remove Contact with Correct Contact Id. r=echen (8d746fdbd2)
- Bug 1194149 - Continue importing contacts when there is no sufficient Type 2 USIM contact fields record. r=echen (e9be40dbf2)
- Bug 962995 - xpcshell tests for write ICC UCS2 characters for 0x81 and 0x82 encoding. r=echen (9500afaa4d)
- Bug 1161438 - Part 3 - xpcshell testcase. r=echen (01f7fb4514)
- Bug 1122376 - Support write SIM contact dialling number exceed 20 digits. r=echen (91133e286d)
- Bug 999300 - Part 1: Removed the Ril v5 legacy support. r=edgar (ded77fcb6f)
- Bug 999300 - Part 2: Update the related testcases. r=edgar (f77a8b96cc)
- Bug 1177146 - [Aries][RIL] Reply from QUERY_AVAILABLE_NETWORKS has extra strings. r=hsinyi (a6816cbbab)
- Bug 1043250 - Part 1: Update ril_worker and xpcshell test. r=btseng (8b9b25b5cf)
- Bug 1185406 - B2G RIL: Read 'pcscf' and expose it in nsIRilNetworkInfo. r=hsinyi (ce707ecb83)
- Bug 1174998 - Part 3: Read data call's MTU from network/apn settings. r=echen (bfa08d8380)
- Bug 1166320 - Make volume service safer to use off main thread. r=dhylands (b3976622ad)
- Bug 1177374 - Call realpath on volume mount points so thatVolumeService::GetVolumeByPath works properly. r=achen (aea97080eb)
- Bug 1195166 - AutoMounter: add ignore command to allow volumes to be ignored. r=alchen (f265d832c8)
- Bug 1196724 - Refactoring of AudioManager r=alwu (e5b896b7ce)
- Bug 1222564 - Save audio volume to database r=alwu (1303d01ae7)
- Bug 1164049 - Fix some mode lines in embedding/. r=smaug (79ddce4871)
2023-01-24 11:52:32 +08:00

556 lines
17 KiB
C++

/* 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 "nsIDOMWakeLockListener.h"
#include "nsIMutableArray.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIPowerManagerService.h"
#include "nsISupportsPrimitives.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 "nsVolumeMountLock.h"
#include "nsXULAppAPI.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/Services.h"
#undef VOLUME_MANAGER_LOG_TAG
#define VOLUME_MANAGER_LOG_TAG "nsVolumeService"
#include "VolumeManagerLog.h"
#include <stdlib.h>
using namespace mozilla::dom;
using namespace mozilla::services;
namespace mozilla {
namespace system {
NS_IMPL_ISUPPORTS(nsVolumeService,
nsIVolumeService,
nsIDOMMozWakeLockListener)
StaticRefPtr<nsVolumeService> nsVolumeService::sSingleton;
// static
already_AddRefed<nsVolumeService>
nsVolumeService::GetSingleton()
{
MOZ_ASSERT(NS_IsMainThread());
if (!sSingleton) {
sSingleton = new nsVolumeService();
}
RefPtr<nsVolumeService> volumeService = sSingleton.get();
return volumeService.forget();
}
// static
void
nsVolumeService::Shutdown()
{
if (!sSingleton) {
return;
}
if (!XRE_IsParentProcess()) {
sSingleton = nullptr;
return;
}
nsCOMPtr<nsIPowerManagerService> pmService =
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
if (pmService) {
pmService->RemoveWakeLockListener(sSingleton.get());
}
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(ShutdownVolumeServiceIOThread));
sSingleton = nullptr;
}
nsVolumeService::nsVolumeService()
: mArrayMonitor("nsVolumeServiceArray"),
mGotVolumesFromParent(false)
{
sSingleton = this;
if (!XRE_IsParentProcess()) {
// VolumeServiceIOThread and the WakeLock listener should only run in the
// parent, so we return early.
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);
}
nsVolumeService::~nsVolumeService()
{
}
// Callback for nsIDOMMozWakeLockListener
NS_IMETHODIMP
nsVolumeService::Callback(const nsAString& aTopic, const nsAString& aState)
{
CheckMountLock(aTopic, aState);
return NS_OK;
}
void nsVolumeService::DumpNoLock(const char* aLabel)
{
mArrayMonitor.AssertCurrentThreadOwns();
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
if (numVolumes == 0) {
LOG("%s: No Volumes!", aLabel);
return;
}
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<nsVolume> vol = mVolumeArray[volIndex];
vol->Dump(aLabel);
}
}
NS_IMETHODIMP
nsVolumeService::Dump(const nsAString& aLabel)
{
MonitorAutoLock autoLock(mArrayMonitor);
DumpNoLock(NS_LossyConvertUTF16toASCII(aLabel).get());
return NS_OK;
}
NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult)
{
MonitorAutoLock autoLock(mArrayMonitor);
RefPtr<nsVolume> vol = FindVolumeByName(aVolName);
if (!vol) {
return NS_ERROR_NOT_AVAILABLE;
}
vol.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
{
NS_ConvertUTF16toUTF8 utf8Path(aPath);
char realPathBuf[PATH_MAX];
while (realpath(utf8Path.get(), realPathBuf) < 0) {
if (errno != ENOENT) {
ERR("GetVolumeByPath: realpath on '%s' failed: %d", utf8Path.get(), errno);
return NSRESULT_FOR_ERRNO();
}
// The pathname we were passed doesn't exist, so we try stripping off trailing
// components until we get a successful call to realpath, or until we run out
// of components (if we finally get to /something then we also stop).
int32_t slashIndex = utf8Path.RFindChar('/');
if ((slashIndex == kNotFound) || (slashIndex == 0)) {
errno = ENOENT;
ERR("GetVolumeByPath: realpath on '%s' failed.", utf8Path.get());
return NSRESULT_FOR_ERRNO();
}
utf8Path.Assign(Substring(utf8Path, 0, slashIndex));
}
// 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));
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<nsVolume> vol = mVolumeArray[volIndex];
NS_ConvertUTF16toUTF8 volMountPointSlash(vol->MountPoint());
volMountPointSlash.Append('/');
nsDependentCSubstring testStr(realPathBuf, volMountPointSlash.Length());
if (volMountPointSlash.Equals(testStr)) {
vol.forget(aResult);
return NS_OK;
}
}
return NS_ERROR_FILE_NOT_FOUND;
}
NS_IMETHODIMP
nsVolumeService::CreateOrGetVolumeByPath(const nsAString& aPath, nsIVolume** aResult)
{
nsresult rv = GetVolumeByPath(aPath, aResult);
if (rv == NS_OK) {
return NS_OK;
}
// In order to support queries by the updater, we will fabricate a volume
// from the pathname, so that the caller can determine the volume size.
nsCOMPtr<nsIVolume> vol = new nsVolume(NS_LITERAL_STRING("fake"),
aPath, nsIVolume::STATE_MOUNTED,
-1 /* generation */,
true /* isMediaPresent*/,
false /* isSharing */,
false /* isFormatting */,
true /* isFake */,
false /* isUnmounting */,
false /* isRemovable */,
false /* isHotSwappable*/);
vol.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsVolumeService::GetVolumeNames(nsIArray** aVolNames)
{
NS_ENSURE_ARG_POINTER(aVolNames);
MonitorAutoLock autoLock(mArrayMonitor);
*aVolNames = nullptr;
nsresult rv;
nsCOMPtr<nsIMutableArray> volNames =
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<nsVolume> vol = mVolumeArray[volIndex];
nsCOMPtr<nsISupportsString> isupportsString =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = isupportsString->SetData(vol->Name());
NS_ENSURE_SUCCESS(rv, rv);
rv = volNames->AppendElement(isupportsString, false);
NS_ENSURE_SUCCESS(rv, rv);
}
volNames.forget(aVolNames);
return NS_OK;
}
void
nsVolumeService::GetVolumesForIPC(nsTArray<VolumeInfo>* aResult)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<nsVolume> vol = mVolumeArray[volIndex];
VolumeInfo* volInfo = aResult->AppendElement();
volInfo->name() = vol->mName;
volInfo->mountPoint() = vol->mMountPoint;
volInfo->volState() = vol->mState;
volInfo->mountGeneration() = vol->mMountGeneration;
volInfo->isMediaPresent() = vol->mIsMediaPresent;
volInfo->isSharing() = vol->mIsSharing;
volInfo->isFormatting() = vol->mIsFormatting;
volInfo->isFake() = vol->mIsFake;
volInfo->isUnmounting() = vol->mIsUnmounting;
volInfo->isRemovable() = vol->mIsRemovable;
volInfo->isHotSwappable() = vol->mIsHotSwappable;
}
}
void
nsVolumeService::RecvVolumesFromParent(const nsTArray<VolumeInfo>& aVolumes)
{
if (XRE_IsParentProcess()) {
// We are the parent. Therefore our volumes are already correct.
return;
}
if (mGotVolumesFromParent) {
// We've already done this, no need to do it again.
return;
}
for (uint32_t i = 0; i < aVolumes.Length(); i++) {
const VolumeInfo& volInfo(aVolumes[i]);
RefPtr<nsVolume> vol = new nsVolume(volInfo.name(),
volInfo.mountPoint(),
volInfo.volState(),
volInfo.mountGeneration(),
volInfo.isMediaPresent(),
volInfo.isSharing(),
volInfo.isFormatting(),
volInfo.isFake(),
volInfo.isUnmounting(),
volInfo.isRemovable(),
volInfo.isHotSwappable());
UpdateVolume(vol, false);
}
}
NS_IMETHODIMP
nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult)
{
nsCOMPtr<nsIVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName);
if (!mountLock) {
return NS_ERROR_NOT_AVAILABLE;
}
mountLock.forget(aResult);
return NS_OK;
}
void
nsVolumeService::CheckMountLock(const nsAString& aMountLockName,
const nsAString& aMountLockState)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
RefPtr<nsVolume> vol = FindVolumeByMountLockName(aMountLockName);
if (vol) {
vol->UpdateMountLock(aMountLockState);
}
}
already_AddRefed<nsVolume>
nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
{
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<nsVolume> vol = mVolumeArray[volIndex];
nsString mountLockName;
vol->GetMountLockName(mountLockName);
if (mountLockName.Equals(aMountLockName)) {
return vol.forget();
}
}
return nullptr;
}
already_AddRefed<nsVolume>
nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex)
{
mArrayMonitor.AssertCurrentThreadOwns();
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
RefPtr<nsVolume> vol = mVolumeArray[volIndex];
if (vol->Name().Equals(aName)) {
if (aIndex) {
*aIndex = volIndex;
}
return vol.forget();
}
}
return nullptr;
}
void
nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
{
MOZ_ASSERT(NS_IsMainThread());
{
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::index_type volIndex;
RefPtr<nsVolume> vol = FindVolumeByName(aVolume->Name(), &volIndex);
if (!vol) {
mVolumeArray.AppendElement(aVolume);
} else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) {
// Ignore if nothing changed or if a fake tries to override a real volume.
return;
} else {
mVolumeArray.ReplaceElementAt(volIndex, aVolume);
}
aVolume->UpdateMountLock(vol);
}
if (!aNotifyObservers) {
return;
}
nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (!obs) {
return;
}
NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr());
obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get());
}
NS_IMETHODIMP
nsVolumeService::CreateFakeVolume(const nsAString& name, const nsAString& path)
{
if (XRE_IsParentProcess()) {
RefPtr<nsVolume> vol = new nsVolume(name, path, nsIVolume::STATE_INIT,
-1 /* mountGeneration */,
true /* isMediaPresent */,
false /* isSharing */,
false /* isFormatting */,
true /* isFake */,
false /* isUnmounting */,
false /* isRemovable */,
false /* isHotSwappable */);
vol->SetState(nsIVolume::STATE_MOUNTED);
vol->LogState();
UpdateVolume(vol.get());
return NS_OK;
}
ContentChild::GetSingleton()->SendCreateFakeVolume(nsString(name), nsString(path));
return NS_OK;
}
NS_IMETHODIMP
nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
{
if (XRE_IsParentProcess()) {
RefPtr<nsVolume> vol;
{
MonitorAutoLock autoLock(mArrayMonitor);
vol = FindVolumeByName(name);
}
if (!vol || !vol->IsFake()) {
return NS_ERROR_NOT_AVAILABLE;
}
// Clone the existing volume so we can replace it
RefPtr<nsVolume> volume = new nsVolume(vol);
volume->SetState(state);
volume->LogState();
UpdateVolume(volume.get());
return NS_OK;
}
ContentChild::GetSingleton()->SendSetFakeVolumeState(nsString(name), state);
return NS_OK;
}
NS_IMETHODIMP
nsVolumeService::RemoveFakeVolume(const nsAString& name)
{
if (XRE_IsParentProcess()) {
SetFakeVolumeState(name, nsIVolume::STATE_NOMEDIA);
RemoveVolumeByName(name);
return NS_OK;
}
ContentChild::GetSingleton()->SendRemoveFakeVolume(nsString(name));
return NS_OK;
}
void
nsVolumeService::RemoveVolumeByName(const nsAString& aName)
{
{
MonitorAutoLock autoLock(mArrayMonitor);
nsVolume::Array::index_type volIndex;
RefPtr<nsVolume> vol = FindVolumeByName(aName, &volIndex);
if (!vol) {
return;
}
mVolumeArray.RemoveElementAt(volIndex);
}
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (!obs) {
return;
}
obs->NotifyObservers(nullptr, NS_VOLUME_REMOVED, nsString(aName).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(nsVolumeService* aVolumeService, const Volume* aVolume)
: mVolumeService(aVolumeService),
mVolume(new nsVolume(aVolume))
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
DBG("UpdateVolumeRunnable::Run '%s' state %s gen %d locked %d "
"media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
mVolume->NameStr().get(), mVolume->StateStr(),
mVolume->MountGeneration(), (int)mVolume->IsMountLocked(),
(int)mVolume->IsMediaPresent(), mVolume->IsSharing(),
mVolume->IsFormatting(), mVolume->IsUnmounting(),
(int)mVolume->IsRemovable(), (int)mVolume->IsHotSwappable());
mVolumeService->UpdateVolume(mVolume);
mVolumeService = nullptr;
mVolume = nullptr;
return NS_OK;
}
private:
RefPtr<nsVolumeService> mVolumeService;
RefPtr<nsVolume> mVolume;
};
void
nsVolumeService::UpdateVolumeIOThread(const Volume* aVolume)
{
DBG("UpdateVolumeIOThread: Volume '%s' state %s mount '%s' gen %d locked %d "
"media %d sharing %d formatting %d unmounting %d removable %d hotswappable %d",
aVolume->NameStr(), aVolume->StateStr(), aVolume->MountPoint().get(),
aVolume->MountGeneration(), (int)aVolume->IsMountLocked(),
(int)aVolume->MediaPresent(), (int)aVolume->IsSharing(),
(int)aVolume->IsFormatting(), (int)aVolume->IsUnmounting(),
(int)aVolume->IsRemovable(), (int)aVolume->IsHotSwappable());
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
NS_DispatchToMainThread(new UpdateVolumeRunnable(this, aVolume));
}
} // namespace system
} // namespace mozilla