mirror of
https://github.com/luxfi/safe-ios.git
synced 2026-10-30 15:19:20 +00:00
114 lines
4.3 KiB
Swift
114 lines
4.3 KiB
Swift
//
|
|
// Copyright © 2019 Gnosis Ltd. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import FirebaseAnalytics
|
|
import Firebase
|
|
|
|
final class FirebaseTrackingHandler: TrackingHandler {
|
|
|
|
private let reservedNames: [String] = [
|
|
"ad_activeview",
|
|
"ad_click",
|
|
"ad_exposure",
|
|
"ad_impression",
|
|
"ad_query",
|
|
"adunit_exposure",
|
|
"app_clear_data",
|
|
"app_remove",
|
|
"app_update",
|
|
"error",
|
|
"first_open",
|
|
"in_app_purchase",
|
|
"notification_dismiss",
|
|
"notification_foreground",
|
|
"notification_open",
|
|
"notification_receive",
|
|
"os_update",
|
|
"screen_view",
|
|
"session_start",
|
|
"user_engagement"
|
|
]
|
|
private let reservedPrefixes: [String] = [
|
|
"firebase_",
|
|
"google_",
|
|
"ga_"
|
|
]
|
|
private let nameLengthRange = (1...40)
|
|
private let nameBodyCharacterSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "_"))
|
|
private let nameHeadCharacterSet = CharacterSet.letters
|
|
private let maxParameterCount = 25
|
|
private let stringParameterLengthRange = (1...100)
|
|
private let propertyNameLengthRange = (1...24)
|
|
private let propertyValueLengthRange = (0...36)
|
|
|
|
/// Tracks an event with parameters, verifying that event name, parameter count, parameter names and values
|
|
/// are conforming to Firebase's limitations specified in the FIRAnalytics.h
|
|
func track(event: String, parameters: [String: Any]?, file: StaticString = #file, line: UInt = #line, function: StaticString = #function) {
|
|
// check event name
|
|
assert(!reservedNames.contains(event), "reserved name: \(event)")
|
|
check(name: event)
|
|
|
|
// check parameters
|
|
if let parameters = parameters {
|
|
assert(parameters.count <= maxParameterCount, "Too many parameters: \(parameters.count)")
|
|
|
|
for (name, value) in parameters {
|
|
check(name: name)
|
|
assert(value as? NSString != nil || value as? NSNumber != nil,
|
|
"Event parameter value \(value) for key \(name) is of unsupported type: \(type(of: value))")
|
|
|
|
if let stringValue = value as? NSString {
|
|
assert(stringParameterLengthRange.contains(stringValue.length),
|
|
"Event parameter value \(stringValue) for key \(name) is too long: \(stringValue.length)")
|
|
checkPrefix(value: stringValue as String)
|
|
}
|
|
}
|
|
}
|
|
Analytics.logEvent(event, parameters: parameters)
|
|
}
|
|
|
|
func setUserProperty(_ value: String, for property: UserProperty, file: StaticString = #file, line: UInt = #line, function: StaticString = #function) {
|
|
assert(propertyNameLengthRange.contains(property.rawValue.count), "wrong property name length")
|
|
assert(propertyValueLengthRange.contains(value.count), "wrong property value length")
|
|
checkPrefix(value: value)
|
|
|
|
Analytics.setUserProperty(value, forName: property.rawValue)
|
|
}
|
|
|
|
func setTrackingEnabled(_ value: Bool) {
|
|
Analytics.setAnalyticsCollectionEnabled(value)
|
|
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(value)
|
|
}
|
|
|
|
/// Verifies that the name is correct.
|
|
///
|
|
/// Criteria:
|
|
/// 1. Within allowed length
|
|
/// 2. First characters and other characters are from allowed characters
|
|
/// 3. Does not use preserved prefix
|
|
///
|
|
/// - Parameter name: string to be used as event name or parameter name
|
|
private func check(name: String) {
|
|
assert(nameLengthRange.contains(name.count),
|
|
"name length is \(name.count)")
|
|
assert(name.rangeOfCharacter(from: nameBodyCharacterSet.inverted) == nil,
|
|
"name contains forbidden characters: \(name)")
|
|
assert(String(name.first!).rangeOfCharacter(from: nameHeadCharacterSet.inverted) == nil,
|
|
"name starts with forbidden character: \(name)")
|
|
checkPrefix(value: name)
|
|
}
|
|
|
|
/// Verifies that the value is correct
|
|
///
|
|
/// Criteria:
|
|
/// 1. Does not use preserved prefix
|
|
///
|
|
/// - Parameter value: string to use as parameter value or event name
|
|
private func checkPrefix(value: String) {
|
|
assert(!reservedPrefixes.contains { value.starts(with: $0) }, "reserved prefix in the value: \(value)")
|
|
}
|
|
|
|
}
|