Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
47 changes: 47 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,32 @@ 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 {
if (!serialized_registration_received) return;
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 {
if (!serialized_unregistration_received) return;
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