Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions AuthenticatorBridgeKit/AuthenticatorBridgeDataStore.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import BitwardenKit
import CoreData
@preconcurrency import CoreData

// MARK: - AuthenticatorStoreType

Expand All @@ -20,8 +20,11 @@ public enum AuthenticatorBridgeStoreType {
private let authenticatorBridgeModelName = "Bitwarden-Authenticator"

/// A data store that manages persisting data across app launches in Core Data.
/// This is currently marked `@unchecked Sendable` because of how we ensure thread safety of the `backgroundContext`
/// property. Once we have a minimum version of iOS 16 or higher, we can migrate to the `Synchronization` framework
/// and make this more properly `Sendable`.
///
public class AuthenticatorBridgeDataStore {
public final nonisolated class AuthenticatorBridgeDataStore: @unchecked Sendable {
// MARK: Type Properties

/// The managed object model representing the entities in the database schema. CoreData throws
Expand All @@ -41,12 +44,29 @@ public class AuthenticatorBridgeDataStore {

// MARK: Properties

/// A thread-safe lock for `backgroundContext`. Once we have a minimum of iOS 16, we can use an
/// `OSAllocatedUnfairLock` instead.
private let _backgroundContextLock = DispatchQueue(label: "backgroundContext.lock")

/// A private backing for `backgroundContext`. The `backgroundContext` variable provides thread-safe access, and
/// is what should be used. Once we have a minimum of iOS 16, this can be converted to an `OSAllocatedUnfairLock`,
/// and remove the need for the additional `_backgroundContextLock`.
private var _backgroundContext: NSManagedObjectContext?

/// A managed object context which executes on a background queue.
private(set) lazy var backgroundContext: NSManagedObjectContext = {
let context = persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
return context
}()
/// This is the thread-safe version of the backing variable `_backgroundContext`,
/// and initializes that property lazily.
public var backgroundContext: NSManagedObjectContext {
_backgroundContextLock.sync {
if let context = _backgroundContext {
return context
}
let newContext = persistentContainer.newBackgroundContext()
newContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
_backgroundContext = newContext
return newContext
}
}

/// The service used by the application to report non-fatal errors.
let errorReporter: ErrorReporter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public protocol SharedKeychainService: AnyObject {
// MARK: - SharedKeychainServiceError

/// Enum with possible error cases that can be thrown from `SharedKeychainService`.
public enum SharedKeychainServiceError: Error, Equatable, CustomNSError {
public enum SharedKeychainServiceError: Error, Equatable, CustomNSError, Sendable {
/// When a `KeychainService` is unable to locate an auth key for a given storage key.
///
/// - Parameter KeychainItem: The potential storage key for the auth key.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Foundation

/// Enumeration of support Keychain Items that can be placed in the `SharedKeychainRepository`
///
public enum SharedKeychainItem: Equatable, Hashable {
public enum SharedKeychainItem: Equatable, Hashable, Sendable {
/// The keychain item for the authenticator encryption key.
case authenticatorKey

Expand Down
3 changes: 3 additions & 0 deletions project-bwk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ targets:
base:
APPLICATION_EXTENSION_API_ONLY: true
INFOPLIST_FILE: AuthenticatorBridgeKit/Info.plist
SWIFT_STRICT_CONCURRENCY: complete
sources:
- path: AuthenticatorBridgeKit
excludes:
Expand All @@ -82,6 +83,7 @@ targets:
settings:
base:
INFOPLIST_FILE: AuthenticatorBridgeKit/Tests/TestHelpers/Support/Info.plist
SWIFT_STRICT_CONCURRENCY: complete
sources:
- path: AuthenticatorBridgeKit
includes:
Expand All @@ -102,6 +104,7 @@ targets:
base:
ENABLE_TESTING_SEARCH_PATHS: YES
INFOPLIST_FILE: AuthenticatorBridgeKit/MocksInfo.plist
SWIFT_STRICT_CONCURRENCY: complete
sources:
- path: AuthenticatorBridgeKit
includes:
Expand Down