dom/system/gonk/nsVolumeMountLock.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:6a2c1e1e8111
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "nsVolumeMountLock.h"
6
7 #include "mozilla/dom/ContentChild.h"
8 #include "mozilla/Services.h"
9
10 #include "nsIObserverService.h"
11 #include "nsIPowerManagerService.h"
12 #include "nsIVolume.h"
13 #include "nsIVolumeService.h"
14 #include "nsString.h"
15 #include "nsXULAppAPI.h"
16
17 #define VOLUME_MANAGER_LOG_TAG "nsVolumeMountLock"
18 #include "VolumeManagerLog.h"
19 #include "nsServiceManagerUtils.h"
20 #include "mozilla/dom/power/PowerManagerService.h"
21
22 using namespace mozilla::dom;
23 using namespace mozilla::services;
24
25 namespace mozilla {
26 namespace system {
27
28 NS_IMPL_ISUPPORTS(nsVolumeMountLock, nsIVolumeMountLock,
29 nsIObserver, nsISupportsWeakReference)
30
31 // static
32 already_AddRefed<nsVolumeMountLock>
33 nsVolumeMountLock::Create(const nsAString& aVolumeName)
34 {
35 DBG("nsVolumeMountLock::Create called");
36
37 nsRefPtr<nsVolumeMountLock> mountLock = new nsVolumeMountLock(aVolumeName);
38 nsresult rv = mountLock->Init();
39 NS_ENSURE_SUCCESS(rv, nullptr);
40
41 return mountLock.forget();
42 }
43
44 nsVolumeMountLock::nsVolumeMountLock(const nsAString& aVolumeName)
45 : mVolumeName(aVolumeName),
46 mVolumeGeneration(-1),
47 mUnlocked(false)
48 {
49 }
50
51 //virtual
52 nsVolumeMountLock::~nsVolumeMountLock()
53 {
54 Unlock();
55 }
56
57 nsresult nsVolumeMountLock::Init()
58 {
59 LOG("nsVolumeMountLock created for '%s'",
60 NS_LossyConvertUTF16toASCII(mVolumeName).get());
61
62 // Add ourselves as an Observer. It's important that we use a weak
63 // reference here. If we used a strong reference, then that reference
64 // would prevent this object from being destructed.
65 nsCOMPtr<nsIObserverService> obs = GetObserverService();
66 obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, true /*weak*/);
67
68 // Request the sdcard info, so we know the state/generation without having
69 // to wait for a state change.
70 if (XRE_GetProcessType() == GeckoProcessType_Content) {
71 ContentChild::GetSingleton()->SendBroadcastVolume(mVolumeName);
72 return NS_OK;
73 }
74 nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
75 NS_ENSURE_TRUE(vs, NS_ERROR_FAILURE);
76
77 vs->BroadcastVolume(mVolumeName);
78
79 return NS_OK;
80 }
81
82 /* void unlock (); */
83 NS_IMETHODIMP nsVolumeMountLock::Unlock()
84 {
85 LOG("nsVolumeMountLock released for '%s'",
86 NS_LossyConvertUTF16toASCII(mVolumeName).get());
87
88 mUnlocked = true;
89 mWakeLock = nullptr;
90
91 // While we don't really need to remove weak observers, we do so anyways
92 // since it will reduce the number of times Observe gets called.
93 nsCOMPtr<nsIObserverService> obs = GetObserverService();
94 obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
95 return NS_OK;
96 }
97
98 NS_IMETHODIMP nsVolumeMountLock::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
99 {
100 if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
101 return NS_OK;
102 }
103 if (mUnlocked) {
104 // We're not locked anymore, so we don't need to look at the notifications.
105 return NS_OK;
106 }
107
108 nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
109 if (!vol) {
110 return NS_OK;
111 }
112 nsString volName;
113 vol->GetName(volName);
114 if (!volName.Equals(mVolumeName)) {
115 return NS_OK;
116 }
117 int32_t state;
118 nsresult rv = vol->GetState(&state);
119 NS_ENSURE_SUCCESS(rv, rv);
120
121 if (state != nsIVolume::STATE_MOUNTED) {
122 mWakeLock = nullptr;
123 mVolumeGeneration = -1;
124 return NS_OK;
125 }
126
127 int32_t mountGeneration;
128 rv = vol->GetMountGeneration(&mountGeneration);
129 NS_ENSURE_SUCCESS(rv, rv);
130
131 DBG("nsVolumeMountLock::Observe mountGeneration = %d mVolumeGeneration = %d",
132 mountGeneration, mVolumeGeneration);
133
134 if (mVolumeGeneration == mountGeneration) {
135 return NS_OK;
136 }
137
138 // The generation changed, which means that any wakelock we may have
139 // been holding is now invalid. Grab a new wakelock for the new generation
140 // number.
141
142 mWakeLock = nullptr;
143 mVolumeGeneration = mountGeneration;
144
145 nsRefPtr<power::PowerManagerService> pmService =
146 power::PowerManagerService::GetInstance();
147 NS_ENSURE_TRUE(pmService, NS_ERROR_FAILURE);
148
149 nsString mountLockName;
150 vol->GetMountLockName(mountLockName);
151
152 ErrorResult err;
153 mWakeLock = pmService->NewWakeLock(mountLockName, nullptr, err);
154 if (err.Failed()) {
155 return err.ErrorCode();
156 }
157
158 LOG("nsVolumeMountLock acquired for '%s' gen %d",
159 NS_LossyConvertUTF16toASCII(mVolumeName).get(), mVolumeGeneration);
160 return NS_OK;
161 }
162
163 } // namespace system
164 } // namespace mozilla

mercurial