From 167aaed615ec406422d763ef0813f94bcca1ec2b Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 3 Dec 2025 09:58:49 +0700 Subject: [PATCH 1/5] Initialize authenticator before initializeAfterDependenciesAreInitialized --- WooCommerce/Classes/AppDelegate.swift | 6 ++++-- WooCommerce/Classes/ViewRelated/AppCoordinator.swift | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/AppDelegate.swift b/WooCommerce/Classes/AppDelegate.swift index 59a20bfd8ee..e53d56708ac 100644 --- a/WooCommerce/Classes/AppDelegate.swift +++ b/WooCommerce/Classes/AppDelegate.swift @@ -57,9 +57,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let stores = ServiceLocator.stores let analytics = ServiceLocator.analytics let pushNotesManager = ServiceLocator.pushNotesManager + + ServiceLocator.authenticationManager.initialize() stores.initializeAfterDependenciesAreInitialized() - setupAnalytics(analytics) + setupAnalytics(analytics) setupCocoaLumberjack() setupLibraryLogger() setupLogLevel(.verbose) @@ -224,7 +226,7 @@ extension AppDelegate { ZendeskProvider.shared.initialize() } - /// Sets up the WordPress Authenticator. + /// Sets up app analytics. /// func setupAnalytics(_ analytics: Analytics) { analytics.initialize() diff --git a/WooCommerce/Classes/ViewRelated/AppCoordinator.swift b/WooCommerce/Classes/ViewRelated/AppCoordinator.swift index d68eada9efb..602d8de5ad8 100644 --- a/WooCommerce/Classes/ViewRelated/AppCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/AppCoordinator.swift @@ -238,7 +238,6 @@ private extension AppCoordinator { /// Configures the WPAuthenticator for usage in both logged-in and logged-out states. func configureAuthenticator() { - authenticationManager.initialize() authenticationManager.setLoggedOutAppSettings(loggedOutAppSettings) authenticationManager.displayAuthenticatorIfLoggedOut = { [weak self] in guard let self, self.isLoggedIn == false else { return nil } From 3fc1e29677aff541472224227386c107555d8947 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 3 Dec 2025 10:14:58 +0700 Subject: [PATCH 2/5] Add comments for the early initialization of the authenticator --- WooCommerce/Classes/AppDelegate.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/WooCommerce/Classes/AppDelegate.swift b/WooCommerce/Classes/AppDelegate.swift index e53d56708ac..8a92b388b55 100644 --- a/WooCommerce/Classes/AppDelegate.swift +++ b/WooCommerce/Classes/AppDelegate.swift @@ -58,6 +58,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let analytics = ServiceLocator.analytics let pushNotesManager = ServiceLocator.pushNotesManager + /// This is important to initialize early as there are a few code points where the authenticator is used. ServiceLocator.authenticationManager.initialize() stores.initializeAfterDependenciesAreInitialized() From db670ab4a5fba2cbd464ca79f08eba73e49b57e2 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 3 Dec 2025 12:48:30 +0700 Subject: [PATCH 3/5] Restore initalization in configureAuthenticator --- WooCommerce/Classes/ViewRelated/AppCoordinator.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/WooCommerce/Classes/ViewRelated/AppCoordinator.swift b/WooCommerce/Classes/ViewRelated/AppCoordinator.swift index 602d8de5ad8..d68eada9efb 100644 --- a/WooCommerce/Classes/ViewRelated/AppCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/AppCoordinator.swift @@ -238,6 +238,7 @@ private extension AppCoordinator { /// Configures the WPAuthenticator for usage in both logged-in and logged-out states. func configureAuthenticator() { + authenticationManager.initialize() authenticationManager.setLoggedOutAppSettings(loggedOutAppSettings) authenticationManager.displayAuthenticatorIfLoggedOut = { [weak self] in guard let self, self.isLoggedIn == false else { return nil } From cb9ba8f3c2eb6d54ed272be27e38d0a9fac82ef6 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 3 Dec 2025 12:58:11 +0700 Subject: [PATCH 4/5] Trigger WordPressComBlogService directly instead of using WordPressAuthenticator --- WooCommerce/Classes/AppDelegate.swift | 5 +--- .../Yosemite/DefaultStoresManager.swift | 24 +++++++++---------- .../Services/WordPressComBlogService.swift | 6 +++-- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/WooCommerce/Classes/AppDelegate.swift b/WooCommerce/Classes/AppDelegate.swift index 8a92b388b55..4ae023cb1da 100644 --- a/WooCommerce/Classes/AppDelegate.swift +++ b/WooCommerce/Classes/AppDelegate.swift @@ -57,12 +57,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let stores = ServiceLocator.stores let analytics = ServiceLocator.analytics let pushNotesManager = ServiceLocator.pushNotesManager - - /// This is important to initialize early as there are a few code points where the authenticator is used. - ServiceLocator.authenticationManager.initialize() stores.initializeAfterDependenciesAreInitialized() - setupAnalytics(analytics) + setupCocoaLumberjack() setupLibraryLogger() setupLogLevel(.verbose) diff --git a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift index 16dc1eece35..e8ce5590e28 100644 --- a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift +++ b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift @@ -7,7 +7,7 @@ import class Networking.WordPressOrgNetwork import KeychainAccess import class WidgetKit.WidgetCenter import Experiments -import WordPressAuthenticator +import class WordPressAuthenticator.WordPressComBlogService import enum NetworkingCore.RequestAuthenticationMode // MARK: - DefaultStoresManager @@ -765,19 +765,17 @@ private extension DefaultStoresManager { self.updateAndReloadWidgetInformation(with: site.siteID) /// Trigger the `v1.1/connect/site-info` API to get information about /// the site's Jetpack status and whether it's a WPCom site. - WordPressAuthenticator.fetchSiteInfo(for: url) { [weak self] result in + let service = WordPressComBlogService() + service.fetchUnauthenticatedSiteInfoForAddress(for: url, success: { [weak self] info in guard let self else { return } - switch result { - case .success(let info): - let updatedSite = site.copy(isJetpackThePluginInstalled: info.hasJetpack, - isJetpackConnected: info.isJetpackConnected, - isWordPressComStore: info.isWPCom) - self.sessionManager.defaultSite = updatedSite - self.updateAndReloadWidgetInformation(with: site.siteID) - case .failure(let error): - DDLogError("⛔️ Cannot fetch generic site info: \(error)") - } - } + let updatedSite = site.copy(isJetpackThePluginInstalled: info.hasJetpack, + isJetpackConnected: info.isJetpackConnected, + isWordPressComStore: info.isWPCom) + sessionManager.defaultSite = updatedSite + updateAndReloadWidgetInformation(with: site.siteID) + }, failure: { error in + DDLogError("⛔️ Cannot fetch generic site info: \(error)") + }) case .failure(let error): DDLogError("⛔️ Cannot fetch WordPress site info: \(error)") } diff --git a/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift b/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift index 9aa67c5b006..26f13413d73 100644 --- a/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift +++ b/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift @@ -2,7 +2,9 @@ import Foundation // MARK: - WordPress.com BlogService // -class WordPressComBlogService { +public class WordPressComBlogService { + + public init() {} /// Returns a new anonymous instance of WordPressComRestApi. /// @@ -13,7 +15,7 @@ class WordPressComBlogService { } - func fetchUnauthenticatedSiteInfoForAddress(for address: String, success: @escaping (WordPressComSiteInfo) -> Void, failure: @escaping (Error) -> Void) { + public func fetchUnauthenticatedSiteInfoForAddress(for address: String, success: @escaping (WordPressComSiteInfo) -> Void, failure: @escaping (Error) -> Void) { let remote = BlogServiceRemoteREST(wordPressComRestApi: anonymousAPI, siteID: 0) remote.fetchUnauthenticatedSiteInfo(forAddress: address, success: { response in guard let response = response else { From 119c1fdcd8c72100c0beb4c61961f90117f97499 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Wed, 3 Dec 2025 13:15:46 +0700 Subject: [PATCH 5/5] Fix crashes in tests --- WooCommerce/Classes/AppDelegate.swift | 5 +++- .../Classes/ViewRelated/AppCoordinator.swift | 6 ++++- .../Yosemite/DefaultStoresManager.swift | 24 ++++++++++--------- .../Services/WordPressComBlogService.swift | 6 ++--- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/WooCommerce/Classes/AppDelegate.swift b/WooCommerce/Classes/AppDelegate.swift index 4ae023cb1da..8a92b388b55 100644 --- a/WooCommerce/Classes/AppDelegate.swift +++ b/WooCommerce/Classes/AppDelegate.swift @@ -57,9 +57,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let stores = ServiceLocator.stores let analytics = ServiceLocator.analytics let pushNotesManager = ServiceLocator.pushNotesManager + + /// This is important to initialize early as there are a few code points where the authenticator is used. + ServiceLocator.authenticationManager.initialize() stores.initializeAfterDependenciesAreInitialized() - setupAnalytics(analytics) + setupAnalytics(analytics) setupCocoaLumberjack() setupLibraryLogger() setupLogLevel(.verbose) diff --git a/WooCommerce/Classes/ViewRelated/AppCoordinator.swift b/WooCommerce/Classes/ViewRelated/AppCoordinator.swift index d68eada9efb..61985aca72b 100644 --- a/WooCommerce/Classes/ViewRelated/AppCoordinator.swift +++ b/WooCommerce/Classes/ViewRelated/AppCoordinator.swift @@ -238,7 +238,11 @@ private extension AppCoordinator { /// Configures the WPAuthenticator for usage in both logged-in and logged-out states. func configureAuthenticator() { - authenticationManager.initialize() + if isRunningTests { + /// This is needed to fix crashes in unit tests. + /// The authenticator is initialized in AppDelegate when running the app. + authenticationManager.initialize() + } authenticationManager.setLoggedOutAppSettings(loggedOutAppSettings) authenticationManager.displayAuthenticatorIfLoggedOut = { [weak self] in guard let self, self.isLoggedIn == false else { return nil } diff --git a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift index e8ce5590e28..16dc1eece35 100644 --- a/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift +++ b/WooCommerce/Classes/Yosemite/DefaultStoresManager.swift @@ -7,7 +7,7 @@ import class Networking.WordPressOrgNetwork import KeychainAccess import class WidgetKit.WidgetCenter import Experiments -import class WordPressAuthenticator.WordPressComBlogService +import WordPressAuthenticator import enum NetworkingCore.RequestAuthenticationMode // MARK: - DefaultStoresManager @@ -765,17 +765,19 @@ private extension DefaultStoresManager { self.updateAndReloadWidgetInformation(with: site.siteID) /// Trigger the `v1.1/connect/site-info` API to get information about /// the site's Jetpack status and whether it's a WPCom site. - let service = WordPressComBlogService() - service.fetchUnauthenticatedSiteInfoForAddress(for: url, success: { [weak self] info in + WordPressAuthenticator.fetchSiteInfo(for: url) { [weak self] result in guard let self else { return } - let updatedSite = site.copy(isJetpackThePluginInstalled: info.hasJetpack, - isJetpackConnected: info.isJetpackConnected, - isWordPressComStore: info.isWPCom) - sessionManager.defaultSite = updatedSite - updateAndReloadWidgetInformation(with: site.siteID) - }, failure: { error in - DDLogError("⛔️ Cannot fetch generic site info: \(error)") - }) + switch result { + case .success(let info): + let updatedSite = site.copy(isJetpackThePluginInstalled: info.hasJetpack, + isJetpackConnected: info.isJetpackConnected, + isWordPressComStore: info.isWPCom) + self.sessionManager.defaultSite = updatedSite + self.updateAndReloadWidgetInformation(with: site.siteID) + case .failure(let error): + DDLogError("⛔️ Cannot fetch generic site info: \(error)") + } + } case .failure(let error): DDLogError("⛔️ Cannot fetch WordPress site info: \(error)") } diff --git a/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift b/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift index 26f13413d73..9aa67c5b006 100644 --- a/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift +++ b/WooCommerce/WordPressAuthenticator/Services/WordPressComBlogService.swift @@ -2,9 +2,7 @@ import Foundation // MARK: - WordPress.com BlogService // -public class WordPressComBlogService { - - public init() {} +class WordPressComBlogService { /// Returns a new anonymous instance of WordPressComRestApi. /// @@ -15,7 +13,7 @@ public class WordPressComBlogService { } - public func fetchUnauthenticatedSiteInfoForAddress(for address: String, success: @escaping (WordPressComSiteInfo) -> Void, failure: @escaping (Error) -> Void) { + func fetchUnauthenticatedSiteInfoForAddress(for address: String, success: @escaping (WordPressComSiteInfo) -> Void, failure: @escaping (Error) -> Void) { let remote = BlogServiceRemoteREST(wordPressComRestApi: anonymousAPI, siteID: 0) remote.fetchUnauthenticatedSiteInfo(forAddress: address, success: { response in guard let response = response else {