Skip to content

Commit b09efc2

Browse files
committed
Merge remote-tracking branch 'origin/master' into ghm
2 parents b1ba676 + 2026f49 commit b09efc2

34 files changed

+2420
-147
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ option(FIREBASE_INCLUDE_FIRESTORE
4545
option(FIREBASE_INCLUDE_FUNCTIONS
4646
"Include the Cloud Functions for Firebase library."
4747
${FIREBASE_INCLUDE_LIBRARY_DEFAULT})
48+
option(FIREBASE_INCLUDE_INSTALLATIONS
49+
"Include the Firebase Installations library."
50+
${FIREBASE_INCLUDE_LIBRARY_DEFAULT})
4851
option(FIREBASE_INCLUDE_INSTANCE_ID
4952
"Include the Firebase Instance ID library."
5053
${FIREBASE_INCLUDE_LIBRARY_DEFAULT})
@@ -428,6 +431,9 @@ endif()
428431
if (FIREBASE_INCLUDE_FUNCTIONS)
429432
add_subdirectory(functions)
430433
endif()
434+
if (FIREBASE_INCLUDE_INSTALLATIONS)
435+
add_subdirectory(installations)
436+
endif()
431437
if (FIREBASE_INCLUDE_INSTANCE_ID)
432438
add_subdirectory(instance_id)
433439
endif()

firestore/src/android/document_snapshot_android.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ MapFieldValue DocumentSnapshotInternal::GetData(
8585
Env env = GetEnv();
8686
Local<Object> java_stb = ServerTimestampBehaviorInternal::Create(env, stb);
8787
Local<Object> java_data = env.Call(obj_, kGetData, java_stb);
88+
89+
if (!java_data) {
90+
// If the document doesn't exist, Android returns a null Map. In C++, the
91+
// map is returned by value, so translate this case to an empty map.
92+
return MapFieldValue();
93+
}
94+
8895
return FieldValueInternal(java_data).map_value();
8996
}
9097

firestore/src/android/firestore_android.cc

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "firestore/src/android/lambda_transaction_function.h"
2626
#include "firestore/src/android/listener_registration_android.h"
2727
#include "firestore/src/android/metadata_changes_android.h"
28-
#include "firestore/src/android/promise_android.h"
28+
#include "firestore/src/android/promise_factory_android.h"
2929
#include "firestore/src/android/query_android.h"
3030
#include "firestore/src/android/query_snapshot_android.h"
3131
#include "firestore/src/android/server_timestamp_behavior_android.h"
@@ -213,7 +213,7 @@ FirestoreInternal::FirestoreInternal(App* app) {
213213
FIREBASE_ASSERT(java_user_callback_executor.get() != nullptr);
214214
user_callback_executor_ = java_user_callback_executor;
215215

216-
future_manager_.AllocFutureApi(this, static_cast<int>(AsyncFn::kCount));
216+
promises_ = MakeUnique<PromiseFactory<AsyncFn>>(this);
217217
}
218218

219219
/* static */
@@ -314,7 +314,7 @@ FirestoreInternal::~FirestoreInternal() {
314314
Env env = GetEnv();
315315
ShutdownUserCallbackExecutor(env);
316316

317-
future_manager_.ReleaseFutureApi(this);
317+
promises_.reset(nullptr);
318318

319319
java_firestores_->Remove(env, obj_);
320320

@@ -378,13 +378,11 @@ Future<void> FirestoreInternal::RunTransaction(TransactionFunction* update,
378378
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
379379
auto* completion =
380380
static_cast<LambdaTransactionFunction*>(is_lambda ? update : nullptr);
381-
Promise<void, void, AsyncFn> promise(ref_future(), this, completion);
381+
return promises_->NewFuture<void>(env, AsyncFn::kRunTransaction, task,
382+
completion);
382383
#else // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
383-
Promise<void, void, AsyncFn> promise(ref_future(), this);
384+
return promises_->NewFuture<void>(env, AsyncFn::kRunTransaction, task);
384385
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
385-
386-
promise.RegisterForTask(env, AsyncFn::kRunTransaction, task);
387-
return promise.GetFuture();
388386
}
389387

390388
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
@@ -398,31 +396,31 @@ Future<void> FirestoreInternal::RunTransaction(
398396
Future<void> FirestoreInternal::DisableNetwork() {
399397
Env env = GetEnv();
400398
Local<Object> task = env.Call(obj_, kDisableNetwork);
401-
return NewFuture(env, AsyncFn::kDisableNetwork, task);
399+
return promises_->NewFuture<void>(env, AsyncFn::kDisableNetwork, task);
402400
}
403401

404402
Future<void> FirestoreInternal::EnableNetwork() {
405403
Env env = GetEnv();
406404
Local<Object> task = env.Call(obj_, kEnableNetwork);
407-
return NewFuture(env, AsyncFn::kEnableNetwork, task);
405+
return promises_->NewFuture<void>(env, AsyncFn::kEnableNetwork, task);
408406
}
409407

410408
Future<void> FirestoreInternal::Terminate() {
411409
Env env = GetEnv();
412410
Local<Object> task = env.Call(obj_, kTerminate);
413-
return NewFuture(env, AsyncFn::kTerminate, task);
411+
return promises_->NewFuture<void>(env, AsyncFn::kTerminate, task);
414412
}
415413

416414
Future<void> FirestoreInternal::WaitForPendingWrites() {
417415
Env env = GetEnv();
418416
Local<Object> task = env.Call(obj_, kWaitForPendingWrites);
419-
return NewFuture(env, AsyncFn::kWaitForPendingWrites, task);
417+
return promises_->NewFuture<void>(env, AsyncFn::kWaitForPendingWrites, task);
420418
}
421419

422420
Future<void> FirestoreInternal::ClearPersistence() {
423421
Env env = GetEnv();
424422
Local<Object> task = env.Call(obj_, kClearPersistence);
425-
return NewFuture(env, AsyncFn::kClearPersistence, task);
423+
return promises_->NewFuture<void>(env, AsyncFn::kClearPersistence, task);
426424
}
427425

428426
ListenerRegistration FirestoreInternal::AddSnapshotsInSyncListener(

firestore/src/android/firestore_android.h

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <functional>
99
#endif
1010

11+
#include "app/memory/unique_ptr.h"
1112
#include "app/src/cleanup_notifier.h"
1213
#include "app/src/future_manager.h"
1314
#include "app/src/include/firebase/app.h"
@@ -29,8 +30,8 @@ class Transaction;
2930
class TransactionFunction;
3031
class WriteBatch;
3132

32-
template <typename PublicType, typename InternalType, typename FnEnumType>
33-
class Promise;
33+
template <typename EnumT>
34+
class PromiseFactory;
3435

3536
// Used for registering global callbacks. See
3637
// firebase::util::RegisterCallbackOnTask for context.
@@ -154,27 +155,12 @@ class FirestoreInternal {
154155
static void SetClientLanguage(const std::string& language_token);
155156

156157
private:
157-
// Gets the reference-counted Future implementation of this instance, which
158-
// can be used to create a Future.
159-
ReferenceCountedFutureImpl* ref_future() {
160-
return future_manager_.GetFutureApi(this);
161-
}
158+
friend class FirestoreIntegrationTest;
162159

163160
FirestoreInternal* mutable_this() const {
164161
return const_cast<FirestoreInternal*>(this);
165162
}
166163

167-
template <typename PublicT = void, typename InternalT = InternalType<PublicT>>
168-
Future<PublicT> NewFuture(jni::Env& env, AsyncFn op,
169-
const jni::Object& task) const {
170-
if (!env.ok()) return {};
171-
172-
FirestoreInternal* self = mutable_this();
173-
Promise<PublicT, InternalT, AsyncFn> promise(self->ref_future(), self);
174-
promise.RegisterForTask(env, op, task);
175-
return promise.GetFuture();
176-
}
177-
178164
void ShutdownUserCallbackExecutor(jni::Env& env);
179165

180166
static bool Initialize(App* app);
@@ -211,6 +197,7 @@ class FirestoreInternal {
211197
#endif // defined(_STLPORT_VERSION)
212198

213199
FutureManager future_manager_;
200+
UniquePtr<PromiseFactory<AsyncFn>> promises_;
214201

215202
CleanupNotifier cleanup_;
216203
};

firestore/src/android/lambda_transaction_function.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace firestore {
2525
*/
2626
class LambdaTransactionFunction
2727
: public TransactionFunction,
28-
public Promise<void, void, FirestoreInternal::AsyncFn>::Completion<void> {
28+
public Promise<void, void, FirestoreInternal::AsyncFn>::Completion {
2929
public:
3030
LambdaTransactionFunction(
3131
std::function<Error(Transaction&, std::string&)> update)

firestore/src/android/promise_android.h

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
namespace firebase {
1818
namespace firestore {
1919

20+
template <typename EnumT>
21+
class PromiseFactory;
22+
2023
// This class simplifies the implementation of Future APIs for Android wrappers.
2124
// PublicType is the public type, say Foo, and InternalType is FooInternal.
2225
// FnEnumType is an enum class that defines a set of APIs returning a Future.
@@ -29,25 +32,20 @@ namespace firestore {
2932
// and FnEnumType is CollectionReferenceFn.
3033
template <typename PublicType, typename InternalType, typename FnEnumType>
3134
class Promise {
35+
friend class PromiseFactory<FnEnumType>;
36+
3237
public:
3338
// One can add a completion to execute right after the Future is resolved.
3439
// The Games's Future library does not support chaining-up of completions yet.
3540
// So we add the interface here to allow executing code after Future is
3641
// resolved.
37-
template <typename PublicT>
3842
class Completion {
3943
public:
4044
virtual ~Completion() = default;
4145
virtual void CompleteWith(Error error_code, const char* error_message,
42-
PublicT* result) = 0;
46+
PublicType* result) = 0;
4347
};
4448

45-
Promise(ReferenceCountedFutureImpl* impl, FirestoreInternal* firestore,
46-
Completion<PublicType>* completion = nullptr)
47-
: completer_(MakeUnique<Completer<PublicType, InternalType>>(
48-
impl, firestore, completion)),
49-
impl_(impl) {}
50-
5149
~Promise() {}
5250

5351
Promise(const Promise&) = delete;
@@ -56,10 +54,6 @@ class Promise {
5654
Promise(Promise&& other) = default;
5755
Promise& operator=(Promise&& other) = default;
5856

59-
void RegisterForTask(FnEnumType op, const jni::Object& task) {
60-
return RegisterForTask(op, task.get());
61-
}
62-
6357
void RegisterForTask(jni::Env& env, FnEnumType op, const jni::Object& task) {
6458
handle_ = completer_->Alloc(static_cast<int>(op));
6559

@@ -73,11 +67,19 @@ class Promise {
7367
Future<PublicType> GetFuture() { return MakeFuture(impl_, handle_); }
7468

7569
private:
70+
// The constructor is intentionally private.
71+
// Create instances with `PromiseFactory`.
72+
Promise(ReferenceCountedFutureImpl* impl, FirestoreInternal* firestore,
73+
Completion* completion)
74+
: completer_(MakeUnique<Completer<PublicType, InternalType>>(
75+
impl, firestore, completion)),
76+
impl_(impl) {}
77+
7678
template <typename PublicT>
7779
class CompleterBase {
7880
public:
7981
CompleterBase(ReferenceCountedFutureImpl* impl,
80-
FirestoreInternal* firestore, Completion<PublicT>* completion)
82+
FirestoreInternal* firestore, Completion* completion)
8183
: impl_{impl}, firestore_{firestore}, completion_(completion) {}
8284

8385
virtual ~CompleterBase() = default;
@@ -131,7 +133,7 @@ class Promise {
131133
SafeFutureHandle<PublicT> handle_;
132134
ReferenceCountedFutureImpl* impl_; // not owning
133135
FirestoreInternal* firestore_; // not owning
134-
Completion<PublicType>* completion_; // not owning
136+
Completion* completion_; // not owning
135137
};
136138

137139
// Partial specialization of a nested class is allowed. So adding the no-op
@@ -143,7 +145,8 @@ class Promise {
143145
using CompleterBase<PublicT>::CompleterBase;
144146

145147
void SucceedWithResult(jni::Env& env, const jni::Object& result) override {
146-
auto future_result = MakePublic<PublicT>(env, this->firestore_, result);
148+
auto future_result =
149+
MakePublic<PublicT, InternalT>(env, this->firestore_, result);
147150

148151
this->impl_->CompleteWithResult(this->handle_, Error::kErrorOk,
149152
/*error_msg=*/"", future_result);

firestore/src/android/promise_factory_android.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,21 @@ class PromiseFactory {
3636
// This can be used to implement APIs that return Futures of some public type.
3737
// Use MakePromise<void, void>() to create a Future<void>.
3838
template <typename PublicT, typename InternalT = InternalType<PublicT>>
39-
Promise<PublicT, InternalT, EnumT> MakePromise() {
40-
return Promise<PublicT, InternalT, EnumT>{future_api(), firestore_};
39+
Promise<PublicT, InternalT, EnumT> MakePromise(
40+
typename Promise<PublicT, InternalT, EnumT>::Completion* completion =
41+
nullptr) {
42+
return Promise<PublicT, InternalT, EnumT>{future_api(), firestore_,
43+
completion};
4144
}
4245

4346
template <typename PublicT, typename InternalT = InternalType<PublicT>>
44-
Future<PublicT> NewFuture(jni::Env& env, EnumT op, const jni::Object& task) {
47+
Future<PublicT> NewFuture(
48+
jni::Env& env, EnumT op, const jni::Object& task,
49+
typename Promise<PublicT, InternalT, EnumT>::Completion* completion =
50+
nullptr) {
4551
if (!env.ok()) return {};
4652

47-
auto promise = MakePromise<PublicT, InternalT>();
53+
auto promise = MakePromise<PublicT, InternalT>(completion);
4854
promise.RegisterForTask(env, op, task);
4955
return promise.GetFuture();
5056
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#include "firestore/src/tests/android/cancellation_token_source.h"
2+
3+
#include "firestore/src/jni/env.h"
4+
#include "firestore/src/jni/loader.h"
5+
6+
namespace firebase {
7+
namespace firestore {
8+
namespace {
9+
10+
using jni::Constructor;
11+
using jni::Env;
12+
using jni::Local;
13+
using jni::Method;
14+
using jni::Object;
15+
16+
constexpr char kClassName[] =
17+
PROGUARD_KEEP_CLASS "com/google/android/gms/tasks/CancellationTokenSource";
18+
Constructor<CancellationTokenSource> kConstructor("()V");
19+
Method<Object> kGetToken("getToken",
20+
"()Lcom/google/android/gms/tasks/CancellationToken;");
21+
Method<void> kCancel("cancel", "()V");
22+
23+
} // namespace
24+
25+
void CancellationTokenSource::Initialize(jni::Loader& loader) {
26+
loader.LoadClass(kClassName, kConstructor, kGetToken, kCancel);
27+
}
28+
29+
Local<CancellationTokenSource> CancellationTokenSource::Create(Env& env) {
30+
return env.New(kConstructor);
31+
}
32+
33+
Local<Object> CancellationTokenSource::GetToken(Env& env) {
34+
return env.Call(*this, kGetToken);
35+
}
36+
37+
void CancellationTokenSource::Cancel(Env& env) { env.Call(*this, kCancel); }
38+
39+
} // namespace firestore
40+
} // namespace firebase
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#ifndef FIREBASE_FIRESTORE_CLIENT_CPP_SRC_TESTS_ANDROID_CANCELLATION_TOKEN_SOURCE_H_
2+
#define FIREBASE_FIRESTORE_CLIENT_CPP_SRC_TESTS_ANDROID_CANCELLATION_TOKEN_SOURCE_H_
3+
4+
#include "firestore/src/jni/jni_fwd.h"
5+
#include "firestore/src/jni/object.h"
6+
7+
namespace firebase {
8+
namespace firestore {
9+
10+
/** A C++ proxy for a Java `CancellationTokenSource` from the Tasks API. */
11+
class CancellationTokenSource : public jni::Object {
12+
public:
13+
using jni::Object::Object;
14+
15+
static void Initialize(jni::Loader& loader);
16+
17+
/** Creates a C++ proxy for a Java `CancellationTokenSource` object. */
18+
static jni::Local<CancellationTokenSource> Create(jni::Env& env);
19+
20+
/**
21+
* Invokes `getToken()` on the wrapped Java `CancellationTokenSource` object.
22+
*/
23+
jni::Local<Object> GetToken(jni::Env& env);
24+
25+
/**
26+
* Invokes `cancel()` on the wrapped Java `CancellationTokenSource` object.
27+
*/
28+
void Cancel(jni::Env& env);
29+
};
30+
31+
} // namespace firestore
32+
} // namespace firebase
33+
34+
#endif // FIREBASE_FIRESTORE_CLIENT_CPP_SRC_TESTS_ANDROID_CANCELLATION_TOKEN_SOURCE_H_

0 commit comments

Comments
 (0)