Added unit test for DevTools' ephemeral port support.
[chromium-blink-merge.git] / remoting / ios / data_store.mm
blob1cfbc3f9ac2bb85d571e835ebc6932cbb77f4ebf
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."
7 #endif
9 #import "remoting/ios/data_store.h"
11 @interface DataStore (Private)
12 - (NSString*)itemArchivePath;
13 @end
15 @implementation DataStore {
16  @private
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]; });
29   return sharedStore;
32 // General methods
33 + (id)allocWithZone:(NSZone*)zone {
34   return [self sharedStore];
37 // Load data store from SQLLite backing store
38 - (id)init {
39   self = [super init];
41   if (self) {
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];
51     NSError* error = nil;
53     NSDictionary* tryOptions = @{
54       NSMigratePersistentStoresAutomaticallyOption : @YES,
55       NSInferMappingModelAutomaticallyOption : @YES
56     };
57     NSDictionary* makeOptions =
58         @{NSMigratePersistentStoresAutomaticallyOption : @YES};
60     if (![psc addPersistentStoreWithType:NSSQLiteStoreType
61                            configuration:nil
62                                      URL:storeUrl
63                                  options:tryOptions
64                                    error:&error]) {
65       // An incompatible version of the store exists, delete it and start over
66       [[NSFileManager defaultManager] removeItemAtURL:storeUrl error:nil];
68       [psc addPersistentStoreWithType:NSSQLiteStoreType
69                         configuration:nil
70                                   URL:storeUrl
71                               options:makeOptions
72                                 error:&error];
73       [NSException raise:@"Open failed"
74                   format:@"Reason: %@", [error localizedDescription]];
75     }
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];
84     _allHosts = nil;
85   }
86   return self;
89 // Committing to backing store
90 - (BOOL)saveChanges {
91   NSError* err = nil;
92   BOOL successful = [_context save:&err];
93   return successful;
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
108 // load it now
109 - (NSArray*)allHosts {
110   if (!_allHosts) {
111     NSFetchRequest* request = [[NSFetchRequest alloc] init];
113     NSEntityDescription* e =
114         [[_model entitiesByName] objectForKey:@"HostPreferences"];
116     [request setEntity:e];
118     NSError* error;
119     NSArray* result = [_context executeFetchRequest:request error:&error];
120     if (!result) {
121       [NSException raise:@"Fetch failed"
122                   format:@"Reason: %@", [error localizedDescription]];
123     }
124     _allHosts = [result mutableCopy];
125   }
127   return _allHosts;
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];
136   if (p == nil) {
137     p = [NSEntityDescription insertNewObjectForEntityForName:@"HostPreferences"
138                                       inManagedObjectContext:_context];
139     p.hostId = hostId;
140     [_allHosts addObject:p];
141   }
142   return 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];
163   NSError* error;
164   NSArray* result = [_context executeFetchRequest:request error:&error];
165   if (!result) {
166     [NSException raise:@"Fetch failed"
167                 format:@"Reason: %@", [error localizedDescription]];
168   }
170   for (HostPreferences* curHost in result) {
171     return curHost;
172   }
173   return nil;
176 @end