@@ -78,18 +78,20 @@ public class ModelDownloader {
78
78
telemetryLogger = TelemetryLogger ( app: app)
79
79
userDefaults = defaults
80
80
81
+ let notificationName = " FIRAppDeleteNotification "
81
82
NotificationCenter . default. addObserver (
82
83
self ,
83
84
selector: #selector( deleteModelDownloader) ,
84
- name: Notification . Name ( " FIRAppDeleteNotification " ) ,
85
+ name: Notification . Name ( notificationName ) ,
85
86
object: nil
86
87
)
87
88
}
88
89
89
90
/// Handles app deletion notification.
90
91
@objc private func deleteModelDownloader( notification: Notification ) {
92
+ let userInfoKey = " FIRAppNameKey "
91
93
if let userInfo = notification. userInfo,
92
- let appName = userInfo [ " FIRAppNameKey " ] as? String {
94
+ let appName = userInfo [ userInfoKey ] as? String {
93
95
ModelDownloader . modelDownloaderDictionary. removeValue ( forKey: appName)
94
96
// TODO: Clean up user defaults
95
97
// TODO: Clean up local instances of app
@@ -99,7 +101,7 @@ public class ModelDownloader {
99
101
/// Model downloader with default app.
100
102
public static func modelDownloader( ) -> ModelDownloader {
101
103
guard let defaultApp = FirebaseApp . app ( ) else {
102
- fatalError ( " Default Firebase app not configured. " )
104
+ fatalError ( ModelDownloader . ErrorDescription . defaultAppNotConfigured )
103
105
}
104
106
return modelDownloader ( app: defaultApp)
105
107
}
@@ -144,9 +146,14 @@ public class ModelDownloader {
144
146
progressHandler: nil ,
145
147
completion: { result in
146
148
switch result {
147
- // TODO: Log outcome of background download
148
149
case . success: break
149
- case . failure: break
150
+ case . failure:
151
+ DeviceLogger . logEvent (
152
+ level: . info,
153
+ category: . modelDownload,
154
+ message: ModelDownloader . ErrorDescription. backgroundModelDownload,
155
+ messageCode: . backgroundDownloadError
156
+ )
150
157
}
151
158
}
152
159
)
@@ -176,18 +183,22 @@ public class ModelDownloader {
176
183
var customModels = Set < CustomModel > ( )
177
184
for path in modelPaths {
178
185
guard let modelName = ModelFileManager . getModelNameFromFilePath ( path) else {
179
- completion ( . failure( . internalError( description: " Invalid model file name. " ) ) )
186
+ completion ( . failure( . internalError( description: ModelDownloader
187
+ . ErrorDescription
188
+ . parseModelName ( path. absoluteString) ) ) )
180
189
return
181
190
}
182
191
guard let modelInfo = getLocalModelInfo ( modelName: modelName) else {
183
192
completion (
184
- . failure( . internalError( description: " Failed to get model info for model file. " ) )
193
+ . failure( . internalError( description: ModelDownloader . ErrorDescription
194
+ . retrieveLocalModelInfo) )
185
195
)
186
196
return
187
197
}
188
198
guard modelInfo. path == path. absoluteString else {
189
199
completion (
190
- . failure( . internalError( description: " Outdated model paths in local storage. " ) )
200
+ . failure( . internalError( description: ModelDownloader . ErrorDescription
201
+ . outdatedModelPath) )
191
202
)
192
203
return
193
204
}
@@ -206,7 +217,6 @@ public class ModelDownloader {
206
217
public func deleteDownloadedModel( name modelName: String ,
207
218
completion: @escaping ( Result < Void , DownloadedModelError > )
208
219
-> Void ) {
209
- // TODO: Delete previously downloaded model
210
220
guard let localModelInfo = getLocalModelInfo ( modelName: modelName) ,
211
221
let localPath = URL ( string: localModelInfo. path)
212
222
else {
@@ -276,16 +286,18 @@ extension ModelDownloader {
276
286
progressHandler: progressHandler,
277
287
completion: completion
278
288
)
289
+ // TODO: Is it possible for download URL to expire here?
279
290
downloadTask. resumeModelDownload ( )
280
291
/// Local model info is the latest model info.
281
292
case . notModified:
282
293
guard let localModel = self . getLocalModel ( modelName: modelName) else {
283
294
DispatchQueue . main. async {
284
295
/// This can only happen if either local model info or the model file was suddenly wiped out in the middle of model info request and server response
285
- // TODO: Consider handling: if model file is deleted after local model info is retrieved but before model info network call
296
+ // TODO: Consider handling: If model file is deleted after local model info is retrieved but before model info network call.
286
297
completion (
287
298
. failure(
288
- . internalError( description: " Model unavailable due to deleted local model info. " )
299
+ . internalError( description: ModelDownloader . ErrorDescription
300
+ . deletedLocalModelInfo)
289
301
)
290
302
)
291
303
}
@@ -320,3 +332,23 @@ extension ModelDownloader {
320
332
}
321
333
}
322
334
}
335
+
336
+ /// Possible error messages while using model downloader.
337
+ extension ModelDownloader {
338
+ /// Error descriptions.
339
+ private enum ErrorDescription {
340
+ static let defaultAppNotConfigured =
341
+ " Default Firebase app not configured. "
342
+ static let parseModelName = { ( path: String ) in
343
+ " Unable to parse model file name at \( path) . "
344
+ }
345
+
346
+ static let retrieveLocalModelInfo =
347
+ " Failed to get stored model info for model file. "
348
+ static let outdatedModelPath = " Outdated model paths in local storage. "
349
+ static let deletedLocalModelInfo =
350
+ " Model unavailable due to deleted local model info. "
351
+ static let backgroundModelDownload : StaticString =
352
+ " Failed to update model in background. "
353
+ }
354
+ }
0 commit comments