mirror of
https://github.com/firebase/firebase-ios-sdk
synced 2026-11-11 22:55:59 +05:45
Co-authored-by: Nick Cooke <36927374+ncooke3@users.noreply.github.com>
106 lines
3.6 KiB
Swift
106 lines
3.6 KiB
Swift
// Copyright 2024 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import Foundation
|
|
|
|
#if COCOAPODS
|
|
import GTMSessionFetcher
|
|
#else
|
|
import GTMSessionFetcherCore
|
|
#endif
|
|
|
|
/// Manage Storage's fetcherService
|
|
actor StorageFetcherService {
|
|
static let shared = StorageFetcherService()
|
|
|
|
private var _fetcherService: GTMSessionFetcherService?
|
|
|
|
func service(_ storage: Storage) async -> GTMSessionFetcherService {
|
|
if let _fetcherService {
|
|
return _fetcherService
|
|
}
|
|
let app = storage.app
|
|
if let fetcherService = getFromMap(appName: app.name, bucket: storage.storageBucket) {
|
|
return fetcherService
|
|
} else {
|
|
let fetcherService = GTMSessionFetcherService()
|
|
fetcherService.isRetryEnabled = true
|
|
fetcherService.retryBlock = retryWhenOffline
|
|
fetcherService.allowLocalhostRequest = true
|
|
fetcherService.maxRetryInterval = storage.maxOperationRetryInterval
|
|
fetcherService.testBlock = testBlock
|
|
let authorizer = StorageTokenAuthorizer(
|
|
googleAppID: app.options.googleAppID,
|
|
callbackQueue: storage.callbackQueue,
|
|
authProvider: storage.auth,
|
|
appCheck: storage.appCheck,
|
|
allowInsecureTokenAttachment: { [weak storage] in
|
|
#if DEBUG
|
|
return storage?.allowInsecureTokenAttachment ?? false
|
|
#else
|
|
return false
|
|
#endif
|
|
}
|
|
)
|
|
fetcherService.authorizer = authorizer
|
|
if storage.usesEmulator {
|
|
fetcherService.allowLocalhostRequest = true
|
|
fetcherService.allowedInsecureSchemes = ["http"]
|
|
}
|
|
setMap(appName: app.name, bucket: storage.storageBucket, fetcher: fetcherService)
|
|
return fetcherService
|
|
}
|
|
}
|
|
|
|
/// Update the testBlock for unit testing. Save it as a property since this may be called before
|
|
/// fetcherService is initialized.
|
|
func updateTestBlock(_ block: GTMSessionFetcherTestBlock?) {
|
|
testBlock = block
|
|
if let _fetcherService {
|
|
_fetcherService.testBlock = testBlock
|
|
}
|
|
for bucketMap in fetcherServiceMap.values {
|
|
for fetcherService in bucketMap.values {
|
|
fetcherService.testBlock = testBlock
|
|
}
|
|
}
|
|
}
|
|
|
|
private var testBlock: GTMSessionFetcherTestBlock?
|
|
|
|
private var retryWhenOffline: GTMSessionFetcherRetryBlock = {
|
|
(suggestedWillRetry: Bool,
|
|
error: Error?,
|
|
response: @escaping GTMSessionFetcherRetryResponse) in
|
|
var shouldRetry = suggestedWillRetry
|
|
// GTMSessionFetcher does not consider being offline a retryable error, but we do, so we
|
|
// special-case it here.
|
|
if !shouldRetry, error != nil {
|
|
shouldRetry = (error as? NSError)?.code == URLError.notConnectedToInternet.rawValue
|
|
}
|
|
response(shouldRetry)
|
|
}
|
|
|
|
/// Map of apps to a dictionary of buckets to GTMSessionFetcherService.
|
|
private var fetcherServiceMap: [String: [String: GTMSessionFetcherService]] = [:]
|
|
|
|
private func getFromMap(appName: String, bucket: String) -> GTMSessionFetcherService? {
|
|
return fetcherServiceMap[appName]?[bucket]
|
|
}
|
|
|
|
private func setMap(appName: String, bucket: String, fetcher: GTMSessionFetcherService) {
|
|
fetcherServiceMap[appName, default: [:]][bucket] = fetcher
|
|
}
|
|
}
|