[Android] Move PrefChangeRegistrar to components/prefs
Make it possible to observe local_state instead of Profile prefs.
Bug: 381122436,40132529
Change-Id: Ib7ec2cfac791505b89586df7d682de40bdba2149
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6055147
Reviewed-by: Theresa Sullivan <[email protected]>
Reviewed-by: Ted Choc <[email protected]>
Commit-Queue: Henrique Nakashima <[email protected]>
Reviewed-by: Yaron Friedman <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1390455}
diff --git a/components/prefs/BUILD.gn b/components/prefs/BUILD.gn
index e31c110f..9deb408f 100644
--- a/components/prefs/BUILD.gn
+++ b/components/prefs/BUILD.gn
@@ -64,6 +64,8 @@
if (is_android) {
sources += [
+ "android/pref_change_registrar_android.cc",
+ "android/pref_change_registrar_android.h",
"android/pref_service_android.cc",
"android/pref_service_android.h",
]
diff --git a/components/prefs/android/BUILD.gn b/components/prefs/android/BUILD.gn
index ff3c055..37bda57f 100644
--- a/components/prefs/android/BUILD.gn
+++ b/components/prefs/android/BUILD.gn
@@ -6,13 +6,20 @@
import("//third_party/jni_zero/jni_zero.gni")
generate_jni("jni_headers") {
- sources = [ "java/src/org/chromium/components/prefs/PrefService.java" ]
+ sources = [
+ "java/src/org/chromium/components/prefs/PrefChangeRegistrar.java",
+ "java/src/org/chromium/components/prefs/PrefService.java",
+ ]
}
android_library("java") {
srcjar_deps = [ ":jni_headers" ]
- sources = [ "java/src/org/chromium/components/prefs/PrefService.java" ]
+ sources = [
+ "java/src/org/chromium/components/prefs/PrefChangeRegistrar.java",
+ "java/src/org/chromium/components/prefs/PrefService.java",
+ ]
deps = [
+ "//base:base_java",
"//build/android:build_java",
"//third_party/androidx:androidx_annotation_annotation_java",
"//third_party/jni_zero:jni_zero_java",
diff --git a/components/prefs/android/java/src/org/chromium/components/prefs/PrefChangeRegistrar.java b/components/prefs/android/java/src/org/chromium/components/prefs/PrefChangeRegistrar.java
new file mode 100644
index 0000000..9f0f02f53
--- /dev/null
+++ b/components/prefs/android/java/src/org/chromium/components/prefs/PrefChangeRegistrar.java
@@ -0,0 +1,94 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.prefs;
+
+import android.util.ArrayMap;
+
+import org.jni_zero.CalledByNative;
+import org.jni_zero.JniType;
+import org.jni_zero.NativeMethods;
+
+import java.util.Map;
+
+/**
+ * This class is the Java implementation of native PrefChangeRegistrar. It receives notification for
+ * changes of one or more preferences from native PrefService.
+ *
+ * <p>Note that {@link #destroy} should be called to destroy the native PrefChangeRegistrar.
+ */
+public class PrefChangeRegistrar {
+ /** Interface for callback when registered preference is changed. */
+ public interface PrefObserver {
+ void onPreferenceChange();
+ }
+
+ /** Mapping preference key and corresponding observer. */
+ private final Map<String, PrefObserver> mObservers = new ArrayMap<>();
+
+ /** Native pointer for PrefChangeRegistrarAndroid. */
+ private long mNativeRegistrar;
+
+ /** Initialize native PrefChangeRegistrar. */
+ public PrefChangeRegistrar(PrefService prefs) {
+ mNativeRegistrar = PrefChangeRegistrarJni.get().init(PrefChangeRegistrar.this, prefs);
+ }
+
+ /**
+ * Add an observer to be notified of changes to the specified preference.
+ *
+ * @param preference The preference to be observed.
+ * @param observer The observer to be notified.
+ */
+ public void addObserver(String preference, PrefObserver observer) {
+ assert mObservers.get(preference) == null
+ : "Only one observer should be added to each preference.";
+ mObservers.put(preference, observer);
+ PrefChangeRegistrarJni.get().add(mNativeRegistrar, PrefChangeRegistrar.this, preference);
+ }
+
+ /**
+ * Remove an observer for the specified preference if it has previously been added.
+ *
+ * @param preference The specified preference.
+ */
+ public void removeObserver(String preference) {
+ PrefObserver observer = mObservers.get(preference);
+ if (observer == null) return;
+ mObservers.remove(preference);
+ PrefChangeRegistrarJni.get().remove(mNativeRegistrar, PrefChangeRegistrar.this, preference);
+ }
+
+ /** Destroy native PrefChangeRegistrar. */
+ public void destroy() {
+ if (mNativeRegistrar != 0) {
+ PrefChangeRegistrarJni.get().destroy(mNativeRegistrar, PrefChangeRegistrar.this);
+ }
+ mNativeRegistrar = 0;
+ }
+
+ @CalledByNative
+ private void onPreferenceChange(String preference) {
+ assert mObservers.get(preference) != null
+ : "Notification from unregistered preference changes.";
+ mObservers.get(preference).onPreferenceChange();
+ }
+
+ @NativeMethods
+ public interface Natives {
+ long init(PrefChangeRegistrar caller, @JniType("PrefService*") PrefService prefService);
+
+ void add(
+ long nativePrefChangeRegistrarAndroid,
+ PrefChangeRegistrar caller,
+ String preference);
+
+ void remove(
+ long nativePrefChangeRegistrarAndroid,
+ PrefChangeRegistrar caller,
+ String preference);
+
+ void destroy(long nativePrefChangeRegistrarAndroid, PrefChangeRegistrar caller);
+ }
+}
diff --git a/components/prefs/android/pref_change_registrar_android.cc b/components/prefs/android/pref_change_registrar_android.cc
new file mode 100644
index 0000000..c94d45b5
--- /dev/null
+++ b/components/prefs/android/pref_change_registrar_android.cc
@@ -0,0 +1,66 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/prefs/android/pref_change_registrar_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/functional/bind.h"
+#include "components/prefs/android/pref_service_android.h"
+
+// Must come after all headers that specialize FromJniType() / ToJniType().
+#include "components/prefs/android/jni_headers/PrefChangeRegistrar_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF8ToJavaString;
+
+PrefChangeRegistrarAndroid::PrefChangeRegistrarAndroid(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ PrefService* prefs) {
+ pref_change_registrar_.Init(prefs);
+ pref_change_registrar_jobject_.Reset(env, obj);
+}
+
+PrefChangeRegistrarAndroid::~PrefChangeRegistrarAndroid() = default;
+
+void PrefChangeRegistrarAndroid::Destroy(JNIEnv*,
+ const JavaParamRef<jobject>&) {
+ delete this;
+}
+
+void PrefChangeRegistrarAndroid::Add(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jstring>& j_preference) {
+ std::string preference =
+ base::android::ConvertJavaStringToUTF8(env, j_preference);
+ pref_change_registrar_.Add(
+ preference,
+ base::BindRepeating(&PrefChangeRegistrarAndroid::OnPreferenceChange,
+ base::Unretained(this), preference));
+}
+
+void PrefChangeRegistrarAndroid::Remove(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jstring>& j_preference) {
+ pref_change_registrar_.Remove(
+ base::android::ConvertJavaStringToUTF8(env, j_preference));
+}
+
+void PrefChangeRegistrarAndroid::OnPreferenceChange(std::string preference) {
+ JNIEnv* env = AttachCurrentThread();
+ Java_PrefChangeRegistrar_onPreferenceChange(
+ env, pref_change_registrar_jobject_,
+ base::android::ConvertUTF8ToJavaString(env, preference));
+}
+
+jlong JNI_PrefChangeRegistrar_Init(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ PrefService* prefs) {
+ return reinterpret_cast<intptr_t>(
+ new PrefChangeRegistrarAndroid(env, obj, prefs));
+}
diff --git a/components/prefs/android/pref_change_registrar_android.h b/components/prefs/android/pref_change_registrar_android.h
new file mode 100644
index 0000000..53f780df
--- /dev/null
+++ b/components/prefs/android/pref_change_registrar_android.h
@@ -0,0 +1,45 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PREFS_ANDROID_PREF_CHANGE_REGISTRAR_ANDROID_H_
+#define COMPONENTS_PREFS_ANDROID_PREF_CHANGE_REGISTRAR_ANDROID_H_
+
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/raw_ptr.h"
+#include "components/prefs/pref_change_registrar.h"
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaGlobalRef;
+
+class PrefService;
+
+// This class contains a PrefChangeRegistrar that observes PrefService changes
+// for Android.
+class PrefChangeRegistrarAndroid {
+ public:
+ PrefChangeRegistrarAndroid(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ PrefService* prefs);
+ void Destroy(JNIEnv*, const JavaParamRef<jobject>&);
+
+ PrefChangeRegistrarAndroid(const PrefChangeRegistrarAndroid&) = delete;
+ PrefChangeRegistrarAndroid& operator=(const PrefChangeRegistrarAndroid&) =
+ delete;
+
+ void Add(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jstring>& j_preference);
+ void Remove(JNIEnv* env,
+ const JavaParamRef<jobject>& obj,
+ const JavaParamRef<jstring>& j_preference);
+
+ private:
+ ~PrefChangeRegistrarAndroid();
+ void OnPreferenceChange(std::string preference);
+
+ PrefChangeRegistrar pref_change_registrar_;
+ ScopedJavaGlobalRef<jobject> pref_change_registrar_jobject_;
+};
+
+#endif // COMPONENTS_PREFS_ANDROID_PREF_CHANGE_REGISTRAR_ANDROID_H_