Skip to content

Commit 5ef7eb5

Browse files
committed
Finishing touches
1 parent 3ec23dd commit 5ef7eb5

File tree

5 files changed

+106
-17
lines changed

5 files changed

+106
-17
lines changed

FirebaseAuth/Sources/Swift/ActionCode/ActionCodeInfo.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414

1515
import Foundation
1616

17+
// TODO(Swift 6 Breaking): This type is immutable. Consider removing `open` at
18+
// breaking change so checked Sendable can be used.
19+
1720
/// Manages information regarding action codes.
18-
@objc(FIRActionCodeInfo) public final class ActionCodeInfo: NSObject, Sendable {
21+
@objc(FIRActionCodeInfo) open class ActionCodeInfo: NSObject, @unchecked Sendable {
1922
/// The operation being performed.
2023
@objc public let operation: ActionCodeOperation
2124

FirebaseAuth/Sources/Swift/ActionCode/ActionCodeOperation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import Foundation
1616

1717
/// Operations which can be performed with action codes.
18-
@objc(FIRActionCodeOperation) public enum ActionCodeOperation: Int, @unchecked Sendable {
18+
@objc(FIRActionCodeOperation) public enum ActionCodeOperation: Int, Sendable {
1919
/// Action code for unknown operation.
2020
case unknown = 0
2121

FirebaseAuth/Sources/Swift/ActionCode/ActionCodeSettings.swift

Lines changed: 91 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,55 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import FirebaseCoreInternal
1516
import Foundation
1617

18+
// TODO(Swift 6 Breaking): Consider breaking up into a checked Sendable Swift
19+
// type and unchecked Sendable ObjC wrapper class.
20+
1721
/// Used to set and retrieve settings related to handling action codes.
1822
@objc(FIRActionCodeSettings) open class ActionCodeSettings: NSObject,
19-
@unchecked Sendable /* TODO: sendable */ {
23+
@unchecked Sendable {
2024
/// This URL represents the state/Continue URL in the form of a universal link.
2125
///
2226
/// This URL can should be constructed as a universal link that would either directly open
2327
/// the app where the action code would be handled or continue to the app after the action code
2428
/// is handled by Firebase.
25-
@objc(URL) open var url: URL?
29+
@objc(URL) open var url: URL? {
30+
get { impl.url.value() }
31+
set { impl.url.withLock { $0 = newValue } }
32+
}
2633

2734
/// Indicates whether the action code link will open the app directly or after being
2835
/// redirected from a Firebase owned web widget.
29-
@objc open var handleCodeInApp: Bool = false
36+
@objc open var handleCodeInApp: Bool {
37+
get { impl.handleCodeInApp.value() }
38+
set { impl.handleCodeInApp.withLock { $0 = newValue } }
39+
}
3040

3141
/// The iOS bundle ID, if available. The default value is the current app's bundle ID.
32-
@objc open var iOSBundleID: String?
42+
@objc open var iOSBundleID: String? {
43+
get { impl.iOSBundleID.value() }
44+
set { impl.iOSBundleID.withLock { $0 = newValue } }
45+
}
3346

3447
/// The Android package name, if available.
35-
@objc open var androidPackageName: String?
48+
@objc open var androidPackageName: String? {
49+
get { impl.androidPackageName.value() }
50+
set { impl.androidPackageName.withLock { $0 = newValue } }
51+
}
3652

3753
/// The minimum Android version supported, if available.
38-
@objc open var androidMinimumVersion: String?
54+
@objc open var androidMinimumVersion: String? {
55+
get { impl.androidMinimumVersion.value() }
56+
set { impl.androidMinimumVersion.withLock { $0 = newValue } }
57+
}
3958

4059
/// Indicates whether the Android app should be installed on a device where it is not available.
41-
@objc open var androidInstallIfNotAvailable: Bool = false
60+
@objc open var androidInstallIfNotAvailable: Bool {
61+
get { impl.androidInstallIfNotAvailable.value() }
62+
set { impl.androidInstallIfNotAvailable.withLock { $0 = newValue } }
63+
}
4264

4365
/// The Firebase Dynamic Link domain used for out of band code flow.
4466
#if !FIREBASE_CI
@@ -48,14 +70,22 @@ import Foundation
4870
message: "Firebase Dynamic Links is deprecated. Migrate to use Firebase Hosting link and use `linkDomain` to set a custom domain instead."
4971
)
5072
#endif // !FIREBASE_CI
51-
@objc open var dynamicLinkDomain: String?
73+
@objc open var dynamicLinkDomain: String? {
74+
get { impl.dynamicLinkDomain.value() }
75+
set { impl.dynamicLinkDomain.withLock { $0 = newValue } }
76+
}
5277

5378
/// The out of band custom domain for handling code in app.
54-
@objc public var linkDomain: String?
79+
@objc public var linkDomain: String? {
80+
get { impl.linkDomain.value() }
81+
set { impl.linkDomain.withLock { $0 = newValue } }
82+
}
83+
84+
private let impl: SendableActionCodeSettings
5585

5686
/// Sets the iOS bundle ID.
5787
@objc override public init() {
58-
iOSBundleID = Bundle.main.bundleIdentifier
88+
impl = .init()
5989
}
6090

6191
/// Sets the Android package name, the flag to indicate whether or not to install the app,
@@ -71,13 +101,60 @@ import Foundation
71101
@objc open func setAndroidPackageName(_ androidPackageName: String,
72102
installIfNotAvailable: Bool,
73103
minimumVersion: String?) {
74-
self.androidPackageName = androidPackageName
75-
androidInstallIfNotAvailable = installIfNotAvailable
76-
androidMinimumVersion = minimumVersion
104+
impl
105+
.setAndroidPackageName(
106+
androidPackageName,
107+
installIfNotAvailable: installIfNotAvailable,
108+
minimumVersion: minimumVersion
109+
)
77110
}
78111

79112
/// Sets the iOS bundle ID.
80113
open func setIOSBundleID(_ bundleID: String) {
81-
iOSBundleID = bundleID
114+
impl.setIOSBundleID(bundleID)
115+
}
116+
}
117+
118+
private extension ActionCodeSettings {
119+
/// Checked Sendable implementation of `ActionCodeSettings`.
120+
final class SendableActionCodeSettings: Sendable {
121+
let url = FIRAllocatedUnfairLock<URL?>(initialState: nil)
122+
123+
let handleCodeInApp = FIRAllocatedUnfairLock<Bool>(initialState: false)
124+
125+
let iOSBundleID: FIRAllocatedUnfairLock<String?>
126+
127+
let androidPackageName = FIRAllocatedUnfairLock<String?>(initialState: nil)
128+
129+
let androidMinimumVersion = FIRAllocatedUnfairLock<String?>(initialState: nil)
130+
131+
let androidInstallIfNotAvailable = FIRAllocatedUnfairLock<Bool>(initialState: false)
132+
133+
#if !FIREBASE_CI
134+
@available(
135+
*,
136+
deprecated,
137+
message: "Firebase Dynamic Links is deprecated. Migrate to use Firebase Hosting link and use `linkDomain` to set a custom domain instead."
138+
)
139+
#endif // !FIREBASE_CI
140+
let dynamicLinkDomain = FIRAllocatedUnfairLock<String?>(initialState: nil)
141+
142+
let linkDomain = FIRAllocatedUnfairLock<String?>(initialState: nil)
143+
144+
init() {
145+
iOSBundleID = FIRAllocatedUnfairLock<String?>(initialState: Bundle.main.bundleIdentifier)
146+
}
147+
148+
func setAndroidPackageName(_ androidPackageName: String,
149+
installIfNotAvailable: Bool,
150+
minimumVersion: String?) {
151+
self.androidPackageName.withLock { $0 = androidPackageName }
152+
androidInstallIfNotAvailable.withLock { $0 = installIfNotAvailable }
153+
androidMinimumVersion.withLock { $0 = minimumVersion }
154+
}
155+
156+
func setIOSBundleID(_ bundleID: String) {
157+
iOSBundleID.withLock { $0 = bundleID }
158+
}
82159
}
83160
}

FirebaseAuth/Sources/Swift/ActionCode/ActionCodeURL.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414

1515
import Foundation
1616

17+
// TODO(Swift 6 Breaking): This type is immutable. Consider removing `open` at
18+
// breaking change so checked Sendable can be used.
19+
1720
/// This class will allow developers to easily extract information about out of band links.
18-
@objc(FIRActionCodeURL) open class ActionCodeURL: NSObject {
21+
@objc(FIRActionCodeURL) open class ActionCodeURL: NSObject, @unchecked Sendable {
1922
/// Returns the API key from the link. nil, if not provided.
2023
@objc(APIKey) public let apiKey: String?
2124

FirebaseCore/Internal/Sources/Utilities/FIRAllocatedUnfairLock.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ public final class FIRAllocatedUnfairLock<State>: @unchecked Sendable {
4242
os_unfair_lock_unlock(lockPointer)
4343
}
4444

45+
public func value() -> State {
46+
lock()
47+
defer { unlock() }
48+
return state
49+
}
50+
4551
@discardableResult
4652
public func withLock<R>(_ body: (inout State) throws -> R) rethrows -> R {
4753
let value: R

0 commit comments

Comments
 (0)