Identifiers.swift 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. //
  2. // Copyright 2022 Google LLC
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. import Foundation
  16. @_implementationOnly import FirebaseInstallations
  17. protocol IdentifierProvider {
  18. var installationID: String {
  19. get
  20. }
  21. var sessionID: String {
  22. get
  23. }
  24. var previousSessionID: String? {
  25. get
  26. }
  27. }
  28. ///
  29. /// Identifiers is responsible for:
  30. /// 1) Getting the Installation ID from Installations
  31. /// 2) Generating the Session ID
  32. /// 3) Persisting and reading the Session ID from the last session
  33. /// (Maybe) 4) Persisting, reading, and incrementing an increasing index
  34. ///
  35. class Identifiers: IdentifierProvider {
  36. private let installations: InstallationsProtocol
  37. private var _sessionID: String?
  38. private var _previousSessionID: String?
  39. init(installations: InstallationsProtocol) {
  40. self.installations = installations
  41. }
  42. // Generates a new Session ID. If there was already a generated Session ID
  43. // from the last session during the app's lifecycle, it will also set the last Session ID
  44. func generateNewSessionID() {
  45. _previousSessionID = _sessionID
  46. _sessionID = UUID().uuidString.replacingOccurrences(of: "-", with: "").lowercased()
  47. }
  48. // Fetches the Installation ID from Firebase Installation Service. This method must be run on a background thread due to how Firebase Installations
  49. // handles threading.
  50. var installationID: String {
  51. if Thread.isMainThread {
  52. Logger
  53. .logError(
  54. "Error: Identifiers.installationID getter must be called on a background thread. Using an empty ID"
  55. )
  56. return ""
  57. }
  58. var localInstallationID = ""
  59. let semaphore = DispatchSemaphore(value: 0)
  60. installations.installationID { result in
  61. switch result {
  62. case let .success(fiid):
  63. localInstallationID = fiid
  64. case let .failure(error):
  65. Logger
  66. .logError(
  67. "Error getting Firebase Installation ID: \(error). Using an empty ID"
  68. )
  69. }
  70. semaphore.signal()
  71. }
  72. switch semaphore.wait(timeout: DispatchTime.now() + 1.0) {
  73. case .success:
  74. break
  75. case .timedOut:
  76. Logger.logError("Error: took too long to get the Firebase Installation ID. Using an empty ID")
  77. }
  78. return localInstallationID
  79. }
  80. var sessionID: String {
  81. guard let _sessionID = _sessionID else {
  82. Logger.logError("Error: Sessions SDK did not generate a Session ID")
  83. return ""
  84. }
  85. return _sessionID
  86. }
  87. var previousSessionID: String? {
  88. return _previousSessionID
  89. }
  90. }