dom/system/gonk/nsVolume.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "nsVolume.h"
michael@0 6
michael@0 7 #include "base/message_loop.h"
michael@0 8 #include "nsIPowerManagerService.h"
michael@0 9 #include "nsISupportsUtils.h"
michael@0 10 #include "nsIVolume.h"
michael@0 11 #include "nsServiceManagerUtils.h"
michael@0 12 #include "nsThreadUtils.h"
michael@0 13 #include "nsVolumeStat.h"
michael@0 14 #include "nsXULAppAPI.h"
michael@0 15 #include "Volume.h"
michael@0 16 #include "AutoMounter.h"
michael@0 17 #include "VolumeManager.h"
michael@0 18
michael@0 19 #define VOLUME_MANAGER_LOG_TAG "nsVolume"
michael@0 20 #include "VolumeManagerLog.h"
michael@0 21
michael@0 22 namespace mozilla {
michael@0 23 namespace system {
michael@0 24
michael@0 25 const char *
michael@0 26 NS_VolumeStateStr(int32_t aState)
michael@0 27 {
michael@0 28 switch (aState) {
michael@0 29 case nsIVolume::STATE_INIT: return "Init";
michael@0 30 case nsIVolume::STATE_NOMEDIA: return "NoMedia";
michael@0 31 case nsIVolume::STATE_IDLE: return "Idle";
michael@0 32 case nsIVolume::STATE_PENDING: return "Pending";
michael@0 33 case nsIVolume::STATE_CHECKING: return "Checking";
michael@0 34 case nsIVolume::STATE_MOUNTED: return "Mounted";
michael@0 35 case nsIVolume::STATE_UNMOUNTING: return "Unmounting";
michael@0 36 case nsIVolume::STATE_FORMATTING: return "Formatting";
michael@0 37 case nsIVolume::STATE_SHARED: return "Shared";
michael@0 38 case nsIVolume::STATE_SHAREDMNT: return "Shared-Mounted";
michael@0 39 }
michael@0 40 return "???";
michael@0 41 }
michael@0 42
michael@0 43 // While nsVolumes can only be used on the main thread, in the
michael@0 44 // UpdateVolumeRunnable constructor (which is called from IOThread) we
michael@0 45 // allocate an nsVolume which is then passed to MainThread. Since we
michael@0 46 // have a situation where we allocate on one thread and free on another
michael@0 47 // we use a thread safe AddRef implementation.
michael@0 48 NS_IMPL_ISUPPORTS(nsVolume, nsIVolume)
michael@0 49
michael@0 50 nsVolume::nsVolume(const Volume* aVolume)
michael@0 51 : mName(NS_ConvertUTF8toUTF16(aVolume->Name())),
michael@0 52 mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
michael@0 53 mState(aVolume->State()),
michael@0 54 mMountGeneration(aVolume->MountGeneration()),
michael@0 55 mMountLocked(aVolume->IsMountLocked()),
michael@0 56 mIsFake(false),
michael@0 57 mIsMediaPresent(aVolume->MediaPresent()),
michael@0 58 mIsSharing(aVolume->IsSharing()),
michael@0 59 mIsFormatting(aVolume->IsFormatting())
michael@0 60 {
michael@0 61 }
michael@0 62
michael@0 63 bool nsVolume::Equals(nsIVolume* aVolume)
michael@0 64 {
michael@0 65 nsString volName;
michael@0 66 aVolume->GetName(volName);
michael@0 67 if (!mName.Equals(volName)) {
michael@0 68 return false;
michael@0 69 }
michael@0 70
michael@0 71 nsString volMountPoint;
michael@0 72 aVolume->GetMountPoint(volMountPoint);
michael@0 73 if (!mMountPoint.Equals(volMountPoint)) {
michael@0 74 return false;
michael@0 75 }
michael@0 76
michael@0 77 int32_t volState;
michael@0 78 aVolume->GetState(&volState);
michael@0 79 if (mState != volState){
michael@0 80 return false;
michael@0 81 }
michael@0 82
michael@0 83 int32_t volMountGeneration;
michael@0 84 aVolume->GetMountGeneration(&volMountGeneration);
michael@0 85 if (mMountGeneration != volMountGeneration) {
michael@0 86 return false;
michael@0 87 }
michael@0 88
michael@0 89 bool volIsMountLocked;
michael@0 90 aVolume->GetIsMountLocked(&volIsMountLocked);
michael@0 91 if (mMountLocked != volIsMountLocked) {
michael@0 92 return false;
michael@0 93 }
michael@0 94
michael@0 95 bool isFake;
michael@0 96 aVolume->GetIsFake(&isFake);
michael@0 97 if (mIsFake != isFake) {
michael@0 98 return false;
michael@0 99 }
michael@0 100
michael@0 101 bool isSharing;
michael@0 102 aVolume->GetIsSharing(&isSharing);
michael@0 103 if (mIsSharing != isSharing) {
michael@0 104 return false;
michael@0 105 }
michael@0 106
michael@0 107 bool isFormatting;
michael@0 108 aVolume->GetIsFormatting(&isFormatting);
michael@0 109 if (mIsFormatting != isFormatting) {
michael@0 110 return false;
michael@0 111 }
michael@0 112
michael@0 113 return true;
michael@0 114 }
michael@0 115
michael@0 116 NS_IMETHODIMP nsVolume::GetIsMediaPresent(bool *aIsMediaPresent)
michael@0 117 {
michael@0 118 *aIsMediaPresent = mIsMediaPresent;
michael@0 119 return NS_OK;
michael@0 120 }
michael@0 121
michael@0 122 NS_IMETHODIMP nsVolume::GetIsMountLocked(bool *aIsMountLocked)
michael@0 123 {
michael@0 124 *aIsMountLocked = mMountLocked;
michael@0 125 return NS_OK;
michael@0 126 }
michael@0 127
michael@0 128 NS_IMETHODIMP nsVolume::GetIsSharing(bool *aIsSharing)
michael@0 129 {
michael@0 130 *aIsSharing = mIsSharing;
michael@0 131 return NS_OK;
michael@0 132 }
michael@0 133
michael@0 134 NS_IMETHODIMP nsVolume::GetIsFormatting(bool *aIsFormatting)
michael@0 135 {
michael@0 136 *aIsFormatting = mIsFormatting;
michael@0 137 return NS_OK;
michael@0 138 }
michael@0 139
michael@0 140 NS_IMETHODIMP nsVolume::GetName(nsAString& aName)
michael@0 141 {
michael@0 142 aName = mName;
michael@0 143 return NS_OK;
michael@0 144 }
michael@0 145
michael@0 146 NS_IMETHODIMP nsVolume::GetMountGeneration(int32_t* aMountGeneration)
michael@0 147 {
michael@0 148 *aMountGeneration = mMountGeneration;
michael@0 149 return NS_OK;
michael@0 150 }
michael@0 151
michael@0 152 NS_IMETHODIMP nsVolume::GetMountLockName(nsAString& aMountLockName)
michael@0 153 {
michael@0 154 aMountLockName = NS_LITERAL_STRING("volume-") + Name();
michael@0 155 aMountLockName.AppendPrintf("-%d", mMountGeneration);
michael@0 156
michael@0 157 return NS_OK;
michael@0 158 }
michael@0 159
michael@0 160 NS_IMETHODIMP nsVolume::GetMountPoint(nsAString& aMountPoint)
michael@0 161 {
michael@0 162 aMountPoint = mMountPoint;
michael@0 163 return NS_OK;
michael@0 164 }
michael@0 165
michael@0 166 NS_IMETHODIMP nsVolume::GetState(int32_t* aState)
michael@0 167 {
michael@0 168 *aState = mState;
michael@0 169 return NS_OK;
michael@0 170 }
michael@0 171
michael@0 172 NS_IMETHODIMP nsVolume::GetStats(nsIVolumeStat **aResult)
michael@0 173 {
michael@0 174 if (mState != STATE_MOUNTED) {
michael@0 175 return NS_ERROR_NOT_AVAILABLE;
michael@0 176 }
michael@0 177
michael@0 178 NS_IF_ADDREF(*aResult = new nsVolumeStat(mMountPoint));
michael@0 179 return NS_OK;
michael@0 180 }
michael@0 181
michael@0 182 NS_IMETHODIMP nsVolume::GetIsFake(bool *aIsFake)
michael@0 183 {
michael@0 184 *aIsFake = mIsFake;
michael@0 185 return NS_OK;
michael@0 186 }
michael@0 187
michael@0 188 NS_IMETHODIMP nsVolume::Format()
michael@0 189 {
michael@0 190 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 191
michael@0 192 XRE_GetIOMessageLoop()->PostTask(
michael@0 193 FROM_HERE,
michael@0 194 NewRunnableFunction(FormatVolumeIOThread, NameStr()));
michael@0 195
michael@0 196 return NS_OK;
michael@0 197 }
michael@0 198
michael@0 199 /* static */
michael@0 200 void nsVolume::FormatVolumeIOThread(const nsCString& aVolume)
michael@0 201 {
michael@0 202 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 203
michael@0 204 MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
michael@0 205 if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
michael@0 206 return;
michael@0 207 }
michael@0 208
michael@0 209 AutoMounterFormatVolume(aVolume);
michael@0 210 }
michael@0 211
michael@0 212 NS_IMETHODIMP nsVolume::Mount()
michael@0 213 {
michael@0 214 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 215
michael@0 216 XRE_GetIOMessageLoop()->PostTask(
michael@0 217 FROM_HERE,
michael@0 218 NewRunnableFunction(MountVolumeIOThread, NameStr()));
michael@0 219
michael@0 220 return NS_OK;
michael@0 221 }
michael@0 222
michael@0 223 /* static */
michael@0 224 void nsVolume::MountVolumeIOThread(const nsCString& aVolume)
michael@0 225 {
michael@0 226 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 227
michael@0 228 MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
michael@0 229 if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
michael@0 230 return;
michael@0 231 }
michael@0 232
michael@0 233 AutoMounterMountVolume(aVolume);
michael@0 234 }
michael@0 235
michael@0 236 NS_IMETHODIMP nsVolume::Unmount()
michael@0 237 {
michael@0 238 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 239
michael@0 240 XRE_GetIOMessageLoop()->PostTask(
michael@0 241 FROM_HERE,
michael@0 242 NewRunnableFunction(UnmountVolumeIOThread, NameStr()));
michael@0 243
michael@0 244 return NS_OK;
michael@0 245 }
michael@0 246
michael@0 247 /* static */
michael@0 248 void nsVolume::UnmountVolumeIOThread(const nsCString& aVolume)
michael@0 249 {
michael@0 250 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 251
michael@0 252 MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
michael@0 253 if (VolumeManager::State() != VolumeManager::VOLUMES_READY) {
michael@0 254 return;
michael@0 255 }
michael@0 256
michael@0 257 AutoMounterUnmountVolume(aVolume);
michael@0 258 }
michael@0 259
michael@0 260 void
michael@0 261 nsVolume::LogState() const
michael@0 262 {
michael@0 263 if (mState == nsIVolume::STATE_MOUNTED) {
michael@0 264 LOG("nsVolume: %s state %s @ '%s' gen %d locked %d fake %d "
michael@0 265 "media %d sharing %d formatting %d",
michael@0 266 NameStr().get(), StateStr(), MountPointStr().get(),
michael@0 267 MountGeneration(), (int)IsMountLocked(), (int)IsFake(),
michael@0 268 (int)IsMediaPresent(), (int)IsSharing(),
michael@0 269 (int)IsFormatting());
michael@0 270 return;
michael@0 271 }
michael@0 272
michael@0 273 LOG("nsVolume: %s state %s", NameStr().get(), StateStr());
michael@0 274 }
michael@0 275
michael@0 276 void nsVolume::Set(nsIVolume* aVolume)
michael@0 277 {
michael@0 278 MOZ_ASSERT(NS_IsMainThread());
michael@0 279
michael@0 280 aVolume->GetName(mName);
michael@0 281 aVolume->GetMountPoint(mMountPoint);
michael@0 282 aVolume->GetState(&mState);
michael@0 283 aVolume->GetIsFake(&mIsFake);
michael@0 284 aVolume->GetIsMediaPresent(&mIsMediaPresent);
michael@0 285 aVolume->GetIsSharing(&mIsSharing);
michael@0 286 aVolume->GetIsFormatting(&mIsFormatting);
michael@0 287
michael@0 288 int32_t volMountGeneration;
michael@0 289 aVolume->GetMountGeneration(&volMountGeneration);
michael@0 290
michael@0 291 if (mState != nsIVolume::STATE_MOUNTED) {
michael@0 292 // Since we're not in the mounted state, we need to
michael@0 293 // forgot whatever mount generation we may have had.
michael@0 294 mMountGeneration = -1;
michael@0 295 return;
michael@0 296 }
michael@0 297 if (mMountGeneration == volMountGeneration) {
michael@0 298 // No change in mount generation, nothing else to do
michael@0 299 return;
michael@0 300 }
michael@0 301
michael@0 302 mMountGeneration = volMountGeneration;
michael@0 303
michael@0 304 if (XRE_GetProcessType() != GeckoProcessType_Default) {
michael@0 305 // Child processes just track the state, not maintain it.
michael@0 306 aVolume->GetIsMountLocked(&mMountLocked);
michael@0 307 return;
michael@0 308 }
michael@0 309
michael@0 310 // Notify the Volume on IOThread whether the volume is locked or not.
michael@0 311 nsCOMPtr<nsIPowerManagerService> pmService =
michael@0 312 do_GetService(POWERMANAGERSERVICE_CONTRACTID);
michael@0 313 if (!pmService) {
michael@0 314 return;
michael@0 315 }
michael@0 316 nsString mountLockName;
michael@0 317 GetMountLockName(mountLockName);
michael@0 318 nsString mountLockState;
michael@0 319 pmService->GetWakeLockState(mountLockName, mountLockState);
michael@0 320 UpdateMountLock(mountLockState);
michael@0 321 }
michael@0 322
michael@0 323 void
michael@0 324 nsVolume::UpdateMountLock(const nsAString& aMountLockState)
michael@0 325 {
michael@0 326 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 327 MOZ_ASSERT(NS_IsMainThread());
michael@0 328
michael@0 329 // There are 3 states, unlocked, locked-background, and locked-foreground
michael@0 330 // I figured it was easier to use negtive logic and compare for unlocked.
michael@0 331 UpdateMountLock(!aMountLockState.EqualsLiteral("unlocked"));
michael@0 332 }
michael@0 333
michael@0 334 void
michael@0 335 nsVolume::UpdateMountLock(bool aMountLocked)
michael@0 336 {
michael@0 337 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 338 MOZ_ASSERT(NS_IsMainThread());
michael@0 339
michael@0 340 if (aMountLocked == mMountLocked) {
michael@0 341 return;
michael@0 342 }
michael@0 343 // The locked/unlocked state changed. Tell IOThread about it.
michael@0 344 mMountLocked = aMountLocked;
michael@0 345 LogState();
michael@0 346 XRE_GetIOMessageLoop()->PostTask(
michael@0 347 FROM_HERE,
michael@0 348 NewRunnableFunction(Volume::UpdateMountLock,
michael@0 349 NS_LossyConvertUTF16toASCII(Name()),
michael@0 350 MountGeneration(), aMountLocked));
michael@0 351 }
michael@0 352
michael@0 353 void
michael@0 354 nsVolume::SetIsFake(bool aIsFake)
michael@0 355 {
michael@0 356 mIsFake = aIsFake;
michael@0 357 if (mIsFake) {
michael@0 358 // The media is always present for fake volumes.
michael@0 359 mIsMediaPresent = true;
michael@0 360 MOZ_ASSERT(!mIsSharing);
michael@0 361 }
michael@0 362 }
michael@0 363
michael@0 364 void
michael@0 365 nsVolume::SetState(int32_t aState)
michael@0 366 {
michael@0 367 static int32_t sMountGeneration = 0;
michael@0 368
michael@0 369 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
michael@0 370 MOZ_ASSERT(NS_IsMainThread());
michael@0 371 MOZ_ASSERT(IsFake());
michael@0 372
michael@0 373 if (aState == mState) {
michael@0 374 return;
michael@0 375 }
michael@0 376
michael@0 377 if (aState == nsIVolume::STATE_MOUNTED) {
michael@0 378 mMountGeneration = ++sMountGeneration;
michael@0 379 }
michael@0 380
michael@0 381 mState = aState;
michael@0 382 }
michael@0 383
michael@0 384 } // system
michael@0 385 } // mozilla

mercurial