From 457d448699d3697d239749aacf62b4d6665e05b5 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 11:46:05 -0400 Subject: [PATCH 01/16] [DynamicLinks] Delete source --- FirebaseDynamicLinks/CHANGELOG.md | 200 -- FirebaseDynamicLinks/README.md | 40 - .../FDLURLComponents+Private.h | 67 - .../FDLURLComponents/FDLURLComponents.m | 700 ------- .../FIRDynamicLinkComponentsKeyProvider.h | 23 - .../FIRDynamicLinkComponentsKeyProvider.m | 39 - .../Sources/FIRDLDefaultRetrievalProcessV2.h | 41 - .../Sources/FIRDLDefaultRetrievalProcessV2.m | 256 --- .../Sources/FIRDLJavaScriptExecutor.h | 38 - .../Sources/FIRDLJavaScriptExecutor.m | 174 -- .../Sources/FIRDLRetrievalProcessFactory.h | 39 - .../Sources/FIRDLRetrievalProcessFactory.m | 61 - .../Sources/FIRDLRetrievalProcessProtocols.h | 39 - .../FIRDLRetrievalProcessResult+Private.h | 30 - .../Sources/FIRDLRetrievalProcessResult.h | 38 - .../Sources/FIRDLRetrievalProcessResult.m | 65 - .../Sources/FIRDLScionLogging.h | 45 - .../Sources/FIRDLScionLogging.m | 59 - .../Sources/FIRDynamicLink+Private.h | 52 - FirebaseDynamicLinks/Sources/FIRDynamicLink.m | 153 -- .../FIRDynamicLinkNetworking+Private.h | 49 - .../Sources/FIRDynamicLinkNetworking.h | 133 -- .../Sources/FIRDynamicLinkNetworking.m | 369 ---- .../Sources/FIRDynamicLinks+FirstParty.h | 122 -- .../Sources/FIRDynamicLinks+Private.h | 55 - .../Sources/FIRDynamicLinks.m | 805 -------- .../Sources/GINInvocation/GINArgument.h | 52 - .../Sources/GINInvocation/GINArgument.m | 84 - .../Sources/GINInvocation/GINInvocation.h | 71 - .../Sources/GINInvocation/GINInvocation.m | 98 - .../Sources/Logging/FDLLogging.h | 48 - .../Sources/Logging/FDLLogging.m | 73 - .../FirebaseDynamicLinks/FDLURLComponents.h | 560 ------ .../FirebaseDynamicLinks/FIRDynamicLink.h | 90 - .../FirebaseDynamicLinks/FIRDynamicLinks.h | 147 -- .../FIRDynamicLinksCommon.h | 41 - .../FirebaseDynamicLinks.h | 20 - .../Sources/Resources/PrivacyInfo.xcprivacy | 46 - .../Utilities/FDLDeviceHeuristicsHelper.h | 33 - .../Utilities/FDLDeviceHeuristicsHelper.m | 43 - .../Sources/Utilities/FDLUtilities.h | 148 -- .../Sources/Utilities/FDLUtilities.m | 368 ---- .../project.pbxproj | 442 ---- .../FDLBuilderTestAppObjC/AppDelegate.h | 23 - .../FDLBuilderTestAppObjC/AppDelegate.m | 103 - .../AppIcon.appiconset/Contents.json | 98 - .../Assets.xcassets/Contents.json | 6 - .../Base.lproj/LaunchScreen.storyboard | 25 - .../Base.lproj/Main.storyboard | 26 - .../FDLBuilderTestAppObjC.entitlements | 20 - .../Sample/FDLBuilderTestAppObjC/Info.plist | 83 - .../FDLBuilderTestAppObjC/LinkTableViewCell.h | 23 - .../FDLBuilderTestAppObjC/LinkTableViewCell.m | 69 - .../ParamTableViewCell.h | 33 - .../ParamTableViewCell.m | 82 - .../FDLBuilderTestAppObjC/SceneDelegate.h | 23 - .../FDLBuilderTestAppObjC/SceneDelegate.m | 108 - .../FDLBuilderTestAppObjC/ViewController.h | 21 - .../FDLBuilderTestAppObjC/ViewController.m | 399 ---- .../Tests/Sample/FDLBuilderTestAppObjC/main.m | 27 - FirebaseDynamicLinks/Tests/Sample/Podfile | 11 - FirebaseDynamicLinks/Tests/Unit/DL-Info.plist | 56 - .../Tests/Unit/FDLURLComponentsTests.m | 779 ------- .../Tests/Unit/FIRDLScionLoggingTest.m | 182 -- .../Unit/FIRDynamicLinkNetworkingTests.m | 100 - .../Tests/Unit/FIRDynamicLinkTest.m | 79 - .../Tests/Unit/FIRDynamicLinksImportsTest3P.m | 33 - .../Tests/Unit/FIRDynamicLinksTest.m | 1787 ----------------- .../Tests/Unit/UtilitiesTests.m | 198 -- 69 files changed, 10450 deletions(-) delete mode 100644 FirebaseDynamicLinks/CHANGELOG.md delete mode 100644 FirebaseDynamicLinks/README.md delete mode 100644 FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h delete mode 100644 FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents.m delete mode 100644 FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h delete mode 100644 FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessProtocols.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult+Private.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLScionLogging.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDLScionLogging.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLink.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking+Private.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.m delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLinks+FirstParty.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLinks+Private.h delete mode 100644 FirebaseDynamicLinks/Sources/FIRDynamicLinks.m delete mode 100644 FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.h delete mode 100644 FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.m delete mode 100644 FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.h delete mode 100644 FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.m delete mode 100644 FirebaseDynamicLinks/Sources/Logging/FDLLogging.h delete mode 100644 FirebaseDynamicLinks/Sources/Logging/FDLLogging.m delete mode 100644 FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FDLURLComponents.h delete mode 100644 FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLink.h delete mode 100644 FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h delete mode 100644 FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinksCommon.h delete mode 100755 FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FirebaseDynamicLinks.h delete mode 100644 FirebaseDynamicLinks/Sources/Resources/PrivacyInfo.xcprivacy delete mode 100644 FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.h delete mode 100644 FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.m delete mode 100644 FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h delete mode 100644 FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.m delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC.xcodeproj/project.pbxproj delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.h delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.m delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/Contents.json delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/LaunchScreen.storyboard delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/Main.storyboard delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/FDLBuilderTestAppObjC.entitlements delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Info.plist delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.h delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.m delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.h delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.m delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.h delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.m delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.h delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.m delete mode 100644 FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/main.m delete mode 100644 FirebaseDynamicLinks/Tests/Sample/Podfile delete mode 100644 FirebaseDynamicLinks/Tests/Unit/DL-Info.plist delete mode 100644 FirebaseDynamicLinks/Tests/Unit/FDLURLComponentsTests.m delete mode 100644 FirebaseDynamicLinks/Tests/Unit/FIRDLScionLoggingTest.m delete mode 100644 FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkNetworkingTests.m delete mode 100644 FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkTest.m delete mode 100644 FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksImportsTest3P.m delete mode 100644 FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksTest.m delete mode 100644 FirebaseDynamicLinks/Tests/Unit/UtilitiesTests.m diff --git a/FirebaseDynamicLinks/CHANGELOG.md b/FirebaseDynamicLinks/CHANGELOG.md deleted file mode 100644 index 6983b145e35..00000000000 --- a/FirebaseDynamicLinks/CHANGELOG.md +++ /dev/null @@ -1,200 +0,0 @@ -# 11.8.0 -- [deprecated] The `FirebaseDynamicLinks` CocoaPod is deprecated. For information about timelines and alternatives, see the [Dynamic Links deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq). - -# 10.27.0 -- [deprecated] Dynamic Links is deprecated. For information about timelines and alternatives, see the [Dynamic Links deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq) - -# 10.3.0 -- [fixed] Fixes issue where `utmParametersDictionary` / `minimumAppVersion` were not provided and their value were set to `[NSNull null]` instead of `nil`. - -# 10.2.0 -- [fixed] Fixes utm parameters not being returned to dynamic link when using universal links (#10341) - -# 10.0.0 -- [removed] Removed bare initializer from `DynamicLink`. (#10000) -- [fixed] Added app.google (1p domain) support in FDL SDK which was missing. - -# 9.0.0 -- [fixed] Fixed async/await crash when retrieving a dynamic link from a universal link fails. (#9612) - -# 8.15.0 -- [fixed] Fixed Custom domain long url validation logic. (#6978) - -# 8.9.0 -- [fixed] Fixed Shortlink regression involving underscores and dashes introduced in 8.8.0. (#8786) -- [fixed] Reduce memory stress on `WebKit` API. (#8847) -- [fixed] Fixed regression introduced in 8.8.0 that failed to accept link query params after the - FDL domain prefix. It caused the Dynamic Links Quick Start to fail. (#8866) - -# 8.8.0 -- [fixed] Firebase dynamic links with custom domain will only work if the custom domain has a trailing '/'. (#7087) -- [fixed] Fix device-only build warning for unused `processIsTranslated` function. (#8694) - -# 8.7.0 -- [added] Refactoring and adding helper class. (#8432) - -# 8.6.0 -- [changed] Replaced conditionally-compiled APIs with `API_UNAVAILABLE` annotations on unsupported platforms (#8467). - -# 8.4.0 -- [fixed] Fixed build issues introduced in Xcode 13 beta 3. (#8401) -- [fixed] Fixed build failures for extension targets. (#6548) - -# 8.2.0 -- [fixed] Fixed analyze issue introduced in Xcode 12.5. (#8208) - -# 8.0.0 -- [fixed] Fixed crashes on simulators targeting below iOS14 on Apple Silicon. (#7989) - -# 7.7.0 -- [added] Added `utmParametersDictionary` property to `DynamicLink`. (#6730) - -# 7.6.0 -- [fixed] Fixed build warnings introduced with Xcode 12.5. (#7434) - -# 7.3.1 -- [fixed] New callback added in 7.3.0 should be on the main thread. (#7159) - -# 7.3.0 -- [added] Manually created dynamic links should be subject to allowed/blocked check (#5853) - -# 4.3.1 -- [changed] Client id usage in api call and respective checks in the code. -- [fixed] Fix attempts to connect to invalid ipv6 domain by updating ipv4 and ipv6 to use a single, valid endpoint (#5032) - -# 4.3.0 -- [changed] Functionally neutral public header refactor to enable Swift Package - Manager support. - -# 4.2.1 -- [fixed]Check for Pending Dynamic link guard check logic - -# 4.2.0 -- [fixed] Fixed crashes that occur when a dynamic link is opened for the second time while an app is in the foreground (#5880) -- [Added] Plist property `FirebaseDeepLinkPasteboardRetrievalEnabled` to enable/disable fetching dynamic links from Pasteboard. -- [fixed] Reduce frequency of iOS14 pasteboard notifications by only reading from it when it contains URL(s). (#5905) -- [changed] Functionally neutral updated import references for dependencies. (#5824) - -Refer to the [README.md](https://github.com/firebase/firebase-ios-sdk/blob/main/FirebaseDynamicLinks/README.md) for more details about this release. - -# 4.1.0 -- [fixed] Fixing unwanted pending dynamic links checks on subsequent app restarts. (#5665) - -# 4.0.8 -- [fixed] Fix Catalyst build - removed deprecated unused Apple framework dependencies. (#5139) - -# 4.0.7 -- [fixed] Use module import syntax for headers from other SDKs. (#4824) - -# 4.0.6 -- [fixed] Fix component startup time. (#4137) -- [fixed] Fix crash due to object deallocation on app launch. (#4308) - -# 4.0.5 -- [fixed] Removed references to UIWebViewDelegate to comply with App Store Submission warning. (#3722) - -# 4.0.4 -- [fixed] Removed references to UIWebView to comply with App Store Submission warning. (#3722) - -# 4.0.3 -- [added] Added support for custom domains for internal Google apps. (#3540) - -# 4.0.2 -- [changed] Updated to maintain compatibility with Firebase Core in 6.6.0. - -# 4.0.1 -- [changed] Removed deprecated internal log method. (#3333) - -# 4.0 -- [feature] FirebaseAnalytics is no longer a hard dependency in the DynamicLinks pod. If you were installing Dynamic Links via pod ''Firebase/DynamicLinks'', you should add 'pod 'Firebase/Analytics'' to the Podfile to maintain full Dynamic Links functionality. If you previously have 'pod 'Firebase/Core'' in the Podfile, no change is necessary. (#2738) -- [removed] Remove deprecated API in FDLURLComponents. (#2768) - -# 3.4.3 -- [fixed] Fixed an issue where matchesshortlinkformat was returning true for certain FDL long links. - -# 3.4.2 -- [fixed] Fixes an issue with certain analytics attribution parameters not being recorded on an app install. (#2462) - -# 3.4.1 -- [changed] Return call validation for sysctlbyname. (#2394) - -# 3.4.0 -- [changed] Bug fixes and internal SDK changes. (#2238, #2220) - -# 3.3.0 -- [added] Introduced a new `componentsWithLink:domainURIPrefix:` and deprecated the existing `componentsWithLink:domain:`. (#1962, #2017, #2078, #2097, #2112) - -# 3.2.0 -- [changed] Delete deprecated source files. (#2038) - -# 3.1.1 -- [changed] Use c99 compatible __typeof__() operator. (#1982) - -# 3.1.0 -- [feature] Firebase Dynamic Links is now open source and delivered as a source pod. (#1842) - -# 3.0.2 -- [changed] Bug fixes. - -# 3.0.1 -- [fixed] Fixed issue where first app opens were getting double counted when using unique match. - -# 2.3.2 -- [fixed] Fixed error when fingerprint match fails for some locales. - -# 2.3.1 -- [fixed] Fixed race condition while processing server response(s). - -# 2.3.0 -- [added] Added new confidence type property. See FIRDLMatchType (values Unique, Default, Weak); -- [changed] Updates to self diagnostic output. - -# 2.2.0 -- [added] Added Other platform fallback link to FDL Builder API; - -# 2.1.0 -- [added] Added basic self diagnostic to identify Firebase Dynamic Links configuration issues. See method - [FIRDynamicLinks performDiagnosticsWithCompletion:]. -- [fixed] Fixed returning warning in Builder API, see warnings parameter in - FIRDynamicLinkShortenerCompletion block. - -# 2.0.0 -- [fixed] Change Swift API names to better align with Swift convention. -- [fixed] Fixes to pending link retrieval process, especially when custom URL schemes are not - set up properly. - -# 1.4.0 -- [added] Added Builder API to create and shorten dynamic links in iOS Apps. - -# 1.3.5 -- [changed] Minor update triggered by changes in Firebase Core libraries. - -# 1.3.4 -- [changed] Bug fixes - -# 1.3.3 -- [changed] Improved tracking of social media tag parameters in Dynamic Links - -# 1.3.2 -- [changed] Removes dependency on the Core Motion framework - -# 1.3.1 -- [added] Adds FIRLogger support (not public-facing) -- [fixed] Fixes IPv6 compatibility issues - -# 1.3.0 -- [changed] Removes the SFSafariViewController per Apple's Review Guidelines -- [changed] Removes dependency on the Core Location framework - -# 1.2.0 -- [added] iOS 10 Support - -# 1.1.1 -- [fixed] Fixes an issue where if resolveLink() API returned a non-JSON object, it - would cause a crash. - -# 1.1.0 -- [fixed] Greatly reduced SDK size. - -# 1.0.0 -- Initial public release. diff --git a/FirebaseDynamicLinks/README.md b/FirebaseDynamicLinks/README.md deleted file mode 100644 index b921229e91e..00000000000 --- a/FirebaseDynamicLinks/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Firebase Dynamic Links SDK for iOS - -> [!IMPORTANT] -> Firebase Dynamic Links is **deprecated** and should not be used in new projects. The service will shut down on August 25, 2025. -> -> Please see our [Dynamic Links Deprecation FAQ documentation](https://firebase.google.com/support/dynamic-links-faq) for more guidance. - -Firebase Dynamic Links are universal deep links that persist across app installs. -For more info, see the [Firebase website](https://firebase.google.com/products/dynamic-links). - -Please visit [our developer site](https://firebase.google.com/docs/dynamic-links/) for integration -instructions, documentations, support information, and terms of service. - -## Managing the Pasteboard - -Firebase Dynamic Links 4.2.0 and higher use a plist property -`FirebaseDeepLinkPasteboardRetrievalEnabled` that a developer can set to enable/disable the use of -iOS pasteboard by the SDK. - -FDL SDK uses the pasteboard for deep-linking post app install (to enable deferred deep-linking, -where the link is copied on the -[app preview page](https://firebase.google.com/docs/dynamic-links/link-previews#app_preview_pages)) -and app install attribution; otherwise, FDL does not use the pasteboard for anything else. - -Disabling pasteboard access affects the app in the following ways: -* Deferred deep-linking will not work as reliably. At best, your app receives -[weak matches](https://firebase.google.com/docs/reference/unity/namespace/firebase/dynamic-links#linkmatchstrength) -for deep-links. -* App install attribution stats will be less accurate (potentially undercounting app installs). - -Enabling pasteboard access affects the app in the following ways: -* On iOS 14, will show a system alert notifying that your app accessed the content in the -pasteboard. This should happen one-time after installation of the app. -* Deferred deep-linking will work as designed. At best, your app receives a -[perfect match](https://firebase.google.com/docs/reference/unity/namespace/firebase/dynamic-links#linkmatchstrength) -for deep-links. -* SDK will be able to more reliably attribute installation stats for links. - -For more information, check out the -[iOS documentation](https://firebase.google.com/docs/dynamic-links/ios/receive). diff --git a/FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h b/FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h deleted file mode 100644 index f418bfb7e79..00000000000 --- a/FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FDLURLComponents.h" - -/** - * Label exceptions from FDL. - */ -FOUNDATION_EXPORT NSString *_Nonnull const kFirebaseDurableDeepLinkErrorDomain; - -NS_ASSUME_NONNULL_BEGIN - -/// Each of the parameter classes used in FIRDynamicLinkURLComponents needs to be able to -/// provide a dictionary representation of itself to be codified into URL query parameters. This -/// protocol defines that behavior. -@protocol FDLDictionaryRepresenting -@required -@property(nonatomic, readonly) NSDictionary *dictionaryRepresentation; -@end - -@interface FIRDynamicLinkGoogleAnalyticsParameters () -@end - -@interface FIRDynamicLinkIOSParameters () -@end - -@interface FIRDynamicLinkItunesConnectAnalyticsParameters () -@end - -@interface FIRDynamicLinkAndroidParameters () -@end - -@interface FIRDynamicLinkSocialMetaTagParameters () -@end - -@interface FIRDynamicLinkNavigationInfoParameters () -@end - -@interface FIRDynamicLinkOtherPlatformParameters () -@end - -@interface FIRDynamicLinkComponents () - -/// Creates and returns a request based on the url and options. Exposed for testing. -+ (NSURLRequest *)shorteningRequestForLongURL:(NSURL *)url - options:(nullable FIRDynamicLinkComponentsOptions *)options; - -/// Sends an HTTP request using NSURLSession. Exposed for testing. -+ (void)sendHTTPRequest:(NSURLRequest *)request - completion:(void (^)(NSData *_Nullable data, NSError *_Nullable error))completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents.m b/FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents.m deleted file mode 100644 index 5a5ea1a3316..00000000000 --- a/FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents.m +++ /dev/null @@ -1,700 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import - -#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h" -#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h" -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FDLURLComponents.h" - -#import "FirebaseDynamicLinks/Sources/Logging/FDLLogging.h" -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -// Label exceptions from FDL. -NSString *const kFirebaseDurableDeepLinkErrorDomain = @"com.firebase.durabledeeplink"; - -/// The exact behavior of dict[key] = value is unclear when value is nil. This function safely adds -/// the key-value pair to the dictionary, even when value is nil. -/// This function will treat empty string in the same way as nil. -NS_INLINE void FDLSafelyAddKeyValuePairToDictionary(NSString *key, - NSString *stringValue, - NSMutableDictionary *dictionary) { - if (stringValue != nil && stringValue.length > 0) { - dictionary[key] = stringValue; - } else { - [dictionary removeObjectForKey:key]; - } -} - -@implementation FIRDynamicLinkGoogleAnalyticsParameters { - NSMutableDictionary *_dictionary; -} - -static NSString *const kFDLUTMSourceKey = @"utm_source"; -static NSString *const kFDLUTMMediumKey = @"utm_medium"; -static NSString *const kFDLUTMCampaignKey = @"utm_campaign"; -static NSString *const kFDLUTMTermKey = @"utm_term"; -static NSString *const kFDLUTMContentKey = @"utm_content"; - -+ (instancetype)parameters { - return [[self alloc] init]; -} - -+ (instancetype)parametersWithSource:(NSString *)source - medium:(NSString *)medium - campaign:(NSString *)campaign { - return [[self alloc] initWithSource:source medium:medium campaign:campaign]; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _dictionary = [NSMutableDictionary dictionary]; - } - return self; -} - -- (instancetype)initWithSource:(NSString *)source - medium:(NSString *)medium - campaign:(NSString *)campaign { - self = [self init]; - if (self) { - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMSourceKey, [source copy], _dictionary); - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMMediumKey, [medium copy], _dictionary); - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMCampaignKey, [campaign copy], _dictionary); - } - return self; -} - -- (void)setSource:(NSString *)source { - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMSourceKey, [source copy], _dictionary); -} - -- (NSString *)source { - return _dictionary[kFDLUTMSourceKey]; -} - -- (void)setMedium:(NSString *)medium { - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMMediumKey, [medium copy], _dictionary); -} - -- (NSString *)medium { - return _dictionary[kFDLUTMMediumKey]; -} - -- (void)setCampaign:(NSString *)campaign { - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMCampaignKey, [campaign copy], _dictionary); -} - -- (NSString *)campaign { - return _dictionary[kFDLUTMCampaignKey]; -} - -- (void)setTerm:(NSString *)term { - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMTermKey, [term copy], _dictionary); -} - -- (NSString *)term { - return _dictionary[kFDLUTMTermKey]; -} - -- (void)setContent:(NSString *)content { - FDLSafelyAddKeyValuePairToDictionary(kFDLUTMContentKey, [content copy], _dictionary); -} - -- (NSString *)content { - return _dictionary[kFDLUTMContentKey]; -} - -- (NSDictionary *)dictionaryRepresentation { - return [_dictionary copy]; -} - -@end - -@implementation FIRDynamicLinkIOSParameters { - NSMutableDictionary *_dictionary; -} - -static NSString *const kFDLIOSBundleIdentifierKey = @"ibi"; -static NSString *const kFDLIOSAppStoreIdentifierKey = @"isi"; -static NSString *const kFDLIOSFallbackURLKey = @"ifl"; -static NSString *const kFDLIOSCustomURLSchemeKey = @"ius"; -static NSString *const kFDLIOSMinimumVersionKey = @"imv"; -static NSString *const kFDLIOSIPadBundleIdentifierKey = @"ipbi"; -static NSString *const kFDLIOSIPadFallbackURLKey = @"ipfl"; - -+ (instancetype)parametersWithBundleID:(NSString *)bundleID { - return [[self alloc] initWithBundleID:bundleID]; -} - -- (instancetype)initWithBundleID:(NSString *)bundleID { - self = [super init]; - if (self) { - _dictionary = [NSMutableDictionary dictionary]; - FDLSafelyAddKeyValuePairToDictionary(kFDLIOSBundleIdentifierKey, [bundleID copy], _dictionary); - } - return self; -} - -- (NSString *)bundleID { - return _dictionary[kFDLIOSBundleIdentifierKey]; -} - -- (void)setAppStoreID:(NSString *)appStoreID { - FDLSafelyAddKeyValuePairToDictionary(kFDLIOSAppStoreIdentifierKey, [appStoreID copy], - _dictionary); -} - -- (NSString *)appStoreID { - return _dictionary[kFDLIOSAppStoreIdentifierKey]; -} - -- (void)setFallbackURL:(NSURL *)fallbackURL { - FDLSafelyAddKeyValuePairToDictionary(kFDLIOSFallbackURLKey, fallbackURL.absoluteString, - _dictionary); -} - -- (NSURL *)fallbackURL { - NSString *fallbackURLString = _dictionary[kFDLIOSFallbackURLKey]; - return fallbackURLString != nil ? [NSURL URLWithString:fallbackURLString] : nil; -} - -- (void)setCustomScheme:(NSString *)customScheme { - FDLSafelyAddKeyValuePairToDictionary(kFDLIOSCustomURLSchemeKey, [customScheme copy], _dictionary); -} - -- (NSString *)customScheme { - return _dictionary[kFDLIOSCustomURLSchemeKey]; -} - -- (void)setMinimumAppVersion:(NSString *)minimumAppVersion { - FDLSafelyAddKeyValuePairToDictionary(kFDLIOSMinimumVersionKey, [minimumAppVersion copy], - _dictionary); -} - -- (NSString *)minimumAppVersion { - return _dictionary[kFDLIOSMinimumVersionKey]; -} - -- (void)setIPadBundleID:(NSString *)iPadBundleID { - FDLSafelyAddKeyValuePairToDictionary(kFDLIOSIPadBundleIdentifierKey, [iPadBundleID copy], - _dictionary); -} - -- (NSString *)iPadBundleID { - return _dictionary[kFDLIOSIPadBundleIdentifierKey]; -} - -- (void)setIPadFallbackURL:(NSURL *)iPadFallbackURL { - FDLSafelyAddKeyValuePairToDictionary(kFDLIOSIPadFallbackURLKey, iPadFallbackURL.absoluteString, - _dictionary); -} - -- (NSURL *)iPadFallbackURL { - NSString *fallbackURLString = _dictionary[kFDLIOSIPadFallbackURLKey]; - return fallbackURLString != nil ? [NSURL URLWithString:fallbackURLString] : nil; -} - -- (NSDictionary *)dictionaryRepresentation { - return [_dictionary copy]; -} - -@end - -@implementation FIRDynamicLinkItunesConnectAnalyticsParameters { - NSMutableDictionary *_dictionary; -} - -static NSString *const kFDLITunesConnectAffiliateTokeyKey = @"at"; -static NSString *const kFDLITunesConnectCampaignTokenKey = @"ct"; -static NSString *const kFDLITunesConnectProviderTokenKey = @"pt"; - -+ (instancetype)parameters { - return [[self alloc] init]; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _dictionary = [NSMutableDictionary dictionary]; - } - return self; -} - -- (void)setAffiliateToken:(NSString *)affiliateToken { - FDLSafelyAddKeyValuePairToDictionary(kFDLITunesConnectAffiliateTokeyKey, [affiliateToken copy], - _dictionary); -} - -- (NSString *)affiliateToken { - return _dictionary[kFDLITunesConnectAffiliateTokeyKey]; -} - -- (void)setCampaignToken:(NSString *)campaignToken { - FDLSafelyAddKeyValuePairToDictionary(kFDLITunesConnectCampaignTokenKey, [campaignToken copy], - _dictionary); -} - -- (NSString *)campaignToken { - return _dictionary[kFDLITunesConnectCampaignTokenKey]; -} - -- (void)setProviderToken:(NSString *)providerToken { - FDLSafelyAddKeyValuePairToDictionary(kFDLITunesConnectProviderTokenKey, [providerToken copy], - _dictionary); -} - -- (NSString *)providerToken { - return _dictionary[kFDLITunesConnectProviderTokenKey]; -} - -- (NSDictionary *)dictionaryRepresentation { - return [_dictionary copy]; -} - -@end - -@implementation FIRDynamicLinkAndroidParameters { - NSMutableDictionary *_dictionary; -} - -static NSString *const kFDLAndroidMinimumVersionKey = @"amv"; -static NSString *const kFDLAndroidFallbackURLKey = @"afl"; -static NSString *const kFDLAndroidPackageNameKey = @"apn"; - -+ (instancetype)parametersWithPackageName:(NSString *)packageName { - return [[self alloc] initWithPackageName:packageName]; -} - -- (instancetype)initWithPackageName:(NSString *)packageName { - self = [super init]; - if (self) { - _dictionary = [NSMutableDictionary dictionary]; - FDLSafelyAddKeyValuePairToDictionary(kFDLAndroidPackageNameKey, packageName, _dictionary); - } - return self; -} - -- (NSString *)packageName { - return _dictionary[kFDLAndroidPackageNameKey]; -} - -- (void)setMinimumVersion:(NSInteger)minimumVersion { - _dictionary[kFDLAndroidMinimumVersionKey] = @(minimumVersion).stringValue; -} - -- (NSInteger)minimumVersion { - return _dictionary[kFDLAndroidMinimumVersionKey].integerValue; -} - -- (void)setFallbackURL:(NSURL *)fallbackURL { - FDLSafelyAddKeyValuePairToDictionary(kFDLAndroidFallbackURLKey, fallbackURL.absoluteString, - _dictionary); -} - -- (NSURL *)fallbackURL { - NSString *fallbackURLString = _dictionary[kFDLAndroidFallbackURLKey]; - return fallbackURLString != nil ? [NSURL URLWithString:fallbackURLString] : nil; -} - -- (NSDictionary *)dictionaryRepresentation { - return [_dictionary copy]; -} - -@end - -@implementation FIRDynamicLinkSocialMetaTagParameters { - NSMutableDictionary *_dictionary; -} - -static NSString *const kFDLSocialTitleKey = @"st"; -static NSString *const kFDLSocialDescriptionKey = @"sd"; -static NSString *const kFDLSocialImageURLKey = @"si"; - -+ (instancetype)parameters { - return [[self alloc] init]; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _dictionary = [NSMutableDictionary dictionary]; - } - return self; -} - -- (void)setTitle:(NSString *)title { - FDLSafelyAddKeyValuePairToDictionary(kFDLSocialTitleKey, [title copy], _dictionary); -} - -- (NSString *)title { - return _dictionary[kFDLSocialTitleKey]; -} - -- (void)setDescriptionText:(NSString *)descriptionText { - FDLSafelyAddKeyValuePairToDictionary(kFDLSocialDescriptionKey, [descriptionText copy], - _dictionary); -} - -- (NSString *)descriptionText { - return _dictionary[kFDLSocialDescriptionKey]; -} - -- (void)setImageURL:(NSURL *)imageURL { - FDLSafelyAddKeyValuePairToDictionary(kFDLSocialImageURLKey, imageURL.absoluteString, _dictionary); -} - -- (NSURL *)imageURL { - NSString *imageURLString = _dictionary[kFDLSocialImageURLKey]; - return imageURLString != nil ? [NSURL URLWithString:imageURLString] : nil; -} - -- (NSDictionary *)dictionaryRepresentation { - return [_dictionary copy]; -} - -@end - -@implementation FIRDynamicLinkNavigationInfoParameters { - NSMutableDictionary *_dictionary; -} - -static NSString *const kFDLNavigationInfoForceRedirectKey = @"efr"; - -+ (instancetype)parameters { - return [[self alloc] init]; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _dictionary = [NSMutableDictionary dictionary]; - } - return self; -} - -- (BOOL)isForcedRedirectEnabled { - return [_dictionary[kFDLNavigationInfoForceRedirectKey] boolValue]; -} - -- (void)setForcedRedirectEnabled:(BOOL)forcedRedirectEnabled { - FDLSafelyAddKeyValuePairToDictionary(kFDLNavigationInfoForceRedirectKey, - forcedRedirectEnabled ? @"1" : @"0", _dictionary); -} - -- (NSDictionary *)dictionaryRepresentation { - return [_dictionary copy]; -} - -@end - -@implementation FIRDynamicLinkOtherPlatformParameters { - NSMutableDictionary *_dictionary; -} - -static NSString *const kFDLOtherPlatformParametersFallbackURLKey = @"ofl"; - -+ (instancetype)parameters { - return [[self alloc] init]; -} - -- (instancetype)init { - self = [super init]; - if (self) { - _dictionary = [NSMutableDictionary dictionary]; - } - return self; -} - -- (NSURL *)fallbackUrl { - NSString *fallbackURLString = _dictionary[kFDLOtherPlatformParametersFallbackURLKey]; - return fallbackURLString != nil ? [NSURL URLWithString:fallbackURLString] : nil; -} - -- (void)setFallbackUrl:(NSURL *)fallbackUrl { - FDLSafelyAddKeyValuePairToDictionary(kFDLOtherPlatformParametersFallbackURLKey, - fallbackUrl.absoluteString, _dictionary); -} - -- (NSDictionary *)dictionaryRepresentation { - return [_dictionary copy]; -} - -@end - -@implementation FIRDynamicLinkComponentsOptions - -+ (instancetype)options { - return [[self alloc] init]; -} - -// This is implemented to silence the 'not implemented' warning. -- (instancetype)init { - return [super init]; -} - -@end - -@implementation FIRDynamicLinkComponents - -#pragma mark Deprecated Initializers. -+ (instancetype)componentsWithLink:(NSURL *)link domain:(NSString *)domain { - return [[self alloc] initWithLink:link domain:domain]; -} - -- (instancetype)initWithLink:(NSURL *)link domain:(NSString *)domain { - NSURL *domainURL = [NSURL URLWithString:domain]; - if (domainURL.scheme) { - FDLLog(FDLLogLevelWarning, FDLLogIdentifierSetupWarnHTTPSScheme, - @"You have supplied a domain with a scheme. Please enter a domain name without the " - @"scheme."); - } - NSString *domainURIPrefix = [NSString stringWithFormat:@"https://%@", domain]; - self = [super init]; - if (self) { - _link = link; - _domain = domainURIPrefix; - } - return self; -} - -#pragma mark Initializers. -+ (instancetype)componentsWithLink:(NSURL *)link domainURIPrefix:(NSString *)domainURIPrefix { - return [[self alloc] initWithLink:link domainURIPrefix:domainURIPrefix]; -} - -- (instancetype)initWithLink:(NSURL *)link domainURIPrefix:(NSString *)domainURIPrefix { - self = [super init]; - if (self) { - _link = link; - /// Must be a URL that conforms to RFC 2396. - NSURL *domainURIPrefixURL = [NSURL URLWithString:domainURIPrefix]; - if (!domainURIPrefixURL) { - FDLLog(FDLLogLevelError, FDLLogIdentifierSetupInvalidDomainURIPrefix, - @"Invalid domainURIPrefix. Please input a valid URL."); - return nil; - } - if (![[domainURIPrefixURL.scheme lowercaseString] isEqualToString:@"https"]) { - FDLLog(FDLLogLevelError, FDLLogIdentifierSetupInvalidDomainURIPrefixScheme, - @"Invalid domainURIPrefix scheme. Scheme needs to be https"); - return nil; - } - _domain = [domainURIPrefix copy]; - } - return self; -} - -+ (void)shortenURL:(NSURL *)url - options:(FIRDynamicLinkComponentsOptions *)options - completion:(FIRDynamicLinkShortenerCompletion)completion { - if (![FIRDynamicLinkComponentsKeyProvider APIKey]) { - NSError *error = [NSError - errorWithDomain:kFirebaseDurableDeepLinkErrorDomain - code:0 - userInfo:@{ - NSLocalizedFailureReasonErrorKey : NSLocalizedString( - @"API key is missing.", @"Error reason message when API key is missing"), - }]; - completion(nil, nil, error); - return; - } - NSURLRequest *request = [self shorteningRequestForLongURL:url options:options]; - if (!request) { - NSError *error = [NSError errorWithDomain:kFirebaseDurableDeepLinkErrorDomain - code:0 - userInfo:nil]; - completion(nil, nil, error); - return; - } - [self sendHTTPRequest:request - completion:^(NSData *_Nullable data, NSError *_Nullable error) { - NSURL *shortURL; - NSArray *warnings; - if (data != nil && error == nil) { - NSError *deserializationError; - id JSONObject = [NSJSONSerialization JSONObjectWithData:data - options:0 - error:&deserializationError]; - - if ([JSONObject isKindOfClass:[NSDictionary class]]) { - if ([JSONObject[@"shortLink"] isKindOfClass:[NSString class]]) { - shortURL = [NSURL URLWithString:JSONObject[@"shortLink"]]; - } else { - if ([JSONObject[@"error"] isKindOfClass:[NSDictionary class]]) { - NSMutableDictionary *errorUserInfo = [[NSMutableDictionary alloc] init]; - - NSDictionary *errorDictionary = JSONObject[@"error"]; - if ([errorDictionary[@"message"] isKindOfClass:[NSString class]]) { - errorUserInfo[NSLocalizedFailureReasonErrorKey] = - errorDictionary[@"message"]; - } - if ([errorDictionary[@"status"] isKindOfClass:[NSString class]]) { - errorUserInfo[@"remoteStatus"] = errorDictionary[@"status"]; - } - if (errorDictionary[@"code"] && - [errorDictionary[@"code"] isKindOfClass:[NSNumber class]]) { - errorUserInfo[@"remoteErrorCode"] = errorDictionary[@"code"]; - } - error = [NSError errorWithDomain:kFirebaseDurableDeepLinkErrorDomain - code:0 - userInfo:errorUserInfo]; - } - } - if ([JSONObject[@"warning"] isKindOfClass:[NSArray class]]) { - NSArray *warningsServer = JSONObject[@"warning"]; - NSMutableArray *warningsTmp = - [NSMutableArray arrayWithCapacity:[warningsServer count]]; - for (NSDictionary *warningServer in warningsServer) { - if ([warningServer[@"warningMessage"] isKindOfClass:[NSString class]]) { - [warningsTmp addObject:warningServer[@"warningMessage"]]; - } - } - if ([warningsTmp count] > 0) { - warnings = [warningsTmp copy]; - } - } - } else if (deserializationError) { - error = [NSError - errorWithDomain:kFirebaseDurableDeepLinkErrorDomain - code:0 - userInfo:@{ - NSLocalizedFailureReasonErrorKey : NSLocalizedString( - @"Unrecognized server response", - @"Error reason message when server response can't be parsed"), - NSUnderlyingErrorKey : deserializationError, - }]; - } - } - if (!shortURL && !error) { - // provide generic error message if we have no additional details about failure - error = [NSError errorWithDomain:kFirebaseDurableDeepLinkErrorDomain - code:0 - userInfo:nil]; - } - dispatch_async(dispatch_get_main_queue(), ^{ - completion(shortURL, warnings, error); - }); - }]; -} - -- (void)shortenWithCompletion:(FIRDynamicLinkShortenerCompletion)completion { - NSURL *url = [self url]; - if (!url) { - NSError *error = [NSError errorWithDomain:kFirebaseDurableDeepLinkErrorDomain - code:0 - userInfo:@{ - NSLocalizedFailureReasonErrorKey : NSLocalizedString( - @"Unable to produce long URL", - @"Error reason when long url can't be produced"), - }]; - completion(nil, nil, error); - return; - } - return [FIRDynamicLinkComponents shortenURL:url options:_options completion:completion]; -} - -- (NSURL *)url { - static NSString *const kFDLURLComponentsLinkKey = @"link"; - - NSMutableDictionary *queryDictionary = - [NSMutableDictionary dictionaryWithObject:self.link.absoluteString - forKey:kFDLURLComponentsLinkKey]; - - void (^addEntriesFromDictionaryRepresentingConformerToDictionary)(id) = - ^(id _Nullable dictionaryRepresentingConformer) { - NSDictionary *dictionary = dictionaryRepresentingConformer.dictionaryRepresentation; - if (dictionary.count > 0) { - [queryDictionary addEntriesFromDictionary:dictionary]; - } - }; - - addEntriesFromDictionaryRepresentingConformerToDictionary(_analyticsParameters); - addEntriesFromDictionaryRepresentingConformerToDictionary(_socialMetaTagParameters); - addEntriesFromDictionaryRepresentingConformerToDictionary(_iOSParameters); - addEntriesFromDictionaryRepresentingConformerToDictionary(_iTunesConnectParameters); - addEntriesFromDictionaryRepresentingConformerToDictionary(_androidParameters); - addEntriesFromDictionaryRepresentingConformerToDictionary(_navigationInfoParameters); - addEntriesFromDictionaryRepresentingConformerToDictionary(_otherPlatformParameters); - - NSString *queryString = FIRDLURLQueryStringFromDictionary(queryDictionary); - NSString *urlString = [NSString stringWithFormat:@"%@/%@", _domain, queryString]; - return [NSURL URLWithString:urlString]; -} - -#pragma mark Helper Methods - -+ (void)sendHTTPRequest:(NSURLRequest *)request - completion:(void (^)(NSData *_Nullable data, NSError *_Nullable error))completion { - NSURLSession *session = [NSURLSession sharedSession]; - NSURLSessionDataTask *task = - [session dataTaskWithRequest:request - completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, - NSError *_Nullable error) { - completion(data, error); - }]; - [task resume]; -} - -+ (NSURLRequest *)shorteningRequestForLongURL:(NSURL *)url - options:(nullable FIRDynamicLinkComponentsOptions *)options { - if (!url) { - return nil; - } - - static NSString *const kFDLURLShortenerAPIHost = @"https://firebasedynamiclinks.googleapis.com"; - static NSString *const kFDLURLShortenerAPIPath = @"/v1/shortLinks"; - static NSString *const kFDLURLShortenerAPIQuery = @"?key="; - - NSString *apiKey = [FIRDynamicLinkComponentsKeyProvider APIKey]; - - NSString *postURLString = - [NSString stringWithFormat:@"%@%@%@%@", kFDLURLShortenerAPIHost, kFDLURLShortenerAPIPath, - kFDLURLShortenerAPIQuery, apiKey]; - NSURL *postURL = [NSURL URLWithString:postURLString]; - - NSMutableDictionary *payloadDictionary = - [NSMutableDictionary dictionaryWithObject:url.absoluteString forKey:@"longDynamicLink"]; - switch (options.pathLength) { - case FIRShortDynamicLinkPathLengthShort: - payloadDictionary[@"suffix"] = @{@"option" : @"SHORT"}; - break; - case FIRShortDynamicLinkPathLengthUnguessable: - payloadDictionary[@"suffix"] = @{@"option" : @"UNGUESSABLE"}; - break; - default: - break; - } - NSData *payload = [NSJSONSerialization dataWithJSONObject:payloadDictionary options:0 error:0]; - - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:postURL]; - request.HTTPMethod = @"POST"; - request.HTTPBody = payload; - [request setValue:[NSBundle mainBundle].bundleIdentifier - forHTTPHeaderField:@"X-Ios-Bundle-Identifier"]; - NSString *contentType = @"application/json"; - [request setValue:contentType forHTTPHeaderField:@"Accept"]; - [request setValue:contentType forHTTPHeaderField:@"Content-Type"]; - - return [request copy]; -} - -@end - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h b/FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h deleted file mode 100644 index a6e11dd9223..00000000000 --- a/FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@interface FIRDynamicLinkComponentsKeyProvider : NSObject - -+ (nullable NSString *)APIKey; - -@end diff --git a/FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.m b/FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.m deleted file mode 100644 index 24b6c79528c..00000000000 --- a/FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.m +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h" - -#import "FirebaseCore/Extension/FirebaseCoreInternal.h" - -@implementation FIRDynamicLinkComponentsKeyProvider - -+ (nullable NSString *)APIKey { - // If there's no default app, immediately return nil since reading from the default app will cause - // an error to be logged. - if (![FIRApp isDefaultAppConfigured]) { - return nil; - } - - // FDL only supports the default app, use the options from it. - return [FIRApp defaultApp].options.APIKey; -} - -@end - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h b/FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h deleted file mode 100644 index 9d911e29e24..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessProtocols.h" - -#import - -@class FIRDynamicLinkNetworking; - -NS_ASSUME_NONNULL_BEGIN - -/** - Class to encapsulate logic related to retrieving pending dynamic link. - */ -@interface FIRDLDefaultRetrievalProcessV2 : NSObject - -- (instancetype)initWithNetworkingService:(FIRDynamicLinkNetworking *)networkingService - URLScheme:(NSString *)URLScheme - APIKey:(NSString *)APIKey - FDLSDKVersion:(NSString *)FDLSDKVersion - delegate:(id)delegate - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.m b/FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.m deleted file mode 100644 index 15224d061c4..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.m +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h" - -#import -#import "FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.h" -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult+Private.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h" -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -// Reason for this string to ensure that only FDL links, copied to clipboard by AppPreview Page -// JavaScript code, are recognized and used in copy-unique-match process. If user copied FDL to -// clipboard by himself, that link must not be used in copy-unique-match process. -// This constant must be kept in sync with constant in the server version at -// durabledeeplink/click/ios/click_page.js -static NSString *expectedCopiedLinkStringSuffix = @"_icp=1"; - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRDLDefaultRetrievalProcessV2 () - -@end - -@implementation FIRDLDefaultRetrievalProcessV2 { - FIRDynamicLinkNetworking *_networkingService; - NSString *_URLScheme; - NSString *_APIKey; - NSString *_FDLSDKVersion; - NSString *_clipboardContentAtMatchProcessStart; - FIRDLJavaScriptExecutor *_jsExecutor; - NSString *_localeFromWebView; -} - -@synthesize delegate = _delegate; - -#pragma mark - Initialization - -- (instancetype)initWithNetworkingService:(FIRDynamicLinkNetworking *)networkingService - URLScheme:(NSString *)URLScheme - APIKey:(NSString *)APIKey - FDLSDKVersion:(NSString *)FDLSDKVersion - delegate:(id)delegate { - NSParameterAssert(networkingService); - NSParameterAssert(URLScheme); - NSParameterAssert(APIKey); - if (self = [super init]) { - _networkingService = networkingService; - _URLScheme = [URLScheme copy]; - _APIKey = [APIKey copy]; - _FDLSDKVersion = [FDLSDKVersion copy]; - _delegate = delegate; - } - return self; -} - -#pragma mark - FIRDLRetrievalProcessProtocol - -- (void)retrievePendingDynamicLink { - if (_localeFromWebView) { - [self retrievePendingDynamicLinkInternal]; - } else { - [self fetchLocaleFromWebView]; - } -} - -#pragma mark - FIRDLJavaScriptExecutorDelegate - -- (void)javaScriptExecutor:(FIRDLJavaScriptExecutor *)executor - completedExecutionWithResult:(NSString *)result { - _localeFromWebView = result ?: @""; - _jsExecutor = nil; - [self retrievePendingDynamicLinkInternal]; -} - -- (void)javaScriptExecutor:(FIRDLJavaScriptExecutor *)executor failedWithError:(NSError *)error { - _localeFromWebView = @""; - _jsExecutor = nil; - [self retrievePendingDynamicLinkInternal]; -} - -#pragma mark - Internal methods - -- (void)retrievePendingDynamicLinkInternal { - CGRect mainScreenBounds = [UIScreen mainScreen].bounds; - NSInteger resolutionWidth = mainScreenBounds.size.width; - NSInteger resolutionHeight = mainScreenBounds.size.height; - if ([[[UIDevice currentDevice] model] isEqualToString:@"iPad"] && - UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { - // iPhone App running in compatibility mode on iPad - // screen resolution reported by UIDevice/UIScreen will be wrong - resolutionWidth = 0; - resolutionHeight = 0; - } - NSURL *uniqueMatchLinkToCheck = [self uniqueMatchLinkToCheck]; - - __weak __typeof__(self) weakSelf = self; - FIRPostInstallAttributionCompletionHandler completionHandler = - ^(NSDictionary *_Nullable dynamicLinkParameters, NSString *_Nullable matchMessage, - NSError *_Nullable error) { - __typeof__(self) strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - FIRDynamicLink *dynamicLink; - if (dynamicLinkParameters.count) { - dynamicLink = [[FIRDynamicLink alloc] initWithParametersDictionary:dynamicLinkParameters]; - } - FIRDLRetrievalProcessResult *result = - [[FIRDLRetrievalProcessResult alloc] initWithDynamicLink:dynamicLink - error:error - message:matchMessage - matchSource:nil]; - - [strongSelf handleRetrievalProcessWithResult:result]; - if (!error) { - [strongSelf clearUsedUniqueMatchLinkToCheckFromClipboard]; - } - }; - - // Disable deprecated warning for internal methods. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - // If there is not a unique match, we will send an additional request for device heuristics based - // matching. - [_networkingService - retrievePendingDynamicLinkWithIOSVersion:[UIDevice currentDevice].systemVersion - resolutionHeight:resolutionHeight - resolutionWidth:resolutionWidth - locale:FIRDLDeviceLocale() - localeRaw:FIRDLDeviceLocaleRaw() - localeFromWebView:_localeFromWebView - timezone:FIRDLDeviceTimezone() - modelName:FIRDLDeviceModelName() - FDLSDKVersion:_FDLSDKVersion - appInstallationDate:FIRDLAppInstallationDate() - uniqueMatchVisualStyle:FIRDynamicLinkNetworkingUniqueMatchVisualStyleUnknown - retrievalProcessType: - FIRDynamicLinkNetworkingRetrievalProcessTypeImplicitDefault - uniqueMatchLinkToCheck:uniqueMatchLinkToCheck - handler:completionHandler]; -#pragma clang pop -} - -- (void)handleRetrievalProcessWithResult:(FIRDLRetrievalProcessResult *)result { - if (!result) { - // if we did not get any results, construct one - NSString *message = NSLocalizedString(@"Pending dynamic link not found", - @"Message when dynamic link was not found"); - result = [[FIRDLRetrievalProcessResult alloc] initWithDynamicLink:nil - error:nil - message:message - matchSource:nil]; - } - [self.delegate retrievalProcess:self completedWithResult:result]; -} - -- (nullable NSURL *)uniqueMatchLinkToCheck { - _clipboardContentAtMatchProcessStart = nil; - NSString *pasteboardContents = [self retrievePasteboardContents]; - if (!pasteboardContents) { - return nil; - } - NSInteger linkStringMinimumLength = - expectedCopiedLinkStringSuffix.length + /* ? or & */ 1 + /* http:// */ 7; - if ((pasteboardContents.length >= linkStringMinimumLength) && - [pasteboardContents hasSuffix:expectedCopiedLinkStringSuffix] && - [NSURL URLWithString:pasteboardContents]) { - // remove custom suffix and preceding '&' or '?' character from string - NSString *linkStringWithoutSuffix = [pasteboardContents - substringToIndex:pasteboardContents.length - expectedCopiedLinkStringSuffix.length - 1]; - NSURL *URL = [NSURL URLWithString:linkStringWithoutSuffix]; - if (URL) { - // check is link matches short link format - if (FIRDLMatchesShortLinkFormat(URL)) { - _clipboardContentAtMatchProcessStart = pasteboardContents; - return URL; - } - // check is link matches long link format - if (FIRDLCanParseUniversalLinkURL(URL)) { - _clipboardContentAtMatchProcessStart = pasteboardContents; - return URL; - } - } - } - return nil; -} - -- (nullable NSString *)retrievePasteboardContents { - if (![self isPasteboardRetrievalEnabled]) { - // Pasteboard check for dynamic link is disabled by user. - return nil; - } - - if ([[UIPasteboard generalPasteboard] hasURLs]) { - return [UIPasteboard generalPasteboard].string; - } else { - return nil; - } -} - -/** - Property to enable or disable dynamic link retrieval from Pasteboard. - This property is added because of iOS 14 feature where pop up is displayed while accessing - Pasteboard. So if developers don't want their users to see the Pasteboard popup, they can set - "FirebaseDeepLinkPasteboardRetrievalEnabled" to false in their plist. - */ -- (BOOL)isPasteboardRetrievalEnabled { - id retrievalEnabledValue = - [[NSBundle mainBundle] infoDictionary][@"FirebaseDeepLinkPasteboardRetrievalEnabled"]; - if ([retrievalEnabledValue respondsToSelector:@selector(boolValue)]) { - return [retrievalEnabledValue boolValue]; - } - return YES; -} - -- (void)clearUsedUniqueMatchLinkToCheckFromClipboard { - // See discussion in b/65304652 - // We will clear clipboard after we used the unique match link from the clipboard - if (_clipboardContentAtMatchProcessStart.length > 0 && - [_clipboardContentAtMatchProcessStart isEqualToString:_clipboardContentAtMatchProcessStart]) { - [UIPasteboard generalPasteboard].string = @""; - } -} - -- (void)fetchLocaleFromWebView { - if (_jsExecutor) { - return; - } - NSString *jsString = @"window.generateDeviceHeuristics=()=>navigator.language||''"; - _jsExecutor = [[FIRDLJavaScriptExecutor alloc] initWithDelegate:self script:jsString]; -} - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.h b/FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.h deleted file mode 100644 index ea1952156f6..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@class FIRDLJavaScriptExecutor; - -NS_ASSUME_NONNULL_BEGIN - -@protocol FIRDLJavaScriptExecutorDelegate - -- (void)javaScriptExecutor:(FIRDLJavaScriptExecutor *)executor - completedExecutionWithResult:(NSString *)result; -- (void)javaScriptExecutor:(FIRDLJavaScriptExecutor *)executor failedWithError:(NSError *)error; - -@end - -@interface FIRDLJavaScriptExecutor : NSObject - -- (instancetype)initWithDelegate:(id)delegate - script:(NSString *)script; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.m b/FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.m deleted file mode 100644 index f90113a2438..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.m +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import - -#import - -#import "FirebaseDynamicLinks/Sources/FIRDLJavaScriptExecutor.h" - -NS_ASSUME_NONNULL_BEGIN - -static NSString *const kJSMethodName = @"generateDeviceHeuristics"; - -/** Creates and returns the FDL JS method name. */ -NSString *FIRDLTypeofDeviceHeuristicsJSMethodNameString(void) { - static NSString *methodName; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - methodName = [NSString stringWithFormat:@"typeof(%@)", kJSMethodName]; - }); - return methodName; -} - -/** Creates and returns the FDL JS method definition. */ -NSString *GINDeviceHeuristicsJSMethodString(void) { - static NSString *methodString; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - methodString = [NSString stringWithFormat:@"%@()", kJSMethodName]; - }); - return methodString; -} - -@interface FIRDLJavaScriptExecutor () -@end - -@implementation FIRDLJavaScriptExecutor { - __weak id _delegate; - NSString *_script; - - // Web view with which to run JavaScript. - WKWebView *_wkWebView; -} - -- (instancetype)initWithDelegate:(id)delegate - script:(NSString *)script { - NSParameterAssert(delegate); - NSParameterAssert(script); - NSParameterAssert(script.length > 0); - NSAssert([NSThread isMainThread], @"%@ must be used in main thread", - NSStringFromClass([self class])); - if (self = [super init]) { - _delegate = delegate; - _script = [script copy]; - [self start]; - } - return self; -} - -#pragma mark - Internal methods -- (void)start { -// Initializing a `WKWebView` causes a memory allocation error when the process -// is running under Rosetta translation on Apple Silicon. -// The issue only occurs on the simulator in apps targeting below iOS 14. (Issue #7618) -#if TARGET_OS_SIMULATOR - BOOL systemVersionAtLeastiOS14 = [NSProcessInfo.processInfo - isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){14, 0, 0}]; - // Perform an early exit if the process is running under Rosetta translation and targeting - // under iOS 14. - if (processIsTranslated() && !systemVersionAtLeastiOS14) { - [self handleExecutionError:nil]; - return; - } -#endif - NSString *htmlContent = - [NSString stringWithFormat:@"", _script]; - - _wkWebView = [[WKWebView alloc] init]; - _wkWebView.navigationDelegate = self; - [_wkWebView loadHTMLString:htmlContent baseURL:nil]; -} - -- (void)handleExecutionResult:(NSString *)result { - [self cleanup]; - [_delegate javaScriptExecutor:self completedExecutionWithResult:result]; -} - -- (void)handleExecutionError:(nullable NSError *)error { - [self cleanup]; - if (!error) { - error = [NSError errorWithDomain:@"com.firebase.durabledeeplink" code:-1 userInfo:nil]; - } - [_delegate javaScriptExecutor:self failedWithError:error]; -} - -- (void)cleanup { - _wkWebView.navigationDelegate = nil; - _wkWebView = nil; -} - -#pragma mark - WKNavigationDelegate - -- (void)webView:(WKWebView *)webView - didFinishNavigation:(null_unspecified WKNavigation *)navigation { - __weak __typeof__(self) weakSelf = self; - - // Make sure that the javascript was loaded successfully before calling the method. - [webView evaluateJavaScript:FIRDLTypeofDeviceHeuristicsJSMethodNameString() - completionHandler:^(id _Nullable typeofResult, NSError *_Nullable typeError) { - if (typeError) { - [weakSelf handleExecutionError:typeError]; - return; - } - if ([typeofResult isEqual:@"function"]) { - [webView - evaluateJavaScript:GINDeviceHeuristicsJSMethodString() - completionHandler:^(id _Nullable result, NSError *_Nullable functionError) { - __typeof__(self) strongSelf = weakSelf; - if ([result isKindOfClass:[NSString class]]) { - [strongSelf handleExecutionResult:result]; - } else { - [strongSelf handleExecutionError:nil]; - } - }]; - } else { - [weakSelf handleExecutionError:nil]; - } - }]; -} - -- (void)webView:(WKWebView *)webView - didFailNavigation:(null_unspecified WKNavigation *)navigation - withError:(NSError *)error { - [self handleExecutionError:error]; -} - -// Determine whether a process is running under Rosetta translation. -// Returns 0 for a native process, 1 for a translated process, -// and -1 when an error occurs. -// From: -// https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment -#if TARGET_OS_SIMULATOR -static int processIsTranslated(void) { - int ret = 0; - size_t size = sizeof(ret); - if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) { - if (errno == ENOENT) return 0; - return -1; - } - return ret; -} -#endif - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.h b/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.h deleted file mode 100644 index dfe2602694a..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessProtocols.h" - -@class FIRDynamicLinkNetworking; - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRDLRetrievalProcessFactory : NSObject - -- (instancetype)initWithNetworkingService:(FIRDynamicLinkNetworking *)networkingService - URLScheme:(NSString *)URLScheme - APIKey:(NSString *)APIKey - FDLSDKVersion:(NSString *)FDLSDKVersion - delegate:(id)delegate - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -- (id)automaticRetrievalProcess; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.m b/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.m deleted file mode 100644 index 65242212a60..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.m +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.h" - -#import "FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h" - -NS_ASSUME_NONNULL_BEGIN - -@implementation FIRDLRetrievalProcessFactory { - FIRDynamicLinkNetworking *_networkingService; - NSString *_URLScheme; - NSString *_APIKey; - NSString *_FDLSDKVersion; - id _delegate; -} - -- (instancetype)initWithNetworkingService:(FIRDynamicLinkNetworking *)networkingService - URLScheme:(NSString *)URLScheme - APIKey:(NSString *)APIKey - FDLSDKVersion:(NSString *)FDLSDKVersion - delegate:(id)delegate { - if (self = [super init]) { - _networkingService = networkingService; - _URLScheme = URLScheme; - _APIKey = APIKey; - _FDLSDKVersion = FDLSDKVersion; - _delegate = delegate; - } - return self; -} - -- (id)automaticRetrievalProcess { - return [[FIRDLDefaultRetrievalProcessV2 alloc] initWithNetworkingService:_networkingService - URLScheme:_URLScheme - APIKey:_APIKey - FDLSDKVersion:_FDLSDKVersion - delegate:_delegate]; -} - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessProtocols.h b/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessProtocols.h deleted file mode 100644 index aeb5916208e..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessProtocols.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol FIRDLRetrievalProcessProtocol; -@class FIRDLRetrievalProcessResult; - -@protocol FIRDLRetrievalProcessDelegate - -- (void)retrievalProcess:(id)retrievalProcess - completedWithResult:(FIRDLRetrievalProcessResult *)result; - -@end - -@protocol FIRDLRetrievalProcessProtocol - -@property(weak, nonatomic, readonly) id delegate; - -- (void)retrievePendingDynamicLink; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult+Private.h b/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult+Private.h deleted file mode 100644 index c14a35a06ac..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult+Private.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRDLRetrievalProcessResult () - -- (instancetype)initWithDynamicLink:(nullable FIRDynamicLink *)dynamicLink - error:(nullable NSError *)error - message:(nullable NSString *)message - matchSource:(nullable NSString *)matchSource NS_DESIGNATED_INITIALIZER; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.h b/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.h deleted file mode 100644 index 5f7d5c35b7d..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@class FIRDynamicLink; - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRDLRetrievalProcessResult : NSObject - -- (instancetype)init NS_UNAVAILABLE; - -// Method to present retrieval result as custom URL scheme URL. -// Produced URL will be passed to an application via [UIApplicationDelegate openURL:] method. -- (NSURL *)URLWithCustomURLScheme:(NSString *)customURLScheme; - -@property(nonatomic, nullable, readonly) FIRDynamicLink *dynamicLink; -@property(nonatomic, nullable, readonly) NSError *error; -@property(nonatomic, nullable, copy, readonly) NSString *message; -@property(nonatomic, nullable, copy, readonly) NSString *matchSource; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.m b/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.m deleted file mode 100644 index 581950e4cf4..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.m +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.h" - -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult+Private.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h" -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -NS_ASSUME_NONNULL_BEGIN - -@implementation FIRDLRetrievalProcessResult - -- (instancetype)initWithDynamicLink:(nullable FIRDynamicLink *)dynamicLink - error:(nullable NSError *)error - message:(nullable NSString *)message - matchSource:(nullable NSString *)matchSource { - if (self = [super init]) { - _dynamicLink = dynamicLink; - _error = error; - _message = [message copy]; - _matchSource = [matchSource copy]; - } - return self; -} - -- (NSURL *)URLWithCustomURLScheme:(NSString *)customURLScheme { - NSURL *URL; - if (_dynamicLink) { - NSString *queryString = FIRDLURLQueryStringFromDictionary(_dynamicLink.parametersDictionary); - NSMutableString *URLString = [[NSMutableString alloc] init]; - [URLString appendString:customURLScheme]; - [URLString appendString:@"://google/link/"]; - [URLString appendString:queryString]; - URL = [NSURL URLWithString:URLString]; - } else { - NSMutableString *URLString = [[NSMutableString alloc] init]; - [URLString appendString:customURLScheme]; - [URLString appendString:@"://google/link/?dismiss=1&is_weak_match=1"]; - URL = [NSURL URLWithString:URLString]; - } - return URL; -} - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDLScionLogging.h b/FirebaseDynamicLinks/Sources/FIRDLScionLogging.h deleted file mode 100644 index 1ed65a21f74..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLScionLogging.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" - -/** - * @enum FIRDLLogEvent - * @abstract Types of events that may be logged to Scion. - */ -typedef NS_ENUM(NSInteger, FIRDLLogEvent) { - /** Log event where the app is first opened with a DL. */ - FIRDLLogEventFirstOpen, - /** Log event where the app is subsequently opened with a DL. */ - FIRDLLogEventAppOpen, -}; - -/** - * @fn FIRDLLogEventToScion - * @abstract Logs a given event to Scion - * @param event The event type that occurred. - * @param source The utm_source URL parameter value. - * @param medium The utm_medium URL parameter value. - * @param campaign The utm_campaign URL parameter value. - * @param analytics The class to be used as the receiver of the logging method. - */ -void FIRDLLogEventToScion(FIRDLLogEvent event, - NSString* _Nullable source, - NSString* _Nullable medium, - NSString* _Nullable campaign, - id _Nullable analytics); diff --git a/FirebaseDynamicLinks/Sources/FIRDLScionLogging.m b/FirebaseDynamicLinks/Sources/FIRDLScionLogging.m deleted file mode 100644 index 145876465d9..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDLScionLogging.m +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/FIRDLScionLogging.h" - -#import "Interop/Analytics/Public/FIRInteropParameterNames.h" - -static NSString *const kFIRDLLogEventFirstOpenCampaign = @"dynamic_link_first_open"; -static NSString *const kFIRDLLogEventAppOpenCampaign = @"dynamic_link_app_open"; - -void FIRDLLogEventToScion(FIRDLLogEvent event, - NSString *_Nullable source, - NSString *_Nullable medium, - NSString *_Nullable campaign, - id _Nullable analytics) { - NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; - - if (source) { - parameters[kFIRIParameterSource] = source; - } - if (medium) { - parameters[kFIRIParameterMedium] = medium; - } - if (campaign) { - parameters[kFIRIParameterCampaign] = campaign; - } - - NSString *name; - switch (event) { - case FIRDLLogEventFirstOpen: - name = kFIRDLLogEventFirstOpenCampaign; - break; - case FIRDLLogEventAppOpen: - name = kFIRDLLogEventAppOpenCampaign; - break; - } - - if (name) { - [analytics logEventWithOrigin:@"fdl" name:name parameters:parameters]; - } -} - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h b/FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h deleted file mode 100644 index 8e26bf3a511..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLink.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRDynamicLink () - -typedef NS_ENUM(NSUInteger, FIRDynamicLinkMatchConfidence) { - FIRDynamicLinkMatchConfidenceWeak, - FIRDynamicLinkMatchConfidenceStrong -} NS_SWIFT_NAME(DynamicLinkMatchConfidence) DEPRECATED_MSG_ATTRIBUTE("Use FIRDLMatchType instead."); - -@property(nonatomic, assign, readonly) - FIRDynamicLinkMatchConfidence matchConfidence DEPRECATED_MSG_ATTRIBUTE( - "Use FIRDynamicLink.matchType (DynamicLink.DLMatchType) instead."); - -@property(nonatomic, copy, nullable) NSURL *url; - -@property(nonatomic, copy, readwrite, nullable) NSString *minimumAppVersion; - -// The invite ID retrieved from the dynamic link. -@property(nonatomic, copy, nullable) NSString *inviteId; - -// Whether the received invite is matched via ipv4 or ipv6 endpoint. -@property(nonatomic, copy, nullable) NSString *weakMatchEndpoint; - -@property(nonatomic, copy, nullable) NSString *matchMessage; - -@property(nonatomic, copy, readonly) NSDictionary *parametersDictionary; - -@property(nonatomic, assign, readwrite) FIRDLMatchType matchType; - -- (instancetype)initWithParametersDictionary:(NSDictionary *)parametersDictionary; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLink.m b/FirebaseDynamicLinks/Sources/FIRDynamicLink.m deleted file mode 100644 index 7a322a9ca09..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLink.m +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h" - -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -@implementation FIRDynamicLink - -NSString *const FDLUTMParamPrefix = @"utm_"; - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p, url [%@], match type: %@, minimumAppVersion: %@, " - "match message: %@>", - NSStringFromClass([self class]), self, self.url, - [[self class] stringWithMatchType:_matchType], - self.minimumAppVersion ?: @"N/A", self.matchMessage]; -} - -- (instancetype)initWithParametersDictionary:(NSDictionary *)parameters { - NSParameterAssert(parameters.count > 0); - - if (self = [super init]) { - _parametersDictionary = [parameters copy]; - _utmParametersDictionary = [[self class] extractUTMParams:parameters]; - NSString *urlString = parameters[kFIRDLParameterDeepLinkIdentifier]; - _url = [NSURL URLWithString:urlString]; - _inviteId = parameters[kFIRDLParameterInviteId]; - _weakMatchEndpoint = parameters[kFIRDLParameterWeakMatchEndpoint]; - _minimumAppVersion = parameters[kFIRDLParameterMinimumAppVersion]; - - if (parameters[kFIRDLParameterMatchType]) { - [self setMatchType:[[self class] matchTypeWithString:parameters[kFIRDLParameterMatchType]]]; - } else if (_url || _inviteId) { - // If matchType not present assume unique match for compatibility with server side behavior - // on iOS 8. - [self setMatchType:FIRDLMatchTypeUnique]; - } - - _matchMessage = parameters[kFIRDLParameterMatchMessage]; - } - return self; -} - -#pragma mark - Properties - -- (void)setUrl:(NSURL *)url { - _url = [url copy]; - [self setParametersDictionaryValue:[_url absoluteString] - forKey:kFIRDLParameterDeepLinkIdentifier]; -} - -- (void)setMinimumAppVersion:(NSString *)minimumAppVersion { - _minimumAppVersion = [minimumAppVersion copy]; - [self setParametersDictionaryValue:_minimumAppVersion forKey:kFIRDLParameterMinimumAppVersion]; -} - -- (void)setInviteId:(NSString *)inviteId { - _inviteId = [inviteId copy]; - [self setParametersDictionaryValue:_inviteId forKey:kFIRDLParameterInviteId]; -} - -- (void)setWeakMatchEndpoint:(NSString *)weakMatchEndpoint { - _weakMatchEndpoint = [weakMatchEndpoint copy]; - [self setParametersDictionaryValue:_weakMatchEndpoint forKey:kFIRDLParameterWeakMatchEndpoint]; -} - -- (void)setMatchType:(FIRDLMatchType)matchType { - _matchType = matchType; - [self setParametersDictionaryValue:[[self class] stringWithMatchType:_matchType] - forKey:kFIRDLParameterMatchType]; -} - -- (void)setMatchMessage:(NSString *)matchMessage { - _matchMessage = [matchMessage copy]; - [self setParametersDictionaryValue:_matchMessage forKey:kFIRDLParameterMatchMessage]; -} - -- (void)setParametersDictionaryValue:(id)value forKey:(NSString *)key { - NSMutableDictionary *parametersDictionary = - [self.parametersDictionary mutableCopy]; - if (value == nil) { - [parametersDictionary removeObjectForKey:key]; - } else { - parametersDictionary[key] = value; - } - - _parametersDictionary = [parametersDictionary copy]; -} - -- (FIRDynamicLinkMatchConfidence)matchConfidence { - return (_matchType == FIRDLMatchTypeUnique) ? FIRDynamicLinkMatchConfidenceStrong - : FIRDynamicLinkMatchConfidenceWeak; -} - -+ (NSString *)stringWithMatchType:(FIRDLMatchType)matchType { - switch (matchType) { - case FIRDLMatchTypeNone: - return @"none"; - case FIRDLMatchTypeWeak: - return @"weak"; - case FIRDLMatchTypeDefault: - return @"default"; - case FIRDLMatchTypeUnique: - return @"unique"; - } -} - -+ (FIRDLMatchType)matchTypeWithString:(NSString *)string { - static NSDictionary *matchMap; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - matchMap = @{ - @"none" : @(FIRDLMatchTypeNone), - @"weak" : @(FIRDLMatchTypeWeak), - @"default" : @(FIRDLMatchTypeDefault), - @"unique" : @(FIRDLMatchTypeUnique), - }; - }); - return [matchMap[string] integerValue] ?: FIRDLMatchTypeNone; -} - -+ (NSDictionary *)extractUTMParams:(NSDictionary *)parameters { - NSMutableDictionary *utmParamsDictionary = [[NSMutableDictionary alloc] init]; - - for (NSString *key in parameters) { - if ([key hasPrefix:FDLUTMParamPrefix]) { - [utmParamsDictionary setObject:[parameters valueForKey:key] forKey:key]; - } - } - - return [[NSDictionary alloc] initWithDictionary:utmParamsDictionary]; -} - -@end - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking+Private.h b/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking+Private.h deleted file mode 100644 index 8a41ccfbd91..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking+Private.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h" - -NS_ASSUME_NONNULL_BEGIN - -/** The key for the DL URL. */ -FOUNDATION_EXPORT NSString *const kFDLResolvedLinkDeepLinkURLKey; -/** The key for the minimum iOS app version. */ -FOUNDATION_EXPORT NSString *const kFDLResolvedLinkMinAppVersionKey; - -// Private interface for testing. -@interface FIRDynamicLinkNetworking () - -/** - * @method executeOnePlatformRequest:forURL:eventString:completionHandler: - * @abstract Creates and sends a OnePlatform HTTP request. Also adds the necessary header. - * @param requestBody The body of the request. Values may be added to this. - * @param requestURLString The URL to which to send the request. - * @param handler A block to be executed upon completion. Guaranteed to be called, but not - * always on the main thread. - */ -- (void)executeOnePlatformRequest:(NSDictionary *)requestBody - forURL:(NSString *)requestURLString - completionHandler:(FIRNetworkRequestCompletionHandler)handler; - -@end - -/** Encodes the API key in a query parameter string. */ -NSString *_Nullable FIRDynamicLinkAPIKeyParameter(NSString *apiKey); - -/** Creates and returns an NSData object from an NSDictionary along with any error. */ -NSData *_Nullable FIRDataWithDictionary(NSDictionary *dictionary, NSError **_Nullable error); - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h b/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h deleted file mode 100644 index 6f59960dd3e..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinksCommon.h" - -NS_ASSUME_NONNULL_BEGIN - -/** A definition for a block used by methods that are asynchronous and may produce errors. */ -typedef void (^FIRDynamicLinkNetworkingErrorHandler)(NSError *_Nullable error); - -/** A definition for a block used to return a pending Dynamic Link. */ -typedef void (^FIRPostInstallAttributionCompletionHandler)( - NSDictionary *_Nullable dynamicLinkParameters, - NSString *_Nullable matchMessage, - NSError *_Nullable error); - -/** A definition for a block used to return data and errors after an asynchronous task. */ -typedef void (^FIRNetworkRequestCompletionHandler)(NSData *_Nullable data, - NSURLResponse *_Nullable response, - NSError *_Nullable error); - -// these enums must be in sync with google/firebase/dynamiclinks/v1/dynamic_links.proto -typedef NS_ENUM(NSInteger, FIRDynamicLinkNetworkingUniqueMatchVisualStyle) { - // Unknown style. - FIRDynamicLinkNetworkingUniqueMatchVisualStyleUnknown = 0, - // Default style. - FIRDynamicLinkNetworkingUniqueMatchVisualStyleDefault = 1, - // Custom style. - FIRDynamicLinkNetworkingUniqueMatchVisualStyleCustom = 2, -}; - -typedef NS_ENUM(NSInteger, FIRDynamicLinkNetworkingRetrievalProcessType) { - // Unknown method. - FIRDynamicLinkNetworkingRetrievalProcessTypeUnknown = 0, - // iSDK performs a server lookup using default match in the background - // when app is first-opened; no API called by developer. - FIRDynamicLinkNetworkingRetrievalProcessTypeImplicitDefault = 1, - // iSDK performs a server lookup by device heuristics upon a dev API call. - FIRDynamicLinkNetworkingRetrievalProcessTypeExplicitDefault = 2, - // iSDK performs a unique match only if default match is found upon a dev - // API call. - FIRDynamicLinkNetworkingRetrievalProcessTypeOptionalUnique = 3, -}; - -/** - * @fn FIRMakeHTTPRequest - * @abstract A basic and simple network request method. - * @param request The NSURLRequest with which to perform the network request. - * @param completion The handler executed after the request has completed. - */ -void FIRMakeHTTPRequest(NSURLRequest *request, FIRNetworkRequestCompletionHandler completion); - -/** The base of the FDL API URL */ -FOUNDATION_EXPORT NSString *const kApiaryRestBaseUrl; - -/** - * @class FIRDynamicLinkNetworking - * @abstract The class used to handle all network communications for the service. - */ -@interface FIRDynamicLinkNetworking : NSObject - -/** - * @method initWithAPIKey:URLScheme: - * @param URLScheme Custom URL scheme of the app. - * @param APIKey API Key value. - */ -- (instancetype)initWithAPIKey:(NSString *)APIKey - URLScheme:(NSString *)URLScheme NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -/** - * @method resolveShortLink:URLScheme:APIKey:completion: - * @abstract Retrieves the details of the durable link that the shortened URL represents - * @param url A Short Dynamic Link. - * @param completion Block to be run upon completion. - */ -- (void)resolveShortLink:(NSURL *)url - FDLSDKVersion:(NSString *)FDLSDKVersion - completion:(FIRDynamicLinkResolverHandler)completion; - -/** - * @method - * retrievePendingDynamicLinkWithIOSVersion:resolutionHeight:resolutionWidth:locale:localeRaw:timezone:modelName:FDLSDKVersion:appInstallationDate:uniqueMatchVisualStyle:retrievalProcessType:handler: - * @abstract Retrieves a pending link from the server using the supplied device info and returns it - * by executing the completion handler. - */ -- (void)retrievePendingDynamicLinkWithIOSVersion:(NSString *)IOSVersion - resolutionHeight:(NSInteger)resolutionHeight - resolutionWidth:(NSInteger)resolutionWidth - locale:(NSString *)locale - localeRaw:(NSString *)localeRaw - localeFromWebView:(NSString *)localeFromWebView - timezone:(NSString *)timezone - modelName:(NSString *)modelName - FDLSDKVersion:(NSString *)FDLSDKVersion - appInstallationDate:(NSDate *_Nullable)appInstallationDate - uniqueMatchVisualStyle: - (FIRDynamicLinkNetworkingUniqueMatchVisualStyle)uniqueMatchVisualStyle - retrievalProcessType: - (FIRDynamicLinkNetworkingRetrievalProcessType)retrievalProcessType - uniqueMatchLinkToCheck:(NSURL *)uniqueMatchLinkToCheck - handler: - (FIRPostInstallAttributionCompletionHandler)handler; -/** - * @method convertInvitation:handler: - * @abstract Marks an invitation as converted. You should call this method in your application after - * the user performs an action that represents a successful conversion. - * @param invitationID The invitation ID of the link. - * @param handler A block that is called upon completion. If successful, the error parameter will be - * nil. This is always executed on the main thread. - */ -- (void)convertInvitation:(NSString *)invitationID - handler:(nullable FIRDynamicLinkNetworkingErrorHandler)handler; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.m b/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.m deleted file mode 100644 index 476bf044f0c..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.m +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking+Private.h" - -#import "FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.h" -#import "FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.h" -#import "FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.h" -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -NS_ASSUME_NONNULL_BEGIN - -NSString *const kApiaryRestBaseUrl = @"https://appinvite-pa.googleapis.com/v1"; -static NSString *const kiOSReopenRestBaseUrl = @"https://firebasedynamiclinks.googleapis.com/v1"; - -// Endpoint for default retrieval process V2. (Endpoint version is V1) -static NSString *const kIosPostInstallAttributionRestBaseUrl = - @"https://firebasedynamiclinks.googleapis.com/v1"; - -static NSString *const kReasonString = @"reason"; -static NSString *const kiOSInviteReason = @"ios_invite"; - -NSString *const kFDLResolvedLinkDeepLinkURLKey = @"deepLink"; -NSString *const kFDLResolvedLinkMinAppVersionKey = @"iosMinAppVersion"; -static NSString *const kFDLAnalyticsDataSourceKey = @"utmSource"; -static NSString *const kFDLAnalyticsDataMediumKey = @"utmMedium"; -static NSString *const kFDLAnalyticsDataCampaignKey = @"utmCampaign"; -static NSString *const kFDLAnalyticsDataTermKey = @"utmTerm"; -static NSString *const kFDLAnalyticsDataContentKey = @"utmContent"; -static NSString *const kHeaderIosBundleIdentifier = @"X-Ios-Bundle-Identifier"; -static NSString *const kGenericErrorDomain = @"com.firebase.dynamicLinks"; - -typedef NSDictionary *_Nullable (^FIRDLNetworkingParserBlock)( - NSString *requestURLString, - NSData *data, - NSString *_Nullable *_Nonnull matchMessagePtr, - NSError *_Nullable *_Nullable errorPtr); - -NSString *FIRURLParameterString(NSString *key, NSString *value) { - if (key.length > 0) { - return [NSString stringWithFormat:@"?%@=%@", key, value]; - } - return @""; -} - -NSString *_Nullable FIRDynamicLinkAPIKeyParameter(NSString *apiKey) { - return apiKey ? FIRURLParameterString(@"key", apiKey) : nil; -} - -void FIRMakeHTTPRequest(NSURLRequest *request, FIRNetworkRequestCompletionHandler completion) { - NSURLSessionConfiguration *sessionConfig = - [NSURLSessionConfiguration defaultSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig]; - NSURLSessionDataTask *dataTask = - [session dataTaskWithRequest:request - completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, - NSError *_Nullable error) { - completion(data, response, error); - }]; - [dataTask resume]; -} - -NSData *_Nullable FIRDataWithDictionary(NSDictionary *dictionary, NSError **_Nullable error) { - return [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:error]; -} - -@implementation FIRDynamicLinkNetworking { - NSString *_APIKey; - NSString *_URLScheme; -} - -- (instancetype)initWithAPIKey:(NSString *)APIKey URLScheme:(NSString *)URLScheme { - NSParameterAssert(APIKey); - NSParameterAssert(URLScheme); - if (self = [super init]) { - _APIKey = [APIKey copy]; - _URLScheme = [URLScheme copy]; - } - return self; -} - -+ (nullable NSError *)extractErrorForShortLink:(NSURL *)url - data:(NSData *)data - response:(NSURLResponse *)response - error:(nullable NSError *)error { - if (error) { - return error; - } - - NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; - NSError *customError = nil; - - if (![response isKindOfClass:[NSHTTPURLResponse class]]) { - customError = - [NSError errorWithDomain:kGenericErrorDomain - code:0 - userInfo:@{@"message" : @"Response should be of type NSHTTPURLResponse."}]; - } else if ((statusCode < 200 || statusCode >= 300) && data) { - NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - if ([result isKindOfClass:[NSDictionary class]] && [result objectForKey:@"error"]) { - id err = [result objectForKey:@"error"]; - customError = [NSError errorWithDomain:kGenericErrorDomain code:statusCode userInfo:err]; - } else { - customError = [NSError - errorWithDomain:kGenericErrorDomain - code:0 - userInfo:@{ - @"message" : - [NSString stringWithFormat:@"Failed to resolve link: %@", url.absoluteString] - }]; - } - } - - return customError; -} - -#pragma mark - Public interface - -- (void)resolveShortLink:(NSURL *)url - FDLSDKVersion:(NSString *)FDLSDKVersion - completion:(FIRDynamicLinkResolverHandler)handler { - NSParameterAssert(handler); - if (!url) { - handler(nil, nil); - return; - } - - NSDictionary *requestBody = @{ - @"requestedLink" : url.absoluteString, - @"bundle_id" : [NSBundle mainBundle].bundleIdentifier, - @"sdk_version" : FDLSDKVersion - }; - - FIRNetworkRequestCompletionHandler resolveLinkCallback = - ^(NSData *data, NSURLResponse *response, NSError *error) { - NSURL *resolvedURL = nil; - NSError *extractedError = [FIRDynamicLinkNetworking extractErrorForShortLink:url - data:data - response:response - error:error]; - - if (!extractedError && data) { - NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - if ([result isKindOfClass:[NSDictionary class]]) { - id invitationIDObject = [result objectForKey:@"invitationId"]; - - NSString *invitationIDString; - if ([invitationIDObject isKindOfClass:[NSDictionary class]]) { - NSDictionary *invitationIDDictionary = invitationIDObject; - invitationIDString = invitationIDDictionary[@"id"]; - } else if ([invitationIDObject isKindOfClass:[NSString class]]) { - invitationIDString = invitationIDObject; - } - - NSString *deepLinkString = result[kFDLResolvedLinkDeepLinkURLKey]; - NSString *minAppVersion = result[kFDLResolvedLinkMinAppVersionKey]; - NSString *utmSource = result[kFDLAnalyticsDataSourceKey]; - NSString *utmMedium = result[kFDLAnalyticsDataMediumKey]; - NSString *utmCampaign = result[kFDLAnalyticsDataCampaignKey]; - NSString *utmContent = result[kFDLAnalyticsDataContentKey]; - NSString *utmTerm = result[kFDLAnalyticsDataTermKey]; - resolvedURL = FIRDLDeepLinkURLWithInviteID( - invitationIDString, deepLinkString, utmSource, utmMedium, utmCampaign, utmContent, - utmTerm, NO, nil, minAppVersion, self->_URLScheme, nil); - } - } - handler(resolvedURL, extractedError); - }; - - NSString *requestURLString = - [NSString stringWithFormat:@"%@/reopenAttribution%@", kiOSReopenRestBaseUrl, - FIRDynamicLinkAPIKeyParameter(_APIKey)]; - [self executeOnePlatformRequest:requestBody - forURL:requestURLString - completionHandler:resolveLinkCallback]; -} - -- (void)retrievePendingDynamicLinkWithIOSVersion:(NSString *)IOSVersion - resolutionHeight:(NSInteger)resolutionHeight - resolutionWidth:(NSInteger)resolutionWidth - locale:(NSString *)locale - localeRaw:(NSString *)localeRaw - localeFromWebView:(NSString *)localeFromWebView - timezone:(NSString *)timezone - modelName:(NSString *)modelName - FDLSDKVersion:(NSString *)FDLSDKVersion - appInstallationDate:(NSDate *_Nullable)appInstallationDate - uniqueMatchVisualStyle: - (FIRDynamicLinkNetworkingUniqueMatchVisualStyle)uniqueMatchVisualStyle - retrievalProcessType: - (FIRDynamicLinkNetworkingRetrievalProcessType)retrievalProcessType - uniqueMatchLinkToCheck:(NSURL *)uniqueMatchLinkToCheck - handler: - (FIRPostInstallAttributionCompletionHandler)handler { - NSParameterAssert(handler); - - NSMutableDictionary *requestBody = [@{ - @"bundleId" : [NSBundle mainBundle].bundleIdentifier, - @"device" : - [FDLDeviceHeuristicsHelper FDLDeviceInfoDictionaryFromResolutionHeight:resolutionHeight - resolutionWidth:resolutionWidth - locale:locale - localeRaw:localeRaw - localeFromWebview:localeFromWebView - timeZone:timezone - modelName:modelName], - @"iosVersion" : IOSVersion, - @"sdkVersion" : FDLSDKVersion, - @"visualStyle" : @(uniqueMatchVisualStyle), - @"retrievalMethod" : @(retrievalProcessType), - } mutableCopy]; - if (appInstallationDate) { - requestBody[@"appInstallationTime"] = @((NSInteger)[appInstallationDate timeIntervalSince1970]); - } - if (uniqueMatchLinkToCheck) { - requestBody[@"uniqueMatchLinkToCheck"] = uniqueMatchLinkToCheck.absoluteString; - } - - FIRDLNetworkingParserBlock responseParserBlock = ^NSDictionary *_Nullable( - NSString *requestURLString, NSData *data, NSString **matchMessagePtr, NSError **errorPtr) { - NSError *serializationError; - NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data - options:0 - error:&serializationError]; - - if (serializationError) { - if (errorPtr != nil) { - *errorPtr = serializationError; - } - return nil; - } - - NSString *matchMessage = result[@"matchMessage"]; - if (matchMessage.length) { - *matchMessagePtr = matchMessage; - } - - // Create the dynamic link parameters - NSMutableDictionary *dynamicLinkParameters = [[NSMutableDictionary alloc] init]; - dynamicLinkParameters[kFIRDLParameterInviteId] = result[@"invitationId"]; - dynamicLinkParameters[kFIRDLParameterDeepLinkIdentifier] = result[@"deepLink"]; - if (result[@"deepLink"]) { - dynamicLinkParameters[kFIRDLParameterMatchType] = - FIRDLMatchTypeStringFromServerString(result[@"attributionConfidence"]); - } - dynamicLinkParameters[kFIRDLParameterSource] = result[@"utmSource"]; - dynamicLinkParameters[kFIRDLParameterMedium] = result[@"utmMedium"]; - dynamicLinkParameters[kFIRDLParameterCampaign] = result[@"utmCampaign"]; - dynamicLinkParameters[kFIRDLParameterMinimumAppVersion] = result[@"appMinimumVersion"]; - dynamicLinkParameters[kFIRDLParameterRequestIPVersion] = result[@"requestIpVersion"]; - dynamicLinkParameters[kFIRDLParameterMatchMessage] = matchMessage; - - return [dynamicLinkParameters copy]; - }; - - [self sendRequestWithBaseURLString:kIosPostInstallAttributionRestBaseUrl - requestBody:requestBody - endpointPath:@"installAttribution" - parserBlock:responseParserBlock - completion:handler]; -} - -- (void)convertInvitation:(NSString *)invitationID - handler:(nullable FIRDynamicLinkNetworkingErrorHandler)handler { - if (!invitationID) { - return; - } - - NSDictionary *requestBody = @{ - @"invitationId" : @{@"id" : invitationID}, - @"containerClientId" : @{ - @"type" : @"IOS", - } - }; - - FIRNetworkRequestCompletionHandler convertInvitationCallback = - ^(NSData *data, NSURLResponse *response, NSError *error) { - if (handler) { - dispatch_async(dispatch_get_main_queue(), ^{ - handler(error); - }); - } - }; - - NSString *requestURL = [NSString stringWithFormat:@"%@/convertInvitation%@", kApiaryRestBaseUrl, - FIRDynamicLinkAPIKeyParameter(_APIKey)]; - - [self executeOnePlatformRequest:requestBody - forURL:requestURL - completionHandler:convertInvitationCallback]; -} - -#pragma mark - Internal methods - -- (void)sendRequestWithBaseURLString:(NSString *)baseURL - requestBody:(NSDictionary *)requestBody - endpointPath:(NSString *)endpointPath - parserBlock:(FIRDLNetworkingParserBlock)parserBlock - completion:(FIRPostInstallAttributionCompletionHandler)handler { - NSParameterAssert(handler); - NSString *requestURLString = [NSString - stringWithFormat:@"%@/%@%@", baseURL, endpointPath, FIRDynamicLinkAPIKeyParameter(_APIKey)]; - - FIRNetworkRequestCompletionHandler completeInvitationByDeviceCallback = - ^(NSData *data, NSURLResponse *response, NSError *error) { - if (error || !data) { - dispatch_async(dispatch_get_main_queue(), ^{ - handler(nil, nil, error); - }); - return; - } - - NSString *matchMessage = nil; - NSError *parsingError = nil; - NSDictionary *parsedDynamicLinkParameters = - parserBlock(requestURLString, data, &matchMessage, &parsingError); - - dispatch_async(dispatch_get_main_queue(), ^{ - handler(parsedDynamicLinkParameters, matchMessage, parsingError); - }); - }; - - [self executeOnePlatformRequest:requestBody - forURL:requestURLString - completionHandler:completeInvitationByDeviceCallback]; -} - -- (void)executeOnePlatformRequest:(NSDictionary *)requestBody - forURL:(NSString *)requestURLString - completionHandler:(FIRNetworkRequestCompletionHandler)handler { - NSURL *requestURL = [NSURL URLWithString:requestURLString]; - - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL]; - - // TODO: Verify that HTTPBody and HTTPMethod are iOS 8+ and find an alternative. - request.HTTPBody = FIRDataWithDictionary(requestBody, nil); - request.HTTPMethod = @"POST"; - - [request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"]; - - // Set the iOS bundleID as a request header. - NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; - if (bundleID) { - [request setValue:bundleID forHTTPHeaderField:kHeaderIosBundleIdentifier]; - } - FIRMakeHTTPRequest(request, handler); -} - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLinks+FirstParty.h b/FirebaseDynamicLinks/Sources/FIRDynamicLinks+FirstParty.h deleted file mode 100644 index db277969d7a..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLinks+FirstParty.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h" // IWYU pragma: export - -#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h" - -@class UIViewController; - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRDynamicLinks (FirstParty) - -/** - * @method setUpWithLaunchOptions::apiKey:clientID:urlScheme:userDefaults: - * @abstract Set up Dynamic Links. - * @param launchOptions launchOptions from |application:didFinishLaunchingWithOptions:|. If nil, the - * deep link may appear twice on iOS 9 if a user clicks on a link before opening the app. - * @param apiKey API key for API access. - * @param clientID client ID for API access. - * @param urlScheme A custom url scheme used by the application. If nil, bundle id will be used. - * @param userDefaults The defaults from a user’s defaults database. If nil, standard - * NSUserDefaults will be used. - * @return whether the Dynamic Links was set up successfully. - */ -- (BOOL)setUpWithLaunchOptions:(nullable NSDictionary *)launchOptions - apiKey:(NSString *)apiKey - clientID:(NSString *)clientID - urlScheme:(nullable NSString *)urlScheme - userDefaults:(nullable NSUserDefaults *)userDefaults - DEPRECATED_MSG_ATTRIBUTE( - "Use [FIRDynamicLinks setUpWithLaunchOptions::apiKey:urlScheme:userDefaults:] instead."); - -/** - * @method setUpWithLaunchOptions::apiKey:urlScheme:userDefaults: - * @abstract Set up Dynamic Links. - * @param launchOptions launchOptions from |application:didFinishLaunchingWithOptions:|. If nil, the - * deep link may appear twice on iOS 9 if a user clicks on a link before opening the app. - * @param apiKey API key for API access. - * @param urlScheme A custom url scheme used by the application. If nil, bundle id will be used. - * @param userDefaults The defaults from a user’s defaults database. If nil, standard - * NSUserDefaults will be used. - * @return whether the Dynamic Links was set up successfully. - */ -- (BOOL)setUpWithLaunchOptions:(nullable NSDictionary *)launchOptions - apiKey:(NSString *)apiKey - urlScheme:(nullable NSString *)urlScheme - userDefaults:(nullable NSUserDefaults *)userDefaults; - -/** - * @method checkForPendingDynamicLink - * @abstract check for a pending Dynamic Link. This method should be called from your - * |UIApplicationDelegate|'s |application:didFinishLaunchingWithOptions:|. If a Dynamic Link is - * found, you'll receive an URL in |application:openURL:options:| on iOS9 or later, and - * |application:openURL:sourceApplication:annotation| on iOS 8 and earlier. From there you could - * get a |GINDeepLink| object by calling |dynamicLinkFromCustomSchemeURL:|. If no Dynamic Link - * is found, you will receive callback with "dismiss link". For "dismiss link" the - * FIRDynamicLink.url property is nil. - * For new integrations prefer to use method - * retrievePendingDynamicLinkWithRetrievalProcessType:retrievalOptions:delegate: . This method - * will be the only way to use FDL in near future. - */ -- (void)checkForPendingDynamicLink; - -/** - @method checkForPendingDynamicLinkUsingExperimentalRetrievalProcess - @abstract The same as checkForPendingDynamicLink. Will be using experimental retrieval process. - */ -- (void)checkForPendingDynamicLinkUsingExperimentalRetrievalProcess; - -/** - * @method sharedInstance - * @abstract Method for compatibility with old interface of the GINDurableDeepLinkService - */ -+ (instancetype) - sharedInstance DEPRECATED_MSG_ATTRIBUTE("Use [FIRDynamicLinks dynamicLinks] instead."); - -/** - * @method checkForPendingDeepLink - * @abstract Method for compatibility with old interface of the GINDurableDeepLinkService - */ -- (void)checkForPendingDeepLink DEPRECATED_MSG_ATTRIBUTE( - "Use [FIRDynamicLinks checkForPendingDynamicLink] instead."); - -/** - * @method deepLinkFromCustomSchemeURL: - * @abstract Method for compatibility with old interface of the GINDurableDeepLinkService - */ -- (nullable FIRDynamicLink *)deepLinkFromCustomSchemeURL:(NSURL *)url - DEPRECATED_MSG_ATTRIBUTE("Use [FIRDynamicLinks dynamicLinkFromCustomSchemeURL:] instead."); - -/** - * @method deepLinkFromUniversalLinkURL: - * @abstract Method for compatibility with old interface of the GINDurableDeepLinkService - */ -- (nullable FIRDynamicLink *)deepLinkFromUniversalLinkURL:(NSURL *)url - DEPRECATED_MSG_ATTRIBUTE("Use [FIRDynamicLinks dynamicLinkFromUniversalLinkURL:] instead."); - -/** - * @method shouldHandleDeepLinkFromCustomSchemeURL: - * @abstract Method for compatibility with old interface of the GINDurableDeepLinkService - */ -- (BOOL)shouldHandleDeepLinkFromCustomSchemeURL:(NSURL *)url - DEPRECATED_MSG_ATTRIBUTE("Use [FIRDynamicLinks shouldHandleDynamicLinkFromCustomSchemeURL:]" - " instead."); - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLinks+Private.h b/FirebaseDynamicLinks/Sources/FIRDynamicLinks+Private.h deleted file mode 100644 index 53db683e54a..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLinks+Private.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h" - -@class UIViewController; - -NS_ASSUME_NONNULL_BEGIN - -/** - * The version of the Firebase Dynamic Link Service SDK. - */ -FOUNDATION_EXPORT NSString *const kFIRDLVersion; - -/** - * Exposed for Unit Tests usage. - */ -FOUNDATION_EXPORT NSString *const kFIRDLReadDeepLinkAfterInstallKey; - -@interface FIRDynamicLinks (Private) - -/** - * @abstract Internal method to return is automatic retrieval of dynamic link enabled or not. - * To be used for internal purposes. - */ -+ (BOOL)isAutomaticRetrievalEnabled; - -/** - * @property APIKey - * @abstract API Key for API access. - */ -@property(nonatomic, copy, readonly) NSString *APIKey; - -/** - * @property URLScheme - * @abstract Custom URL scheme. - */ -@property(nonatomic, copy, readonly, nullable) NSString *URLScheme; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/FIRDynamicLinks.m b/FirebaseDynamicLinks/Sources/FIRDynamicLinks.m deleted file mode 100644 index f7b0b0f5e3c..00000000000 --- a/FirebaseDynamicLinks/Sources/FIRDynamicLinks.m +++ /dev/null @@ -1,805 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h" - -#import - -#ifdef FIRDynamicLinks3P -#import "FirebaseCore/Extension/FirebaseCoreInternal.h" -#import "FirebaseDynamicLinks/Sources/FIRDLScionLogging.h" -#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" -#else -#import "FirebaseCore/Sources/Public/FirebaseCore/FIRVersion.h" -#endif - -#ifdef FIRDynamicLinks3P -#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h" -#endif -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.h" -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessProtocols.h" -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinks+FirstParty.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinks+Private.h" -#import "FirebaseDynamicLinks/Sources/Logging/FDLLogging.h" -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -// We should only read the deeplink after install once. We use the following key to store the state -// in the user defaults. -NSString *const kFIRDLReadDeepLinkAfterInstallKey = - @"com.google.appinvite.readDeeplinkAfterInstall"; - -// We should only open url once. We use the following key to store the state in the user defaults. -static NSString *const kFIRDLOpenURLKey = @"com.google.appinvite.openURL"; - -// Custom domains to be allowed are optionally added as an array to the info.plist. -static NSString *const kInfoPlistCustomDomainsKey = @"FirebaseDynamicLinksCustomDomains"; - -NS_ASSUME_NONNULL_BEGIN - -@interface FIRDynamicLinks () - -// API Key for API access. -@property(nonatomic, copy) NSString *APIKey; - -// Custom URL scheme. -@property(nonatomic, copy) NSString *URLScheme; - -// Networking object for Dynamic Links -@property(nonatomic, readonly) FIRDynamicLinkNetworking *dynamicLinkNetworking; - -@property(atomic, assign) BOOL retrievingPendingDynamicLink; - -@end - -#ifdef FIRDynamicLinks3P -// Error code from FDL. -static const NSInteger FIRErrorCodeDurableDeepLinkFailed = -119; - -@interface FIRDynamicLinks () { - /// Stored Analytics reference, if it exists. - id _Nullable _analytics; -} -@end - -// DynamicLinks doesn't provide any functionality to other components, -// so it provides a private, empty protocol that it conforms to and use it for registration. - -@protocol FIRDynamicLinksInstanceProvider -@end - -@interface FIRDynamicLinks () - -@end - -#endif - -@implementation FIRDynamicLinks { - // User defaults passed. - NSUserDefaults *_userDefaults; - - FIRDynamicLinkNetworking *_dynamicLinkNetworking; - - id _retrievalProcess; -} - -#pragma mark - Object lifecycle - -#ifdef FIRDynamicLinks3P - -+ (void)load { - [FIRApp registerInternalLibrary:self withName:@"fire-dl"]; -} - -+ (nonnull NSArray *)componentsToRegister { - FIRComponentCreationBlock creationBlock = - ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { - // Don't return an instance when it's not the default app. - if (!container.app.isDefaultApp) { - // Only configure for the default FIRApp. - FDLLog(FDLLogLevelInfo, FDLLogIdentifierSetupNonDefaultApp, - @"Firebase Dynamic Links only " - "works with the default app."); - return nil; - } - - // Ensure it's cached so it returns the same instance every time dynamicLinks is called. - *isCacheable = YES; - id analytics = FIR_COMPONENT(FIRAnalyticsInterop, container); - FIRDynamicLinks *dynamicLinks = [[FIRDynamicLinks alloc] initWithAnalytics:analytics]; - [dynamicLinks configureDynamicLinks:container.app]; - - if ([FIRDynamicLinks isAutomaticRetrievalEnabled]) { - [dynamicLinks checkForPendingDynamicLink]; - } - return dynamicLinks; - }; - FIRComponent *dynamicLinksProvider = - [FIRComponent componentWithProtocol:@protocol(FIRDynamicLinksInstanceProvider) - instantiationTiming:FIRInstantiationTimingEagerInDefaultApp - creationBlock:creationBlock]; - - return @[ dynamicLinksProvider ]; -} - -- (void)configureDynamicLinks:(FIRApp *)app { - FIROptions *options = app.options; - NSError *error; - NSMutableString *errorDescription; - NSString *urlScheme; - - if (options.APIKey.length == 0) { - errorDescription = [@"API key must not be nil or empty." mutableCopy]; - } - - if (!errorDescription) { - // setup FDL if no error detected - urlScheme = options.deepLinkURLScheme ?: [NSBundle mainBundle].bundleIdentifier; - [self setUpWithLaunchOptions:nil apiKey:options.APIKey urlScheme:urlScheme userDefaults:nil]; - } else { - NSString *description = - [NSString stringWithFormat:@"Configuration failed for service DynamicLinks."]; - NSDictionary *errorDict = @{ - NSLocalizedDescriptionKey : description, - NSLocalizedFailureReasonErrorKey : errorDescription - }; - error = [NSError errorWithDomain:kFirebaseDurableDeepLinkErrorDomain - code:FIRErrorCodeDurableDeepLinkFailed - userInfo:errorDict]; - } - if (error) { - NSString *message = - [NSString stringWithFormat: - @"Firebase Dynamic Links has stopped your project " - @"because there are incorrect values provided in Firebase's configuration " - @"options that may prevent your app from behaving as expected:\n\n" - @"Error: %@\n\n" - @"Please fix these issues to ensure that Firebase is correctly configured in " - @"your project.", - error.localizedFailureReason]; - [NSException raise:kFirebaseDurableDeepLinkErrorDomain format:@"%@", message]; - } - [self checkForCustomDomainEntriesInInfoPlist]; -} - -- (instancetype)initWithAnalytics:(nullable id)analytics { - self = [super init]; - if (self) { - _analytics = analytics; - } - return self; -} - -+ (instancetype)dynamicLinks { - FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. - id instance = - FIR_COMPONENT(FIRDynamicLinksInstanceProvider, defaultApp.container); - return (FIRDynamicLinks *)instance; -} - -#else -+ (instancetype)dynamicLinks { - static FIRDynamicLinks *dynamicLinks; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - dynamicLinks = [[self alloc] init]; - }); - return dynamicLinks; -} -#endif - -#pragma mark - Custom domains - -- (instancetype)init { - self = [super init]; - if (self) { - [self checkForCustomDomainEntriesInInfoPlist]; - } - return self; -} - -// Check for custom domains entry in PLIST file. -- (void)checkForCustomDomainEntriesInInfoPlist { - // Check to see if FirebaseDynamicLinksCustomDomains array is present. - NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary; - NSArray *customDomains = infoDictionary[kInfoPlistCustomDomainsKey]; - if (customDomains) { - FIRDLAddToAllowListForCustomDomainsArray(customDomains); - } -} - -#pragma mark - First party interface - -- (BOOL)setUpWithLaunchOptions:(nullable NSDictionary *)launchOptions - apiKey:(NSString *)apiKey - urlScheme:(nullable NSString *)urlScheme - userDefaults:(nullable NSUserDefaults *)userDefaults { - if (apiKey == nil) { - FDLLog(FDLLogLevelError, FDLLogIdentifierSetupNilAPIKey, @"API Key must not be nil."); - return NO; - } - - _APIKey = [apiKey copy]; - _URLScheme = urlScheme.length ? [urlScheme copy] : [NSBundle mainBundle].bundleIdentifier; - - if (!userDefaults) { - _userDefaults = [NSUserDefaults standardUserDefaults]; - } else { - _userDefaults = userDefaults; - } - - NSURL *url = launchOptions[UIApplicationLaunchOptionsURLKey]; - if (url) { - if ([self canParseCustomSchemeURL:url] || [self canParseUniversalLinkURL:url]) { - // Make sure we don't call |checkForPendingDynamicLink| again if - // a strong deep link is found. - [_userDefaults setBool:YES forKey:kFIRDLReadDeepLinkAfterInstallKey]; - } - } - return YES; -} - -- (void)checkForPendingDynamicLinkUsingExperimentalRetrievalProcess { - [self checkForPendingDynamicLink]; -} - -- (void)checkForPendingDynamicLink { - // Make sure this method is called only once after the application was installed. - // kFIRDLOpenURLKey marks checkForPendingDynamic link had been called already so no need to do it - // again. kFIRDLReadDeepLinkAfterInstallKey marks we have already read a deeplink after the - // install and so no need to do check for pending dynamic link. - BOOL appInviteDeepLinkRead = [_userDefaults boolForKey:kFIRDLOpenURLKey] || - [_userDefaults boolForKey:kFIRDLReadDeepLinkAfterInstallKey]; - - if (appInviteDeepLinkRead || self.retrievingPendingDynamicLink) { - NSString *errorDescription = - appInviteDeepLinkRead ? NSLocalizedString(@"Link was already retrieved", @"Error message") - : NSLocalizedString(@"Already retrieving link", @"Error message"); - [self handlePendingDynamicLinkRetrievalFailureWithErrorCode:-1 - errorDescription:errorDescription - underlyingError:nil]; - return; - } - - self.retrievingPendingDynamicLink = YES; - - FIRDLRetrievalProcessFactory *factory = - [[FIRDLRetrievalProcessFactory alloc] initWithNetworkingService:self.dynamicLinkNetworking - URLScheme:_URLScheme - APIKey:_APIKey - FDLSDKVersion:FIRFirebaseVersion() - delegate:self]; - _retrievalProcess = [factory automaticRetrievalProcess]; - [_retrievalProcess retrievePendingDynamicLink]; -} - -// Disable deprecated warning for internal methods. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-implementations" - -+ (instancetype)sharedInstance { - return [self dynamicLinks]; -} - -- (BOOL)setUpWithLaunchOptions:(nullable NSDictionary *)launchOptions - apiKey:(NSString *)apiKey - clientID:(NSString *)clientID - urlScheme:(nullable NSString *)urlScheme - userDefaults:(nullable NSUserDefaults *)userDefaults { - return [self setUpWithLaunchOptions:launchOptions - apiKey:apiKey - urlScheme:urlScheme - userDefaults:userDefaults]; -} - -- (void)checkForPendingDeepLink { - [self checkForPendingDynamicLink]; -} - -- (nullable FIRDynamicLink *)deepLinkFromCustomSchemeURL:(NSURL *)url { - return [self dynamicLinkFromCustomSchemeURL:url]; -} - -- (nullable FIRDynamicLink *)deepLinkFromUniversalLinkURL:(NSURL *)url { - return [self dynamicLinkFromUniversalLinkURL:url]; -} - -- (BOOL)shouldHandleDeepLinkFromCustomSchemeURL:(NSURL *)url { - return [self shouldHandleDynamicLinkFromCustomSchemeURL:url]; -} - -#pragma clang pop - -#pragma mark - Public interface - -- (BOOL)shouldHandleDynamicLinkFromCustomSchemeURL:(NSURL *)url { - // Return NO if the URL scheme does not match. - if (![self canParseCustomSchemeURL:url]) { - return NO; - } - - // We can handle "/link" and "/link/dismiss". The latter will return a nil deep link. - return ([url.path hasPrefix:@"/link"] && [url.host isEqualToString:@"google"]); -} - -- (nullable FIRDynamicLink *)dynamicLinkFromCustomSchemeURL:(NSURL *)url { - // Return nil if the URL scheme does not match. - if (![self canParseCustomSchemeURL:url]) { - return nil; - } - - if ([url.path isEqualToString:@"/link"] && [url.host isEqualToString:@"google"]) { - // This URL is a callback url from a device heuristics based match - // Extract information from query. - NSString *query = url.query; - - NSDictionary *parameters = FIRDLDictionaryFromQuery(query); - - // As long as the deepLink has some parameter, return it. - if (parameters.count > 0) { - FIRDynamicLink *dynamicLink = - [[FIRDynamicLink alloc] initWithParametersDictionary:parameters]; - -#ifdef GIN_SCION_LOGGING - if (dynamicLink.url) { - BOOL isFirstOpen = ![_userDefaults boolForKey:kFIRDLReadDeepLinkAfterInstallKey]; - FIRDLLogEvent event = isFirstOpen ? FIRDLLogEventFirstOpen : FIRDLLogEventAppOpen; - FIRDLLogEventToScion(event, parameters[kFIRDLParameterSource], - parameters[kFIRDLParameterMedium], parameters[kFIRDLParameterCampaign], - _analytics); - } -#endif - // Make sure we don't call |checkForPendingDynamicLink| again if we did this already. - if ([_userDefaults boolForKey:kFIRDLOpenURLKey]) { - [_userDefaults setBool:YES forKey:kFIRDLReadDeepLinkAfterInstallKey]; - } - return dynamicLink; - } - } - return nil; -} - -- (nullable FIRDynamicLink *) - dynamicLinkInternalFromUniversalLinkURL:(NSURL *)url - completion: - (nullable FIRDynamicLinkUniversalLinkHandler)completion { - // Make sure the completion is always called on the main queue. - FIRDynamicLinkUniversalLinkHandler mainQueueCompletion = - ^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { - if (completion) { - dispatch_async(dispatch_get_main_queue(), ^{ - completion(dynamicLink, error); - }); - } - }; - - if ([self canParseUniversalLinkURL:url]) { - if (url.query.length > 0) { - NSDictionary *parameters = FIRDLDictionaryFromQuery(url.query); - if (parameters[kFIRDLParameterLink]) { - NSString *urlString = parameters[kFIRDLParameterLink]; - NSURL *deepLinkURL = [NSURL URLWithString:urlString]; - if (deepLinkURL) { - NSMutableDictionary *paramsDictionary = [[NSMutableDictionary alloc] - initWithDictionary:@{kFIRDLParameterDeepLinkIdentifier : urlString}]; - - if (parameters[kFIRDLParameterSource] != nil) { - [paramsDictionary setValue:parameters[kFIRDLParameterSource] - forKey:kFIRDLParameterSource]; - } - - if (parameters[kFIRDLParameterMedium] != nil) { - [paramsDictionary setValue:parameters[kFIRDLParameterMedium] - forKey:kFIRDLParameterMedium]; - } - - if (parameters[kFIRDLParameterTerm] != nil) { - [paramsDictionary setValue:parameters[kFIRDLParameterTerm] forKey:kFIRDLParameterTerm]; - } - - if (parameters[kFIRDLParameterCampaign] != nil) { - [paramsDictionary setValue:parameters[kFIRDLParameterCampaign] - forKey:(kFIRDLParameterCampaign)]; - } - - if (parameters[kFIRDLParameterContent] != nil) { - [paramsDictionary setValue:parameters[kFIRDLParameterContent] - forKey:kFIRDLParameterContent]; - } - - FIRDynamicLink *dynamicLink = - [[FIRDynamicLink alloc] initWithParametersDictionary:paramsDictionary]; - dynamicLink.matchType = FIRDLMatchTypeUnique; - dynamicLink.minimumAppVersion = parameters[kFIRDLParameterMinimumAppVersion]; - - // Call resolveShortLink:completion: to do logging. - // TODO: Create dedicated logging function to prevent this. - [self.dynamicLinkNetworking - resolveShortLink:url - FDLSDKVersion:FIRFirebaseVersion() - completion:^(NSURL *_Nullable resolverURL, NSError *_Nullable resolverError) { - mainQueueCompletion(dynamicLink, resolverError); - }]; -#ifdef GIN_SCION_LOGGING - FIRDLLogEventToScion(FIRDLLogEventAppOpen, parameters[kFIRDLParameterSource], - parameters[kFIRDLParameterMedium], - parameters[kFIRDLParameterCampaign], _analytics); -#endif - return dynamicLink; - } - } - } - } - - mainQueueCompletion( - nil, [[NSError alloc] initWithDomain:@"com.firebase.dynamicLinks" - code:1 - userInfo:@{ - NSLocalizedFailureReasonErrorKey : - @"Universal link URL could not be parsed by Dynamic Links." - }]); - return nil; -} - -- (nullable FIRDynamicLink *)dynamicLinkFromUniversalLinkURL:(NSURL *)url { - return [self dynamicLinkInternalFromUniversalLinkURL:url completion:nil]; -} - -- (void)dynamicLinkFromUniversalLinkURL:(NSURL *)url - completion:(FIRDynamicLinkUniversalLinkHandler)completion { - [self dynamicLinkInternalFromUniversalLinkURL:url completion:completion]; -} - -- (BOOL)handleUniversalLink:(NSURL *)universalLinkURL - completion:(FIRDynamicLinkUniversalLinkHandler)completion { - if ([self matchesShortLinkFormat:universalLinkURL]) { - __weak __typeof__(self) weakSelf = self; - [self resolveShortLink:universalLinkURL - completion:^(NSURL *url, NSError *error) { - __typeof__(self) strongSelf = weakSelf; - if (strongSelf) { - FIRDynamicLink *dynamicLink = [strongSelf dynamicLinkFromCustomSchemeURL:url]; - dispatch_async(dispatch_get_main_queue(), ^{ - completion(dynamicLink, error); - }); - } else { - completion(nil, nil); - } - }]; - return YES; - } else { - [self dynamicLinkFromUniversalLinkURL:universalLinkURL completion:completion]; - BOOL canHandleUniversalLink = - [self canParseUniversalLinkURL:universalLinkURL] && universalLinkURL.query.length > 0 && - FIRDLDictionaryFromQuery(universalLinkURL.query)[kFIRDLParameterLink]; - return canHandleUniversalLink; - } -} - -- (void)resolveShortLink:(NSURL *)url completion:(FIRDynamicLinkResolverHandler)completion { - [self.dynamicLinkNetworking resolveShortLink:url - FDLSDKVersion:FIRFirebaseVersion() - completion:completion]; -} - -- (BOOL)matchesShortLinkFormat:(NSURL *)url { - return FIRDLMatchesShortLinkFormat(url); -} - -#pragma mark - Private interface - -+ (BOOL)isAutomaticRetrievalEnabled { - id retrievalEnabledValue = - [[NSBundle mainBundle] infoDictionary][@"FirebaseDeepLinkAutomaticRetrievalEnabled"]; - if ([retrievalEnabledValue respondsToSelector:@selector(boolValue)]) { - return [retrievalEnabledValue boolValue]; - } - return YES; -} - -#pragma mark - Internal methods - -- (FIRDynamicLinkNetworking *)dynamicLinkNetworking { - if (!_dynamicLinkNetworking) { - _dynamicLinkNetworking = [[FIRDynamicLinkNetworking alloc] initWithAPIKey:_APIKey - URLScheme:_URLScheme]; - } - return _dynamicLinkNetworking; -} - -- (BOOL)canParseCustomSchemeURL:(nullable NSURL *)url { - if (url.scheme.length) { - NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier; - if ([url.scheme.lowercaseString isEqualToString:_URLScheme.lowercaseString] || - [url.scheme.lowercaseString isEqualToString:bundleIdentifier.lowercaseString]) { - return YES; - } - } - return NO; -} - -- (BOOL)canParseUniversalLinkURL:(nullable NSURL *)url { - return FIRDLCanParseUniversalLinkURL(url); -} - -- (BOOL)handleIncomingCustomSchemeDeepLink:(NSURL *)url { - return [self canParseCustomSchemeURL:url]; -} - -- (void)passRetrievedDynamicLinkToApplication:(NSURL *)url { - id applicationDelegate = [UIApplication sharedApplication].delegate; - if ([self isOpenUrlMethodPresentInAppDelegate:applicationDelegate]) { - // pass url directly to application delegate to avoid hop into - // iOS handling of the universal links - [applicationDelegate application:[UIApplication sharedApplication] openURL:url options:@{}]; - return; - } - - [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; -} - -- (BOOL)isOpenUrlMethodPresentInAppDelegate:(id)applicationDelegate { - return applicationDelegate && - [applicationDelegate respondsToSelector:@selector(application:openURL:options:)]; -} - -- (void)handlePendingDynamicLinkRetrievalFailureWithErrorCode:(NSInteger)errorCode - errorDescription:(NSString *)errorDescription - underlyingError:(nullable NSError *)underlyingError { - self.retrievingPendingDynamicLink = NO; -} - -#pragma mark - FIRDLRetrievalProcessDelegate - -- (void)retrievalProcess:(id)retrievalProcess - completedWithResult:(FIRDLRetrievalProcessResult *)result { - self.retrievingPendingDynamicLink = NO; - _retrievalProcess = nil; - - if (![_userDefaults boolForKey:kFIRDLOpenURLKey]) { - // Once we complete the Pending dynamic link retrieval, regardless of whether the retrieval is - // success or failure, we don't want to do the retrieval again on next app start. - // If we try to redo the retrieval again because of some error, the user will experience - // unwanted deeplinking when they restart the app next time. - [_userDefaults setBool:YES forKey:kFIRDLOpenURLKey]; - } - - NSURL *linkToPassToApp = [result URLWithCustomURLScheme:_URLScheme]; - [self passRetrievedDynamicLinkToApplication:linkToPassToApp]; -} - -#pragma mark - Diagnostics methods - -static NSString *kSelfDiagnoseOutputHeader = - @"---- Firebase Dynamic Links diagnostic output start ----\n"; -static NSString *kSelfDiagnoseOutputFooter = - @"---- Firebase Dynamic Links diagnostic output end ----\n"; - -+ (NSString *)genericDiagnosticInformation { - NSMutableString *genericDiagnosticInfo = [[NSMutableString alloc] init]; - - [genericDiagnosticInfo - appendFormat:@"Firebase Dynamic Links framework version %@\n", FIRFirebaseVersion()]; - [genericDiagnosticInfo appendFormat:@"System information: OS %@, OS version %@, model %@\n", - [UIDevice currentDevice].systemName, - [UIDevice currentDevice].systemVersion, - [UIDevice currentDevice].model]; - [genericDiagnosticInfo appendFormat:@"Current date %@\n", [NSDate date]]; - // TODO: bring this diagnostic info back when we shipped non-automatic retrieval - // [genericDiagnosticInfo appendFormat:@"AutomaticRetrievalEnabled: %@\n", - // [self isAutomaticRetrievalEnabled] ? @"YES" : @"NO"]; - - // Disable deprecated warning for internal methods. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - [genericDiagnosticInfo appendFormat:@"Device locale %@ (raw %@), timezone %@\n", - FIRDLDeviceLocale(), FIRDLDeviceLocaleRaw(), - FIRDLDeviceTimezone()]; -#pragma clang pop - - return genericDiagnosticInfo; -} - -+ (NSString *)diagnosticAnalyzeEntitlements { - NSString *embeddedMobileprovisionFilePath = [[[NSBundle mainBundle] bundlePath] - stringByAppendingPathComponent:@"embedded.mobileprovision"]; - - NSError *error; - NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:embeddedMobileprovisionFilePath - options:0 - error:&error]; - - if (!profileData.length || error) { - return @"\tSKIPPED: Not able to read entitlements (embedded.mobileprovision).\n"; - } - - // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the - // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit - // ASCII. Replace any 0s or invalid characters in the input. - uint8_t *profileBytes = (uint8_t *)profileData.bytes; - for (int i = 0; i < profileData.length; i++) { - uint8_t currentByte = profileBytes[i]; - if (!currentByte || currentByte > 127) { - profileBytes[i] = '.'; - } - } - - NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes - length:profileData.length - encoding:NSASCIIStringEncoding - freeWhenDone:NO]; - - if (error || !embeddedProfile.length) { - return @"\tSKIPPED: Not able to read entitlements (embedded.mobileprovision).\n"; - } - - NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile]; - NSString *plistContents; - if ([scanner scanUpToString:@"" intoString:&plistContents]) { - plistContents = [plistContents stringByAppendingString:@""]; - } - } - - if (!plistContents.length) { - return @"\tWARNING: Not able to read plist entitlements (embedded.mobileprovision).\n"; - } - - NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding]; - if (!data.length) { - return @"\tWARNING: Not able to parse entitlements (embedded.mobileprovision).\n"; - } - - NSError *plistMapError; - id plistData = [NSPropertyListSerialization propertyListWithData:data - options:NSPropertyListImmutable - format:nil - error:&plistMapError]; - if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) { - return @"\tWARNING: Not able to deserialize entitlements (embedded.mobileprovision).\n"; - } - NSDictionary *plistMap = (NSDictionary *)plistData; - - // analyze entitlements and print diagnostic information - // we can't detect errors, information p[rinted here may hint developer or will help support - // to identify the issue - NSMutableString *outputString = [[NSMutableString alloc] init]; - - NSArray *appIdentifierPrefixes = plistMap[@"ApplicationIdentifierPrefix"]; - NSString *teamID = plistMap[@"Entitlements"][@"com.apple.developer.team-identifier"]; - - if (appIdentifierPrefixes.count > 1) { - // is this possible? anyway, we can handle it - [outputString - appendFormat:@"\tAppID Prefixes: %@, Team ID: %@, AppId Prefixes contains to Team ID: %@\n", - appIdentifierPrefixes, teamID, - ([appIdentifierPrefixes containsObject:teamID] ? @"YES" : @"NO")]; - } else { - [outputString - appendFormat:@"\tAppID Prefix: %@, Team ID: %@, AppId Prefix equal to Team ID: %@\n", - appIdentifierPrefixes[0], teamID, - ([appIdentifierPrefixes[0] isEqualToString:teamID] ? @"YES" : @"NO")]; - } - - return outputString; -} - -+ (NSString *)performDiagnosticsIncludingHeaderFooter:(BOOL)includingHeaderFooter - detectedErrors:(nullable NSInteger *)detectedErrors { - NSMutableString *diagnosticString = [[NSMutableString alloc] init]; - if (includingHeaderFooter) { - [diagnosticString appendString:@"\n"]; - [diagnosticString appendString:kSelfDiagnoseOutputHeader]; - } - - NSInteger detectedErrorsCnt = 0; - - [diagnosticString appendString:[self genericDiagnosticInformation]]; - -#if TARGET_IPHONE_SIMULATOR - // check is Simulator and print WARNING that Universal Links is not supported on Simulator - [diagnosticString - appendString:@"WARNING: iOS Simulator does not support Universal Links. Firebase " - @"Dynamic Links SDK functionality will be limited. Some FDL " - @"features may be missing or will not work correctly.\n"]; -#endif // TARGET_IPHONE_SIMULATOR - - id applicationDelegate = [UIApplication sharedApplication].delegate; - if (![applicationDelegate respondsToSelector:@selector(application:openURL:options:)]) { - detectedErrorsCnt++; - [diagnosticString appendFormat:@"ERROR: UIApplication delegate %@ does not implements selector " - @"%@. FDL depends on this implementation to retrieve pending " - @"dynamic link.\n", - applicationDelegate, - NSStringFromSelector(@selector(application:openURL:options:))]; - } - - // check that Info.plist has custom URL scheme and the scheme is the same as bundleID or - // as customURLScheme passed to FDL iOS SDK - NSString *URLScheme = [FIRDynamicLinks dynamicLinks].URLScheme; - BOOL URLSchemeFoundInPlist = NO; - NSArray *URLSchemesFromInfoPlist = [[NSBundle mainBundle] infoDictionary][@"CFBundleURLTypes"]; - for (NSDictionary *schemeDetails in URLSchemesFromInfoPlist) { - NSArray *arrayOfSchemes = schemeDetails[@"CFBundleURLSchemes"]; - for (NSString *scheme in arrayOfSchemes) { - if ([scheme isEqualToString:URLScheme]) { - URLSchemeFoundInPlist = YES; - break; - } - } - if (URLSchemeFoundInPlist) { - break; - } - } - if (!URLSchemeFoundInPlist) { - detectedErrorsCnt++; - [diagnosticString appendFormat:@"ERROR: Specified custom URL scheme is %@ but Info.plist do " - @"not contain such scheme in " - "CFBundleURLTypes key.\n", - URLScheme]; - } else { - [diagnosticString appendFormat:@"\tSpecified custom URL scheme is %@ and Info.plist contains " - @"such scheme in CFBundleURLTypes key.\n", - URLScheme]; - } - -#if !TARGET_IPHONE_SIMULATOR - // analyse information in entitlements file - NSString *entitlementsAnalysis = [self diagnosticAnalyzeEntitlements]; - if (entitlementsAnalysis.length) { - [diagnosticString appendString:entitlementsAnalysis]; - } -#endif // TARGET_IPHONE_SIMULATOR - - if (includingHeaderFooter) { - if (detectedErrorsCnt == 0) { - [diagnosticString - appendString:@"performDiagnostic completed successfully! No errors found.\n"]; - } else { - [diagnosticString - appendFormat:@"performDiagnostic detected %ld ERRORS.\n", (long)detectedErrorsCnt]; - } - [diagnosticString appendString:kSelfDiagnoseOutputFooter]; - } - if (detectedErrors) { - *detectedErrors = detectedErrorsCnt; - } - return [diagnosticString copy]; -} - -+ (void)performDiagnosticsWithCompletion:(void (^_Nullable)(NSString *diagnosticOutput, - BOOL hasErrors))completionHandler; -{ - NSInteger detectedErrorsCnt = 0; - NSString *diagnosticString = [self performDiagnosticsIncludingHeaderFooter:YES - detectedErrors:&detectedErrorsCnt]; - if (completionHandler) { - completionHandler(diagnosticString, detectedErrorsCnt > 0); - } else { - NSLog(@"%@", diagnosticString); - } -} - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.h b/FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.h deleted file mode 100644 index f4077ca2a9b..00000000000 --- a/FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -/** - * @class GINArgument - * @abstract Encapsulates an argument that is passed to a method. - */ -@interface GINArgument : NSObject - -/** - * @method argumentWithObject: - * @abstract Creates an GINArgument with an NSObject. - * @param object The NSObject representing the value of the argument. - * @return An instance of GINArgument. - */ -+ (instancetype)argumentWithObject:(NSObject *)object; - -/** - * @method argumentWithInteger: - * @abstract Creates an GINArgument with an NSObject. - * @param integer The NSInteger representing the value of the argument. - * @return An instance of GINArgument. - */ -+ (instancetype)argumentWithInteger:(NSInteger)integer; - -/** - * @method setNextArgumentInList:inInvocation: - * @abstract Reads the next argument in |argumentList| and sets it in the |invocation| object. - * @param argumentList The list of arguments. Each entry must be of type GINArgument. - * @param index The argument index to set on the |invocation| object. - * @param invocation The invocation object to set the argument to. - * @return YES if the argument was set, NO if there were no arguments left in the list. - */ -+ (BOOL)setNextArgumentInList:(va_list)argumentList - atIndex:(NSUInteger)index - inInvocation:(NSInvocation *)invocation; -@end diff --git a/FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.m b/FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.m deleted file mode 100644 index 66d26b2e96b..00000000000 --- a/FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.m +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.h" - -// Currently only supporting arguments of types id and integer. -// Will support more argument types when it is needed. -typedef NS_ENUM(NSUInteger, GINArgumentType) { - kGINArgumentTypeObject = 0, - kGINArgumentTypeInteger -}; - -@interface GINArgument () - -@property(nonatomic, assign) GINArgumentType type; - -@property(nonatomic, strong) id object; -@property(nonatomic, assign) NSInteger integer; - -@end - -@implementation GINArgument - -+ (instancetype)argumentWithObject:(NSObject *)object { - GINArgument *arg = [[GINArgument alloc] init]; - arg.type = kGINArgumentTypeObject; - arg.object = object; - return arg; -} - -+ (instancetype)argumentWithInteger:(NSInteger)integer { - GINArgument *arg = [[GINArgument alloc] init]; - arg.type = kGINArgumentTypeInteger; - arg.integer = integer; - return arg; -} - -+ (BOOL)setNextArgumentInList:(va_list)argumentList - atIndex:(NSUInteger)index - inInvocation:(NSInvocation *)invocation { - id argument = va_arg(argumentList, id); - - if (!argument) { - return NO; - } - - if (![argument isKindOfClass:[GINArgument class]]) { - [NSException raise:@"InvalidArgumentException" - format:@"Invalid argument type at index %lu", (unsigned long)index]; - } - - [argument setArgumentInInvocation:invocation atIndex:index]; - return YES; -} - -- (void)setArgumentInInvocation:(NSInvocation *)invocation atIndex:(NSUInteger)index { - switch (self.type) { - case kGINArgumentTypeObject: - [invocation setArgument:&_object atIndex:index]; - break; - - case kGINArgumentTypeInteger: - [invocation setArgument:&_integer atIndex:index]; - break; - - default: - break; - } -} - -@end diff --git a/FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.h b/FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.h deleted file mode 100644 index 67092d21692..00000000000 --- a/FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -// Calls a method on a class or object. -#define GINPerformSelector(target, selector) \ - GINPerformSelectorWithArguments(target, selector, 0, nil) - -// Calls a method on a class or object, that takes arguments. -#define GINPerformSelectorWithArguments(target, selector, numArgs, args...) \ - [GINInvocation objectByPerformingSelector:selector \ - onTarget:target \ - numberOfArguments:numArgs, args, nil] - -// Calls a method that returns double on a class or object. -#define GINDoubleByPerformingSelector(target, selector) \ - GINDoubleByPerformingSelectorWithArguments(target, selector, 0, nil) - -// Calls a method that returns double on a class or object, that takes arguments. -#define GINDoubleByPerformingSelectorWithArguments(target, selector, numArgs, args...) \ - [GINInvocation doubleByPerformingSelector:selector \ - onTarget:target \ - numberOfArguments:numArgs, args, nil] - -/** - * @class GINInvocation - * @abstract A utility class that provide helper methods to invoke methods on objects and classes. - */ -@interface GINInvocation : NSObject - -/** - * @method objectByPerformingSelector:onTarget:numberOfArguments:... - * @abstract Performs a selector on a class or object. - * @param selector The selector to perform. - * @param target The target class or object to perform the selector on. - * @param numberOfArguments Number of arguments in the argument list. - * @param ... An optional argument list, each argument should be of type GINArgument. - * @return id The result of the selector. - */ -+ (id)objectByPerformingSelector:(SEL)selector - onTarget:(id)target - numberOfArguments:(NSInteger)numberOfArguments, ...; - -/** - * @method doubleByPerformingSelector:onTarget:numberOfArguments:... - * @abstract Performs a selector on a class or object. - * @param selector The selector to perform. - * @param target The target class or object to perform the selector on. - * @param numberOfArguments Number of arguments in the argument list. - * @param ... An optional argument list, each argument should be of type GINArgument. - * @return double The result of the selector. - */ -+ (double)doubleByPerformingSelector:(SEL)selector - onTarget:(id)target - numberOfArguments:(NSInteger)numberOfArguments, ...; - -@end diff --git a/FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.m b/FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.m deleted file mode 100644 index 2ea2bf631f6..00000000000 --- a/FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.m +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/GINInvocation/GINInvocation.h" - -#import "FirebaseDynamicLinks/Sources/GINInvocation/GINArgument.h" - -@implementation GINInvocation - -// A method that performs a selector on a target object, and return the result. -+ (id)objectByPerformingSelector:(SEL)selector - onTarget:(id)target - numberOfArguments:(NSInteger)numberOfArguments, ... { - if (![target respondsToSelector:selector]) { -#if DEBUG - [NSException raise:@"InvalidSelectorException" format:@"Invalid selector send to target"]; -#endif - return nil; - } - - NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector]; - NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; - [inv setSelector:selector]; - [inv setTarget:target]; - - int index = 2; - va_list argumentList; - - va_start(argumentList, numberOfArguments); - for (NSInteger i = 0; i < numberOfArguments; i++) { - [GINArgument setNextArgumentInList:argumentList atIndex:index inInvocation:inv]; - } - va_end(argumentList); - - [inv invoke]; - - // This method only returns object. - if ([methodSignature methodReturnLength]) { - CFTypeRef result; - [inv getReturnValue:&result]; - if (result) { - CFRetain(result); - } - return (__bridge_transfer id)result; - } - return nil; -} - -// A method that performs a selector on a target object, and return the result. -+ (double)doubleByPerformingSelector:(SEL)selector - onTarget:(id)target - numberOfArguments:(NSInteger)numberOfArguments, ... { - if (![target respondsToSelector:selector]) { -#if DEBUG - [NSException raise:@"InvalidSelectorException" format:@"Invalid selector send to target"]; -#endif - return 0; - } - - NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector]; - NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; - [inv setSelector:selector]; - [inv setTarget:target]; - - int index = 2; - va_list argumentList; - - va_start(argumentList, numberOfArguments); - for (NSInteger i = 0; i < numberOfArguments; i++) { - [GINArgument setNextArgumentInList:argumentList atIndex:index inInvocation:inv]; - } - va_end(argumentList); - - [inv invoke]; - - // This method only returns double. - if ([methodSignature methodReturnLength]) { - double doubleValue; - [inv getReturnValue:&doubleValue]; - return doubleValue; - } - return 0; -} - -@end diff --git a/FirebaseDynamicLinks/Sources/Logging/FDLLogging.h b/FirebaseDynamicLinks/Sources/Logging/FDLLogging.h deleted file mode 100644 index f20727a096a..00000000000 --- a/FirebaseDynamicLinks/Sources/Logging/FDLLogging.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -/** Log level for FIRLogger. */ -typedef NS_ENUM(NSInteger, FDLLogLevel) { - FDLLogLevelError = 0, - FDLLogLevelWarning, - FDLLogLevelNotice, - FDLLogLevelInfo, - FDLLogLevelDebug, -}; - -/** - Used to specify a unique integer for FIRLogger. Add entries ONLY to the end of the enum. - Unique values are specified so that items can be safely removed without affecting the others. - */ -typedef NS_ENUM(NSInteger, FDLLogIdentifier) { - FDLLogIdentifierSetupNilAPIKey = 0, - FDLLogIdentifierSetupNilClientID = 1, // Not used anymore - FDLLogIdentifierSetupNonDefaultApp = 2, - FDLLogIdentifierSetupInvalidDomainURIPrefixScheme = 3, - FDLLogIdentifierSetupInvalidDomainURIPrefix = 4, - FDLLogIdentifierSetupWarnHTTPSScheme = 5, -}; - -/** The appropriate formatter for using NSInteger in FIRLogger. */ -FOUNDATION_EXPORT NSString *const FDLMessageCodeIntegerFormat; - -/** Logs a message with FIRLogger. */ -FOUNDATION_EXPORT void FDLLog(FDLLogLevel logLevel, - FDLLogIdentifier identifier, - NSString *message, - ...) NS_FORMAT_FUNCTION(3, 4); diff --git a/FirebaseDynamicLinks/Sources/Logging/FDLLogging.m b/FirebaseDynamicLinks/Sources/Logging/FDLLogging.m deleted file mode 100644 index a422007fe8e..00000000000 --- a/FirebaseDynamicLinks/Sources/Logging/FDLLogging.m +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/Logging/FDLLogging.h" - -#ifdef GIN_SCION_LOGGING -#import "FirebaseCore/Extension/FirebaseCoreInternal.h" - -FIRLoggerService kFIRLoggerDynamicLinks = @"[FirebaseDynamicLinks]"; -#endif // GIN_SCION_LOGGING - -#ifdef GIN_SCION_LOGGING - -#if __LP64__ // 64-bit -NSString *const FDLMessageCodeIntegerFormat = @"%06ld"; -#else // 32-bit -NSString *const FDLMessageCodeIntegerFormat = @"%06d"; -#endif // #if __LP64__ - -NSString *FDLMessageCodeForLogIdentifier(FDLLogIdentifier identifier) { - static NSString *const kMessageCodePrefix = @"I-FDL"; - NSString *intString = [NSString stringWithFormat:FDLMessageCodeIntegerFormat, identifier]; - return [kMessageCodePrefix stringByAppendingString:intString]; -} -#endif // GIN_SCION_LOGGING - -void FDLLog(FDLLogLevel logLevel, FDLLogIdentifier identifier, NSString *message, ...) { - va_list args_ptr; - va_start(args_ptr, message); -#ifdef GIN_SCION_LOGGING - NSString *messageCode = FDLMessageCodeForLogIdentifier(identifier); - - switch (logLevel) { - case FDLLogLevelError: - FIRLogError(kFIRLoggerDynamicLinks, messageCode, message, args_ptr); - break; - case FDLLogLevelWarning: - FIRLogWarning(kFIRLoggerDynamicLinks, messageCode, message, args_ptr); - break; - case FDLLogLevelNotice: - FIRLogNotice(kFIRLoggerDynamicLinks, messageCode, message, args_ptr); - break; - case FDLLogLevelInfo: - FIRLogInfo(kFIRLoggerDynamicLinks, messageCode, message, args_ptr); - break; - case FDLLogLevelDebug: - FIRLogDebug(kFIRLoggerDynamicLinks, messageCode, message, args_ptr); - break; - } - -#else - NSLogv(message, args_ptr); -#endif // GIN_SCION_LOGGING - va_end(args_ptr); -} - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FDLURLComponents.h b/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FDLURLComponents.h deleted file mode 100644 index a0b99105b76..00000000000 --- a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FDLURLComponents.h +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * @abstract Enum used to define the desired path length for shortened Dynamic Link URLs. - */ -typedef NS_ENUM(NSInteger, FIRShortDynamicLinkPathLength) { - /** - * Uses the server-default for the path length. See https://goo.gl/8yDAqC for more information. - */ - FIRShortDynamicLinkPathLengthDefault = 0, - /** Typical short link for non-sensitive links. */ - FIRShortDynamicLinkPathLengthShort, - /** Short link with an extra long path for great difficulty in guessing. */ - FIRShortDynamicLinkPathLengthUnguessable, -} NS_SWIFT_NAME(ShortDynamicLinkPathLength); - -/** - * @abstract The definition of the completion block used by URL shortener. - * @param shortURL Shortened URL. - * @param warnings Warnings that describe usability or function limitations of the generated - * short link. Usually presence of warnings means parameters format error, parameters value - * error or missing parameter. - * @param error Error if URL can't be shortened. - */ -typedef void (^FIRDynamicLinkShortenerCompletion)(NSURL *_Nullable shortURL, - NSArray *_Nullable warnings, - NSError *_Nullable error) - NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead."); - -/** - * @class FIRDynamicLinkGoogleAnalyticsParameters - * @abstract The Dynamic Link analytics parameters. - */ -NS_SWIFT_NAME(DynamicLinkGoogleAnalyticsParameters) -@interface FIRDynamicLinkGoogleAnalyticsParameters : NSObject - -/** - * @property source - * @abstract The utm_source analytics parameter. - */ -@property(nonatomic, copy, nullable) NSString *source; -/** - * @property medium - * @abstract The utm_medium analytics parameter. - */ -@property(nonatomic, copy, nullable) NSString *medium; -/** - * @property campaign - * @abstract The utm_campaign analytics parameter. - */ -@property(nonatomic, copy, nullable) NSString *campaign; -/** - * @property term - * @abstract The utm_term analytics parameter. - */ -@property(nonatomic, copy, nullable) NSString *term; -/** - * @property content - * @abstract The utm_content analytics parameter. - */ -@property(nonatomic, copy, nullable) NSString *content; - -/** - * @method parametersWithSource:medium:campaign: - * @abstract The preferred factory method for creating the analytics parameters object. It includes - * the commonly-used source, medium, and campaign fields. - * @param source The utm_source analytics parameter. - * @param medium The utm_medium analytics parameter. - * @param campaign The utm_campaign analytics parameter. - * @return Returns An object to be used with FIRDynamicLinkURLComponents to add analytics parameters - * to a generated Dynamic Link URL. - */ -+ (instancetype)parametersWithSource:(NSString *)source - medium:(NSString *)medium - campaign:(NSString *)campaign - NS_SWIFT_UNAVAILABLE("Use init(source:medium:campaign:)"); - -/** - * @method parameters - * @abstract A factory method for creating the analytics parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add analytics parameters - * to a generated Dynamic Link URL. - */ -+ (instancetype)parameters NS_SWIFT_UNAVAILABLE("Use init()"); - -/** - * @method initWithSource:medium:campaign: - * @abstract The preferred instance method for creating the analytics parameters object. It - * includes the commonly-used source, medium, and campaign fields. - * @param source The utm_source analytics parameter. - * @param medium The utm_medium analytics parameter. - * @param campaign The utm_campaign analytics parameter. - * @return Returns An object to be used with FIRDynamicLinkURLComponents to add analytics parameters - * to a generated Dynamic Link URL. - */ -- (instancetype)initWithSource:(NSString *)source - medium:(NSString *)medium - campaign:(NSString *)campaign; - -/** - * @method init - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add analytics parameters - * to a generated Dynamic Link URL. - */ -- (instancetype)init; - -@end - -/** - * @class FIRDynamicLinkIOSParameters - * @abstract The Dynamic Link iOS parameters. - */ -NS_SWIFT_NAME(DynamicLinkIOSParameters) -@interface FIRDynamicLinkIOSParameters : NSObject - -/** - * @property bundleID - * @abstract The bundle ID of the iOS app to use to open the link. - */ -@property(nonatomic, copy, nullable, readonly) NSString *bundleID; - -/** - * @property appStoreID - * @abstract The appStore ID of the iOS app in AppStore. - */ -@property(nonatomic, copy, nullable) NSString *appStoreID; - -/** - * @property fallbackURL - * @abstract The link to open when the app isn't installed. Specify this to do something other than - * install the app from the App Store when the app isn't installed, such as open the mobile - * web version of the content, or display a promotional page for the app. - */ -@property(nonatomic, nullable) NSURL *fallbackURL; -/** - * @property customScheme - * @abstract The target app's custom URL scheme, if defined to be something other than the app's - * bundle ID - */ -@property(nonatomic, copy, nullable) NSString *customScheme; -/** - * @property iPadBundleID - * @abstract The bundle ID of the iOS app to use on iPads to open the link. This is only required if - * there are separate iPhone and iPad applications. - */ -@property(nonatomic, copy, nullable) NSString *iPadBundleID; -/** - * @property iPadFallbackURL - * @abstract The link to open on iPads when the app isn't installed. Specify this to do something - * other than install the app from the App Store when the app isn't installed, such as open the - * web version of the content, or display a promotional page for the app. - */ -@property(nonatomic, nullable) NSURL *iPadFallbackURL; - -/** - @property minimumAppVersion - @abstract The minimum version of your app that can open the link. If the - * installed app is an older version, the user is taken to the AppStore to upgrade the app. - * Note: It is app's developer responsibility to open AppStore when received link declares - * higher minimumAppVersion than currently installed. - */ -@property(nonatomic, copy, nullable) NSString *minimumAppVersion; - -/** - * @method parametersWithBundleID: - * @abstract A method for creating the iOS parameters object. - * @param bundleID The bundle ID of the iOS app to use to open the link. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add iOS parameters to a - * generated Dynamic Link URL. - */ -+ (instancetype)parametersWithBundleID:(NSString *)bundleID - NS_SWIFT_UNAVAILABLE("Use initWithBundleID()"); - -/** - * @method initWithBundleID: - * @abstract A method for creating the iOS parameters object. - * @param bundleID The bundle ID of the iOS app to use to open the link. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add iOS parameters to a - * generated Dynamic Link URL. - */ -- (instancetype)initWithBundleID:(NSString *)bundleID; - -@end - -/** - * @class FIRDynamicLinkItunesConnectAnalyticsParameters - * @abstract The Dynamic Link iTunes Connect parameters. - */ -NS_SWIFT_NAME(DynamicLinkItunesConnectAnalyticsParameters) -@interface FIRDynamicLinkItunesConnectAnalyticsParameters : NSObject - -/** - * @property affiliateToken - * @abstract The iTunes Connect affiliate token. - */ -@property(nonatomic, copy, nullable) NSString *affiliateToken; -/** - * @property campaignToken - * @abstract The iTunes Connect campaign token. - */ -@property(nonatomic, copy, nullable) NSString *campaignToken; -/** - * @property providerToken - * @abstract The iTunes Connect provider token. - */ -@property(nonatomic, copy, nullable) NSString *providerToken; - -/** - * @method parameters - * @abstract A method for creating the iTunes Connect parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add iTunes Connect - * parameters to a generated Dynamic Link URL. - */ -+ (instancetype)parameters NS_SWIFT_UNAVAILABLE("Use init()"); - -/** - * @method init - * @abstract A method for creating the iTunes Connect parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add iTunes Connect - * parameters to a generated Dynamic Link URL. - */ -- (instancetype)init; - -@end - -/** - * @class FIRDynamicLinkAndroidParameters - * @abstract The Dynamic Link Android parameters. - */ -NS_SWIFT_NAME(DynamicLinkAndroidParameters) -@interface FIRDynamicLinkAndroidParameters : NSObject - -/** - * @property packageName - * @abstract The Android app's package name. - */ -@property(nonatomic, copy, nullable, readonly) NSString *packageName; - -/** - * @property fallbackURL - * @abstract The link to open when the app isn't installed. Specify this to do something other than - * install the app from the Play Store when the app isn't installed, such as open the mobile web - * version of the content, or display a promotional page for the app. - */ -@property(nonatomic, nullable) NSURL *fallbackURL; -/** - @property minimumVersion - @abstract The version code of the minimum version of your app that can open the link. If the - * installed app is an older version, the user is taken to the Play Store to upgrade the app. - */ -@property(nonatomic) NSInteger minimumVersion; - -/** - * @method parametersWithPackageName: - * @abstract A method for creating the Android parameters object. - * @param packageName The Android app's package name. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Android parameters - * to a generated Dynamic Link URL. - */ -+ (instancetype)parametersWithPackageName:(NSString *)packageName - NS_SWIFT_UNAVAILABLE("Use initWithPackageName()"); - -/** - * @method initWithPackageName: - * @abstract A method for creating the Android parameters object. - * @param packageName The Android app's package name. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Android parameters - * to a generated Dynamic Link URL. - */ -- (instancetype)initWithPackageName:(NSString *)packageName; - -@end - -/** - * @class FIRDynamicLinkSocialMetaTagParameters - * @abstract The Dynamic Link Social Meta Tag parameters. - */ -NS_SWIFT_NAME(DynamicLinkSocialMetaTagParameters) -@interface FIRDynamicLinkSocialMetaTagParameters : NSObject - -/** - * @property title - * @abstract The title to use when the Dynamic Link is shared in a social post. - */ -@property(nonatomic, copy, nullable) NSString *title; -/** - * @property descriptionText - * @abstract The description to use when the Dynamic Link is shared in a social post. - */ -@property(nonatomic, copy, nullable) NSString *descriptionText; -/** - * @property imageURL - * @abstract The URL to an image related to this link. - */ -@property(nonatomic, nullable) NSURL *imageURL; - -/** - * @method parameters - * @abstract A method for creating the Social Meta Tag parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Social Meta Tag - * parameters to a generated Dynamic Link URL. - */ -+ (instancetype)parameters NS_SWIFT_UNAVAILABLE("Use init()"); - -/** - * @method init - * @abstract A method for creating the Social Meta Tag parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Social Meta Tag - * parameters to a generated Dynamic Link URL. - */ -- (instancetype)init; - -@end - -/** - * @class FIRDynamicLinkNavigationInfoParameters - * @abstract Options class for defining navigation behavior of the Dynamic Link. - */ -NS_SWIFT_NAME(DynamicLinkNavigationInfoParameters) -@interface FIRDynamicLinkNavigationInfoParameters : NSObject - -/** - * @property forcedRedirectEnabled - * @abstract Property defines should forced non-interactive redirect be used when link is tapped on - * mobile device. Default behavior is to disable force redirect and show interstitial page where - * user tap will initiate navigation to the App (or AppStore if not installed). Disabled force - * redirect normally improves reliability of the click. - */ -@property(nonatomic, getter=isForcedRedirectEnabled) BOOL forcedRedirectEnabled; - -/** - * @method parameters - * @abstract A method for creating the Navigation Info parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Navigation Info - * parameters to a generated Dynamic Link URL. - */ -+ (instancetype)parameters NS_SWIFT_UNAVAILABLE("Use init()"); - -/** - * @method init - * @abstract A method for creating the Navigation Info parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Navigation Info - * parameters to a generated Dynamic Link URL. - */ -- (instancetype)init; - -@end - -/** - * @class FIRDynamicLinkOtherPlatformParameters - * @abstract Options class for defining other platform(s) parameters of the Dynamic Link. - * Other here means not covered by specific parameters (not iOS and not Android). - */ -NS_SWIFT_NAME(DynamicLinkOtherPlatformParameters) -@interface FIRDynamicLinkOtherPlatformParameters : NSObject - -/** - * @property fallbackUrl - * @abstract Property defines fallback URL to navigate to when Dynamic Link is clicked on - * other platform. - */ -@property(nonatomic, nullable) NSURL *fallbackUrl; - -/** - * @method parameters - * @abstract A method for creating the Other platform parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Other Platform - * parameters to a generated Dynamic Link URL. - */ -+ (instancetype)parameters NS_SWIFT_UNAVAILABLE("Use init()"); - -/** - * @method init - * @abstract A method for creating the Other platform parameters object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to add Other Platform - * parameters to a generated Dynamic Link URL. - */ -- (instancetype)init; - -@end - -/** - * @class FIRDynamicLinkComponentsOptions - * @abstract Options class for defining how Dynamic Link URLs are generated. - */ -NS_SWIFT_NAME(DynamicLinkComponentsOptions) -@interface FIRDynamicLinkComponentsOptions : NSObject - -/** - * @property pathLength - * @abstract Specifies the length of the path component of a short Dynamic Link. - */ -@property(nonatomic) FIRShortDynamicLinkPathLength pathLength; - -/** - * @method options - * @abstract A method for creating the Dynamic Link components options object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to specify options related - * to the generation of Dynamic Link URLs. - */ -+ (instancetype)options NS_SWIFT_UNAVAILABLE("Use init()"); - -/** - * @method init - * @abstract A method for creating the Dynamic Link components options object. - * @return Returns an object to be used with FIRDynamicLinkURLComponents to specify options related - * to the generation of Dynamic Link URLs. - */ -- (instancetype)init; - -@end - -/** - * @class FIRDynamicLinkComponents - * @abstract The class used for Dynamic Link URL generation; supports creation of short and long - * Dynamic Link URLs. Short URLs will have a domain and a randomized path; long URLs will have a - * domain and a query that contains all of the Dynamic Link parameters. - */ -NS_SWIFT_NAME(DynamicLinkComponents) -@interface FIRDynamicLinkComponents : NSObject - -/** - * @property analyticsParameters - * @abstract Applies Analytics parameters to a generated Dynamic Link URL. - */ -@property(nonatomic, nullable) FIRDynamicLinkGoogleAnalyticsParameters *analyticsParameters; -/** - * @property socialMetaTagParameters - * @abstract Applies Social Meta Tag parameters to a generated Dynamic Link URL. - */ -@property(nonatomic, nullable) FIRDynamicLinkSocialMetaTagParameters *socialMetaTagParameters; -/** - * @property iOSParameters - * @abstract Applies iOS parameters to a generated Dynamic Link URL. - */ -@property(nonatomic, nullable) FIRDynamicLinkIOSParameters *iOSParameters; -/** - * @property iTunesConnectParameters - * @abstract Applies iTunes Connect parameters to a generated Dynamic Link URL. - */ -@property(nonatomic, nullable) - FIRDynamicLinkItunesConnectAnalyticsParameters *iTunesConnectParameters; -/** - * @property androidParameters - * @abstract Applies Android parameters to a generated Dynamic Link URL. - */ -@property(nonatomic, nullable) FIRDynamicLinkAndroidParameters *androidParameters; -/** - * @property navigationInfoParameters - * @abstract Applies Navigation Info parameters to a generated Dynamic Link URL. - */ -@property(nonatomic, nullable) FIRDynamicLinkNavigationInfoParameters *navigationInfoParameters; -/** - * @property otherPlatformParameters - * @abstract Applies Other platform parameters to a generated Dynamic Link URL. - */ -@property(nonatomic, nullable) FIRDynamicLinkOtherPlatformParameters *otherPlatformParameters; -/** - * @property options - * @abstract Defines behavior for generating Dynamic Link URLs. - */ -@property(nonatomic, nullable) FIRDynamicLinkComponentsOptions *options; - -/** - * @property link - * @abstract The link the target app will open. You can specify any URL the app can handle, such as - * a link to the app's content, or a URL that initiates some app-specific logic such as - * crediting the user with a coupon, or displaying a specific welcome screen. This link must be - * a well-formatted URL, be properly URL-encoded, and use the HTTP or HTTPS scheme. - */ -@property(nonatomic) NSURL *link; -/** - * @property domain - * @abstract The Firebase project's Dynamic Links domain. You can find this value in the Dynamic - * Links section of the Firebase console. - * https://console.firebase.google.com/ - */ -@property(nonatomic, nullable, copy) NSString *domain; - -/** - * @property url - * @abstract A generated long Dynamic Link URL. - */ -@property(nonatomic, nullable, readonly) NSURL *url; - -/** - * @method componentsWithLink:domainURIPrefix: - * @abstract Generates a Dynamic Link URL components object with the minimum necessary parameters - * set to generate a fully-functional Dynamic Link. - * @param link Deep link to be stored in created Dynamic link. This link also called "payload" of - * the Dynamic link. - * @param domainURIPrefix Domain URI Prefix of your App. This value must be your assigned - * domain from the Firebase console. (e.g. https://xyz.page.link) The domain URI prefix must - * start with a valid HTTPS scheme (https://). - * @return Returns an instance of FIRDynamicLinkComponents if the parameters succeed validation, - * else returns nil. - */ -+ (nullable instancetype)componentsWithLink:(NSURL *)link - domainURIPrefix:(NSString *)domainURIPrefix - NS_SWIFT_UNAVAILABLE("Use init(link:domainURIPrefix:)"); - -/** - * @method initWithLink:domainURIPrefix: - * @abstract Generates a Dynamic Link URL components object with the minimum necessary parameters - * set to generate a fully-functional Dynamic Link. - * @param link Deep link to be stored in created Dynamic link. This link also called "payload" of - * the Dynamic link. - * @param domainURIPrefix Domain URI Prefix of your App. This value must be your assigned - * domain from the Firebase console. (e.g. https://xyz.page.link) The domain URI prefix must - * start with a valid HTTPS scheme (https://). - * @return Returns an instance of FIRDynamicLinkComponents if the parameters succeed validation, - * else returns nil. - */ -- (nullable instancetype)initWithLink:(NSURL *)link domainURIPrefix:(NSString *)domainURIPrefix; - -/** - * @method shortenURL:options:completion: - * @abstract Shortens a Dynamic Link URL. This method may be used for shortening a custom URL that - * was not generated using FIRDynamicLinkComponents. - * @param url A properly-formatted long Dynamic Link URL. - * @param completion A block to be executed upon completion of the shortening attempt. It is - * guaranteed to be executed once and on the main thread. - */ -+ (void)shortenURL:(NSURL *)url - options:(FIRDynamicLinkComponentsOptions *_Nullable)options - completion:(void (^)(NSURL *_Nullable shortURL, - NSArray *_Nullable warnings, - NSError *_Nullable error))completion; - -/** - * @method shortenWithCompletion: - * @abstract Generates a short Dynamic Link URL using all set parameters. - * @param completion A block to be executed upon completion of the shortening attempt. It is - * guaranteed to be executed once and on the main thread. - */ -- (void)shortenWithCompletion:(void (^)(NSURL *_Nullable shortURL, - NSArray *_Nullable warnings, - NSError *_Nullable error))completion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLink.h b/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLink.h deleted file mode 100644 index 5524d3c52ee..00000000000 --- a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLink.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * @file FIRDynamicLink.h - * @abstract Dynamic Link object used in Firebase Dynamic Links. - */ - -/** - * @abstract The match type of the Dynamic Link. - */ -typedef NS_ENUM(NSUInteger, FIRDLMatchType) { - /** - * The match has not been achieved. - */ - FIRDLMatchTypeNone, - /** - * The match between the Dynamic Link and this device may not be perfect, hence you should not - * reveal any personal information related to the Dynamic Link. - */ - FIRDLMatchTypeWeak, - /** - * The match between the Dynamic Link and this device has high confidence but small possibility of - * error still exist. - */ - FIRDLMatchTypeDefault, - /** - * The match between the Dynamic Link and this device is exact, hence you may reveal personal - * information related to the Dynamic Link. - */ - FIRDLMatchTypeUnique, -} NS_SWIFT_NAME(DLMatchType); - -/** - * @class FIRDynamicLink - * @abstract A received Dynamic Link. - */ -NS_SWIFT_NAME(DynamicLink) -@interface FIRDynamicLink : NSObject - -/** - * @property url - * @abstract The URL that was passed to the app. - */ -@property(nonatomic, copy, readonly, nullable) NSURL *url; - -/** - * @property matchType - * @abstract The match type of the received Dynamic Link. - */ -@property(nonatomic, assign, readonly) FIRDLMatchType matchType; - -/** - * @property utmParametersDictionary - * @abstract UTM parameters associated with a Firebase Dynamic Link. - */ -@property(nonatomic, copy, readonly) NSDictionary *utmParametersDictionary; - -/** - * @property minimumAppVersion - * @abstract The minimum iOS application version that supports the Dynamic Link. This is retrieved - * from the imv= parameter of the Dynamic Link URL. Note: This is not the minimum iOS system - * version, but the minimum app version. If app version of the opening app is less than the - * value of this property, then app expected to open AppStore to allow user to download most - * recent version. App can notify or ask user before opening AppStore. - */ -@property(nonatomic, copy, readonly, nullable) NSString *minimumAppVersion; - -- (instancetype)init NS_UNAVAILABLE; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h b/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h deleted file mode 100644 index c07a88fa2bf..00000000000 --- a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import "FIRDynamicLink.h" -#import "FIRDynamicLinksCommon.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * @file FIRDynamicLinks.h - * @abstract Firebase Dynamic Links - */ - -/** - * @class FIRDynamicLinks - * @abstract A class that checks for pending Dynamic Links and parses URLs. - * This class is available on iOS only. - */ -DEPRECATED_MSG_ATTRIBUTE( - "Firebase Dynamic Links is deprecated and the service will shut down on August 25, 2025.") -NS_EXTENSION_UNAVAILABLE_IOS("Firebase Dynamic Links is not supported for iOS extensions.") -API_UNAVAILABLE(macos, tvos, watchos) -NS_SWIFT_NAME(DynamicLinks) -@interface FIRDynamicLinks : NSObject - -/** - * @method dynamicLinks - * @abstract Shared instance of FIRDynamicLinks. - * @return Shared instance of FIRDynamicLinks. - */ -+ (instancetype)dynamicLinks NS_SWIFT_NAME(dynamicLinks()); - -/** - * @method shouldHandleDynamicLinkFromCustomSchemeURL: - * @abstract Determine whether FIRDynamicLinks should handle the given URL. This does not - * guarantee that |dynamicLinkFromCustomSchemeURL:| will return a non-nil value, but it means - * the client should not attempt to handle the URL. - * @param url Custom scheme URL. - * @return Whether the URL can be handled by FIRDynamicLinks. - */ -- (BOOL)shouldHandleDynamicLinkFromCustomSchemeURL:(NSURL *)url - NS_SWIFT_NAME(shouldHandleDynamicLink(fromCustomSchemeURL:)); - -/** - * @method dynamicLinkFromCustomSchemeURL: - * @abstract Get a Dynamic Link from a custom scheme URL. This method parses URLs with a custom - * scheme, for instance, "comgoogleapp://google/link?deep_link_id=abc123". It is suggested to - * call it inside your |UIApplicationDelegate|'s - * |application:openURL:sourceApplication:annotation| and |application:openURL:options:| - * methods. - * @param url Custom scheme URL. - * @return Dynamic Link object if the URL is valid and has link parameter, otherwise nil. - */ -- (nullable FIRDynamicLink *)dynamicLinkFromCustomSchemeURL:(NSURL *)url - NS_SWIFT_NAME(dynamicLink(fromCustomSchemeURL:)); - -/** - * @method dynamicLinkFromUniversalLinkURL:completion: - * @abstract Get a Dynamic Link from a universal link URL. This method parses universal link - * URLs, for instance, - * "https://example.page.link?link=https://www.google.com&ibi=com.google.app&ius=comgoogleapp". - * It is suggested to call it inside your |UIApplicationDelegate|'s - * |application:continueUserActivity:restorationHandler:| method. - * @param url Custom scheme URL. - * @param completion A block that handles the outcome of attempting to get a Dynamic Link from a - * universal link URL. - */ -- (void)dynamicLinkFromUniversalLinkURL:(NSURL *)url - completion:(void (^)(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error))completion - NS_SWIFT_NAME(dynamicLink(fromUniversalLink:completion:)); - -/** - * @method dynamicLinkFromUniversalLinkURL: - * @abstract Get a Dynamic Link from a universal link URL. This method parses universal link - * URLs, for instance, - * "https://example.page.link?link=https://www.google.com&ibi=com.google.app&ius=comgoogleapp". - * It is suggested to call it inside your |UIApplicationDelegate|'s - * |application:continueUserActivity:restorationHandler:| method. - * @param url Custom scheme URL. - * @return Dynamic Link object if the URL is valid and has link parameter, otherwise nil. - */ -- (nullable FIRDynamicLink *)dynamicLinkFromUniversalLinkURL:(NSURL *)url - NS_SWIFT_NAME(dynamicLink(fromUniversalLink:)) - DEPRECATED_MSG_ATTRIBUTE("Use dynamicLinkFromUniversalLinkURL:completion: instead."); - -/** - * @method handleUniversalLink:completion: - * @abstract Convenience method to handle a Universal Link whether it is long or short. - * @param url A Universal Link URL. - * @param completion A block that handles the outcome of attempting to create a FIRDynamicLink. - * @return YES if FIRDynamicLinks is handling the link, otherwise, NO. - */ -- (BOOL)handleUniversalLink:(NSURL *)url - completion:(void (^)(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error))completion; - -/** - * @method resolveShortLink:completion: - * @abstract Retrieves the details of the Dynamic Link that the shortened URL represents. - * @param url A Short Dynamic Link. - * @param completion Block to be run upon completion. - */ -- (void)resolveShortLink:(NSURL *)url - completion:(void (^)(NSURL *_Nullable url, NSError *_Nullable error))completion; - -/** - * @method matchesShortLinkFormat: - * @abstract Determines if a given URL matches the given short Dynamic Link format. - * @param url A URL. - * @return YES if the URL is a short Dynamic Link, otherwise, NO. - */ -- (BOOL)matchesShortLinkFormat:(NSURL *)url; - -/** - * @method performDiagnosticsWithCompletion: - * @abstract Performs basic FDL self diagnostic. Method effect on startup latency is quite small - * and no user-visible UI is presented. This method should be used for debugging purposes. - * App developers are encouraged to include output, generated by this method, to the support - * requests sent to Firebase support. - * @param completionHandler Handler that will be called when diagnostic completes. - * If value of the completionHandler is nil than diagnostic output will be printed to - * the standard output. - * diagnosticOutput String that includes diagnostic information. - * hasErrors Param will have YES value if diagnostic method detected error, NO otherwise. - */ -+ (void)performDiagnosticsWithCompletion:(void (^_Nullable)(NSString *diagnosticOutput, - BOOL hasErrors))completionHandler; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinksCommon.h b/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinksCommon.h deleted file mode 100644 index c4f0fdca6be..00000000000 --- a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinksCommon.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@class FIRDynamicLink; - -NS_ASSUME_NONNULL_BEGIN - -/** - * @file FIRDynamicLinksCommon.h - * @abstract Commonly shared definitions within Firebase Dynamic Links. - */ - -/** - * @abstract The definition of the block used by |resolveShortLink:completion:| - */ -typedef void (^FIRDynamicLinkResolverHandler)(NSURL* _Nullable url, NSError* _Nullable error) - NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead."); - -/** - * @abstract The definition of the block used by |handleUniversalLink:completion:| - */ -typedef void (^FIRDynamicLinkUniversalLinkHandler)(FIRDynamicLink* _Nullable dynamicLink, - NSError* _Nullable error) - NS_SWIFT_UNAVAILABLE("Use Swift's closure syntax instead."); - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FirebaseDynamicLinks.h b/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FirebaseDynamicLinks.h deleted file mode 100755 index ea6f45f021e..00000000000 --- a/FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FirebaseDynamicLinks.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FDLURLComponents.h" -#import "FIRDynamicLink.h" -#import "FIRDynamicLinks.h" -#import "FIRDynamicLinksCommon.h" diff --git a/FirebaseDynamicLinks/Sources/Resources/PrivacyInfo.xcprivacy b/FirebaseDynamicLinks/Sources/Resources/PrivacyInfo.xcprivacy deleted file mode 100644 index 0fccd3b0f69..00000000000 --- a/FirebaseDynamicLinks/Sources/Resources/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,46 +0,0 @@ - - - - - NSPrivacyTracking - - NSPrivacyTrackingDomains - - - NSPrivacyCollectedDataTypes - - - NSPrivacyCollectedDataType - NSPrivacyCollectedDataTypeOtherDataTypes - NSPrivacyCollectedDataTypeLinked - - NSPrivacyCollectedDataTypeTracking - - NSPrivacyCollectedDataTypePurposes - - NSPrivacyCollectedDataTypePurposeAppFunctionality - - - - NSPrivacyAccessedAPITypes - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryFileTimestamp - NSPrivacyAccessedAPITypeReasons - - C617.1 - - - - NSPrivacyAccessedAPIType - NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - 1C8F.1 - - - - - - diff --git a/FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.h b/FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.h deleted file mode 100644 index 84b3179e6ab..00000000000 --- a/FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@interface FDLDeviceHeuristicsHelper : NSObject - -/** - * Creates DeviceInfo dictionary based on the provided information. - */ -+ (NSDictionary *) - FDLDeviceInfoDictionaryFromResolutionHeight:(NSInteger)resolutionHeight - resolutionWidth:(NSInteger)resolutionWidth - locale:(NSString *)locale - localeRaw:(NSString *)localeRaw - localeFromWebview:(NSString *)localeFromWebView - timeZone:(NSString *)timezone - modelName:(NSString *)modelName; - -@end diff --git a/FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.m b/FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.m deleted file mode 100644 index ae9f18fc4da..00000000000 --- a/FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.m +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FirebaseDynamicLinks/Sources/Utilities/FDLDeviceHeuristicsHelper.h" -#import - -@implementation FDLDeviceHeuristicsHelper - -/** - * Creates DeviceInfo dictionary based on the provided information. - */ -+ (NSDictionary *) - FDLDeviceInfoDictionaryFromResolutionHeight:(NSInteger)resolutionHeight - resolutionWidth:(NSInteger)resolutionWidth - locale:(NSString *)locale - localeRaw:(NSString *)localeRaw - localeFromWebview:(NSString *)localeFromWebView - timeZone:(NSString *)timezone - modelName:(NSString *)modelName { - return @{ - @"screenResolutionHeight" : @(resolutionHeight), - @"screenResolutionWidth" : @(resolutionWidth), - @"languageCode" : locale, - @"languageCodeRaw" : localeRaw, - @"languageCodeFromWebview" : localeFromWebView, - @"timezone" : timezone, - @"deviceModelName" : modelName, - }; -} -@end diff --git a/FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h b/FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h deleted file mode 100644 index a985355e907..00000000000 --- a/FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -FOUNDATION_EXPORT NSString *const kFIRDLParameterDeepLinkIdentifier; -FOUNDATION_EXPORT NSString *const kFIRDLParameterLink; -FOUNDATION_EXPORT NSString *const kFIRDLParameterMinimumAppVersion; -FOUNDATION_EXPORT NSString *const kFIRDLParameterCampaign; -FOUNDATION_EXPORT NSString *const kFIRDLParameterContent; -FOUNDATION_EXPORT NSString *const kFIRDLParameterMedium; -FOUNDATION_EXPORT NSString *const kFIRDLParameterTerm; -FOUNDATION_EXPORT NSString *const kFIRDLParameterSource; -FOUNDATION_EXPORT NSString *const kFIRDLParameterMatchType; -FOUNDATION_EXPORT NSString *const kFIRDLParameterInviteId; -FOUNDATION_EXPORT NSString *const kFIRDLParameterWeakMatchEndpoint; -FOUNDATION_EXPORT NSString *const kFIRDLParameterMatchMessage; -FOUNDATION_EXPORT NSString *const kFIRDLParameterRequestIPVersion; - -/** - * After a Dynamic Link URL is opened in Safari, a cookie is dropped on the domain goo.gl. When a - * specific URL is used, JavaScript checks if there's a cookie and, if it exists, redirects to the - * custom-scheme URL stored in it. That causes application:openURL:options: to be called in - * AppDelegate with the custom-scheme URL. This method creates and returns the URL required to check - * for the presence of the FDL cookie on goo.gl. - */ -NSURL *FIRDLCookieRetrievalURL(NSString *urlScheme, NSString *bundleID); - -/** - * Creates a URL query string from the contents of an NSDictionary. Single-percent-encoded using - * allowed query characters. - */ -NSString *FIRDLURLQueryStringFromDictionary(NSDictionary *dictionary); - -/** - * @fn FIRDLDictionaryFromQuery - * @abstract This receives a URL query parameter string and parses it into a dictionary that - * represents the query. This method is necessary as |gtm_dictionaryWithHttpArgumentsString:| - * removes the pluses with spaces and, as a result, cannot be used without first replacing all - * instances of the plus character with '%2B'. - * @param queryString The query string of a URL. - * @return returns a dictionary of type that represents the query. - */ -NSDictionary *FIRDLDictionaryFromQuery(NSString *queryString); - -/** - * @fn FIRDLDeepLinkURLWithInviteID - * @abstract A method that takes the given parameters and constructs a url-scheme-based URL that can - * be opened within the containing app, so that the correct link handlers are fired. This is - * used after Firebase Dynamic Links either has found a pending deep link, or no link was found. - * @param inviteID The invitation ID associated with the Dynamic Link. Included in App Invite URLs. - * @param deepLinkString The deep link, if any, found in the response from a server lookup. - * @param utmSource The UTM source, if any, found in the response from a server lookup. - * @param utmMedium The UTM medium, if any, found in the response from a server lookup. - * @param utmCampaign The UTM campaign, if any, found in the response from a server lookup. - * @param isWeakLink This value provides information is deep link was weak-matched. - * @param weakMatchEndpoint This value provides information about which endpoint, IPv4 or IPv6, was - * used to perform the lookup if weak match is used. - * @param minAppVersion The minimum app version string, if any, found in the response from a server - * lookup. If this value is provided, the app developer can use it to determine whether or not - * to handle the deep link, or to encourage their users to perhaps upgrade their app. - * @param URLScheme Custom URL scheme of the Application. - */ -NSURL *FIRDLDeepLinkURLWithInviteID(NSString *_Nullable inviteID, - NSString *_Nullable deepLinkString, - NSString *_Nullable utmSource, - NSString *_Nullable utmMedium, - NSString *_Nullable utmCampaign, - NSString *_Nullable utmContent, - NSString *_Nullable utmTerm, - BOOL isWeakLink, - NSString *_Nullable weakMatchEndpoint, - NSString *_Nullable minAppVersion, - NSString *URLScheme, - NSString *_Nullable matchMessage); - -/** - * @fn FIRDLOSVersionSupported(NSString *systemVersion, NSString *minSupportedVersion) - * @abstract Determines if the system version is greater than or equal to the minSupportedVersion. - * @param systemVersion The iOS version to use as the current version in the comparison. - * @param minSupportedVersion The minimum iOS system version that is supported. - * @return YES if the system version is greater than or equal to the minimum, otherwise, NO. - */ -BOOL FIRDLOSVersionSupported(NSString *_Nullable systemVersion, NSString *minSupportedVersion); - -/** - Returns date of the App installation. Return value may be nil in case of failure. - */ -NSDate *_Nullable FIRDLAppInstallationDate(void); - -/** - Returns current device model name. - */ -NSString *FIRDLDeviceModelName(void); - -/** - Returns current device locale. The method will try to bring locale format to the same format as - reported by Safari/WebView. - */ -NSString *FIRDLDeviceLocale(void) __deprecated_msg("Use FIRDeviceLocaleRaw instead"); - -/** - Returns current device locale as reported by iOS. - */ -NSString *FIRDLDeviceLocaleRaw(void); - -/** - Returns current device timezone. - */ -NSString *FIRDLDeviceTimezone(void); - -/** - Returns is universal link (long FDL link) parsable. - */ -BOOL FIRDLCanParseUniversalLinkURL(NSURL *_Nullable URL); - -/** - Return is link matches FDL short link format. - */ -BOOL FIRDLMatchesShortLinkFormat(NSURL *URL); - -/** - Returns match type string using server side match type string. - Returned string can be used as customURLScheme URL with parameter kFIRDLParameterMatchType. - */ -NSString *FIRDLMatchTypeStringFromServerString(NSString *_Nullable serverMatchTypeString); - -/** - Add custom domains from the info.plist to the internal allowlist. - */ -void FIRDLAddToAllowListForCustomDomainsArray(NSArray *customDomains); - -NS_ASSUME_NONNULL_END diff --git a/FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.m b/FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.m deleted file mode 100644 index fa00871bce0..00000000000 --- a/FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.m +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#if TARGET_OS_IOS - -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -#import -#include - -NS_ASSUME_NONNULL_BEGIN - -NSString *const kFIRDLParameterDeepLinkIdentifier = @"deep_link_id"; -NSString *const kFIRDLParameterLink = @"link"; -NSString *const kFIRDLParameterMinimumAppVersion = @"imv"; -NSString *const kFIRDLParameterCampaign = @"utm_campaign"; -NSString *const kFIRDLParameterContent = @"utm_content"; -NSString *const kFIRDLParameterMedium = @"utm_medium"; -NSString *const kFIRDLParameterSource = @"utm_source"; -NSString *const kFIRDLParameterTerm = @"utm_term"; -NSString *const kFIRDLParameterMatchType = @"match_type"; -NSString *const kFIRDLParameterInviteId = @"invitation_id"; -NSString *const kFIRDLParameterWeakMatchEndpoint = @"invitation_weakMatchEndpoint"; -NSString *const kFIRDLParameterMatchMessage = @"match_message"; -NSString *const kFIRDLParameterRequestIPVersion = @"request_ip_version"; -static NSSet *FIRDLCustomDomains = nil; - -NSURL *FIRDLCookieRetrievalURL(NSString *urlScheme, NSString *bundleID) { - static NSString *const kFDLBundleIDQueryParameterName = @"fdl_ios_bundle_id"; - static NSString *const kFDLURLSchemeQueryParameterName = @"fdl_ios_url_scheme"; - - NSURLComponents *components = [[NSURLComponents alloc] init]; - components.scheme = @"https"; - components.host = @"goo.gl"; - components.path = @"/app/_/deeplink"; - NSMutableArray *queryItems = [NSMutableArray array]; - - [queryItems addObject:[NSURLQueryItem queryItemWithName:kFDLBundleIDQueryParameterName - value:bundleID]]; - [queryItems addObject:[NSURLQueryItem queryItemWithName:kFDLURLSchemeQueryParameterName - value:urlScheme]]; - [components setQueryItems:queryItems]; - - return [components URL]; -} - -NSString *FIRDLURLQueryStringFromDictionary(NSDictionary *dictionary) { - NSMutableString *parameters = [NSMutableString string]; - - NSCharacterSet *queryCharacterSet = [NSCharacterSet alphanumericCharacterSet]; - NSString *parameterFormatString = @"%@%@=%@"; - __block NSUInteger index = 0; - [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull key, NSString *_Nonnull value, - BOOL *_Nonnull stop) { - NSString *delimiter = index++ == 0 ? @"?" : @"&"; - NSString *encodedValue = - [value stringByAddingPercentEncodingWithAllowedCharacters:queryCharacterSet]; - NSString *parameter = - [NSString stringWithFormat:parameterFormatString, delimiter, key, encodedValue]; - [parameters appendString:parameter]; - }]; - - return parameters; -} - -NSDictionary *FIRDLDictionaryFromQuery(NSString *queryString) { - NSArray *keyValuePairs = [queryString componentsSeparatedByString:@"&"]; - - NSMutableDictionary *queryDictionary = - [NSMutableDictionary dictionaryWithCapacity:keyValuePairs.count]; - - for (NSString *pair in keyValuePairs) { - NSArray *keyValuePair = [pair componentsSeparatedByString:@"="]; - if (keyValuePair.count == 2) { - NSString *key = keyValuePair[0]; - NSString *value = [keyValuePair[1] stringByRemovingPercentEncoding]; - [queryDictionary setObject:value forKey:key]; - } - } - - return [queryDictionary copy]; -} - -NSURL *FIRDLDeepLinkURLWithInviteID(NSString *_Nullable inviteID, - NSString *_Nullable deepLinkString, - NSString *_Nullable utmSource, - NSString *_Nullable utmMedium, - NSString *_Nullable utmCampaign, - NSString *_Nullable utmContent, - NSString *_Nullable utmTerm, - BOOL isWeakLink, - NSString *_Nullable weakMatchEndpoint, - NSString *_Nullable minAppVersion, - NSString *URLScheme, - NSString *_Nullable matchMessage) { - // We are unable to use NSURLComponents as NSURLQueryItem is available beginning in iOS 8 and - // appending our query string with NSURLComponents improperly formats the query by adding - // a second '?' in the query. - NSMutableDictionary *queryDictionary = [NSMutableDictionary dictionary]; - if (inviteID != nil) { - queryDictionary[kFIRDLParameterInviteId] = inviteID; - } - if (deepLinkString != nil) { - queryDictionary[kFIRDLParameterDeepLinkIdentifier] = deepLinkString; - } - if (utmSource != nil) { - queryDictionary[kFIRDLParameterSource] = utmSource; - } - if (utmMedium != nil) { - queryDictionary[kFIRDLParameterMedium] = utmMedium; - } - if (utmCampaign != nil) { - queryDictionary[kFIRDLParameterCampaign] = utmCampaign; - } - - if (utmContent != nil) { - queryDictionary[kFIRDLParameterContent] = utmContent; - } - - if (utmTerm != nil) { - queryDictionary[kFIRDLParameterTerm] = utmTerm; - } - - if (isWeakLink) { - queryDictionary[kFIRDLParameterMatchType] = @"weak"; - } else { - queryDictionary[kFIRDLParameterMatchType] = @"unique"; - } - if (weakMatchEndpoint != nil) { - queryDictionary[kFIRDLParameterWeakMatchEndpoint] = weakMatchEndpoint; - } - if (minAppVersion != nil) { - queryDictionary[kFIRDLParameterMinimumAppVersion] = minAppVersion; - } - if (matchMessage != nil) { - queryDictionary[kFIRDLParameterMatchMessage] = matchMessage; - } - - NSString *scheme = [URLScheme lowercaseString]; - NSString *queryString = FIRDLURLQueryStringFromDictionary(queryDictionary); - NSString *urlString = [NSString stringWithFormat:@"%@://google/link/%@", scheme, queryString]; - - return [NSURL URLWithString:urlString]; -} - -BOOL FIRDLOSVersionSupported(NSString *_Nullable systemVersion, NSString *minSupportedVersion) { - systemVersion = systemVersion ?: [UIDevice currentDevice].systemVersion; - return [systemVersion compare:minSupportedVersion options:NSNumericSearch] != NSOrderedAscending; -} - -NSDate *_Nullable FIRDLAppInstallationDate(void) { - NSURL *documentsDirectoryURL = - [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory - inDomains:NSUserDomainMask] firstObject]; - if (!documentsDirectoryURL) { - return nil; - } - NSDictionary *attributes = - [[NSFileManager defaultManager] attributesOfItemAtPath:documentsDirectoryURL.path error:NULL]; - if (attributes[NSFileCreationDate] && - [attributes[NSFileCreationDate] isKindOfClass:[NSDate class]]) { - return attributes[NSFileCreationDate]; - } - return nil; -} - -NSString *FIRDLDeviceModelName(void) { - // this method will return string like iPad3,3 - // for Simulator this will be x86_64 - static NSString *machineString = @""; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - size_t size; - - // compute string size - if (sysctlbyname("hw.machine", NULL, &size, NULL, 0) == 0) { - // get device name - char *machine = calloc(1, size); - if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == 0) { - machineString = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding]; - } - free(machine); - } - }); - return machineString; -} - -NSString *FIRDLDeviceLocale(void) { - // expected return value from this method looks like: @"en-US" - return [[[NSLocale currentLocale] localeIdentifier] stringByReplacingOccurrencesOfString:@"_" - withString:@"-"]; -} - -NSString *FIRDLDeviceLocaleRaw(void) { - return [[NSLocale currentLocale] localeIdentifier]; -} - -NSString *FIRDLDeviceTimezone(void) { - NSString *timeZoneName = [[NSTimeZone localTimeZone] name]; - return timeZoneName; -} - -BOOL FIRDLIsURLForAllowedCustomDomain(NSURL *URL) { - if (URL) { - for (NSURL *allowedCustomDomain in FIRDLCustomDomains) { - // At least one custom domain host name should match at a minimum. - if ([URL.absoluteString hasPrefix:allowedCustomDomain.absoluteString]) { - NSString *urlWithoutDomainURIPrefix = - [URL.absoluteString substringFromIndex:allowedCustomDomain.absoluteString.length]; - - // The urlWithoutDomainURIPrefix should be starting with '/' or '?' otherwise it means the - // allowed domain is not exactly matching the incoming URL domain prefix. - if ([urlWithoutDomainURIPrefix hasPrefix:@"/"] || - [urlWithoutDomainURIPrefix hasPrefix:@"?"]) { - // For a valid custom domain DL Suffix the urlWithoutDomainURIPrefix should have: - // 1. At least one path exists OR - // 2. Should have a link query param with an http/https link - - NSURLComponents *components = - [[NSURLComponents alloc] initWithString:urlWithoutDomainURIPrefix]; - if (components.path && components.path.length > 1) { - // Have a path exists. So valid custom domain. - return true; - } - - if (components.queryItems && components.queryItems.count > 0) { - for (NSURLQueryItem *queryItem in components.queryItems) { - // Checks whether we have a link query param - if ([queryItem.name caseInsensitiveCompare:@"link"] == NSOrderedSame) { - // Checks whether link query param value starts with http/https - if (queryItem.value && ([queryItem.value hasPrefix:@"http://"] || - [queryItem.value hasPrefix:@"https://"])) { - return true; - } - } - } - } - } - } - } - } - return false; -} - -/* We are validating following domains in proper format. - *.page.link - *.app.goo.gl - *.page.link/i/ - *.app.goo.gl/i/ - */ -BOOL FIRDLIsAValidDLWithFDLDomain(NSURL *_Nullable URL) { - BOOL matchesRegularExpression = false; - NSString *urlStr = URL.absoluteString; - - if ([URL.host containsString:@".page.link"] || [URL.host containsString:@".app.goo.gl"] || - [URL.host containsString:@".app.google"]) { - // Matches the *.page.link and *.app.goo.gl domains. - matchesRegularExpression = - ([urlStr rangeOfString: - @"^https?://" - @"[a-zA-Z0-9]+((\\.app\\.goo\\.gl)|(\\.page\\.link)|(\\.app\\.google))((\\/" - @"?\\?.*link=https?.*)|(\\/[a-zA-Z0-9-_]+)((\\/?\\?.*=.*)?$|$))" - options:NSRegularExpressionSearch] - .location != NSNotFound); - - if (!matchesRegularExpression) { - // Matches the *.page.link/i/ and *.app.goo.gl/i/ domains. - // Checks whether the URL is of the format : - // http(s)://$DOMAIN(.page.link or .app.goo.gl)/i/$ANYTHING - matchesRegularExpression = - ([urlStr - rangeOfString: - @"^https?:\\/\\/" - @"[a-zA-Z0-9]+((\\.app\\.goo\\.gl)|(\\.page\\.link)|(\\.app\\.google))\\/i\\/.*$" - options:NSRegularExpressionSearch] - .location != NSNotFound); - } - } - - return matchesRegularExpression; -} - -/* - DL can be parsed if it : - 1. Has http(s)://goo.gl/app* or http(s)://page.link/app* format - 2. OR http(s)://$DomainPrefix.page.link or http(s)://$DomainPrefix.app.goo.gl domain with specific - format - 3. OR the domain is a listed custom domain - */ -BOOL FIRDLCanParseUniversalLinkURL(NSURL *_Nullable URL) { - // Handle universal links with format |https://goo.gl/app/?|. - // Also support page.link format. - BOOL isDDLWithAppcodeInPath = ([URL.host isEqual:@"goo.gl"] || [URL.host isEqual:@"page.link"] || - [URL.host isEqual:@"app.google"]) && - [URL.path hasPrefix:@"/app"]; - - return isDDLWithAppcodeInPath || FIRDLIsAValidDLWithFDLDomain(URL) || - FIRDLIsURLForAllowedCustomDomain(URL); -} - -BOOL FIRDLMatchesShortLinkFormat(NSURL *URL) { - // Short Durable Link URLs always have a path or it should be a custom domain. - BOOL hasPathOrCustomDomain = URL.path.length > 0 || FIRDLIsURLForAllowedCustomDomain(URL); - - // Must be able to parse (also checks if the URL conforms to *.app.goo.gl/* or goo.gl/app/* or - // *.page.link or custom domain with valid suffix) - BOOL canParse = FIRDLCanParseUniversalLinkURL(URL); - - // Path cannot be prefixed with /link/dismiss - BOOL isDismiss = [[URL.path lowercaseString] hasPrefix:@"/link/dismiss"]; - - // Checks short link format by having only one path after domain prefix. - BOOL matchesRegularExpression = - ([URL.path rangeOfString:@"/[^/]+" options:NSRegularExpressionSearch].location != NSNotFound); - - return hasPathOrCustomDomain && !isDismiss && canParse && matchesRegularExpression; -} - -NSString *FIRDLMatchTypeStringFromServerString(NSString *_Nullable serverMatchTypeString) { - static NSDictionary *matchMap; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - matchMap = @{ - @"WEAK" : @"weak", - @"DEFAULT" : @"default", - @"UNIQUE" : @"unique", - }; - }); - return matchMap[serverMatchTypeString] ?: @"none"; -} - -void FIRDLAddToAllowListForCustomDomainsArray(NSArray *_Nonnull customDomains) { - // Duplicates will be weeded out when converting to a set. - NSMutableArray *validCustomDomains = - [[NSMutableArray alloc] initWithCapacity:customDomains.count]; - for (NSString *customDomainEntry in customDomains) { - // We remove trailing slashes in the path if present. - NSString *domainEntry = - [customDomainEntry hasSuffix:@"/"] - ? [customDomainEntry substringToIndex:[customDomainEntry length] - 1] - : customDomainEntry; - NSURL *customDomainURL = [NSURL URLWithString:domainEntry]; - // We require a valid scheme for each custom domain enumerated in the info.plist file. - if (customDomainURL && customDomainURL.scheme) { - [validCustomDomains addObject:customDomainURL]; - } - } - // Duplicates will be weeded out when converting to a set. - FIRDLCustomDomains = [NSSet setWithArray:validCustomDomains]; -} - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_IOS diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC.xcodeproj/project.pbxproj b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC.xcodeproj/project.pbxproj deleted file mode 100644 index 89d6a91da27..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC.xcodeproj/project.pbxproj +++ /dev/null @@ -1,442 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 51; - objects = { - -/* Begin PBXBuildFile section */ - 5B41DB1823E3A71C00929EC5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B41DB1723E3A71C00929EC5 /* AppDelegate.m */; }; - 5B41DB1B23E3A71C00929EC5 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B41DB1A23E3A71C00929EC5 /* SceneDelegate.m */; }; - 5B41DB1E23E3A71C00929EC5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B41DB1D23E3A71C00929EC5 /* ViewController.m */; }; - 5B41DB2123E3A71C00929EC5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B41DB1F23E3A71C00929EC5 /* Main.storyboard */; }; - 5B41DB2323E3A71E00929EC5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5B41DB2223E3A71E00929EC5 /* Assets.xcassets */; }; - 5B41DB2623E3A71E00929EC5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B41DB2423E3A71E00929EC5 /* LaunchScreen.storyboard */; }; - 5B41DB2923E3A71E00929EC5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B41DB2823E3A71E00929EC5 /* main.m */; }; - 5B41DB3323E3A7FA00929EC5 /* LinkTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B41DB2F23E3A7F900929EC5 /* LinkTableViewCell.m */; }; - 5B41DB3423E3A7FA00929EC5 /* ParamTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B41DB3123E3A7F900929EC5 /* ParamTableViewCell.m */; }; - 5B41DB3623E3A8F400929EC5 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5B41DB3523E3A8F400929EC5 /* GoogleService-Info.plist */; }; - CF16533A355AFED181ABDD38 /* Pods_FDLBuilderTestAppObjC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B90D2E2F25A43DD8A8773AF2 /* Pods_FDLBuilderTestAppObjC.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 5B3E9BB723E3ADDC00FF3A1E /* FDLBuilderTestAppObjC.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FDLBuilderTestAppObjC.entitlements; sourceTree = ""; }; - 5B41DB1323E3A71C00929EC5 /* FDLBuilderTestAppObjC.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FDLBuilderTestAppObjC.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 5B41DB1623E3A71C00929EC5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 5B41DB1723E3A71C00929EC5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 5B41DB1923E3A71C00929EC5 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = ""; }; - 5B41DB1A23E3A71C00929EC5 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = ""; }; - 5B41DB1C23E3A71C00929EC5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - 5B41DB1D23E3A71C00929EC5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - 5B41DB2023E3A71C00929EC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 5B41DB2223E3A71E00929EC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 5B41DB2523E3A71E00929EC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 5B41DB2723E3A71E00929EC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5B41DB2823E3A71E00929EC5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 5B41DB2F23E3A7F900929EC5 /* LinkTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LinkTableViewCell.m; sourceTree = ""; }; - 5B41DB3023E3A7F900929EC5 /* LinkTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkTableViewCell.h; sourceTree = ""; }; - 5B41DB3123E3A7F900929EC5 /* ParamTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ParamTableViewCell.m; sourceTree = ""; }; - 5B41DB3223E3A7FA00929EC5 /* ParamTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParamTableViewCell.h; sourceTree = ""; }; - 5B41DB3523E3A8F400929EC5 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - 8C3596C191E82DCECC6735C8 /* Pods-FDLBuilderTestAppObjC.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FDLBuilderTestAppObjC.release.xcconfig"; path = "Target Support Files/Pods-FDLBuilderTestAppObjC/Pods-FDLBuilderTestAppObjC.release.xcconfig"; sourceTree = ""; }; - B90D2E2F25A43DD8A8773AF2 /* Pods_FDLBuilderTestAppObjC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FDLBuilderTestAppObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E8ED1BD19C174903FC5BDF2C /* Pods-FDLBuilderTestAppObjC.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FDLBuilderTestAppObjC.debug.xcconfig"; path = "Target Support Files/Pods-FDLBuilderTestAppObjC/Pods-FDLBuilderTestAppObjC.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 5B41DB1023E3A71C00929EC5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - CF16533A355AFED181ABDD38 /* Pods_FDLBuilderTestAppObjC.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 165ECBBDCCBFA3107802A5B8 /* Pods */ = { - isa = PBXGroup; - children = ( - E8ED1BD19C174903FC5BDF2C /* Pods-FDLBuilderTestAppObjC.debug.xcconfig */, - 8C3596C191E82DCECC6735C8 /* Pods-FDLBuilderTestAppObjC.release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - 5B41DB0A23E3A71C00929EC5 = { - isa = PBXGroup; - children = ( - 5B41DB3523E3A8F400929EC5 /* GoogleService-Info.plist */, - 5B41DB1523E3A71C00929EC5 /* FDLBuilderTestAppObjC */, - 5B41DB1423E3A71C00929EC5 /* Products */, - 165ECBBDCCBFA3107802A5B8 /* Pods */, - 8AB095C8794DB7CBE5853D77 /* Frameworks */, - ); - sourceTree = ""; - }; - 5B41DB1423E3A71C00929EC5 /* Products */ = { - isa = PBXGroup; - children = ( - 5B41DB1323E3A71C00929EC5 /* FDLBuilderTestAppObjC.app */, - ); - name = Products; - sourceTree = ""; - }; - 5B41DB1523E3A71C00929EC5 /* FDLBuilderTestAppObjC */ = { - isa = PBXGroup; - children = ( - 5B3E9BB723E3ADDC00FF3A1E /* FDLBuilderTestAppObjC.entitlements */, - 5B41DB3023E3A7F900929EC5 /* LinkTableViewCell.h */, - 5B41DB2F23E3A7F900929EC5 /* LinkTableViewCell.m */, - 5B41DB3223E3A7FA00929EC5 /* ParamTableViewCell.h */, - 5B41DB3123E3A7F900929EC5 /* ParamTableViewCell.m */, - 5B41DB1623E3A71C00929EC5 /* AppDelegate.h */, - 5B41DB1723E3A71C00929EC5 /* AppDelegate.m */, - 5B41DB1923E3A71C00929EC5 /* SceneDelegate.h */, - 5B41DB1A23E3A71C00929EC5 /* SceneDelegate.m */, - 5B41DB1C23E3A71C00929EC5 /* ViewController.h */, - 5B41DB1D23E3A71C00929EC5 /* ViewController.m */, - 5B41DB1F23E3A71C00929EC5 /* Main.storyboard */, - 5B41DB2223E3A71E00929EC5 /* Assets.xcassets */, - 5B41DB2423E3A71E00929EC5 /* LaunchScreen.storyboard */, - 5B41DB2723E3A71E00929EC5 /* Info.plist */, - 5B41DB2823E3A71E00929EC5 /* main.m */, - ); - path = FDLBuilderTestAppObjC; - sourceTree = ""; - }; - 8AB095C8794DB7CBE5853D77 /* Frameworks */ = { - isa = PBXGroup; - children = ( - B90D2E2F25A43DD8A8773AF2 /* Pods_FDLBuilderTestAppObjC.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 5B41DB1223E3A71C00929EC5 /* FDLBuilderTestAppObjC */ = { - isa = PBXNativeTarget; - buildConfigurationList = 5B41DB2C23E3A71E00929EC5 /* Build configuration list for PBXNativeTarget "FDLBuilderTestAppObjC" */; - buildPhases = ( - 064F9DD0B6255FE37CE6E06D /* [CP] Check Pods Manifest.lock */, - 5B41DB0F23E3A71C00929EC5 /* Sources */, - 5B41DB1023E3A71C00929EC5 /* Frameworks */, - 5B41DB1123E3A71C00929EC5 /* Resources */, - 94C2948974AD9FEF43500B54 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = FDLBuilderTestAppObjC; - productName = FDLBuilderTestAppObjC; - productReference = 5B41DB1323E3A71C00929EC5 /* FDLBuilderTestAppObjC.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 5B41DB0B23E3A71C00929EC5 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1130; - ORGANIZATIONNAME = "Google Inc"; - TargetAttributes = { - 5B41DB1223E3A71C00929EC5 = { - CreatedOnToolsVersion = 11.3.1; - }; - }; - }; - buildConfigurationList = 5B41DB0E23E3A71C00929EC5 /* Build configuration list for PBXProject "FDLBuilderTestAppObjC" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 5B41DB0A23E3A71C00929EC5; - productRefGroup = 5B41DB1423E3A71C00929EC5 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 5B41DB1223E3A71C00929EC5 /* FDLBuilderTestAppObjC */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 5B41DB1123E3A71C00929EC5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5B41DB2623E3A71E00929EC5 /* LaunchScreen.storyboard in Resources */, - 5B41DB3623E3A8F400929EC5 /* GoogleService-Info.plist in Resources */, - 5B41DB2323E3A71E00929EC5 /* Assets.xcassets in Resources */, - 5B41DB2123E3A71C00929EC5 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 064F9DD0B6255FE37CE6E06D /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-FDLBuilderTestAppObjC-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 94C2948974AD9FEF43500B54 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-FDLBuilderTestAppObjC/Pods-FDLBuilderTestAppObjC-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-FDLBuilderTestAppObjC/Pods-FDLBuilderTestAppObjC-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FDLBuilderTestAppObjC/Pods-FDLBuilderTestAppObjC-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 5B41DB0F23E3A71C00929EC5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 5B41DB1E23E3A71C00929EC5 /* ViewController.m in Sources */, - 5B41DB3423E3A7FA00929EC5 /* ParamTableViewCell.m in Sources */, - 5B41DB1823E3A71C00929EC5 /* AppDelegate.m in Sources */, - 5B41DB3323E3A7FA00929EC5 /* LinkTableViewCell.m in Sources */, - 5B41DB2923E3A71E00929EC5 /* main.m in Sources */, - 5B41DB1B23E3A71C00929EC5 /* SceneDelegate.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 5B41DB1F23E3A71C00929EC5 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 5B41DB2023E3A71C00929EC5 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 5B41DB2423E3A71E00929EC5 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 5B41DB2523E3A71E00929EC5 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 5B41DB2A23E3A71E00929EC5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.2; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 5B41DB2B23E3A71E00929EC5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.2; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 5B41DB2D23E3A71E00929EC5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E8ED1BD19C174903FC5BDF2C /* Pods-FDLBuilderTestAppObjC.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = FDLBuilderTestAppObjC/FDLBuilderTestAppObjC.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = EQHXZ8M8AV; - INFOPLIST_FILE = FDLBuilderTestAppObjC/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.dynamiclinks.demo.dev; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "Firebase Dynamic Links Demo Dev"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 5B41DB2E23E3A71E00929EC5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8C3596C191E82DCECC6735C8 /* Pods-FDLBuilderTestAppObjC.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = FDLBuilderTestAppObjC/FDLBuilderTestAppObjC.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = EQHXZ8M8AV; - INFOPLIST_FILE = FDLBuilderTestAppObjC/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.google.firebase.dynamiclinks.demo.dev; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "Firebase Dynamic Links Demo Dev"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 5B41DB0E23E3A71C00929EC5 /* Build configuration list for PBXProject "FDLBuilderTestAppObjC" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5B41DB2A23E3A71E00929EC5 /* Debug */, - 5B41DB2B23E3A71E00929EC5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 5B41DB2C23E3A71E00929EC5 /* Build configuration list for PBXNativeTarget "FDLBuilderTestAppObjC" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 5B41DB2D23E3A71E00929EC5 /* Debug */, - 5B41DB2E23E3A71E00929EC5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 5B41DB0B23E3A71C00929EC5 /* Project object */; -} diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.h b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.h deleted file mode 100644 index 31bd7f7f20a..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@interface AppDelegate : UIResponder - -@property(strong, nonatomic) UIWindow *window; - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.m b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.m deleted file mode 100644 index a318e3fea17..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/AppDelegate.m +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "AppDelegate.h" -#import "ViewController.h" - -#import -#import - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [FIRApp configure]; - - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - UINavigationController *navController = [[UINavigationController alloc] - initWithRootViewController:[[ViewController alloc] initWithNibName:nil bundle:nil]]; - self.window.rootViewController = navController; - [self.window makeKeyAndVisible]; - -#ifdef DEBUG - [FIRDynamicLinks performDiagnosticsWithCompletion:nil]; -#endif // DEBUG - - return YES; -} - -- (BOOL)application:(UIApplication *)app - openURL:(NSURL *)url - options:(NSDictionary *)options { - FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url]; - - if (dynamicLink) { - [self _showDynamicLinkInfo:dynamicLink]; - } - return YES; -} - -- (BOOL)application:(UIApplication *)application - openURL:(NSURL *)url - sourceApplication:(NSString *)sourceApplication - annotation:(id)annotation { - return [self application:application openURL:url options:@{}]; -} - -- (BOOL)application:(UIApplication *)application - continueUserActivity:(NSUserActivity *)userActivity - restorationHandler: -#if __has_include() - (void (^)(NSArray> *_Nullable))restorationHandler { -#else - (void (^)(NSArray *))restorationHandler { -#endif - BOOL handled = [[FIRDynamicLinks dynamicLinks] - handleUniversalLink:userActivity.webpageURL - completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { - [self _showDynamicLinkInfo:dynamicLink]; - }]; - - if (!handled) { - // Show the deep link URL from userActivity. - NSLog(@"Unhandled link %@", userActivity.webpageURL); - } - - return handled; -} - -- (void)_showDynamicLinkInfo:(FIRDynamicLink *)dynamicLink { - NSLog(@"Got dynamic link %@", dynamicLink); - - UIAlertController *alertVC = [UIAlertController - alertControllerWithTitle:@"Got Dynamic Link!" - message:[NSString stringWithFormat:@"URL [%@], matchType [%ld], " - @"minimumAppVersion [%@], utmParams [%@]", - dynamicLink.url, - (unsigned long)dynamicLink.matchType, - dynamicLink.minimumAppVersion, - dynamicLink.utmParametersDictionary] - preferredStyle:UIAlertControllerStyleAlert]; - [alertVC addAction:[UIAlertAction actionWithTitle:@"Dismiss" - style:UIAlertActionStyleCancel - handler:NULL]]; - - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertVC - animated:YES - completion:NULL]; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/AppIcon.appiconset/Contents.json b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index b542ec24d24..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/Contents.json b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/Contents.json deleted file mode 100644 index 2d92bd53fdb..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/LaunchScreen.storyboard b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 865e9329f37..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/Main.storyboard b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/Main.storyboard deleted file mode 100644 index 9c999bcaa25..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/FDLBuilderTestAppObjC.entitlements b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/FDLBuilderTestAppObjC.entitlements deleted file mode 100644 index 1c9bada1bf6..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/FDLBuilderTestAppObjC.entitlements +++ /dev/null @@ -1,20 +0,0 @@ - - - - - application-identifier - $(AppIdentifierPrefix)$(CFBundleIdentifier) - com.apple.developer.associated-domains - - applinks:goo.gl - applinks:testfdl.app.goo.gl - applinks:testfdl.page.link - - keychain-access-groups - - $(AppIdentifierPrefix)$(CFBundleIdentifier) - $(AppIdentifierPrefix)$(CFBundleIdentifier).sso - $(AppIdentifierPrefix)com.google.common.SSO - - - diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Info.plist b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Info.plist deleted file mode 100644 index 9a257ed9341..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/Info.plist +++ /dev/null @@ -1,83 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLName - Dev url scheme - CFBundleURLSchemes - - com.google.firebase.dynamiclinks.demo.dev - - - - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneConfigurationName - Default Configuration - UISceneDelegateClassName - SceneDelegate - UISceneStoryboardFile - Main - - - - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - FirebaseDynamicLinksCustomDomains - - https://google.com - https://google.com/one/ - https://a.firebase.com/mypath - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.h b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.h deleted file mode 100644 index d2f3701099d..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@interface LinkTableViewCell : UITableViewCell - -- (void)setTitle:(NSString *)title link:(NSString *)link; - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.m b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.m deleted file mode 100644 index c38ca7787b5..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/LinkTableViewCell.m +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "LinkTableViewCell.h" - -static const NSUInteger kHInset = 10; -static const NSUInteger kVInset = 4; - -@implementation LinkTableViewCell { - UILabel *_titleLabel; - UITextView *_linkTextView; -} - -- (instancetype)init { - self = [super initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:NSStringFromClass(self.class)]; - if (self) { - _titleLabel = [[UILabel alloc] init]; - _titleLabel.font = [UIFont systemFontOfSize:15]; - _linkTextView = [[UITextView alloc] init]; - _linkTextView.font = [UIFont boldSystemFontOfSize:15]; - _linkTextView.editable = NO; - _linkTextView.scrollEnabled = NO; - _linkTextView.dataDetectorTypes = UIDataDetectorTypeLink; - [self.contentView addSubview:_titleLabel]; - [self.contentView addSubview:_linkTextView]; - } - return self; -} - -- (void)layoutSubviews { - _titleLabel.frame = CGRectMake(kHInset, kVInset, self.contentView.frame.size.width - 2 * kHInset, - (self.contentView.frame.size.height / 2) - 2 * kVInset); - _linkTextView.frame = CGRectMake(kHInset, (self.contentView.frame.size.height / 2) + kVInset, - self.contentView.frame.size.width - 2 * kHInset, - (self.contentView.frame.size.height / 2) - 2 * kVInset); -} - -- (void)setTitle:(NSString *)title link:(NSString *)link { - self.accessibilityIdentifier = - [NSString stringWithFormat:@"%@-%@", NSStringFromClass(self.class), title]; - _linkTextView.accessibilityIdentifier = - [NSString stringWithFormat:@"%@-LinkTextView-%@", NSStringFromClass(self.class), title]; - - _titleLabel.text = title; - - if (link) { - NSURL *URL = [NSURL URLWithString:link]; - NSAttributedString *attributedLink = - [[NSAttributedString alloc] initWithString:link attributes:@{NSLinkAttributeName : URL}]; - _linkTextView.attributedText = attributedLink; - } - _linkTextView.accessibilityValue = link; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.h b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.h deleted file mode 100644 index bd3a67a8d91..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@class ParamTableViewCell; - -@protocol ParamTableViewCellDelegate - -- (void)paramTableViewCellUpdatedValue:(ParamTableViewCell *)cell; - -@end - -@interface ParamTableViewCell : UITableViewCell - -@property(nonatomic, readwrite, copy) NSDictionary *paramConfig; -@property(nonatomic, readwrite, copy) NSString *textFieldValue; -@property(nonatomic, weak) id delegate; - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.m b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.m deleted file mode 100644 index 78af6f8f3c5..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ParamTableViewCell.m +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "ParamTableViewCell.h" - -static const NSUInteger kHInset = 10; -static const NSUInteger kVInset = 4; - -@implementation ParamTableViewCell { - UILabel *_label; - UITextField *_textField; -} - -@synthesize paramConfig = _paramConfig; - -- (instancetype)init { - self = [super initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:NSStringFromClass(self.class)]; - if (self) { - self.selectionStyle = UITableViewCellSelectionStyleNone; - _label = [[UILabel alloc] init]; - _label.font = [UIFont italicSystemFontOfSize:[UIFont systemFontSize]]; - _textField = [[UITextField alloc] init]; - _textField.autocapitalizationType = UITextAutocapitalizationTypeNone; - [self.contentView addSubview:_label]; - [self.contentView addSubview:_textField]; - [_textField addTarget:self - action:@selector(onTextFieldValueChanged) - forControlEvents:UIControlEventEditingChanged]; - [_textField addTarget:self - action:@selector(onTextFieldDidEndOnExit) - forControlEvents:UIControlEventEditingDidEndOnExit]; - } - return self; -} - -- (void)layoutSubviews { - _label.frame = CGRectMake(kHInset, kVInset, self.contentView.frame.size.width - 2 * kHInset, - (self.contentView.frame.size.height / 2) - 2 * kVInset); - _textField.frame = CGRectMake(kHInset, (self.contentView.frame.size.height / 2) + kVInset, - self.contentView.frame.size.width - 2 * kHInset, - (self.contentView.frame.size.height / 2) - 2 * kVInset); -} - -- (void)onTextFieldValueChanged { - if (![self.textFieldValue isEqualToString:_textField.text]) { - self.textFieldValue = _textField.text; - [_delegate paramTableViewCellUpdatedValue:self]; - } -} - -- (void)onTextFieldDidEndOnExit { - [_textField resignFirstResponder]; -} - -- (void)setTextFieldValue:(NSString *)textFieldValue { - _textFieldValue = textFieldValue; - if (![_textFieldValue isEqualToString:_textField.text]) { - _textField.text = self.textFieldValue; - } -} - -- (void)setParamConfig:(NSDictionary *)paramConfig { - _paramConfig = [paramConfig copy]; - self.accessibilityIdentifier = _paramConfig[@"id"]; - _label.text = _paramConfig[@"label"]; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.h b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.h deleted file mode 100644 index c7bebfeae6b..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@interface SceneDelegate : UIResponder - -@property(strong, nonatomic) UIWindow* window; - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.m b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.m deleted file mode 100644 index 2cc043aef9b..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/SceneDelegate.m +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "SceneDelegate.h" - -#import - -@interface SceneDelegate () - -@end - -@implementation SceneDelegate - -- (void)scene:(UIScene *)scene - willConnectToSession:(UISceneSession *)session - options:(UISceneConnectionOptions *)connectionOptions { - // Use this method to optionally configure and attach the UIWindow `window` to the provided - // UIWindowScene `scene`. If using a storyboard, the `window` property will automatically be - // initialized and attached to the scene. This delegate does not imply the connecting scene or - // session are new (see `application:configurationForConnectingSceneSession` instead). - if (connectionOptions.userActivities && connectionOptions.userActivities.count > 0) { - NSUserActivity *userActivity = connectionOptions.userActivities.allObjects.firstObject; - [self handleDynamicLinkFromActivity:userActivity]; - } -} - -- (void)sceneDidDisconnect:(UIScene *)scene { - // Called as the scene is being released by the system. - // This occurs shortly after the scene enters the background, or when its session is discarded. - // Release any resources associated with this scene that can be re-created the next time the scene - // connects. The scene may re-connect later, as its session was not necessarily discarded (see - // `application:didDiscardSceneSessions` instead). -} - -- (void)sceneDidBecomeActive:(UIScene *)scene { - // Called when the scene has moved from an inactive state to an active state. - // Use this method to restart any tasks that were paused (or not yet started) when the scene was - // inactive. -} - -- (void)sceneWillResignActive:(UIScene *)scene { - // Called when the scene will move from an active state to an inactive state. - // This may occur due to temporary interruptions (ex. an incoming phone call). -} - -- (void)sceneWillEnterForeground:(UIScene *)scene { - // Called as the scene transitions from the background to the foreground. - // Use this method to undo the changes made on entering the background. -} - -- (void)sceneDidEnterBackground:(UIScene *)scene { - // Called as the scene transitions from the foreground to the background. - // Use this method to save data, release shared resources, and store enough scene-specific state - // information to restore the scene back to its current state. -} - -- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity { - [self handleDynamicLinkFromActivity:userActivity]; -} - -- (void)handleDynamicLinkFromActivity:(NSUserActivity *)userActivity { - if (!userActivity) { - return; - } - BOOL handled = [[FIRDynamicLinks dynamicLinks] - handleUniversalLink:userActivity.webpageURL - completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { - [self _showDynamicLinkInfo:dynamicLink]; - }]; - - if (!handled) { - // Show the deep link URL from userActivity. - NSLog(@"Unhandled link %@", userActivity.webpageURL); - } -} - -- (void)_showDynamicLinkInfo:(FIRDynamicLink *)dynamicLink { - NSLog(@"Got dynamic link %@", dynamicLink); - - UIAlertController *alertVC = [UIAlertController - alertControllerWithTitle:@"Got Dynamic Link!" - message:[NSString stringWithFormat:@"URL [%@], matchType [%ld], " - @"minimumAppVersion [%@], utmParams [%@]", - dynamicLink.url, - (unsigned long)dynamicLink.matchType, - dynamicLink.minimumAppVersion, - dynamicLink.utmParametersDictionary] - preferredStyle:UIAlertControllerStyleAlert]; - [alertVC addAction:[UIAlertAction actionWithTitle:@"Dismiss" - style:UIAlertActionStyleCancel - handler:NULL]]; - [self.window.rootViewController presentViewController:alertVC animated:YES completion:NULL]; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.h b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.h deleted file mode 100644 index 9096b8f39d5..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -@interface ViewController : UITableViewController - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.m b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.m deleted file mode 100644 index dc4a55e8286..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/ViewController.m +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "ViewController.h" - -#import -#import - -#import "LinkTableViewCell.h" -#import "ParamTableViewCell.h" - -static NSArray *kParamsConfiguration; - -@interface ViewController () -@end - -@implementation ViewController { - NSArray *_paramsConfiguration; - NSMutableDictionary *_paramValues; - - NSURL *_longLink; - NSURL *_shortLink; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.view.backgroundColor = [UIColor whiteColor]; - self.title = @"FDL Builder"; - - self.tableView.rowHeight = 60; - - [self _initDefaultValues]; -} - -#pragma mark - UITableViewDelegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section == 0 && indexPath.row == (kParamsConfiguration.count + 0)) { - [self _buildFDLLink]; - } - if (indexPath.section == 0 && indexPath.row == (kParamsConfiguration.count + 1)) { - // copy long link - if (_longLink) { - [UIPasteboard generalPasteboard].string = _longLink.absoluteString; - [self _presentMessage:@"Long Link copied to Clipboard" description:nil]; - } else { - [self _presentMessage:@"Long Link is empty" description:nil]; - } - } - if (indexPath.section == 0 && indexPath.row == (kParamsConfiguration.count + 2)) { - // copy short link - if (_shortLink) { - [UIPasteboard generalPasteboard].string = _shortLink.absoluteString; - [self _presentMessage:@"Short Link copied to Clipboard" description:nil]; - } else { - [self _presentMessage:@"Short Link is empty" description:nil]; - } - } -} - -#pragma mark - UITableViewDataSource - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (section == 0) { - return kParamsConfiguration.count + 3; - } else { - return 0; - } -} - -- (UITableViewCell *)tableView:(UITableView *)tableView - cellForRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.row >= kParamsConfiguration.count) { - return [self _customCellForRow:indexPath.row - kParamsConfiguration.count]; - } else { - ParamTableViewCell *cell = - (ParamTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"ParamTableViewCell"]; - if (!cell) { - cell = [[ParamTableViewCell alloc] init]; - } - NSDictionary *paramConfig = kParamsConfiguration[indexPath.row]; - cell.paramConfig = paramConfig; - cell.textFieldValue = _paramValues[paramConfig[@"id"]]; - cell.delegate = self; - return cell; - } -} - -- (void)paramTableViewCellUpdatedValue:(ParamTableViewCell *)cell; -{ _paramValues[cell.paramConfig[@"id"]] = cell.textFieldValue; } - -#pragma mark - Private methods - -- (UITableViewCell *)_customCellForRow:(NSUInteger)row { - switch (row) { - case 0: { - UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"cell"]; - cell.textLabel.text = @"Generate Link"; - cell.accessibilityIdentifier = @"generate-link"; - cell.textLabel.textAlignment = NSTextAlignmentCenter; - cell.textLabel.font = [UIFont boldSystemFontOfSize:22]; - return cell; - } break; - - case 1: - case 2: { - LinkTableViewCell *cell = (LinkTableViewCell *)[self.tableView - dequeueReusableCellWithIdentifier:@"LinkTableViewCell"]; - if (!cell) { - cell = [[LinkTableViewCell alloc] init]; - } - if (row == 1) { - [cell setTitle:@"Long link" link:_longLink.absoluteString]; - } else { - [cell setTitle:@"Short link" link:_shortLink.absoluteString]; - } - return cell; - } break; - case 3: { - UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"cell"]; - cell.textLabel.text = @"Perform FDL self diagnostic"; - cell.textLabel.textAlignment = NSTextAlignmentCenter; - cell.textLabel.font = [UIFont systemFontOfSize:22]; - return cell; - } break; - } - return nil; -} - -- (void)_initDefaultValues { - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - kParamsConfiguration = @[ - // general link params - @{ - @"id" : @"linkString", - @"label" : @"Link value (required)", - @"defaultValue" : @"https://www.google.com?q=jump", - }, - // The default value of domain appcode belongs to project: app-invites-qa - @{ - @"id" : @"domainURIPrefix", - @"label" : @"App domainURIPrefix (required)", - @"defaultValue" : @"https://testfdl.page.link", - }, - // analytics params - @{ - @"id" : @"FIRDynamicLinkGoogleAnalyticsParameters.source", - @"label" : @"Google Analytics source (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkGoogleAnalyticsParameters.medium", - @"label" : @"Google Analytics medium (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkGoogleAnalyticsParameters.campaign", - @"label" : @"Google Analytics campaign (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkGoogleAnalyticsParameters.term", - @"label" : @"Google Analytics term (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkGoogleAnalyticsParameters.content", - @"label" : @"Google Analytics content (optional)", - @"defaultValue" : @"", - }, - // iOS params - @{ - @"id" : @"FIRDynamicLinkIOSParameters.bundleId", - @"label" : @"iOS App bundle ID", - @"defaultValue" : [[NSBundle mainBundle] bundleIdentifier] ?: @"", - }, - @{ - @"id" : @"FIRDynamicLinkIOSParameters.fallbackURL", - @"label" : @"Fallback URL iOS (optional)", - }, - @{ - @"id" : @"FIRDynamicLinkIOSParameters.minimumAppVersion", - @"label" : @"minimum version of iOS App (optional)", - @"defaultValue" : @"1.0", - }, - @{ - @"id" : @"FIRDynamicLinkIOSParameters.customScheme", - @"label" : @"iOS App custom scheme (optional)", - }, - @{ - @"id" : @"FIRDynamicLinkIOSParameters.iPadBundleID", - @"label" : @"iPad App bundleID (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkIOSParameters.iPadFallbackURL", - @"label" : @"Fallback URL on iPad (optional)", - }, - @{ - @"id" : @"FIRDynamicLinkIOSParameters.appStoreID", - @"label" : @"iOS AppStore ID (optional)", - }, - - // iTunesConnect params - @{ - @"id" : @"FIRDynamicLinkItunesConnectAnalyticsParameters.affiliateToken", - @"label" : @"iTunesConnect affiliate token (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkItunesConnectAnalyticsParameters.campaignToken", - @"label" : @"iTunesConnect campaign token (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkItunesConnectAnalyticsParameters.providerToken", - @"label" : @"iTunesConnect provider token (optional)", - @"defaultValue" : @"", - }, - - // Android params - @{ - @"id" : @"FIRDynamicLinkAndroidParameters.packageName", - @"label" : @"Android App package name (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkAndroidParameters.fallbackURL", - @"label" : @"Android fallback URL (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkAndroidParameters.minimumVersion", - @"label" : @"Andropid App minimum version, integer number (optional)", - @"defaultValue" : @"", - }, - - // social tag params - @{ - @"id" : @"FIRDynamicLinkSocialMetaTagParameters.title", - @"label" : @"Social meta tag title (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkSocialMetaTagParameters.descriptionText", - @"label" : @"Social meta tag description text (optional)", - @"defaultValue" : @"", - }, - @{ - @"id" : @"FIRDynamicLinkSocialMetaTagParameters.imageURL", - @"label" : @"Social meta tag image URL (optional)", - @"defaultValue" : @"", - }, - - // OtherPlatform params - @{ - @"id" : @"FIRDynamicLinkOtherPlatformParameters.fallbackUrl", - @"label" : @"OtherPlatform Fallback link (optional)", - @"defaultValue" : @"", - }, - ]; - }); - - _paramValues = [[NSMutableDictionary alloc] initWithCapacity:kParamsConfiguration.count]; - for (NSDictionary *paramConfig in kParamsConfiguration) { - if (paramConfig[@"defaultValue"]) { - _paramValues[paramConfig[@"id"]] = paramConfig[@"defaultValue"]; - } - } -} - -- (void)_buildFDLLink { - NSURL *link = [NSURL URLWithString:_paramValues[@"linkString"]]; - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link - domainURIPrefix:_paramValues[@"domainURIPrefix"]]; - - FIRDynamicLinkGoogleAnalyticsParameters *analyticsParams = - [FIRDynamicLinkGoogleAnalyticsParameters - parametersWithSource:_paramValues[@"FIRDynamicLinkGoogleAnalyticsParameters.source"] - medium:_paramValues[@"FIRDynamicLinkGoogleAnalyticsPara" - @"meters.medium"] - campaign:_paramValues[@"FIRDynamicLinkGoogleAnalyticsPara" - @"meters.campaign"]]; - analyticsParams.term = _paramValues[@"FIRDynamicLinkGoogleAnalyticsParameters.term"]; - analyticsParams.content = _paramValues[@"FIRDynamicLinkGoogleAnalyticsParameters.content"]; - - FIRDynamicLinkIOSParameters *iOSParams; - if (_paramValues[@"FIRDynamicLinkIOSParameters.bundleId"]) { - iOSParams = [FIRDynamicLinkIOSParameters - parametersWithBundleID:_paramValues[@"FIRDynamicLinkIOSParameters.bundleId"]]; - iOSParams.fallbackURL = - [NSURL URLWithString:_paramValues[@"FIRDynamicLinkIOSParameters.fallbackURL"]]; - iOSParams.customScheme = _paramValues[@"FIRDynamicLinkIOSParameters.customScheme"]; - iOSParams.iPadBundleID = _paramValues[@"FIRDynamicLinkIOSParameters.iPadBundleID"]; - iOSParams.iPadFallbackURL = - [NSURL URLWithString:_paramValues[@"FIRDynamicLinkIOSParameters.iPadFallbackURL"]]; - iOSParams.appStoreID = _paramValues[@"FIRDynamicLinkIOSParameters.appStoreId"]; - iOSParams.minimumAppVersion = _paramValues[@"FIRDynamicLinkIOSParameters.minimumAppVersion"]; - } - - FIRDynamicLinkItunesConnectAnalyticsParameters *appStoreParams = - [FIRDynamicLinkItunesConnectAnalyticsParameters parameters]; - appStoreParams.affiliateToken = - _paramValues[@"FIRDynamicLinkItunesConnectAnalyticsParameters.affiliateToken"]; - appStoreParams.campaignToken = - _paramValues[@"FIRDynamicLinkItunesConnectAnalyticsParameters.campaignToken"]; - appStoreParams.providerToken = - _paramValues[@"FIRDynamicLinkItunesConnectAnalyticsParameters.providerToken"]; - - FIRDynamicLinkAndroidParameters *androidParams; - if (_paramValues[@"FIRDynamicLinkAndroidParameters.packageName"]) { - androidParams = [FIRDynamicLinkAndroidParameters - parametersWithPackageName:_paramValues[@"FIRDynamicLinkAndroidParameters.packageName"]]; - androidParams.fallbackURL = - [NSURL URLWithString:_paramValues[@"FIRDynamicLinkAndroidParameters.fallbackURL"]]; - if ([_paramValues[@"FIRDynamicLinkAndroidParameters.minimumVersion"] integerValue] > 0) { - androidParams.minimumVersion = - [_paramValues[@"FIRDynamicLinkAndroidParameters.minimumVersion"] integerValue]; - } - } - - FIRDynamicLinkSocialMetaTagParameters *socialParams = - [FIRDynamicLinkSocialMetaTagParameters parameters]; - socialParams.title = _paramValues[@"FIRDynamicLinkSocialMetaTagParameters.title"]; - socialParams.descriptionText = - _paramValues[@"FIRDynamicLinkSocialMetaTagParameters.descriptionText"]; - socialParams.imageURL = - [NSURL URLWithString:_paramValues[@"FIRDynamicLinkSocialMetaTagParameters.imageURL"]]; - - FIRDynamicLinkOtherPlatformParameters *otherPlatformParams = - [FIRDynamicLinkOtherPlatformParameters parameters]; - otherPlatformParams.fallbackUrl = - [NSURL URLWithString:_paramValues[@"FIRDynamicLinkOtherPlatformParameters.fallbackUrl"]]; - - FIRDynamicLinkComponentsOptions *options = [FIRDynamicLinkComponentsOptions options]; - options.pathLength = FIRShortDynamicLinkPathLengthShort; - - components.analyticsParameters = analyticsParams; - components.iOSParameters = iOSParams; - components.iTunesConnectParameters = appStoreParams; - components.androidParameters = androidParams; - components.socialMetaTagParameters = socialParams; - components.otherPlatformParameters = otherPlatformParams; - components.options = options; - - NSURL *longURL = components.url; - // Handle longURL. - NSLog(@"Long URL: %@", longURL); - _longLink = longURL; - [self.tableView - reloadRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:kParamsConfiguration.count + 1 - inSection:0] ] - withRowAnimation:UITableViewRowAnimationNone]; - - [components shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray *_Nullable warnings, - NSError *_Nullable error) { - // Handle shortURL or error. - NSLog(@"Short URL: %@, warnings: %@ error: %@", shortURL, warnings, error); - if (error) { - [self _presentMessage:@"Error generating short link" description:[error description]]; - } - _shortLink = shortURL; - [self.tableView - reloadRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:kParamsConfiguration.count + 2 - inSection:0] ] - withRowAnimation:UITableViewRowAnimationNone]; - }]; -} - -- (void)_presentMessage:(NSString *)message description:(NSString *)description { - UIAlertController *alertVC = - [UIAlertController alertControllerWithTitle:message - message:description - preferredStyle:UIAlertControllerStyleAlert]; - [alertVC addAction:[UIAlertAction actionWithTitle:@"Dismiss" - style:UIAlertActionStyleCancel - handler:NULL]]; - [self presentViewController:alertVC animated:YES completion:NULL]; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/main.m b/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/main.m deleted file mode 100644 index 7dc9d63f8d6..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/FDLBuilderTestAppObjC/main.m +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#import "AppDelegate.h" - -int main(int argc, char* argv[]) { - NSString* appDelegateClassName; - @autoreleasepool { - // Setup code that might create autoreleased objects goes here. - appDelegateClassName = NSStringFromClass([AppDelegate class]); - } - return UIApplicationMain(argc, argv, nil, appDelegateClassName); -} diff --git a/FirebaseDynamicLinks/Tests/Sample/Podfile b/FirebaseDynamicLinks/Tests/Sample/Podfile deleted file mode 100644 index 5db03c20125..00000000000 --- a/FirebaseDynamicLinks/Tests/Sample/Podfile +++ /dev/null @@ -1,11 +0,0 @@ -source 'https://github.com/firebase/SpecsDev.git' -source 'https://github.com/firebase/SpecsStaging.git' -source 'https://cdn.cocoapods.org/' - -target 'FDLBuilderTestAppObjC' do - platform :ios, '13.0' - use_frameworks! - - pod 'FirebaseCore', :path => '../../../' - pod 'FirebaseDynamicLinks', :path => '../../../' -end diff --git a/FirebaseDynamicLinks/Tests/Unit/DL-Info.plist b/FirebaseDynamicLinks/Tests/Unit/DL-Info.plist deleted file mode 100644 index 034e43597cc..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/DL-Info.plist +++ /dev/null @@ -1,56 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleDisplayName - ${PRODUCT_NAME} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - org.cocoapods-generate.App-iOS - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - LSRequiresIPhoneOS - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - FirebaseDynamicLinksCustomDomains - - https://google.com - https://google.com/one/ - https://a.firebase.com/mypath - - - diff --git a/FirebaseDynamicLinks/Tests/Unit/FDLURLComponentsTests.m b/FirebaseDynamicLinks/Tests/Unit/FDLURLComponentsTests.m deleted file mode 100644 index e7d9dce6a79..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/FDLURLComponentsTests.m +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h" -#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h" - -#import - -static NSString *const kFDLURLDomain = @"https://xyz.page.link"; -static NSString *const kFDLURLCustomDomain = @"https://foo.com/path"; - -@interface FDLURLComponentsTests : XCTestCase -@end - -@implementation FDLURLComponentsTests - -#pragma mark - FIRDynamicLinkGoogleAnalyticsParameters - -- (void)testAnalyticsParamsFactoryReturnsInstanceOfCorrectClass { - id returnValue = [FIRDynamicLinkGoogleAnalyticsParameters parameters]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkGoogleAnalyticsParameters class]]); -} - -- (void)testAnalyticsParamsFactoryReturnsInstanceWithAllNilProperties { - FIRDynamicLinkGoogleAnalyticsParameters *params = - [FIRDynamicLinkGoogleAnalyticsParameters parameters]; - - XCTAssertNil(params.source); - XCTAssertNil(params.medium); - XCTAssertNil(params.campaign); - XCTAssertNil(params.term); - XCTAssertNil(params.content); -} - -- (void)testAnalyticsParamsPropertiesSetProperly { - FIRDynamicLinkGoogleAnalyticsParameters *params = - [FIRDynamicLinkGoogleAnalyticsParameters parameters]; - - params.source = @"s"; - params.medium = @"m"; - params.campaign = @"ca"; - params.term = @"t"; - params.content = @"co"; - - XCTAssertEqualObjects(params.source, @"s"); - XCTAssertEqualObjects(params.medium, @"m"); - XCTAssertEqualObjects(params.campaign, @"ca"); - XCTAssertEqualObjects(params.term, @"t"); - XCTAssertEqualObjects(params.content, @"co"); - - params.source = nil; - params.medium = nil; - params.campaign = nil; - params.term = nil; - params.content = nil; - - XCTAssertNil(params.source); - XCTAssertNil(params.medium); - XCTAssertNil(params.campaign); - XCTAssertNil(params.term); - XCTAssertNil(params.content); -} - -- (void)testAnalyticsParamsDictionaryRepresentationReturnsCorrectDictionaryFull { - FIRDynamicLinkGoogleAnalyticsParameters *params = - [FIRDynamicLinkGoogleAnalyticsParameters parameters]; - - params.source = @"s"; - params.medium = @"m"; - params.campaign = @"ca"; - params.term = @"t"; - params.content = @"co"; - - NSDictionary *expectedDictionary = @{ - @"utm_source" : @"s", - @"utm_medium" : @"m", - @"utm_campaign" : @"ca", - @"utm_term" : @"t", - @"utm_content" : @"co", - }; - - XCTAssertEqualObjects(expectedDictionary, params.dictionaryRepresentation); -} - -- (void)testAnalyticsParamsDictionaryRepresentationReturnsCorrectDictionaryEmpty { - FIRDynamicLinkGoogleAnalyticsParameters *params = - [FIRDynamicLinkGoogleAnalyticsParameters parameters]; - XCTAssertEqualObjects(@{}, params.dictionaryRepresentation); -} - -- (void)testAnalyticsParamsFactoryWithParamsReturnsInstanceOfCorrectClass { - id returnValue = [FIRDynamicLinkGoogleAnalyticsParameters parametersWithSource:@"s" - medium:@"m" - campaign:@"c"]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkGoogleAnalyticsParameters class]]); -} - -- (void)testAnalyticsParamsFactoryWithParamsReturnsInstanceWithCorrectInitialPropertyValues { - FIRDynamicLinkGoogleAnalyticsParameters *params = - [FIRDynamicLinkGoogleAnalyticsParameters parametersWithSource:@"s" medium:@"m" campaign:@"c"]; - - XCTAssertEqualObjects(params.source, @"s"); - XCTAssertEqualObjects(params.medium, @"m"); - XCTAssertEqualObjects(params.campaign, @"c"); - XCTAssertNil(params.term); - XCTAssertNil(params.content); -} - -#pragma mark - FIRDynamicLinkIOSParameters - -- (void)testIOSParamsFactoryReturnsInstanceOfCorrectClass { - id returnValue = [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.iphone.app"]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkIOSParameters class]]); -} - -- (void)testIOSParamsFactoryReturnsInstanceWithAllOptionalNilProperties { - FIRDynamicLinkIOSParameters *params = - [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.iphone.app"]; - - XCTAssertNil(params.fallbackURL); - XCTAssertNil(params.customScheme); - XCTAssertNil(params.minimumAppVersion); - XCTAssertNil(params.iPadBundleID); - XCTAssertNil(params.iPadFallbackURL); - XCTAssertNil(params.appStoreID); -} - -- (void)testIOSParamsPropertiesSetProperly { - FIRDynamicLinkIOSParameters *params = - [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.iphone.app"]; - - params.fallbackURL = [NSURL URLWithString:@"https://google.com/iphone"]; - params.customScheme = @"mycustomsheme"; - params.minimumAppVersion = @"1.2.3"; - params.iPadBundleID = @"com.ipad.app"; - params.iPadFallbackURL = [NSURL URLWithString:@"https://google.com/ipad"]; - params.appStoreID = @"666"; - - XCTAssertEqualObjects(params.bundleID, @"com.iphone.app"); - XCTAssertEqualObjects(params.fallbackURL, [NSURL URLWithString:@"https://google.com/iphone"]); - XCTAssertEqualObjects(params.customScheme, @"mycustomsheme"); - XCTAssertEqualObjects(params.minimumAppVersion, @"1.2.3"); - XCTAssertEqualObjects(params.iPadBundleID, @"com.ipad.app"); - XCTAssertEqualObjects(params.iPadFallbackURL, [NSURL URLWithString:@"https://google.com/ipad"]); - XCTAssertEqualObjects(params.appStoreID, @"666"); - - params.fallbackURL = nil; - params.customScheme = nil; - params.minimumAppVersion = nil; - params.iPadBundleID = nil; - params.iPadFallbackURL = nil; - params.appStoreID = nil; - - XCTAssertNil(params.fallbackURL); - XCTAssertNil(params.customScheme); - XCTAssertNil(params.minimumAppVersion); - XCTAssertNil(params.iPadBundleID); - XCTAssertNil(params.iPadFallbackURL); - XCTAssertNil(params.appStoreID); -} - -- (void)testIOSParamsDictionaryRepresentationReturnsCorrectDictionaryFull { - FIRDynamicLinkIOSParameters *params = - [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.iphone.app"]; - - params.fallbackURL = [NSURL URLWithString:@"https://google.com/iphone"]; - params.customScheme = @"mycustomscheme"; - params.minimumAppVersion = @"1.2.3"; - params.iPadBundleID = @"com.ipad.app"; - params.iPadFallbackURL = [NSURL URLWithString:@"https://google.com/ipad"]; - params.appStoreID = @"666"; - - NSDictionary *expectedDictionary = @{ - @"ibi" : @"com.iphone.app", - @"ifl" : [NSURL URLWithString:@"https://google.com/iphone"].absoluteString, - @"ius" : @"mycustomscheme", - @"imv" : @"1.2.3", - @"ipbi" : @"com.ipad.app", - @"ipfl" : [NSURL URLWithString:@"https://google.com/ipad"].absoluteString, - @"isi" : @"666" - }; - - XCTAssertEqualObjects(expectedDictionary, params.dictionaryRepresentation); -} - -- (void)testIOSParamsDictionaryRepresentationReturnsCorrectDictionaryOnlyReqParams { - FIRDynamicLinkIOSParameters *params = - [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.iphone.app"]; - XCTAssertEqualObjects(@{@"ibi" : @"com.iphone.app"}, params.dictionaryRepresentation); -} - -#pragma mark - FIRDynamicLinkItunesConnectAnalyticsParameters - -- (void)testIOSAppStoreParamsFactoryReturnsInstanceOfCorrectClass { - id returnValue = [FIRDynamicLinkItunesConnectAnalyticsParameters parameters]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkItunesConnectAnalyticsParameters class]]); -} - -- (void)testIOSAppStoreParamsFactoryReturnsInstanceWithAllNilProperties { - FIRDynamicLinkItunesConnectAnalyticsParameters *params = - [FIRDynamicLinkItunesConnectAnalyticsParameters parameters]; - - XCTAssertNil(params.affiliateToken); - XCTAssertNil(params.campaignToken); - XCTAssertNil(params.providerToken); -} - -- (void)testIOSAppStoreParamsPropertiesSetProperly { - FIRDynamicLinkItunesConnectAnalyticsParameters *params = - [FIRDynamicLinkItunesConnectAnalyticsParameters parameters]; - - params.affiliateToken = @"affiliate"; - params.campaignToken = @"campaign"; - params.providerToken = @"provider"; - - XCTAssertEqualObjects(params.affiliateToken, @"affiliate"); - XCTAssertEqualObjects(params.campaignToken, @"campaign"); - XCTAssertEqualObjects(params.providerToken, @"provider"); - - params.affiliateToken = nil; - params.campaignToken = nil; - params.providerToken = nil; - - XCTAssertNil(params.affiliateToken); - XCTAssertNil(params.campaignToken); - XCTAssertNil(params.providerToken); -} - -- (void)testIOSAppStoreDictionaryRepresentationReturnsCorrectDictionaryFull { - FIRDynamicLinkItunesConnectAnalyticsParameters *params = - [FIRDynamicLinkItunesConnectAnalyticsParameters parameters]; - - params.affiliateToken = @"affiliate"; - params.campaignToken = @"campaign"; - params.providerToken = @"provider"; - - NSDictionary *expectedDictionary = @{ - @"at" : @"affiliate", - @"ct" : @"campaign", - @"pt" : @"provider", - }; - - XCTAssertEqualObjects(expectedDictionary, params.dictionaryRepresentation); -} - -- (void)testIOSAppStoreDictionaryRepresentationReturnsCorrectDictionaryEmpty { - FIRDynamicLinkItunesConnectAnalyticsParameters *params = - [FIRDynamicLinkItunesConnectAnalyticsParameters parameters]; - XCTAssertEqualObjects(@{}, params.dictionaryRepresentation); -} - -#pragma mark - FIRDynamicLinkAndroidParameters - -- (void)testAndroidParamsFactoryReturnsInstanceOfCorrectClass { - id returnValue = - [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.google.android.gms"]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkAndroidParameters class]]); -} - -- (void)testAndroidParamsFactoryReturnsInstanceWithAllOptionalNilProperties { - FIRDynamicLinkAndroidParameters *params = - [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.google.android.gms"]; - - XCTAssertNil(params.fallbackURL); - XCTAssertEqual(params.minimumVersion, 0); -} - -- (void)testAndroidParamsPropertiesSetProperly { - FIRDynamicLinkAndroidParameters *params = - [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.google.android.gms"]; - - params.fallbackURL = [NSURL URLWithString:@"https://google.com/android"]; - params.minimumVersion = 14; - - XCTAssertEqualObjects(params.packageName, @"com.google.android.gms"); - XCTAssertEqualObjects(params.fallbackURL, [NSURL URLWithString:@"https://google.com/android"]); - XCTAssertEqual(params.minimumVersion, 14); - - params.fallbackURL = nil; - params.minimumVersion = 0; - - XCTAssertNil(params.fallbackURL); - XCTAssertEqual(params.minimumVersion, 0); -} - -- (void)testAndroidParamsDictionaryRepresentationReturnsCorrectDictionaryFull { - FIRDynamicLinkAndroidParameters *params = - [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.google.android.gms"]; - - params.fallbackURL = [NSURL URLWithString:@"https://google.com/android"]; - params.minimumVersion = 14; - - NSDictionary *expectedDictionary = @{ - @"apn" : @"com.google.android.gms", - @"afl" : [NSURL URLWithString:@"https://google.com/android"].absoluteString, - @"amv" : @"14", - }; - - XCTAssertEqualObjects(expectedDictionary, params.dictionaryRepresentation); -} - -- (void)testAndroidParamsDictionaryRepresentationReturnsCorrectDictionaryEmpty { - FIRDynamicLinkAndroidParameters *params = - [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.google.android.gms"]; - XCTAssertEqualObjects(@{@"apn" : @"com.google.android.gms"}, params.dictionaryRepresentation); -} - -#pragma mark - FIRDynamicLinkSocialMetaTagParameters - -- (void)testSocialParamsFactoryReturnsInstanceOfCorrectClass { - id returnValue = [FIRDynamicLinkSocialMetaTagParameters parameters]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkSocialMetaTagParameters class]]); -} - -- (void)testSocialParamsFactoryReturnsInstanceWithAllNilProperties { - FIRDynamicLinkSocialMetaTagParameters *params = - [FIRDynamicLinkSocialMetaTagParameters parameters]; - - XCTAssertNil(params.title); - XCTAssertNil(params.descriptionText); - XCTAssertNil(params.imageURL); -} - -- (void)testSocialParamsPropertiesSetProperly { - FIRDynamicLinkSocialMetaTagParameters *params = - [FIRDynamicLinkSocialMetaTagParameters parameters]; - - params.title = @"title"; - params.descriptionText = @"description"; - params.imageURL = [NSURL URLWithString:@"https://google.com/someimage"]; - - XCTAssertEqualObjects(params.title, @"title"); - XCTAssertEqualObjects(params.descriptionText, @"description"); - XCTAssertEqualObjects(params.imageURL, [NSURL URLWithString:@"https://google.com/someimage"]); - - params.title = nil; - params.descriptionText = nil; - params.imageURL = nil; - - XCTAssertNil(params.title); - XCTAssertNil(params.descriptionText); - XCTAssertNil(params.imageURL); -} - -- (void)testSocialParamsDictionaryRepresentationReturnsCorrectDictionaryFull { - FIRDynamicLinkSocialMetaTagParameters *params = - [FIRDynamicLinkSocialMetaTagParameters parameters]; - - params.title = @"title"; - params.descriptionText = @"description"; - params.imageURL = [NSURL URLWithString:@"https://google.com/someimage"]; - - NSDictionary *expectedDictionary = @{ - @"st" : @"title", - @"sd" : @"description", - @"si" : [NSURL URLWithString:@"https://google.com/someimage"].absoluteString, - }; - - XCTAssertEqualObjects(expectedDictionary, params.dictionaryRepresentation); -} - -- (void)testSocialParamsDictionaryRepresentationReturnsCorrectDictionaryEmpty { - FIRDynamicLinkSocialMetaTagParameters *params = - [FIRDynamicLinkSocialMetaTagParameters parameters]; - XCTAssertEqualObjects(@{}, params.dictionaryRepresentation); -} - -#pragma mark - FIRDynamicLinkNavigationInfoParameters - -- (void)testNavigationOptionsReturnsCorrectClass { - id returnValue = [FIRDynamicLinkNavigationInfoParameters parameters]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkNavigationInfoParameters class]]); -} - -- (void)testNavigationOptionsFactoryReturnsInstanceWithAllNilProperties { - FIRDynamicLinkNavigationInfoParameters *options = - [FIRDynamicLinkNavigationInfoParameters parameters]; - - XCTAssertEqual(options.forcedRedirectEnabled, NO); -} - -- (void)testNavigationOptionsParamsPropertiesSetProperly { - FIRDynamicLinkNavigationInfoParameters *options = - [FIRDynamicLinkNavigationInfoParameters parameters]; - - options.forcedRedirectEnabled = YES; - - XCTAssertEqual(options.forcedRedirectEnabled, YES); - - options.forcedRedirectEnabled = NO; - - XCTAssertEqual(options.forcedRedirectEnabled, NO); -} - -#pragma mark - FIRDynamicLinkOtherPlatformParameters - -- (void)testOtherPlatformParametersReturnsCorrectClass { - id returnValue = [FIRDynamicLinkOtherPlatformParameters parameters]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkOtherPlatformParameters class]]); -} - -- (void)testOtherPlatformParametersFactoryReturnsInstanceWithAllNilProperties { - FIRDynamicLinkOtherPlatformParameters *options = - [FIRDynamicLinkOtherPlatformParameters parameters]; - - XCTAssertNil(options.fallbackUrl); -} - -- (void)testOtherPlatformParametersParamsPropertiesSetProperly { - FIRDynamicLinkOtherPlatformParameters *options = - [FIRDynamicLinkOtherPlatformParameters parameters]; - - options.fallbackUrl = [NSURL URLWithString:@"https://google.com"]; - - XCTAssertEqualObjects(options.fallbackUrl, [NSURL URLWithString:@"https://google.com"]); - - options.fallbackUrl = nil; - - XCTAssertNil(options.fallbackUrl); -} - -#pragma mark - FIRDynamicLinkComponentsOptions - -- (void)testLinkOptionsFactoryReturnsInstanceOfCorrectClass { - id returnValue = [FIRDynamicLinkComponentsOptions options]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkComponentsOptions class]]); -} - -- (void)testLinkOptionsParamsFactoryReturnsInstanceWithAllNilProperties { - FIRDynamicLinkComponentsOptions *options = [FIRDynamicLinkComponentsOptions options]; - - XCTAssertEqual(options.pathLength, FIRShortDynamicLinkPathLengthDefault); -} - -- (void)testLinkOptionsParamsPropertiesSetProperly { - FIRDynamicLinkComponentsOptions *options = [FIRDynamicLinkComponentsOptions options]; - - options.pathLength = FIRShortDynamicLinkPathLengthUnguessable; - - XCTAssertEqual(options.pathLength, FIRShortDynamicLinkPathLengthUnguessable); - - options.pathLength = FIRShortDynamicLinkPathLengthShort; - - XCTAssertEqual(options.pathLength, FIRShortDynamicLinkPathLengthShort); -} - -#pragma mark - FIRDynamicLinkComponents - -- (void)testFDLComponentsFactoryReturnsInstanceOfCorrectClass { - NSURL *link = [NSURL URLWithString:@"https://google.com"]; - id returnValue = [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain]; - XCTAssertTrue([returnValue isKindOfClass:[FIRDynamicLinkComponents class]]); -} - -- (void)testFDLComponentsFactoryReturnsInstanceWithAllNilProperties { - NSURL *link = [NSURL URLWithString:@"https://google.com"]; - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain]; - - XCTAssertNil(components.analyticsParameters); - XCTAssertNil(components.socialMetaTagParameters); - XCTAssertNil(components.iOSParameters); - XCTAssertNil(components.iTunesConnectParameters); - XCTAssertNil(components.analyticsParameters); - XCTAssertNil(components.options); -} - -- (void)testFDLComponentsCreatesSimplestLinkCorrectly { - NSString *linkString = @"https://google.com"; - NSString *encodedLinkString = @"https%3A%2F%2Fgoogle%2Ecom"; - NSURL *link = [NSURL URLWithString:linkString]; - - NSString *expectedURLString = - [NSString stringWithFormat:@"%@/?link=%@", kFDLURLDomain, encodedLinkString]; - NSURL *expectedURL = [NSURL URLWithString:expectedURLString]; - - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain]; - NSURL *actualURL = components.url; - - XCTAssertEqualObjects(actualURL, expectedURL); -} - -- (void)testFDLComponentsCustomDomainWithPath { - NSString *linkString = @"https://google.com"; - NSString *encodedLinkString = @"https%3A%2F%2Fgoogle%2Ecom"; - NSURL *link = [NSURL URLWithString:linkString]; - - NSString *expectedURLString = - [NSString stringWithFormat:@"%@/?link=%@", kFDLURLCustomDomain, encodedLinkString]; - NSURL *expectedURL = [NSURL URLWithString:expectedURLString]; - - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLCustomDomain]; - NSURL *actualURL = components.url; - - XCTAssertEqualObjects(actualURL, expectedURL); -} - -- (void)testFDLComponentsFailsOnMalformedDomainURIPrefix { - NSString *linkString = @"https://google.com"; - NSURL *link = [NSURL URLWithString:linkString]; - - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link - domainURIPrefix:@"this is invalid domain URI Prefix"]; - - XCTAssertNil(components.url); -} - -- (void)testFDLComponentsNotNilOnDomainWithHTTPScheme { - NSString *linkString = @"https://google.com"; - NSURL *link = [NSURL URLWithString:linkString]; - - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:@"https://xyz.page.link"]; - - XCTAssertNotNil(components); -} - -- (void)testFDLComponentsNotNilOnDomainWithHTTPSScheme { - NSString *linkString = @"https://google.com"; - NSURL *link = [NSURL URLWithString:linkString]; - - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:@"https://xyz.page.link"]; - - XCTAssertNotNil(components); -} - -- (void)testFDLComponentsFailsOnMalformedDomain { - NSString *linkString = @"https://google.com"; - NSURL *link = [NSURL URLWithString:linkString]; - - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link - domainURIPrefix:@"this is invalid domain URI Prefix"]; - - XCTAssertNil(components); -} - -- (void)testFDLComponentsCreatesFullLinkCorrectly { - FIRDynamicLinkGoogleAnalyticsParameters *analyticsParams = - [FIRDynamicLinkGoogleAnalyticsParameters parameters]; - analyticsParams.source = @"s"; - analyticsParams.medium = @"m"; - analyticsParams.campaign = @"ca"; - analyticsParams.term = @"t"; - analyticsParams.content = @"co"; - - FIRDynamicLinkIOSParameters *iosParams = - [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.iphone.app"]; - iosParams.fallbackURL = [NSURL URLWithString:@"https://google.com/iphone"]; - iosParams.customScheme = @"mycustomsheme"; - iosParams.minimumAppVersion = @"1.2.3"; - iosParams.iPadBundleID = @"com.ipad.app"; - iosParams.iPadFallbackURL = [NSURL URLWithString:@"https://google.com/ipad"]; - iosParams.appStoreID = @"666"; - - FIRDynamicLinkItunesConnectAnalyticsParameters *itcParams = - [FIRDynamicLinkItunesConnectAnalyticsParameters parameters]; - itcParams.affiliateToken = @"affiliate"; - itcParams.campaignToken = @"campaign"; - itcParams.providerToken = @"provider"; - - FIRDynamicLinkAndroidParameters *androidParams = - [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.google.android.gms"]; - androidParams.fallbackURL = [NSURL URLWithString:@"https://google.com/android"]; - androidParams.minimumVersion = 14; - - FIRDynamicLinkSocialMetaTagParameters *socialParams = - [FIRDynamicLinkSocialMetaTagParameters parameters]; - socialParams.title = @"title"; - socialParams.descriptionText = @"description"; - socialParams.imageURL = [NSURL URLWithString:@"https://google.com/someimage"]; - - FIRDynamicLinkOtherPlatformParameters *otherPlatformParams = - [FIRDynamicLinkOtherPlatformParameters parameters]; - otherPlatformParams.fallbackUrl = - [NSURL URLWithString:@"https://google.com/fallbackForOtherPlatform"]; - - FIRDynamicLinkNavigationInfoParameters *navInfo = - [FIRDynamicLinkNavigationInfoParameters parameters]; - navInfo.forcedRedirectEnabled = YES; - - FIRDynamicLinkComponentsOptions *options = [FIRDynamicLinkComponentsOptions options]; - options.pathLength = FIRShortDynamicLinkPathLengthUnguessable; - - NSURL *link = [NSURL URLWithString:@"https://google.com"]; - FIRDynamicLinkComponents *fdlComponents = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain]; - fdlComponents.analyticsParameters = analyticsParams; - fdlComponents.iOSParameters = iosParams; - fdlComponents.iTunesConnectParameters = itcParams; - fdlComponents.androidParameters = androidParams; - fdlComponents.socialMetaTagParameters = socialParams; - fdlComponents.navigationInfoParameters = navInfo; - fdlComponents.otherPlatformParameters = otherPlatformParams; - fdlComponents.options = options; - - // This is a long FDL URL that has been verified to be a correct representation of the expected - // URL. Since the parameters are not guaranteed to be in any specific order, we must compare - // arrays of properties of the URLs rather than the URLs themselves. - NSString *possibleExpectedURLString = - @"https://xyz.page.link/?afl=https%3A%2F%2Fgoogle%2Ecom%2F" - "android&amv=14&apn=com.google.android.gms&ibi=com%2Eiphone%2Eapp&utm_term=t&link=https%3A%" - "2F" - "%2Fgoogle%2Ecom&ipbi=com%2Eipad%2Eapp&ius=mycustomsheme&ifl=https%3A%2F%2Fgoogle%2Ecom%2" - "Fiphone&isi=666&utm_content=co&utm_source=s&utm_medium=m&imv=1%2E2%2E3&ct=campaign&ipfl=" - "http" - "s%3A%2F%2Fgoogle%2Ecom%2Fipad&si=https%3A%2F%2Fgoogle%2Ecom%2Fsomeimage&at=affiliate&pt=" - "prov" - "ider&st=title&utm_campaign=ca&sd=description&efr=1&ofl=https%3A%2F%2Fgoogle%2Ecom%" - "2Ffallback" - "ForOtherPlatform"; - NSURL *possibleExpectedURL = [NSURL URLWithString:possibleExpectedURLString]; - NSURLComponents *expectedURLComponents = - [NSURLComponents componentsWithString:possibleExpectedURLString]; - // sort both expected/actual arrays to prevent order influencing the test results - NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; - NSArray *expectedURLQueryItems = - [expectedURLComponents.queryItems sortedArrayUsingDescriptors:@[ sort ]]; - - NSURL *actualURL = fdlComponents.url; - NSURLComponents *actualURLComponents = - [NSURLComponents componentsWithString:actualURL.absoluteString]; - NSArray *actualQueryItems = - [actualURLComponents.queryItems sortedArrayUsingDescriptors:@[ sort ]]; - - XCTAssertEqualObjects(actualQueryItems, expectedURLQueryItems); - XCTAssertEqualObjects(actualURL.host, possibleExpectedURL.host); -} - -- (void)testFDLComponentsCorrectlySetsPathLengthInRequest { - NSURL *url = [NSURL URLWithString:@"https://google.com/abc"]; - NSURLRequest *request; - NSDictionary *JSON; - - FIRDynamicLinkComponentsOptions *options = [FIRDynamicLinkComponentsOptions options]; - - // Default path-length - request = [FIRDynamicLinkComponents shorteningRequestForLongURL:url options:options]; - JSON = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil]; - XCTAssertNil(JSON[@"suffix"]); - - // Unguessable - options.pathLength = FIRShortDynamicLinkPathLengthUnguessable; - request = [FIRDynamicLinkComponents shorteningRequestForLongURL:url options:options]; - JSON = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil]; - XCTAssertTrue([JSON[@"suffix"][@"option"] isEqualToString:@"UNGUESSABLE"]); - - // Short - options.pathLength = FIRShortDynamicLinkPathLengthShort; - request = [FIRDynamicLinkComponents shorteningRequestForLongURL:url options:options]; - JSON = [NSJSONSerialization JSONObjectWithData:request.HTTPBody options:0 error:nil]; - XCTAssertTrue([JSON[@"suffix"][@"option"] isEqualToString:@"SHORT"]); -} - -- (void)testShortenURL { - NSString *shortURLString = @"https://xyz.page.link/abcd"; - - // Mock key provider - id keyProviderClassMock = OCMClassMock([FIRDynamicLinkComponentsKeyProvider class]); - [[[keyProviderClassMock expect] andReturn:@"fake-api-key"] APIKey]; - - id componentsClassMock = OCMClassMock([FIRDynamicLinkComponents class]); - [[componentsClassMock expect] - sendHTTPRequest:OCMOCK_ANY - completion:[OCMArg checkWithBlock:^BOOL(id obj) { - void (^completion)(NSData *_Nullable, NSError *_Nullable) = obj; - NSDictionary *JSON = @{@"shortLink" : shortURLString}; - NSData *JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:0]; - completion(JSONData, nil); - return YES; - }]]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - NSURL *link = [NSURL URLWithString:@"https://google.com/abc"]; - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain]; - [components - shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray *_Nullable warnings, - NSError *_Nullable error) { - XCTAssertEqualObjects(shortURL.absoluteString, shortURLString); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:0.1 handler:nil]; - - [keyProviderClassMock verify]; - [keyProviderClassMock stopMocking]; - [componentsClassMock verify]; - [componentsClassMock stopMocking]; -} - -- (void)testShortenURLReturnsErrorWhenAPIKeyMissing { - NSString *shortURLString = @"https://xyz.page.link/abcd"; - - // Mock key provider - id keyProviderClassMock = OCMClassMock([FIRDynamicLinkComponentsKeyProvider class]); - [[[keyProviderClassMock expect] andReturn:nil] APIKey]; - - id componentsClassMock = OCMClassMock([FIRDynamicLinkComponents class]); - [[componentsClassMock stub] - sendHTTPRequest:OCMOCK_ANY - completion:[OCMArg checkWithBlock:^BOOL(id obj) { - void (^completion)(NSData *_Nullable, NSError *_Nullable) = obj; - NSDictionary *JSON = @{@"shortLink" : shortURLString}; - NSData *JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:0]; - completion(JSONData, nil); - return YES; - }]]; - - XCTestExpectation *expectation = - [self expectationWithDescription:@"completion called with error"]; - NSURL *link = [NSURL URLWithString:@"https://google.com/abc"]; - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link domainURIPrefix:kFDLURLDomain]; - [components - shortenWithCompletion:^(NSURL *_Nullable shortURL, NSArray *_Nullable warnings, - NSError *_Nullable error) { - XCTAssertNil(shortURL); - if (error) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:0.1 handler:nil]; - - [keyProviderClassMock verify]; - [keyProviderClassMock stopMocking]; - [componentsClassMock verify]; - [componentsClassMock stopMocking]; -} - -- (void)testShortenURLReturnsErrorWhenDomainIsMalformed { - NSString *shortURLString = @"https://xyz.page.link/abcd"; - - // Mock key provider - id keyProviderClassMock = OCMClassMock([FIRDynamicLinkComponentsKeyProvider class]); - [[keyProviderClassMock reject] APIKey]; - - id componentsClassMock = OCMClassMock([FIRDynamicLinkComponents class]); - [[componentsClassMock reject] - sendHTTPRequest:OCMOCK_ANY - completion:[OCMArg checkWithBlock:^BOOL(id obj) { - void (^completion)(NSData *_Nullable, NSError *_Nullable) = obj; - NSDictionary *JSON = @{@"shortLink" : shortURLString}; - NSData *JSONData = [NSJSONSerialization dataWithJSONObject:JSON options:0 error:0]; - completion(JSONData, nil); - return YES; - }]]; - - NSURL *link = [NSURL URLWithString:@"https://google.com/abc"]; - FIRDynamicLinkComponents *components = - [FIRDynamicLinkComponents componentsWithLink:link - domainURIPrefix:@"this is invalid domain URI Prefix"]; - XCTAssertNil(components); - - [keyProviderClassMock verify]; - [keyProviderClassMock stopMocking]; - [componentsClassMock verify]; - [componentsClassMock stopMocking]; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Unit/FIRDLScionLoggingTest.m b/FirebaseDynamicLinks/Tests/Unit/FIRDLScionLoggingTest.m deleted file mode 100644 index c313b96ea90..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/FIRDLScionLoggingTest.m +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import -#import "FirebaseDynamicLinks/Sources/FIRDLScionLogging.h" - -static const NSTimeInterval kAsyncTestTimeout = 0.5; - -typedef void (^FakeAnalyticsLogEventWithOriginNameParametersHandler)(NSString *origin, - NSString *name, - NSDictionary *parameters); - -@interface FakeAnalytics : NSObject - -- (instancetype)initWithHandler:(FakeAnalyticsLogEventWithOriginNameParametersHandler)handler; - -@end - -@implementation FakeAnalytics - -static FakeAnalyticsLogEventWithOriginNameParametersHandler _handler; - -- (instancetype)initWithHandler:(FakeAnalyticsLogEventWithOriginNameParametersHandler)handler { - self = [super init]; - if (self) { - _handler = handler; - } - return self; -} - -- (void)logEventWithOrigin:(nonnull NSString *)origin - name:(nonnull NSString *)name - parameters:(nullable NSDictionary *)parameters { - if (_handler) { - _handler(origin, name, parameters); - } -} - -// Stubs -- (void)clearConditionalUserProperty:(nonnull NSString *)userPropertyName - clearEventName:(nonnull NSString *)clearEventName - clearEventParameters:(nonnull NSDictionary *)clearEventParameters { -} - -- (NSInteger)maxUserProperties:(nonnull NSString *)origin { - return -1; -} - -- (void)setUserPropertyWithOrigin:(nonnull NSString *)origin - name:(nonnull NSString *)name - value:(nonnull id)value { -} - -- (void)checkLastNotificationForOrigin:(nonnull NSString *)origin - queue:(nonnull dispatch_queue_t)queue - callback:(nonnull void (^)(NSString *_Nullable)) - currentLastNotificationProperty { -} - -- (void)registerAnalyticsListener:(nonnull id)listener - withOrigin:(nonnull NSString *)origin { -} - -- (void)unregisterAnalyticsListenerWithOrigin:(nonnull NSString *)origin { -} - -- (void)clearConditionalUserProperty:(nonnull NSString *)userPropertyName - forOrigin:(nonnull NSString *)origin - clearEventName:(nonnull NSString *)clearEventName - clearEventParameters: - (nonnull NSDictionary *)clearEventParameters { -} - -- (nonnull NSArray *> *) - conditionalUserProperties:(nonnull NSString *)origin - propertyNamePrefix:(nonnull NSString *)propertyNamePrefix { - return nil; -} - -- (void)setConditionalUserProperty:(nonnull NSDictionary *)conditionalUserProperty { -} - -- (void)getUserPropertiesWithCallback:(nonnull FIRAInteropUserPropertiesCallback)callback { -} -@end - -@interface FIRDLScionLoggingTest : XCTestCase -@end - -@implementation FIRDLScionLoggingTest - -- (void)testGINLogEventToScionCallsLogMethodWithFirstOpen { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - - FakeAnalytics *analytics = [[FakeAnalytics alloc] - initWithHandler:^(NSString *origin, NSString *name, NSDictionary *parameters) { - [expectation fulfill]; - }]; - - FIRDLLogEventToScion(FIRDLLogEventFirstOpen, nil, nil, nil, analytics); - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testGINLogEventToScionContainsCorrectNameWithFirstOpen { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - - FakeAnalytics *analytics = [[FakeAnalytics alloc] - initWithHandler:^(NSString *origin, NSString *name, NSDictionary *parameters) { - XCTAssertEqualObjects(name, @"dynamic_link_first_open", @"scion name param was incorrect"); - [expectation fulfill]; - }]; - - FIRDLLogEventToScion(FIRDLLogEventFirstOpen, nil, nil, nil, analytics); - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testGINLogEventToScionCallsLogMethodWithAppOpen { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - - FakeAnalytics *analytics = [[FakeAnalytics alloc] - initWithHandler:^(NSString *origin, NSString *name, NSDictionary *parameters) { - [expectation fulfill]; - }]; - FIRDLLogEventToScion(FIRDLLogEventAppOpen, nil, nil, nil, analytics); - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testGINLogEventToScionContainsCorrectNameWithAppOpen { - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - - FakeAnalytics *analytics = [[FakeAnalytics alloc] - initWithHandler:^(NSString *origin, NSString *name, NSDictionary *parameters) { - XCTAssertEqualObjects(name, @"dynamic_link_app_open", @"scion name param was incorrect"); - [expectation fulfill]; - }]; - FIRDLLogEventToScion(FIRDLLogEventAppOpen, nil, nil, nil, analytics); - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testGINLogEventToScionLogsParametersCorrectly { - NSString *source = @"9-2nkg"; - NSString *medium = @"fjg0"; - NSString *campaign = @"gjoo3u5"; - - NSString *sourceKey = @"source"; - NSString *mediumKey = @"medium"; - NSString *campaignKey = @"campaign"; - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion"]; - - FakeAnalytics *analytics = [[FakeAnalytics alloc] - initWithHandler:^(NSString *origin, NSString *name, NSDictionary *params) { - XCTAssertEqualObjects(params[sourceKey], source, @"scion logger has incorrect source."); - XCTAssertEqualObjects(params[mediumKey], medium, @"scion logger has incorrect medium."); - XCTAssertEqualObjects(params[campaignKey], campaign, - @"scion logger has incorrect campaign."); - [expectation fulfill]; - }]; - - FIRDLLogEventToScion(FIRDLLogEventAppOpen, source, medium, campaign, analytics); - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkNetworkingTests.m b/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkNetworkingTests.m deleted file mode 100644 index b93e8e92332..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkNetworkingTests.m +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import - -#import - -#import -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking+Private.h" - -static NSString *const kAPIKey = @"myfakeapikey"; -const NSInteger kJSONParsingErrorCode = 3840; -static NSString *const kURLScheme = @"gindeeplinkurl"; -static const NSTimeInterval kAsyncTestTimeout = 5.0; - -@interface FIRDynamicLinkNetworkingTests : XCTestCase - -@property(strong, nonatomic) FIRDynamicLinkNetworking *service; - -@end - -@implementation FIRDynamicLinkNetworkingTests - -- (void)tearDown { - self.service = nil; -} - -- (FIRDynamicLinkNetworking *)service { - if (!_service) { - _service = [[FIRDynamicLinkNetworking alloc] initWithAPIKey:kAPIKey URLScheme:kURLScheme]; - } - return _service; -} - -- (void)testFIRDynamicLinkAPIKeyParameterReturnsCorrectlyFormattedParameterString { - NSString *expectedValue = [NSString stringWithFormat:@"?key=%@", kAPIKey]; - - NSString *parameter = FIRDynamicLinkAPIKeyParameter(kAPIKey); - - XCTAssertEqualObjects(parameter, expectedValue, - @"FIRDynamicLinkAPIKeyParameter() returned incorrect parameter string"); -} - -- (void)testFIRDynamicLinkAPIKeyParameterReturnsNilParameterStringWhenAPIKeyIsNil { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnonnull" - NSString *parameter = FIRDynamicLinkAPIKeyParameter(nil); -#pragma clang diagnostic pop - - XCTAssertNil(parameter, - @"FIRDynamicLinkAPIKeyParameter() returned non-nil result when API key was nil"); -} - -- (void)testResolveShortLinkServiceCompletionDoesntCrashWhenNilDataIsRetrieved { - NSURL *url = [NSURL URLWithString:@"https://google.com"]; - - void (^executeRequestBlock)(id, NSDictionary *, NSString *, FIRNetworkRequestCompletionHandler) = - ^(id p1, NSDictionary *requestBody, NSString *requestURLString, - FIRNetworkRequestCompletionHandler handler) { - handler(nil, nil, nil); - }; - - SEL executeRequestSelector = @selector(executeOnePlatformRequest:forURL:completionHandler:); - - [GULSwizzler swizzleClass:[FIRDynamicLinkNetworking class] - selector:executeRequestSelector - isClassSelector:NO - withBlock:executeRequestBlock]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - - [self.service resolveShortLink:url - FDLSDKVersion:@"1.0.0" - completion:^(NSURL *_Nullable url, NSError *_Nullable error) { - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - [GULSwizzler unswizzleClass:[FIRDynamicLinkNetworking class] - selector:executeRequestSelector - isClassSelector:NO]; -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkTest.m b/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkTest.m deleted file mode 100644 index b2dfb50381a..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinkTest.m +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import -#import -#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h" - -@interface FIRDynamicLinkTest : XCTestCase { -} -@end - -@implementation FIRDynamicLinkTest - -NSMutableDictionary *fdlParameters = nil; -NSDictionary *linkParameters = nil; -NSDictionary *utmParameters = nil; - -- (void)setUp { - [super setUp]; - - linkParameters = @{ - @"deep_link_id" : @"https://mmaksym.com/test-app1", - @"match_message" : @"Link is uniquely matched for this device.", - @"match_type" : @"unique", - @"a_parameter" : @"a_value" - }; - utmParameters = @{ - @"utm_campaign" : @"eldhosembabu Test", - @"utm_medium" : @"test_medium", - @"utm_source" : @"test_source", - }; - - fdlParameters = [[NSMutableDictionary alloc] initWithDictionary:linkParameters]; - [fdlParameters addEntriesFromDictionary:utmParameters]; -} - -- (void)testDynamicLinkParameters_InitWithParameters { - FIRDynamicLink *dynamicLink = [[FIRDynamicLink alloc] initWithParametersDictionary:fdlParameters]; - XCTAssertEqual([fdlParameters count], [[dynamicLink parametersDictionary] count]); - for (NSString *key in fdlParameters) { - NSString *expectedValue = [fdlParameters valueForKey:key]; - NSString *derivedValue = [[dynamicLink parametersDictionary] valueForKey:key]; - XCTAssertNotNil(derivedValue, @"Cannot be null!"); - XCTAssertEqualObjects(derivedValue, expectedValue); - } -} - -- (void)testDynamicLinkUtmParameters_InitWithParameters { - FIRDynamicLink *dynamicLink = [[FIRDynamicLink alloc] initWithParametersDictionary:fdlParameters]; - XCTAssertEqual([[dynamicLink utmParametersDictionary] count], [utmParameters count]); - for (NSString *key in utmParameters) { - NSString *expectedValue = [utmParameters valueForKey:key]; - NSString *derivedValue = [[dynamicLink utmParametersDictionary] valueForKey:key]; - XCTAssertNotNil(derivedValue, @"Cannot be null!"); - XCTAssertEqualObjects(derivedValue, expectedValue); - } -} - -- (void)testDynamicLinkParameters_InitWithNoUtmParameters { - FIRDynamicLink *dynamicLink = - [[FIRDynamicLink alloc] initWithParametersDictionary:linkParameters]; - XCTAssertEqual([[dynamicLink parametersDictionary] count], [linkParameters count]); - XCTAssertEqual([[dynamicLink utmParametersDictionary] count], 0); -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksImportsTest3P.m b/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksImportsTest3P.m deleted file mode 100644 index 8e91ff87d82..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksImportsTest3P.m +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h" - -@interface FIRDynamicLinksImportsTest3P : XCTestCase - -@end - -@implementation FIRDynamicLinksImportsTest3P - -- (void)testPlaceholder { - // This is empty test case. - // The test file designed to test successful build if source file, that includes - // FIRDynamicLinks.h, does not includes any other headers, like UIKit. -} - -@end diff --git a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksTest.m b/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksTest.m deleted file mode 100644 index d53ee7d6660..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksTest.m +++ /dev/null @@ -1,1787 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import - -#import -#import -#import "FirebaseCore/Extension/FirebaseCoreInternal.h" -#import "FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h" -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessFactory.h" -#import "FirebaseDynamicLinks/Sources/FIRDLRetrievalProcessResult+Private.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinkNetworking+Private.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinks+FirstParty.h" -#import "FirebaseDynamicLinks/Sources/FIRDynamicLinks+Private.h" -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" -#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" - -static NSString *const kAPIKey = @"myAPIKey"; -static NSString *const kStructuredLinkFmtFreeform = @"%@://google/link/%@"; -static NSString *const kStructuredLinkFmtDeepLink = @"%@://google/link/?deep_link_id=%@"; -static NSString *const kStructuredLinkFmtInvitation = @"%@://google/link/?invitation_id=%@"; -static NSString *const kStructuredLinkFmtInvitationWeak = - @"%@://google/link/?invitation_id=%@&match_type=weak"; -static NSString *const kStructuredLinkFmtDeepLinkAndInvitation = - @"%@://google/link/?deep_link_id=%@&invitation_id=%@"; -static NSString *const kStructuredUniversalLinkFmtFreeForm = @"https://goo.gl/app/sample%@"; -static NSString *const kStructuredUniversalLinkFmtDeepLink = - @"https://goo.gl/app/sample?link=%@&isi=585027354"; -static NSString *const kStructuredUniversalLinkFmtSubdomain = @"https://sample.page.link%@"; -static NSString *const kStructuredUniversalLinkFmtSubdomainDeepLink = - @"https://sample.page.link?link=%@&isi=585027354"; -static NSString *const kURLScheme = @"gindeeplinkurl"; - -static const NSTimeInterval kAsyncTestTimeout = 5.0; - -/** - * This string was generated by percent-encoding the Tactile URL for the Tokyo American Club in - * Tokyo, and then replacing a '%2B' with a '+' to verify that the '+' does not cause our parsing to - * fail and double-encoding one value to verify that only one decoding pass is run. - */ -NSString *kEncodedComplicatedURLString = - @"https%3A%2F%2Fwww.google.com%252Fmaps%2Fplace%2FTokyo+Am" - @"erican%2BClub%2F%4035.658578%2C139.741588%2C3a%2C75y%2C90t%2Fdata%3D%213m8%211e2%213m6%211s42" - @"66698%212e1%213e10%216s%252F%252Fstorage.googleapis.com%252Fstatic.panoramio.com%252Fphotos%2" - @"52Fmedium%252F4266698.jpg%217i640%218i480%214m2%213m1%211s0x0000000000000000%3A0x1b8b8130c791" - @"48e1%216m1%211e1"; -/** This string was generated by percent-decoding kEncodedComplicatedURLString. */ -NSString *kDecodedComplicatedURLString = - @"https://www.google.com%2Fmaps/place/Tokyo+American+Club/" - @"@35.658578,139.741588,3a,75y,90t/data=!3m8!1e2!3m6!1s4266698!2e1!3e10!6s%2F%2Fstorage.googlea" - @"pis.com%2Fstatic.panoramio.com%2Fphotos%2Fmedium%2F4266698.jpg!7i640!8i480!4m2!3m1!1s0x000000" - @"0000000000:0x1b8b8130c79148e1!6m1!1e1"; - -static void *kOpenURLHandlerKey = &kOpenURLHandlerKey; - -typedef NSURL * (^FakeShortLinkResolverHandler)(NSURL *shortLink); - -@interface FIRDynamicLinks (FIRApp) -- (void)configureDynamicLinks:(FIRApp *)app; -- (BOOL)setUpWithLaunchOptions:(nullable NSDictionary *)launchOptions - apiKey:(NSString *)apiKey - urlScheme:(nullable NSString *)urlScheme - userDefaults:(nullable NSUserDefaults *)userDefaults; -- (BOOL)canParseUniversalLinkURL:(nullable NSURL *)url; -- (void)passRetrievedDynamicLinkToApplication:(NSURL *)url; -- (BOOL)isOpenUrlMethodPresentInAppDelegate:(id)applicationDelegate; -@end - -@interface FakeShortLinkResolver : FIRDynamicLinkNetworking -+ (instancetype)resolverWithBlock:(FakeShortLinkResolverHandler)resolverHandler; -@end - -@implementation FakeShortLinkResolver { - FakeShortLinkResolverHandler _resolverHandler; -} - -+ (instancetype)resolverWithBlock:(FakeShortLinkResolverHandler)resolverHandler { - // The parameters don't matter since they aren't validated or used here. - FakeShortLinkResolver *resolver = [[self alloc] initWithAPIKey:@"" URLScheme:@""]; - resolver->_resolverHandler = [resolverHandler copy]; - return resolver; -} - -- (void)resolveShortLink:(NSURL *)url - FDLSDKVersion:(NSString *)FDLSDKVersion - completion:(FIRDynamicLinkResolverHandler)completion { - if (_resolverHandler && completion) { - NSURL *resolvedLink = _resolverHandler(url); - completion(resolvedLink, nil); - } -} - -@end - -// dummy protocol to prevent compile warning -@protocol DummyProtocol - -@property(atomic, assign) BOOL retrievingPendingDynamicLink; - -@property(nonatomic, readonly) FIRDynamicLinkNetworking *dynamicLinkNetworking; - -- (void)handlePendingDynamicLinkRetrievalFailureWithErrorCode:(NSInteger)errorCode - errorDescription:(NSString *)errorDescription - underlyingError:(nullable NSError *)underlyingError; - -@end - -// Swizzle DynamicLinks.dynamicLinkNetworking property to return fake resolver. -static void SwizzleDynamicLinkNetworking(id linkResolver) { - id (^dynamicLinkNetworkingBlock)(void) = ^id(void) { - return linkResolver; - }; - [GULSwizzler swizzleClass:[FIRDynamicLinks class] - selector:@selector(dynamicLinkNetworking) - isClassSelector:NO - withBlock:dynamicLinkNetworkingBlock]; -} - -static void SwizzleDynamicLinkNetworkingWithMock(void) { - id linkResolver = OCMPartialMock([[FIRDynamicLinkNetworking alloc] initWithAPIKey:kAPIKey - URLScheme:kURLScheme]); - [[linkResolver stub] resolveShortLink:OCMOCK_ANY FDLSDKVersion:@"1.0.0" completion:OCMOCK_ANY]; - - SwizzleDynamicLinkNetworking(linkResolver); -} - -static void UnswizzleDynamicLinkNetworking(void) { - [GULSwizzler unswizzleClass:[FIRDynamicLinks class] - selector:@selector(dynamicLinkNetworking) - isClassSelector:NO]; -} - -@interface FIRDynamicLinksTest : XCTestCase { - id _bundleMock; -} - -// An instance of |GINDurableDeepLinkService| used for testing. -@property(nonatomic, strong) FIRDynamicLinks *service; -// An instance of |NSUserDefaults| that have all default values removed. -@property(nonatomic, strong) NSUserDefaults *userDefaults; -// FIRAnalytics mock. Necessary because we don't call [FIRAPP configure]. -@property(nonatomic, strong) id analytics; - -@end - -@implementation FIRDynamicLinksTest - -// Disable deprecated warning for internal methods. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - -#pragma mark - Test lifecycle - -static NSString *const kInfoPlistCustomDomainsKey = @"FirebaseDynamicLinksCustomDomains"; - -- (void)setUp { - [super setUp]; - - // Mock the mainBundle infoDictionary with version from DL-Info.plist for custom domain testing. - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSString *filePath = [bundle pathForResource:@"DL-Info" ofType:@"plist"]; - _bundleMock = OCMPartialMock([NSBundle mainBundle]); - OCMStub([_bundleMock infoDictionary]) - .andReturn([NSDictionary dictionaryWithContentsOfFile:filePath]); - - if (![FIRApp isDefaultAppConfigured]) { - XCTAssertNoThrow([FIRApp configureWithOptions:[self appOptions]]); - } - - self.service = [[FIRDynamicLinks alloc] init]; - self.userDefaults = [[NSUserDefaults alloc] init]; - [self.userDefaults removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]]; - self.analytics = OCMProtocolMock(@protocol(FIRAnalyticsInterop)); -} - -- (void)tearDown { - self.service = nil; - self.userDefaults = nil; - [self.analytics stopMocking]; - self.analytics = nil; - [_bundleMock stopMocking]; - _bundleMock = nil; - [super tearDown]; -} - -- (FIROptions *)appOptions { - // TODO: Evaluate if we want to hardcode things here instead. - FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"1:123:ios:123abc" - GCMSenderID:@"correct_gcm_sender_id"]; - options.APIKey = @"correct_api_key"; - options.projectID = @"abc-xyz-123"; - return options; -} - -#pragma mark - Set Up. - -- (void)testURLScheme_NoApiKey { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wnonnull" - BOOL setUpSucceed = [self.service setUpWithLaunchOptions:nil - apiKey:nil - urlScheme:nil - userDefaults:nil]; -#pragma clang diagnostic pop - XCTAssertFalse(setUpSucceed, @"Should fail when apiKey is nil."); -} - -- (void)testURLScheme_MinimumParameters { - BOOL setUpSucceed = [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:nil - userDefaults:nil]; - XCTAssertTrue(setUpSucceed, @"Should not fail when apiKey is set."); -} - -- (void)testFactoryMethodReturnsProperClassObject { - id service = [FIRDynamicLinks dynamicLinks]; - - XCTAssertNotNil(service, @"Factory method returned nil"); - XCTAssertEqualObjects([service class], [FIRDynamicLinks class], - @"Factory returned incorrect class object"); -} - -- (void)testURLScheme_LaunchOptionsWithCustomSchemeURL { - NSString *deepLinkString = - [NSString stringWithFormat:kStructuredLinkFmtDeepLink, - [[NSBundle mainBundle] bundleIdentifier], @"abc123"]; - NSDictionary *launchOptions = - @{UIApplicationLaunchOptionsURLKey : [NSURL URLWithString:deepLinkString]}; - - [self.userDefaults setBool:NO forKey:kFIRDLReadDeepLinkAfterInstallKey]; - [self.service setUpWithLaunchOptions:launchOptions - apiKey:kAPIKey - urlScheme:nil - userDefaults:self.userDefaults]; - XCTAssertTrue([self.userDefaults boolForKey:kFIRDLReadDeepLinkAfterInstallKey]); -} - -- (void)testURLScheme_LaunchOptionsWithUniversalLinkURL { - NSString *deepLinkString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtDeepLink, @"abc123"]; - NSDictionary *launchOptions = - @{UIApplicationLaunchOptionsURLKey : [NSURL URLWithString:deepLinkString]}; - - [self.userDefaults setBool:NO forKey:kFIRDLReadDeepLinkAfterInstallKey]; - [self.service setUpWithLaunchOptions:launchOptions - apiKey:kAPIKey - urlScheme:nil - userDefaults:self.userDefaults]; - XCTAssertTrue([self.userDefaults boolForKey:kFIRDLReadDeepLinkAfterInstallKey]); -} - -- (void)testURLScheme_LaunchOptionsWithInvalidURLWillNotResetUserDefaultsFlag { - NSDictionary *launchOptions = - @{UIApplicationLaunchOptionsURLKey : [NSURL URLWithString:@"https://www.google.com"]}; - - [self.userDefaults setBool:YES forKey:kFIRDLReadDeepLinkAfterInstallKey]; - [self.service setUpWithLaunchOptions:launchOptions - apiKey:kAPIKey - urlScheme:nil - userDefaults:self.userDefaults]; - XCTAssertTrue([self.userDefaults boolForKey:kFIRDLReadDeepLinkAfterInstallKey]); -} - -- (void)testURLScheme_Nil { - BOOL setUpSucceed = [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:nil - userDefaults:nil]; - XCTAssertTrue(setUpSucceed); - XCTAssertEqualObjects(self.service.URLScheme, [NSBundle mainBundle].bundleIdentifier); -} - -- (void)testURLScheme_EmptyString { - BOOL setUpSucceed = [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:@"" - userDefaults:nil]; - XCTAssertTrue(setUpSucceed); - XCTAssertEqualObjects(self.service.URLScheme, [NSBundle mainBundle].bundleIdentifier); -} - -- (void)testURLScheme_NonNil { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - XCTAssertEqualObjects(self.service.URLScheme, kURLScheme, - @"URLScheme should be the same as in argument"); -} - -// TODO (b/63079414) Re-enable this -- (void)DISABLED_testConfigNamedFIRApp { - [self removeAllFIRApps]; - - id deepLinkServicePartialMock = OCMPartialMock([FIRDynamicLinks dynamicLinks]); - [[deepLinkServicePartialMock reject] configureDynamicLinks:[OCMArg any]]; - [FIRApp configureWithName:@"NonDefaultName" options:[FIROptions defaultOptions]]; - [deepLinkServicePartialMock stopMocking]; -} - -// TODO (b/37855379) re-enable the test -- (void)DISABLED_testConfigForFIRApp { - [self removeAllFIRApps]; - - id deepLinkServicePartialMock = OCMPartialMock([FIRDynamicLinks dynamicLinks]); - [FIRApp configure]; - OCMVerify([deepLinkServicePartialMock configureDynamicLinks:[OCMArg any]]); - [deepLinkServicePartialMock stopMocking]; -} - -#pragma mark - dynamicLinkFromCustomSchemeURL - -- (void)testCustomScheme_NoDeepLink { - NSString *urlString = - [NSString stringWithFormat:kStructuredLinkFmtFreeform, kURLScheme, @"abc123xyz"]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertNil(dynamicLink, @"invite should be nil since there is no parameter."); -} - -- (void)testCustomScheme_DeepLinkOnly { - NSString *deepLinkString = @"https://developers.google.com/products/"; - NSString *urlString = - [NSString stringWithFormat:kStructuredLinkFmtDeepLink, kURLScheme, deepLinkString]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertEqualObjects(dynamicLink.url.absoluteString, deepLinkString); - XCTAssertNil(dynamicLink.inviteId); -} - -- (void)testCustomScheme_InvitationOnly { - NSString *invitationId = @"213920940217491274389172947"; - - NSString *urlString = - [NSString stringWithFormat:kStructuredLinkFmtInvitation, kURLScheme, invitationId]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertNil(dynamicLink.url); - XCTAssertEqualObjects(dynamicLink.inviteId, invitationId); -} - -- (void)testCustomScheme_DeepLinkAndInvitation { - NSString *deepLinkString = @"https://developers.google.com/products/"; - NSString *invitationId = @"21392094021749127-4389172947"; - - NSString *urlString = [NSString stringWithFormat:kStructuredLinkFmtDeepLinkAndInvitation, - [[NSBundle mainBundle] bundleIdentifier], - deepLinkString, invitationId]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertEqualObjects(dynamicLink.url.absoluteString, deepLinkString); - XCTAssertEqualObjects(dynamicLink.inviteId, invitationId); -} - -- (void)testCustomScheme_FirstTimeOpenedWithCustomSchemeShouldGetStrongMatch { - NSString *invitationId = @"21392094021749127-4389172947"; - - NSString *urlString = - [NSString stringWithFormat:kStructuredLinkFmtInvitation, kURLScheme, invitationId]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertEqual(dynamicLink.matchConfidence, FIRDynamicLinkMatchConfidenceStrong, - @"matchConfidence should be strong when app is first opened with custom scheme."); - XCTAssertNil(dynamicLink.url); - XCTAssertEqualObjects(dynamicLink.inviteId, invitationId); -} - -- (void)testCustomScheme_FirstTimeOpenedFromDeviceHeuristicsCodepathShouldGetWeakMatch { - NSString *invitationId = @"21392094021749127-4389172947"; - - NSString *urlString = - [NSString stringWithFormat:kStructuredLinkFmtInvitationWeak, kURLScheme, invitationId]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertEqual( - dynamicLink.matchConfidence, FIRDynamicLinkMatchConfidenceWeak, - @"matchConfidence should be weak when app is first opened from device heuristics codepath."); - XCTAssertNil(dynamicLink.url); - XCTAssertEqualObjects(dynamicLink.inviteId, invitationId); -} - -- (void)testCustomScheme_StrongMatch { - NSString *invitationId = @"21392094021749127-4389172947"; - - NSString *urlString = - [NSString stringWithFormat:kStructuredLinkFmtInvitation, kURLScheme, invitationId]; - NSURL *url = [NSURL URLWithString:urlString]; - - // Simulate opening the app. - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kFIRDLReadDeepLinkAfterInstallKey]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertEqual(dynamicLink.matchConfidence, FIRDynamicLinkMatchConfidenceStrong, - @"matchConfidence should be strong when opening an url after app is installed."); - XCTAssertNil(dynamicLink.url); - XCTAssertEqualObjects(dynamicLink.inviteId, invitationId); -} - -- (void)testLinkParamWithPlus { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - NSString *durableDeepLinkString = - [NSString stringWithFormat:@"gindeeplinkurl://google/link?deep_link_id=%@", - kEncodedComplicatedURLString]; - NSURL *durabledeepLinkURL = [NSURL URLWithString:durableDeepLinkString]; - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:durabledeepLinkURL]; - - NSString *deepLinkURLString = dynamicLink.url.absoluteString; - - XCTAssertEqualObjects(kDecodedComplicatedURLString, deepLinkURLString, - @"ddl url parameter and deep link url should be the same"); -} - -#pragma mark - dynamicLinkFromUniversalLinkURL - -- (void)testUniversalLink_NoDeepLink { - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtFreeForm, @"/abc123"]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - NSUserActivity *activity = - [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb]; - activity.webpageURL = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertNil(dynamicLink, @"invite should be nil since there is no parameter."); -} - -// Custom domain entries in plist file: -// https://google.com -// https://google.com/one -// https://a.firebase.com/mypath -- (void)testDynamicLinkFromUniversalLinkURLWithCustomDomainLink { - self.service = [[FIRDynamicLinks alloc] init]; - NSString *durableDeepLinkString = @"https://a.firebase.com/mypath/?link=http://abcd"; - NSURL *durabledeepLinkURL = [NSURL URLWithString:durableDeepLinkString]; - - SwizzleDynamicLinkNetworkingWithMock(); - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:durabledeepLinkURL]; - - XCTAssertNotNil(dynamicLink); - NSString *deepLinkURLString = dynamicLink.url.absoluteString; - - XCTAssertEqualObjects(@"http://abcd", deepLinkURLString, - @"ddl url parameter and deep link url should be the same"); - UnswizzleDynamicLinkNetworking(); -} - -- (void)testDynamicLinkFromUniversalLinkURLCompletionWithCustomDomainLink { - self.service = [[FIRDynamicLinks alloc] init]; - NSString *durableDeepLinkString = @"https://a.firebase.com/mypath/?link=http://abcd"; - NSURL *durabledeepLinkURL = [NSURL URLWithString:durableDeepLinkString]; - - SwizzleDynamicLinkNetworkingWithMock(); - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:durabledeepLinkURL - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - XCTAssertNotNil(dynamicLink); - NSString *deepLinkURLString = dynamicLink.url.absoluteString; - - XCTAssertEqualObjects( - @"http://abcd", deepLinkURLString, - @"ddl url parameter and deep link url should be the same"); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - UnswizzleDynamicLinkNetworking(); -} - -- (void)testDynamicLinkFromUniversalLinkURLWithSpecialCharacters { - NSString *durableDeepLinkString = - [NSString stringWithFormat:@"https://xyz.page.link/?link=%@", kEncodedComplicatedURLString]; - NSURL *durabledeepLinkURL = [NSURL URLWithString:durableDeepLinkString]; - - SwizzleDynamicLinkNetworkingWithMock(); - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:durabledeepLinkURL]; - - NSString *deepLinkURLString = dynamicLink.url.absoluteString; - - XCTAssertEqualObjects(kDecodedComplicatedURLString, deepLinkURLString, - @"ddl url parameter and deep link url should be the same"); - UnswizzleDynamicLinkNetworking(); -} - -- (void)testDynamicLinkFromUniversalLinkURLCompletionWithSpecialCharacters { - NSString *durableDeepLinkString = - [NSString stringWithFormat:@"https://xyz.page.link/?link=%@", kEncodedComplicatedURLString]; - NSURL *durabledeepLinkURL = [NSURL URLWithString:durableDeepLinkString]; - - SwizzleDynamicLinkNetworkingWithMock(); - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:durabledeepLinkURL - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - NSString *deepLinkURLString = dynamicLink.url.absoluteString; - - XCTAssertEqualObjects( - kDecodedComplicatedURLString, deepLinkURLString, - @"ddl url parameter and deep link url should be the same"); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - UnswizzleDynamicLinkNetworking(); -} - -- (void)testDynamicLinkFromUniversalLinkURLWithEncodedCharacters { - NSString *durableDeepLinkString = - [NSString stringWithFormat:@"https://xyz.page.link/?link=%@", kEncodedComplicatedURLString]; - NSURL *durabledeepLinkURL = [NSURL URLWithString:durableDeepLinkString]; - - SwizzleDynamicLinkNetworkingWithMock(); - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:durabledeepLinkURL]; - - NSString *deepLinkURLString = dynamicLink.url.absoluteString; - - XCTAssertEqualObjects(kDecodedComplicatedURLString, deepLinkURLString, - @"ddl url parameter and deep link url should be the same"); - UnswizzleDynamicLinkNetworking(); -} - -- (void)testDynamicLinkFromUniversalLinkURLCompletionWithEncodedCharacters { - NSString *durableDeepLinkString = - [NSString stringWithFormat:@"https://xyz.page.link/?link=%@", kEncodedComplicatedURLString]; - NSURL *durabledeepLinkURL = [NSURL URLWithString:durableDeepLinkString]; - - SwizzleDynamicLinkNetworkingWithMock(); - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:durabledeepLinkURL - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - NSString *deepLinkURLString = dynamicLink.url.absoluteString; - - XCTAssertEqualObjects( - kDecodedComplicatedURLString, deepLinkURLString, - @"ddl url parameter and deep link url should be the same"); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - UnswizzleDynamicLinkNetworking(); -} - -- (void)testUniversalLink_DeepLink { - NSString *deepLinkString = @"https://www.google.com/maps/place/Minneapolis"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - SwizzleDynamicLinkNetworkingWithMock(); - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:url]; - - XCTAssertEqual(dynamicLink.matchConfidence, FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, deepLinkString); - UnswizzleDynamicLinkNetworking(); -} - -- (void)testUniversalLinkWithCompletion_DeepLink { - NSString *deepLinkString = @"https://www.google.com/maps/place/Minneapolis"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - SwizzleDynamicLinkNetworkingWithMock(); - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - XCTAssertEqual(dynamicLink.matchConfidence, - FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, deepLinkString); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - UnswizzleDynamicLinkNetworking(); -} - -- (void)testUniversalLink_DeepLinkWithParameters { - NSString *deepLinkString = @"https://www.google.com?key1%3Dvalue1%26key2%3Dvalue2"; - NSString *parsedDeepLinkString = @"https://www.google.com?key1=value1&key2=value2"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - SwizzleDynamicLinkNetworkingWithMock(); - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:url]; - XCTAssertEqual(dynamicLink.matchConfidence, FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, parsedDeepLinkString); - UnswizzleDynamicLinkNetworking(); -} - -- (void)testUniversalLinkWithCompletion_DeepLinkWithParameters { - NSString *deepLinkString = @"https://www.google.com?key1%3Dvalue1%26key2%3Dvalue2"; - NSString *parsedDeepLinkString = @"https://www.google.com?key1=value1&key2=value2"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - SwizzleDynamicLinkNetworkingWithMock(); - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service dynamicLinkFromUniversalLinkURL:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - XCTAssertEqual(dynamicLink.matchConfidence, - FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, - parsedDeepLinkString); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - UnswizzleDynamicLinkNetworking(); -} - -- (void)testResolveLinkReturnsDLWithNilMinAppVersionWhenNotPresent { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - NSString *urlString = @"http://reinl.page.link/t4ionvr"; - NSURL *url = [NSURL URLWithString:urlString]; - - void (^executeRequestBlock)(id, NSDictionary *, NSString *, FIRNetworkRequestCompletionHandler) = - ^(id p1, NSDictionary *requestBody, NSString *requestURLString, - FIRNetworkRequestCompletionHandler handler) { - NSDictionary *dictionary = @{kFDLResolvedLinkDeepLinkURLKey : kEncodedComplicatedURLString}; - NSData *data = FIRDataWithDictionary(dictionary, nil); - - handler(data, nil, nil); - }; - - SEL executeRequestSelector = @selector(executeOnePlatformRequest:forURL:completionHandler:); - [GULSwizzler swizzleClass:[FIRDynamicLinkNetworking class] - selector:executeRequestSelector - isClassSelector:NO - withBlock:executeRequestBlock]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"handler called"]; - - [self.service - handleUniversalLink:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { - XCTAssertNil(dynamicLink.minimumAppVersion, - @"Min app version not nil when not present."); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testResolveLinkReturnsDLWithMinAppVersionWhenPresent { - NSString *expectedMinVersion = @"8g5u3e"; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - NSString *urlString = @"http://reinl.page.link/t4ionvr"; - NSURL *url = [NSURL URLWithString:urlString]; - - void (^executeRequestBlock)(id, NSDictionary *, NSString *, FIRNetworkRequestCompletionHandler) = - ^(id p1, NSDictionary *requestBody, NSString *requestURLString, - FIRNetworkRequestCompletionHandler handler) { - NSDictionary *dictionary = @{ - kFDLResolvedLinkDeepLinkURLKey : kEncodedComplicatedURLString, - kFDLResolvedLinkMinAppVersionKey : expectedMinVersion, - }; - NSData *data = FIRDataWithDictionary(dictionary, nil); - NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url - statusCode:200 - HTTPVersion:nil - headerFields:nil]; - handler(data, response, nil); - }; - - SEL executeRequestSelector = @selector(executeOnePlatformRequest:forURL:completionHandler:); - [GULSwizzler swizzleClass:[FIRDynamicLinkNetworking class] - selector:executeRequestSelector - isClassSelector:NO - withBlock:executeRequestBlock]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"handler called"]; - - [self.service - handleUniversalLink:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { - XCTAssertEqualObjects(expectedMinVersion, dynamicLink.minimumAppVersion, - @"min app version did not match imv parameter."); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testUniversalLinkWithSubdomain_NoDeepLink { - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomain, @"/abc123"]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - XCTAssertNil(dynamicLink, @"deepLink should be nil since there is no parameter."); -} - -- (void)testDynamicLinkFromCustomSchemeURLReturnsDLWithNilMinimumVersion { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - NSURL *url = FIRDLDeepLinkURLWithInviteID(nil, kEncodedComplicatedURLString, nil, nil, nil, nil, - nil, NO, nil, nil, kURLScheme, nil); - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - - XCTAssertNil(dynamicLink.minimumAppVersion, @"Min app version was not nil when not set."); -} - -- (void)testDynamicLinkFromCustomSchemeURLReturnsDLMinimumVersion { - NSString *expectedMinVersion = @"03-9g03hfd"; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - NSURL *url = FIRDLDeepLinkURLWithInviteID(nil, kEncodedComplicatedURLString, nil, nil, nil, nil, - nil, NO, nil, expectedMinVersion, kURLScheme, nil); - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromCustomSchemeURL:url]; - - NSString *minVersion = dynamicLink.minimumAppVersion; - - XCTAssertEqualObjects(expectedMinVersion, minVersion, - @"Min version didn't match the min app version parameter"); -} - -- (void)testDynamicLinkFromUniversalLinkURLReturnsDLWithNilMinimumVersion { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - NSURL *url = FIRDLDeepLinkURLWithInviteID(nil, kEncodedComplicatedURLString, nil, nil, nil, nil, - nil, NO, nil, nil, kURLScheme, nil); - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:url]; - - NSString *minVersion = dynamicLink.minimumAppVersion; - - XCTAssertNil(minVersion, @"Min app version was not nil when not set."); -} - -- (void)testDynamicLinkFromUniversalLinkURLCompletionReturnsDLWithNilMinimumVersion { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - NSURL *url = FIRDLDeepLinkURLWithInviteID(nil, kEncodedComplicatedURLString, nil, nil, nil, nil, - nil, NO, nil, nil, kURLScheme, nil); - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - NSString *minVersion = dynamicLink.minimumAppVersion; - - XCTAssertNil(minVersion, @"Min app version was not nil when not set."); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testDynamicLinkFromUniversalLinkURLReturnsDLMinimumVersion { - NSString *expectedMinVersion = @"03-9g03hfd"; - NSString *urlSuffix = - [NSString stringWithFormat:@"%@&imv=%@", kEncodedComplicatedURLString, expectedMinVersion]; - NSString *urlString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomainDeepLink, urlSuffix]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:url]; - - NSString *minVersion = dynamicLink.minimumAppVersion; - - XCTAssertEqualObjects(expectedMinVersion, minVersion, @"Min version didn't match imv= parameter"); -} - -- (void)testDynamicLinkFromUniversalLinkURLReturnsUTMParams { - NSString *expectedUtmSource = @"utm_source"; - NSString *expectedUtmMedium = @"utm_medium"; - NSString *expectedUtmCampaign = @"utm_campaign"; - NSString *expectedUtmTerm = @"utm_term"; - NSString *expectedUtmContent = @"utm_content"; - - NSString *utmParamsString = [NSString - stringWithFormat:@"utm_source=%@&utm_medium=%@&utm_campaign=%@&utm_term=%@&utm_content=%@", - expectedUtmSource, expectedUtmMedium, expectedUtmCampaign, expectedUtmTerm, - expectedUtmContent]; - NSString *urlSuffix = - [NSString stringWithFormat:@"%@&%@", kEncodedComplicatedURLString, utmParamsString]; - - NSString *urlString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomainDeepLink, urlSuffix]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - NSDictionary *utmParameters = dynamicLink.utmParametersDictionary; - NSString *utmSource = [utmParameters objectForKey:@"utm_source"]; - XCTAssertEqualObjects(utmSource, expectedUtmSource, - @"UtmSource doesn't match utm_source parameter"); - - NSString *utmMedium = [utmParameters objectForKey:@"utm_medium"]; - XCTAssertEqualObjects(utmMedium, expectedUtmMedium, - @"UtmMedium doesn't match utm_medium parameter"); - - NSString *utmCampaign = [utmParameters objectForKey:@"utm_campaign"]; - XCTAssertEqualObjects( - utmCampaign, expectedUtmCampaign, - @"UtmCampaign doesn't match utm_campaign parameter"); - - NSString *utmTerm = [utmParameters objectForKey:@"utm_term"]; - XCTAssertEqualObjects(utmTerm, expectedUtmTerm, - @"UtmTerm doesn't match utm_term parameter"); - - NSString *utmContent = [utmParameters objectForKey:@"utm_content"]; - XCTAssertEqualObjects( - utmContent, expectedUtmContent, - @"UtmContent doesn't match utm_content parameter"); - - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testDynamicLinkFromUniversalLinkURLCompletionReturnsDLMinimumVersion { - NSString *expectedMinVersion = @"03-9g03hfd"; - NSString *urlSuffix = - [NSString stringWithFormat:@"%@&imv=%@", kEncodedComplicatedURLString, expectedMinVersion]; - NSString *urlString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomainDeepLink, urlSuffix]; - NSURL *url = [NSURL URLWithString:urlString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - NSString *minVersion = dynamicLink.minimumAppVersion; - - XCTAssertEqualObjects(expectedMinVersion, minVersion, - @"Min version didn't match imv= parameter"); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testUniversalLinkWithSubdomain_DeepLink { - NSString *deepLinkString = @"https://www.google.com/maps/place/Minneapolis"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomainDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - SwizzleDynamicLinkNetworkingWithMock(); - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:url]; - XCTAssertEqual(dynamicLink.matchConfidence, FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, deepLinkString); - UnswizzleDynamicLinkNetworking(); -} - -- (void)testUniversalLinkWithCompletionWithSubdomain_DeepLink { - NSString *deepLinkString = @"https://www.google.com/maps/place/Minneapolis"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomainDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - SwizzleDynamicLinkNetworkingWithMock(); - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service - dynamicLinkFromUniversalLinkURL:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - XCTAssertEqual(dynamicLink.matchConfidence, - FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, deepLinkString); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - UnswizzleDynamicLinkNetworking(); -} - -- (void)testUniversalLinkWithSubdomain_DeepLinkWithParameters { - NSString *deepLinkString = @"https://www.google.com?key1%3Dvalue1%26key2%3Dvalue2"; - NSString *parsedDeepLinkString = @"https://www.google.com?key1=value1&key2=value2"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomainDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - FIRDynamicLink *dynamicLink = [self.service dynamicLinkFromUniversalLinkURL:url]; - XCTAssertEqual(dynamicLink.matchConfidence, FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, parsedDeepLinkString); -} - -- (void)testUniversalLinkWithCompletionWithSubdomain_DeepLinkWithParameters { - NSString *deepLinkString = @"https://www.google.com?key1%3Dvalue1%26key2%3Dvalue2"; - NSString *parsedDeepLinkString = @"https://www.google.com?key1=value1&key2=value2"; - NSString *webPageURLString = - [NSString stringWithFormat:kStructuredUniversalLinkFmtSubdomainDeepLink, deepLinkString]; - NSURL *url = [NSURL URLWithString:webPageURLString]; - - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"completion called"]; - [self.service dynamicLinkFromUniversalLinkURL:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, - NSError *_Nullable error) { - XCTAssertTrue([NSThread isMainThread]); - XCTAssertEqual(dynamicLink.matchConfidence, - FIRDynamicLinkMatchConfidenceStrong); - XCTAssertEqualObjects(dynamicLink.url.absoluteString, - parsedDeepLinkString); - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testResolveLinkRespectsResponseSuccessStatusCode { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - NSString *urlString = @"http://domain"; - NSURL *url = [NSURL URLWithString:urlString]; - - void (^executeRequestBlock)(id, NSDictionary *, NSString *, FIRNetworkRequestCompletionHandler) = - ^(id p1, NSDictionary *requestBody, NSString *requestURLString, - FIRNetworkRequestCompletionHandler handler) { - NSData *data = FIRDataWithDictionary(@{}, nil); - NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url - statusCode:200 - HTTPVersion:nil - headerFields:nil]; - handler(data, response, nil); - }; - - SEL executeRequestSelector = @selector(executeOnePlatformRequest:forURL:completionHandler:); - [GULSwizzler swizzleClass:[FIRDynamicLinkNetworking class] - selector:executeRequestSelector - isClassSelector:NO - withBlock:executeRequestBlock]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"handler called"]; - - [self.service resolveShortLink:url - completion:^(NSURL *_Nullable url, NSError *_Nullable error) { - XCTAssertNotNil(url); - XCTAssertNil(error); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testResolveLinkRespectsResponseErrorStatusCode { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - NSString *urlString = @"http://domain"; - NSURL *url = [NSURL URLWithString:urlString]; - - NSError *expectedError = [NSError - errorWithDomain:@"com.firebase.dynamicLinks" - code:0 - userInfo:@{ - @"message" : [NSString stringWithFormat:@"Failed to resolve link: %@", urlString] - }]; - - void (^executeRequestBlock)(id, NSDictionary *, NSString *, FIRNetworkRequestCompletionHandler) = - ^(id p1, NSDictionary *requestBody, NSString *requestURLString, - FIRNetworkRequestCompletionHandler handler) { - NSData *data = FIRDataWithDictionary(@{}, nil); - NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url - statusCode:400 - HTTPVersion:nil - headerFields:nil]; - handler(data, response, nil); - }; - - SEL executeRequestSelector = @selector(executeOnePlatformRequest:forURL:completionHandler:); - [GULSwizzler swizzleClass:[FIRDynamicLinkNetworking class] - selector:executeRequestSelector - isClassSelector:NO - withBlock:executeRequestBlock]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"handler called"]; - - [self.service resolveShortLink:url - completion:^(NSURL *_Nullable url, NSError *_Nullable error) { - XCTAssertNil(url); - XCTAssertNotNil(error); - XCTAssertEqualObjects(error, expectedError, - @"Handle universal link returned unexpected error"); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; -} - -- (void)testPassMatchesShortLinkFormatForDDLDomains { - NSArray *urlStrings = @[ - @"https://someapp.app.goo.gl/somepath", - @"https://someapp.app.goo.gl/link", - @"https://someapp.app.goo.gl/somepath?link=https://somedomain", - @"https://someapp.app.goo.gl/somepath?somekey=somevalue", - @"https://someapp.app.goo.gl/somepath/?link=https://somedomain", - @"https://someapp.app.goo.gl/somepath/?somekey=somevalue", - @"https://someapp.app.google/somepath", - @"https://someapp.app.google/link", - @"https://someapp.app.google/somepath?link=https://somedomain", - @"https://someapp.app.google/somepath?somekey=somevalue", - @"https://someapp.app.google/somepath/?link=https://somedomain", - @"https://someapp.app.google/somepath/?somekey=somevalue", - @"https://someapp.page.link/somepath", - @"https://someapp.page.link/link", - @"https://someapp.page.link/somepath?link=https://somedomain", - @"https://someapp.page.link/somepath?somekey=somevalue", - @"https://someapp.page.link/somepath/?link=https://somedomain", - @"https://someapp.page.link/somepath/?somekey=somevalue", - @"http://someapp.page.link/somepath", - @"http://someapp.page.link/link", - @"http://someapp.page.link/somepath?link=https://somedomain", - @"http://someapp.page.link/somepath?somekey=somevalue", - @"http://someapp.page.link/somepath/?link=http://somedomain", - @"http://someapp.page.link/somepath/?somekey=somevalue" - ]; - - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url]; - - XCTAssertTrue(matchesShortLinkFormat, - @"Non-DDL domain URL matched short link format with URL: %@", url); - } -} - -- (void)testFailMatchesShortLinkFormat { - NSArray *urlStrings = @[ - @"https://someapp.app.goo.gl", - @"https://someapp.app.goo.gl/", - @"https://someapp.app.goo.gl?", - @"https://someapp.app.goo.gl/?", - @"https://someapp.app.goo.gl?somekey=somevalue", - @"https://someapp.app.goo.gl/?somekey=somevalue", - @"https://someapp.app.goo.gl/somepath/somepath2", - @"https://someapp.app.goo.gl/somepath/somepath2?somekey=somevalue", - @"https://someapp.app.goo.gl/somepath/somepath2?link=https://somedomain", - @"https://someapp.app.google", - @"https://someapp.app.google/", - @"https://someapp.app.google?", - @"https://someapp.app.google/?", - @"https://someapp.app.google?somekey=somevalue", - @"https://someapp.app.google/?somekey=somevalue", - @"https://someapp.app.google/somepath/somepath2", - @"https://someapp.app.google/somepath/somepath2?somekey=somevalue", - @"https://someapp.app.google/somepath/somepath2?link=https://somedomain", - @"https://someapp.page.link", - @"https://someapp.page.link/", - @"https://someapp.page.link?", - @"https://someapp.page.link/?", - @"https://someapp.page.link?somekey=somevalue", - @"https://someapp.page.link/?somekey=somevalue", - @"https://someapp.page.link/somepath/somepath2", - @"https://someapp.page.link/somepath/somepath2?somekey=somevalue", - @"https://someapp.page.link/somepath/somepath2?link=https://somedomain", - @"https://www.google.com/maps/place/@1,1/My+Home/", - @"https://mydomain.com/t439gfde", - @"https://goo.gl/309dht4", - @"https://59eh.goo.gl/309dht4", - @"https://app.59eh.goo.gl/309dht4", - @"https://goo.gl/i/309dht4", - @"https://page.link/i/309dht4", - @"https://fjo3eh.goo.gl/i/309dht4", - @"https://app.fjo3eh.goo.gl/i/309dht4", - @"https://1234.page.link/link/dismiss" - ]; - - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url]; - - XCTAssertFalse(matchesShortLinkFormat, - @"Non-DDL domain URL matched short link format with URL: %@", url); - } -} - -// Custom domain entries in plist file: -// https://google.com -// https://google.com/one -// https://a.firebase.com/mypath -- (void)testFailMatchesShortLinkFormatForCustomDomains { - NSArray *urlStrings = @[ - @"https://google.com", - @"https://a.firebase.com", - @"https://google.com/", - @"https://google.com?", - @"https://google.com/?", - @"https://google.com?utm_campgilink=someval", - @"https://google.com?somekey=someval", - ]; - - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url]; - - XCTAssertFalse(matchesShortLinkFormat, - @"Non-DDL domain URL matched short link format with URL: %@", url); - } -} - -// Custom domain entries in plist file: -// https://google.com -// https://google.com/one -// https://a.firebase.com/mypath -- (void)testPassMatchesShortLinkFormatForCustomDomains { - NSArray *urlStrings = @[ - @"https://google.com/xyz", @"https://google.com/xyz/?link=https://somedomain", - @"https://google.com/xyz?link=https://somedomain", - @"https://google.com/xyz/?link=https://somedomain", @"https://google.com/one/xyz", - @"https://google.com/one/xyz?link=https://somedomain", - @"https://google.com/one/xyz/?link=https://somedomain", - @"https://google.com/one?utm_campaignlink=https://somedomain", - @"https://google.com/one/?utm_campaignlink=https://somedomain", @"https://google.com/mylink", - @"https://google.com/one/mylink", @"https://a.firebase.com/mypath/mylink" - ]; - - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url]; - - XCTAssertTrue(matchesShortLinkFormat, - @"Non-DDL domain URL matched short link format with URL: %@", url); - } -} - -- (void)testMatchesUnversalLinkWithShortDurableLink { - NSString *urlString = @"https://sample.page.link/79g49s"; - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShort = [self.service matchesShortLinkFormat:url]; - - XCTAssertTrue(matchesShort, @"Short Durable Link didn't match short link"); -} - -- (void)testMatchesUnversalLinkWithAppInvite { - NSString *urlString = @"https://sample.page.link/i/79g49s"; - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShort = [self.service matchesShortLinkFormat:url]; - - XCTAssertTrue(matchesShort, @"AppInvite didn't match short link"); -} - -- (void)testDoesNotMatchesShortLinkFormatWithNonDDLDomains { - NSArray *urlStrings = @[ - @"https://www.google.com/maps/place/@1,1/My+Home/", @"https://mydomain.com/t439gfde", - @"https://goo.gl/309dht4", @"https://59eh.goo.gl/309dht4", @"https://app.59eh.goo.gl/309dht4", - @"https://goo.gl/i/309dht4", @"https://page.link/i/309dht4", @"https://fjo3eh.goo.gl/i/309dht4", - @"https://app.fjo3eh.goo.gl/i/309dht4", @"https://1234.page.link/link/dismiss" - ]; - - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url]; - - XCTAssertFalse(matchesShortLinkFormat, - @"Non-DDL domain URL matched short link format with URL: %@", url); - } -} - -- (void)testHandleUniversalLinkWithShortLink { - NSString *shortLinkString = @"https://sample.page.link/549igo"; - - NSString *bundleID = [NSBundle mainBundle].bundleIdentifier; - - NSString *customSchemeURLString = [NSString - stringWithFormat:kStructuredLinkFmtDeepLink, bundleID, kEncodedComplicatedURLString]; - - XCTestExpectation *handleLinkCompletionExpectation = - [self expectationWithDescription:@"handleLink"]; - XCTestExpectation *linkResolverCompletionExpectation = - [self expectationWithDescription:@"linkResolver"]; - - FakeShortLinkResolver *resolver = - [FakeShortLinkResolver resolverWithBlock:^NSURL *(NSURL *shortLink) { - [linkResolverCompletionExpectation fulfill]; - return [NSURL URLWithString:customSchemeURLString]; - }]; - - SwizzleDynamicLinkNetworking(resolver); - - [self.service - handleUniversalLink:[NSURL URLWithString:shortLinkString] - completion:^(FIRDynamicLink *_Nonnull dynamicLink, NSError *_Nullable error) { - NSString *returnedURLString = dynamicLink.url.absoluteString; - XCTAssertEqualObjects(kDecodedComplicatedURLString, returnedURLString, - @"Handle universal link returned unexpected link"); - [handleLinkCompletionExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - UnswizzleDynamicLinkNetworking(); -} - -- (void)testHandleUniversalLinkWithLongLink { - NSString *longLinkString = [NSString - stringWithFormat:@"https://sample.page.link?link=%@&ibi=com.google.sample&ius=79306483", - kEncodedComplicatedURLString]; - - XCTestExpectation *handleLinkCompletionExpectation = - [self expectationWithDescription:@"handleLink"]; - __block NSUInteger resolverInvocationsCount = 0; - - // should not be used. - FakeShortLinkResolver *resolver = - [FakeShortLinkResolver resolverWithBlock:^NSURL *(NSURL *shortLink) { - resolverInvocationsCount++; - return [NSURL URLWithString:kDecodedComplicatedURLString]; - }]; - - id handleUniversalLinkBlock = ^(FIRDynamicLink *_Nonnull dynamicLink, NSError *_Nullable error) { - [handleLinkCompletionExpectation fulfill]; - NSURL *expectedResolvedLink = [NSURL URLWithString:kDecodedComplicatedURLString]; - XCTAssertEqualObjects(expectedResolvedLink, dynamicLink.url, - @"Resolve short link returned unexpected link"); - }; - - SwizzleDynamicLinkNetworking(resolver); - - [self.service handleUniversalLink:[NSURL URLWithString:longLinkString] - completion:handleUniversalLinkBlock]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - // It is expected to call resolveLink once for logging. - XCTAssertEqual(resolverInvocationsCount, 1, - @"handleUniversalLink called resolveLink more than once"); - UnswizzleDynamicLinkNetworking(); -} - -- (void)testHandleUniversalLinkCallsHandleUniversalLinkResolver { - XCTestExpectation *handleLinkCompletionExpectation = - [self expectationWithDescription:@"handleLink"]; - void (^replacementBlock)(void) = ^{ - [handleLinkCompletionExpectation fulfill]; - }; - - SEL selectorToSwizzle = @selector(handleUniversalLink:completion:); - - [GULSwizzler swizzleClass:[FIRDynamicLinks class] - selector:selectorToSwizzle - isClassSelector:NO - withBlock:replacementBlock]; - - NSURL *url = [NSURL URLWithString:@"https://google.com"]; - - [self.service - handleUniversalLink:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error){ - }]; - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - - [GULSwizzler unswizzleClass:[FIRDynamicLinks class] - selector:selectorToSwizzle - isClassSelector:NO]; -} - -- (void)testHandleUniversalLinkCompletionReturnsNoForNonDDL { - NSArray *urlStrings = @[ - @"https://www.google.com/maps/place/@1,1/My+Home/", @"https://mydomain.com/t439gfde", - @"https://goo.gl/309dht4", @"https://59eh.goo.gl/309dht4", @"https://app.59eh.goo.gl/309dht4", - @"https://goo.gl/i/309dht4", @"https://page.link/i/309dht4", @"https://fjo3eh.goo.gl/i/309dht4", - @"https://app.fjo3eh.goo.gl/i/309dht4", @"https://1234.page.link/link/dismiss" - ]; - - [urlStrings enumerateObjectsUsingBlock:^(NSString *_Nonnull urlString, NSUInteger idx, - BOOL *_Nonnull stop) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL handled = [self.service - handleUniversalLink:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { - XCTAssertNil(dynamicLink, @"Non DDL returned FIRDynamicLink"); - }]; - - XCTAssertFalse(handled, @"Non DDL Universal Link was handled"); - }]; -} - -- (void)testHandleUniversalLinkCompletionReturnsYesForValidDDL { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - NSArray *urlStrings = @[ - @"https://some.page.link/test", @"https://some.page.link/test-test", - @"https://some.page.link/test_test", @"https://some.page.link/test_test-test", - @"https://some.app.goo.gl/test_test-test", @"https://some.app.google/test_test-test", - @"https://n8r9f.app.goo.gl/?ibi=com%2Egoogle%2EGCMTestApp%2Edev&amv=0&imv=1%2E0&link=https%3A%2F%2Fwww%2Egoogle%2Ecom", - @"https://n8r9f.app.goo.gl/?link=https%3A%2F%2Fwww%2Egoogle%2Ecom&ibi=com%2Egoogle%2EGCMTestApp%2Edev&amv=0&imv=1%2E0", - @"https://n8r9f.app.google/?ibi=com%2Egoogle%2EGCMTestApp%2Edev&amv=0&imv=1%2E0&link=https%3A%2F%2Fwww%2Egoogle%2Ecom", - @"https://n8r9f.app.google/?link=https%3A%2F%2Fwww%2Egoogle%2Ecom&ibi=com%2Egoogle%2EGCMTestApp%2Edev&amv=0&imv=1%2E0" - ]; - - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - - void (^executeRequestBlock)(id, NSDictionary *, NSString *, - FIRNetworkRequestCompletionHandler) = - ^(id p1, NSDictionary *requestBody, NSString *requestURLString, - FIRNetworkRequestCompletionHandler handler) { - NSData *data = FIRDataWithDictionary(@{}, nil); - NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url - statusCode:200 - HTTPVersion:nil - headerFields:nil]; - handler(data, response, nil); - }; - - SEL executeRequestSelector = @selector(executeOnePlatformRequest:forURL:completionHandler:); - [GULSwizzler swizzleClass:[FIRDynamicLinkNetworking class] - selector:executeRequestSelector - isClassSelector:NO - withBlock:executeRequestBlock]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"handler called"]; - - BOOL handled = [self.service - handleUniversalLink:url - completion:^(FIRDynamicLink *_Nullable dynamicLink, NSError *_Nullable error) { - XCTAssertNotNil(dynamicLink, @"Non DDL returned FIRDynamicLink"); - [expectation fulfill]; - }]; - - XCTAssertTrue(handled, @"Valid DDL Universal Link was not handled"); - - [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; - } -} - -- (void)test_ensureInternalMethodsNotRenamed { - // sanity check to ensure these methods has not been renamed - // we relaying on these to be the same for tests to work properly - // we are not exposing these methods in internal headers as we do not have "internal headers" - // 1P apps can import all of our headers - XCTAssertTrue([self.service - respondsToSelector:@selector - (handlePendingDynamicLinkRetrievalFailureWithErrorCode:errorDescription:underlyingError:)]); - XCTAssertTrue([self.service respondsToSelector:@selector(setRetrievingPendingDynamicLink:)]); - XCTAssertTrue([self.service respondsToSelector:@selector(dynamicLinkNetworking)]); -} - -- (void)testCheckForPendingDynamicLinkReturnsImmediatelyIfAlreadyRead { - id mockService = OCMPartialMock(self.service); - [[mockService expect] handlePendingDynamicLinkRetrievalFailureWithErrorCode:-1 - errorDescription:[OCMArg any] - underlyingError:[OCMArg any]]; - [[mockService reject] setRetrievingPendingDynamicLink:YES]; - - [mockService setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:nil - userDefaults:[NSUserDefaults standardUserDefaults]]; - - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kFIRDLReadDeepLinkAfterInstallKey]; - - [mockService checkForPendingDynamicLink]; - - [mockService verify]; - [mockService stopMocking]; -} - -- (void)testRetrievalProcessResultURLContainsAllParametersPassedToDynamicLinkInitializer { - NSDictionary *linkParameters = @{ - @"deep_link_id" : @"https://mmaksym.com/test-app1", - @"match_message" : @"Link is uniquely matched for this device.", - @"match_type" : @"unique", - @"utm_campaign" : @"Maksym M Test", - @"utm_medium" : @"test_medium", - @"utm_source" : @"test_source", - @"utm_content" : @"test_content", - @"utm_term" : @"test_term", - @"a_parameter" : @"a_value" - }; - - FIRDynamicLink *dynamicLink = - [[FIRDynamicLink alloc] initWithParametersDictionary:linkParameters]; - FIRDLRetrievalProcessResult *result = - [[FIRDLRetrievalProcessResult alloc] initWithDynamicLink:dynamicLink - error:nil - message:nil - matchSource:nil]; - - NSURL *customSchemeURL = [result URLWithCustomURLScheme:@"scheme"]; - XCTAssertNotNil(customSchemeURL); - - // Validate URL parameters - NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:customSchemeURL - resolvingAgainstBaseURL:NO]; - XCTAssertNotNil(urlComponents); - XCTAssertEqualObjects(urlComponents.scheme, @"scheme"); - - NSMutableDictionary *notEncodedParameters = [linkParameters mutableCopy]; - - for (NSURLQueryItem *queryItem in urlComponents.queryItems) { - NSString *expectedValue = notEncodedParameters[queryItem.name]; - XCTAssertNotNil(expectedValue, @"Extra parameter encoded: %@ = %@", queryItem.name, - queryItem.value); - - XCTAssertEqualObjects(queryItem.value, expectedValue); - [notEncodedParameters removeObjectForKey:queryItem.name]; - } - - XCTAssertEqual(notEncodedParameters.count, 0, @"The parameters must have been encoded: %@", - notEncodedParameters); -} - -- (void)test_multipleRequestsToRetrievePendingDeepLinkShouldNotCrash { - id mockService = OCMPartialMock(self.service); - [[mockService expect] handlePendingDynamicLinkRetrievalFailureWithErrorCode:-1 - errorDescription:[OCMArg any] - underlyingError:[OCMArg any]]; - // swizzle method to prevent actual retrieval, this will ensure that first pending link - // retrieval will stuck and second will fail with error - id (^replacementBlock)(void) = (id) ^ { return nil; }; - - SEL selectorToSwizzle = @selector(automaticRetrievalProcess); - - [GULSwizzler swizzleClass:[FIRDLRetrievalProcessFactory class] - selector:selectorToSwizzle - isClassSelector:NO - withBlock:replacementBlock]; - - [mockService setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:kURLScheme - userDefaults:self.userDefaults]; - - [mockService checkForPendingDynamicLink]; - // we should not crash here - [mockService checkForPendingDynamicLink]; - - [mockService verify]; - [mockService stopMocking]; - [GULSwizzler unswizzleClass:[FIRDLRetrievalProcessFactory class] - selector:selectorToSwizzle - isClassSelector:NO]; -} - -- (void)test_retrievePendingDeepLinkShouldSetkFIRDLOpenURLKeyRegardlessOfFailures { - [self.service setUpWithLaunchOptions:nil - apiKey:kAPIKey - urlScheme:nil - userDefaults:[NSUserDefaults standardUserDefaults]]; - FIRDynamicLinks *delegate = - (FIRDynamicLinks *)self.service; - - // Error Result to pass - FIRDLRetrievalProcessResult *result = [[FIRDLRetrievalProcessResult alloc] - initWithDynamicLink:nil - error:[NSError errorWithDomain:@"unknown domain" code:500 userInfo:nil] - message:nil - matchSource:nil]; - - FIRDLDefaultRetrievalProcessV2 *defaultRetrievalProcess = [FIRDLDefaultRetrievalProcessV2 alloc]; - - [delegate retrievalProcess:defaultRetrievalProcess completedWithResult:result]; - - NSString *kFIRDLOpenURLKey = @"com.google.appinvite.openURL"; - XCTAssertEqual([[NSUserDefaults standardUserDefaults] boolForKey:kFIRDLOpenURLKey], YES, - @"kFIRDLOpenURL key should be set regardless of failures"); -} - -- (void)test_passRetrievedDynamicLinkToApplicationDelegatesProperly { - // Creating ApplicationDelegate partial mock object. - id applicationDelegate = OCMPartialMock([UIApplication sharedApplication].delegate); - // Creating FIRDynamicLinks partial mock object. - id firebaseDynamicLinks = OCMPartialMock(self.service); - // Stubbing Application delegate to return YES when application:openURL:options method is called. - // Not sure why this is required as we are not concerned about its return, but without this, the - // test will throw NSInvalidArgumentException with message "unrecognized selector sent to - // instance". - OCMStub([applicationDelegate application:[OCMArg any] openURL:[OCMArg any] options:[OCMArg any]]) - .andReturn(YES); - // Stubbing firebase dynamiclinks instance to return YES when isOpenUrlMethodPresentInAppDelegate - // is called. - OCMStub([firebaseDynamicLinks isOpenUrlMethodPresentInAppDelegate:[OCMArg any]]).andReturn(YES); - - // Executing the function with a URL. - NSURL *url = [NSURL URLWithString:@"http://www.google.com"]; - [firebaseDynamicLinks passRetrievedDynamicLinkToApplication:url]; - - // Verifying the application:openURL:options method is called in AppDelegate. - OCMVerify([applicationDelegate application:[OCMArg any] openURL:url options:[OCMArg any]]); -} - -#pragma mark - Self-diagnose tests - -- (void)testSelfDiagnoseWithNilCompletion { - [FIRDynamicLinks performDiagnosticsWithCompletion:nil]; -} - -- (void)testSelfDiagnoseCompletionCalled { - XCTestExpectation *expectation = - [self expectationWithDescription:@"Self diagnose completion block must be called"]; - - [FIRDynamicLinks - performDiagnosticsWithCompletion:^(NSString *_Nonnull diagnosticOutput, BOOL hasErrors) { - XCTAssert(diagnosticOutput.length > 0, @"Diagnostic expected to provide output"); - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:2.0 handler:nil]; -} - -#pragma mark - Custom domain tests -- (void)testValidCustomDomainNames { - // Entries in plist file: - // https://google.com - // https://google.com/one - // https://a.firebase.com/mypath - - NSArray *urlStrings = @[ - @"https://google.com/mylink", // Short FDL starting with 'https://google.com' - @"https://google.com/one", // Short FDL starting with 'https://google.com' - @"https://google.com/one/", // Short FDL starting with 'https://google.com' - @"https://google.com/one?", // Short FDL starting with 'https://google.com' - @"https://google.com/one/mylink", // Short FDL starting with 'https://google.com/one' - @"https://a.firebase.com/mypath/mylink", // Short FDL starting https://a.firebase.com/mypath - @"https://google.com/somepath?link=https://somedomain", - @"https://google.com/somepath/?link=https://somedomain", - @"https://google.com/somepath/somepath2?link=https://somedomain", - @"https://google.com/somepath/somepath2/?link=https://somedomain", - @"https://google.com/somepath?utm_campgilink=someval" - ]; - - NSArray *longFDLURLStrings = @[ - @"https://a.firebase.com/mypath/?link=https://abcd&test=1", // Long FDL starting with - // https://a.firebase.com/mypath - @"https://google.com?link=http://abcd", // Long FDL starting with 'https://google.com' - @"https://google.com/?link=http://abcd", // Long FDL starting with 'https://google.com' - @"https://google.com?link=https://somedomain&some=qry", // Long FDL with link param as another - // argument. - @"https://google.com/?link=https://somedomain&some=qry", // Long FDL with link param as another - // argument. - @"https://google.com?some=qry&link=https://somedomain", // Long FDL with link param as second - // argument. - @"https://google.com/?some=qry&link=https://somedomain", // Long FDL with link param as second - // argument - @"https://google.com/?a=b&c=d&link=https://somedomain&y=z", // Long FDL with link param as - // middle argument argument - @"https://google.com?some=qry&link=https%3A%2F%2Fsomedomain", // Long FDL with Url encoded link - // param - ]; - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url]; - - XCTAssertTrue(matchesShortLinkFormat, @"URL did not validate as short link: %@", url); - } - for (NSString *urlString in longFDLURLStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesLongLinkFormat = [self.service canParseUniversalLinkURL:url]; - - XCTAssertTrue(matchesLongLinkFormat, @"URL did not validate as long link: %@", url); - } -} - -- (void)testInvalidCustomDomainNames { - // Entries in plist file: - // https://google.com - // https://google.com/one - // https://a.firebase.com/mypath - - NSArray *urlStrings = @[ - @"google.com", // Valid domain. No scheme. - @"https://google.com", // Valid domain. No path after domainURIPrefix. - @"https://google.com/", // Valid domain. No path after domainURIPrefix. - @"https://google.co.in/mylink", // No matching domainURIPrefix. - @"https://google.com/?some=qry", // Valid domain with no path and link param - @"https://google.com/?some=qry&link=bla", // Valid domain with no path and no valid link param - @"https://firebase.com/mypath", // No matching domainURIPrefix: Invalid (sub)domain. - @"https://b.firebase.com/mypath", // No matching domainURIPrefix: Invalid subdomain. - @"https://a.firebase.com/mypathabc", // No matching domainURIPrefix: Invalid subdomain. - @"mydomain.com", // https scheme not specified for domainURIPrefix. - @"http://mydomain", // Domain not in plist. No path after domainURIPrefix. - @"https://somecustom.com?", @"https://somecustom.com/?", - @"https://somecustom.com?somekey=someval", - @"https://google.com?some=qry&somelink=https%3A%2F%2Fsomedomain", // Having somelink param - // instead of link param to - // confuse validation. - @"https://a.firebase.com/mypaths?some=qry&link=https%3A%2F%2Fsomedomain", // Additional 's' in - // path param - @"https://a.firebase.com/mypath/?some=qry#other=b&link=https://somedomain", // link param comes - // in fragmentation - @"https://a.firebase.com/mypath/?some=qry#other=b&link=https%3A%2F%2Fsomedomain", // link param - // which is - // url - // encoded - // and comes - // in - // fragmentation. - @"https://google.com?link=https1://abcd", // link query param is not a valid http link - ]; - - for (NSString *urlString in urlStrings) { - NSURL *url = [NSURL URLWithString:urlString]; - BOOL matchesShortLinkFormat = [self.service canParseUniversalLinkURL:url]; - - XCTAssertFalse(matchesShortLinkFormat, - @"Non-DDL domain URL matched short link format with URL: %@", url); - } -} - -#pragma mark - Private Helpers - -- (void)removeAllFIRApps { - NSDictionary *apps = [FIRApp allApps]; - for (FIRApp *app in apps.allValues) { - [app deleteApp:^(BOOL success) { - if (!success) { - NSLog(@"Error deleting FIRApp before tests - config tests may fail."); - } - }]; - } -} - -#pragma clang pop - -@end diff --git a/FirebaseDynamicLinks/Tests/Unit/UtilitiesTests.m b/FirebaseDynamicLinks/Tests/Unit/UtilitiesTests.m deleted file mode 100644 index 2a6ac0fa523..00000000000 --- a/FirebaseDynamicLinks/Tests/Unit/UtilitiesTests.m +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2018 Google - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import - -#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h" - -static NSString *const kURLScheme = @"gindeeplinkurl"; - -@interface FDLUtilitiesTests : XCTestCase -@end - -@implementation FDLUtilitiesTests - -- (void)testFDLCookieRetrievalURLCreatesCorrectURL { - static NSString *const kCustomScheme = @"customscheme"; - static NSString *const kBundleID = @"com.My.Bundle.ID"; - - NSString *expectedURLString = [NSString stringWithFormat:@"https://goo.gl/app/_/deeplink?fdl_ios_" - "bundle_id=%@&fdl_ios_url_scheme=%@", - kBundleID, kCustomScheme]; - - NSURL *url = FIRDLCookieRetrievalURL(kCustomScheme, kBundleID); - - XCTAssertEqualObjects(url.absoluteString, expectedURLString); -} - -- (void)testFDLURLQueryStringFromDictionaryReturnsEmptyStringWithEmptyDictionary { - NSString *query = FIRDLURLQueryStringFromDictionary(@{}); - - XCTAssertEqualObjects(query, @""); -} - -- (void)testFDLURLQueryStringFromDictionaryReturnsCorrectStringWithSingleKVP { - NSString *key = @"key"; - NSString *value = @"value"; - - NSDictionary *queryDict = @{key : value}; - NSString *query = FIRDLURLQueryStringFromDictionary(queryDict); - - NSString *expectedQuery = [NSString stringWithFormat:@"?%@=%@", key, value]; - - XCTAssertEqualObjects(query, expectedQuery); -} - -- (void)testFDLURLQueryStringFromDictionary { - NSDictionary *expectedQueryDict = @{ - @"key1" : @"va!lue1", - @"key2" : @"val=ue2", - @"key3" : @"val&ue3", - @"key4" : @"valu?e4", - @"key5" : @"val$ue5", - }; - - NSString *query = FIRDLURLQueryStringFromDictionary(expectedQueryDict); - NSString *prefixToRemove = @"?"; - NSString *queryWithoutPrefix = [query substringFromIndex:prefixToRemove.length]; - - NSDictionary *retrievedQueryDict = FIRDLDictionaryFromQuery(queryWithoutPrefix); - - XCTAssertEqualObjects(retrievedQueryDict, expectedQueryDict); -} - -- (void)testGINDictionaryFromQueryWithNormalQuery { - NSString *query = @"key1=value1&key2=value2"; - - NSDictionary *returnedDictionary = FIRDLDictionaryFromQuery(query); - NSDictionary *expectedDictionary = @{@"key1" : @"value1", @"key2" : @"value2"}; - - XCTAssertEqualObjects(returnedDictionary, expectedDictionary); -} - -- (void)testGINDictionaryFromQueryWithQueryMissingValue { - NSString *query = @"key1=value1&key2="; - - NSDictionary *returnedDictionary = FIRDLDictionaryFromQuery(query); - NSDictionary *expectedDictionary = @{@"key1" : @"value1", @"key2" : @""}; - - XCTAssertEqualObjects(returnedDictionary, expectedDictionary); -} - -- (void)testGINDictionaryFromQueryWithQueryMissingKey { - NSString *query = @"key1=value1&=value2"; - - NSDictionary *returnedDictionary = FIRDLDictionaryFromQuery(query); - NSDictionary *expectedDictionary = @{@"key1" : @"value1", @"" : @"value2"}; - - XCTAssertEqualObjects(returnedDictionary, expectedDictionary); -} - -- (void)testGINDictionaryFromQueryWithQueryMissingKeyAndValue { - NSString *query = @"key1=value1&="; - - NSDictionary *returnedDictionary = FIRDLDictionaryFromQuery(query); - NSDictionary *expectedDictionary = @{@"key1" : @"value1", @"" : @""}; - - XCTAssertEqualObjects(returnedDictionary, expectedDictionary); -} - -- (void)testGINDictionaryFromQueryWithQueryMissingPairAtTheEnd { - NSString *query = @"key1=value1&"; - - NSDictionary *returnedDictionary = FIRDLDictionaryFromQuery(query); - NSDictionary *expectedDictionary = @{@"key1" : @"value1"}; - - XCTAssertEqualObjects(returnedDictionary, expectedDictionary); -} - -- (void)testGINDictionaryFromQueryWithQueryMissingPairAtTheBeginning { - NSString *query = @"&key1=value1"; - - NSDictionary *returnedDictionary = FIRDLDictionaryFromQuery(query); - NSDictionary *expectedDictionary = @{@"key1" : @"value1"}; - - XCTAssertEqualObjects(returnedDictionary, expectedDictionary); -} - -- (void)testGINDictionaryFromQueryWithQueryMissingPairInTheMiddle { - NSString *query = @"key1=value1&&key2=value2"; - - NSDictionary *returnedDictionary = FIRDLDictionaryFromQuery(query); - NSDictionary *expectedDictionary = @{@"key1" : @"value1", @"key2" : @"value2"}; - - XCTAssertEqualObjects(returnedDictionary, expectedDictionary); -} - -- (void)testDeepLinkURLWithInviteIDDeepLinkStringWeakMatchEndpointCreatesExpectedCustomSchemeURL { - NSString *inviteID = @"3082906yht4i02"; - NSString *deepLinkString = @"https://google.com/a%b!c=d"; - NSString *encodedDeepLinkString = @"https%3A%2F%2Fgoogle%2Ecom%2Fa%25b%21c%3Dd"; - NSString *weakMatchEndpoint = @"IPV6"; - NSString *utmSource = @"firebase"; - NSString *utmMedium = @"email"; - NSString *utmCampaign = @"testCampaign"; - NSString *utmTerm = @"testTerm"; - NSString *utmContent = @"testContent"; - NSString *matchType = @"unique"; - - NSString *expectedURLString = [NSString - stringWithFormat:@"%@://google/link/?utm_campaign=%@" - @"&deep_link_id=%@&utm_medium=%@&invitation_weakMatchEndpoint=%@" - @"&utm_source=%@&invitation_id=%@&match_type=%@" - @"&utm_content=%@&utm_term=%@", - kURLScheme, utmCampaign, encodedDeepLinkString, utmMedium, weakMatchEndpoint, - utmSource, inviteID, matchType, utmContent, utmTerm]; - NSURLComponents *expectedURLComponents = [NSURLComponents componentsWithString:expectedURLString]; - - NSURL *actualURL = FIRDLDeepLinkURLWithInviteID(inviteID, deepLinkString, utmSource, utmMedium, - utmCampaign, utmContent, utmTerm, NO, - weakMatchEndpoint, nil, kURLScheme, nil); - - NSURLComponents *actualURLComponents = [NSURLComponents componentsWithURL:actualURL - resolvingAgainstBaseURL:NO]; - - // Since the parameters are not guaranteed to be in any specific order, we must compare - // arrays of properties of the URLs rather than the URLs themselves. - // sort both expected/actual arrays to prevent order influencing the test results - NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; - NSArray *expectedURLQueryItems = - [expectedURLComponents.queryItems sortedArrayUsingDescriptors:@[ sort ]]; - - NSArray *actualQueryItems = - [actualURLComponents.queryItems sortedArrayUsingDescriptors:@[ sort ]]; - - XCTAssertEqualObjects(actualQueryItems, expectedURLQueryItems); - XCTAssertEqualObjects(actualURLComponents.host, expectedURLComponents.host); -} - -- (void)testGINOSVersionSupportedReturnsYESWhenCurrentIsGreaterThanMin { - BOOL supported = FIRDLOSVersionSupported(@"8.0.1", @"8.0"); - XCTAssertTrue(supported, @"FIRDLOSVersionSupported() returned NO when the OS was supported."); -} - -- (void)testGINOSVersionSupportedReturnsYESWhenCurrentIsEqualToMin { - BOOL supported = FIRDLOSVersionSupported(@"8.0", @"8.0"); - XCTAssertTrue(supported, @"FIRDLOSVersionSupported() returned NO when the OS was supported."); -} - -- (void)testGINOSVersionSupportedReturnsNOWhenCurrentIsLessThanMin { - BOOL supported = FIRDLOSVersionSupported(@"7.1", @"8.1"); - XCTAssertFalse(supported, - @"FIRDLOSVersionSupported() returned YES when the OS was not supported."); -} - -@end From 4eba7ac6473094675246578f01b96909d4cc37ac Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 11:57:59 -0400 Subject: [PATCH 02/16] remove workflow references --- .github/workflows/archiving.yml | 2 +- .github/workflows/dynamiclinks.yml | 61 ------------------- .../workflows/health-metrics-presubmit.yml | 26 +------- .github/workflows/zip.yml | 2 - 4 files changed, 2 insertions(+), 89 deletions(-) delete mode 100644 .github/workflows/dynamiclinks.yml diff --git a/.github/workflows/archiving.yml b/.github/workflows/archiving.yml index 3b609718f89..c70afe14b8e 100644 --- a/.github/workflows/archiving.yml +++ b/.github/workflows/archiving.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: # These need to be on a single line or else the formatting won't validate. - pod: ["FirebaseAppDistribution", "FirebaseDynamicLinks", "FirebaseInAppMessaging", "FirebasePerformance"] + pod: ["FirebaseAppDistribution", "FirebaseInAppMessaging", "FirebasePerformance"] steps: - uses: actions/checkout@v4 - uses: mikehardy/buildcache-action@c87cea0ccd718971d6cc39e672c4f26815b6c126 diff --git a/.github/workflows/dynamiclinks.yml b/.github/workflows/dynamiclinks.yml deleted file mode 100644 index 919027e7e20..00000000000 --- a/.github/workflows/dynamiclinks.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: dynamiclinks - -permissions: - contents: read - -on: - workflow_dispatch: - pull_request: - paths: - - 'FirebaseDynamicLinks**' - - '.github/workflows/dynamiclinks.yml' - - 'Interop/Analytics/Public/*.h' - - '.github/workflows/common.yml' - - '.github/workflows/common_cocoapods.yml' - - 'Gemfile*' - schedule: - # Run every day at 1am (PST) - cron uses UTC times - - cron: '0 9 * * *' - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - spm: - strategy: - matrix: - target: [FirebaseAppCheckUnit, FirebaseAppCheckUnitSwift] - uses: ./.github/workflows/common.yml - with: - target: FirebaseDynamicLinks - buildonly_platforms: iOS - platforms: iOS - - pod_lib_lint: - uses: ./.github/workflows/common_cocoapods.yml - with: - product: FirebaseDynamicLinks - platforms: iOS # Dynamic Links only supports iOS. - allow_warnings: true - - dynamiclinks-cron-only: - # Don't run on private repo. - if: github.event_name == 'schedule' && github.repository == 'Firebase/firebase-ios-sdk' - - runs-on: macos-15 - strategy: - matrix: - flags: [ - '--use-static-frameworks' - ] - needs: pod_lib_lint - steps: - - uses: actions/checkout@v4 - - uses: ruby/setup-ruby@354a1ad156761f5ee2b7b13fa8e09943a5e8d252 # v1 - - name: Setup Bundler - run: scripts/setup_bundler.sh - - name: Xcode - run: sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer - - name: PodLibLint Storage Cron - run: scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb FirebaseDynamicLinks.podspec --platforms=ios ${{ matrix.flags }} --allow-warnings diff --git a/.github/workflows/health-metrics-presubmit.yml b/.github/workflows/health-metrics-presubmit.yml index 886cf90f90a..b9bd1a00edc 100644 --- a/.github/workflows/health-metrics-presubmit.yml +++ b/.github/workflows/health-metrics-presubmit.yml @@ -33,7 +33,6 @@ jobs: auth_run_job: ${{ steps.check_files.outputs.auth_run_job }} crashlytics_run_job: ${{ steps.check_files.outputs.crashlytics_run_job }} database_run_job: ${{ steps.check_files.outputs.database_run_job }} - dynamiclinks_run_job: ${{ steps.check_files.outputs.dynamiclinks_run_job }} firestore_run_job: ${{ steps.check_files.outputs.firestore_run_job }} functions_run_job: ${{ steps.check_files.outputs.functions_run_job }} inappmessaging_run_job: ${{ steps.check_files.outputs.inappmessaging_run_job }} @@ -126,29 +125,6 @@ jobs: name: codecoverage path: /Users/runner/*.xcresult - pod-lib-lint-dynamiclinks: - needs: check - # Don't run on private repo unless it is a PR. - if: always() && github.repository == 'Firebase/firebase-ios-sdk' && (needs.check.outputs.dynamiclinks_run_job == 'true'|| github.event.pull_request.merged) - runs-on: macos-14 - strategy: - matrix: - target: [iOS] - steps: - - uses: actions/checkout@v4 - - uses: mikehardy/buildcache-action@c87cea0ccd718971d6cc39e672c4f26815b6c126 - with: - cache_key: ${{ matrix.os }} - - uses: ruby/setup-ruby@354a1ad156761f5ee2b7b13fa8e09943a5e8d252 # v1 - - name: Setup Bundler - run: scripts/setup_bundler.sh - - name: Build and test - run: ./scripts/health_metrics/pod_test_code_coverage_report.sh --sdk=FirebaseDynamicLinks --platform=${{ matrix.target }} - - uses: actions/upload-artifact@v4 - with: - name: codecoverage - path: /Users/runner/*.xcresult - pod-lib-lint-firestore: needs: check # Don't run on private repo unless it is a PR. @@ -317,7 +293,7 @@ jobs: path: /Users/runner/*.xcresult create_report: - needs: [check, pod-lib-lint-abtesting, pod-lib-lint-auth, pod-lib-lint-database, pod-lib-lint-dynamiclinks, pod-lib-lint-firestore, pod-lib-lint-functions, pod-lib-lint-inappmessaging, pod-lib-lint-messaging, pod-lib-lint-performance, pod-lib-lint-remoteconfig, pod-lib-lint-storage] + needs: [check, pod-lib-lint-abtesting, pod-lib-lint-auth, pod-lib-lint-database, pod-lib-lint-firestore, pod-lib-lint-functions, pod-lib-lint-inappmessaging, pod-lib-lint-messaging, pod-lib-lint-performance, pod-lib-lint-remoteconfig, pod-lib-lint-storage] if: always() runs-on: macos-14 steps: diff --git a/.github/workflows/zip.yml b/.github/workflows/zip.yml index 2b300b11e86..074fc1a26ad 100644 --- a/.github/workflows/zip.yml +++ b/.github/workflows/zip.yml @@ -196,7 +196,6 @@ jobs: - name: Setup Swift Quickstart run: SAMPLE="$SDK" TARGET="${SDK}Example" NON_FIREBASE_SDKS="FBSDKLoginKit FBSDKCoreKit FBSDKCoreKit_Basics FBAEMKit" scripts/setup_quickstart_framework.sh \ "${HOME}"/ios_frameworks/Firebase/NonFirebaseSDKs/* \ - "${HOME}"/ios_frameworks/Firebase/FirebaseDynamicLinks/* \ "${HOME}"/ios_frameworks/Firebase/GoogleSignIn/* \ "${HOME}"/ios_frameworks/Firebase/FirebaseAuth/* \ "${HOME}"/ios_frameworks/Firebase/FirebaseAnalytics/* @@ -508,7 +507,6 @@ jobs: - uses: actions/checkout@v4 - name: Setup quickstart run: SAMPLE="$SDK" TARGET="${SDK}Example" scripts/setup_quickstart_framework.sh \ - "${HOME}"/ios_frameworks/Firebase/FirebaseDynamicLinks/* \ "${HOME}"/ios_frameworks/Firebase/FirebaseInAppMessaging/* \ "${HOME}"/ios_frameworks/Firebase/FirebaseAnalytics/* - name: Xcode From 6b011adbd416f0ac0e8202540312e3bb71782270 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 11:58:50 -0400 Subject: [PATCH 03/16] remove from issue and fr forms --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 1 - .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 0bf195312d7..37f30027362 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -76,7 +76,6 @@ body: - Crashlytics - Database - Data Connect - - DynamicLinks - Firestore - Functions - In-App Messaging diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml index 61b4fe2ebd3..5b1a38a0b07 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -56,7 +56,6 @@ body: - Crashlytics - Database - Data Connect - - DynamicLinks - Firestore - Functions - In-App Messaging From b1dc3609d22c37190e9eacfc622e435431b354ec Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:00:39 -0400 Subject: [PATCH 04/16] Remove podspec --- FirebaseDynamicLinks.podspec | 60 ------------------------------------ 1 file changed, 60 deletions(-) delete mode 100644 FirebaseDynamicLinks.podspec diff --git a/FirebaseDynamicLinks.podspec b/FirebaseDynamicLinks.podspec deleted file mode 100644 index 5ad9a08caa3..00000000000 --- a/FirebaseDynamicLinks.podspec +++ /dev/null @@ -1,60 +0,0 @@ -Pod::Spec.new do |s| - s.name = 'FirebaseDynamicLinks' - s.version = '11.15.0' - s.summary = 'Firebase Dynamic Links' - - s.description = <<-DESC -Firebase Dynamic Links are deep links that enhance user experience and increase engagement by retaining context post-install, across platforms. - DESC - - s.homepage = 'https://firebase.google.com' - s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } - s.authors = 'Google, Inc.' - - s.source = { - :git => 'https://github.com/firebase/firebase-ios-sdk.git', - :tag => 'CocoaPods-' + s.version.to_s - } - s.social_media_url = 'https://twitter.com/Firebase' - s.ios.deployment_target = '13.0' - - s.swift_version = '5.9' - - # See https://firebase.google.com/support/dynamic-links-faq - s.deprecated = true - - s.cocoapods_version = '>= 1.12.0' - s.prefix_header_file = false - - s.source_files = [ - 'FirebaseDynamicLinks/Sources/**/*.[mh]', - 'Interop/Analytics/Public/*.h', - 'FirebaseCore/Extension/*.h', - ] - s.public_header_files = 'FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/*.h' - s.resource_bundles = { - "#{s.module_name}_Privacy" => 'FirebaseDynamicLinks/Sources/Resources/PrivacyInfo.xcprivacy' - } - s.frameworks = 'QuartzCore' - s.weak_framework = 'WebKit' - s.dependency 'FirebaseCore', '~> 11.15.0' - - s.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'FIRDynamicLinks3P GIN_SCION_LOGGING', - 'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}"' - } - - s.test_spec 'unit' do |unit_tests| - unit_tests.scheme = { :code_coverage => true } - unit_tests.source_files = [ - 'FirebaseDynamicLinks/Tests/Unit/*.[mh]', - ] - unit_tests.requires_app_host = true - unit_tests.resources = 'FirebaseDynamicLinks/Tests/Unit/GoogleService-Info.plist', - # Supply plist for custom domain testing. - 'FirebaseDynamicLinks/Tests/Unit/DL-Info.plist' - unit_tests.dependency 'OCMock' - unit_tests.dependency 'GoogleUtilities/MethodSwizzler', '~> 8.1' - unit_tests.dependency 'GoogleUtilities/SwizzlerTestHelpers', '~> 8.1' - end -end From 8eb157adefe57ebfa13db5ac4548f1e476a80f57 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:01:26 -0400 Subject: [PATCH 05/16] remove from Carthage.md --- Carthage.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Carthage.md b/Carthage.md index d9c8a144c6e..7e8bbfc90a6 100644 --- a/Carthage.md +++ b/Carthage.md @@ -39,7 +39,6 @@ binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAppDistributionBi binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAuthBinary.json" binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseCrashlyticsBinary.json" binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseDatabaseBinary.json" -binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseDynamicLinksBinary.json" binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseFirestoreBinary.json" binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseFunctionsBinary.json" binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseGoogleSignInBinary.json" From 5ec8ee5ec21c71fb825cb2690fe1a3182d817b1d Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:03:43 -0400 Subject: [PATCH 06/16] CoreOnly --- CoreOnly/NOTICES | 1 - CoreOnly/Sources/Firebase.h | 4 ---- 2 files changed, 5 deletions(-) diff --git a/CoreOnly/NOTICES b/CoreOnly/NOTICES index 2442b90fb98..01a6bf30bda 100644 --- a/CoreOnly/NOTICES +++ b/CoreOnly/NOTICES @@ -10,7 +10,6 @@ FirebaseAuthInterop FirebaseCore FirebaseCoreExtension FirebaseCoreInternal -FirebaseDynamicLinks FirebaseFunctions FirebaseInAppMessaging FirebaseInstallations diff --git a/CoreOnly/Sources/Firebase.h b/CoreOnly/Sources/Firebase.h index 37d5f9e495c..5262bb4b607 100755 --- a/CoreOnly/Sources/Firebase.h +++ b/CoreOnly/Sources/Firebase.h @@ -49,10 +49,6 @@ #import #endif - #if __has_include() - #import - #endif - #if __has_include() #import #endif From 55a1d9e7a8b11da802fdaadf7f85a050e606a587 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:03:54 -0400 Subject: [PATCH 07/16] Firebase.podspec --- Firebase.podspec | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Firebase.podspec b/Firebase.podspec index 2417f0dcb38..007b7ebfe9c 100644 --- a/Firebase.podspec +++ b/Firebase.podspec @@ -138,12 +138,6 @@ Simplify your app development, grow your user base, and monetize more effectivel ss.watchos.deployment_target = '7.0' end - s.subspec 'DynamicLinks' do |ss| - ss.dependency 'Firebase/CoreOnly' - ss.ios.dependency 'FirebaseDynamicLinks', '~> 11.15.0' - ss.ios.deployment_target = '13.0' - end - s.subspec 'Firestore' do |ss| ss.dependency 'Firebase/CoreOnly' ss.dependency 'FirebaseFirestore', '~> 11.15.0' From e3cb14446705decec0c7be2e5939a1d9bf9de6e8 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:21:01 -0400 Subject: [PATCH 08/16] add changelog --- FirebaseCore/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/FirebaseCore/CHANGELOG.md b/FirebaseCore/CHANGELOG.md index 33bf5733e7b..927e991400a 100644 --- a/FirebaseCore/CHANGELOG.md +++ b/FirebaseCore/CHANGELOG.md @@ -1,4 +1,8 @@ # Unreleased +- [removed] **Breaking change**: FirebaseDynamicLinks has been removed. See + https://firebase.google.com/support/dynamic-links-faq for more info. + +# Firebase 11.15.0 - [fixed] Remove c99 as the required C language standard. (#14950) # Firebase 11.12.0 From 64cebfa6e1235e1a19cdc860248449ea0741fa3c Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:25:52 -0400 Subject: [PATCH 09/16] Remove spm wrapper dir --- .../FirebaseDynamicLinksWrap/dummy.m | 18 ------------------ .../FirebaseDynamicLinksWrap/include/dummy.h | 15 --------------- 2 files changed, 33 deletions(-) delete mode 100644 SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/dummy.m delete mode 100644 SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/include/dummy.h diff --git a/SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/dummy.m b/SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/dummy.m deleted file mode 100644 index c7b9e82f08a..00000000000 --- a/SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/dummy.m +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#import -#if !TARGET_OS_IOS -#warning "Firebase Dynamic Links only supports the iOS platform" -#endif diff --git a/SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/include/dummy.h b/SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/include/dummy.h deleted file mode 100644 index 5224d0b2249..00000000000 --- a/SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap/include/dummy.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Prevent a missing umbrella header warning. From d07d19a8590e212de91c0fbf770eeafb451e1239 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:26:03 -0400 Subject: [PATCH 10/16] CoreOnly 2 --- CoreOnly/Tests/FirebasePodTest/FirebasePodTest/AppDelegate.swift | 1 - CoreOnly/Tests/FirebasePodTest/Podfile | 1 - 2 files changed, 2 deletions(-) diff --git a/CoreOnly/Tests/FirebasePodTest/FirebasePodTest/AppDelegate.swift b/CoreOnly/Tests/FirebasePodTest/FirebasePodTest/AppDelegate.swift index 6470841c297..4ae7852f591 100644 --- a/CoreOnly/Tests/FirebasePodTest/FirebasePodTest/AppDelegate.swift +++ b/CoreOnly/Tests/FirebasePodTest/FirebasePodTest/AppDelegate.swift @@ -25,7 +25,6 @@ class AuthExists: Auth {} // Uncomment next line if ABTesting gets added to Firebase.h. // class ABTestingExists : LifecycleEvents {} class DatabaseExists: Database {} -class DynamicLinksExists: DynamicLinks {} class FirestoreExists: Firestore {} class FunctionsExists: Functions {} class InAppMessagingExists: InAppMessaging {} diff --git a/CoreOnly/Tests/FirebasePodTest/Podfile b/CoreOnly/Tests/FirebasePodTest/Podfile index f96f6219677..238756b7569 100644 --- a/CoreOnly/Tests/FirebasePodTest/Podfile +++ b/CoreOnly/Tests/FirebasePodTest/Podfile @@ -16,7 +16,6 @@ target 'FirebasePodTest' do pod 'FirebaseCore', :path => '../../../' pod 'FirebaseCrashlytics', :path => '../../../' pod 'FirebaseDatabase', :path => '../../../' - pod 'FirebaseDynamicLinks', :path => '../../../' pod 'FirebaseFirestore', :path => '../../../' pod 'FirebaseFirestoreInternal', :path => '../../../' pod 'FirebaseFunctions', :path => '../../../' From fdea9718b8507b394649430253d00a11b15ce7e8 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:26:19 -0400 Subject: [PATCH 11/16] Package.swift --- Package.swift | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/Package.swift b/Package.swift index f82fa0e8222..edf7aa23344 100644 --- a/Package.swift +++ b/Package.swift @@ -108,10 +108,6 @@ let package = Package( name: "FirebaseDatabase", targets: ["FirebaseDatabase"] ), - .library( - name: "FirebaseDynamicLinks", - targets: ["FirebaseDynamicLinksTarget"] - ), .library( name: "FirebaseFirestore", targets: ["FirebaseFirestoreTarget"] @@ -777,28 +773,6 @@ let package = Package( dependencies: ["FirebaseSharedSwift"], path: "FirebaseSharedSwift/Tests/" ), - .target( - name: "FirebaseDynamicLinksTarget", - dependencies: [.target(name: "FirebaseDynamicLinks", - condition: .when(platforms: [.iOS]))], - path: "SwiftPM-PlatformExclude/FirebaseDynamicLinksWrap" - ), - - .target( - name: "FirebaseDynamicLinks", - dependencies: ["FirebaseCore"], - path: "FirebaseDynamicLinks/Sources", - resources: [.process("Resources/PrivacyInfo.xcprivacy")], - publicHeadersPath: "Public", - cSettings: [ - .headerSearchPath("../../"), - .define("FIRDynamicLinks3P", to: "1"), - .define("GIN_SCION_LOGGING", to: "1"), - ], - linkerSettings: [ - .linkedFramework("QuartzCore"), - ] - ), firestoreWrapperTarget(), From c4d4b958b67444b343e5cc56ff61456d81ecd896 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:26:32 -0400 Subject: [PATCH 12/16] Various infra --- Dangerfile | 5 ----- .../Sources/FirebaseManifest/FirebaseManifest.swift | 1 - SymbolCollisionTest/Podfile | 1 - docs/ContinuousIntegration.md | 2 +- scripts/api_diff_report/icore_module.py | 1 - scripts/change_headers.swift | 2 +- scripts/check_imports.swift | 1 - scripts/health_metrics/file_patterns.json | 9 --------- scripts/health_metrics/pod_test_code_coverage_report.sh | 2 -- scripts/make_release_notes.py | 1 - 10 files changed, 2 insertions(+), 23 deletions(-) diff --git a/Dangerfile b/Dangerfile index 1438a1d1010..6e6cb1ce057 100644 --- a/Dangerfile +++ b/Dangerfile @@ -55,7 +55,6 @@ def labelsForModifiedFiles() labels.push("api: core") if @has_core_changes labels.push("api: crashlytics") if @has_crashlytics_changes labels.push("api: database") if @has_database_changes - labels.push("api: dynamiclinks") if @has_dynamiclinks_changes labels.push("api: firebaseai") if @has_firebaseai_changes labels.push("api: firestore") if @has_firestore_changes labels.push("api: functions") if @has_functions_changes @@ -93,7 +92,6 @@ has_license_changes = didModify(["LICENSE"]) "Core", "Crashlytics", "Database", - "DynamicLinks", "FirebaseAI", "Firestore", "Functions", @@ -132,8 +130,6 @@ has_license_changes = didModify(["LICENSE"]) @has_crashlytics_api_changes = hasChangesIn("Crashlytics/Crashlytics/Public/") @has_database_changes = hasChangesIn("FirebaseDatabase") @has_database_api_changes = hasChangesIn("FirebaseDatabase/Sources/Public/") -@has_dynamiclinks_changes = hasChangesIn("FirebaseDynamicLinks") -@has_dynamiclinks_api_changes = hasChangesIn("FirebaseDynamicLinks/Sources/Public/") @has_firebaseai_changes = hasChangesIn([ "FirebaseAI", "FirebaseVertexAI" @@ -168,7 +164,6 @@ has_license_changes = didModify(["LICENSE"]) @has_core_api_changes || @has_crashlytics_api_changes || @has_database_api_changes || - @has_dynamiclinks_api_changes || @has_firestore_api_changes || @has_functions_api_changes || @has_inappmessaging_api_changes || diff --git a/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift b/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift index ae578987656..d807ec0e69e 100755 --- a/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift +++ b/ReleaseTooling/Sources/FirebaseManifest/FirebaseManifest.swift @@ -45,7 +45,6 @@ public let shared = Manifest( Pod("FirebaseAuth", zip: true), Pod("FirebaseCrashlytics", zip: true), Pod("FirebaseDatabase", platforms: ["ios", "macos", "tvos"], zip: true), - Pod("FirebaseDynamicLinks", allowWarnings: true, platforms: ["ios"], zip: true), Pod("FirebaseFirestoreInternal", allowWarnings: true, platforms: ["ios", "macos", "tvos"]), Pod("FirebaseFirestore", allowWarnings: true, platforms: ["ios", "macos", "tvos"], zip: true), Pod("FirebaseFunctions", zip: true), diff --git a/SymbolCollisionTest/Podfile b/SymbolCollisionTest/Podfile index 95dfd255f4c..e0047ee2631 100644 --- a/SymbolCollisionTest/Podfile +++ b/SymbolCollisionTest/Podfile @@ -18,7 +18,6 @@ target 'SymbolCollisionTest' do pod 'FirebaseCoreInternal', :path => '../' pod 'FirebaseCrashlytics', :path => '../' pod 'FirebaseDatabase', :path => '../' - pod 'FirebaseDynamicLinks', :path => '../' pod 'FirebaseFirestore', :path => '../' pod 'FirebaseFunctions', :path => '../' pod 'FirebaseInAppMessaging', :path => '../' diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md index 40f8d85b99c..3ea518ee4a8 100644 --- a/docs/ContinuousIntegration.md +++ b/docs/ContinuousIntegration.md @@ -97,7 +97,7 @@ repo. The previous setup will run podspecs testing nightly. This enables presubmits of pod spec lint podspecs and accelerates the testing process. This is to run presubmit tests for Firebase Apple SDKs in the SDK repo. A job to run `pod spec lint` is added to SDK testing workflows, including ABTesting, -Analytics, Auth, Core, Crashlytics, Database, DynamicLinks, Firestore, Functions, GoogleUtilities, +Analytics, Auth, Core, Crashlytics, Database, Firestore, Functions, GoogleUtilities, InAppMessaging, Installations, Messaging, MLModelDownloader, Performance, RemoteConfig and Storage. These jobs will be triggered in presubmit and run pod spec lint with a source of Firebase/SpecsTesting repo, which is updated to the head of main nightly in the prerelease diff --git a/scripts/api_diff_report/icore_module.py b/scripts/api_diff_report/icore_module.py index 313180c14a1..4e088347956 100644 --- a/scripts/api_diff_report/icore_module.py +++ b/scripts/api_diff_report/icore_module.py @@ -31,7 +31,6 @@ 'FirebaseCore', 'FirebaseCrashlytics', 'FirebaseDatabase', - 'FirebaseDynamicLinks', 'FirebaseFirestoreInternal', 'FirebaseFirestore', 'FirebaseFunctions', diff --git a/scripts/change_headers.swift b/scripts/change_headers.swift index ee6f1c44b02..80beb9dbcaa 100755 --- a/scripts/change_headers.swift +++ b/scripts/change_headers.swift @@ -25,7 +25,7 @@ let findHeaders = ["FirebaseMessaging"] // Update with directories in which to change imports. let changeImports = ["GoogleUtilities", "FirebaseAuth", "FirebaseCore", "Firebase", "FirebaseDatabase", "GoogleDataTransport", - "FirebaseDynamicLinks", "FirebaseInAppMessaging", "FirebaseMessaging", + "FirebaseInAppMessaging", "FirebaseMessaging", "FirebaseRemoteConfig", "FirebaseInstallations", "FirebaseFunctions", "FirebaseABTesting", "FirebaseAppDistribution", "Example", "Crashlytics", "FirebaseStorage"] diff --git a/scripts/check_imports.swift b/scripts/check_imports.swift index b21af3fcd4c..6f5e5a9ebb3 100755 --- a/scripts/check_imports.swift +++ b/scripts/check_imports.swift @@ -25,7 +25,6 @@ import Foundation // Skip these directories. Imports should only be repo-relative in libraries // and unit tests. let skipDirPatterns = ["/Sample/", "/Pods/", - "FirebaseDynamicLinks/Tests/Integration", "FirebaseInAppMessaging/Tests/Integration/", "FirebaseAuth/", // TODO: Turn Combine back on without Auth includes. diff --git a/scripts/health_metrics/file_patterns.json b/scripts/health_metrics/file_patterns.json index 4b488a28df3..ad7840f354d 100644 --- a/scripts/health_metrics/file_patterns.json +++ b/scripts/health_metrics/file_patterns.json @@ -66,15 +66,6 @@ "FirebaseAuth/Interop/[^/]+\\.h" ] }, - { - "sdk": "dynamiclinks", - "podspecs": ["FirebaseDynamicLinks.podspec"], - "filePatterns": [ - "^FirebaseDynamicLinks.*", - "\\.github/workflows/dynamiclinks\\.yml", - "Interop/Analytics/Public/[^/]+\\.h" - ] - }, { "sdk": "firebase", "podspecs": ["Firebase.podspec"], diff --git a/scripts/health_metrics/pod_test_code_coverage_report.sh b/scripts/health_metrics/pod_test_code_coverage_report.sh index ff742a89965..1908c92d0d6 100755 --- a/scripts/health_metrics/pod_test_code_coverage_report.sh +++ b/scripts/health_metrics/pod_test_code_coverage_report.sh @@ -60,8 +60,6 @@ if [ $SDK == "FirebasePerformance" ]; then elif [ $SDK == "FirebaseFirestore" ]; then scripts/install_prereqs.sh Firestore ${PLATFORM} xcodebuild scripts/third_party/travis/retry.sh scripts/build.sh Firestore ${PLATFORM} xcodebuild -elif [ $SDK == "FirebaseDynamicLinks" ]; then - scripts/third_party/travis/retry.sh scripts/pod_lib_lint.rb "${SDK}".podspec --verbose --allow-warnings --platforms="$(tr '[:upper:]' '[:lower:]'<<<${PLATFORM})" --test-specs="${TEST_SPEC}" else # Run unit tests of pods and put xcresult bundles into OUTPUT_PATH, which # should be a targeted dir of actions/upload-artifact in workflows. diff --git a/scripts/make_release_notes.py b/scripts/make_release_notes.py index a372940e4bd..5e11a9ea12f 100755 --- a/scripts/make_release_notes.py +++ b/scripts/make_release_notes.py @@ -34,7 +34,6 @@ 'FirebaseCore/CHANGELOG.md': NO_HEADING, 'Crashlytics/CHANGELOG.md': '{{crashlytics}}', 'FirebaseDatabase/CHANGELOG.md': '{{database}}', - 'FirebaseDynamicLinks/CHANGELOG.md': '{{ddls}}', 'FirebaseInAppMessaging/CHANGELOG.md': '{{inapp_messaging}}', 'FirebaseInstallations/CHANGELOG.md': 'Installations', 'FirebaseMessaging/CHANGELOG.md': '{{messaging}}', From 57e4533c5fa4e228758a6a97b6922c93c9415f8d Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:50:36 -0400 Subject: [PATCH 13/16] more test changes --- .../ClientApp/ClientApp.xcodeproj/project.pbxproj | 7 ------- IntegrationTesting/ClientApp/Podfile | 1 - .../ClientApp/Shared/objc-header-import-test.m | 4 ---- .../ClientApp/Shared/objc-module-import-test.m | 3 --- .../ClientApp/Shared/objcxx-header-import-test.mm | 4 ---- .../ClientApp/Shared/swift-import-test.swift | 3 --- .../Cocoapods_multiprojects_frameworks/Podfile | 1 - Package.swift | 2 -- SwiftPMTests/objc-import-test/objc-header.m | 2 -- SwiftPMTests/objc-import-test/objc-module.m | 1 - SwiftPMTests/swift-test/all-imports.swift | 1 - 11 files changed, 29 deletions(-) diff --git a/IntegrationTesting/ClientApp/ClientApp.xcodeproj/project.pbxproj b/IntegrationTesting/ClientApp/ClientApp.xcodeproj/project.pbxproj index 645924782b1..363cc8ff7cb 100644 --- a/IntegrationTesting/ClientApp/ClientApp.xcodeproj/project.pbxproj +++ b/IntegrationTesting/ClientApp/ClientApp.xcodeproj/project.pbxproj @@ -29,7 +29,6 @@ EA7DF58D29EF3326005664A7 /* FirebaseAppDistribution-Beta in Frameworks */ = {isa = PBXBuildFile; platformFilter = ios; productRef = EA7DF58C29EF3326005664A7 /* FirebaseAppDistribution-Beta */; }; EA7DF59329EF3326005664A7 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = EA7DF59229EF3326005664A7 /* FirebaseCrashlytics */; }; EA7DF59529EF3326005664A7 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = EA7DF59429EF3326005664A7 /* FirebaseDatabase */; }; - EA7DF59929EF3326005664A7 /* FirebaseDynamicLinks in Frameworks */ = {isa = PBXBuildFile; platformFilter = ios; productRef = EA7DF59829EF3326005664A7 /* FirebaseDynamicLinks */; }; EA7DF59B29EF3326005664A7 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = EA7DF59A29EF3326005664A7 /* FirebaseFirestore */; }; EA7DF59D29EF3326005664A7 /* FirebaseFirestoreCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = EA7DF59C29EF3326005664A7 /* FirebaseFirestoreCombine-Community */; }; EA7DF5A129EF3327005664A7 /* FirebaseFunctions in Frameworks */ = {isa = PBXBuildFile; productRef = EA7DF5A029EF3327005664A7 /* FirebaseFunctions */; }; @@ -81,7 +80,6 @@ EA7DF5A129EF3327005664A7 /* FirebaseFunctions in Frameworks */, EA7DF58D29EF3326005664A7 /* FirebaseAppDistribution-Beta in Frameworks */, EA7DF5AF29EF3328005664A7 /* FirebasePerformance in Frameworks */, - EA7DF59929EF3326005664A7 /* FirebaseDynamicLinks in Frameworks */, EA7DF59D29EF3326005664A7 /* FirebaseFirestoreCombine-Community in Frameworks */, EA7DF5A929EF3327005664A7 /* FirebaseInstallations in Frameworks */, ); @@ -203,7 +201,6 @@ EA7DF58C29EF3326005664A7 /* FirebaseAppDistribution-Beta */, EA7DF59229EF3326005664A7 /* FirebaseCrashlytics */, EA7DF59429EF3326005664A7 /* FirebaseDatabase */, - EA7DF59829EF3326005664A7 /* FirebaseDynamicLinks */, EA7DF59A29EF3326005664A7 /* FirebaseFirestore */, EA7DF59C29EF3326005664A7 /* FirebaseFirestoreCombine-Community */, EA7DF5A029EF3327005664A7 /* FirebaseFunctions */, @@ -661,10 +658,6 @@ isa = XCSwiftPackageProductDependency; productName = FirebaseDatabase; }; - EA7DF59829EF3326005664A7 /* FirebaseDynamicLinks */ = { - isa = XCSwiftPackageProductDependency; - productName = FirebaseDynamicLinks; - }; EA7DF59A29EF3326005664A7 /* FirebaseFirestore */ = { isa = XCSwiftPackageProductDependency; productName = FirebaseFirestore; diff --git a/IntegrationTesting/ClientApp/Podfile b/IntegrationTesting/ClientApp/Podfile index 9a2a124703f..43ffaf35960 100644 --- a/IntegrationTesting/ClientApp/Podfile +++ b/IntegrationTesting/ClientApp/Podfile @@ -22,7 +22,6 @@ target 'ClientApp-CocoaPods' do pod 'FirebaseAuth', :path => '../../' pod 'FirebaseCrashlytics', :path => '../../' pod 'FirebaseDatabase', :path => '../../' - pod 'FirebaseDynamicLinks', :path => '../../' pod 'FirebaseFirestore', :path => '../../' pod 'FirebaseFirestoreInternal', :path => '../../' pod 'FirebaseFunctions', :path => '../../' diff --git a/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m b/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m index 83727384a57..6a214124f25 100644 --- a/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m +++ b/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m @@ -34,10 +34,6 @@ #import "FirebaseCore/FirebaseCore.h" #import "FirebaseCrashlytics/FirebaseCrashlytics.h" #import "FirebaseDatabase/FirebaseDatabase.h" -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST -#import -#import "FirebaseDynamicLinks/FirebaseDynamicLinks.h" -#endif #import #import #import diff --git a/IntegrationTesting/ClientApp/Shared/objc-module-import-test.m b/IntegrationTesting/ClientApp/Shared/objc-module-import-test.m index e465a83c86a..0b334f4aace 100644 --- a/IntegrationTesting/ClientApp/Shared/objc-module-import-test.m +++ b/IntegrationTesting/ClientApp/Shared/objc-module-import-test.m @@ -27,9 +27,6 @@ @import FirebaseAuth; @import FirebaseCore; @import FirebaseCrashlytics; -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST -@import FirebaseDynamicLinks; -#endif #if (TARGET_OS_IOS && !TARGET_OS_MACCATALYST) || TARGET_OS_TV @import FirebasePerformance; @import FirebaseInAppMessaging; diff --git a/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm b/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm index 4bb988bbfb6..3585fa057f7 100644 --- a/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm +++ b/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm @@ -37,10 +37,6 @@ #import "FirebaseCore/FirebaseCore.h" #import "FirebaseCrashlytics/FirebaseCrashlytics.h" #import "FirebaseDatabase/FirebaseDatabase.h" -#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST -#import -#import "FirebaseDynamicLinks/FirebaseDynamicLinks.h" -#endif #import #import #import diff --git a/IntegrationTesting/ClientApp/Shared/swift-import-test.swift b/IntegrationTesting/ClientApp/Shared/swift-import-test.swift index 2965a289ab5..25cb2f01962 100644 --- a/IntegrationTesting/ClientApp/Shared/swift-import-test.swift +++ b/IntegrationTesting/ClientApp/Shared/swift-import-test.swift @@ -32,9 +32,6 @@ import FirebaseAuth import FirebaseCore import FirebaseCrashlytics import FirebaseDatabase -#if os(iOS) && !targetEnvironment(macCatalyst) - import FirebaseDynamicLinks -#endif import FirebaseFirestore #if SWIFT_PACKAGE import FirebaseFirestoreCombineSwift diff --git a/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile b/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile index cf2128071c6..e422c6b350c 100644 --- a/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile +++ b/IntegrationTesting/CocoapodsIntegrationTest/TestEnvironments/Cocoapods_multiprojects_frameworks/Podfile @@ -18,7 +18,6 @@ target 'CocoapodsIntegrationTest' do pod 'FirebaseAuth', :path => '../../' pod 'FirebaseAuthInterop', :path => '../../' pod 'FirebaseDatabase', :path => '../../' - pod 'FirebaseDynamicLinks', :path => '../../' pod 'FirebaseFirestore', :path => '../../' pod 'FirebaseFunctions', :path => '../../' pod 'FirebaseInAppMessaging', :path => '../../' diff --git a/Package.swift b/Package.swift index edf7aa23344..4229d69632c 100644 --- a/Package.swift +++ b/Package.swift @@ -1266,7 +1266,6 @@ let package = Package( "FirebaseCrashlytics", "FirebaseCore", "FirebaseDatabase", - "FirebaseDynamicLinks", "FirebaseFirestoreTarget", "FirebaseFunctions", .target(name: "FirebaseInAppMessaging", @@ -1302,7 +1301,6 @@ let package = Package( "FirebaseCrashlytics", "FirebaseCore", "FirebaseDatabase", - "FirebaseDynamicLinks", "FirebaseFirestoreTarget", "FirebaseFunctions", .target(name: "FirebaseInAppMessaging", diff --git a/SwiftPMTests/objc-import-test/objc-header.m b/SwiftPMTests/objc-import-test/objc-header.m index b00070f99c7..1e994c3bbd5 100644 --- a/SwiftPMTests/objc-import-test/objc-header.m +++ b/SwiftPMTests/objc-import-test/objc-header.m @@ -21,7 +21,6 @@ #import "FirebaseCore/FirebaseCore.h" #import "FirebaseCrashlytics/FirebaseCrashlytics.h" #import "FirebaseDatabase/FirebaseDatabase.h" -#import "FirebaseDynamicLinks/FirebaseDynamicLinks.h" #import "FirebaseFirestore/FirebaseFirestore.h" #import "FirebaseInstallations/FirebaseInstallations.h" #import "FirebaseMessaging/FirebaseMessaging.h" @@ -40,7 +39,6 @@ #import #import #import -#import #import #if TARGET_OS_IOS || TARGET_OS_TV #import diff --git a/SwiftPMTests/objc-import-test/objc-module.m b/SwiftPMTests/objc-import-test/objc-module.m index 3f60b824127..02ce7ce6539 100644 --- a/SwiftPMTests/objc-import-test/objc-module.m +++ b/SwiftPMTests/objc-import-test/objc-module.m @@ -22,7 +22,6 @@ @import FirebaseCrashlytics; @import FirebaseCore; @import FirebaseDatabase; -@import FirebaseDynamicLinks; @import FirebaseFirestore; @import FirebaseFunctions; @import FirebaseInstallations; diff --git a/SwiftPMTests/swift-test/all-imports.swift b/SwiftPMTests/swift-test/all-imports.swift index e06afa311d4..f7548373f5c 100644 --- a/SwiftPMTests/swift-test/all-imports.swift +++ b/SwiftPMTests/swift-test/all-imports.swift @@ -23,7 +23,6 @@ import Foundation #endif import FirebaseCrashlytics import FirebaseDatabase -import FirebaseDynamicLinks import FirebaseFirestore import FirebaseFunctions import FirebaseInstallations From b035e359239d879418ca27c73a47c5f0281d6903 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:51:39 -0400 Subject: [PATCH 14/16] review --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 1 + FirebaseDynamicLinks/CHANGELOG.md | 200 ++++++++++++++++++++++++++ scripts/make_release_notes.py | 1 + 3 files changed, 202 insertions(+) create mode 100644 FirebaseDynamicLinks/CHANGELOG.md diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 37f30027362..0bf195312d7 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -76,6 +76,7 @@ body: - Crashlytics - Database - Data Connect + - DynamicLinks - Firestore - Functions - In-App Messaging diff --git a/FirebaseDynamicLinks/CHANGELOG.md b/FirebaseDynamicLinks/CHANGELOG.md new file mode 100644 index 00000000000..6983b145e35 --- /dev/null +++ b/FirebaseDynamicLinks/CHANGELOG.md @@ -0,0 +1,200 @@ +# 11.8.0 +- [deprecated] The `FirebaseDynamicLinks` CocoaPod is deprecated. For information about timelines and alternatives, see the [Dynamic Links deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq). + +# 10.27.0 +- [deprecated] Dynamic Links is deprecated. For information about timelines and alternatives, see the [Dynamic Links deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq) + +# 10.3.0 +- [fixed] Fixes issue where `utmParametersDictionary` / `minimumAppVersion` were not provided and their value were set to `[NSNull null]` instead of `nil`. + +# 10.2.0 +- [fixed] Fixes utm parameters not being returned to dynamic link when using universal links (#10341) + +# 10.0.0 +- [removed] Removed bare initializer from `DynamicLink`. (#10000) +- [fixed] Added app.google (1p domain) support in FDL SDK which was missing. + +# 9.0.0 +- [fixed] Fixed async/await crash when retrieving a dynamic link from a universal link fails. (#9612) + +# 8.15.0 +- [fixed] Fixed Custom domain long url validation logic. (#6978) + +# 8.9.0 +- [fixed] Fixed Shortlink regression involving underscores and dashes introduced in 8.8.0. (#8786) +- [fixed] Reduce memory stress on `WebKit` API. (#8847) +- [fixed] Fixed regression introduced in 8.8.0 that failed to accept link query params after the + FDL domain prefix. It caused the Dynamic Links Quick Start to fail. (#8866) + +# 8.8.0 +- [fixed] Firebase dynamic links with custom domain will only work if the custom domain has a trailing '/'. (#7087) +- [fixed] Fix device-only build warning for unused `processIsTranslated` function. (#8694) + +# 8.7.0 +- [added] Refactoring and adding helper class. (#8432) + +# 8.6.0 +- [changed] Replaced conditionally-compiled APIs with `API_UNAVAILABLE` annotations on unsupported platforms (#8467). + +# 8.4.0 +- [fixed] Fixed build issues introduced in Xcode 13 beta 3. (#8401) +- [fixed] Fixed build failures for extension targets. (#6548) + +# 8.2.0 +- [fixed] Fixed analyze issue introduced in Xcode 12.5. (#8208) + +# 8.0.0 +- [fixed] Fixed crashes on simulators targeting below iOS14 on Apple Silicon. (#7989) + +# 7.7.0 +- [added] Added `utmParametersDictionary` property to `DynamicLink`. (#6730) + +# 7.6.0 +- [fixed] Fixed build warnings introduced with Xcode 12.5. (#7434) + +# 7.3.1 +- [fixed] New callback added in 7.3.0 should be on the main thread. (#7159) + +# 7.3.0 +- [added] Manually created dynamic links should be subject to allowed/blocked check (#5853) + +# 4.3.1 +- [changed] Client id usage in api call and respective checks in the code. +- [fixed] Fix attempts to connect to invalid ipv6 domain by updating ipv4 and ipv6 to use a single, valid endpoint (#5032) + +# 4.3.0 +- [changed] Functionally neutral public header refactor to enable Swift Package + Manager support. + +# 4.2.1 +- [fixed]Check for Pending Dynamic link guard check logic + +# 4.2.0 +- [fixed] Fixed crashes that occur when a dynamic link is opened for the second time while an app is in the foreground (#5880) +- [Added] Plist property `FirebaseDeepLinkPasteboardRetrievalEnabled` to enable/disable fetching dynamic links from Pasteboard. +- [fixed] Reduce frequency of iOS14 pasteboard notifications by only reading from it when it contains URL(s). (#5905) +- [changed] Functionally neutral updated import references for dependencies. (#5824) + +Refer to the [README.md](https://github.com/firebase/firebase-ios-sdk/blob/main/FirebaseDynamicLinks/README.md) for more details about this release. + +# 4.1.0 +- [fixed] Fixing unwanted pending dynamic links checks on subsequent app restarts. (#5665) + +# 4.0.8 +- [fixed] Fix Catalyst build - removed deprecated unused Apple framework dependencies. (#5139) + +# 4.0.7 +- [fixed] Use module import syntax for headers from other SDKs. (#4824) + +# 4.0.6 +- [fixed] Fix component startup time. (#4137) +- [fixed] Fix crash due to object deallocation on app launch. (#4308) + +# 4.0.5 +- [fixed] Removed references to UIWebViewDelegate to comply with App Store Submission warning. (#3722) + +# 4.0.4 +- [fixed] Removed references to UIWebView to comply with App Store Submission warning. (#3722) + +# 4.0.3 +- [added] Added support for custom domains for internal Google apps. (#3540) + +# 4.0.2 +- [changed] Updated to maintain compatibility with Firebase Core in 6.6.0. + +# 4.0.1 +- [changed] Removed deprecated internal log method. (#3333) + +# 4.0 +- [feature] FirebaseAnalytics is no longer a hard dependency in the DynamicLinks pod. If you were installing Dynamic Links via pod ''Firebase/DynamicLinks'', you should add 'pod 'Firebase/Analytics'' to the Podfile to maintain full Dynamic Links functionality. If you previously have 'pod 'Firebase/Core'' in the Podfile, no change is necessary. (#2738) +- [removed] Remove deprecated API in FDLURLComponents. (#2768) + +# 3.4.3 +- [fixed] Fixed an issue where matchesshortlinkformat was returning true for certain FDL long links. + +# 3.4.2 +- [fixed] Fixes an issue with certain analytics attribution parameters not being recorded on an app install. (#2462) + +# 3.4.1 +- [changed] Return call validation for sysctlbyname. (#2394) + +# 3.4.0 +- [changed] Bug fixes and internal SDK changes. (#2238, #2220) + +# 3.3.0 +- [added] Introduced a new `componentsWithLink:domainURIPrefix:` and deprecated the existing `componentsWithLink:domain:`. (#1962, #2017, #2078, #2097, #2112) + +# 3.2.0 +- [changed] Delete deprecated source files. (#2038) + +# 3.1.1 +- [changed] Use c99 compatible __typeof__() operator. (#1982) + +# 3.1.0 +- [feature] Firebase Dynamic Links is now open source and delivered as a source pod. (#1842) + +# 3.0.2 +- [changed] Bug fixes. + +# 3.0.1 +- [fixed] Fixed issue where first app opens were getting double counted when using unique match. + +# 2.3.2 +- [fixed] Fixed error when fingerprint match fails for some locales. + +# 2.3.1 +- [fixed] Fixed race condition while processing server response(s). + +# 2.3.0 +- [added] Added new confidence type property. See FIRDLMatchType (values Unique, Default, Weak); +- [changed] Updates to self diagnostic output. + +# 2.2.0 +- [added] Added Other platform fallback link to FDL Builder API; + +# 2.1.0 +- [added] Added basic self diagnostic to identify Firebase Dynamic Links configuration issues. See method + [FIRDynamicLinks performDiagnosticsWithCompletion:]. +- [fixed] Fixed returning warning in Builder API, see warnings parameter in + FIRDynamicLinkShortenerCompletion block. + +# 2.0.0 +- [fixed] Change Swift API names to better align with Swift convention. +- [fixed] Fixes to pending link retrieval process, especially when custom URL schemes are not + set up properly. + +# 1.4.0 +- [added] Added Builder API to create and shorten dynamic links in iOS Apps. + +# 1.3.5 +- [changed] Minor update triggered by changes in Firebase Core libraries. + +# 1.3.4 +- [changed] Bug fixes + +# 1.3.3 +- [changed] Improved tracking of social media tag parameters in Dynamic Links + +# 1.3.2 +- [changed] Removes dependency on the Core Motion framework + +# 1.3.1 +- [added] Adds FIRLogger support (not public-facing) +- [fixed] Fixes IPv6 compatibility issues + +# 1.3.0 +- [changed] Removes the SFSafariViewController per Apple's Review Guidelines +- [changed] Removes dependency on the Core Location framework + +# 1.2.0 +- [added] iOS 10 Support + +# 1.1.1 +- [fixed] Fixes an issue where if resolveLink() API returned a non-JSON object, it + would cause a crash. + +# 1.1.0 +- [fixed] Greatly reduced SDK size. + +# 1.0.0 +- Initial public release. diff --git a/scripts/make_release_notes.py b/scripts/make_release_notes.py index 5e11a9ea12f..a372940e4bd 100755 --- a/scripts/make_release_notes.py +++ b/scripts/make_release_notes.py @@ -34,6 +34,7 @@ 'FirebaseCore/CHANGELOG.md': NO_HEADING, 'Crashlytics/CHANGELOG.md': '{{crashlytics}}', 'FirebaseDatabase/CHANGELOG.md': '{{database}}', + 'FirebaseDynamicLinks/CHANGELOG.md': '{{ddls}}', 'FirebaseInAppMessaging/CHANGELOG.md': '{{inapp_messaging}}', 'FirebaseInstallations/CHANGELOG.md': 'Installations', 'FirebaseMessaging/CHANGELOG.md': '{{messaging}}', From 1f00217d5045b3e1cb6c0497d6e930a1998e2e0b Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 12:54:52 -0400 Subject: [PATCH 15/16] add changelog entry in fdl --- FirebaseDynamicLinks/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/FirebaseDynamicLinks/CHANGELOG.md b/FirebaseDynamicLinks/CHANGELOG.md index 6983b145e35..5734ac9812b 100644 --- a/FirebaseDynamicLinks/CHANGELOG.md +++ b/FirebaseDynamicLinks/CHANGELOG.md @@ -1,3 +1,7 @@ +# 12.0.0 +- [removed] **Breaking change**: FirebaseDynamicLinks has been removed. See + https://firebase.google.com/support/dynamic-links-faq for more info. + # 11.8.0 - [deprecated] The `FirebaseDynamicLinks` CocoaPod is deprecated. For information about timelines and alternatives, see the [Dynamic Links deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq). From 62611537a2d24e79d697d85074ba3ed545a89625 Mon Sep 17 00:00:00 2001 From: Nick Cooke Date: Fri, 13 Jun 2025 13:01:33 -0400 Subject: [PATCH 16/16] style 1 --- .../ClientApp/Shared/objc-header-import-test.m | 6 +++--- .../ClientApp/Shared/objcxx-header-import-test.mm | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m b/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m index 6a214124f25..5691ee8df4e 100644 --- a/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m +++ b/IntegrationTesting/ClientApp/Shared/objc-header-import-test.m @@ -31,12 +31,12 @@ #import #import #import -#import "FirebaseCore/FirebaseCore.h" -#import "FirebaseCrashlytics/FirebaseCrashlytics.h" -#import "FirebaseDatabase/FirebaseDatabase.h" #import #import #import +#import "FirebaseCore/FirebaseCore.h" +#import "FirebaseCrashlytics/FirebaseCrashlytics.h" +#import "FirebaseDatabase/FirebaseDatabase.h" #import "FirebaseFirestore/FirebaseFirestore.h" #import "FirebaseInstallations/FirebaseInstallations.h" #import "FirebaseMessaging/FirebaseMessaging.h" diff --git a/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm b/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm index 3585fa057f7..e3b04630a6e 100644 --- a/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm +++ b/IntegrationTesting/ClientApp/Shared/objcxx-header-import-test.mm @@ -34,12 +34,12 @@ #import #import #import -#import "FirebaseCore/FirebaseCore.h" -#import "FirebaseCrashlytics/FirebaseCrashlytics.h" -#import "FirebaseDatabase/FirebaseDatabase.h" #import #import #import +#import "FirebaseCore/FirebaseCore.h" +#import "FirebaseCrashlytics/FirebaseCrashlytics.h" +#import "FirebaseDatabase/FirebaseDatabase.h" #import "FirebaseFirestore/FirebaseFirestore.h" #import "FirebaseInstallations/FirebaseInstallations.h" #import "FirebaseMessaging/FirebaseMessaging.h"