StorageFactory.swift 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Copyright 2021 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Foundation
  15. private enum Constants {
  16. /// The name of the file system directory where heartbeat data is stored.
  17. static let heartbeatFileStorageDirectoryPath = "google-heartbeat-storage"
  18. /// The name of the user defaults suite where heartbeat data is stored.
  19. static let heartbeatUserDefaultsSuiteName = "com.google.heartbeat.storage"
  20. }
  21. /// A factory type for `Storage`.
  22. protocol StorageFactory {
  23. static func makeStorage(id: String) -> Storage
  24. }
  25. // MARK: - FileStorage + StorageFactory
  26. extension FileStorage: StorageFactory {
  27. static func makeStorage(id: String) -> Storage {
  28. let rootDirectory = FileManager.default.applicationSupportDirectory
  29. let heartbeatDirectoryPath = Constants.heartbeatFileStorageDirectoryPath
  30. // Sanitize the `id` so the heartbeat file name does not include a ":".
  31. let sanitizedID = id.replacingOccurrences(of: ":", with: "_")
  32. let heartbeatFilePath = "heartbeats-\(sanitizedID)"
  33. let storageURL = rootDirectory
  34. .appendingPathComponent(heartbeatDirectoryPath, isDirectory: true)
  35. .appendingPathComponent(heartbeatFilePath, isDirectory: false)
  36. return FileStorage(url: storageURL)
  37. }
  38. }
  39. extension FileManager {
  40. var applicationSupportDirectory: URL {
  41. urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
  42. }
  43. }
  44. // MARK: - UserDefaultsStorage + StorageFactory
  45. extension UserDefaultsStorage: StorageFactory {
  46. static func makeStorage(id: String) -> Storage {
  47. let suiteName = Constants.heartbeatUserDefaultsSuiteName
  48. // It's safe to force unwrap the below defaults instance because the
  49. // initializer only returns `nil` when the bundle id or `globalDomain`
  50. // is passed in as the `suiteName`.
  51. let defaults = UserDefaults(suiteName: suiteName)!
  52. let key = "heartbeats-\(id)"
  53. return UserDefaultsStorage(defaults: defaults, key: key)
  54. }
  55. }