1 /* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "GeneratedJNINatives.h"
10 #include "MainThreadUtils.h"
11 #include "nsAppShell.h"
13 #include "nsVariant.h"
15 #include "mozilla/Preferences.h"
16 #include "mozilla/Services.h"
20 class PrefsHelper
: public java::PrefsHelper::Natives
<PrefsHelper
> {
21 PrefsHelper() = delete;
23 static bool GetVariantPref(nsIObserverService
* aObsServ
,
24 nsIWritableVariant
* aVariant
,
25 jni::Object::Param aPrefHandler
,
26 const jni::String::LocalRef
& aPrefName
) {
27 if (NS_FAILED(aObsServ
->NotifyObservers(aVariant
, "android-get-pref",
28 aPrefName
->ToString().get()))) {
32 uint16_t varType
= aVariant
->GetDataType();
34 int32_t type
= java::PrefsHelper::PREF_INVALID
;
40 case nsIDataType::VTYPE_BOOL
:
41 type
= java::PrefsHelper::PREF_BOOL
;
42 if (NS_FAILED(aVariant
->GetAsBool(&boolVal
))) {
46 case nsIDataType::VTYPE_INT32
:
47 type
= java::PrefsHelper::PREF_INT
;
48 if (NS_FAILED(aVariant
->GetAsInt32(&intVal
))) {
52 case nsIDataType::VTYPE_ASTRING
:
53 type
= java::PrefsHelper::PREF_STRING
;
54 if (NS_FAILED(aVariant
->GetAsAString(strVal
))) {
62 jni::StringParam
jstrVal(type
== java::PrefsHelper::PREF_STRING
63 ? jni::StringParam(strVal
, aPrefName
.Env())
64 : jni::StringParam(nullptr));
67 java::PrefsHelper::CallPrefHandler(aPrefHandler
, type
, aPrefName
, boolVal
,
70 java::PrefsHelper::OnPrefChange(aPrefName
, type
, boolVal
, intVal
,
76 static bool SetVariantPref(nsIObserverService
* aObsServ
,
77 nsIWritableVariant
* aVariant
,
78 jni::String::Param aPrefName
, bool aFlush
,
79 int32_t aType
, bool aBoolVal
, int32_t aIntVal
,
80 jni::String::Param aStrVal
) {
81 nsresult rv
= NS_ERROR_FAILURE
;
84 case java::PrefsHelper::PREF_BOOL
:
85 rv
= aVariant
->SetAsBool(aBoolVal
);
87 case java::PrefsHelper::PREF_INT
:
88 rv
= aVariant
->SetAsInt32(aIntVal
);
90 case java::PrefsHelper::PREF_STRING
:
91 rv
= aVariant
->SetAsAString(aStrVal
->ToString());
95 if (NS_SUCCEEDED(rv
)) {
96 rv
= aObsServ
->NotifyObservers(aVariant
, "android-set-pref",
97 aPrefName
->ToString().get());
100 uint16_t varType
= nsIDataType::VTYPE_EMPTY
;
101 if (NS_SUCCEEDED(rv
)) {
102 varType
= aVariant
->GetDataType();
105 // We use set-to-empty to signal the pref was handled.
106 const bool handled
= varType
== nsIDataType::VTYPE_EMPTY
;
108 if (NS_SUCCEEDED(rv
) && handled
&& aFlush
) {
109 rv
= Preferences::GetService()->SavePrefFile(nullptr);
112 if (NS_SUCCEEDED(rv
)) {
117 nsPrintfCString("Failed to set pref %s", aPrefName
->ToCString().get())
119 // Pretend we handled the pref.
124 static void GetPrefs(const jni::Class::LocalRef
& aCls
,
125 jni::ObjectArray::Param aPrefNames
,
126 jni::Object::Param aPrefHandler
) {
127 nsTArray
<jni::Object::LocalRef
> nameRefArray(aPrefNames
->GetElements());
128 nsCOMPtr
<nsIObserverService
> obsServ
;
129 nsCOMPtr
<nsIWritableVariant
> value
;
132 for (jni::Object::LocalRef
& nameRef
: nameRefArray
) {
133 jni::String::LocalRef
nameStr(std::move(nameRef
));
134 const nsCString
& name
= nameStr
->ToCString();
136 int32_t type
= java::PrefsHelper::PREF_INVALID
;
137 bool boolVal
= false;
141 switch (Preferences::GetType(name
.get())) {
142 case nsIPrefBranch::PREF_BOOL
:
143 type
= java::PrefsHelper::PREF_BOOL
;
144 boolVal
= Preferences::GetBool(name
.get());
147 case nsIPrefBranch::PREF_INT
:
148 type
= java::PrefsHelper::PREF_INT
;
149 intVal
= Preferences::GetInt(name
.get());
152 case nsIPrefBranch::PREF_STRING
: {
153 type
= java::PrefsHelper::PREF_STRING
;
154 nsresult rv
= Preferences::GetLocalizedString(name
.get(), strVal
);
156 Preferences::GetString(name
.get(), strVal
);
161 // Pref not found; try to find it.
163 obsServ
= services::GetObserverService();
171 value
= new nsVariant();
173 if (!GetVariantPref(obsServ
, value
, aPrefHandler
, nameStr
)) {
175 nsPrintfCString("Failed to get pref %s", name
.get()).get());
180 java::PrefsHelper::CallPrefHandler(
181 aPrefHandler
, type
, nameStr
, boolVal
, intVal
,
182 jni::StringParam(type
== java::PrefsHelper::PREF_STRING
183 ? jni::StringParam(strVal
, aCls
.Env())
184 : jni::StringParam(nullptr)));
187 java::PrefsHelper::CallPrefHandler(aPrefHandler
,
188 java::PrefsHelper::PREF_FINISH
, nullptr,
192 static void SetPref(jni::String::Param aPrefName
, bool aFlush
, int32_t aType
,
193 bool aBoolVal
, int32_t aIntVal
,
194 jni::String::Param aStrVal
) {
195 const nsCString
& name
= aPrefName
->ToCString();
197 if (Preferences::GetType(name
.get()) == nsIPrefBranch::PREF_INVALID
) {
198 // No pref; try asking first.
199 nsCOMPtr
<nsIObserverService
> obsServ
= services::GetObserverService();
200 nsCOMPtr
<nsIWritableVariant
> value
= new nsVariant();
201 if (obsServ
&& SetVariantPref(obsServ
, value
, aPrefName
, aFlush
, aType
,
202 aBoolVal
, aIntVal
, aStrVal
)) {
203 // The "pref" has changed; send a notification.
204 GetVariantPref(obsServ
, value
, nullptr,
205 jni::String::LocalRef(aPrefName
));
211 case java::PrefsHelper::PREF_BOOL
:
212 Preferences::SetBool(name
.get(), aBoolVal
);
214 case java::PrefsHelper::PREF_INT
:
215 Preferences::SetInt(name
.get(), aIntVal
);
217 case java::PrefsHelper::PREF_STRING
:
218 Preferences::SetString(name
.get(), aStrVal
->ToString());
221 MOZ_ASSERT(false, "Invalid pref type");
225 Preferences::GetService()->SavePrefFile(nullptr);
229 static void AddObserver(const jni::Class::LocalRef
& aCls
,
230 jni::ObjectArray::Param aPrefNames
,
231 jni::Object::Param aPrefHandler
,
232 jni::ObjectArray::Param aPrefsToObserve
) {
233 // Call observer immediately with existing pref values.
234 GetPrefs(aCls
, aPrefNames
, aPrefHandler
);
236 if (!aPrefsToObserve
) {
240 nsTArray
<jni::Object::LocalRef
> nameRefArray(
241 aPrefsToObserve
->GetElements());
242 nsAppShell
* const appShell
= nsAppShell::Get();
243 MOZ_ASSERT(appShell
);
245 for (jni::Object::LocalRef
& nameRef
: nameRefArray
) {
246 jni::String::LocalRef
nameStr(std::move(nameRef
));
248 Preferences::AddStrongObserver(appShell
, nameStr
->ToCString()));
252 static void RemoveObserver(const jni::Class::LocalRef
& aCls
,
253 jni::ObjectArray::Param aPrefsToUnobserve
) {
254 nsTArray
<jni::Object::LocalRef
> nameRefArray(
255 aPrefsToUnobserve
->GetElements());
256 nsAppShell
* const appShell
= nsAppShell::Get();
257 MOZ_ASSERT(appShell
);
259 for (jni::Object::LocalRef
& nameRef
: nameRefArray
) {
260 jni::String::LocalRef
nameStr(std::move(nameRef
));
262 Preferences::RemoveObserver(appShell
, nameStr
->ToCString()));
266 static void OnPrefChange(const char16_t
* aData
) {
267 const nsCString
& name
= NS_LossyConvertUTF16toASCII(aData
);
270 bool boolVal
= false;
271 int32_t intVal
= false;
274 switch (Preferences::GetType(name
.get())) {
275 case nsIPrefBranch::PREF_BOOL
:
276 type
= java::PrefsHelper::PREF_BOOL
;
277 boolVal
= Preferences::GetBool(name
.get());
279 case nsIPrefBranch::PREF_INT
:
280 type
= java::PrefsHelper::PREF_INT
;
281 intVal
= Preferences::GetInt(name
.get());
283 case nsIPrefBranch::PREF_STRING
: {
284 type
= java::PrefsHelper::PREF_STRING
;
285 nsresult rv
= Preferences::GetLocalizedString(name
.get(), strVal
);
287 Preferences::GetString(name
.get(), strVal
);
292 NS_WARNING(nsPrintfCString("Invalid pref %s", name
.get()).get());
296 java::PrefsHelper::OnPrefChange(
297 name
, type
, boolVal
, intVal
,
298 jni::StringParam(type
== java::PrefsHelper::PREF_STRING
299 ? jni::StringParam(strVal
)
300 : jni::StringParam(nullptr)));
304 } // namespace mozilla
306 #endif // PrefsHelper_h