Skip to content

Commit 36b79e6

Browse files
dmandarryanwilson
authored andcommitted
Move to domainURIPrefix for FIRDynamicLinkComponents (#2119)
* Revert "Revert premature api changes (#2097)" The new API is optional and current API is fully supported. This reverts commit 46cb564. * Update comments to reflect API changes. * Mark the FDLURLComponents initializer return as nullable. * Run Style. * Allow for new initializer for FIRDynamicLinkComponents to have a nullable instancetype return. * Update Changelog for v3.3.0 * Keep deprecated method initalization separate. * Comments updates and other minor fixes. * Consider domainURIPrefixes for exact matches with incoming short/long URLs. * Add warning for deprecated API if developer passes in a domain with a scheme.
1 parent 9d07038 commit 36b79e6

File tree

14 files changed

+383
-50
lines changed

14 files changed

+383
-50
lines changed

Example/DynamicLinks/App/iOS/DL-Info.plist

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,11 @@
5050
<string>UIInterfaceOrientationLandscapeLeft</string>
5151
<string>UIInterfaceOrientationLandscapeRight</string>
5252
</array>
53+
<key>FirebaseDynamicLinksCustomDomains</key>
54+
<array>
55+
<string>https://google.com</string>
56+
<string>https://google.com/one/</string>
57+
<string>https://a.firebase.com/mypath</string>
58+
</array>
5359
</dict>
5460
</plist>

Example/DynamicLinks/FDLBuilderTestAppObjC/Info.plist

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>en</string>
7+
<key>CFBundleExecutable</key>
8+
<string>$(EXECUTABLE_NAME)</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundleName</key>
14+
<string>$(PRODUCT_NAME)</string>
15+
<key>CFBundlePackageType</key>
16+
<string>APPL</string>
17+
<key>CFBundleShortVersionString</key>
18+
<string>1.0</string>
519
<key>CFBundleURLTypes</key>
620
<array>
721
<dict>
@@ -55,22 +69,22 @@
5569
</array>
5670
</dict>
5771
</array>
58-
<key>CFBundleDevelopmentRegion</key>
59-
<string>en</string>
60-
<key>CFBundleExecutable</key>
61-
<string>$(EXECUTABLE_NAME)</string>
62-
<key>CFBundleIdentifier</key>
63-
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
64-
<key>CFBundleInfoDictionaryVersion</key>
65-
<string>6.0</string>
66-
<key>CFBundleName</key>
67-
<string>$(PRODUCT_NAME)</string>
68-
<key>CFBundlePackageType</key>
69-
<string>APPL</string>
70-
<key>CFBundleShortVersionString</key>
71-
<string>1.0</string>
7272
<key>CFBundleVersion</key>
7373
<string>1</string>
74+
<key>FirebaseDynamicLinksCustomDomains</key>
75+
<array>
76+
<string>https://mydomain.com</string>
77+
<string>https://mydomain2.com</string>
78+
<string>https://google.com</string>
79+
<string>https://google.com</string>
80+
<string>google</string>
81+
<string>mydomain.com</string>
82+
<string>https://mydomain</string>
83+
<string>https://mydomain3.com</string>
84+
<string>https://google.com/one</string>
85+
<string>https://custom.com/one/two</string>
86+
<string>https://custom1.com/one/</string>
87+
</array>
7488
<key>LSRequiresIPhoneOS</key>
7589
<true/>
7690
<key>UILaunchStoryboardName</key>

Example/DynamicLinks/FDLBuilderTestAppObjC/ViewController.m

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ - (void)_initDefaultValues {
155155
},
156156
// The default value of domain appcode belongs to project: app-invites-qa
157157
@{
158-
@"id" : @"domain",
159-
@"label" : @"App domain (required)",
160-
@"defaultValue" : @"testfdl.page.link",
158+
@"id" : @"domainURIPrefix",
159+
@"label" : @"App domainURIPrefix (required)",
160+
@"defaultValue" : @"https://testfdl.page.link",
161161
},
162162
// analytics params
163163
@{
@@ -289,7 +289,8 @@ - (void)_initDefaultValues {
289289
- (void)_buildFDLLink {
290290
NSURL *link = [NSURL URLWithString:_paramValues[@"linkString"]];
291291
FIRDynamicLinkComponents *components =
292-
[FIRDynamicLinkComponents componentsWithLink:link domain:_paramValues[@"domain"]];
292+
[FIRDynamicLinkComponents componentsWithLink:link
293+
domainURIPrefix:_paramValues[@"https://domain"]];
293294

294295
FIRDynamicLinkGoogleAnalyticsParameters *analyticsParams =
295296
[FIRDynamicLinkGoogleAnalyticsParameters

Example/DynamicLinks/FDLBuilderTestAppObjCTests/Info.plist

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,24 @@
1818
<string>1.0</string>
1919
<key>CFBundleVersion</key>
2020
<string>1</string>
21+
<key>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
22+
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
23+
&lt;plist version=&quot;1.0&quot;&gt;
24+
&lt;array&gt;
25+
&lt;string&gt;https://mydomain.com&lt;/string&gt;
26+
&lt;string&gt;https://mydomain2.com&lt;/string&gt;
27+
&lt;string&gt;https://google.com&lt;/string&gt;
28+
&lt;string&gt;https://google.com&lt;/string&gt;
29+
&lt;string&gt;go&lt;/string&gt;
30+
&lt;string&gt;g.co&lt;/string&gt;
31+
&lt;string&gt;https://go&lt;/string&gt;
32+
&lt;string&gt;https://g.co&lt;/string&gt;
33+
&lt;string&gt;https://google.com/one&lt;/string&gt;
34+
&lt;string&gt;https://custom.com/one/two&lt;/string&gt;
35+
&lt;string&gt;https://custom1.com/one/&lt;/string&gt;
36+
&lt;/array&gt;
37+
&lt;/plist&gt;
38+
</key>
39+
<string></string>
2140
</dict>
2241
</plist>

Example/DynamicLinks/Tests/FDLURLComponentsTests.m

Lines changed: 103 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121

2222
#import <OCMock/OCMock.h>
2323

24-
static NSString *const kFDLURLDomain = @"xyz.page.link";
24+
static NSString *const kFDLURLDomain = @"https://xyz.page.link";
25+
static NSString *const kFDLURLCustomDomain = @"https://foo.com/path";
2526

2627
@interface FDLURLComponentsTests : XCTestCase
2728
@end
@@ -461,14 +462,14 @@ - (void)testLinkOptionsParamsPropertiesSetProperly {
461462

462463
- (void)testFDLComponentsFactoryReturnsInstanceOfCorrectClass {
463464
NSURL *link = [NSURL URLWithString:@"https://google.com"];
464-
id returnValue = [FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
465+
id returnValue = [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
465466
XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkComponents class]]);
466467
}
467468

468469
- (void)testFDLComponentsFactoryReturnsInstanceWithAllNilProperties {
469470
NSURL *link = [NSURL URLWithString:@"https://google.com"];
470471
FIRDynamicLinkComponents *components =
471-
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
472+
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
472473

473474
XCTAssertNil(components.analyticsParameters);
474475
XCTAssertNil(components.socialMetaTagParameters);
@@ -484,11 +485,27 @@ - (void)testFDLComponentsCreatesSimplestLinkCorrectly {
484485
NSURL *link = [NSURL URLWithString:linkString];
485486

486487
NSString *expectedURLString =
487-
[NSString stringWithFormat:@"https://%@/?link=%@", kFDLURLDomain, endcodedLinkString];
488+
[NSString stringWithFormat:@"%@/?link=%@", kFDLURLDomain, endcodedLinkString];
488489
NSURL *expectedURL = [NSURL URLWithString:expectedURLString];
489490

490491
FIRDynamicLinkComponents *components =
491-
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
492+
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
493+
NSURL *actualURL = components.url;
494+
495+
XCTAssertEqualObjects(actualURL, expectedURL);
496+
}
497+
498+
- (void)testFDLComponentsCustomDomainWithPath {
499+
NSString *linkString = @"https://google.com";
500+
NSString *endcodedLinkString = @"https%3A%2F%2Fgoogle%2Ecom";
501+
NSURL *link = [NSURL URLWithString:linkString];
502+
503+
NSString *expectedURLString =
504+
[NSString stringWithFormat:@"%@/?link=%@", kFDLURLCustomDomain, endcodedLinkString];
505+
NSURL *expectedURL = [NSURL URLWithString:expectedURLString];
506+
507+
FIRDynamicLinkComponents *components =
508+
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLCustomDomain];
492509
NSURL *actualURL = components.url;
493510

494511
XCTAssertEqualObjects(actualURL, expectedURL);
@@ -499,7 +516,8 @@ - (void)testFDLComponentsFailsOnMalformedDomain {
499516
NSURL *link = [NSURL URLWithString:linkString];
500517

501518
FIRDynamicLinkComponents *components =
502-
[FIRDynamicLinkComponents componentsWithLink:link domain:@"this is invalid domain"];
519+
[FIRDynamicLinkComponents componentsWithLink:link
520+
domainURIPrefix:@"this is invalid domain URI Prefix"];
503521

504522
XCTAssertNil(components.url);
505523
}
@@ -553,7 +571,7 @@ - (void)testFDLComponentsCreatesFullLinkCorrectly {
553571

554572
NSURL *link = [NSURL URLWithString:@"https://google.com"];
555573
FIRDynamicLinkComponents *fdlComponents =
556-
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
574+
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
557575
fdlComponents.analyticsParameters = analyticsParams;
558576
fdlComponents.iOSParameters = iosParams;
559577
fdlComponents.iTunesConnectParameters = itcParams;
@@ -642,7 +660,80 @@ - (void)testShortenURL {
642660
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
643661
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
644662
FIRDynamicLinkComponents *components =
645-
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
663+
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
664+
[components
665+
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
666+
NSError *_Nullable error) {
667+
XCTAssertEqualObjects(shortURL.absoluteString, shortURLString);
668+
[expectation fulfill];
669+
}];
670+
[self waitForExpectationsWithTimeout:0.1 handler:nil];
671+
672+
[keyProviderClassMock verify];
673+
[keyProviderClassMock stopMocking];
674+
[componentsClassMock verify];
675+
[componentsClassMock stopMocking];
676+
}
677+
678+
- (void)testDeprecatedMethodComponentsWithLinkForDomain {
679+
NSString *shortURLString = @"https://xyz.page.link/abcd";
680+
681+
// Mock key provider
682+
id keyProviderClassMock = OCMClassMock([FIRDynamicLinkComponentsKeyProvider class]);
683+
[[[keyProviderClassMock expect] andReturn:@"fake-api-key"] APIKey];
684+
685+
id componentsClassMock = OCMClassMock([FIRDynamicLinkComponents class]);
686+
[[componentsClassMock expect]
687+
sendHTTPRequest:OCMOCK_ANY
688+
completion:[OCMArg checkWithBlock:^BOOL(id obj) {
689+
void (^completion)(NSData *_Nullable, NSError *_Nullable) = obj;
690+
NSDictionary *JSON = @{@"shortLink" : shortURLString};
691+
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:0];
692+
completion(JSONData, nil);
693+
return YES;
694+
}]];
695+
696+
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
697+
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
698+
FIRDynamicLinkComponents *components =
699+
[FIRDynamicLinkComponents componentsWithLink:link domain:@"xyz.page.link"];
700+
[components
701+
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
702+
NSError *_Nullable error) {
703+
XCTAssertEqualObjects(shortURL.absoluteString, shortURLString);
704+
[expectation fulfill];
705+
}];
706+
[self waitForExpectationsWithTimeout:0.1 handler:nil];
707+
708+
[keyProviderClassMock verify];
709+
[keyProviderClassMock stopMocking];
710+
[componentsClassMock verify];
711+
[componentsClassMock stopMocking];
712+
}
713+
714+
- (void)testDeprecatedMethodComponentsWithLinkForDomainWithInvalidDomainScheme {
715+
NSString *shortURLString = @"https://xyz.page.link/abcd";
716+
717+
// Mock key provider
718+
id keyProviderClassMock = OCMClassMock([FIRDynamicLinkComponentsKeyProvider class]);
719+
[[[keyProviderClassMock expect] andReturn:@"fake-api-key"] APIKey];
720+
721+
id componentsClassMock = OCMClassMock([FIRDynamicLinkComponents class]);
722+
[[componentsClassMock expect]
723+
sendHTTPRequest:OCMOCK_ANY
724+
completion:[OCMArg checkWithBlock:^BOOL(id obj) {
725+
void (^completion)(NSData *_Nullable, NSError *_Nullable) = obj;
726+
NSDictionary *JSON = @{@"shortLink" : shortURLString};
727+
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:0];
728+
completion(JSONData, nil);
729+
return YES;
730+
}]];
731+
732+
XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"];
733+
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
734+
FIRDynamicLinkComponents *components =
735+
[FIRDynamicLinkComponents componentsWithLink:link domain:@"http://xyz.page.link"];
736+
XCTAssertNotNil(components);
646737
[components
647738
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
648739
NSError *_Nullable error) {
@@ -679,7 +770,7 @@ - (void)testShortenURLReturnsErrorWhenAPIKeyMissing {
679770
[self expectationWithDescription:@"completion called with error"];
680771
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
681772
FIRDynamicLinkComponents *components =
682-
[FIRDynamicLinkComponents componentsWithLink:link domain:kFDLURLDomain];
773+
[FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain];
683774
[components
684775
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
685776
NSError *_Nullable error) {
@@ -714,20 +805,11 @@ - (void)testShortenURLReturnsErrorWhenDomainIsMalformed {
714805
return YES;
715806
}]];
716807

717-
XCTestExpectation *expectation =
718-
[self expectationWithDescription:@"completion called with error"];
719808
NSURL *link = [NSURL URLWithString:@"https://google.com/abc"];
720809
FIRDynamicLinkComponents *components =
721-
[FIRDynamicLinkComponents componentsWithLink:link domain:@"this is invalid domain"];
722-
[components
723-
shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray<NSString *> *_Nullable warnings,
724-
NSError *_Nullable error) {
725-
XCTAssertNil(shortURL);
726-
if (error) {
727-
[expectation fulfill];
728-
}
729-
}];
730-
[self waitForExpectationsWithTimeout:0.1 handler:nil];
810+
[FIRDynamicLinkComponents componentsWithLink:link
811+
domainURIPrefix:@"this is invalid domain URI Prefix"];
812+
XCTAssertNil(components);
731813

732814
[keyProviderClassMock verify];
733815
[keyProviderClassMock stopMocking];

Example/DynamicLinks/Tests/FIRDynamicLinkNetworkingTests.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#import <XCTest/XCTest.h>
1818

19-
#import "OCMock.h"
19+
#import <OCMock/OCMock.h>
2020

2121
#import <GoogleUtilities/GULSwizzler.h>
2222
#import "DynamicLinks/FIRDynamicLinkNetworking+Private.h"

Example/DynamicLinks/Tests/FIRDynamicLinksTest.m

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ @implementation FIRDynamicLinksTest
161161

162162
- (void)setUp {
163163
[super setUp];
164+
if (!(FIRApp.defaultApp)) {
165+
[FIRApp configure];
166+
}
164167
self.service = [[FIRDynamicLinks alloc] init];
165168
self.userDefaults = [[NSUserDefaults alloc] init];
166169
[self.userDefaults removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
@@ -223,7 +226,6 @@ - (void)testURLScheme_MinimumParameters {
223226
}
224227

225228
- (void)testFactoryMethodReturnsProperClassObject {
226-
[FIRApp configure];
227229
id service = [FIRDynamicLinks dynamicLinks];
228230

229231
XCTAssertNotNil(service, @"Factory method returned nil");
@@ -1015,6 +1017,61 @@ - (void)testSelfDiagnoseCompletionCalled {
10151017
[self waitForExpectationsWithTimeout:2.0 handler:nil];
10161018
}
10171019

1020+
#pragma mark - Custom domain tests
1021+
- (void)testValidCustomDomainNames {
1022+
// Entries in plist file:
1023+
// https://google.com
1024+
// https://google.com/one
1025+
// https://a.firebase.com/mypath
1026+
1027+
NSArray<NSString *> *urlStrings = @[
1028+
@"https://google.com/mylink", // Short FDL starting with 'https://google.com'
1029+
@"https://google.com/one", // Short FDL starting with 'https://google.com'
1030+
@"https://google.com?link=abcd", // Long FDL starting with 'https://google.com'
1031+
@"https://google.com/one/mylink", // Long FDL starting with 'https://google.com/one'
1032+
@"https://a.firebase.com/mypath/mylink", // Short FDL starting https://a.firebase.com/mypath
1033+
@"https://a.firebase.com/mypath?link=abcd&test=1", // Long FDL starting with
1034+
// https://a.firebase.com/mypath
1035+
];
1036+
1037+
for (NSString *urlString in urlStrings) {
1038+
NSURL *url = [NSURL URLWithString:urlString];
1039+
BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url];
1040+
1041+
XCTAssertTrue(matchesShortLinkFormat,
1042+
@"Non-DDL domain URL matched short link format with URL: %@", url);
1043+
}
1044+
}
1045+
1046+
- (void)testInvalidCustomDomainNames {
1047+
// Entries in plist file:
1048+
// https://google.com
1049+
// https://google.com/one
1050+
// https://a.firebase.com/mypath
1051+
1052+
NSArray<NSString *> *urlStrings = @[
1053+
@"google.com", // Valid domain. No scheme.
1054+
@"https://google.com", // Valid domain. No path after domainURIPrefix.
1055+
@"https://google.com/", // Valid domain. No path after domainURIPrefix.
1056+
@"https://google.com/one/", // Valid domain. No path after domainURIPrefix.
1057+
@"https://google.com/one/two/mylink", // domainURIPrefix not exact match.
1058+
@"https://google.co.in/mylink", // No matching domainURIPrefix.
1059+
@"https://firebase.com/mypath", // No matching domainURIPrefix: Invalid (sub)domain.
1060+
@"https://b.firebase.com/mypath", // No matching domainURIPrefix: Invalid subdomain.
1061+
@"https://a.firebase.com/mypathabc", // No matching domainURIPrefix: Invalid subdomain.
1062+
@"mydomain.com", // https scheme not specified for domainURIPrefix.
1063+
@"http://mydomain", // Domain not in plist. No path after domainURIPrefix.
1064+
];
1065+
1066+
for (NSString *urlString in urlStrings) {
1067+
NSURL *url = [NSURL URLWithString:urlString];
1068+
BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url];
1069+
1070+
XCTAssertFalse(matchesShortLinkFormat,
1071+
@"Non-DDL domain URL matched short link format with URL: %@", url);
1072+
}
1073+
}
1074+
10181075
#pragma mark - Private Helpers
10191076

10201077
- (void)removeAllFIRApps {

0 commit comments

Comments
 (0)