Skip to content

Commit 77dae0b

Browse files
authored
Add Dynamic Links PR to 7.3.0 release with Changelog update (#7119)
1 parent 7134db8 commit 77dae0b

File tree

7 files changed

+448
-53
lines changed

7 files changed

+448
-53
lines changed

FirebaseDynamicLinks/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# v7.3.0
2+
- [added] Manually created dynamic links should be subject to allowed/blocked check (#5853)
3+
14
# v4.3.1
25
- [changed] Client id usage in api call and respective checks in the code.
36
- [fixed] Fix attempts to connect to invalid ipv6 domain by updating ipv4 and ipv6 to use a single, valid endpoint (#5032)

FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ typedef void (^FIRPostInstallAttributionCompletionHandler)(
3131

3232
/** A definition for a block used to return data and errors after an asynchronous task. */
3333
typedef void (^FIRNetworkRequestCompletionHandler)(NSData *_Nullable data,
34+
NSURLResponse *_Nullable response,
3435
NSError *_Nullable error);
3536

3637
// these enums must be in sync with google/firebase/dynamiclinks/v1/dynamic_links.proto

FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.m

Lines changed: 78 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
static NSString *const kFDLAnalyticsDataMediumKey = @"utmMedium";
4242
static NSString *const kFDLAnalyticsDataCampaignKey = @"utmCampaign";
4343
static NSString *const kHeaderIosBundleIdentifier = @"X-Ios-Bundle-Identifier";
44+
static NSString *const kGenericErrorDomain = @"com.firebase.dynamicLinks";
4445

4546
typedef NSDictionary *_Nullable (^FIRDLNetworkingParserBlock)(
4647
NSString *requestURLString,
@@ -67,7 +68,7 @@ void FIRMakeHTTPRequest(NSURLRequest *request, FIRNetworkRequestCompletionHandle
6768
[session dataTaskWithRequest:request
6869
completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response,
6970
NSError *_Nullable error) {
70-
completion(data, error);
71+
completion(data, response, error);
7172
}];
7273
[dataTask resume];
7374
}
@@ -91,6 +92,41 @@ - (instancetype)initWithAPIKey:(NSString *)APIKey URLScheme:(NSString *)URLSchem
9192
return self;
9293
}
9394

95+
+ (nullable NSError *)extractErrorForShortLink:(NSURL *)url
96+
data:(NSData *)data
97+
response:(NSURLResponse *)response
98+
error:(nullable NSError *)error {
99+
if (error) {
100+
return error;
101+
}
102+
103+
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
104+
NSError *customError = nil;
105+
106+
if (![response isKindOfClass:[NSHTTPURLResponse class]]) {
107+
customError =
108+
[NSError errorWithDomain:kGenericErrorDomain
109+
code:0
110+
userInfo:@{@"message" : @"Response should be of type NSHTTPURLResponse."}];
111+
} else if ((statusCode < 200 || statusCode >= 300) && data) {
112+
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
113+
if ([result isKindOfClass:[NSDictionary class]] && [result objectForKey:@"error"]) {
114+
id err = [result objectForKey:@"error"];
115+
customError = [NSError errorWithDomain:kGenericErrorDomain code:statusCode userInfo:err];
116+
} else {
117+
customError = [NSError
118+
errorWithDomain:kGenericErrorDomain
119+
code:0
120+
userInfo:@{
121+
@"message" :
122+
[NSString stringWithFormat:@"Failed to resolve link: %@", url.absoluteString]
123+
}];
124+
}
125+
}
126+
127+
return customError;
128+
}
129+
94130
#pragma mark - Public interface
95131

96132
- (void)resolveShortLink:(NSURL *)url
@@ -108,34 +144,39 @@ - (void)resolveShortLink:(NSURL *)url
108144
@"sdk_version" : FDLSDKVersion
109145
};
110146

111-
FIRNetworkRequestCompletionHandler resolveLinkCallback = ^(NSData *data, NSError *error) {
112-
NSURL *resolvedURL;
113-
114-
if (!error && data) {
115-
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
116-
if ([result isKindOfClass:[NSDictionary class]]) {
117-
id invitationIDObject = [result objectForKey:@"invitationId"];
118-
119-
NSString *invitationIDString;
120-
if ([invitationIDObject isKindOfClass:[NSDictionary class]]) {
121-
NSDictionary *invitationIDDictionary = invitationIDObject;
122-
invitationIDString = invitationIDDictionary[@"id"];
123-
} else if ([invitationIDObject isKindOfClass:[NSString class]]) {
124-
invitationIDString = invitationIDObject;
147+
FIRNetworkRequestCompletionHandler resolveLinkCallback =
148+
^(NSData *data, NSURLResponse *response, NSError *error) {
149+
NSURL *resolvedURL = nil;
150+
NSError *extractedError = [FIRDynamicLinkNetworking extractErrorForShortLink:url
151+
data:data
152+
response:response
153+
error:error];
154+
155+
if (!extractedError && data) {
156+
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
157+
if ([result isKindOfClass:[NSDictionary class]]) {
158+
id invitationIDObject = [result objectForKey:@"invitationId"];
159+
160+
NSString *invitationIDString;
161+
if ([invitationIDObject isKindOfClass:[NSDictionary class]]) {
162+
NSDictionary *invitationIDDictionary = invitationIDObject;
163+
invitationIDString = invitationIDDictionary[@"id"];
164+
} else if ([invitationIDObject isKindOfClass:[NSString class]]) {
165+
invitationIDString = invitationIDObject;
166+
}
167+
168+
NSString *deepLinkString = result[kFDLResolvedLinkDeepLinkURLKey];
169+
NSString *minAppVersion = result[kFDLResolvedLinkMinAppVersionKey];
170+
NSString *utmSource = result[kFDLAnalyticsDataSourceKey];
171+
NSString *utmMedium = result[kFDLAnalyticsDataMediumKey];
172+
NSString *utmCampaign = result[kFDLAnalyticsDataCampaignKey];
173+
resolvedURL = FIRDLDeepLinkURLWithInviteID(invitationIDString, deepLinkString,
174+
utmSource, utmMedium, utmCampaign, NO, nil,
175+
minAppVersion, self->_URLScheme, nil);
176+
}
125177
}
126-
127-
NSString *deepLinkString = result[kFDLResolvedLinkDeepLinkURLKey];
128-
NSString *minAppVersion = result[kFDLResolvedLinkMinAppVersionKey];
129-
NSString *utmSource = result[kFDLAnalyticsDataSourceKey];
130-
NSString *utmMedium = result[kFDLAnalyticsDataMediumKey];
131-
NSString *utmCampaign = result[kFDLAnalyticsDataCampaignKey];
132-
resolvedURL = FIRDLDeepLinkURLWithInviteID(invitationIDString, deepLinkString, utmSource,
133-
utmMedium, utmCampaign, NO, nil, minAppVersion,
134-
self->_URLScheme, nil);
135-
}
136-
}
137-
handler(resolvedURL, error);
138-
};
178+
handler(resolvedURL, extractedError);
179+
};
139180

140181
NSString *requestURLString =
141182
[NSString stringWithFormat:@"%@/reopenAttribution%@", kiOSReopenRestBaseUrl,
@@ -242,13 +283,14 @@ - (void)convertInvitation:(NSString *)invitationID
242283
}
243284
};
244285

245-
FIRNetworkRequestCompletionHandler convertInvitationCallback = ^(NSData *data, NSError *error) {
246-
if (handler) {
247-
dispatch_async(dispatch_get_main_queue(), ^{
248-
handler(error);
249-
});
250-
}
251-
};
286+
FIRNetworkRequestCompletionHandler convertInvitationCallback =
287+
^(NSData *data, NSURLResponse *response, NSError *error) {
288+
if (handler) {
289+
dispatch_async(dispatch_get_main_queue(), ^{
290+
handler(error);
291+
});
292+
}
293+
};
252294

253295
NSString *requestURL = [NSString stringWithFormat:@"%@/convertInvitation%@", kApiaryRestBaseUrl,
254296
FIRDynamicLinkAPIKeyParameter(_APIKey)];
@@ -270,7 +312,7 @@ - (void)sendRequestWithBaseURLString:(NSString *)baseURL
270312
stringWithFormat:@"%@/%@%@", baseURL, endpointPath, FIRDynamicLinkAPIKeyParameter(_APIKey)];
271313

272314
FIRNetworkRequestCompletionHandler completeInvitationByDeviceCallback =
273-
^(NSData *data, NSError *error) {
315+
^(NSData *data, NSURLResponse *response, NSError *error) {
274316
if (error || !data) {
275317
dispatch_async(dispatch_get_main_queue(), ^{
276318
handler(nil, nil, error);

FirebaseDynamicLinks/Sources/FIRDynamicLinks.m

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,10 @@ - (nullable FIRDynamicLink *)dynamicLinkFromCustomSchemeURL:(NSURL *)url {
397397
return nil;
398398
}
399399

400-
- (nullable FIRDynamicLink *)dynamicLinkFromUniversalLinkURL:(NSURL *)url {
400+
- (nullable FIRDynamicLink *)
401+
dynamicLinkInternalFromUniversalLinkURL:(NSURL *)url
402+
completion:
403+
(nullable FIRDynamicLinkUniversalLinkHandler)completion {
401404
if ([self canParseUniversalLinkURL:url]) {
402405
if (url.query.length > 0) {
403406
NSDictionary *parameters = FIRDLDictionaryFromQuery(url.query);
@@ -414,8 +417,10 @@ - (nullable FIRDynamicLink *)dynamicLinkFromUniversalLinkURL:(NSURL *)url {
414417
[self.dynamicLinkNetworking
415418
resolveShortLink:url
416419
FDLSDKVersion:FIRFirebaseVersion()
417-
completion:^(NSURL *_Nullable resolverURL, NSError *_Nullable resolverError){
418-
// Nothing to do
420+
completion:^(NSURL *_Nullable resolverURL, NSError *_Nullable resolverError) {
421+
if (completion) {
422+
completion(dynamicLink, resolverError);
423+
}
419424
}];
420425
#ifdef GIN_SCION_LOGGING
421426
FIRDLLogEventToScion(FIRDLLogEventAppOpen, parameters[kFIRDLParameterSource],
@@ -427,9 +432,21 @@ - (nullable FIRDynamicLink *)dynamicLinkFromUniversalLinkURL:(NSURL *)url {
427432
}
428433
}
429434
}
435+
if (completion) {
436+
completion(nil, nil);
437+
}
430438
return nil;
431439
}
432440

441+
- (nullable FIRDynamicLink *)dynamicLinkFromUniversalLinkURL:(NSURL *)url {
442+
return [self dynamicLinkInternalFromUniversalLinkURL:url completion:nil];
443+
}
444+
445+
- (void)dynamicLinkFromUniversalLinkURL:(NSURL *)url
446+
completion:(FIRDynamicLinkUniversalLinkHandler)completion {
447+
[self dynamicLinkInternalFromUniversalLinkURL:url completion:completion];
448+
}
449+
433450
- (BOOL)handleUniversalLink:(NSURL *)universalLinkURL
434451
completion:(FIRDynamicLinkUniversalLinkHandler)completion {
435452
if ([self matchesShortLinkFormat:universalLinkURL]) {
@@ -448,14 +465,12 @@ - (BOOL)handleUniversalLink:(NSURL *)universalLinkURL
448465
}];
449466
return YES;
450467
} else {
451-
FIRDynamicLink *dynamicLink = [self dynamicLinkFromUniversalLinkURL:universalLinkURL];
452-
if (dynamicLink) {
453-
completion(dynamicLink, nil);
454-
return YES;
455-
}
468+
[self dynamicLinkFromUniversalLinkURL:universalLinkURL completion:completion];
469+
BOOL canHandleUniversalLink =
470+
[self canParseUniversalLinkURL:universalLinkURL] && universalLinkURL.query.length > 0 &&
471+
FIRDLDictionaryFromQuery(universalLinkURL.query)[kFIRDLParameterLink];
472+
return canHandleUniversalLink;
456473
}
457-
458-
return NO;
459474
}
460475

461476
- (void)resolveShortLink:(NSURL *)url completion:(FIRDynamicLinkResolverHandler)completion {

FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,21 @@ NS_SWIFT_NAME(DynamicLinks)
6767
- (nullable FIRDynamicLink *)dynamicLinkFromCustomSchemeURL:(NSURL *)url
6868
NS_SWIFT_NAME(dynamicLink(fromCustomSchemeURL:));
6969

70+
/**
71+
* @method dynamicLinkFromUniversalLinkURL:completion:
72+
* @abstract Get a Dynamic Link from a universal link URL. This method parses universal link
73+
* URLs, for instance,
74+
* "https://example.page.link?link=https://www.google.com&ibi=com.google.app&ius=comgoogleapp".
75+
* It is suggested to call it inside your |UIApplicationDelegate|'s
76+
* |application:continueUserActivity:restorationHandler:| method.
77+
* @param url Custom scheme URL.
78+
* @param completion A block that handles the outcome of attempting to get a Dynamic Link from a
79+
* universal link URL.
80+
*/
81+
- (void)dynamicLinkFromUniversalLinkURL:(NSURL *)url
82+
completion:(FIRDynamicLinkUniversalLinkHandler)completion
83+
NS_SWIFT_NAME(dynamicLink(fromUniversalLink:completion:));
84+
7085
/**
7186
* @method dynamicLinkFromUniversalLinkURL:
7287
* @abstract Get a Dynamic Link from a universal link URL. This method parses universal link
@@ -78,12 +93,12 @@ NS_SWIFT_NAME(DynamicLinks)
7893
* @return Dynamic Link object if the URL is valid and has link parameter, otherwise nil.
7994
*/
8095
- (nullable FIRDynamicLink *)dynamicLinkFromUniversalLinkURL:(NSURL *)url
81-
NS_SWIFT_NAME(dynamicLink(fromUniversalLink:));
96+
NS_SWIFT_NAME(dynamicLink(fromUniversalLink:))
97+
DEPRECATED_MSG_ATTRIBUTE("Use dynamicLinkFromUniversalLinkURL:completion: instead.");
8298

8399
/**
84100
* @method handleUniversalLink:completion:
85-
* @abstract Convenience method to handle a Universal Link whether it is long or short. A long link
86-
* will call the handler immediately, but a short link may not.
101+
* @abstract Convenience method to handle a Universal Link whether it is long or short.
87102
* @param url A Universal Link URL.
88103
* @param completion A block that handles the outcome of attempting to create a FIRDynamicLink.
89104
* @return YES if FIRDynamicLinks is handling the link, otherwise, NO.

FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkNetworkingTests.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ - (void)testResolveShortLinkServiceCompletionDoesntCrashWhenNilDataIsRetrieved {
7373
void (^executeRequestBlock)(id, NSDictionary *, NSString *, FIRNetworkRequestCompletionHandler) =
7474
^(id p1, NSDictionary *requestBody, NSString *requestURLString,
7575
FIRNetworkRequestCompletionHandler handler) {
76-
handler(nil, nil);
76+
handler(nil, nil, nil);
7777
};
7878

7979
SEL executeRequestSelector = @selector(executeOnePlatformRequest:forURL:completionHandler:);

0 commit comments

Comments
 (0)