Chromium Code Reviews| 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..2497596232e5e934a7fee55d0bd13c1a0421d7d1 |
| --- /dev/null |
| +++ b/remoting/ios/data_store.mm |
| @@ -0,0 +1,181 @@ |
| +// 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]; }); |
|
dcaiafa
2014/03/19 01:14:15
Why allocWithZone instead of just alloc?
aboone
2014/03/21 16:42:07
allocWithZone has been overridden to always return
|
| + |
| + 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; |
| + |
| + if (![psc |
| + addPersistentStoreWithType:NSSQLiteStoreType |
| + configuration:nil |
| + URL:storeUrl |
| + options: |
| + @{ |
|
dcaiafa
2014/03/19 01:14:15
Maybe use a intermediate local variable for this N
aboone
2014/03/21 16:42:07
Done.
|
| + NSMigratePersistentStoresAutomaticallyOption : |
| + @YES, |
| + NSInferMappingModelAutomaticallyOption : |
| + @YES |
| + } |
| + error:&error]) { |
| + // An incompatiable version of the store exists, delete it and start over |
| + [[NSFileManager defaultManager] removeItemAtURL:storeUrl error:nil]; |
| + |
| + [psc |
| + addPersistentStoreWithType:NSSQLiteStoreType |
| + configuration:nil |
| + URL:storeUrl |
| + options: |
| + @{ |
| + NSMigratePersistentStoresAutomaticallyOption : |
| + @YES |
| + } |
| + 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; |
| +} |
| + |
| +// Commiting 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 |