dom/system/gonk/AutoMounterSetting.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:68aadb39803d
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 "AutoMounter.h"
6 #include "AutoMounterSetting.h"
7
8 #include "base/message_loop.h"
9 #include "jsapi.h"
10 #include "mozilla/Services.h"
11 #include "nsCOMPtr.h"
12 #include "nsDebug.h"
13 #include "nsIObserverService.h"
14 #include "nsCxPusher.h"
15 #include "nsISettingsService.h"
16 #include "nsJSUtils.h"
17 #include "nsPrintfCString.h"
18 #include "nsServiceManagerUtils.h"
19 #include "nsString.h"
20 #include "nsThreadUtils.h"
21 #include "xpcpublic.h"
22 #include "mozilla/Attributes.h"
23
24 #undef LOG
25 #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "AutoMounterSetting" , ## args)
26 #define ERR(args...) __android_log_print(ANDROID_LOG_ERROR, "AutoMounterSetting" , ## args)
27
28 #define UMS_MODE "ums.mode"
29 #define UMS_STATUS "ums.status"
30 #define UMS_VOLUME_ENABLED_PREFIX "ums.volume."
31 #define UMS_VOLUME_ENABLED_SUFFIX ".enabled"
32 #define MOZSETTINGS_CHANGED "mozsettings-changed"
33
34 namespace mozilla {
35 namespace system {
36
37 class SettingsServiceCallback MOZ_FINAL : public nsISettingsServiceCallback
38 {
39 public:
40 NS_DECL_THREADSAFE_ISUPPORTS
41
42 SettingsServiceCallback() {}
43
44 NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
45 {
46 if (JSVAL_IS_INT(aResult)) {
47 int32_t mode = JSVAL_TO_INT(aResult);
48 SetAutoMounterMode(mode);
49 }
50 return NS_OK;
51 }
52
53 NS_IMETHOD HandleError(const nsAString& aName)
54 {
55 ERR("SettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
56 return NS_OK;
57 }
58 };
59
60 NS_IMPL_ISUPPORTS(SettingsServiceCallback, nsISettingsServiceCallback)
61
62 class CheckVolumeSettingsCallback MOZ_FINAL : public nsISettingsServiceCallback
63 {
64 public:
65 NS_DECL_THREADSAFE_ISUPPORTS
66
67 CheckVolumeSettingsCallback(const nsACString& aVolumeName)
68 : mVolumeName(aVolumeName) {}
69
70 NS_IMETHOD Handle(const nsAString& aName, JS::Handle<JS::Value> aResult)
71 {
72 if (JSVAL_IS_BOOLEAN(aResult)) {
73 bool isSharingEnabled = JSVAL_TO_BOOLEAN(aResult);
74 SetAutoMounterSharingMode(mVolumeName, isSharingEnabled);
75 }
76 return NS_OK;
77 }
78
79 NS_IMETHOD HandleError(const nsAString& aName)
80 {
81 ERR("CheckVolumeSettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
82 return NS_OK;
83 }
84 private:
85 nsCString mVolumeName;
86 };
87
88 NS_IMPL_ISUPPORTS(CheckVolumeSettingsCallback, nsISettingsServiceCallback)
89
90 AutoMounterSetting::AutoMounterSetting()
91 : mStatus(AUTOMOUNTER_STATUS_DISABLED)
92 {
93 MOZ_ASSERT(NS_IsMainThread());
94
95 // Setup an observer to watch changes to the setting
96 nsCOMPtr<nsIObserverService> observerService =
97 mozilla::services::GetObserverService();
98 if (!observerService) {
99 ERR("GetObserverService failed");
100 return;
101 }
102 nsresult rv;
103 rv = observerService->AddObserver(this, MOZSETTINGS_CHANGED, false);
104 if (NS_FAILED(rv)) {
105 ERR("AddObserver failed");
106 return;
107 }
108
109 // Force ums.mode to be 0 initially. We do this because settings are persisted.
110 // We don't want UMS to be enabled until such time as the phone is unlocked,
111 // and gaia/apps/system/js/storage.js takes care of detecting when the phone
112 // becomes unlocked and changes ums.mode appropriately.
113 nsCOMPtr<nsISettingsService> settingsService =
114 do_GetService("@mozilla.org/settingsService;1");
115 if (!settingsService) {
116 ERR("Failed to get settingsLock service!");
117 return;
118 }
119 nsCOMPtr<nsISettingsServiceLock> lock;
120 settingsService->CreateLock(nullptr, getter_AddRefs(lock));
121 nsCOMPtr<nsISettingsServiceCallback> callback = new SettingsServiceCallback();
122 mozilla::AutoSafeJSContext cx;
123 JS::Rooted<JS::Value> value(cx);
124 value.setInt32(AUTOMOUNTER_DISABLE);
125 lock->Set(UMS_MODE, value, callback, nullptr);
126 value.setInt32(mStatus);
127 lock->Set(UMS_STATUS, value, nullptr, nullptr);
128 }
129
130 AutoMounterSetting::~AutoMounterSetting()
131 {
132 nsCOMPtr<nsIObserverService> observerService =
133 mozilla::services::GetObserverService();
134 if (observerService) {
135 observerService->RemoveObserver(this, MOZSETTINGS_CHANGED);
136 }
137 }
138
139 NS_IMPL_ISUPPORTS(AutoMounterSetting, nsIObserver)
140
141 const char *
142 AutoMounterSetting::StatusStr(int32_t aStatus)
143 {
144 switch (aStatus) {
145 case AUTOMOUNTER_STATUS_DISABLED: return "Disabled";
146 case AUTOMOUNTER_STATUS_ENABLED: return "Enabled";
147 case AUTOMOUNTER_STATUS_FILES_OPEN: return "FilesOpen";
148 }
149 return "??? Unknown ???";
150 }
151
152 class CheckVolumeSettingsRunnable : public nsRunnable
153 {
154 public:
155 CheckVolumeSettingsRunnable(const nsACString& aVolumeName)
156 : mVolumeName(aVolumeName) {}
157
158 NS_IMETHOD Run()
159 {
160 MOZ_ASSERT(NS_IsMainThread());
161 nsCOMPtr<nsISettingsService> settingsService =
162 do_GetService("@mozilla.org/settingsService;1");
163 NS_ENSURE_TRUE(settingsService, NS_ERROR_FAILURE);
164 nsCOMPtr<nsISettingsServiceLock> lock;
165 settingsService->CreateLock(nullptr, getter_AddRefs(lock));
166 nsCOMPtr<nsISettingsServiceCallback> callback =
167 new CheckVolumeSettingsCallback(mVolumeName);
168 nsPrintfCString setting(UMS_VOLUME_ENABLED_PREFIX "%s" UMS_VOLUME_ENABLED_SUFFIX,
169 mVolumeName.get());
170 lock->Get(setting.get(), callback);
171 return NS_OK;
172 }
173
174 private:
175 nsCString mVolumeName;
176 };
177
178 //static
179 void
180 AutoMounterSetting::CheckVolumeSettings(const nsACString& aVolumeName)
181 {
182 NS_DispatchToMainThread(new CheckVolumeSettingsRunnable(aVolumeName));
183 }
184
185 class SetStatusRunnable : public nsRunnable
186 {
187 public:
188 SetStatusRunnable(int32_t aStatus) : mStatus(aStatus) {}
189
190 NS_IMETHOD Run()
191 {
192 MOZ_ASSERT(NS_IsMainThread());
193 nsCOMPtr<nsISettingsService> settingsService =
194 do_GetService("@mozilla.org/settingsService;1");
195 NS_ENSURE_TRUE(settingsService, NS_ERROR_FAILURE);
196 nsCOMPtr<nsISettingsServiceLock> lock;
197 settingsService->CreateLock(nullptr, getter_AddRefs(lock));
198 // lock may be null if this gets called during shutdown.
199 if (lock) {
200 mozilla::AutoSafeJSContext cx;
201 JS::Rooted<JS::Value> value(cx, JS::Int32Value(mStatus));
202 lock->Set(UMS_STATUS, value, nullptr, nullptr);
203 }
204 return NS_OK;
205 }
206
207 private:
208 int32_t mStatus;
209 };
210
211 //static
212 void
213 AutoMounterSetting::SetStatus(int32_t aStatus)
214 {
215 if (aStatus != mStatus) {
216 LOG("Changing status from '%s' to '%s'",
217 StatusStr(mStatus), StatusStr(aStatus));
218 mStatus = aStatus;
219 NS_DispatchToMainThread(new SetStatusRunnable(aStatus));
220 }
221 }
222
223 NS_IMETHODIMP
224 AutoMounterSetting::Observe(nsISupports* aSubject,
225 const char* aTopic,
226 const char16_t* aData)
227 {
228 if (strcmp(aTopic, MOZSETTINGS_CHANGED) != 0) {
229 return NS_OK;
230 }
231
232 // Note that this function gets called for any and all settings changes,
233 // so we need to carefully check if we have the one we're interested in.
234 //
235 // The string that we're interested in will be a JSON string that looks like:
236 // {"key":"ums.autoMount","value":true}
237
238 mozilla::AutoSafeJSContext cx;
239 nsDependentString dataStr(aData);
240 JS::Rooted<JS::Value> val(cx);
241 if (!JS_ParseJSON(cx, dataStr.get(), dataStr.Length(), &val) ||
242 !val.isObject()) {
243 return NS_OK;
244 }
245 JS::Rooted<JSObject*> obj(cx, &val.toObject());
246 JS::Rooted<JS::Value> key(cx);
247 if (!JS_GetProperty(cx, obj, "key", &key) ||
248 !key.isString()) {
249 return NS_OK;
250 }
251
252 JSString *jsKey = JS::ToString(cx, key);
253 nsDependentJSString keyStr;
254 if (!keyStr.init(cx, jsKey)) {
255 return NS_OK;
256 }
257
258 JS::Rooted<JS::Value> value(cx);
259 if (!JS_GetProperty(cx, obj, "value", &value)) {
260 return NS_OK;
261 }
262
263 // Check for ums.mode changes
264 if (keyStr.EqualsLiteral(UMS_MODE)) {
265 if (!value.isInt32()) {
266 return NS_OK;
267 }
268 int32_t mode = value.toInt32();
269 SetAutoMounterMode(mode);
270 return NS_OK;
271 }
272
273 // Check for ums.volume.NAME.enabled
274 if (StringBeginsWith(keyStr, NS_LITERAL_STRING(UMS_VOLUME_ENABLED_PREFIX)) &&
275 StringEndsWith(keyStr, NS_LITERAL_STRING(UMS_VOLUME_ENABLED_SUFFIX))) {
276 if (!value.isBoolean()) {
277 return NS_OK;
278 }
279 const size_t prefixLen = sizeof(UMS_VOLUME_ENABLED_PREFIX) - 1;
280 const size_t suffixLen = sizeof(UMS_VOLUME_ENABLED_SUFFIX) - 1;
281 nsDependentSubstring volumeName =
282 Substring(keyStr, prefixLen, keyStr.Length() - prefixLen - suffixLen);
283 bool isSharingEnabled = value.toBoolean();
284 SetAutoMounterSharingMode(NS_LossyConvertUTF16toASCII(volumeName), isSharingEnabled);
285 return NS_OK;
286 }
287
288 return NS_OK;
289 }
290
291 } // namespace system
292 } // namespace mozilla

mercurial