Skip to content

Add interfaces for FirebaseMessaging to use DI and mocking in the real projects #333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
202 changes: 15 additions & 187 deletions FirebaseAdmin/FirebaseAdmin/Messaging/FirebaseMessaging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace FirebaseAdmin.Messaging
/// This is the entry point to all server-side Firebase Cloud Messaging (FCM) operations. You
/// can get an instance of this class via <c>FirebaseMessaging.DefaultInstance</c>.
/// </summary>
public sealed class FirebaseMessaging : IFirebaseService
public sealed class FirebaseMessaging : IFirebaseService, IFirebaseMessageSender, IFirebaseMessageSubscriber
{
private readonly FirebaseMessagingClient messagingClient;
private readonly InstanceIdClient instanceIdClient;
Expand Down Expand Up @@ -72,247 +72,85 @@ public static FirebaseMessaging GetMessaging(FirebaseApp app)
});
}

/// <summary>
/// Sends a message to the FCM service for delivery. The message gets validated both by
/// the Admin SDK, and the remote FCM service. A successful return value indicates
/// that the message has been successfully sent to FCM, where it has been accepted by the
/// FCM service.
/// </summary>
/// <returns>A task that completes with a message ID string, which represents
/// successful handoff to FCM.</returns>
/// <exception cref="ArgumentNullException">If the message argument is null.</exception>
/// <exception cref="ArgumentException">If the message contains any invalid
/// fields.</exception>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// message.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <inheritdoc />
public async Task<string> SendAsync(Message message)
{
return await this.SendAsync(message, false)
.ConfigureAwait(false);
}

/// <summary>
/// Sends a message to the FCM service for delivery. The message gets validated both by
/// the Admin SDK, and the remote FCM service. A successful return value indicates
/// that the message has been successfully sent to FCM, where it has been accepted by the
/// FCM service.
/// </summary>
/// <returns>A task that completes with a message ID string, which represents
/// successful handoff to FCM.</returns>
/// <exception cref="ArgumentNullException">If the message argument is null.</exception>
/// <exception cref="ArgumentException">If the message contains any invalid
/// fields.</exception>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// message.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <inheritdoc />
public async Task<string> SendAsync(Message message, CancellationToken cancellationToken)
{
return await this.SendAsync(message, false, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Sends a message to the FCM service for delivery. The message gets validated both by
/// the Admin SDK, and the remote FCM service. A successful return value indicates
/// that the message has been successfully sent to FCM, where it has been accepted by the
/// FCM service.
/// <para>If the <paramref name="dryRun"/> option is set to true, the message will not be
/// actually sent to the recipients. Instead, the FCM service performs all the necessary
/// validations, and emulates the send operation. This is a good way to check if a
/// certain message will be accepted by FCM for delivery.</para>
/// </summary>
/// <returns>A task that completes with a message ID string, which represents
/// successful handoff to FCM.</returns>
/// <exception cref="ArgumentNullException">If the message argument is null.</exception>
/// <exception cref="ArgumentException">If the message contains any invalid
/// fields.</exception>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// message.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <param name="dryRun">A boolean indicating whether to perform a dry run (validation
/// only) of the send. If set to true, the message will be sent to the FCM backend service,
/// but it will not be delivered to any actual recipients.</param>
/// <inheritdoc />
public async Task<string> SendAsync(Message message, bool dryRun)
{
return await this.SendAsync(message, dryRun, default(CancellationToken))
.ConfigureAwait(false);
}

/// <summary>
/// Sends a message to the FCM service for delivery. The message gets validated both by
/// the Admin SDK, and the remote FCM service. A successful return value indicates
/// that the message has been successfully sent to FCM, where it has been accepted by the
/// FCM service.
/// <para>If the <paramref name="dryRun"/> option is set to true, the message will not be
/// actually sent to the recipients. Instead, the FCM service performs all the necessary
/// validations, and emulates the send operation. This is a good way to check if a
/// certain message will be accepted by FCM for delivery.</para>
/// </summary>
/// <returns>A task that completes with a message ID string, which represents
/// successful handoff to FCM.</returns>
/// <exception cref="ArgumentNullException">If the message argument is null.</exception>
/// <exception cref="ArgumentException">If the message contains any invalid
/// fields.</exception>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// message.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <param name="dryRun">A boolean indicating whether to perform a dry run (validation
/// only) of the send. If set to true, the message will be sent to the FCM backend service,
/// but it will not be delivered to any actual recipients.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <inheritdoc />
public async Task<string> SendAsync(
Message message, bool dryRun, CancellationToken cancellationToken)
{
return await this.messagingClient.SendAsync(
message, dryRun, cancellationToken).ConfigureAwait(false);
}

/// <summary>
/// Sends all the messages in the given list via Firebase Cloud Messaging. Employs batching to
/// send the entire list as a single RPC call. Compared to the <see cref="SendAsync(Message)"/>
/// method, this is a significantly more efficient way to send multiple messages.
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="messages">Up to 100 messages to send in the batch. Cannot be null.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendAllAsync(IEnumerable<Message> messages)
{
return await this.SendAllAsync(messages, false)
.ConfigureAwait(false);
}

/// <summary>
/// Sends all the messages in the given list via Firebase Cloud Messaging. Employs batching to
/// send the entire list as a single RPC call. Compared to the <see cref="SendAsync(Message)"/>
/// method, this is a significantly more efficient way to send multiple messages.
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="messages">Up to 100 messages to send in the batch. Cannot be null.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendAllAsync(IEnumerable<Message> messages, CancellationToken cancellationToken)
{
return await this.SendAllAsync(messages, false, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Sends all the messages in the given list via Firebase Cloud Messaging. Employs batching to
/// send the entire list as a single RPC call. Compared to the <see cref="SendAsync(Message)"/>
/// method, this is a significantly more efficient way to send multiple messages.
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="messages">Up to 100 messages to send in the batch. Cannot be null.</param>
/// <param name="dryRun">A boolean indicating whether to perform a dry run (validation
/// only) of the send. If set to true, the message will be sent to the FCM backend service,
/// but it will not be delivered to any actual recipients.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendAllAsync(IEnumerable<Message> messages, bool dryRun)
{
return await this.SendAllAsync(messages, dryRun, default)
.ConfigureAwait(false);
}

/// <summary>
/// Sends all the messages in the given list via Firebase Cloud Messaging. Employs batching to
/// send the entire list as a single RPC call. Compared to the <see cref="SendAsync(Message)"/>
/// method, this is a significantly more efficient way to send multiple messages.
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="messages">Up to 100 messages to send in the batch. Cannot be null.</param>
/// <param name="dryRun">A boolean indicating whether to perform a dry run (validation
/// only) of the send. If set to true, the message will be sent to the FCM backend service,
/// but it will not be delivered to any actual recipients.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendAllAsync(IEnumerable<Message> messages, bool dryRun, CancellationToken cancellationToken)
{
return await this.messagingClient.SendAllAsync(messages, dryRun, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Sends the given multicast message to all the FCM registration tokens specified in it.
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendMulticastAsync(MulticastMessage message)
{
return await this.SendMulticastAsync(message, false)
.ConfigureAwait(false);
}

/// <summary>
/// Sends the given multicast message to all the FCM registration tokens specified in it.
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendMulticastAsync(MulticastMessage message, CancellationToken cancellationToken)
{
return await this.SendMulticastAsync(message, false, cancellationToken)
.ConfigureAwait(false);
}

/// <summary>
/// Sends the given multicast message to all the FCM registration tokens specified in it.
/// <para>If the <paramref name="dryRun"/> option is set to true, the message will not be
/// actually sent to the recipients. Instead, the FCM service performs all the necessary
/// validations, and emulates the send operation. This is a good way to check if a
/// certain message will be accepted by FCM for delivery.</para>
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <param name="dryRun">A boolean indicating whether to perform a dry run (validation
/// only) of the send. If set to true, the message will be sent to the FCM backend service,
/// but it will not be delivered to any actual recipients.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendMulticastAsync(MulticastMessage message, bool dryRun)
{
return await this.SendMulticastAsync(message, dryRun, default)
.ConfigureAwait(false);
}

/// <summary>
/// Sends the given multicast message to all the FCM registration tokens specified in it.
/// <para>If the <paramref name="dryRun"/> option is set to true, the message will not be
/// actually sent to the recipients. Instead, the FCM service performs all the necessary
/// validations, and emulates the send operation. This is a good way to check if a
/// certain message will be accepted by FCM for delivery.</para>
/// </summary>
/// <exception cref="FirebaseMessagingException">If an error occurs while sending the
/// messages.</exception>
/// <param name="message">The message to be sent. Must not be null.</param>
/// <param name="dryRun">A boolean indicating whether to perform a dry run (validation
/// only) of the send. If set to true, the message will be sent to the FCM backend service,
/// but it will not be delivered to any actual recipients.</param>
/// <param name="cancellationToken">A cancellation token to monitor the asynchronous
/// operation.</param>
/// <returns>A <see cref="BatchResponse"/> containing details of the batch operation's
/// outcome.</returns>
/// <inheritdoc />
public async Task<BatchResponse> SendMulticastAsync(
MulticastMessage message, bool dryRun, CancellationToken cancellationToken)
{
Expand All @@ -321,25 +159,15 @@ public async Task<BatchResponse> SendMulticastAsync(
.ConfigureAwait(false);
}

/// <summary>
/// Subscribes a list of registration tokens to a topic.
/// </summary>
/// <param name="registrationTokens">A list of registration tokens to subscribe.</param>
/// <param name="topic">The topic name to subscribe to. /topics/ will be prepended to the topic name provided if absent.</param>
/// <returns>A task that completes with a <see cref="TopicManagementResponse"/>, giving details about the topic subscription operations.</returns>
/// <inheritdoc />
public async Task<TopicManagementResponse> SubscribeToTopicAsync(
IReadOnlyList<string> registrationTokens, string topic)
{
return await this.instanceIdClient.SubscribeToTopicAsync(registrationTokens, topic)
.ConfigureAwait(false);
}

/// <summary>
/// Unsubscribes a list of registration tokens from a topic.
/// </summary>
/// <param name="registrationTokens">A list of registration tokens to unsubscribe.</param>
/// <param name="topic">The topic name to unsubscribe from. /topics/ will be prepended to the topic name provided if absent.</param>
/// <returns>A task that completes with a <see cref="TopicManagementResponse"/>, giving details about the topic unsubscription operations.</returns>
/// <inheritdoc />
public async Task<TopicManagementResponse> UnsubscribeFromTopicAsync(
IReadOnlyList<string> registrationTokens, string topic)
{
Expand Down
Loading