blob: 1cfbc3f9ac2bb85d571e835ebc6932cbb77f4ebf [file] [log] [blame]
// 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