Skip to content

Commit

Permalink
Release 16.12.0 (#2757)
Browse files Browse the repository at this point in the history
* Update version to 16.12.0

* Update keychain store to kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly

* Release 16.12.0

* Update release date
  • Loading branch information
rlepinski authored Jun 12, 2023
1 parent 06e2a00 commit 8ca5a0f
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 55 deletions.
2 changes: 1 addition & 1 deletion Airship.podspec
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AIRSHIP_VERSION="16.11.3"
AIRSHIP_VERSION="16.12.0"

Pod::Spec.new do |s|
s.version = AIRSHIP_VERSION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
* Factory method. Use for testing.
*
* @param config The UARuntimeConfigInstance.
* @param automationEngine The automation engine.
* @param audienceManager The audience manager.
* @param remoteDataClient The remote data client.
Expand All @@ -39,7 +40,8 @@ NS_ASSUME_NONNULL_BEGIN
* @param privacyManager The privacy manager.
* @return A in-app automation manager instance.
*/
+ (instancetype)automationWithEngine:(UAAutomationEngine *)automationEngine
+ (instancetype)automationWithConfig:(UARuntimeConfig *)config
automationEngine:(UAAutomationEngine *)automationEngine
audienceManager:(UAInAppAudienceManager *)audienceManager
remoteDataClient:(UAInAppRemoteDataClient *)remoteDataClient
dataStore:(UAPreferenceDataStore *)dataStore
Expand Down
64 changes: 36 additions & 28 deletions Airship/AirshipAutomation/Source/UAInAppAutomation.m
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ @interface UAInAppAutomation () <UAAutomationEngineDelegate, UAInAppAudienceMana
@property(nonatomic, assign) dispatch_once_t engineStarted;
@property(nonatomic, strong) UAComponentDisableHelper *disableHelper;
@property(nonatomic, strong) NSMutableDictionary<NSString *, NSURL *> *redirectURLs;

@end

@implementation UAInAppAutomation
Expand All @@ -51,7 +50,8 @@ + (UAInAppAutomation *)shared {
return (UAInAppAutomation *)[UAirship componentForClassName:NSStringFromClass([self class])];
}

+ (instancetype)automationWithEngine:(UAAutomationEngine *)automationEngine
+ (instancetype)automationWithConfig:(UARuntimeConfig *)config
automationEngine:(UAAutomationEngine *)automationEngine
audienceManager:(UAInAppAudienceManager *)audienceManager
remoteDataClient:(UAInAppRemoteDataClient *)remoteDataClient
dataStore:(UAPreferenceDataStore *)dataStore
Expand All @@ -61,15 +61,16 @@ + (instancetype)automationWithEngine:(UAAutomationEngine *)automationEngine
frequencyLimitManager:(UAFrequencyLimitManager *)frequencyLimitManager
privacyManager:(UAPrivacyManager *)privacyManager {

return [[self alloc] initWithAutomationEngine:automationEngine
audienceManager:audienceManager
remoteDataClient:remoteDataClient
dataStore:dataStore
inAppMessageManager:inAppMessageManager
channel:channel
deferredScheduleAPIClient:deferredScheduleAPIClient
frequencyLimitManager:frequencyLimitManager
privacyManager:privacyManager];
return [[self alloc] initWithConfig:config
automationEngine:automationEngine
audienceManager:audienceManager
remoteDataClient:remoteDataClient
dataStore:dataStore
inAppMessageManager:inAppMessageManager
channel:channel
deferredScheduleAPIClient:deferredScheduleAPIClient
frequencyLimitManager:frequencyLimitManager
privacyManager:privacyManager];
}

+ (instancetype)automationWithConfig:(UARuntimeConfig *)config
Expand Down Expand Up @@ -101,26 +102,28 @@ + (instancetype)automationWithConfig:(UARuntimeConfig *)config

UAFrequencyLimitManager *frequencyLimitManager = [UAFrequencyLimitManager managerWithConfig:config];

return [[UAInAppAutomation alloc] initWithAutomationEngine:automationEngine
audienceManager:audienceManager
remoteDataClient:dataClient
dataStore:dataStore
inAppMessageManager:inAppMessageManager
channel:channel
deferredScheduleAPIClient:deferredScheduleAPIClient
frequencyLimitManager:frequencyLimitManager
return [[UAInAppAutomation alloc] initWithConfig:config
automationEngine:automationEngine
audienceManager:audienceManager
remoteDataClient:dataClient
dataStore:dataStore
inAppMessageManager:inAppMessageManager
channel:channel
deferredScheduleAPIClient:deferredScheduleAPIClient
frequencyLimitManager:frequencyLimitManager
privacyManager:privacyManager];
}

- (instancetype)initWithAutomationEngine:(UAAutomationEngine *)automationEngine
audienceManager:(UAInAppAudienceManager *)audienceManager
remoteDataClient:(UAInAppRemoteDataClient *)remoteDataClient
dataStore:(UAPreferenceDataStore *)dataStore
inAppMessageManager:(UAInAppMessageManager *)inAppMessageManager
channel:(UAChannel *)channel
deferredScheduleAPIClient:(UADeferredScheduleAPIClient *)deferredScheduleAPIClient
frequencyLimitManager:(UAFrequencyLimitManager *)frequencyLimitManager
privacyManager:(UAPrivacyManager *)privacyManager {
- (instancetype)initWithConfig:(UARuntimeConfig *)config
automationEngine:(UAAutomationEngine *)automationEngine
audienceManager:(UAInAppAudienceManager *)audienceManager
remoteDataClient:(UAInAppRemoteDataClient *)remoteDataClient
dataStore:(UAPreferenceDataStore *)dataStore
inAppMessageManager:(UAInAppMessageManager *)inAppMessageManager
channel:(UAChannel *)channel
deferredScheduleAPIClient:(UADeferredScheduleAPIClient *)deferredScheduleAPIClient
frequencyLimitManager:(UAFrequencyLimitManager *)frequencyLimitManager
privacyManager:(UAPrivacyManager *)privacyManager {

self = [super init];

Expand Down Expand Up @@ -149,6 +152,10 @@ - (instancetype)initWithAutomationEngine:(UAAutomationEngine *)automationEngine
UA_STRONGIFY(self)
[self onComponentEnableChange];
};

if (config.autoPauseInAppAutomationOnLaunch) {
self.paused = YES;
}
}

return self;
Expand All @@ -161,6 +168,7 @@ - (void)airshipReady {
name:UAPrivacyManager.changeEvent
object:nil];


[self updateSubscription];
[self updateEnginePauseState];
}
Expand Down
2 changes: 1 addition & 1 deletion Airship/AirshipConfig.xcconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//* Copyright Airship and Contributors */

CURRENT_PROJECT_VERSION = 16.11.3
CURRENT_PROJECT_VERSION = 16.12.0

// Uncomment to include the preview build warning
// OTHER_CFLAGS = $(inherited) -DUA_PREVIEW=1
73 changes: 56 additions & 17 deletions Airship/AirshipCore/Source/AirshipKeychainAccess.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class AirshipKeychainAccess: NSObject {
identifier: identifier,
service: self.service
)

// Write to old location in case of a downgrade
if let bundleID = Bundle.main.bundleIdentifier {
let _ = Keychain.writeCredentials(
Expand All @@ -70,7 +70,7 @@ public class AirshipKeychainAccess: NSObject {
service: bundleID
)
}

completionHandler?(result)
}
}
Expand Down Expand Up @@ -124,8 +124,10 @@ public class AirshipKeychainAccess: NSObject {
@objc
public func readCredentials(
identifier: String,
completionHandler: @escaping(AirshipKeychainCredentials?
) -> Void) {
completionHandler: @escaping (
AirshipKeychainCredentials?
) -> Void
) {
self.dispatcher.dispatchAsync {
let credentials = self.readCredentialsHelper(
identifier: identifier
Expand All @@ -142,28 +144,28 @@ public class AirshipKeychainAccess: NSObject {
) {
return credentials
}

// If we do not have a new value, check
// the old service location
if let bundleID = Bundle.main.bundleIdentifier {

let old = Keychain.readCredentials(
identifier: identifier,
service: bundleID
)

if let old = old {
// Migrate old data to new service location
let _ = Keychain.writeCredentials(
old,
identifier: identifier,
service: self.service
)

return old
}
}

return nil
}
}
Expand All @@ -176,22 +178,22 @@ fileprivate struct Keychain {
service: String
) -> Bool {
guard let identifierData = identifier.data(using: .utf8),
let passwordData = credentials.password.data(
let passwordData = credentials.password.data(
using: .utf8
)
)
else {
return false
}

deleteCredentials(identifier: identifier, service: service)

let addquery: [String: Any] = [
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock,
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrGeneric as String: identifierData,
kSecAttrAccount as String: credentials.username,
kSecValueData as String: passwordData
kSecValueData as String: passwordData,
]

let status = SecItemAdd(addquery as CFDictionary, nil)
Expand Down Expand Up @@ -230,26 +232,63 @@ fileprivate struct Keychain {
kSecAttrService as String: service,
kSecAttrGeneric as String: identifierData,
kSecReturnAttributes as String: true,
kSecReturnData as String: true
kSecReturnData as String: true,
]


var item: CFTypeRef?
let status = SecItemCopyMatching(searchQuery as CFDictionary, &item)
guard status == errSecSuccess else {
return nil
}

guard let existingItem = item as? [String : Any],
let passwordData = existingItem[kSecValueData as String] as? Data,
let password = String(data: passwordData, encoding: String.Encoding.utf8),
guard let existingItem = item as? [String: Any] else {
return nil
}

guard let passwordData = existingItem[kSecValueData as String] as? Data,
let password = String(
data: passwordData,
encoding: String.Encoding.utf8
),
let username = existingItem[kSecAttrAccount as String] as? String
else {
return nil
}

let attrAccessible = existingItem[kSecAttrAccessible as String] as? String
if attrAccessible != (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly as String) {
updateThisDeviceOnly(identifier: identifier, service: service)
}

return AirshipKeychainCredentials(
username: username,
password: password
)
}

static func updateThisDeviceOnly(identifier: String, service: String) {
guard let identifierData = identifier.data(using: .utf8) else {
return
}

let updateQuery: [String: Any] = [
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
]

let searchQuery: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecMatchLimit as String: kSecMatchLimitOne,
kSecAttrService as String: service,
kSecAttrGeneric as String: identifierData
]

let updateStatus = SecItemUpdate(searchQuery as CFDictionary, updateQuery as CFDictionary)

if (updateStatus == errSecSuccess) {
AirshipLogger.trace("Updated keychain value \(identifier) to this device only")
} else {
AirshipLogger.error("Failed to update keychain value \(identifier) status:\(updateStatus)")
}
}
}
2 changes: 1 addition & 1 deletion Airship/AirshipCore/Source/AirshipVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Foundation;

@objc(UAirshipVersion)
public class AirshipVersion : NSObject {
public static let version = "16.11.3"
public static let version = "16.12.0"

@objc
public class func get() -> String {
Expand Down
6 changes: 5 additions & 1 deletion Airship/AirshipCore/Source/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ public class Config: NSObject, NSCopying {
/// The log level used for production apps. Defaults to `error`.
@objc
public var productionLogLevel: LogLevel = .error


/// Auto pause InAppAutomation on launch. Defaults to `false`
@objc
public var autoPauseInAppAutomationOnLaunch: Bool = false

/// The airship cloud site. Defaults to `us`.
@objc
Expand Down Expand Up @@ -393,6 +396,7 @@ public class Config: NSObject, NSCopying {
_detectProvisioningMode = config.detectProvisioningMode
_defaultProvisioningMode = config._defaultProvisioningMode
_inProduction = config._inProduction
autoPauseInAppAutomationOnLaunch = config.autoPauseInAppAutomationOnLaunch
}

public func copy(with zone: NSZone? = nil) -> Any {
Expand Down
5 changes: 5 additions & 0 deletions Airship/AirshipCore/Source/RuntimeConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ open class RuntimeConfig: NSObject {
/// Dictionary of custom config values.
@objc
public let customConfig: [AnyHashable : Any]?

/// Auto pause InAppAutomation on launch.
@objc
public let autoPauseInAppAutomationOnLaunch: Bool

/// If enabled, the Airship library automatically registers for remote notifications when push is enabled
/// and intercepts incoming notifications in both the foreground and upon launch.
Expand Down Expand Up @@ -275,6 +279,7 @@ open class RuntimeConfig: NSObject {
self.site = config.site
self.defaultAnalyticsURL = config.analyticsURL?.normalizeURLString()
self.defaultDeviceAPIURL = config.deviceAPIURL?.normalizeURLString()
self.autoPauseInAppAutomationOnLaunch = config.autoPauseInAppAutomationOnLaunch

if let initialConfigURL = config.initialConfigURL {
self.defaultRemoteDataAPIURL = initialConfigURL.normalizeURLString()
Expand Down
Loading

0 comments on commit 8ca5a0f

Please sign in to comment.