diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /widget/android/PrefsHelper.h | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'widget/android/PrefsHelper.h')
-rw-r--r-- | widget/android/PrefsHelper.h | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/widget/android/PrefsHelper.h b/widget/android/PrefsHelper.h new file mode 100644 index 0000000000..0cc4ec4548 --- /dev/null +++ b/widget/android/PrefsHelper.h @@ -0,0 +1,306 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * 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 PrefsHelper_h +#define PrefsHelper_h + +#include "MainThreadUtils.h" +#include "nsAppShell.h" +#include "nsCOMPtr.h" +#include "nsVariant.h" + +#include "mozilla/java/PrefsHelperNatives.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" + +namespace mozilla { + +class PrefsHelper : public java::PrefsHelper::Natives<PrefsHelper> { + PrefsHelper() = delete; + + static bool GetVariantPref(nsIObserverService* aObsServ, + nsIWritableVariant* aVariant, + jni::Object::Param aPrefHandler, + const jni::String::LocalRef& aPrefName) { + if (NS_FAILED(aObsServ->NotifyObservers(aVariant, "android-get-pref", + aPrefName->ToString().get()))) { + return false; + } + + uint16_t varType = aVariant->GetDataType(); + + int32_t type = java::PrefsHelper::PREF_INVALID; + bool boolVal = false; + int32_t intVal = 0; + nsAutoString strVal; + + switch (varType) { + case nsIDataType::VTYPE_BOOL: + type = java::PrefsHelper::PREF_BOOL; + if (NS_FAILED(aVariant->GetAsBool(&boolVal))) { + return false; + } + break; + case nsIDataType::VTYPE_INT32: + type = java::PrefsHelper::PREF_INT; + if (NS_FAILED(aVariant->GetAsInt32(&intVal))) { + return false; + } + break; + case nsIDataType::VTYPE_ASTRING: + type = java::PrefsHelper::PREF_STRING; + if (NS_FAILED(aVariant->GetAsAString(strVal))) { + return false; + } + break; + default: + return false; + } + + jni::StringParam jstrVal(type == java::PrefsHelper::PREF_STRING + ? jni::StringParam(strVal, aPrefName.Env()) + : jni::StringParam(nullptr)); + + if (aPrefHandler) { + java::PrefsHelper::CallPrefHandler(aPrefHandler, type, aPrefName, boolVal, + intVal, jstrVal); + } else { + java::PrefsHelper::OnPrefChange(aPrefName, type, boolVal, intVal, + jstrVal); + } + return true; + } + + static bool SetVariantPref(nsIObserverService* aObsServ, + nsIWritableVariant* aVariant, + jni::String::Param aPrefName, bool aFlush, + int32_t aType, bool aBoolVal, int32_t aIntVal, + jni::String::Param aStrVal) { + nsresult rv = NS_ERROR_FAILURE; + + switch (aType) { + case java::PrefsHelper::PREF_BOOL: + rv = aVariant->SetAsBool(aBoolVal); + break; + case java::PrefsHelper::PREF_INT: + rv = aVariant->SetAsInt32(aIntVal); + break; + case java::PrefsHelper::PREF_STRING: + rv = aVariant->SetAsAString(aStrVal->ToString()); + break; + } + + if (NS_SUCCEEDED(rv)) { + rv = aObsServ->NotifyObservers(aVariant, "android-set-pref", + aPrefName->ToString().get()); + } + + uint16_t varType = nsIDataType::VTYPE_EMPTY; + if (NS_SUCCEEDED(rv)) { + varType = aVariant->GetDataType(); + } + + // We use set-to-empty to signal the pref was handled. + const bool handled = varType == nsIDataType::VTYPE_EMPTY; + + if (NS_SUCCEEDED(rv) && handled && aFlush) { + rv = Preferences::GetService()->SavePrefFile(nullptr); + } + + if (NS_SUCCEEDED(rv)) { + return handled; + } + + NS_WARNING( + nsPrintfCString("Failed to set pref %s", aPrefName->ToCString().get()) + .get()); + // Pretend we handled the pref. + return true; + } + + public: + static void GetPrefs(const jni::Class::LocalRef& aCls, + jni::ObjectArray::Param aPrefNames, + jni::Object::Param aPrefHandler) { + nsTArray<jni::Object::LocalRef> nameRefArray(aPrefNames->GetElements()); + nsCOMPtr<nsIObserverService> obsServ; + nsCOMPtr<nsIWritableVariant> value; + nsAutoString strVal; + + for (jni::Object::LocalRef& nameRef : nameRefArray) { + jni::String::LocalRef nameStr(std::move(nameRef)); + const nsCString& name = nameStr->ToCString(); + + int32_t type = java::PrefsHelper::PREF_INVALID; + bool boolVal = false; + int32_t intVal = 0; + strVal.Truncate(); + + switch (Preferences::GetType(name.get())) { + case nsIPrefBranch::PREF_BOOL: + type = java::PrefsHelper::PREF_BOOL; + boolVal = Preferences::GetBool(name.get()); + break; + + case nsIPrefBranch::PREF_INT: + type = java::PrefsHelper::PREF_INT; + intVal = Preferences::GetInt(name.get()); + break; + + case nsIPrefBranch::PREF_STRING: { + type = java::PrefsHelper::PREF_STRING; + nsresult rv = Preferences::GetLocalizedString(name.get(), strVal); + if (NS_FAILED(rv)) { + Preferences::GetString(name.get(), strVal); + } + break; + } + default: + // Pref not found; try to find it. + if (!obsServ) { + obsServ = services::GetObserverService(); + if (!obsServ) { + continue; + } + } + if (value) { + value->SetAsEmpty(); + } else { + value = new nsVariant(); + } + if (!GetVariantPref(obsServ, value, aPrefHandler, nameStr)) { + NS_WARNING( + nsPrintfCString("Failed to get pref %s", name.get()).get()); + } + continue; + } + + java::PrefsHelper::CallPrefHandler( + aPrefHandler, type, nameStr, boolVal, intVal, + jni::StringParam(type == java::PrefsHelper::PREF_STRING + ? jni::StringParam(strVal, aCls.Env()) + : jni::StringParam(nullptr))); + } + + java::PrefsHelper::CallPrefHandler(aPrefHandler, + java::PrefsHelper::PREF_FINISH, nullptr, + false, 0, nullptr); + } + + static void SetPref(jni::String::Param aPrefName, bool aFlush, int32_t aType, + bool aBoolVal, int32_t aIntVal, + jni::String::Param aStrVal) { + const nsCString& name = aPrefName->ToCString(); + + if (Preferences::GetType(name.get()) == nsIPrefBranch::PREF_INVALID) { + // No pref; try asking first. + nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService(); + nsCOMPtr<nsIWritableVariant> value = new nsVariant(); + if (obsServ && SetVariantPref(obsServ, value, aPrefName, aFlush, aType, + aBoolVal, aIntVal, aStrVal)) { + // The "pref" has changed; send a notification. + GetVariantPref(obsServ, value, nullptr, + jni::String::LocalRef(aPrefName)); + return; + } + } + + switch (aType) { + case java::PrefsHelper::PREF_BOOL: + Preferences::SetBool(name.get(), aBoolVal); + break; + case java::PrefsHelper::PREF_INT: + Preferences::SetInt(name.get(), aIntVal); + break; + case java::PrefsHelper::PREF_STRING: + Preferences::SetString(name.get(), aStrVal->ToString()); + break; + default: + MOZ_ASSERT(false, "Invalid pref type"); + } + + if (aFlush) { + Preferences::GetService()->SavePrefFile(nullptr); + } + } + + static void AddObserver(const jni::Class::LocalRef& aCls, + jni::ObjectArray::Param aPrefNames, + jni::Object::Param aPrefHandler, + jni::ObjectArray::Param aPrefsToObserve) { + // Call observer immediately with existing pref values. + GetPrefs(aCls, aPrefNames, aPrefHandler); + + if (!aPrefsToObserve) { + return; + } + + nsTArray<jni::Object::LocalRef> nameRefArray( + aPrefsToObserve->GetElements()); + nsAppShell* const appShell = nsAppShell::Get(); + MOZ_ASSERT(appShell); + + for (jni::Object::LocalRef& nameRef : nameRefArray) { + jni::String::LocalRef nameStr(std::move(nameRef)); + MOZ_ALWAYS_SUCCEEDS( + Preferences::AddStrongObserver(appShell, nameStr->ToCString())); + } + } + + static void RemoveObserver(const jni::Class::LocalRef& aCls, + jni::ObjectArray::Param aPrefsToUnobserve) { + nsTArray<jni::Object::LocalRef> nameRefArray( + aPrefsToUnobserve->GetElements()); + nsAppShell* const appShell = nsAppShell::Get(); + MOZ_ASSERT(appShell); + + for (jni::Object::LocalRef& nameRef : nameRefArray) { + jni::String::LocalRef nameStr(std::move(nameRef)); + MOZ_ALWAYS_SUCCEEDS( + Preferences::RemoveObserver(appShell, nameStr->ToCString())); + } + } + + static void OnPrefChange(const char16_t* aData) { + const nsCString& name = NS_LossyConvertUTF16toASCII(aData); + + int32_t type = -1; + bool boolVal = false; + int32_t intVal = false; + nsAutoString strVal; + + switch (Preferences::GetType(name.get())) { + case nsIPrefBranch::PREF_BOOL: + type = java::PrefsHelper::PREF_BOOL; + boolVal = Preferences::GetBool(name.get()); + break; + case nsIPrefBranch::PREF_INT: + type = java::PrefsHelper::PREF_INT; + intVal = Preferences::GetInt(name.get()); + break; + case nsIPrefBranch::PREF_STRING: { + type = java::PrefsHelper::PREF_STRING; + nsresult rv = Preferences::GetLocalizedString(name.get(), strVal); + if (NS_FAILED(rv)) { + Preferences::GetString(name.get(), strVal); + } + break; + } + default: + NS_WARNING(nsPrintfCString("Invalid pref %s", name.get()).get()); + return; + } + + java::PrefsHelper::OnPrefChange( + name, type, boolVal, intVal, + jni::StringParam(type == java::PrefsHelper::PREF_STRING + ? jni::StringParam(strVal) + : jni::StringParam(nullptr))); + } +}; + +} // namespace mozilla + +#endif // PrefsHelper_h |