diff --git a/dom/camera/CameraPreferences.cpp b/dom/camera/CameraPreferences.cpp new file mode 100644 index 00000000000..82a6ff98be0 --- /dev/null +++ b/dom/camera/CameraPreferences.cpp @@ -0,0 +1,243 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "CameraPreferences.h" +#include "CameraCommon.h" +#include "mozilla/Monitor.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/Preferences.h" + +using namespace mozilla; + +/* statics */ +static StaticAutoPtr sPrefMonitor; + +StaticAutoPtr CameraPreferences::sPrefTestEnabled; +StaticAutoPtr CameraPreferences::sPrefHardwareTest; +StaticAutoPtr CameraPreferences::sPrefGonkParameters; + +nsresult CameraPreferences::sPrefCameraControlMethodErrorOverride = NS_OK; +nsresult CameraPreferences::sPrefCameraControlAsyncErrorOverride = NS_OK; + +/* static */ +nsresult +CameraPreferences::UpdatePref(const char* aPref, nsresult& aVal) +{ + uint32_t val; + nsresult rv = Preferences::GetUint(aPref, &val); + if (NS_SUCCEEDED(rv)) { + aVal = static_cast(val); + } + return rv; +} + +/* static */ +nsresult +CameraPreferences::UpdatePref(const char* aPref, nsACString& aVal) +{ + nsCString val; + nsresult rv = Preferences::GetCString(aPref, &val); + if (NS_SUCCEEDED(rv)) { + aVal = val; + } + return rv; +} + +/* static */ +CameraPreferences::Pref CameraPreferences::sPrefs[] = { + { + "camera.control.test.enabled", + kPrefValueIsCString, + { &sPrefTestEnabled } + }, + { + "camera.control.test.hardware", + kPrefValueIsCString, + { &sPrefHardwareTest } + }, +#ifdef MOZ_B2G + { + "camera.control.test.hardware.gonk.parameters", + kPrefValueIsCString, + { &sPrefGonkParameters } + }, +#endif + { + "camera.control.test.method.error", + kPrefValueIsNSResult, + { &sPrefCameraControlMethodErrorOverride } + }, + { + "camera.control.test.async.error", + kPrefValueIsNSResult, + { &sPrefCameraControlAsyncErrorOverride } + }, +}; + +/* static */ +uint32_t +CameraPreferences::PrefToIndex(const char* aPref) +{ + for (uint32_t i = 0; i < ArrayLength(sPrefs); ++i) { + if (strcmp(aPref, sPrefs[i].mPref) == 0) { + return i; + } + } + return kPrefNotFound; +} + +/* static */ +void +CameraPreferences::PreferenceChanged(const char* aPref, void* aClosure) +{ + MonitorAutoLock mon(*sPrefMonitor); + + uint32_t i = PrefToIndex(aPref); + if (i == kPrefNotFound) { + DOM_CAMERA_LOGE("Preference '%s' is not tracked by CameraPreferences\n", aPref); + return; + } + + Pref& p = sPrefs[i]; + nsresult rv; + switch (p.mValueType) { + case kPrefValueIsNSResult: + { + nsresult& v = *p.mValue.mAsNsResult; + rv = UpdatePref(aPref, v); + if (NS_SUCCEEDED(rv)) { + DOM_CAMERA_LOGI("Preference '%s' has changed, 0x%x\n", aPref, v); + } + } + break; + + case kPrefValueIsCString: + { + nsCString& v = **p.mValue.mAsCString; + rv = UpdatePref(aPref, v); + if (NS_SUCCEEDED(rv)) { + DOM_CAMERA_LOGI("Preference '%s' has changed, '%s'\n", aPref, v.get()); + } + } + break; + + default: + MOZ_ASSERT_UNREACHABLE("Unhandled preference value type!"); + return; + } + +#ifdef DEBUG + if (NS_FAILED(rv)) { + nsCString msg; + msg.AppendPrintf("Failed to update pref '%s' (0x%x)\n", aPref, rv); + NS_WARNING(msg.get()); + } +#endif +} + +/* static */ +bool +CameraPreferences::Initialize() +{ + DOM_CAMERA_LOGI("Initializing camera preference callbacks\n"); + + nsresult rv; + + sPrefMonitor = new Monitor("CameraPreferences.sPrefMonitor"); + + sPrefTestEnabled = new nsCString(); + sPrefHardwareTest = new nsCString(); + sPrefGonkParameters = new nsCString(); + + for (uint32_t i = 0; i < ArrayLength(sPrefs); ++i) { + rv = Preferences::RegisterCallbackAndCall(CameraPreferences::PreferenceChanged, + sPrefs[i].mPref); + if (NS_WARN_IF(NS_FAILED(rv))) { + return false; + } + } + + DOM_CAMERA_LOGI("Camera preferences initialized\n"); + return true; +} + +/* static */ +void +CameraPreferences::Shutdown() +{ + DOM_CAMERA_LOGI("Shutting down camera preference callbacks\n"); + + for (uint32_t i = 0; i < ArrayLength(sPrefs); ++i) { + Preferences::UnregisterCallback(CameraPreferences::PreferenceChanged, + sPrefs[i].mPref); + } + + sPrefTestEnabled = nullptr; + sPrefHardwareTest = nullptr; + sPrefGonkParameters = nullptr; + sPrefMonitor = nullptr; + + DOM_CAMERA_LOGI("Camera preferences shut down\n"); +} + +/* static */ +bool +CameraPreferences::GetPref(const char* aPref, nsACString& aVal) +{ + MOZ_ASSERT(sPrefMonitor, "sPrefMonitor missing in CameraPreferences::GetPref()"); + MonitorAutoLock mon(*sPrefMonitor); + + uint32_t i = PrefToIndex(aPref); + if (i == kPrefNotFound || i >= ArrayLength(sPrefs)) { + DOM_CAMERA_LOGW("Preference '%s' is not tracked by CameraPreferences\n", aPref); + return false; + } + if (sPrefs[i].mValueType != kPrefValueIsCString) { + DOM_CAMERA_LOGW("Preference '%s' is not a string type\n", aPref); + return false; + } + + StaticAutoPtr* s = sPrefs[i].mValue.mAsCString; + if (!*s) { + DOM_CAMERA_LOGE("Preference '%s' cache is not initialized\n", aPref); + return false; + } + if ((*s)->IsEmpty()) { + DOM_CAMERA_LOGI("Preference '%s' is not set\n", aPref); + return false; + } + + DOM_CAMERA_LOGI("Preference '%s', got '%s'\n", aPref, (*s)->get()); + aVal = **s; + return true; +} + +/* static */ +bool +CameraPreferences::GetPref(const char* aPref, nsresult& aVal) +{ + MOZ_ASSERT(sPrefMonitor, "sPrefMonitor missing in CameraPreferences::GetPref()"); + MonitorAutoLock mon(*sPrefMonitor); + + uint32_t i = PrefToIndex(aPref); + if (i == kPrefNotFound || i >= ArrayLength(sPrefs)) { + DOM_CAMERA_LOGW("Preference '%s' is not tracked by CameraPreferences\n", aPref); + return false; + } + if (sPrefs[i].mValueType != kPrefValueIsNSResult) { + DOM_CAMERA_LOGW("Preference '%s' is not an nsresult type\n", aPref); + return false; + } + + nsresult v = *sPrefs[i].mValue.mAsNsResult; + if (v == NS_OK) { + DOM_CAMERA_LOGI("Preference '%s' is not set\n", aPref); + return false; + } + + DOM_CAMERA_LOGI("Preference '%s', got 0x%x\n", aPref, v); + aVal = v; + return true; +} diff --git a/dom/camera/CameraPreferences.h b/dom/camera/CameraPreferences.h new file mode 100644 index 00000000000..f1a59522ac2 --- /dev/null +++ b/dom/camera/CameraPreferences.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef DOM_CAMERA_CAMERAPREFERENCES_H +#define DOM_CAMERA_CAMERAPREFERENCES_H + +#include "nsString.h" + +namespace mozilla { + +template class StaticAutoPtr; + +class CameraPreferences +{ +public: + static bool Initialize(); + static void Shutdown(); + + static bool GetPref(const char* aPref, nsACString& aVal); + static bool GetPref(const char* aPref, nsresult& aVal); + +protected: + static const uint32_t kPrefNotFound = UINT32_MAX; + static uint32_t PrefToIndex(const char* aPref); + + static void PreferenceChanged(const char* aPref, void* aClosure); + static nsresult UpdatePref(const char* aPref, nsresult& aVar); + static nsresult UpdatePref(const char* aPref, nsACString& aVar); + + enum PrefValueType { + kPrefValueIsNSResult, + kPrefValueIsCString + }; + struct Pref { + const char* const mPref; + PrefValueType mValueType; + union { + // The 'mAsVoid' member must be first and is required to allow 'mValue' + // to be initialized with any pointer type, as not all of our platforms + // support the use of designated initializers; in their absence, only + // the first element of a union can be statically initialized, and + // 'void*' lets us stuff any pointer type into it. + void* mAsVoid; + StaticAutoPtr* mAsCString; + nsresult* mAsNsResult; + } mValue; + }; + static Pref sPrefs[]; + + static StaticAutoPtr sPrefTestEnabled; + static StaticAutoPtr sPrefHardwareTest; + static StaticAutoPtr sPrefGonkParameters; + + static nsresult sPrefCameraControlMethodErrorOverride; + static nsresult sPrefCameraControlAsyncErrorOverride; + +private: + // static class only + CameraPreferences(); + ~CameraPreferences(); +}; + +} // namespace mozilla + +#endif // DOM_CAMERA_CAMERAPREFERENCES_H diff --git a/dom/camera/GonkCameraHwMgr.cpp b/dom/camera/GonkCameraHwMgr.cpp index c1eb3dee8fc..96c3628c51a 100644 --- a/dom/camera/GonkCameraHwMgr.cpp +++ b/dom/camera/GonkCameraHwMgr.cpp @@ -23,7 +23,7 @@ #include "base/basictypes.h" #include "nsDebug.h" #include "mozilla/layers/TextureClient.h" -#include "mozilla/Preferences.h" +#include "CameraPreferences.h" #include "mozilla/RefPtr.h" #include "GonkCameraControl.h" #include "GonkNativeWindow.h" @@ -212,8 +212,8 @@ GonkCameraHardware::Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCam return nullptr; } - const nsAdoptingCString& test = - mozilla::Preferences::GetCString("camera.control.test.enabled"); + nsCString test; + CameraPreferences::GetPref("camera.control.test.enabled", test); sp cameraHardware; if (test.EqualsASCII("hardware")) { NS_WARNING("Using test Gonk hardware layer"); diff --git a/dom/camera/GonkCameraManager.cpp b/dom/camera/GonkCameraManager.cpp index febb31a888a..41d0b6d7746 100644 --- a/dom/camera/GonkCameraManager.cpp +++ b/dom/camera/GonkCameraManager.cpp @@ -20,7 +20,7 @@ #include "CameraCommon.h" #include "GonkCameraControl.h" -#include "mozilla/Preferences.h" +#include "CameraPreferences.h" #include "TestGonkCameraControl.h" using namespace mozilla; @@ -117,13 +117,12 @@ ICameraControl::GetListOfCameras(nsTArray& aList) return NS_OK; } -static const char* sTestModeEnabled = "camera.control.test.enabled"; - // implementation-specific camera factory already_AddRefed ICameraControl::Create(uint32_t aCameraId) { - const nsAdoptingCString& test = Preferences::GetCString(sTestModeEnabled); + nsCString test; + CameraPreferences::GetPref("camera.control.test.enabled", test); nsRefPtr control; if (test.EqualsASCII("control")) { NS_WARNING("Using test CameraControl layer"); diff --git a/dom/camera/TestGonkCameraControl.cpp b/dom/camera/TestGonkCameraControl.cpp index d78504045a2..67518a23dac 100644 --- a/dom/camera/TestGonkCameraControl.cpp +++ b/dom/camera/TestGonkCameraControl.cpp @@ -15,13 +15,10 @@ */ #include "TestGonkCameraControl.h" -#include "mozilla/Preferences.h" +#include "CameraPreferences.h" using namespace mozilla; -static const char* sMethodErrorOverride = "camera.control.test.method.error"; -static const char* sAsyncErrorOverride = "camera.control.test.async.error"; - TestGonkCameraControl::TestGonkCameraControl(uint32_t aCameraId) : nsGonkCameraControl(aCameraId) { @@ -37,9 +34,8 @@ TestGonkCameraControl::~TestGonkCameraControl() nsresult TestGonkCameraControl::ForceMethodFailWithCodeInternal(const char* aFile, int aLine) { - nsresult rv = - static_cast(Preferences::GetInt(sMethodErrorOverride, - static_cast(NS_OK))); + nsresult rv = NS_OK; + CameraPreferences::GetPref("camera.control.test.method.error", rv); if (NS_FAILED(rv)) { DOM_CAMERA_LOGI("[%s:%d] CameraControl method error override: 0x%x\n", aFile, aLine, rv); @@ -50,9 +46,8 @@ TestGonkCameraControl::ForceMethodFailWithCodeInternal(const char* aFile, int aL nsresult TestGonkCameraControl::ForceAsyncFailWithCodeInternal(const char* aFile, int aLine) { - nsresult rv = - static_cast(Preferences::GetInt(sAsyncErrorOverride, - static_cast(NS_OK))); + nsresult rv = NS_OK; + CameraPreferences::GetPref("camera.control.test.async.error", rv); if (NS_FAILED(rv)) { DOM_CAMERA_LOGI("[%s:%d] CameraControl async error override: 0x%x\n", aFile, aLine, rv); diff --git a/dom/camera/TestGonkCameraHardware.cpp b/dom/camera/TestGonkCameraHardware.cpp index e4f83685151..418388e2247 100644 --- a/dom/camera/TestGonkCameraHardware.cpp +++ b/dom/camera/TestGonkCameraHardware.cpp @@ -16,7 +16,7 @@ #include "TestGonkCameraHardware.h" -#include "mozilla/Preferences.h" +#include "CameraPreferences.h" #include "nsThreadUtils.h" using namespace android; @@ -52,7 +52,8 @@ TestGonkCameraHardware::Init() const nsCString TestGonkCameraHardware::TestCase() { - const nsCString test = Preferences::GetCString("camera.control.test.hardware"); + nsCString test; + CameraPreferences::GetPref("camera.control.test.hardware", test); return test; } @@ -77,7 +78,8 @@ TestGonkCameraHardware::GetExtraParameters() * may contain equals signs or semicolons. We don't enforce that here * so that we can also test correct handling of improperly-formatted values. */ - const nsCString parameters = Preferences::GetCString("camera.control.test.hardware.gonk.parameters"); + nsCString parameters; + CameraPreferences::GetPref("camera.control.test.hardware.gonk.parameters", parameters); DOM_CAMERA_LOGA("TestGonkCameraHardware : extra-parameters '%s'\n", parameters.get()); return parameters; diff --git a/dom/camera/moz.build b/dom/camera/moz.build index 6acf7ded68c..148aa5d8d1d 100644 --- a/dom/camera/moz.build +++ b/dom/camera/moz.build @@ -9,13 +9,13 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': EXPORTS += [ 'CameraCommon.h', - 'CameraPreviewMediaStream.h', + 'CameraPreferences.h', 'DOMCameraManager.h', - 'GonkCameraControl.h', ] SOURCES += [ 'CameraControlImpl.cpp', + 'CameraPreferences.cpp', 'CameraPreviewMediaStream.cpp', 'CameraRecorderProfiles.cpp', 'DOMCameraCapabilities.cpp', diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 35a3756e817..716f0317035 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -132,6 +132,7 @@ using namespace mozilla::system; #include "mozilla/IMEStateManager.h" #include "nsDocument.h" #include "mozilla/dom/HTMLVideoElement.h" +#include "CameraPreferences.h" using namespace mozilla; using namespace mozilla::net; @@ -296,6 +297,8 @@ nsLayoutStatics::Initialize() CounterStyleManager::InitializeBuiltinCounterStyles(); + CameraPreferences::Initialize(); + return NS_OK; } @@ -426,4 +429,6 @@ nsLayoutStatics::Shutdown() nsDocument::XPCOMShutdown(); CacheObserver::Shutdown(); + + CameraPreferences::Shutdown(); }