mirror of
https://github.com/firebase/firebase-ios-sdk
synced 2026-11-09 22:36:01 +05:45
[DynamicLinks] Remove library and corresponding infra (#14978)
This commit is contained in:
1 parent
6f603aa162
commit
9f311f2376
104 files changed
+16
-10530
No files matched your search
@@ -56,7 +56,6 @@ body:
|
||||
- Crashlytics
|
||||
- Database
|
||||
- Data Connect
|
||||
- DynamicLinks
|
||||
- Firestore
|
||||
- Functions
|
||||
- In-App Messaging
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -10,7 +10,6 @@ FirebaseAuthInterop
|
||||
FirebaseCore
|
||||
FirebaseCoreExtension
|
||||
FirebaseCoreInternal
|
||||
FirebaseDynamicLinks
|
||||
FirebaseFunctions
|
||||
FirebaseInAppMessaging
|
||||
FirebaseInstallations
|
||||
|
||||
@@ -49,10 +49,6 @@
|
||||
#import <FirebaseDatabase/FirebaseDatabase.h>
|
||||
#endif
|
||||
|
||||
#if __has_include(<FirebaseDynamicLinks/FirebaseDynamicLinks.h>)
|
||||
#import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
|
||||
#endif
|
||||
|
||||
#if __has_include(<FirebaseFirestore/FirebaseFirestore.h>)
|
||||
#import <FirebaseFirestore/FirebaseFirestore.h>
|
||||
#endif
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 => '../../../'
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Unreleased
|
||||
- [removed] **Breaking change**: FirebaseDynamicLinks has been removed. See
|
||||
https://firebase.google.com/support/dynamic-links-faq for more info.
|
||||
- [removed] **Breaking change**: Removed the `Options.deepLinkURLScheme`
|
||||
property. This API was exclusively used by the Dynamic Links SDK, which
|
||||
has been removed.
|
||||
|
||||
@@ -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
|
||||
@@ -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).
|
||||
|
||||
|
||||
@@ -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).
|
||||
@@ -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 <NSObject>
|
||||
@required
|
||||
@property(nonatomic, readonly) NSDictionary<NSString *, NSString *> *dictionaryRepresentation;
|
||||
@end
|
||||
|
||||
@interface FIRDynamicLinkGoogleAnalyticsParameters () <FDLDictionaryRepresenting>
|
||||
@end
|
||||
|
||||
@interface FIRDynamicLinkIOSParameters () <FDLDictionaryRepresenting>
|
||||
@end
|
||||
|
||||
@interface FIRDynamicLinkItunesConnectAnalyticsParameters () <FDLDictionaryRepresenting>
|
||||
@end
|
||||
|
||||
@interface FIRDynamicLinkAndroidParameters () <FDLDictionaryRepresenting>
|
||||
@end
|
||||
|
||||
@interface FIRDynamicLinkSocialMetaTagParameters () <FDLDictionaryRepresenting>
|
||||
@end
|
||||
|
||||
@interface FIRDynamicLinkNavigationInfoParameters () <FDLDictionaryRepresenting>
|
||||
@end
|
||||
|
||||
@interface FIRDynamicLinkOtherPlatformParameters () <FDLDictionaryRepresenting>
|
||||
@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
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#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<NSString *, NSString *> *_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<NSString *, NSString *> *)dictionaryRepresentation {
|
||||
return [_dictionary copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRDynamicLinkIOSParameters {
|
||||
NSMutableDictionary<NSString *, NSString *> *_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<NSString *, NSString *> *)dictionaryRepresentation {
|
||||
return [_dictionary copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRDynamicLinkItunesConnectAnalyticsParameters {
|
||||
NSMutableDictionary<NSString *, NSString *> *_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<NSString *, NSString *> *)dictionaryRepresentation {
|
||||
return [_dictionary copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRDynamicLinkAndroidParameters {
|
||||
NSMutableDictionary<NSString *, NSString *> *_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<NSString *, NSString *> *)dictionaryRepresentation {
|
||||
return [_dictionary copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRDynamicLinkSocialMetaTagParameters {
|
||||
NSMutableDictionary<NSString *, NSString *> *_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<NSString *, NSString *> *)dictionaryRepresentation {
|
||||
return [_dictionary copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRDynamicLinkNavigationInfoParameters {
|
||||
NSMutableDictionary<NSString *, NSString *> *_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<NSString *, NSString *> *)dictionaryRepresentation {
|
||||
return [_dictionary copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FIRDynamicLinkOtherPlatformParameters {
|
||||
NSMutableDictionary<NSString *, NSString *> *_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<NSString *, NSString *> *)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<FDLDictionaryRepresenting>) =
|
||||
^(id<FDLDictionaryRepresenting> _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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@interface FIRDynamicLinkComponentsKeyProvider : NSObject
|
||||
|
||||
+ (nullable NSString *)APIKey;
|
||||
|
||||
@end
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRDynamicLinkNetworking;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Class to encapsulate logic related to retrieving pending dynamic link.
|
||||
*/
|
||||
@interface FIRDLDefaultRetrievalProcessV2 : NSObject <FIRDLRetrievalProcessProtocol>
|
||||
|
||||
- (instancetype)initWithNetworkingService:(FIRDynamicLinkNetworking *)networkingService
|
||||
URLScheme:(NSString *)URLScheme
|
||||
APIKey:(NSString *)APIKey
|
||||
FDLSDKVersion:(NSString *)FDLSDKVersion
|
||||
delegate:(id<FIRDLRetrievalProcessDelegate>)delegate
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
|
||||
#import "FirebaseDynamicLinks/Sources/FIRDLDefaultRetrievalProcessV2.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#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 () <FIRDLJavaScriptExecutorDelegate>
|
||||
|
||||
@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<FIRDLRetrievalProcessDelegate>)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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@class FIRDLJavaScriptExecutor;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FIRDLJavaScriptExecutorDelegate <NSObject>
|
||||
|
||||
- (void)javaScriptExecutor:(FIRDLJavaScriptExecutor *)executor
|
||||
completedExecutionWithResult:(NSString *)result;
|
||||
- (void)javaScriptExecutor:(FIRDLJavaScriptExecutor *)executor failedWithError:(NSError *)error;
|
||||
|
||||
@end
|
||||
|
||||
@interface FIRDLJavaScriptExecutor : NSObject
|
||||
|
||||
- (instancetype)initWithDelegate:(id<FIRDLJavaScriptExecutorDelegate>)delegate
|
||||
script:(NSString *)script;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
#import <WebKit/WebKit.h>
|
||||
|
||||
#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 () <WKNavigationDelegate>
|
||||
@end
|
||||
|
||||
@implementation FIRDLJavaScriptExecutor {
|
||||
__weak id<FIRDLJavaScriptExecutorDelegate> _delegate;
|
||||
NSString *_script;
|
||||
|
||||
// Web view with which to run JavaScript.
|
||||
WKWebView *_wkWebView;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDelegate:(id<FIRDLJavaScriptExecutorDelegate>)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:@"<html><head><script>%@</script></head></html>", _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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
#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<FIRDLRetrievalProcessDelegate>)delegate
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (id<FIRDLRetrievalProcessProtocol>)automaticRetrievalProcess;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#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<FIRDLRetrievalProcessDelegate> _delegate;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNetworkingService:(FIRDynamicLinkNetworking *)networkingService
|
||||
URLScheme:(NSString *)URLScheme
|
||||
APIKey:(NSString *)APIKey
|
||||
FDLSDKVersion:(NSString *)FDLSDKVersion
|
||||
delegate:(id<FIRDLRetrievalProcessDelegate>)delegate {
|
||||
if (self = [super init]) {
|
||||
_networkingService = networkingService;
|
||||
_URLScheme = URLScheme;
|
||||
_APIKey = APIKey;
|
||||
_FDLSDKVersion = FDLSDKVersion;
|
||||
_delegate = delegate;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id<FIRDLRetrievalProcessProtocol>)automaticRetrievalProcess {
|
||||
return [[FIRDLDefaultRetrievalProcessV2 alloc] initWithNetworkingService:_networkingService
|
||||
URLScheme:_URLScheme
|
||||
APIKey:_APIKey
|
||||
FDLSDKVersion:_FDLSDKVersion
|
||||
delegate:_delegate];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif // TARGET_OS_IOS
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FIRDLRetrievalProcessProtocol;
|
||||
@class FIRDLRetrievalProcessResult;
|
||||
|
||||
@protocol FIRDLRetrievalProcessDelegate <NSObject>
|
||||
|
||||
- (void)retrievalProcess:(id<FIRDLRetrievalProcessProtocol>)retrievalProcess
|
||||
completedWithResult:(FIRDLRetrievalProcessResult *)result;
|
||||
|
||||
@end
|
||||
|
||||
@protocol FIRDLRetrievalProcessProtocol <NSObject>
|
||||
|
||||
@property(weak, nonatomic, readonly) id<FIRDLRetrievalProcessDelegate> delegate;
|
||||
|
||||
- (void)retrievePendingDynamicLink;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@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
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
#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<FIRAnalyticsInterop> _Nullable analytics);
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#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<FIRAnalyticsInterop> _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
|
||||
@@ -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<NSString *, id> *parametersDictionary;
|
||||
|
||||
@property(nonatomic, assign, readwrite) FIRDLMatchType matchType;
|
||||
|
||||
- (instancetype)initWithParametersDictionary:(NSDictionary<NSString *, id> *)parametersDictionary;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#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<NSString *, id> *)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<NSString *, id> *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<NSString *, id> *)extractUTMParams:(NSDictionary<NSString *, id> *)parameters {
|
||||
NSMutableDictionary<NSString *, id> *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
|
||||
@@ -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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
#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
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
|
||||
#import "FirebaseDynamicLinks/Sources/Public/FirebaseDynamicLinks/FIRDynamicLinks.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#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 () <FIRDLRetrievalProcessDelegate>
|
||||
|
||||
// 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<FIRAnalyticsInterop> _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 () <FIRDynamicLinksInstanceProvider, FIRLibrary>
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
@implementation FIRDynamicLinks {
|
||||
// User defaults passed.
|
||||
NSUserDefaults *_userDefaults;
|
||||
|
||||
FIRDynamicLinkNetworking *_dynamicLinkNetworking;
|
||||
|
||||
id<FIRDLRetrievalProcessProtocol> _retrievalProcess;
|
||||
}
|
||||
|
||||
#pragma mark - Object lifecycle
|
||||
|
||||
#ifdef FIRDynamicLinks3P
|
||||
|
||||
+ (void)load {
|
||||
[FIRApp registerInternalLibrary:self withName:@"fire-dl"];
|
||||
}
|
||||
|
||||
+ (nonnull NSArray<FIRComponent *> *)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<FIRAnalyticsInterop> 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<FIRAnalyticsInterop>)analytics {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_analytics = analytics;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)dynamicLinks {
|
||||
FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here.
|
||||
id<FIRDynamicLinksInstanceProvider> 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<NSString *, NSString *> *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<UIApplicationDelegate> 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<UIApplicationDelegate>)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<FIRDLRetrievalProcessProtocol>)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:@"<plist" intoString:nil]) {
|
||||
if ([scanner scanUpToString:@"</plist>" intoString:&plistContents]) {
|
||||
plistContents = [plistContents stringByAppendingString:@"</plist>"];
|
||||
}
|
||||
}
|
||||
|
||||
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<UIApplicationDelegate> 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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* @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
|
||||
@@ -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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
// 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
|
||||
@@ -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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
/** 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);
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
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<NSString *> *_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<NSString *> *_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<NSString *> *_Nullable warnings,
|
||||
NSError *_Nullable error))completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
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<NSString *, id> *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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
#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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@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
|
||||
@@ -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"
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyTrackingDomains</key>
|
||||
<array>
|
||||
</array>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyCollectedDataType</key>
|
||||
<string>NSPrivacyCollectedDataTypeOtherDataTypes</string>
|
||||
<key>NSPrivacyCollectedDataTypeLinked</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypeTracking</key>
|
||||
<false/>
|
||||
<key>NSPrivacyCollectedDataTypePurposes</key>
|
||||
<array>
|
||||
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>1C8F.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@interface FDLDeviceHeuristicsHelper : NSObject
|
||||
|
||||
/**
|
||||
* Creates DeviceInfo dictionary based on the provided information.
|
||||
*/
|
||||
+ (NSDictionary<NSString *, NSObject *> *)
|
||||
FDLDeviceInfoDictionaryFromResolutionHeight:(NSInteger)resolutionHeight
|
||||
resolutionWidth:(NSInteger)resolutionWidth
|
||||
locale:(NSString *)locale
|
||||
localeRaw:(NSString *)localeRaw
|
||||
localeFromWebview:(NSString *)localeFromWebView
|
||||
timeZone:(NSString *)timezone
|
||||
modelName:(NSString *)modelName;
|
||||
|
||||
@end
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
@implementation FDLDeviceHeuristicsHelper
|
||||
|
||||
/**
|
||||
* Creates DeviceInfo dictionary based on the provided information.
|
||||
*/
|
||||
+ (NSDictionary<NSString *, NSObject *> *)
|
||||
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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
|
||||
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<NSString *, NSString *> *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 <NSString *, NSString *> 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
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
|
||||
#import "FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.h"
|
||||
|
||||
#import <UIKit/UIDevice.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
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<NSString *, NSString *> *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<NSString *> *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<NSString *, id> *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/<appcode>?<parameters>|.
|
||||
// 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
|
||||
@@ -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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
5B41DB1723E3A71C00929EC5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
5B41DB1923E3A71C00929EC5 /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = "<group>"; };
|
||||
5B41DB1A23E3A71C00929EC5 /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = "<group>"; };
|
||||
5B41DB1C23E3A71C00929EC5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||
5B41DB1D23E3A71C00929EC5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||
5B41DB2023E3A71C00929EC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
5B41DB2223E3A71E00929EC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
5B41DB2523E3A71E00929EC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
5B41DB2723E3A71E00929EC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
5B41DB2823E3A71E00929EC5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
5B41DB2F23E3A7F900929EC5 /* LinkTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LinkTableViewCell.m; sourceTree = "<group>"; };
|
||||
5B41DB3023E3A7F900929EC5 /* LinkTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkTableViewCell.h; sourceTree = "<group>"; };
|
||||
5B41DB3123E3A7F900929EC5 /* ParamTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ParamTableViewCell.m; sourceTree = "<group>"; };
|
||||
5B41DB3223E3A7FA00929EC5 /* ParamTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParamTableViewCell.h; sourceTree = "<group>"; };
|
||||
5B41DB3523E3A8F400929EC5 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
/* 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 = "<group>";
|
||||
};
|
||||
5B41DB0A23E3A71C00929EC5 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B41DB3523E3A8F400929EC5 /* GoogleService-Info.plist */,
|
||||
5B41DB1523E3A71C00929EC5 /* FDLBuilderTestAppObjC */,
|
||||
5B41DB1423E3A71C00929EC5 /* Products */,
|
||||
165ECBBDCCBFA3107802A5B8 /* Pods */,
|
||||
8AB095C8794DB7CBE5853D77 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5B41DB1423E3A71C00929EC5 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B41DB1323E3A71C00929EC5 /* FDLBuilderTestAppObjC.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 = "<group>";
|
||||
};
|
||||
8AB095C8794DB7CBE5853D77 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B90D2E2F25A43DD8A8773AF2 /* Pods_FDLBuilderTestAppObjC.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* 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 = "<group>";
|
||||
};
|
||||
5B41DB2423E3A71E00929EC5 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
5B41DB2523E3A71E00929EC5 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* 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 */;
|
||||
}
|
||||
@@ -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 <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property(strong, nonatomic) UIWindow *window;
|
||||
|
||||
@end
|
||||
@@ -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 <FirebaseCore/FirebaseCore.h>
|
||||
#import <FirebaseDynamicLinks/FIRDynamicLinks.h>
|
||||
|
||||
@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<NSString *, id> *)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(<UIKit/UIUserActivity.h>)
|
||||
(void (^)(NSArray<id<UIUserActivityRestoring>> *_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
|
||||
-98
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="UITableView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="132" y="66"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>application-identifier</key>
|
||||
<string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:goo.gl</string>
|
||||
<string>applinks:testfdl.app.goo.gl</string>
|
||||
<string>applinks:testfdl.page.link</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
|
||||
<string>$(AppIdentifierPrefix)$(CFBundleIdentifier).sso</string>
|
||||
<string>$(AppIdentifierPrefix)com.google.common.SSO</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,83 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Dev url scheme</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.google.firebase.dynamiclinks.demo.dev</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>Default Configuration</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>SceneDelegate</string>
|
||||
<key>UISceneStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>FirebaseDynamicLinksCustomDomains</key>
|
||||
<array>
|
||||
<string>https://google.com</string>
|
||||
<string>https://google.com/one/</string>
|
||||
<string>https://a.firebase.com/mypath</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -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 <UIKit/UIKit.h>
|
||||
|
||||
@interface LinkTableViewCell : UITableViewCell <UITextViewDelegate>
|
||||
|
||||
- (void)setTitle:(NSString *)title link:(NSString *)link;
|
||||
|
||||
@end
|
||||
@@ -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
|
||||
@@ -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 <UIKit/UIKit.h>
|
||||
|
||||
@class ParamTableViewCell;
|
||||
|
||||
@protocol ParamTableViewCellDelegate <NSObject>
|
||||
|
||||
- (void)paramTableViewCellUpdatedValue:(ParamTableViewCell *)cell;
|
||||
|
||||
@end
|
||||
|
||||
@interface ParamTableViewCell : UITableViewCell
|
||||
|
||||
@property(nonatomic, readwrite, copy) NSDictionary *paramConfig;
|
||||
@property(nonatomic, readwrite, copy) NSString *textFieldValue;
|
||||
@property(nonatomic, weak) id<ParamTableViewCellDelegate> delegate;
|
||||
|
||||
@end
|
||||
@@ -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
|
||||
@@ -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 <UIKit/UIKit.h>
|
||||
|
||||
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
|
||||
|
||||
@property(strong, nonatomic) UIWindow* window;
|
||||
|
||||
@end
|
||||
@@ -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 <FirebaseDynamicLinks/FIRDynamicLinks.h>
|
||||
|
||||
@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
|
||||
@@ -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 <UIKit/UIKit.h>
|
||||
|
||||
@interface ViewController : UITableViewController
|
||||
|
||||
@end
|
||||
@@ -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 <FirebaseDynamicLinks/FDLURLComponents.h>
|
||||
#import <FirebaseDynamicLinks/FIRDynamicLinks.h>
|
||||
|
||||
#import "LinkTableViewCell.h"
|
||||
#import "ParamTableViewCell.h"
|
||||
|
||||
static NSArray *kParamsConfiguration;
|
||||
|
||||
@interface ViewController () <ParamTableViewCellDelegate>
|
||||
@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
|
||||
@@ -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 <UIKit/UIKit.h>
|
||||
#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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.cocoapods-generate.App-iOS</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>FirebaseDynamicLinksCustomDomains</key>
|
||||
<array>
|
||||
<string>https://google.com</string>
|
||||
<string>https://google.com/one/</string>
|
||||
<string>https://a.firebase.com/mypath</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -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 <XCTest/XCTest.h>
|
||||
|
||||
#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FDLURLComponents+Private.h"
|
||||
#import "FirebaseDynamicLinks/Sources/FDLURLComponents/FIRDynamicLinkComponentsKeyProvider.h"
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
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<NSURLQueryItem *> *expectedURLQueryItems =
|
||||
[expectedURLComponents.queryItems sortedArrayUsingDescriptors:@[ sort ]];
|
||||
|
||||
NSURL *actualURL = fdlComponents.url;
|
||||
NSURLComponents *actualURLComponents =
|
||||
[NSURLComponents componentsWithString:actualURL.absoluteString];
|
||||
NSArray<NSURLQueryItem *> *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<NSString *> *_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<NSString *> *_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
|
||||
@@ -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 <XCTest/XCTest.h>
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
#import "FirebaseDynamicLinks/Sources/FIRDLScionLogging.h"
|
||||
|
||||
static const NSTimeInterval kAsyncTestTimeout = 0.5;
|
||||
|
||||
typedef void (^FakeAnalyticsLogEventWithOriginNameParametersHandler)(NSString *origin,
|
||||
NSString *name,
|
||||
NSDictionary *parameters);
|
||||
|
||||
@interface FakeAnalytics : NSObject <FIRAnalyticsInterop>
|
||||
|
||||
- (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<NSString *, id> *)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<FIRAnalyticsInteropListener>)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<NSString *, NSString *> *)clearEventParameters {
|
||||
}
|
||||
|
||||
- (nonnull NSArray<NSDictionary<NSString *, NSString *> *> *)
|
||||
conditionalUserProperties:(nonnull NSString *)origin
|
||||
propertyNamePrefix:(nonnull NSString *)propertyNamePrefix {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)setConditionalUserProperty:(nonnull NSDictionary<NSString *, id> *)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
|
||||
@@ -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 <XCTest/XCTest.h>
|
||||
|
||||
#import <OCMock/OCMock.h>
|
||||
|
||||
#import <GoogleUtilities/GULSwizzler.h>
|
||||
|
||||
#import <GoogleUtilities/GULSwizzler+Unswizzle.h>
|
||||
#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
|
||||
@@ -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 <Foundation/Foundation.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "FirebaseDynamicLinks/Sources/FIRDynamicLink+Private.h"
|
||||
|
||||
@interface FIRDynamicLinkTest : XCTestCase {
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation FIRDynamicLinkTest
|
||||
|
||||
NSMutableDictionary<NSString *, NSString *> *fdlParameters = nil;
|
||||
NSDictionary<NSString *, NSString *> *linkParameters = nil;
|
||||
NSDictionary<NSString *, NSString *> *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
|
||||
@@ -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 <XCTest/XCTest.h>
|
||||
|
||||
#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
|
||||
File diff suppressed because it is too large.
Load diff
@@ -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 <XCTest/XCTest.h>
|
||||
|
||||
#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<NSURLQueryItem *> *expectedURLQueryItems =
|
||||
[expectedURLComponents.queryItems sortedArrayUsingDescriptors:@[ sort ]];
|
||||
|
||||
NSArray<NSURLQueryItem *> *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
|
||||
@@ -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;
|
||||
|
||||
@@ -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 => '../../'
|
||||
|
||||
@@ -31,16 +31,12 @@
|
||||
#import <FirebaseCore/FirebaseCore.h>
|
||||
#import <FirebaseCrashlytics/FirebaseCrashlytics.h>
|
||||
#import <FirebaseDatabase/FirebaseDatabase.h>
|
||||
#import "FirebaseCore/FirebaseCore.h"
|
||||
#import "FirebaseCrashlytics/FirebaseCrashlytics.h"
|
||||
#import "FirebaseDatabase/FirebaseDatabase.h"
|
||||
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
|
||||
#import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
|
||||
#import "FirebaseDynamicLinks/FirebaseDynamicLinks.h"
|
||||
#endif
|
||||
#import <FirebaseFirestore/FirebaseFirestore.h>
|
||||
#import <FirebaseInstallations/FirebaseInstallations.h>
|
||||
#import <FirebaseMessaging/FirebaseMessaging.h>
|
||||
#import "FirebaseCore/FirebaseCore.h"
|
||||
#import "FirebaseCrashlytics/FirebaseCrashlytics.h"
|
||||
#import "FirebaseDatabase/FirebaseDatabase.h"
|
||||
#import "FirebaseFirestore/FirebaseFirestore.h"
|
||||
#import "FirebaseInstallations/FirebaseInstallations.h"
|
||||
#import "FirebaseMessaging/FirebaseMessaging.h"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -34,16 +34,12 @@
|
||||
#import <FirebaseCore/FirebaseCore.h>
|
||||
#import <FirebaseCrashlytics/FirebaseCrashlytics.h>
|
||||
#import <FirebaseDatabase/FirebaseDatabase.h>
|
||||
#import "FirebaseCore/FirebaseCore.h"
|
||||
#import "FirebaseCrashlytics/FirebaseCrashlytics.h"
|
||||
#import "FirebaseDatabase/FirebaseDatabase.h"
|
||||
#if TARGET_OS_IOS && !TARGET_OS_MACCATALYST
|
||||
#import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
|
||||
#import "FirebaseDynamicLinks/FirebaseDynamicLinks.h"
|
||||
#endif
|
||||
#import <FirebaseFirestore/FirebaseFirestore.h>
|
||||
#import <FirebaseInstallations/FirebaseInstallations.h>
|
||||
#import <FirebaseMessaging/FirebaseMessaging.h>
|
||||
#import "FirebaseCore/FirebaseCore.h"
|
||||
#import "FirebaseCrashlytics/FirebaseCrashlytics.h"
|
||||
#import "FirebaseDatabase/FirebaseDatabase.h"
|
||||
#import "FirebaseFirestore/FirebaseFirestore.h"
|
||||
#import "FirebaseInstallations/FirebaseInstallations.h"
|
||||
#import "FirebaseMessaging/FirebaseMessaging.h"
|
||||
|
||||
@@ -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
|
||||
|
||||
-1
@@ -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 => '../../'
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -1292,7 +1266,6 @@ let package = Package(
|
||||
"FirebaseCrashlytics",
|
||||
"FirebaseCore",
|
||||
"FirebaseDatabase",
|
||||
"FirebaseDynamicLinks",
|
||||
"FirebaseFirestoreTarget",
|
||||
"FirebaseFunctions",
|
||||
.target(name: "FirebaseInAppMessaging",
|
||||
@@ -1328,7 +1301,6 @@ let package = Package(
|
||||
"FirebaseCrashlytics",
|
||||
"FirebaseCore",
|
||||
"FirebaseDatabase",
|
||||
"FirebaseDynamicLinks",
|
||||
"FirebaseFirestoreTarget",
|
||||
"FirebaseFunctions",
|
||||
.target(name: "FirebaseInAppMessaging",
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 <TargetConditionals.h>
|
||||
#if !TARGET_OS_IOS
|
||||
#warning "Firebase Dynamic Links only supports the iOS platform"
|
||||
#endif
|
||||
@@ -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.
|
||||
@@ -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 <FirebaseCore/FirebaseCore.h>
|
||||
#import <FirebaseCrashlytics/FirebaseCrashlytics.h>
|
||||
#import <FirebaseDatabase/FirebaseDatabase.h>
|
||||
#import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
|
||||
#import <FirebaseFirestore/FirebaseFirestore.h>
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
#import <FirebaseInAppMessaging/FirebaseInAppMessaging.h>
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
@import FirebaseCrashlytics;
|
||||
@import FirebaseCore;
|
||||
@import FirebaseDatabase;
|
||||
@import FirebaseDynamicLinks;
|
||||
@import FirebaseFirestore;
|
||||
@import FirebaseFunctions;
|
||||
@import FirebaseInstallations;
|
||||
|
||||
@@ -23,7 +23,6 @@ import Foundation
|
||||
#endif
|
||||
import FirebaseCrashlytics
|
||||
import FirebaseDatabase
|
||||
import FirebaseDynamicLinks
|
||||
import FirebaseFirestore
|
||||
import FirebaseFunctions
|
||||
import FirebaseInstallations
|
||||
|
||||
@@ -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 => '../'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -31,7 +31,6 @@ MODULE_LIST = [
|
||||
'FirebaseCore',
|
||||
'FirebaseCrashlytics',
|
||||
'FirebaseDatabase',
|
||||
'FirebaseDynamicLinks',
|
||||
'FirebaseFirestoreInternal',
|
||||
'FirebaseFirestore',
|
||||
'FirebaseFunctions',
|
||||
|
||||
Loaded 100 of 104 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user