Bug 1540028 [wpt PR 16099] - Catch more exceptions in Document-createElement-namespac...
[gecko.git] / widget / android / PrefsHelper.h
blobb5cb37c3910ea84e405b326a8dd1c56946e560ef
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/. */
6 #ifndef PrefsHelper_h
7 #define PrefsHelper_h
9 #include "GeneratedJNINatives.h"
10 #include "MainThreadUtils.h"
11 #include "nsAppShell.h"
12 #include "nsCOMPtr.h"
13 #include "nsVariant.h"
15 #include "mozilla/Preferences.h"
16 #include "mozilla/Services.h"
18 namespace mozilla {
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()))) {
29 return false;
32 uint16_t varType = aVariant->GetDataType();
34 int32_t type = java::PrefsHelper::PREF_INVALID;
35 bool boolVal = false;
36 int32_t intVal = 0;
37 nsAutoString strVal;
39 switch (varType) {
40 case nsIDataType::VTYPE_BOOL:
41 type = java::PrefsHelper::PREF_BOOL;
42 if (NS_FAILED(aVariant->GetAsBool(&boolVal))) {
43 return false;
45 break;
46 case nsIDataType::VTYPE_INT32:
47 type = java::PrefsHelper::PREF_INT;
48 if (NS_FAILED(aVariant->GetAsInt32(&intVal))) {
49 return false;
51 break;
52 case nsIDataType::VTYPE_ASTRING:
53 type = java::PrefsHelper::PREF_STRING;
54 if (NS_FAILED(aVariant->GetAsAString(strVal))) {
55 return false;
57 break;
58 default:
59 return false;
62 jni::StringParam jstrVal(type == java::PrefsHelper::PREF_STRING
63 ? jni::StringParam(strVal, aPrefName.Env())
64 : jni::StringParam(nullptr));
66 if (aPrefHandler) {
67 java::PrefsHelper::CallPrefHandler(aPrefHandler, type, aPrefName, boolVal,
68 intVal, jstrVal);
69 } else {
70 java::PrefsHelper::OnPrefChange(aPrefName, type, boolVal, intVal,
71 jstrVal);
73 return true;
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;
83 switch (aType) {
84 case java::PrefsHelper::PREF_BOOL:
85 rv = aVariant->SetAsBool(aBoolVal);
86 break;
87 case java::PrefsHelper::PREF_INT:
88 rv = aVariant->SetAsInt32(aIntVal);
89 break;
90 case java::PrefsHelper::PREF_STRING:
91 rv = aVariant->SetAsAString(aStrVal->ToString());
92 break;
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)) {
113 return handled;
116 NS_WARNING(
117 nsPrintfCString("Failed to set pref %s", aPrefName->ToCString().get())
118 .get());
119 // Pretend we handled the pref.
120 return true;
123 public:
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;
130 nsAutoString strVal;
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;
138 int32_t intVal = 0;
139 strVal.Truncate();
141 switch (Preferences::GetType(name.get())) {
142 case nsIPrefBranch::PREF_BOOL:
143 type = java::PrefsHelper::PREF_BOOL;
144 boolVal = Preferences::GetBool(name.get());
145 break;
147 case nsIPrefBranch::PREF_INT:
148 type = java::PrefsHelper::PREF_INT;
149 intVal = Preferences::GetInt(name.get());
150 break;
152 case nsIPrefBranch::PREF_STRING: {
153 type = java::PrefsHelper::PREF_STRING;
154 nsresult rv = Preferences::GetLocalizedString(name.get(), strVal);
155 if (NS_FAILED(rv)) {
156 Preferences::GetString(name.get(), strVal);
158 break;
160 default:
161 // Pref not found; try to find it.
162 if (!obsServ) {
163 obsServ = services::GetObserverService();
164 if (!obsServ) {
165 continue;
168 if (value) {
169 value->SetAsEmpty();
170 } else {
171 value = new nsVariant();
173 if (!GetVariantPref(obsServ, value, aPrefHandler, nameStr)) {
174 NS_WARNING(
175 nsPrintfCString("Failed to get pref %s", name.get()).get());
177 continue;
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,
189 false, 0, 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));
206 return;
210 switch (aType) {
211 case java::PrefsHelper::PREF_BOOL:
212 Preferences::SetBool(name.get(), aBoolVal);
213 break;
214 case java::PrefsHelper::PREF_INT:
215 Preferences::SetInt(name.get(), aIntVal);
216 break;
217 case java::PrefsHelper::PREF_STRING:
218 Preferences::SetString(name.get(), aStrVal->ToString());
219 break;
220 default:
221 MOZ_ASSERT(false, "Invalid pref type");
224 if (aFlush) {
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) {
237 return;
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));
247 MOZ_ALWAYS_SUCCEEDS(
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));
261 MOZ_ALWAYS_SUCCEEDS(
262 Preferences::RemoveObserver(appShell, nameStr->ToCString()));
266 static void OnPrefChange(const char16_t* aData) {
267 const nsCString& name = NS_LossyConvertUTF16toASCII(aData);
269 int32_t type = -1;
270 bool boolVal = false;
271 int32_t intVal = false;
272 nsAutoString strVal;
274 switch (Preferences::GetType(name.get())) {
275 case nsIPrefBranch::PREF_BOOL:
276 type = java::PrefsHelper::PREF_BOOL;
277 boolVal = Preferences::GetBool(name.get());
278 break;
279 case nsIPrefBranch::PREF_INT:
280 type = java::PrefsHelper::PREF_INT;
281 intVal = Preferences::GetInt(name.get());
282 break;
283 case nsIPrefBranch::PREF_STRING: {
284 type = java::PrefsHelper::PREF_STRING;
285 nsresult rv = Preferences::GetLocalizedString(name.get(), strVal);
286 if (NS_FAILED(rv)) {
287 Preferences::GetString(name.get(), strVal);
289 break;
291 default:
292 NS_WARNING(nsPrintfCString("Invalid pref %s", name.get()).get());
293 return;
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