summaryrefslogtreecommitdiffstats
path: root/dom/system/gonk/nsVolumeService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/system/gonk/nsVolumeService.cpp')
-rw-r--r--dom/system/gonk/nsVolumeService.cpp553
1 files changed, 0 insertions, 553 deletions
diff --git a/dom/system/gonk/nsVolumeService.cpp b/dom/system/gonk/nsVolumeService.cpp
deleted file mode 100644
index 48d95c26a..000000000
--- a/dom/system/gonk/nsVolumeService.cpp
+++ /dev/null
@@ -1,553 +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 "nsVolumeService.h"
-
-#include "Volume.h"
-#include "VolumeManager.h"
-#include "VolumeServiceIOThread.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"
-#include "base/task.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(
- 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(
- 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 Runnable
-{
-public:
- UpdateVolumeRunnable(nsVolumeService* aVolumeService, const Volume* aVolume)
- : mVolumeService(aVolumeService),
- mVolume(new nsVolume(aVolume))
- {
- MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
- }
-
- NS_IMETHOD Run() override
- {
- 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