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

mercurial