Index: remoting/ios/data_store.mm |
diff --git a/remoting/ios/data_store.mm b/remoting/ios/data_store.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1cfbc3f9ac2bb85d571e835ebc6932cbb77f4ebf |
--- /dev/null |
+++ b/remoting/ios/data_store.mm |
@@ -0,0 +1,176 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#if !defined(__has_feature) || !__has_feature(objc_arc) |
+#error "This file requires ARC support." |
+#endif |
+ |
+#import "remoting/ios/data_store.h" |
+ |
+@interface DataStore (Private) |
+- (NSString*)itemArchivePath; |
+@end |
+ |
+@implementation DataStore { |
+ @private |
+ NSMutableArray* _allHosts; |
+ NSManagedObjectContext* _context; |
+ NSManagedObjectModel* _model; |
+} |
+ |
+// Create or Get a static data store |
++ (DataStore*)sharedStore { |
+ static DataStore* sharedStore = nil; |
+ static dispatch_once_t onceToken; |
+ dispatch_once(&onceToken, |
+ ^{ sharedStore = [[super allocWithZone:nil] init]; }); |
+ |
+ return sharedStore; |
+} |
+ |
+// General methods |
++ (id)allocWithZone:(NSZone*)zone { |
+ return [self sharedStore]; |
+} |
+ |
+// Load data store from SQLLite backing store |
+- (id)init { |
+ self = [super init]; |
+ |
+ if (self) { |
+ // Read in ChromotingModel.xdatamodeld |
+ _model = [NSManagedObjectModel mergedModelFromBundles:nil]; |
+ |
+ NSPersistentStoreCoordinator* psc = [[NSPersistentStoreCoordinator alloc] |
+ initWithManagedObjectModel:_model]; |
+ |
+ NSString* path = [self itemArchivePath]; |
+ NSURL* storeUrl = [NSURL fileURLWithPath:path]; |
+ |
+ NSError* error = nil; |
+ |
+ NSDictionary* tryOptions = @{ |
+ NSMigratePersistentStoresAutomaticallyOption : @YES, |
+ NSInferMappingModelAutomaticallyOption : @YES |
+ }; |
+ NSDictionary* makeOptions = |
+ @{NSMigratePersistentStoresAutomaticallyOption : @YES}; |
+ |
+ if (![psc addPersistentStoreWithType:NSSQLiteStoreType |
+ configuration:nil |
+ URL:storeUrl |
+ options:tryOptions |
+ error:&error]) { |
+ // An incompatible version of the store exists, delete it and start over |
+ [[NSFileManager defaultManager] removeItemAtURL:storeUrl error:nil]; |
+ |
+ [psc addPersistentStoreWithType:NSSQLiteStoreType |
+ configuration:nil |
+ URL:storeUrl |
+ options:makeOptions |
+ error:&error]; |
+ [NSException raise:@"Open failed" |
+ format:@"Reason: %@", [error localizedDescription]]; |
+ } |
+ |
+ // Create the managed object context |
+ _context = [[NSManagedObjectContext alloc] init]; |
+ [_context setPersistentStoreCoordinator:psc]; |
+ |
+ // The managed object context can manage undo, but we don't need it |
+ [_context setUndoManager:nil]; |
+ |
+ _allHosts = nil; |
+ } |
+ return self; |
+} |
+ |
+// Committing to backing store |
+- (BOOL)saveChanges { |
+ NSError* err = nil; |
+ BOOL successful = [_context save:&err]; |
+ return successful; |
+} |
+ |
+// Looking up the backing store path |
+- (NSString*)itemArchivePath { |
+ NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains( |
+ NSDocumentDirectory, NSUserDomainMask, YES); |
+ |
+ // Get one and only document directory from that list |
+ NSString* documentDirectory = [documentDirectories objectAtIndex:0]; |
+ |
+ return [documentDirectory stringByAppendingPathComponent:@"store.data"]; |
+} |
+ |
+// Return an array of all known hosts, if the list hasn't been loaded yet, then |
+// load it now |
+- (NSArray*)allHosts { |
+ if (!_allHosts) { |
+ NSFetchRequest* request = [[NSFetchRequest alloc] init]; |
+ |
+ NSEntityDescription* e = |
+ [[_model entitiesByName] objectForKey:@"HostPreferences"]; |
+ |
+ [request setEntity:e]; |
+ |
+ NSError* error; |
+ NSArray* result = [_context executeFetchRequest:request error:&error]; |
+ if (!result) { |
+ [NSException raise:@"Fetch failed" |
+ format:@"Reason: %@", [error localizedDescription]]; |
+ } |
+ _allHosts = [result mutableCopy]; |
+ } |
+ |
+ return _allHosts; |
+} |
+ |
+// Return a HostPreferences if it already exists, otherwise create a new |
+// HostPreferences to use |
+- (const HostPreferences*)createHost:(NSString*)hostId { |
+ |
+ const HostPreferences* p = [self getHostForId:hostId]; |
+ |
+ if (p == nil) { |
+ p = [NSEntityDescription insertNewObjectForEntityForName:@"HostPreferences" |
+ inManagedObjectContext:_context]; |
+ p.hostId = hostId; |
+ [_allHosts addObject:p]; |
+ } |
+ return p; |
+} |
+ |
+- (void)removeHost:(HostPreferences*)p { |
+ [_context deleteObject:p]; |
+ [_allHosts removeObjectIdenticalTo:p]; |
+} |
+ |
+// Search the store for any matching HostPreferences |
+// return the 1st match or nil |
+- (const HostPreferences*)getHostForId:(NSString*)hostId { |
+ NSFetchRequest* request = [[NSFetchRequest alloc] init]; |
+ |
+ NSEntityDescription* e = |
+ [[_model entitiesByName] objectForKey:@"HostPreferences"]; |
+ [request setEntity:e]; |
+ |
+ NSPredicate* predicate = |
+ [NSPredicate predicateWithFormat:@"(hostId = %@)", hostId]; |
+ [request setPredicate:predicate]; |
+ |
+ NSError* error; |
+ NSArray* result = [_context executeFetchRequest:request error:&error]; |
+ if (!result) { |
+ [NSException raise:@"Fetch failed" |
+ format:@"Reason: %@", [error localizedDescription]]; |
+ } |
+ |
+ for (HostPreferences* curHost in result) { |
+ return curHost; |
+ } |
+ return nil; |
+} |
+ |
+@end |