1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/system/gonk/nsVolumeMountLock.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,164 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "nsVolumeMountLock.h" 1.9 + 1.10 +#include "mozilla/dom/ContentChild.h" 1.11 +#include "mozilla/Services.h" 1.12 + 1.13 +#include "nsIObserverService.h" 1.14 +#include "nsIPowerManagerService.h" 1.15 +#include "nsIVolume.h" 1.16 +#include "nsIVolumeService.h" 1.17 +#include "nsString.h" 1.18 +#include "nsXULAppAPI.h" 1.19 + 1.20 +#define VOLUME_MANAGER_LOG_TAG "nsVolumeMountLock" 1.21 +#include "VolumeManagerLog.h" 1.22 +#include "nsServiceManagerUtils.h" 1.23 +#include "mozilla/dom/power/PowerManagerService.h" 1.24 + 1.25 +using namespace mozilla::dom; 1.26 +using namespace mozilla::services; 1.27 + 1.28 +namespace mozilla { 1.29 +namespace system { 1.30 + 1.31 +NS_IMPL_ISUPPORTS(nsVolumeMountLock, nsIVolumeMountLock, 1.32 + nsIObserver, nsISupportsWeakReference) 1.33 + 1.34 +// static 1.35 +already_AddRefed<nsVolumeMountLock> 1.36 +nsVolumeMountLock::Create(const nsAString& aVolumeName) 1.37 +{ 1.38 + DBG("nsVolumeMountLock::Create called"); 1.39 + 1.40 + nsRefPtr<nsVolumeMountLock> mountLock = new nsVolumeMountLock(aVolumeName); 1.41 + nsresult rv = mountLock->Init(); 1.42 + NS_ENSURE_SUCCESS(rv, nullptr); 1.43 + 1.44 + return mountLock.forget(); 1.45 +} 1.46 + 1.47 +nsVolumeMountLock::nsVolumeMountLock(const nsAString& aVolumeName) 1.48 + : mVolumeName(aVolumeName), 1.49 + mVolumeGeneration(-1), 1.50 + mUnlocked(false) 1.51 +{ 1.52 +} 1.53 + 1.54 +//virtual 1.55 +nsVolumeMountLock::~nsVolumeMountLock() 1.56 +{ 1.57 + Unlock(); 1.58 +} 1.59 + 1.60 +nsresult nsVolumeMountLock::Init() 1.61 +{ 1.62 + LOG("nsVolumeMountLock created for '%s'", 1.63 + NS_LossyConvertUTF16toASCII(mVolumeName).get()); 1.64 + 1.65 + // Add ourselves as an Observer. It's important that we use a weak 1.66 + // reference here. If we used a strong reference, then that reference 1.67 + // would prevent this object from being destructed. 1.68 + nsCOMPtr<nsIObserverService> obs = GetObserverService(); 1.69 + obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, true /*weak*/); 1.70 + 1.71 + // Request the sdcard info, so we know the state/generation without having 1.72 + // to wait for a state change. 1.73 + if (XRE_GetProcessType() == GeckoProcessType_Content) { 1.74 + ContentChild::GetSingleton()->SendBroadcastVolume(mVolumeName); 1.75 + return NS_OK; 1.76 + } 1.77 + nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID); 1.78 + NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE); 1.79 + 1.80 + vs->BroadcastVolume(mVolumeName); 1.81 + 1.82 + return NS_OK; 1.83 +} 1.84 + 1.85 +/* void unlock (); */ 1.86 +NS_IMETHODIMP nsVolumeMountLock::Unlock() 1.87 +{ 1.88 + LOG("nsVolumeMountLock released for '%s'", 1.89 + NS_LossyConvertUTF16toASCII(mVolumeName).get()); 1.90 + 1.91 + mUnlocked = true; 1.92 + mWakeLock = nullptr; 1.93 + 1.94 + // While we don't really need to remove weak observers, we do so anyways 1.95 + // since it will reduce the number of times Observe gets called. 1.96 + nsCOMPtr<nsIObserverService> obs = GetObserverService(); 1.97 + obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED); 1.98 + return NS_OK; 1.99 +} 1.100 + 1.101 +NS_IMETHODIMP nsVolumeMountLock::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) 1.102 +{ 1.103 + if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) { 1.104 + return NS_OK; 1.105 + } 1.106 + if (mUnlocked) { 1.107 + // We're not locked anymore, so we don't need to look at the notifications. 1.108 + return NS_OK; 1.109 + } 1.110 + 1.111 + nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject); 1.112 + if (!vol) { 1.113 + return NS_OK; 1.114 + } 1.115 + nsString volName; 1.116 + vol->GetName(volName); 1.117 + if (!volName.Equals(mVolumeName)) { 1.118 + return NS_OK; 1.119 + } 1.120 + int32_t state; 1.121 + nsresult rv = vol->GetState(&state); 1.122 + NS_ENSURE_SUCCESS(rv, rv); 1.123 + 1.124 + if (state != nsIVolume::STATE_MOUNTED) { 1.125 + mWakeLock = nullptr; 1.126 + mVolumeGeneration = -1; 1.127 + return NS_OK; 1.128 + } 1.129 + 1.130 + int32_t mountGeneration; 1.131 + rv = vol->GetMountGeneration(&mountGeneration); 1.132 + NS_ENSURE_SUCCESS(rv, rv); 1.133 + 1.134 + DBG("nsVolumeMountLock::Observe mountGeneration = %d mVolumeGeneration = %d", 1.135 + mountGeneration, mVolumeGeneration); 1.136 + 1.137 + if (mVolumeGeneration == mountGeneration) { 1.138 + return NS_OK; 1.139 + } 1.140 + 1.141 + // The generation changed, which means that any wakelock we may have 1.142 + // been holding is now invalid. Grab a new wakelock for the new generation 1.143 + // number. 1.144 + 1.145 + mWakeLock = nullptr; 1.146 + mVolumeGeneration = mountGeneration; 1.147 + 1.148 + nsRefPtr<power::PowerManagerService> pmService = 1.149 + power::PowerManagerService::GetInstance(); 1.150 + NS_ENSURE_TRUE(pmService, NS_ERROR_FAILURE); 1.151 + 1.152 + nsString mountLockName; 1.153 + vol->GetMountLockName(mountLockName); 1.154 + 1.155 + ErrorResult err; 1.156 + mWakeLock = pmService->NewWakeLock(mountLockName, nullptr, err); 1.157 + if (err.Failed()) { 1.158 + return err.ErrorCode(); 1.159 + } 1.160 + 1.161 + LOG("nsVolumeMountLock acquired for '%s' gen %d", 1.162 + NS_LossyConvertUTF16toASCII(mVolumeName).get(), mVolumeGeneration); 1.163 + return NS_OK; 1.164 +} 1.165 + 1.166 +} // namespace system 1.167 +} // namespace mozilla