Skip to content

Commit 2e730b4

Browse files
Googlera-maurice
authored andcommitted
[c++] port addSnapshotsInSyncListener
+mcg@ for java readability approval TESTED= linux: http://sponge2/e38ce350-ddeb-4461-9db7-07d20ed34e29 iOS: http://sponge2/f1fa15e4-747d-43f4-b725-f5f38ef9f9d3 Android:http://sponge2/72ec3dd4-cb27-4698-a14a-f365c03ee5f2 PiperOrigin-RevId: 292610511
1 parent c25fed5 commit 2e730b4

File tree

15 files changed

+285
-7
lines changed

15 files changed

+285
-7
lines changed

firestore/src/android/event_listener_android.cc

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ METHOD_LOOKUP_DEFINITION(
3939
"com/google/firebase/firestore/internal/cpp/QueryEventListener",
4040
QUERY_EVENT_LISTENER_METHODS)
4141

42+
#define VOID_EVENT_LISTENER_METHODS(X) X(Constructor, "<init>", "(J)V")
43+
METHOD_LOOKUP_DECLARATION(void_event_listener, VOID_EVENT_LISTENER_METHODS)
44+
METHOD_LOOKUP_DEFINITION(
45+
void_event_listener,
46+
"com/google/firebase/firestore/internal/cpp/VoidEventListener",
47+
VOID_EVENT_LISTENER_METHODS)
48+
4249
/* static */
4350
void EventListenerInternal::DocumentEventListenerNativeOnEvent(
4451
JNIEnv* env, jclass clazz, jlong firestore_ptr, jlong listener_ptr,
@@ -83,6 +90,19 @@ void EventListenerInternal::QueryEventListenerNativeOnEvent(
8390
listener->OnEvent(snapshot, error_code);
8491
}
8592

93+
/* static */
94+
void EventListenerInternal::VoidEventListenerNativeOnEvent(JNIEnv* env,
95+
jclass clazz,
96+
jlong listener_ptr) {
97+
if (listener_ptr == 0) {
98+
return;
99+
}
100+
EventListener<void>* listener =
101+
reinterpret_cast<EventListener<void>*>(listener_ptr);
102+
103+
listener->OnEvent(Error::Ok);
104+
}
105+
86106
/* static */
87107
jobject EventListenerInternal::EventListenerToJavaEventListener(
88108
JNIEnv* env, FirestoreInternal* firestore,
@@ -108,6 +128,17 @@ jobject EventListenerInternal::EventListenerToJavaEventListener(
108128
return result;
109129
}
110130

131+
/* static */
132+
jobject EventListenerInternal::EventListenerToJavaRunnable(
133+
JNIEnv* env, EventListener<void>* listener) {
134+
jobject result = env->NewObject(
135+
void_event_listener::GetClass(),
136+
void_event_listener::GetMethodId(void_event_listener::kConstructor),
137+
reinterpret_cast<jlong>(listener));
138+
CheckAndClearJniExceptions(env);
139+
return result;
140+
}
141+
111142
/* static */
112143
bool EventListenerInternal::InitializeEmbeddedClasses(
113144
App* app, const std::vector<internal::EmbeddedFile>* embedded_files) {
@@ -123,6 +154,10 @@ bool EventListenerInternal::InitializeEmbeddedClasses(
123154
"FirebaseFirestoreException;)V",
124155
reinterpret_cast<void*>(
125156
&EventListenerInternal::QueryEventListenerNativeOnEvent)}};
157+
static const JNINativeMethod kVoidEventListenerNatives[] = {
158+
{"nativeOnEvent", "(J)V",
159+
reinterpret_cast<void*>(
160+
&EventListenerInternal::VoidEventListenerNativeOnEvent)}};
126161

127162
JNIEnv* env = app->GetJNIEnv();
128163
jobject activity = app->activity();
@@ -133,17 +168,22 @@ bool EventListenerInternal::InitializeEmbeddedClasses(
133168
embedded_files) &&
134169
query_event_listener::CacheClassFromFiles(env, activity,
135170
embedded_files) &&
171+
void_event_listener::CacheClassFromFiles(env, activity, embedded_files) &&
136172
// Cache method-ids
137173
cpp_event_listener::CacheMethodIds(env, activity) &&
138174
document_event_listener::CacheMethodIds(env, activity) &&
139175
query_event_listener::CacheMethodIds(env, activity) &&
176+
void_event_listener::CacheMethodIds(env, activity) &&
140177
// Register natives
141178
document_event_listener::RegisterNatives(
142179
env, kDocumentEventListenerNatives,
143180
FIREBASE_ARRAYSIZE(kDocumentEventListenerNatives)) &&
144181
query_event_listener::RegisterNatives(
145182
env, kQueryEventListenerNatives,
146-
FIREBASE_ARRAYSIZE(kQueryEventListenerNatives));
183+
FIREBASE_ARRAYSIZE(kQueryEventListenerNatives)) &&
184+
void_event_listener::RegisterNatives(
185+
env, kVoidEventListenerNatives,
186+
FIREBASE_ARRAYSIZE(kVoidEventListenerNatives));
147187
util::CheckAndClearJniExceptions(env);
148188
return result;
149189
}
@@ -155,6 +195,7 @@ void EventListenerInternal::Terminate(App* app) {
155195
cpp_event_listener::ReleaseClass(env);
156196
document_event_listener::ReleaseClass(env);
157197
query_event_listener::ReleaseClass(env);
198+
void_event_listener::ReleaseClass(env);
158199
util::CheckAndClearJniExceptions(env);
159200
}
160201

firestore/src/android/event_listener_android.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class EventListenerInternal {
2121
jlong firestore_ptr,
2222
jlong listener_ptr, jobject value,
2323
jobject error);
24+
static void VoidEventListenerNativeOnEvent(JNIEnv* env, jclass clazz,
25+
jlong listener_ptr);
2426

2527
static jobject EventListenerToJavaEventListener(
2628
JNIEnv* env, FirestoreInternal* firestore,
@@ -30,6 +32,9 @@ class EventListenerInternal {
3032
JNIEnv* env, FirestoreInternal* firestore,
3133
EventListener<QuerySnapshot>* listener);
3234

35+
static jobject EventListenerToJavaRunnable(JNIEnv* env,
36+
EventListener<void>* listener);
37+
3338
private:
3439
friend class FirestoreInternal;
3540

firestore/src/android/firestore_android.cc

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "firestore/src/android/firebase_firestore_exception_android.h"
2323
#include "firestore/src/android/firebase_firestore_settings_android.h"
2424
#include "firestore/src/android/geo_point_android.h"
25+
#include "firestore/src/android/lambda_event_listener.h"
2526
#include "firestore/src/android/lambda_transaction_function.h"
2627
#include "firestore/src/android/metadata_changes_android.h"
2728
#include "firestore/src/android/promise_android.h"
@@ -78,7 +79,11 @@ const char kApiIdentifier[] = "Firestore";
7879
X(WaitForPendingWrites, "waitForPendingWrites", \
7980
"()Lcom/google/android/gms/tasks/Task;"), \
8081
X(ClearPersistence, "clearPersistence", \
81-
"()Lcom/google/android/gms/tasks/Task;")
82+
"()Lcom/google/android/gms/tasks/Task;"), \
83+
X(AddSnapshotsInSyncListener, "addSnapshotsInSyncListener", \
84+
"(Ljava/lang/Runnable;)" \
85+
"Lcom/google/firebase/firestore/ListenerRegistration;")
86+
8287
// clang-format on
8388

8489
METHOD_LOOKUP_DECLARATION(firebase_firestore, FIREBASE_FIRESTORE_METHODS)
@@ -463,6 +468,41 @@ Future<void> FirestoreInternal::ClearPersistenceLastResult() {
463468
return LastResult(FirestoreFn::kClearPersistence);
464469
}
465470

471+
ListenerRegistration FirestoreInternal::AddSnapshotsInSyncListener(
472+
EventListener<void>* listener, bool passing_listener_ownership) {
473+
JNIEnv* env = app_->GetJNIEnv();
474+
475+
// Create listener.
476+
jobject java_runnable =
477+
EventListenerInternal::EventListenerToJavaRunnable(env, listener);
478+
479+
// Register listener.
480+
jobject java_registration = env->CallObjectMethod(
481+
obj_,
482+
firebase_firestore::GetMethodId(
483+
firebase_firestore::kAddSnapshotsInSyncListener),
484+
java_runnable);
485+
env->DeleteLocalRef(java_runnable);
486+
CheckAndClearJniExceptions(env);
487+
488+
// Wrapping
489+
ListenerRegistrationInternal* registration = new ListenerRegistrationInternal{
490+
this, listener, passing_listener_ownership, java_registration};
491+
env->DeleteLocalRef(java_registration);
492+
return ListenerRegistration{registration};
493+
}
494+
495+
#if defined(FIREBASE_USE_STD_FUNCTION)
496+
497+
ListenerRegistration FirestoreInternal::AddSnapshotsInSyncListener(
498+
std::function<void()> callback) {
499+
auto* listener = new LambdaEventListener<void>(firebase::Move(callback));
500+
return AddSnapshotsInSyncListener(listener,
501+
/*passing_listener_ownership=*/true);
502+
}
503+
504+
#endif // defined(FIREBASE_USE_STD_FUNCTION)
505+
466506
void FirestoreInternal::RegisterListenerRegistration(
467507
ListenerRegistrationInternal* registration) {
468508
MutexLock lock(listener_registration_mutex_);

firestore/src/android/firestore_android.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
#include <cstdint>
77
#include <unordered_set>
88

9+
#if defined(FIREBASE_USE_STD_FUNCTION)
10+
#include <functional>
11+
#endif
12+
913
#include "app/src/cleanup_notifier.h"
1014
#include "app/src/future_manager.h"
1115
#include "app/src/include/firebase/app.h"
@@ -106,6 +110,14 @@ class FirestoreInternal {
106110
Future<void> ClearPersistence();
107111
Future<void> ClearPersistenceLastResult();
108112

113+
ListenerRegistration AddSnapshotsInSyncListener(
114+
EventListener<void>* listener, bool passing_listener_ownership = false);
115+
116+
#if defined(FIREBASE_USE_STD_FUNCTION)
117+
ListenerRegistration AddSnapshotsInSyncListener(
118+
std::function<void()> callback);
119+
#endif // defined(FIREBASE_USE_STD_FUNCTION)
120+
109121
// Manages the ListenerRegistrationInternal objects.
110122
void RegisterListenerRegistration(ListenerRegistrationInternal* registration);
111123
void UnregisterListenerRegistration(

firestore/src/android/lambda_event_listener.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ template <typename T>
1919
class LambdaEventListener : public EventListener<T> {
2020
public:
2121
LambdaEventListener(std::function<void(const T&, Error)> callback)
22-
: callback_(firebase::Move(callback)) {}
22+
: callback_(firebase::Move(callback)) {
23+
FIREBASE_ASSERT(callback);
24+
}
2325

2426
void OnEvent(const T& value, Error error) override {
2527
callback_(value, error);
@@ -29,6 +31,20 @@ class LambdaEventListener : public EventListener<T> {
2931
std::function<void(const T&, Error)> callback_;
3032
};
3133

34+
template <>
35+
class LambdaEventListener<void> : public EventListener<void> {
36+
public:
37+
LambdaEventListener(std::function<void()> callback)
38+
: callback_(firebase::Move(callback)) {
39+
FIREBASE_ASSERT(callback);
40+
}
41+
42+
void OnEvent(Error) override { callback_(); }
43+
44+
private:
45+
std::function<void()> callback_;
46+
};
47+
3248
} // namespace firestore
3349
} // namespace firebase
3450

firestore/src/android/listener_registration_android.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ ListenerRegistrationInternal::ListenerRegistrationInternal(
4545
firestore->RegisterListenerRegistration(this);
4646
}
4747

48+
ListenerRegistrationInternal::ListenerRegistrationInternal(
49+
FirestoreInternal* firestore, EventListener<void>* event_listener,
50+
bool owning_event_listener, jobject listener_registration)
51+
: firestore_(firestore),
52+
listener_registration_(
53+
firestore->app()->GetJNIEnv()->NewGlobalRef(listener_registration)),
54+
void_event_listener_(event_listener),
55+
owning_event_listener_(owning_event_listener) {
56+
FIREBASE_ASSERT(firestore != nullptr);
57+
FIREBASE_ASSERT(event_listener != nullptr);
58+
FIREBASE_ASSERT(listener_registration != nullptr);
59+
60+
firestore->RegisterListenerRegistration(this);
61+
}
62+
4863
// Destruction only happens when FirestoreInternal de-allocate them.
4964
// FirestoreInternal will hold the lock and unregister all of them. So we do not
5065
// call UnregisterListenerRegistration explicitly here.
@@ -66,6 +81,7 @@ ListenerRegistrationInternal::~ListenerRegistrationInternal() {
6681
if (owning_event_listener_) {
6782
delete document_event_listener_;
6883
delete query_event_listener_;
84+
delete void_event_listener_;
6985
}
7086
}
7187

firestore/src/android/listener_registration_android.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ class ListenerRegistrationInternal {
3333
EventListener<QuerySnapshot>* event_listener,
3434
bool owning_event_listener,
3535
jobject listener_registration);
36+
ListenerRegistrationInternal(FirestoreInternal* firestore,
37+
EventListener<void>* event_listener,
38+
bool owning_event_listener,
39+
jobject listener_registration);
3640

3741
// Delete the default one to make the ownership more obvious i.e.
3842
// FirestoreInternal owns each instance and forbid anyone else to make copy.
@@ -66,6 +70,7 @@ class ListenerRegistrationInternal {
6670
// then the registration owns the LambdaEventListener that wraps the lambda.
6771
EventListener<DocumentSnapshot>* document_event_listener_ = nullptr;
6872
EventListener<QuerySnapshot>* query_event_listener_ = nullptr;
73+
EventListener<void>* void_event_listener_ = nullptr;
6974
bool owning_event_listener_;
7075
};
7176

firestore/src/common/firestore.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,5 +286,21 @@ Future<void> Firestore::ClearPersistenceLastResult() {
286286
return internal_->ClearPersistenceLastResult();
287287
}
288288

289+
#if !defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
290+
ListenerRegistration Firestore::AddSnapshotsInSyncListener(
291+
EventListener<void>* listener) {
292+
if (!internal_) return {};
293+
return internal_->AddSnapshotsInSyncListener(listener);
294+
}
295+
#endif // !defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
296+
297+
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
298+
ListenerRegistration Firestore::AddSnapshotsInSyncListener(
299+
std::function<void()> callback) {
300+
if (!internal_) return {};
301+
return internal_->AddSnapshotsInSyncListener(std::move(callback));
302+
}
303+
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
304+
289305
} // namespace firestore
290306
} // namespace firebase

firestore/src/include/firebase/firestore.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,50 @@ class Firestore {
337337
/** Gets the result of the most recent call to ClearPersistence(). */
338338
Future<void> ClearPersistenceLastResult();
339339

340+
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
341+
/**
342+
* Attaches a listener for a snapshots-in-sync event. Server-generated
343+
* updates and local changes can affect multiple snapshot listeners.
344+
* The snapshots-in-sync event indicates that all listeners affected by
345+
* a given change have fired.
346+
*
347+
* NOTE: The snapshots-in-sync event only indicates that listeners are
348+
* in sync with each other, but does not relate to whether those
349+
* snapshots are in sync with the server. Use `SnapshotMetadata` in the
350+
* individual listeners to determine if a snapshot is from the cache or
351+
* the server.
352+
*
353+
* @param callback A callback to be called every time all snapshot
354+
* listeners are in sync with each other.
355+
* @return A `ListenerRegistration` object that can be used to remove the
356+
* listener.
357+
*/
358+
virtual ListenerRegistration AddSnapshotsInSyncListener(
359+
std::function<void()> callback);
360+
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
361+
362+
#if !defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
363+
/**
364+
* Attaches a listener for a snapshots-in-sync event. Server-generated
365+
* updates and local changes can affect multiple snapshot listeners.
366+
* The snapshots-in-sync event indicates that all listeners affected by
367+
* a given change have fired.
368+
*
369+
* NOTE: The snapshots-in-sync event only indicates that listeners are
370+
* in sync with each other, but does not relate to whether those
371+
* snapshots are in sync with the server. Use `SnapshotMetadata` in the
372+
* individual listeners to determine if a snapshot is from the cache or
373+
* the server.
374+
*
375+
* @param listener A callback to be called every time all snapshot
376+
* listeners are in sync with each other.
377+
* @return A `ListenerRegistration` object that can be used to remove the
378+
* listener.
379+
*/
380+
virtual ListenerRegistration AddSnapshotsInSyncListener(
381+
EventListener<void>* listener);
382+
#endif // !defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
383+
340384
protected:
341385
/**
342386
* Default constructor, to be used only for mocking `Firestore`.

firestore/src/include/firebase/firestore/event_listener.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ class EventListener {
4040
virtual void OnEvent(const T& value, Error error) = 0;
4141
};
4242

43+
template <>
44+
class EventListener<void> {
45+
public:
46+
virtual ~EventListener() = default;
47+
virtual void OnEvent(Error error) = 0;
48+
};
49+
4350
} // namespace firestore
4451
} // namespace firebase
4552

0 commit comments

Comments
 (0)