Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/*
2
 * Copyright 2019 Google
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
#import "FirebaseMessaging/Sources/Token/FIRMessagingTokenStore.h"
18
 
19
#import "FirebaseMessaging/Sources/FIRMessagingConstants.h"
20
#import "FirebaseMessaging/Sources/FIRMessagingLogger.h"
21
#import "FirebaseMessaging/Sources/FIRMessagingUtilities.h"
22
#import "FirebaseMessaging/Sources/Token/FIRMessagingAuthKeychain.h"
23
#import "FirebaseMessaging/Sources/Token/FIRMessagingTokenInfo.h"
24
 
25
static NSString *const kFIRMessagingTokenKeychainId = @"com.google.iid-tokens";
26
 
27
@interface FIRMessagingTokenStore ()
28
 
29
@property(nonatomic, readwrite, strong) FIRMessagingAuthKeychain *keychain;
30
 
31
@end
32
 
33
@implementation FIRMessagingTokenStore
34
 
35
- (instancetype)init {
36
  self = [super init];
37
  if (self) {
38
    _keychain = [[FIRMessagingAuthKeychain alloc] initWithIdentifier:kFIRMessagingTokenKeychainId];
39
  }
40
  return self;
41
}
42
 
43
#pragma mark - Get
44
 
45
+ (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope {
46
  return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope];
47
}
48
 
49
- (nullable FIRMessagingTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity
50
                                                            scope:(NSString *)scope {
51
  // TODO(chliangGoogle): If we don't have the token plist we should delete all the tokens from
52
  // the keychain. This is because not having the plist signifies a backup and restore operation.
53
  // In case the keychain has any tokens these would now be stale and therefore should be
54
  // deleted.
55
  if (![authorizedEntity length] || ![scope length]) {
56
    return nil;
57
  }
58
  NSString *account = FIRMessagingAppIdentifier();
59
  NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope];
60
  NSData *item = [self.keychain dataForService:service account:account];
61
  if (!item) {
62
    return nil;
63
  }
64
  // Token infos created from legacy storage don't have appVersion, firebaseAppID, or APNSInfo.
65
  FIRMessagingTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item];
66
  return tokenInfo;
67
}
68
 
69
- (NSArray<FIRMessagingTokenInfo *> *)cachedTokenInfos {
70
  NSString *account = FIRMessagingAppIdentifier();
71
  NSArray<NSData *> *items =
72
      [self.keychain itemsMatchingService:kFIRMessagingKeychainWildcardIdentifier account:account];
73
  NSMutableArray<FIRMessagingTokenInfo *> *tokenInfos =
74
      [NSMutableArray arrayWithCapacity:items.count];
75
  for (NSData *item in items) {
76
    FIRMessagingTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item];
77
    if (tokenInfo) {
78
      [tokenInfos addObject:tokenInfo];
79
    }
80
  }
81
  return tokenInfos;
82
}
83
 
84
+ (nullable FIRMessagingTokenInfo *)tokenInfoFromKeychainItem:(NSData *)item {
85
  // Check if it is saved as an archived FIRMessagingTokenInfo, otherwise return nil.
86
  FIRMessagingTokenInfo *tokenInfo = nil;
87
  // NOTE: Passing in nil to unarchiveObjectWithData will result in an iOS error logged
88
  // in the console on iOS 10 and below. Avoid by checking item.data's existence.
89
  if (item) {
90
    // TODO(chliangGoogle: Use the new API and secureCoding protocol.
91
    @try {
92
#pragma clang diagnostic push
93
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
94
      [NSKeyedUnarchiver setClass:[FIRMessagingTokenInfo class]
95
                     forClassName:@"FIRInstanceIDTokenInfo"];
96
      tokenInfo = [NSKeyedUnarchiver unarchiveObjectWithData:item];
97
#pragma clang diagnostic pop
98
 
99
    } @catch (NSException *exception) {
100
      FIRMessagingLoggerDebug(kFIRMessagingMessageCodeTokenStoreExceptionUnarchivingTokenInfo,
101
                              @"Unable to parse token info from Keychain item; item was in an "
102
                              @"invalid format");
103
      tokenInfo = nil;
104
    } @finally {
105
    }
106
  }
107
  return tokenInfo;
108
}
109
 
110
#pragma mark - Save
111
// Token Infos will be saved under these Keychain keys:
112
// Account: <Main App Bundle ID> (e.g. com.mycompany.myapp)
113
// Service: <Sender ID>:<Scope> (e.g. 1234567890:*)
114
- (void)saveTokenInfo:(FIRMessagingTokenInfo *)tokenInfo
115
              handler:(void (^)(NSError *))handler {  // Keep the cachetime up-to-date.
116
  tokenInfo.cacheTime = [NSDate date];
117
  // Always write to the Keychain, so that the cacheTime is up-to-date.
118
  NSData *tokenInfoData;
119
  // TODO(chliangGoogle: Use the new API and secureCoding protocol.
120
  [NSKeyedArchiver setClassName:@"FIRInstanceIDTokenInfo" forClass:[FIRMessagingTokenInfo class]];
121
#pragma clang diagnostic push
122
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
123
  tokenInfoData = [NSKeyedArchiver archivedDataWithRootObject:tokenInfo];
124
#pragma clang diagnostic pop
125
  NSString *account = FIRMessagingAppIdentifier();
126
  NSString *service = [[self class] serviceKeyForAuthorizedEntity:tokenInfo.authorizedEntity
127
                                                            scope:tokenInfo.scope];
128
  [self.keychain setData:tokenInfoData forService:service account:account handler:handler];
129
}
130
 
131
- (void)saveTokenInfoInCache:(FIRMessagingTokenInfo *)tokenInfo {
132
  tokenInfo.cacheTime = [NSDate date];
133
  // TODO(chliangGoogle): Use the new API and secureCoding protocol.
134
  // Always write to the Keychain, so that the cacheTime is up-to-date.
135
  NSData *tokenInfoData;
136
  [NSKeyedArchiver setClassName:@"FIRInstanceIDTokenInfo" forClass:[FIRMessagingTokenInfo class]];
137
#pragma clang diagnostic push
138
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
139
  tokenInfoData = [NSKeyedArchiver archivedDataWithRootObject:tokenInfo];
140
#pragma clang diagnostic pop
141
  NSString *account = FIRMessagingAppIdentifier();
142
  NSString *service = [[self class] serviceKeyForAuthorizedEntity:tokenInfo.authorizedEntity
143
                                                            scope:tokenInfo.scope];
144
  [self.keychain setCacheData:tokenInfoData forService:service account:account];
145
}
146
 
147
#pragma mark - Delete
148
 
149
- (void)removeTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity
150
                                  scope:(nonnull NSString *)scope {
151
  if (![authorizedEntity length] || ![scope length]) {
152
    FIRMessagingLoggerError(kFIRMessagingMessageCodeStore012,
153
                            @"Will not delete token with invalid entity: %@, scope: %@",
154
                            authorizedEntity, scope);
155
    return;
156
  }
157
  NSString *account = FIRMessagingAppIdentifier();
158
  NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope];
159
  [self.keychain removeItemsMatchingService:service account:account handler:nil];
160
}
161
 
162
- (void)removeAllTokensWithHandler:(void (^)(NSError *error))handler {
163
  NSString *account = FIRMessagingAppIdentifier();
164
  [self.keychain removeItemsMatchingService:kFIRMessagingKeychainWildcardIdentifier
165
                                    account:account
166
                                    handler:handler];
167
}
168
 
169
@end