Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions messaging/integration_test/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@
</intent-filter>
</activity>
<meta-data android:name="com.google.test.loops" android:value="1" />
<!-- Enables the newer Registration method that uses Installation IDs -->
<meta-data android:name="firebase_messaging_installation_id_enabled" android:value="true" />

<service android:name="com.google.firebase.messaging.cpp.ListenerService"
android:exported="true" >
Expand Down
2 changes: 2 additions & 0 deletions messaging/integration_test/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,7 @@
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>FirebaseMessagingInstallationIdEnabled</key>
<true/>
</dict>
</plist>
50 changes: 49 additions & 1 deletion messaging/integration_test/src/integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ class FirebaseMessagingTest : public FirebaseTest {
static firebase::messaging::PollableListener* shared_listener_;
static std::string* shared_token_;
static bool is_desktop_stub_;
// Used to track if the newer registration method is being used.
static bool is_new_registration_id_;

static firebase::functions::Functions* functions_;
};
Expand All @@ -138,6 +140,7 @@ firebase::App* FirebaseMessagingTest::shared_app_ = nullptr;
firebase::messaging::PollableListener* FirebaseMessagingTest::shared_listener_ =
nullptr;
bool FirebaseMessagingTest::is_desktop_stub_;
bool FirebaseMessagingTest::is_new_registration_id_ = false;
firebase::functions::Functions* FirebaseMessagingTest::functions_ = nullptr;

void FirebaseMessagingTest::SetUpTestSuite() {
Expand Down Expand Up @@ -287,7 +290,16 @@ bool FirebaseMessagingTest::WaitForToken(int timeout) {
if (shared_listener_->PollRegistrationToken(&new_token)) {
if (!new_token.empty()) {
*shared_token_ = new_token;
LogInfo("Got token: %s", shared_token_->c_str());
is_new_registration_id_ = false;
LogInfo("Got FCM Token: %s", shared_token_->c_str());
return true;
}
}
if (shared_listener_->PollRegistration(&new_token)) {
if (!new_token.empty()) {
*shared_token_ = new_token;
is_new_registration_id_ = true;
LogInfo("Got FIS: %s", shared_token_->c_str());
return true;
}
}
Expand Down Expand Up @@ -535,4 +547,40 @@ TEST_F(FirebaseMessagingTest, DeliverMetricsToBigQuery) {
#endif
}

TEST_F(FirebaseMessagingTest, TestRegistrationOnInitEnabled) {
bool initial_val = firebase::messaging::IsRegistrationOnInitEnabled();
EXPECT_TRUE(initial_val);

firebase::messaging::SetRegistrationOnInitEnabled(false);
EXPECT_FALSE(firebase::messaging::IsRegistrationOnInitEnabled());

firebase::messaging::SetRegistrationOnInitEnabled(true);
EXPECT_TRUE(firebase::messaging::IsRegistrationOnInitEnabled());
}

TEST_F(FirebaseMessagingTest, TestRegisterAndUnregister) {
TEST_REQUIRES_USER_INTERACTION_ON_IOS;
EXPECT_TRUE(RequestPermission());

// Note that these methods should only work if the newer registration
// method is enabled. Otherwise, it returns an error.
if (is_new_registration_id_) {
firebase::Future<void> reg_future = firebase::messaging::Register();
EXPECT_TRUE(WaitForCompletion(reg_future, "Register"));
EXPECT_EQ(reg_future.error(), 0);

firebase::Future<void> unreg_future = firebase::messaging::Unregister();
EXPECT_TRUE(WaitForCompletion(unreg_future, "Unregister"));
EXPECT_EQ(unreg_future.error(), 0);
} else {
firebase::Future<void> reg_future = firebase::messaging::Register();
EXPECT_TRUE(WaitForCompletion(reg_future, "Register",
{firebase::messaging::kErrorUnknown}));

firebase::Future<void> unreg_future = firebase::messaging::Unregister();
EXPECT_TRUE(WaitForCompletion(unreg_future, "Unregister",
{firebase::messaging::kErrorUnknown}));
}
}

} // namespace firebase_testapp_automated
45 changes: 45 additions & 0 deletions messaging/src/android/cpp/message_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,17 @@ using com::google::firebase::messaging::cpp::SerializedEvent;
using com::google::firebase::messaging::cpp::SerializedEventUnion;
using com::google::firebase::messaging::cpp::
SerializedEventUnion_SerializedMessage;
using com::google::firebase::messaging::cpp::
SerializedEventUnion_SerializedRegistrationReceived;
using com::google::firebase::messaging::cpp::
SerializedEventUnion_SerializedTokenReceived;
using com::google::firebase::messaging::cpp::
SerializedEventUnion_SerializedUnregistrationReceived;
using com::google::firebase::messaging::cpp::SerializedMessage;
using com::google::firebase::messaging::cpp::SerializedNotification;
using com::google::firebase::messaging::cpp::SerializedRegistrationReceived;
using com::google::firebase::messaging::cpp::SerializedTokenReceived;
using com::google::firebase::messaging::cpp::SerializedUnregistrationReceived;
using com::google::firebase::messaging::cpp::VerifySerializedEventBuffer;

static const char kMessageReadError[] =
Expand Down Expand Up @@ -96,6 +102,21 @@ void MessageReader::ReadFromBuffer(const std::string& buffer) const {
ConsumeTokenReceived(serialized_token_received);
break;
}
case SerializedEventUnion_SerializedRegistrationReceived: {
const SerializedRegistrationReceived* serialized_registration_received =
static_cast<const SerializedRegistrationReceived*>(
serialized_event->event());
ConsumeRegistrationReceived(serialized_registration_received);
break;
}
case SerializedEventUnion_SerializedUnregistrationReceived: {
const SerializedUnregistrationReceived*
serialized_unregistration_received =
static_cast<const SerializedUnregistrationReceived*>(
serialized_event->event());
ConsumeUnregistrationReceived(serialized_unregistration_received);
break;
}
default: {
// This should never happen.
LogError(kMessageReadError, "Detected invalid FCM event type.");
Expand Down Expand Up @@ -205,6 +226,30 @@ void MessageReader::ConsumeTokenReceived(
token_callback_(token, token_callback_data_);
}

// Convert the SerializedRegistrationReceived to an installation ID and calls
// the registered callback.
void MessageReader::ConsumeRegistrationReceived(
const SerializedRegistrationReceived* serialized_registration_received)
const {
const char* installation_id =
SafeFlatbufferString(serialized_registration_received->installation_id());
if (registration_callback_) {
registration_callback_(installation_id, registration_callback_data_);
}
}
Comment thread
a-maurice marked this conversation as resolved.

// Convert the SerializedUnregistrationReceived to an installation ID and calls
// the registered callback.
void MessageReader::ConsumeUnregistrationReceived(
const SerializedUnregistrationReceived* serialized_unregistration_received)
const {
const char* installation_id = SafeFlatbufferString(
serialized_unregistration_received->installation_id());
if (unregistration_callback_) {
unregistration_callback_(installation_id, unregistration_callback_data_);
}
}
Comment thread
a-maurice marked this conversation as resolved.

} // namespace internal
} // namespace messaging
} // namespace firebase
38 changes: 36 additions & 2 deletions messaging/src/android/cpp/message_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,29 @@ class MessageReader {
// Notify the currently set listener of a new token.
typedef void (*TokenCallback)(const char* token, void* callback_data);

// Notify the currently set listener of a new registration installation ID.
typedef void (*RegistrationCallback)(const char* installationId,
void* callback_data);

// Notify the currently set listener of an unregistration installation ID.
typedef void (*UnregistrationCallback)(const char* installationId,
void* callback_data);

// Construct a reader with message and token callbacks.
MessageReader(MessageCallback message_callback, void* message_callback_data,
TokenCallback token_callback, void* token_callback_data)
TokenCallback token_callback, void* token_callback_data,
RegistrationCallback registration_callback = nullptr,
void* registration_callback_data = nullptr,
UnregistrationCallback unregistration_callback = nullptr,
void* unregistration_callback_data = nullptr)
: message_callback_(message_callback),
message_callback_data_(message_callback_data),
token_callback_(token_callback),
token_callback_data_(token_callback_data) {}
token_callback_data_(token_callback_data),
registration_callback_(registration_callback),
registration_callback_data_(registration_callback_data),
unregistration_callback_(unregistration_callback),
unregistration_callback_data_(unregistration_callback_data) {}

// Read messages or tokens from a buffer, calling message_callback and
// token_callback (set on construction) on each message or token respectively.
Expand All @@ -59,6 +75,20 @@ class MessageReader {
const com::google::firebase::messaging::cpp::SerializedTokenReceived*
serialized_token_received) const;

// Convert the SerializedRegistrationReceived to an installation ID and calls
// the registered registration_callback.
void ConsumeRegistrationReceived(
const com::google::firebase::messaging::cpp::
SerializedRegistrationReceived* serialized_registration_received)
const;

// Convert the SerializedUnregistrationReceived to an installation ID and
// calls the registered unregistration_callback.
void ConsumeUnregistrationReceived(
const com::google::firebase::messaging::cpp::
SerializedUnregistrationReceived* serialized_unregistration_received)
const;

// Get the message callback function.
MessageCallback message_callback() const { return message_callback_; }

Expand All @@ -81,6 +111,10 @@ class MessageReader {
void* message_callback_data_;
TokenCallback token_callback_;
void* token_callback_data_;
RegistrationCallback registration_callback_;
void* registration_callback_data_;
UnregistrationCallback unregistration_callback_;
void* unregistration_callback_data_;
};

} // namespace internal
Expand Down
91 changes: 90 additions & 1 deletion messaging/src/android/cpp/messaging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ static bool g_intent_message_fired = false;
X(SetDeliveryMetricsExportToBigQuery, \
"setDeliveryMetricsExportToBigQuery", "(Z)V"), \
X(GetToken, "getToken", "()Lcom/google/android/gms/tasks/Task;"), \
X(DeleteToken, "deleteToken", "()Lcom/google/android/gms/tasks/Task;")
X(DeleteToken, "deleteToken", "()Lcom/google/android/gms/tasks/Task;"), \
X(Register, "register", "()Lcom/google/android/gms/tasks/Task;"), \
X(Unregister, "unregister", "()Lcom/google/android/gms/tasks/Task;")
// clang-format on
METHOD_LOOKUP_DECLARATION(firebase_messaging, FIREBASE_MESSAGING_METHODS);
METHOD_LOOKUP_DEFINITION(firebase_messaging,
Expand Down Expand Up @@ -289,6 +291,19 @@ static void ConsumeEvents() {
}
NotifyListenerOnTokenReceived(token);
},
nullptr,
[](const char* installationId, void* callback_data) {
if (g_registration_token_mutex) {
MutexLock lock(*g_registration_token_mutex);
g_registration_token_received = true;
HandlePendingSubscriptions();
}
NotifyListenerOnRegistrationReceived(installationId);
},
nullptr,
[](const char* installationId, void* callback_data) {
NotifyListenerOnUnregistrationReceived(installationId);
},
nullptr);
reader.ReadFromBuffer(buffer);
}
Expand Down Expand Up @@ -975,6 +990,14 @@ void SetDeliveryMetricsExportToBigQuery(bool enabled) {
}
}

void SetRegistrationOnInitEnabled(bool enabled) {
SetTokenRegistrationOnInitEnabled(enabled);
}

bool IsRegistrationOnInitEnabled() {
return IsTokenRegistrationOnInitEnabled();
}

void SetTokenRegistrationOnInitEnabled(bool enabled) {
// If this is called before JNI is initialized, we'll just cache the intent
// and handle it on actual init.
Expand Down Expand Up @@ -1018,6 +1041,72 @@ bool IsTokenRegistrationOnInitEnabled() {
return static_cast<bool>(result);
}

Future<void> Register() {
FIREBASE_ASSERT_MESSAGE_RETURN(Future<void>(), internal::IsInitialized(),
kMessagingNotInitializedError);
MutexLock lock(*g_registration_token_mutex);
ReferenceCountedFutureImpl* api = FutureData::Get()->api();
SafeFutureHandle<void> handle = api->SafeAlloc<void>(kMessagingFnRegister);

JNIEnv* env = g_app->GetJNIEnv();
jobject task = env->CallObjectMethod(
g_firebase_messaging,
firebase_messaging::GetMethodId(firebase_messaging::kRegister));

std::string error = util::GetAndClearExceptionMessage(env);
if (error.empty()) {
util::RegisterCallbackOnTask(env, task, CompleteVoidCallback,
reinterpret_cast<void*>(handle.get().id()),
kApiIdentifier);
} else {
api->Complete(handle, -1, error.c_str());
}
env->DeleteLocalRef(task);
util::CheckAndClearJniExceptions(env);

return MakeFuture(api, handle);
}

Future<void> RegisterLastResult() {
FIREBASE_ASSERT_RETURN(Future<void>(), internal::IsInitialized());
ReferenceCountedFutureImpl* api = FutureData::Get()->api();
return static_cast<const Future<void>&>(
api->LastResult(kMessagingFnRegister));
}

Future<void> Unregister() {
FIREBASE_ASSERT_MESSAGE_RETURN(Future<void>(), internal::IsInitialized(),
kMessagingNotInitializedError);
MutexLock lock(*g_registration_token_mutex);
ReferenceCountedFutureImpl* api = FutureData::Get()->api();
SafeFutureHandle<void> handle = api->SafeAlloc<void>(kMessagingFnUnregister);

JNIEnv* env = g_app->GetJNIEnv();
jobject task = env->CallObjectMethod(
g_firebase_messaging,
firebase_messaging::GetMethodId(firebase_messaging::kUnregister));

std::string error = util::GetAndClearExceptionMessage(env);
if (error.empty()) {
util::RegisterCallbackOnTask(env, task, CompleteVoidCallback,
reinterpret_cast<void*>(handle.get().id()),
kApiIdentifier);
} else {
api->Complete(handle, -1, error.c_str());
}
env->DeleteLocalRef(task);
util::CheckAndClearJniExceptions(env);

return MakeFuture(api, handle);
}

Future<void> UnregisterLastResult() {
FIREBASE_ASSERT_RETURN(Future<void>(), internal::IsInitialized());
ReferenceCountedFutureImpl* api = FutureData::Get()->api();
return static_cast<const Future<void>&>(
api->LastResult(kMessagingFnUnregister));
}

Future<std::string> GetToken() {
FIREBASE_ASSERT_MESSAGE_RETURN(Future<std::string>(),
internal::IsInitialized(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,16 @@ public void onNewToken(String token) {
DebugLogging.log(TAG, String.format("onNewToken token=%s", token));
RegistrationIntentService.writeTokenToInternalStorage(this, token);
}

@Override
public void onRegistered(String installationId) {
DebugLogging.log(TAG, String.format("onRegistered installationId=%s", installationId));
RegistrationIntentService.writeRegistrationToInternalStorage(this, installationId);
}

@Override
public void onUnregistered(String installationId) {
DebugLogging.log(TAG, String.format("onUnregistered installationId=%s", installationId));
RegistrationIntentService.writeUnregistrationToInternalStorage(this, installationId);
}
}
Loading
Loading