Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MLModelDownloader] Migrate to GoogleUtilities's storage container #12762

Merged
merged 4 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion FirebaseMLModelDownloader.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ Pod::Spec.new do |s|
s.dependency 'FirebaseInstallations', '~> 10.0'
s.dependency 'GoogleDataTransport', '~> 9.2'
# TODO: Revisit this dependency
s.dependency 'GoogleUtilities/Logger', '~> 7.8'
s.dependency 'GoogleUtilities/Logger', '~> 7.13'
s.dependency 'GoogleUtilities/UserDefaults', '~> 7.13'
s.dependency 'SwiftProtobuf', '~> 1.19'

s.pod_target_xcconfig = {
Expand Down
4 changes: 2 additions & 2 deletions FirebaseMLModelDownloader/Sources/DeviceLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

import Foundation
#if SWIFT_PACKAGE
import GoogleUtilities_Logger
@_implementationOnly import GoogleUtilities_Logger
#else
import GoogleUtilities
@_implementationOnly import GoogleUtilities
#endif
ncooke3 marked this conversation as resolved.
Show resolved Hide resolved

/// Enum of log messages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
// limitations under the License.

import Foundation
#if SWIFT_PACKAGE
@_implementationOnly import GoogleUtilities_UserDefaults
#else
@_implementationOnly import GoogleUtilities
#endif // SWIFT_PACKAGE

/// Protocol to save or delete model info in user defaults.
protocol DownloaderUserDefaultsWriteable {
func writeToDefaults(_ defaults: UserDefaults, appName: String)
func removeFromDefaults(_ defaults: UserDefaults, appName: String)
func writeToDefaults(_ defaults: GULUserDefaults, appName: String)
func removeFromDefaults(_ defaults: GULUserDefaults, appName: String)
}
25 changes: 13 additions & 12 deletions FirebaseMLModelDownloader/Sources/LocalModelInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
// limitations under the License.

import Foundation
#if SWIFT_PACKAGE
@_implementationOnly import GoogleUtilities_UserDefaults
#else
@_implementationOnly import GoogleUtilities
#endif // SWIFT_PACKAGE

/// Model info object with details about downloaded and locally available model.
class LocalModelInfo {
Expand Down Expand Up @@ -41,7 +46,7 @@ class LocalModelInfo {
}

/// Convenience init to create local model info from stored info in user defaults.
convenience init?(fromDefaults defaults: UserDefaults, name: String, appName: String) {
convenience init?(fromDefaults defaults: GULUserDefaults, name: String, appName: String) {
let defaultsPrefix = LocalModelInfo.getUserDefaultsKeyPrefix(appName: appName, modelName: name)
guard let modelHash = defaults.string(forKey: "\(defaultsPrefix).model-hash") else {
return nil
Expand All @@ -60,26 +65,22 @@ extension LocalModelInfo: DownloaderUserDefaultsWriteable {
}

/// Write local model info to user defaults.
func writeToDefaults(_ defaults: UserDefaults, appName: String) {
func writeToDefaults(_ defaults: GULUserDefaults, appName: String) {
let defaultsPrefix = LocalModelInfo.getUserDefaultsKeyPrefix(appName: appName, modelName: name)
defaults.setValue(modelHash, forKey: "\(defaultsPrefix).model-hash")
defaults.setValue(size, forKey: "\(defaultsPrefix).model-size")
defaults.setObject(modelHash, forKey: "\(defaultsPrefix).model-hash")
defaults.setObject(size, forKey: "\(defaultsPrefix).model-size")
}

func removeFromDefaults(_ defaults: UserDefaults, appName: String) {
func removeFromDefaults(_ defaults: GULUserDefaults, appName: String) {
let defaultsPrefix = LocalModelInfo.getUserDefaultsKeyPrefix(appName: appName, modelName: name)
defaults.removeObject(forKey: "\(defaultsPrefix).model-hash")
defaults.removeObject(forKey: "\(defaultsPrefix).model-size")
}
}

/// Named user defaults for FirebaseML.
extension UserDefaults {
static var firebaseMLDefaults: UserDefaults {
let suiteName = "com.google.firebase.ml"
guard let defaults = UserDefaults(suiteName: suiteName) else {
return UserDefaults.standard
}
return defaults
extension GULUserDefaults {
static var firebaseMLDefaults: GULUserDefaults {
return GULUserDefaults(suiteName: "com.google.firebase.ml")
}
}
9 changes: 7 additions & 2 deletions FirebaseMLModelDownloader/Sources/ModelDownloadTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
// limitations under the License.

import Foundation
#if SWIFT_PACKAGE
@_implementationOnly import GoogleUtilities_UserDefaults
#else
@_implementationOnly import GoogleUtilities
#endif // SWIFT_PACKAGE

/// Task to download model file to device.
class ModelDownloadTask {
Expand All @@ -23,7 +28,7 @@ class ModelDownloadTask {
private(set) var remoteModelInfo: RemoteModelInfo

/// User defaults to which local model info should ultimately be written.
private let defaults: UserDefaults
private let defaults: GULUserDefaults

/// Keeps track of download associated with this model download task.
private(set) var downloadStatus: ModelDownloadStatus = .ready
Expand All @@ -44,7 +49,7 @@ class ModelDownloadTask {

init(remoteModelInfo: RemoteModelInfo,
appName: String,
defaults: UserDefaults,
defaults: GULUserDefaults,
downloader: FileDownloader,
progressHandler: ProgressHandler? = nil,
completion: @escaping Completion,
Expand Down
11 changes: 8 additions & 3 deletions FirebaseMLModelDownloader/Sources/ModelDownloader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
import FirebaseCore
import FirebaseInstallations
import Foundation
#if SWIFT_PACKAGE
@_implementationOnly import GoogleUtilities_UserDefaults
#else
@_implementationOnly import GoogleUtilities
#endif // SWIFT_PACKAGE

/// Possible ways to get a custom model.
public enum ModelDownloadType {
Expand All @@ -41,7 +46,7 @@ public class ModelDownloader {
private let installations: Installations

/// User defaults for model info.
private let userDefaults: UserDefaults
private let userDefaults: GULUserDefaults

/// Telemetry logger tied to this instance of model downloader.
let telemetryLogger: TelemetryLogger?
Expand All @@ -67,7 +72,7 @@ public class ModelDownloader {
}

/// Private init for model downloader.
private init(app: FirebaseApp, defaults: UserDefaults = .firebaseMLDefaults) {
private init(app: FirebaseApp, defaults: GULUserDefaults = .firebaseMLDefaults) {
appName = app.name
options = app.options
installations = Installations.installations(app: app)
Expand Down Expand Up @@ -641,7 +646,7 @@ extension ModelDownloader {
/// Model downloader extension for testing.
extension ModelDownloader {
/// Model downloader instance for testing.
static func modelDownloaderWithDefaults(_ defaults: UserDefaults,
static func modelDownloaderWithDefaults(_ defaults: GULUserDefaults,
app: FirebaseApp) -> ModelDownloader {
let downloader = ModelDownloader(app: app, defaults: defaults)
return downloader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,26 @@
@testable import FirebaseInstallations
@testable import FirebaseMLModelDownloader
import XCTest

extension UserDefaults {
/// Returns a new cleared instance of user defaults.
static func createTestInstance(testName: String) -> UserDefaults {
#if SWIFT_PACKAGE
@_implementationOnly import GoogleUtilities_UserDefaults
#else
@_implementationOnly import GoogleUtilities
#endif // SWIFT_PACKAGE

extension GULUserDefaults {
/// Returns an instance of user defaults.
static func createTestInstance(testName: String) -> GULUserDefaults {
let suiteName = "com.google.firebase.ml.test.\(testName)"
let defaults = UserDefaults(suiteName: suiteName)!
defaults.removePersistentDomain(forName: suiteName)
return defaults
// Clear the suite (`UserDefaults` and `GULUserDefaults` map to the same
// storage space and `GULUserDefaults` doesn't offer API to do this.)
UserDefaults(suiteName: suiteName)!.removePersistentDomain(forName: suiteName)
return GULUserDefaults(suiteName: suiteName)
}

/// Returns the existing user defaults instance.
static func getTestInstance(testName: String) -> UserDefaults {
static func getTestInstance(testName: String) -> GULUserDefaults {
let suiteName = "com.google.firebase.ml.test.\(testName)"
return UserDefaults(suiteName: suiteName)!
return GULUserDefaults(suiteName: suiteName)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
@testable import FirebaseInstallations
@testable import FirebaseMLModelDownloader
import XCTest
#if SWIFT_PACKAGE
@_implementationOnly import GoogleUtilities_Logger
@_implementationOnly import GoogleUtilities_UserDefaults
#else
@_implementationOnly import GoogleUtilities
#endif // SWIFT_PACKAGE

/// Mock options to configure default Firebase app.
private enum MockOptions {
Expand Down Expand Up @@ -1325,19 +1331,18 @@
}
}

extension UserDefaults {
/// Returns a new cleared instance of user defaults.
static func createUnitTestInstance(testName: String) -> UserDefaults {
extension GULUserDefaults {
/// Returns a new instance of user defaults.
static func createUnitTestInstance(testName: String) -> GULUserDefaults {
let suiteName = "com.google.firebase.ml.test.\(testName)"
let defaults = UserDefaults(suiteName: suiteName)!
defaults.removePersistentDomain(forName: suiteName)
let defaults = GULUserDefaults(suiteName: suiteName)
return defaults
}

/// Returns the existing user defaults instance.
static func getUnitTestInstance(testName: String) -> UserDefaults {
static func getUnitTestInstance(testName: String) -> GULUserDefaults {
let suiteName = "com.google.firebase.ml.test.\(testName)"
return UserDefaults(suiteName: suiteName)!
return GULUserDefaults(suiteName: suiteName)
}
}

Expand Down
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,7 @@ let package = Package(
"FirebaseInstallations",
.product(name: "GoogleDataTransport", package: "GoogleDataTransport"),
.product(name: "GULLogger", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
.product(name: "SwiftProtobuf", package: "swift-protobuf"),
],
path: "FirebaseMLModelDownloader/Sources",
Expand Down
Loading