Skip to content
Merged
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
758 changes: 758 additions & 0 deletions FirebaseAdmin/FirebaseAdmin.Tests/Messaging/MessageTest.cs

Large diffs are not rendered by default.

16 changes: 5 additions & 11 deletions FirebaseAdmin/FirebaseAdmin/Messaging/AndroidNotification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,15 @@ internal AndroidNotification CopyAndValidate()
};
if (copy.Color != null && !Regex.Match(copy.Color, "^#[0-9a-fA-F]{6}$").Success)
{
throw new ArgumentException("Color must be in the form #RRGGBB");
throw new ArgumentException("Color must be in the form #RRGGBB.");
}
if (copy.TitleLocArgs != null && copy.TitleLocArgs.Any())
if (copy.TitleLocArgs?.Any() == true && string.IsNullOrEmpty(copy.TitleLocKey))
{
if (string.IsNullOrEmpty(copy.TitleLocKey))
{
throw new ArgumentException("TitleLocKey is required when specifying TitleLocArgs");
}
throw new ArgumentException("TitleLocKey is required when specifying TitleLocArgs.");
}
if (copy.BodyLocArgs != null && copy.BodyLocArgs.Any())
if (copy.BodyLocArgs?.Any() == true && string.IsNullOrEmpty(copy.BodyLocKey))
{
if (string.IsNullOrEmpty(copy.BodyLocKey))
{
throw new ArgumentException("BodyLocKey is required when specifying BodyLocArgs");
}
throw new ArgumentException("BodyLocKey is required when specifying BodyLocArgs.");
}
return copy;
}
Expand Down
135 changes: 135 additions & 0 deletions FirebaseAdmin/FirebaseAdmin/Messaging/ApnsConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright 2018, Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using Google.Apis.Json;
using Newtonsoft.Json;

namespace FirebaseAdmin.Messaging
{
/// <summary>
/// Represents the APNS-specific options that can be included in a <see cref="Message"/>. Refer
/// to <see href="https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html">
/// APNs documentation</see> for various headers and payload fields supported by APNS.
/// </summary>
public sealed class ApnsConfig
{
private ApnsPayload _payload = new ApnsPayload();

/// <summary>
/// A collection of APNs headers.
/// </summary>
[JsonProperty("headers")]
public IReadOnlyDictionary<string, string> Headers { get; set; }

/// <summary>
/// The <code>aps</code> dictionary to be included in the APNs payload.
/// </summary>
[JsonIgnore]
public Aps Aps
{
get
{
return Payload.Aps;
}
set
{
Payload.Aps = value;
}
}

/// <summary>
/// APNs payload as accepted by the FCM backend servers.
/// </summary>
[JsonProperty("payload")]
private ApnsPayload Payload
{
get
{
if (_payload.Aps != null && _payload.CustomData?.ContainsKey("aps") == true)
{
throw new ArgumentException("Multiple specifications for ApnsConfig key: aps");
}
return _payload;
}
set
{
_payload = value;
}
}

/// <summary>
/// A collection of arbitrary key-value data to be included in the APNs payload.
/// </summary>
[JsonIgnore]
public IDictionary<string, object> CustomData
{
get
{
return Payload.CustomData;
}
set
{
Payload.CustomData = value;
}
}

/// <summary>
/// Copies this APNs config, and validates the content of it to ensure that it can be
/// serialized into the JSON format expected by the FCM service.
/// </summary>
internal ApnsConfig CopyAndValidate()
{
var copy = new ApnsConfig()
{
Headers = this.Headers?.Copy(),
Payload = this.Payload.CopyAndValidate(),
};
return copy;
}
}

/// <summary>
/// The APNs payload object as expected by the FCM backend service.
/// </summary>
internal sealed class ApnsPayload
{
[JsonProperty("aps")]
internal Aps Aps { get; set; }

[JsonExtensionData]
internal IDictionary<string, object> CustomData { get; set; }

/// <summary>
/// Copies this APNs payload, and validates the content of it to ensure that it can be
/// serialized into the JSON format expected by the FCM service.
/// </summary>
internal ApnsPayload CopyAndValidate()
{
var copy = new ApnsPayload()
{
CustomData = this.CustomData?.ToDictionary(e => e.Key, e => e.Value),
};
var aps = this.Aps;
if (aps == null && copy.CustomData?.ContainsKey("aps") == false)
{
throw new ArgumentException("Aps dictionary is required in ApnsConfig");
}
copy.Aps = aps?.CopyAndValidate();
return copy;
}
}
}
Loading