From 2fe66404b8709e0f3d21b1ec20c1703dc807d3af Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Tue, 10 Dec 2024 16:00:58 -0600 Subject: [PATCH 1/4] Add flagged logout avoidance from background task The flag is `avoid_logout_in_background` # Conflicts: # Modules/Utils/Sources/PocketCastsUtils/Feature Flags/FeatureFlag.swift # Conflicts: # Modules/Utils/Sources/PocketCastsUtils/Feature Flags/FeatureFlag.swift --- .../Private/TokenHelper.swift | 22 +++++++++++-------- .../Public/ServerConfig.swift | 1 + .../Feature Flags/FeatureFlag.swift | 10 +++++++++ podcasts/AppDelegate.swift | 1 + 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift b/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift index f3f4a99c9f..9a94d0e575 100644 --- a/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift +++ b/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift @@ -85,17 +85,21 @@ class TokenHelper { ServerSettings.setRefreshToken(refreshedRefreshToken) } else { - if ServerConfig.avoidLogoutOnError { - // if the user doesn't have an email and password or SSO token, they aren't going to be able to acquire a sync token - switch error as? APIError { - case APIError.TOKEN_DEAUTH?, APIError.PERMISSION_DENIED?: + if UIApplication.shared.applicationState == .background && ServerConfig.avoidLogoutInBackground { + FileLog.shared.addMessage("TokenHelper: Skipped logout in background due to error: \(String(describing: error))") + } else { + if ServerConfig.avoidLogoutOnError { + // if the user doesn't have an email and password or SSO token, they aren't going to be able to acquire a sync token + switch error as? APIError { + case APIError.TOKEN_DEAUTH?, APIError.PERMISSION_DENIED?: + tokenCleanUp() + default: + // Do nothing so the user is not disrupted in the case of non-auth errors + FileLog.shared.addMessage("TokenHelper: Unable to acquire token but avoided logout due to error: \(String(describing: error))") + } + } else { tokenCleanUp() - default: - // Do nothing so the user is not disrupted in the case of non-auth errors - FileLog.shared.addMessage("TokenHelper: Unable to acquire token but avoided logout due to error: \(String(describing: error))") } - } else { - tokenCleanUp() } return nil diff --git a/Modules/Server/Sources/PocketCastsServer/Public/ServerConfig.swift b/Modules/Server/Sources/PocketCastsServer/Public/ServerConfig.swift index c02a34b49b..5ab9697bdd 100644 --- a/Modules/Server/Sources/PocketCastsServer/Public/ServerConfig.swift +++ b/Modules/Server/Sources/PocketCastsServer/Public/ServerConfig.swift @@ -4,6 +4,7 @@ public class ServerConfig { public static let shared = ServerConfig() public static var avoidLogoutOnError = false + public static var avoidLogoutInBackground = false private var backgroundSessionHandler: (() -> Void)? diff --git a/Modules/Utils/Sources/PocketCastsUtils/Feature Flags/FeatureFlag.swift b/Modules/Utils/Sources/PocketCastsUtils/Feature Flags/FeatureFlag.swift index 62ef2c5a12..dbfd1037d0 100644 --- a/Modules/Utils/Sources/PocketCastsUtils/Feature Flags/FeatureFlag.swift +++ b/Modules/Utils/Sources/PocketCastsUtils/Feature Flags/FeatureFlag.swift @@ -146,6 +146,12 @@ public enum FeatureFlag: String, CaseIterable { /// Uses the episode IDs from the server's response rather than our local database IDs case useSyncResponseEpisodeIDs + ///Use html description for podcast details + case usePodcastHTMLDescription + + /// Disables logout / keychain clearing when errors occur in the background + case avoidLogoutInBackground + public var enabled: Bool { if let overriddenValue = FeatureFlagOverrideStore().overriddenValue(for: self) { return overriddenValue @@ -244,6 +250,10 @@ public enum FeatureFlag: String, CaseIterable { true case .useSyncResponseEpisodeIDs: true + case .usePodcastHTMLDescription: + false + case .avoidLogoutInBackground: + true } } diff --git a/podcasts/AppDelegate.swift b/podcasts/AppDelegate.swift index 2e463bcbb0..ef4c1b9ae1 100644 --- a/podcasts/AppDelegate.swift +++ b/podcasts/AppDelegate.swift @@ -296,6 +296,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { self?.updateEndOfYearRemoteValue() self?.updateRemoteFeatureFlags() ServerConfig.avoidLogoutOnError = FeatureFlag.errorLogoutHandling.enabled + ServerConfig.avoidLogoutInBackground = FeatureFlag.avoidLogoutInBackground.enabled } } From 8c8e6dac674de29956569852329ed4a4d6973886 Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Wed, 11 Dec 2024 08:07:40 -0600 Subject: [PATCH 2/4] Dispatch application background check to main thread --- .../Private/TokenHelper.swift | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift b/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift index 9a94d0e575..656f26570d 100644 --- a/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift +++ b/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift @@ -85,7 +85,7 @@ class TokenHelper { ServerSettings.setRefreshToken(refreshedRefreshToken) } else { - if UIApplication.shared.applicationState == .background && ServerConfig.avoidLogoutInBackground { + if isApplicationBackgrounded() && ServerConfig.avoidLogoutInBackground { FileLog.shared.addMessage("TokenHelper: Skipped logout in background due to error: \(String(describing: error))") } else { if ServerConfig.avoidLogoutOnError { @@ -108,6 +108,24 @@ class TokenHelper { return refreshedToken } + private func isApplicationBackgrounded() -> Bool { + let semaphore = DispatchSemaphore(value: 0) + var isBackgrounded = false + + DispatchQueue.main.async { + #if os(iOS) + isBackgrounded = UIApplication.shared.applicationState == .background + #elseif os(watchOS) + isBackgrounded = WKExtension.shared().applicationState == .background + #endif + + semaphore.signal() + } + + semaphore.wait() + return isBackgrounded + } + // MARK: - Email / Password Token func acquirePasswordToken() throws -> AuthenticationResponse? { From 1ba5612bfdf40aeface13646ad5be850c5473355 Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Thu, 12 Dec 2024 21:41:23 -0700 Subject: [PATCH 3/4] Import UIKit + WatchKit --- .../Sources/PocketCastsServer/Private/TokenHelper.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift b/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift index 656f26570d..e8c4dff0b3 100644 --- a/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift +++ b/Modules/Server/Sources/PocketCastsServer/Private/TokenHelper.swift @@ -1,5 +1,10 @@ import Foundation import PocketCastsUtils +#if os(iOS) +import UIKit +#elseif os(watchOS) +import WatchKit +#endif class TokenHelper { From 7a3938dfc9fc4ca32c3f2a717bb0020f63aa2d95 Mon Sep 17 00:00:00 2001 From: Brandon Titus Date: Mon, 23 Dec 2024 15:08:56 -0700 Subject: [PATCH 4/4] Add changelog entry for background logout removal --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0952116e7a..7c7da0f50f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ 7.79 ----- - Display the whole chapter title, without truncating it [#2499](https://github.com/Automattic/pocket-casts-ios/pull/2499) +- Remove logout from failed background HTTP requests. [#2586](https://github.com/Automattic/pocket-casts-ios/pull/2586) 7.78 -----