Skip to content

Commit bda2be9

Browse files
authored
[Auth] Remove AuthDispatcher singleton, prefer DI (#14122)
1 parent e4bc445 commit bda2be9

File tree

4 files changed

+24
-28
lines changed

4 files changed

+24
-28
lines changed

FirebaseAuth/Sources/Swift/Auth/Auth.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,8 @@ extension Auth: AuthInterop {
16161616

16171617
init(app: FirebaseApp,
16181618
keychainStorageProvider: AuthKeychainStorage = AuthKeychainStorageReal(),
1619-
backend: AuthBackend = AuthBackend(rpcIssuer: AuthBackendRPCIssuer())) {
1619+
backend: AuthBackend = .init(rpcIssuer: AuthBackendRPCIssuer()),
1620+
authDispatcher: AuthDispatcher = .init()) {
16201621
Auth.setKeychainServiceNameForApp(app)
16211622
self.app = app
16221623
mainBundleUrlTypes = Bundle.main
@@ -1642,6 +1643,7 @@ extension Auth: AuthInterop {
16421643
heartbeatLogger: app.heartbeatLogger,
16431644
appCheck: appCheck)
16441645
self.backend = backend
1646+
self.authDispatcher = authDispatcher
16451647
super.init()
16461648
requestConfiguration.auth = self
16471649

@@ -1902,7 +1904,7 @@ extension Auth: AuthInterop {
19021904
}
19031905
autoRefreshScheduled = true
19041906
weak var weakSelf = self
1905-
AuthDispatcher.shared.dispatch(afterDelay: delay, queue: kAuthGlobalWorkQueue) {
1907+
authDispatcher.dispatch(afterDelay: delay, queue: kAuthGlobalWorkQueue) {
19061908
guard let strongSelf = weakSelf else {
19071909
return
19081910
}
@@ -2361,6 +2363,8 @@ extension Auth: AuthInterop {
23612363
/// The Firebase app name.
23622364
private let firebaseAppName: String
23632365

2366+
private let authDispatcher: AuthDispatcher
2367+
23642368
/// The keychain service.
23652369
private var keychainServices: AuthKeychainServices!
23662370

FirebaseAuth/Sources/Swift/Auth/AuthDispatcher.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,17 @@
1515
import Foundation
1616

1717
/// A utility class used to facilitate scheduling tasks to be executed in the future.
18-
class AuthDispatcher {
19-
static let shared = AuthDispatcher()
20-
18+
struct AuthDispatcher {
2119
/// Allows custom implementation of dispatchAfterDelay:queue:callback:.
2220
///
2321
/// Set to nil to restore default implementation.
24-
var dispatchAfterImplementation: ((TimeInterval, DispatchQueue, @escaping () -> Void) -> Void)?
22+
private let dispatchAfterImplementation: ((TimeInterval, DispatchQueue, @escaping () -> Void)
23+
-> Void)?
24+
25+
init(dispatchAfterImplementation: ((TimeInterval, DispatchQueue, @escaping () -> Void) -> Void)? =
26+
nil) {
27+
self.dispatchAfterImplementation = dispatchAfterImplementation
28+
}
2529

2630
/// Schedules task in the future after a specified delay.
2731
/// - Parameter delay: The delay in seconds after which the task will be scheduled to execute.

FirebaseAuth/Tests/Unit/AuthDispatcherTests.swift

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,15 @@ class AuthDispatcherTests: XCTestCase {
2222
let kTestDelay = 0.1
2323
let kMaxDifferenceBetweenTimeIntervals = 0.4
2424

25-
/** @fn testSharedInstance
26-
@brief Tests @c sharedInstance returns the same object.
27-
*/
28-
func testSharedInstance() {
29-
let instance1 = AuthDispatcher.shared
30-
let instance2 = AuthDispatcher.shared
31-
XCTAssert(instance1 === instance2)
32-
}
33-
3425
/** @fn testDispatchAfterDelay
3526
@brief Tests @c dispatchAfterDelay indeed dispatches the specified task after the provided
3627
delay.
3728
*/
3829
func testDispatchAfterDelay() {
39-
let dispatcher = AuthDispatcher.shared
30+
let dispatcher = AuthDispatcher()
4031
let testWorkQueue = DispatchQueue(label: "test.work.queue")
4132
let expectation = self.expectation(description: #function)
4233
let dateBeforeDispatch = Date()
43-
dispatcher.dispatchAfterImplementation = nil
4434
dispatcher.dispatch(afterDelay: kTestDelay, queue: testWorkQueue) { [self] in
4535
let timeSinceDispatch = fabs(dateBeforeDispatch.timeIntervalSinceNow - self.kTestDelay)
4636
XCTAssertLessThan(timeSinceDispatch, kMaxDifferenceBetweenTimeIntervals)
@@ -54,15 +44,13 @@ class AuthDispatcherTests: XCTestCase {
5444
@c dispatchAfterDelay.
5545
*/
5646
func testSetDispatchAfterImplementation() {
57-
let dispatcher = AuthDispatcher.shared
5847
let testWorkQueue = DispatchQueue(label: "test.work.queue")
5948
let expectation = self.expectation(description: #function)
60-
dispatcher.dispatchAfterImplementation = { delay, queue, task in
49+
let dispatcher = AuthDispatcher { delay, queue, task in
6150
XCTAssertEqual(self.kTestDelay, delay)
6251
XCTAssertEqual(testWorkQueue, queue)
6352
expectation.fulfill()
6453
}
65-
6654
dispatcher.dispatch(afterDelay: kTestDelay, queue: testWorkQueue) {
6755
// Fail to ensure this code is never executed.
6856
XCTFail("Should not execute this code")

FirebaseAuth/Tests/Unit/AuthTests.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,20 @@ class AuthTests: RPCBaseTests {
4545
#else
4646
let keychainStorageProvider = AuthKeychainStorageReal()
4747
#endif // (os(macOS) && !FIREBASE_AUTH_TESTING_USE_MACOS_KEYCHAIN) || SWIFT_PACKAGE
48-
auth = Auth(
49-
app: FirebaseApp.app(name: name)!,
50-
keychainStorageProvider: keychainStorageProvider,
51-
backend: authBackend
52-
)
5348

54-
// Set authDispatcherCallback implementation in order to save the token refresh task for later
55-
// execution.
56-
AuthDispatcher.shared.dispatchAfterImplementation = { delay, queue, task in
49+
// Stub the implementation to save the token refresh task for later execution.
50+
let authDispatcher = AuthDispatcher { delay, queue, task in
5751
XCTAssertNotNil(task)
5852
XCTAssertGreaterThan(delay, 0)
5953
XCTAssertEqual(kAuthGlobalWorkQueue, queue)
6054
self.authDispatcherCallback = task
6155
}
56+
auth = Auth(
57+
app: FirebaseApp.app(name: name)!,
58+
keychainStorageProvider: keychainStorageProvider,
59+
backend: authBackend,
60+
authDispatcher: authDispatcher
61+
)
6262
// Wait until Auth initialization completes
6363
waitForAuthGlobalWorkQueueDrain()
6464
}

0 commit comments

Comments
 (0)