1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #if !defined(__has_feature) || !__has_feature(objc_arc)
6 #error "This file requires ARC support."
9 #import "remoting/ios/data_store.h"
11 @interface DataStore (Private)
12 - (NSString*)itemArchivePath;
15 @implementation DataStore {
17 NSMutableArray* _allHosts;
18 NSManagedObjectContext* _context;
19 NSManagedObjectModel* _model;
22 // Create or Get a static data store
23 + (DataStore*)sharedStore {
24 static DataStore* sharedStore = nil;
25 static dispatch_once_t onceToken;
26 dispatch_once(&onceToken,
27 ^{ sharedStore = [[super allocWithZone:nil] init]; });
33 + (id)allocWithZone:(NSZone*)zone {
34 return [self sharedStore];
37 // Load data store from SQLLite backing store
42 // Read in ChromotingModel.xdatamodeld
43 _model = [NSManagedObjectModel mergedModelFromBundles:nil];
45 NSPersistentStoreCoordinator* psc = [[NSPersistentStoreCoordinator alloc]
46 initWithManagedObjectModel:_model];
48 NSString* path = [self itemArchivePath];
49 NSURL* storeUrl = [NSURL fileURLWithPath:path];
53 NSDictionary* tryOptions = @{
54 NSMigratePersistentStoresAutomaticallyOption : @YES,
55 NSInferMappingModelAutomaticallyOption : @YES
57 NSDictionary* makeOptions =
58 @{NSMigratePersistentStoresAutomaticallyOption : @YES};
60 if (![psc addPersistentStoreWithType:NSSQLiteStoreType
65 // An incompatible version of the store exists, delete it and start over
66 [[NSFileManager defaultManager] removeItemAtURL:storeUrl error:nil];
68 [psc addPersistentStoreWithType:NSSQLiteStoreType
73 [NSException raise:@"Open failed"
74 format:@"Reason: %@", [error localizedDescription]];
77 // Create the managed object context
78 _context = [[NSManagedObjectContext alloc] init];
79 [_context setPersistentStoreCoordinator:psc];
81 // The managed object context can manage undo, but we don't need it
82 [_context setUndoManager:nil];
89 // Committing to backing store
92 BOOL successful = [_context save:&err];
96 // Looking up the backing store path
97 - (NSString*)itemArchivePath {
98 NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(
99 NSDocumentDirectory, NSUserDomainMask, YES);
101 // Get one and only document directory from that list
102 NSString* documentDirectory = [documentDirectories objectAtIndex:0];
104 return [documentDirectory stringByAppendingPathComponent:@"store.data"];
107 // Return an array of all known hosts, if the list hasn't been loaded yet, then
109 - (NSArray*)allHosts {
111 NSFetchRequest* request = [[NSFetchRequest alloc] init];
113 NSEntityDescription* e =
114 [[_model entitiesByName] objectForKey:@"HostPreferences"];
116 [request setEntity:e];
119 NSArray* result = [_context executeFetchRequest:request error:&error];
121 [NSException raise:@"Fetch failed"
122 format:@"Reason: %@", [error localizedDescription]];
124 _allHosts = [result mutableCopy];
130 // Return a HostPreferences if it already exists, otherwise create a new
131 // HostPreferences to use
132 - (const HostPreferences*)createHost:(NSString*)hostId {
134 const HostPreferences* p = [self getHostForId:hostId];
137 p = [NSEntityDescription insertNewObjectForEntityForName:@"HostPreferences"
138 inManagedObjectContext:_context];
140 [_allHosts addObject:p];
145 - (void)removeHost:(HostPreferences*)p {
146 [_context deleteObject:p];
147 [_allHosts removeObjectIdenticalTo:p];
150 // Search the store for any matching HostPreferences
151 // return the 1st match or nil
152 - (const HostPreferences*)getHostForId:(NSString*)hostId {
153 NSFetchRequest* request = [[NSFetchRequest alloc] init];
155 NSEntityDescription* e =
156 [[_model entitiesByName] objectForKey:@"HostPreferences"];
157 [request setEntity:e];
159 NSPredicate* predicate =
160 [NSPredicate predicateWithFormat:@"(hostId = %@)", hostId];
161 [request setPredicate:predicate];
164 NSArray* result = [_context executeFetchRequest:request error:&error];
166 [NSException raise:@"Fetch failed"
167 format:@"Reason: %@", [error localizedDescription]];
170 for (HostPreferences* curHost in result) {