diff options
6 files changed, 52 insertions, 89 deletions
diff --git a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManagerError.swift b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManagerError.swift index 5e1be9b6fc..ad29ef3929 100644 --- a/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManagerError.swift +++ b/ios/MullvadVPN/AppStorePaymentManager/AppStorePaymentManagerError.swift @@ -21,7 +21,7 @@ extension AppStorePaymentManager { case storePayment(Swift.Error) /// Failure to read the AppStore receipt. - case readReceipt(AppStoreReceipt.Error) + case readReceipt(Swift.Error) /// Failure to send the AppStore receipt to backend. case sendReceipt(REST.Error) diff --git a/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift b/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift index 04a7813d4a..32295d4350 100644 --- a/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift +++ b/ios/MullvadVPN/AppStorePaymentManager/SendAppStoreReceiptOperation.swift @@ -60,7 +60,7 @@ class SendAppStoreReceiptOperation: ResultOperation< case let .failure(error): self.logger.error( - chainedError: error, + chainedError: AnyChainedError(error), message: "Failed to fetch the AppStore receipt." ) self.finish(completion: .failure(.readReceipt(error))) diff --git a/ios/MullvadVPN/AppStoreReceipt.swift b/ios/MullvadVPN/AppStoreReceipt.swift index c4bb18060c..ee1186b9b9 100644 --- a/ios/MullvadVPN/AppStoreReceipt.swift +++ b/ios/MullvadVPN/AppStoreReceipt.swift @@ -9,29 +9,13 @@ import Foundation import StoreKit -enum AppStoreReceipt { - enum Error: ChainedError { - /// AppStore receipt file does not exist or file URL is not available. - case doesNotExist - - /// IO error. - case io(Swift.Error) - - /// Failure to refresh the receipt from AppStore. - case refresh(Swift.Error) - - var errorDescription: String? { - switch self { - case .doesNotExist: - return "AppStore receipt file does not exist on disk." - case .io: - return "Read error." - case .refresh: - return "Receipt refresh error." - } - } +struct AppStoreReceiptNotFound: LocalizedError { + var errorDescription: String? { + return "AppStore receipt file does not exist on disk." } +} +enum AppStoreReceipt { /// Internal operation queue. private static let operationQueue: OperationQueue = { let queue = AsyncOperationQueue() @@ -63,9 +47,7 @@ enum AppStoreReceipt { } } -private class FetchAppStoreReceiptOperation: ResultOperation<Data, AppStoreReceipt.Error>, - SKRequestDelegate -{ +private class FetchAppStoreReceiptOperation: ResultOperation<Data, Error>, SKRequestDelegate { private var request: SKReceiptRefreshRequest? private let receiptProperties: [String: Any]? private let forceRefresh: Bool @@ -93,13 +75,15 @@ private class FetchAppStoreReceiptOperation: ResultOperation<Data, AppStoreRecei } // Read AppStore receipt from disk. - let result = readReceiptFromDisk() + do { + let data = try readReceiptFromDisk() - // Pull receipt from AppStore if it's not cached locally. - if case .failure(.doesNotExist) = result { + finish(completion: .success(data)) + } catch is AppStoreReceiptNotFound { + // Pull receipt from AppStore if it's not cached locally. startRefreshRequest() - } else { - finish(completion: OperationCompletion(result: result)) + } catch { + finish(completion: .failure(error)) } } @@ -137,32 +121,28 @@ private class FetchAppStoreReceiptOperation: ResultOperation<Data, AppStoreRecei return } - let result: Result<Data, AppStoreReceipt.Error> - if let error = error { - result = .failure(.refresh(error)) + finish(completion: .failure(error)) } else { - result = readReceiptFromDisk() - } + let result = Result { try readReceiptFromDisk() } - finish(completion: OperationCompletion(result: result)) + finish(completion: OperationCompletion(result: result)) + } } - private func readReceiptFromDisk() -> Result<Data, AppStoreReceipt.Error> { + private func readReceiptFromDisk() throws -> Data { guard let appStoreReceiptURL = Bundle.main.appStoreReceiptURL else { - return .failure(.doesNotExist) + throw AppStoreReceiptNotFound() } - let readResult = Result { try Data(contentsOf: appStoreReceiptURL) } - - return readResult.mapError { error -> AppStoreReceipt.Error in - if let cocoaError = error as? CocoaError, - cocoaError.code == .fileReadNoSuchFile || cocoaError.code == .fileNoSuchFile - { - return .doesNotExist - } else { - return .io(error) - } + do { + return try Data(contentsOf: appStoreReceiptURL) + } catch let error as CocoaError + where error.code == .fileReadNoSuchFile || error.code == .fileNoSuchFile + { + throw AppStoreReceiptNotFound() + } catch { + throw error } } } diff --git a/ios/MullvadVPN/ConsolidatedApplicationLog.swift b/ios/MullvadVPN/ConsolidatedApplicationLog.swift index b7e00b2ea9..ad5f53eda0 100644 --- a/ios/MullvadVPN/ConsolidatedApplicationLog.swift +++ b/ios/MullvadVPN/ConsolidatedApplicationLog.swift @@ -27,20 +27,6 @@ class ConsolidatedApplicationLog: TextOutputStreamable { let content: String } - enum Error: ChainedError { - case logFileDoesNotExist(String) - case invalidLogFileURL(URL) - - var errorDescription: String? { - switch self { - case let .logFileDoesNotExist(path): - return "Log file does not exist: \(path)." - case let .invalidLogFileURL(url): - return "Invalid log file URL: \(url.absoluteString)." - } - } - } - let redactCustomStrings: [String] let applicationGroupContainers: [URL] let metadata: Metadata @@ -75,8 +61,8 @@ class ConsolidatedApplicationLog: TextOutputStreamable { } } - func addError<ErrorType: ChainedError>(message: String, error: ErrorType) { - let redactedError = redact(string: error.displayChain()) + func addError(message: String, error: String) { + let redactedError = redact(string: error) logs.append(LogAttachment(label: message, content: redactedError)) } @@ -105,20 +91,22 @@ class ConsolidatedApplicationLog: TextOutputStreamable { private func addSingleLogFile(_ fileURL: URL) { guard fileURL.isFileURL else { - addError(message: fileURL.absoluteString, error: Error.invalidLogFileURL(fileURL)) + addError( + message: fileURL.absoluteString, + error: "Invalid log file URL: \(fileURL.absoluteString)." + ) return } let path = fileURL.path let redactedPath = redact(string: path) - do { - let lossyString = try Self.readFileLossy(path: path, maxBytes: kLogMaxReadBytes) + if let lossyString = Self.readFileLossy(path: path, maxBytes: kLogMaxReadBytes) { let redactedString = redact(string: lossyString) logs.append(LogAttachment(label: redactedPath, content: redactedString)) - } catch { - addError(message: redactedPath, error: AnyChainedError(error)) + } else { + addError(message: redactedPath, error: "Log file does not exist: \(path).") } } @@ -134,9 +122,9 @@ class ConsolidatedApplicationLog: TextOutputStreamable { ] } - private static func readFileLossy(path: String, maxBytes: UInt64) throws -> String { + private static func readFileLossy(path: String, maxBytes: UInt64) -> String? { guard let fileHandle = FileHandle(forReadingAtPath: path) else { - throw Error.logFileDoesNotExist(path) + return nil } let endOfFileOffset = fileHandle.seekToEndOfFile() diff --git a/ios/MullvadVPN/DisplayChainedError.swift b/ios/MullvadVPN/DisplayChainedError.swift index 15dcf930ce..f0e8efee4c 100644 --- a/ios/MullvadVPN/DisplayChainedError.swift +++ b/ios/MullvadVPN/DisplayChainedError.swift @@ -136,11 +136,14 @@ extension AppStorePaymentManager.Error: DisplayChainedError { } case let .readReceipt(readReceiptError): - switch readReceiptError { - case let .refresh(storeError): - let skErrorMessage = (storeError as? SKError)?.errorDescription ?? storeError - .localizedDescription - + if readReceiptError is AppStoreReceiptNotFound { + return NSLocalizedString( + "RECEIPT_NOT_FOUND_ERROR", + tableName: "AppStorePaymentManager", + value: "AppStore receipt is not found on disk.", + comment: "" + ) + } else if let storeError = readReceiptError as? SKError { return String( format: NSLocalizedString( "REFRESH_RECEIPT_ERROR", @@ -148,9 +151,9 @@ extension AppStorePaymentManager.Error: DisplayChainedError { value: "Cannot refresh the AppStore receipt: %@", comment: "" ), - skErrorMessage + storeError.localizedDescription ) - case let .io(ioError): + } else { return String( format: NSLocalizedString( "READ_RECEIPT_ERROR", @@ -158,14 +161,7 @@ extension AppStorePaymentManager.Error: DisplayChainedError { value: "Cannot read the AppStore receipt from disk: %@", comment: "" ), - ioError.localizedDescription - ) - case .doesNotExist: - return NSLocalizedString( - "RECEIPT_NOT_FOUND_ERROR", - tableName: "AppStorePaymentManager", - value: "AppStore receipt is not found on disk.", - comment: "" + readReceiptError.localizedDescription ) } diff --git a/ios/MullvadVPN/ProblemReportViewController.swift b/ios/MullvadVPN/ProblemReportViewController.swift index a48da7ba24..1c20ddedc0 100644 --- a/ios/MullvadVPN/ProblemReportViewController.swift +++ b/ios/MullvadVPN/ProblemReportViewController.swift @@ -283,8 +283,7 @@ class ProblemReportViewController: UIViewController, UITextFieldDelegate, Condit @objc func handleViewLogsButtonTap() { let reviewController = ProblemReportReviewViewController( - reportString: consolidatedLog - .string + reportString: consolidatedLog.string ) let navigationController = UINavigationController(rootViewController: reviewController) |
