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
13 changes: 10 additions & 3 deletions Firebase/InstanceID/FIRInstanceID.m
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,11 @@ - (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity

FIRInstanceIDDeleteTokenHandler newHandler = ^(NSError *error) {
// If a default token is deleted successfully, reset the defaultFCMToken too.
if (!error && [self isDefaultTokenWithAuthorizedEntity:authorizedEntity scope:scope]) {
self.defaultFCMToken = nil;
if (!error) {
if ([self isDefaultTokenWithAuthorizedEntity:authorizedEntity scope:scope] ||
[authorizedEntity isEqualToString:@"*"]) {
self.defaultFCMToken = nil;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
handler(error);
Expand Down Expand Up @@ -523,7 +526,7 @@ - (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler {
return;
}

[self.tokenManager.authService resetCheckinWithHandler:^(NSError *error) {
[self deleteCheckinWithHandler:^(NSError *_Nullable error) {
if (error) {
if (handler) {
handler(error);
Expand All @@ -550,6 +553,10 @@ - (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler {

#pragma mark - Checkin

- (void)deleteCheckinWithHandler:(void (^)(NSError *error))handler {
[self.tokenManager.authService resetCheckinWithHandler:handler];
}

- (BOOL)tryToLoadValidCheckinInfo {
FIRInstanceIDCheckinPreferences *checkinPreferences =
[self.tokenManager.authService checkinPreferences];
Expand Down
7 changes: 7 additions & 0 deletions Firebase/InstanceID/Private/FIRInstanceID_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (BOOL)tryToLoadValidCheckinInfo;

/**
* Deletes the checkin info for the app.
*
* @param handler The completion handler to invoke once the request has completed.
*/
- (void)deleteCheckinWithHandler:(void (^)(NSError *_Nullable error))handler;

@end

NS_ASSUME_NONNULL_END
2 changes: 1 addition & 1 deletion FirebaseInstanceID.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'FirebaseInstanceID'
s.version = '4.6.0'
s.version = '4.7.0'
s.summary = 'Firebase InstanceID'

s.description = <<-DESC
Expand Down
4 changes: 2 additions & 2 deletions FirebaseMessaging.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'FirebaseMessaging'
s.version = '4.6.2'
s.version = '4.7.0'
s.summary = 'Firebase Messaging'

s.description = <<-DESC
Expand Down Expand Up @@ -55,7 +55,7 @@ device, and it is completely free.
s.osx.framework = 'SystemConfiguration'
s.weak_framework = 'UserNotifications'
s.dependency 'FirebaseCore', '~> 6.10'
s.dependency 'FirebaseInstanceID', '~> 4.6'
s.dependency 'FirebaseInstanceID', '~> 4.7'
s.dependency 'GoogleUtilities/AppDelegateSwizzler', '~> 6.7'
s.dependency 'GoogleUtilities/Reachability', '~> 6.7'
s.dependency 'GoogleUtilities/Environment', '~> 6.7'
Expand Down
167 changes: 131 additions & 36 deletions FirebaseMessaging/Apps/Sample/Sample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct ContentView: View {
Text("InstanceID")
.font(.subheadline)
.fontWeight(.semibold)

Text(identity.instanceID ?? "None").foregroundColor(.green)
}

Expand All @@ -55,68 +56,142 @@ struct ContentView: View {
Text("Topic")
.fontWeight(.semibold)
}
}
.navigationBarTitle("Firebase Messaging")
.foregroundColor(.blue)

// MARK: Action buttons
// MARK: Action buttons

Button(action: getToken) {
HStack {
Image(systemName: "arrow.clockwise.circle.fill").font(.body)
Text("Get ID and Token")
VStack(alignment: .leading) {
Text("getToken")
.fontWeight(.semibold)
}
}
HStack {
Button(action: getIDAndToken) {
HStack {
Image(systemName: "arrow.clockwise.circle.fill")
Text("IID.ID")
.fontWeight(.semibold)
}
}
Button(action: getToken) {
HStack {
Image(systemName: "arrow.clockwise.circle.fill")
Text("IID")
.fontWeight(.semibold)
}
}
Button(action: getFCMToken) {
HStack {
Image(systemName: "arrow.clockwise.circle.fill").font(.body)
Text("FM")
.fontWeight(.semibold)
}
}
}
}.font(.system(size: 14))

Button(action: deleteToken) {
HStack {
Image(systemName: "trash.fill").font(.body)
Text("Delete Token")
VStack(alignment: .leading) {
Text("deleteToken")
.fontWeight(.semibold)
}
}
HStack {
Button(action: deleteToken) {
HStack {
Image(systemName: "trash.fill")
Text("IID")
.fontWeight(.semibold)
}
}
Button(action: deleteFCMToken) {
HStack {
Image(systemName: "trash.fill")
Text("FM")
.fontWeight(.semibold)
}
}
}
}.font(.system(size: 14))

Button(action: deleteID) {
HStack {
Image(systemName: "trash.fill").font(.body)
Text("Delete ID")
VStack(alignment: .leading) {
Text("delete")
.fontWeight(.semibold)
}
HStack {
Button(action: deleteID) {
HStack {
Image(systemName: "trash.fill")
Text("IID")
.fontWeight(.bold)
}
}
Button(action: deleteFCM) {
HStack {
Image(systemName: "trash.fill")
Text("FM")
.fontWeight(.semibold)
}
}
Button(action: deleteFID) {
HStack {
Image(systemName: "trash.fill")
Text("FIS")
.fontWeight(.semibold)
}
}
}
}.font(.system(size: 14))
Text("\(log)")
.lineLimit(10)
.multilineTextAlignment(.leading)
}
.navigationBarTitle("Firebase Messaging")

Button(action: deleteFID) {
HStack {
Image(systemName: "trash.fill").font(.body)
Text("Delete FID")
.fontWeight(.semibold)
}
}
Text("\(log)")
.lineLimit(10)
.multilineTextAlignment(.leading)
}.buttonStyle(IdentityButtonStyle())
}
}

func getToken() {
func getIDAndToken() {
InstanceID.instanceID().instanceID { result, error in
guard let result = result, error == nil else {
self.log = "Failed getting iid and token: \(String(describing: error))"
return
}
self.identity.token = result.token
self.identity.instanceID = result.instanceID
self.log = "Successfully got token."
self.log = "Successfully got iid and token."
}
}

func deleteToken() {
func getToken() {
guard let app = FirebaseApp.app() else {
return
}
let senderID = app.options.gcmSenderID
Messaging.messaging().deleteFCMToken(forSenderID: senderID) { error in
var options: [String: Any] = [:]
if Messaging.messaging().apnsToken == nil {
log = "There's no APNS token available at the moment."
return
}
options = ["apns_token": Messaging.messaging().apnsToken as Any]
InstanceID.instanceID()
.token(withAuthorizedEntity: senderID, scope: "*", options: options) { token, error in
guard let token = token, error == nil else {
self.log = "Failed getting token: \(String(describing: error))"
return
}
self.identity.token = token
self.log = "Successfully got token."
}
}

func getFCMToken() {
Messaging.messaging().token { token, error in
guard let token = token, error == nil else {
self.log = "Failed getting iid and token: \(String(describing: error))"
return
}
self.identity.token = token
self.log = "Successfully got token."
}
}

func deleteFCMToken() {
Messaging.messaging().deleteToken { error in
if let error = error as NSError? {
self.log = "Failed deleting token: \(error)"
return
Expand All @@ -125,6 +200,16 @@ struct ContentView: View {
}
}

func deleteToken() {
guard let app = FirebaseApp.app() else {
return
}
let senderID = app.options.gcmSenderID
InstanceID.instanceID()
.deleteToken(withAuthorizedEntity: senderID, scope: "*") { error in
}
}

func deleteID() {
InstanceID.instanceID().deleteID { error in
if let error = error as NSError? {
Expand All @@ -135,6 +220,16 @@ struct ContentView: View {
}
}

func deleteFCM() {
Messaging.messaging().deleteData { error in
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ryanwilson After renaming, the swift API calls it deleteData, does that look good to you? or I should rename swift API to deleteMessagingData as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me - thanks!

if let error = error as NSError? {
self.log = "Failed deleting Messaging: \(error)"
return
}
self.log = "Successfully deleted Messaging data."
}
}

func deleteFID() {
Installations.installations().delete { error in
if let error = error as NSError? {
Expand Down Expand Up @@ -199,7 +294,7 @@ struct ContentView_Previews: PreviewProvider {
struct IdentityButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.frame(minWidth: 0, maxWidth: 200)
.frame(minWidth: 0, maxWidth: 60)
.padding()
.foregroundColor(.white)
.background(Color.yellow)
Expand Down
3 changes: 3 additions & 0 deletions FirebaseMessaging/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# 2020-09 -- v.4.7.0
- [added] Added new token APIs to get and delete the default FCM registration token asynchronously. Also added a new `Messaging.delete(completion:)` method that deletes all FCM registration tokens and checkin data. (#6313)

# 2020-08 -- v.4.6.2
- [fixed] Fixed an issue that topic doesn't work in watchOS. (#6160)
- [fixed] Improved Xcode completion of public API completion handlers in Swift. (#6278)
Expand Down
41 changes: 41 additions & 0 deletions FirebaseMessaging/Sources/FIRMessaging.m
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,15 @@ - (NSString *)FCMToken {
return token;
}

- (void)tokenWithCompletion:(FIRMessagingFCMTokenFetchCompletion)completion {
FIROptions *options = FIRApp.defaultApp.options;
[self retrieveFCMTokenForSenderID:options.GCMSenderID completion:completion];
}
- (void)deleteTokenWithCompletion:(FIRMessagingDeleteFCMTokenCompletion)completion {
FIROptions *options = FIRApp.defaultApp.options;
[self deleteFCMTokenForSenderID:options.GCMSenderID completion:completion];
}

- (void)retrieveFCMTokenForSenderID:(nonnull NSString *)senderID
completion:(nonnull FIRMessagingFCMTokenFetchCompletion)completion {
if (!senderID.length) {
Expand Down Expand Up @@ -617,6 +626,38 @@ - (void)deleteFCMTokenForSenderID:(nonnull NSString *)senderID
handler:completion];
}

- (void)deleteDataWithCompletion:(void (^)(NSError *_Nullable))completion {
FIRMessaging_WEAKIFY(self);
[self.instanceID
deleteTokenWithAuthorizedEntity:@"*"
scope:@"*"
handler:^(NSError *_Nonnull error) {
FIRMessaging_STRONGIFY(self);
if (error) {
completion(error);
return;
}
[self.instanceID
deleteCheckinWithHandler:^(NSError *_Nullable error) {
if (error) {
completion(error);
return;
}
// Only request new token if FCM auto initialization is
// enabled.
if ([self isAutoInitEnabled]) {
// Deletion succeeds! Requesting new checkin, IID and token.
[self tokenWithCompletion:^(NSString *_Nullable token,
NSError *_Nullable error) {
completion(error);
}];
return;
}
completion(nil);
}];
}];
}

#pragma mark - FIRMessagingDelegate helper methods
- (void)setDelegate:(id<FIRMessagingDelegate>)delegate {
_delegate = delegate;
Expand Down
Loading