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 "FirebaseInstallations/Source/Library/Public/FirebaseInstallations/FIRInstallations.h"
18
 
19
#if __has_include(<FBLPromises/FBLPromises.h>)
20
#import <FBLPromises/FBLPromises.h>
21
#else
22
#import "FBLPromises.h"
23
#endif
24
 
25
#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
26
 
27
#import "FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h"
28
 
29
#import "FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h"
30
#import "FirebaseInstallations/Source/Library/FIRInstallationsItem.h"
31
#import "FirebaseInstallations/Source/Library/FIRInstallationsLogger.h"
32
#import "FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h"
33
#import "FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h"
34
 
35
NS_ASSUME_NONNULL_BEGIN
36
 
37
static const NSUInteger kExpectedAPIKeyLength = 39;
38
 
39
@protocol FIRInstallationsInstanceProvider <FIRLibrary>
40
@end
41
 
42
@interface FIRInstallations () <FIRInstallationsInstanceProvider>
43
@property(nonatomic, readonly) FIROptions *appOptions;
44
@property(nonatomic, readonly) NSString *appName;
45
 
46
@property(nonatomic, readonly) FIRInstallationsIDController *installationsIDController;
47
 
48
@end
49
 
50
@implementation FIRInstallations
51
 
52
#pragma mark - Firebase component
53
 
54
+ (void)load {
55
  [FIRApp registerInternalLibrary:(Class<FIRLibrary>)self withName:@"fire-install"];
56
}
57
 
58
+ (nonnull NSArray<FIRComponent *> *)componentsToRegister {
59
  FIRComponentCreationBlock creationBlock =
60
      ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) {
61
    *isCacheable = YES;
62
    FIRInstallations *installations = [[FIRInstallations alloc] initWithApp:container.app];
63
    return installations;
64
  };
65
 
66
  FIRComponent *installationsProvider =
67
      [FIRComponent componentWithProtocol:@protocol(FIRInstallationsInstanceProvider)
68
                      instantiationTiming:FIRInstantiationTimingAlwaysEager
69
                             dependencies:@[]
70
                            creationBlock:creationBlock];
71
  return @[ installationsProvider ];
72
}
73
 
74
- (instancetype)initWithApp:(FIRApp *)app {
75
  return [self initWitAppOptions:app.options appName:app.name];
76
}
77
 
78
- (instancetype)initWitAppOptions:(FIROptions *)appOptions appName:(NSString *)appName {
79
  FIRInstallationsIDController *IDController =
80
      [[FIRInstallationsIDController alloc] initWithGoogleAppID:appOptions.googleAppID
81
                                                        appName:appName
82
                                                         APIKey:appOptions.APIKey
83
                                                      projectID:appOptions.projectID
84
                                                    GCMSenderID:appOptions.GCMSenderID
85
                                                    accessGroup:appOptions.appGroupID];
86
 
87
  // `prefetchAuthToken` is disabled due to b/156746574.
88
  return [self initWithAppOptions:appOptions
89
                          appName:appName
90
        installationsIDController:IDController
91
                prefetchAuthToken:NO];
92
}
93
 
94
/// The initializer is supposed to be used by tests to inject `installationsStore`.
95
- (instancetype)initWithAppOptions:(FIROptions *)appOptions
96
                           appName:(NSString *)appName
97
         installationsIDController:(FIRInstallationsIDController *)installationsIDController
98
                 prefetchAuthToken:(BOOL)prefetchAuthToken {
99
  self = [super init];
100
  if (self) {
101
    [[self class] validateAppOptions:appOptions appName:appName];
102
    [[self class] assertCompatibleIIDVersion];
103
 
104
    _appOptions = [appOptions copy];
105
    _appName = [appName copy];
106
    _installationsIDController = installationsIDController;
107
 
108
    // Pre-fetch auth token.
109
    if (prefetchAuthToken) {
110
      [self authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult,
111
                                      NSError *_Nullable error){
112
      }];
113
    }
114
  }
115
  return self;
116
}
117
 
118
+ (void)validateAppOptions:(FIROptions *)appOptions appName:(NSString *)appName {
119
  NSMutableArray *missingFields = [NSMutableArray array];
120
  if (appName.length < 1) {
121
    [missingFields addObject:@"`FirebaseApp.name`"];
122
  }
123
  if (appOptions.APIKey.length < 1) {
124
    [missingFields addObject:@"`FirebaseOptions.APIKey`"];
125
  }
126
  if (appOptions.googleAppID.length < 1) {
127
    [missingFields addObject:@"`FirebaseOptions.googleAppID`"];
128
  }
129
 
130
  if (appOptions.projectID.length < 1) {
131
    [missingFields addObject:@"`FirebaseOptions.projectID`"];
132
  }
133
 
134
  if (missingFields.count > 0) {
135
    [NSException
136
         raise:kFirebaseInstallationsErrorDomain
137
        format:
138
            @"%@[%@] Could not configure Firebase Installations due to invalid FirebaseApp "
139
            @"options. The following parameters are nil or empty: %@. If you use "
140
            @"GoogleServices-Info.plist please download the most recent version from the Firebase "
141
            @"Console. If you configure Firebase in code, please make sure you specify all "
142
            @"required parameters.",
143
            kFIRLoggerInstallations, kFIRInstallationsMessageCodeInvalidFirebaseAppOptions,
144
            [missingFields componentsJoinedByString:@", "]];
145
  }
146
 
147
  [self validateAPIKey:appOptions.APIKey];
148
}
149
 
150
+ (void)validateAPIKey:(nullable NSString *)APIKey {
151
  NSMutableArray<NSString *> *validationIssues = [[NSMutableArray alloc] init];
152
 
153
  if (APIKey.length != kExpectedAPIKeyLength) {
154
    [validationIssues addObject:[NSString stringWithFormat:@"API Key length must be %lu characters",
155
                                                           (unsigned long)kExpectedAPIKeyLength]];
156
  }
157
 
158
  if (![[APIKey substringToIndex:1] isEqualToString:@"A"]) {
159
    [validationIssues addObject:@"API Key must start with `A`"];
160
  }
161
 
162
  NSMutableCharacterSet *allowedCharacters = [NSMutableCharacterSet alphanumericCharacterSet];
163
  [allowedCharacters
164
      formUnionWithCharacterSet:[NSCharacterSet characterSetWithCharactersInString:@"-_"]];
165
 
166
  NSCharacterSet *characters = [NSCharacterSet characterSetWithCharactersInString:APIKey];
167
  if (![allowedCharacters isSupersetOfSet:characters]) {
168
    [validationIssues addObject:@"API Key must contain only base64 url-safe characters characters"];
169
  }
170
 
171
  if (validationIssues.count > 0) {
172
    [NSException
173
         raise:kFirebaseInstallationsErrorDomain
174
        format:
175
            @"%@[%@] Could not configure Firebase Installations due to invalid FirebaseApp "
176
            @"options. `FirebaseOptions.APIKey` doesn't match the expected format: %@. If you use "
177
            @"GoogleServices-Info.plist please download the most recent version from the Firebase "
178
            @"Console. If you configure Firebase in code, please make sure you specify all "
179
            @"required parameters.",
180
            kFIRLoggerInstallations, kFIRInstallationsMessageCodeInvalidFirebaseAppOptions,
181
            [validationIssues componentsJoinedByString:@", "]];
182
  }
183
}
184
 
185
#pragma mark - Public
186
 
187
+ (FIRInstallations *)installations {
188
  FIRApp *defaultApp = [FIRApp defaultApp];
189
  if (!defaultApp) {
190
    [NSException raise:kFirebaseInstallationsErrorDomain
191
                format:@"The default FirebaseApp instance must be configured before the default"
192
                       @"FirebaseApp instance can be initialized. One way to ensure this is to "
193
                       @"call `FirebaseApp.configure()` in the App  Delegate's "
194
                       @"`application(_:didFinishLaunchingWithOptions:)` "
195
                       @"(or the `@main` struct's initializer in SwiftUI)."];
196
  }
197
 
198
  return [self installationsWithApp:defaultApp];
199
}
200
 
201
+ (FIRInstallations *)installationsWithApp:(FIRApp *)app {
202
  id<FIRInstallationsInstanceProvider> installations =
203
      FIR_COMPONENT(FIRInstallationsInstanceProvider, app.container);
204
  return (FIRInstallations *)installations;
205
}
206
 
207
- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion {
208
  [self.installationsIDController getInstallationItem]
209
      .then(^id(FIRInstallationsItem *installation) {
210
        completion(installation.firebaseInstallationID, nil);
211
        return nil;
212
      })
213
      .catch(^(NSError *error) {
214
        completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]);
215
      });
216
}
217
 
218
- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion {
219
  [self authTokenForcingRefresh:NO completion:completion];
220
}
221
 
222
- (void)authTokenForcingRefresh:(BOOL)forceRefresh
223
                     completion:(FIRInstallationsTokenHandler)completion {
224
  [self.installationsIDController getAuthTokenForcingRefresh:forceRefresh]
225
      .then(^FIRInstallationsAuthTokenResult *(FIRInstallationsItem *installation) {
226
        FIRInstallationsAuthTokenResult *result = [[FIRInstallationsAuthTokenResult alloc]
227
             initWithToken:installation.authToken.token
228
            expirationDate:installation.authToken.expirationDate];
229
        return result;
230
      })
231
      .then(^id(FIRInstallationsAuthTokenResult *token) {
232
        completion(token, nil);
233
        return nil;
234
      })
235
      .catch(^void(NSError *error) {
236
        completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]);
237
      });
238
}
239
 
240
- (void)deleteWithCompletion:(void (^)(NSError *__nullable error))completion {
241
  [self.installationsIDController deleteInstallation]
242
      .then(^id(id result) {
243
        completion(nil);
244
        return nil;
245
      })
246
      .catch(^void(NSError *error) {
247
        completion([FIRInstallationsErrorUtil publicDomainErrorWithError:error]);
248
      });
249
}
250
 
251
#pragma mark - IID version compatibility
252
 
253
+ (void)assertCompatibleIIDVersion {
254
  // We use this flag to disable IID compatibility exception for unit tests.
255
#ifdef FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION
256
  return;
257
#else
258
  if (![self isIIDVersionCompatible]) {
259
    [NSException
260
         raise:kFirebaseInstallationsErrorDomain
261
        format:@"Firebase Instance ID is not compatible with Firebase 8.x+. Please remove the "
262
               @"dependency from the app. See the documentation at "
263
               @"https://firebase.google.com/docs/cloud-messaging/ios/"
264
               @"client#fetching-the-current-registration-token."];
265
  }
266
#endif
267
}
268
 
269
+ (BOOL)isIIDVersionCompatible {
270
  Class IIDClass = NSClassFromString(@"FIRInstanceID");
271
  if (IIDClass == nil) {
272
    // It is OK if there is no IID at all.
273
    return YES;
274
  }
275
  // We expect a compatible version having the method `+[FIRInstanceID usesFIS]` defined.
276
  BOOL isCompatibleVersion = [IIDClass respondsToSelector:NSSelectorFromString(@"usesFIS")];
277
  return isCompatibleVersion;
278
}
279
 
280
@end
281
 
282
NS_ASSUME_NONNULL_END