OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/web/public/crw_browsing_data_store.h" | 5 #import "ios/web/public/crw_browsing_data_store.h" |
6 | 6 |
7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
8 | 8 |
9 #include "base/ios/ios_util.h" | 9 #include "base/ios/ios_util.h" |
10 #import "base/ios/weak_nsobject.h" | 10 #import "base/ios/weak_nsobject.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 // thread. | 37 // thread. |
38 @property(nonatomic, readonly) NSArray* allBrowsingDataManagers; | 38 @property(nonatomic, readonly) NSArray* allBrowsingDataManagers; |
39 // Returns an array of browsing data managers for the given |browsingDataTypes|. | 39 // Returns an array of browsing data managers for the given |browsingDataTypes|. |
40 - (NSArray*)browsingDataManagersForBrowsingDataTypes: | 40 - (NSArray*)browsingDataManagersForBrowsingDataTypes: |
41 (web::BrowsingDataTypes)browsingDataTypes; | 41 (web::BrowsingDataTypes)browsingDataTypes; |
42 | 42 |
43 // Redefined to be read-write. Must be called from the main thread. | 43 // Redefined to be read-write. Must be called from the main thread. |
44 @property(nonatomic, assign) CRWBrowsingDataStoreMode mode; | 44 @property(nonatomic, assign) CRWBrowsingDataStoreMode mode; |
45 // Sets the mode iff there are no more stash or restore operations that are | 45 // Sets the mode iff there are no more stash or restore operations that are |
46 // still pending. |mode| can only be either |ACTIVE| or |INACTIVE|. | 46 // still pending. |mode| can only be either |ACTIVE| or |INACTIVE|. |
47 - (void)setModeIfNotStashingOrRestoring:(CRWBrowsingDataStoreMode)mode; | 47 // |handler| is called immediately (in the same runloop) with a BOOL indicating |
| 48 // whether the mode change was successful or not. |handler| can be nil. |
| 49 - (void)finalizeChangeToMode:(CRWBrowsingDataStoreMode)mode |
| 50 andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler; |
| 51 |
| 52 // The number of stash or restore operations that are still pending. |
| 53 @property(nonatomic, assign) NSUInteger numberOfPendingStashOrRestoreOperations; |
48 | 54 |
49 // Performs operations of type |operationType| on each of the | 55 // Performs operations of type |operationType| on each of the |
50 // |browsingDataManagers|. | 56 // |browsingDataManagers|. |
51 // The kind of operations are: | 57 // The kind of operations are: |
52 // 1) STASH: Stash operation involves stashing browsing data that web views | 58 // 1) STASH: Stash operation involves stashing browsing data that web views |
53 // (UIWebViews and WKWebViews) create to the associated BrowserState's state | 59 // (UIWebViews and WKWebViews) create to the associated BrowserState's state |
54 // path. | 60 // path. |
55 // 2) RESTORE: Restore operation involves restoring browsing data from the | 61 // 2) RESTORE: Restore operation involves restoring browsing data from the |
56 // associated BrowserState's state path so that web views (UIWebViews and | 62 // associated BrowserState's state path so that web views (UIWebViews and |
57 // WKWebViews) can read from them. | 63 // WKWebViews) can read from them. |
(...skipping 21 matching lines...) Expand all Loading... |
79 @implementation CRWBrowsingDataStore { | 85 @implementation CRWBrowsingDataStore { |
80 web::BrowserState* _browserState; // Weak, owns this object. | 86 web::BrowserState* _browserState; // Weak, owns this object. |
81 // The mode of the CRWBrowsingDataStore. | 87 // The mode of the CRWBrowsingDataStore. |
82 CRWBrowsingDataStoreMode _mode; | 88 CRWBrowsingDataStoreMode _mode; |
83 // The dictionary that maps a browsing data type to its | 89 // The dictionary that maps a browsing data type to its |
84 // CRWBrowsingDataManager. | 90 // CRWBrowsingDataManager. |
85 base::scoped_nsobject<NSDictionary> _browsingDataTypeMap; | 91 base::scoped_nsobject<NSDictionary> _browsingDataTypeMap; |
86 // The last operation that was enqueued to be run. Can be stash, restore or a | 92 // The last operation that was enqueued to be run. Can be stash, restore or a |
87 // delete operation. | 93 // delete operation. |
88 base::scoped_nsobject<NSOperation> _lastDispatchedOperation; | 94 base::scoped_nsobject<NSOperation> _lastDispatchedOperation; |
89 // The last stash or restore operations that was dispatched to be run. | 95 // The number of stash or restore operations that are still pending. If this |
90 base::scoped_nsobject<NSOperation> _lastDispatchedStashOrRestoreOperation; | 96 // value > 0 the mode of the CRWBrowsingDataStore is SYNCHRONIZING. The mode |
| 97 // can be made ACTIVE or INACTIVE only be set when this value is 0. |
| 98 NSUInteger _numberOfPendingStashOrRestoreOperations; |
91 } | 99 } |
92 | 100 |
93 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations { | 101 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations { |
94 static dispatch_once_t onceToken = 0; | 102 static dispatch_once_t onceToken = 0; |
95 static NSOperationQueue* operationQueueForStashAndRestoreOperations = nil; | 103 static NSOperationQueue* operationQueueForStashAndRestoreOperations = nil; |
96 dispatch_once(&onceToken, ^{ | 104 dispatch_once(&onceToken, ^{ |
97 operationQueueForStashAndRestoreOperations = | 105 operationQueueForStashAndRestoreOperations = |
98 [[NSOperationQueue alloc] init]; | 106 [[NSOperationQueue alloc] init]; |
99 [operationQueueForStashAndRestoreOperations | 107 [operationQueueForStashAndRestoreOperations |
100 setMaxConcurrentOperationCount:1U]; | 108 setMaxConcurrentOperationCount:1U]; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 enumerateKeysAndObjectsUsingBlock:^(NSNumber* dataType, | 173 enumerateKeysAndObjectsUsingBlock:^(NSNumber* dataType, |
166 id<CRWBrowsingDataManager> manager, | 174 id<CRWBrowsingDataManager> manager, |
167 BOOL*) { | 175 BOOL*) { |
168 if ([dataType unsignedIntegerValue] & browsingDataTypes) { | 176 if ([dataType unsignedIntegerValue] & browsingDataTypes) { |
169 [result addObject:manager]; | 177 [result addObject:manager]; |
170 } | 178 } |
171 }]; | 179 }]; |
172 return result; | 180 return result; |
173 } | 181 } |
174 | 182 |
| 183 + (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key { |
| 184 // It is necessary to override this for |mode| because the default KVO |
| 185 // behavior in NSObject is to fire a notification irrespective of if an actual |
| 186 // change was made to the ivar or not. The |mode| property needs fine grained |
| 187 // control over the actual notifications being fired since observers need to |
| 188 // be notified iff the |mode| actually changed. |
| 189 if ([key isEqual:@"mode"]) { |
| 190 return NO; |
| 191 } |
| 192 return [super automaticallyNotifiesObserversForKey:(NSString*)key]; |
| 193 } |
| 194 |
175 - (CRWBrowsingDataStoreMode)mode { | 195 - (CRWBrowsingDataStoreMode)mode { |
176 DCHECK([NSThread isMainThread]); | 196 DCHECK([NSThread isMainThread]); |
177 return _mode; | 197 return _mode; |
178 } | 198 } |
179 | 199 |
180 - (void)setMode:(CRWBrowsingDataStoreMode)mode { | 200 - (void)setMode:(CRWBrowsingDataStoreMode)mode { |
181 DCHECK([NSThread isMainThread]); | 201 DCHECK([NSThread isMainThread]); |
| 202 if (_mode == mode) { |
| 203 return; |
| 204 } |
| 205 if (mode == ACTIVE || mode == INACTIVE) { |
| 206 DCHECK(!self.numberOfPendingStashOrRestoreOperations); |
| 207 } |
| 208 [self willChangeValueForKey:@"mode"]; |
182 _mode = mode; | 209 _mode = mode; |
| 210 [self didChangeValueForKey:@"mode"]; |
183 } | 211 } |
184 | 212 |
185 - (void)setModeIfNotStashingOrRestoring:(CRWBrowsingDataStoreMode)mode { | 213 - (void)finalizeChangeToMode:(CRWBrowsingDataStoreMode)mode |
| 214 andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler { |
186 DCHECK([NSThread isMainThread]); | 215 DCHECK([NSThread isMainThread]); |
187 DCHECK_NE(SYNCHRONIZING, mode); | 216 DCHECK_NE(SYNCHRONIZING, mode); |
188 if ([_lastDispatchedStashOrRestoreOperation isFinished]) { | 217 |
189 _mode = mode; | 218 BOOL modeChangeWasSuccessful = NO; |
| 219 if (!self.numberOfPendingStashOrRestoreOperations) { |
| 220 [self setMode:mode]; |
| 221 modeChangeWasSuccessful = YES; |
| 222 } |
| 223 if (handler) { |
| 224 handler(modeChangeWasSuccessful); |
190 } | 225 } |
191 } | 226 } |
192 | 227 |
193 - (void)makeActiveWithCompletionHandler:(ProceduralBlock)completionHandler { | 228 - (NSUInteger)numberOfPendingStashOrRestoreOperations { |
| 229 DCHECK([NSThread isMainThread]); |
| 230 return _numberOfPendingStashOrRestoreOperations; |
| 231 } |
| 232 |
| 233 - (void)setNumberOfPendingStashOrRestoreOperations: |
| 234 (NSUInteger)numberOfPendingStashOrRestoreOperations { |
| 235 DCHECK([NSThread isMainThread]); |
| 236 _numberOfPendingStashOrRestoreOperations = |
| 237 numberOfPendingStashOrRestoreOperations; |
| 238 } |
| 239 |
| 240 - (void)makeActiveWithCompletionHandler: |
| 241 (void (^)(BOOL success))completionHandler { |
194 DCHECK([NSThread isMainThread]); | 242 DCHECK([NSThread isMainThread]); |
195 | 243 |
196 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self); | 244 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self); |
197 [self performOperationWithType:RESTORE | 245 [self performOperationWithType:RESTORE |
198 browsingDataManagers:[self allBrowsingDataManagers] | 246 browsingDataManagers:[self allBrowsingDataManagers] |
199 completionHandler:^{ | 247 completionHandler:^{ |
200 [weakSelf setModeIfNotStashingOrRestoring:ACTIVE]; | 248 [weakSelf finalizeChangeToMode:ACTIVE |
201 if (completionHandler) { | 249 andCallCompletionHandler:completionHandler]; |
202 completionHandler(); | |
203 } | |
204 }]; | 250 }]; |
205 } | 251 } |
206 | 252 |
207 - (void)makeInactiveWithCompletionHandler:(ProceduralBlock)completionHandler { | 253 - (void)makeInactiveWithCompletionHandler: |
| 254 (void (^)(BOOL success))completionHandler { |
208 DCHECK([NSThread isMainThread]); | 255 DCHECK([NSThread isMainThread]); |
209 | 256 |
210 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self); | 257 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self); |
211 [self performOperationWithType:STASH | 258 [self performOperationWithType:STASH |
212 browsingDataManagers:[self allBrowsingDataManagers] | 259 browsingDataManagers:[self allBrowsingDataManagers] |
213 completionHandler:^{ | 260 completionHandler:^{ |
214 [weakSelf setModeIfNotStashingOrRestoring:INACTIVE]; | 261 [weakSelf finalizeChangeToMode:INACTIVE |
215 if (completionHandler) { | 262 andCallCompletionHandler:completionHandler]; |
216 completionHandler(); | |
217 } | |
218 }]; | 263 }]; |
219 } | 264 } |
220 | 265 |
221 - (void)removeDataOfTypes:(web::BrowsingDataTypes)browsingDataTypes | 266 - (void)removeDataOfTypes:(web::BrowsingDataTypes)browsingDataTypes |
222 completionHandler:(ProceduralBlock)completionHandler { | 267 completionHandler:(ProceduralBlock)completionHandler { |
223 DCHECK([NSThread isMainThread]); | 268 DCHECK([NSThread isMainThread]); |
224 | 269 |
225 NSArray* browsingDataManagers = | 270 NSArray* browsingDataManagers = |
226 [self browsingDataManagersForBrowsingDataTypes:browsingDataTypes]; | 271 [self browsingDataManagersForBrowsingDataTypes:browsingDataTypes]; |
227 [self performOperationWithType:REMOVE | 272 [self performOperationWithType:REMOVE |
(...skipping 27 matching lines...) Expand all Loading... |
255 selector = @selector(restoreData); | 300 selector = @selector(restoreData); |
256 break; | 301 break; |
257 case REMOVE: | 302 case REMOVE: |
258 selector = @selector(removeData); | 303 selector = @selector(removeData); |
259 break; | 304 break; |
260 default: | 305 default: |
261 NOTREACHED(); | 306 NOTREACHED(); |
262 break; | 307 break; |
263 }; | 308 }; |
264 | 309 |
| 310 if (operationType == RESTORE || operationType == STASH) { |
| 311 [self setMode:SYNCHRONIZING]; |
| 312 ++self.numberOfPendingStashOrRestoreOperations; |
| 313 completionHandler = ^{ |
| 314 --self.numberOfPendingStashOrRestoreOperations; |
| 315 // It is safe to this and does not lead to the block (|completionHandler|) |
| 316 // retaining itself. |
| 317 completionHandler(); |
| 318 }; |
| 319 } |
| 320 |
265 id callCompletionHandlerOnMainThread = ^{ | 321 id callCompletionHandlerOnMainThread = ^{ |
266 // This can be called on a background thread, hence the need to bounce to | 322 // This is called on a background thread, hence the need to bounce to the |
267 // the main thread. | 323 // main thread. |
268 dispatch_async(dispatch_get_main_queue(), ^{ | 324 dispatch_async(dispatch_get_main_queue(), ^{ |
269 completionHandler(); | 325 completionHandler(); |
270 }); | 326 }); |
271 }; | 327 }; |
272 base::scoped_nsobject<NSOperation> operation([self | 328 base::scoped_nsobject<NSOperation> operation([self |
273 newOperationWithBrowsingDataManagers:browsingDataManagers | 329 newOperationWithBrowsingDataManagers:browsingDataManagers |
274 selector:selector | 330 selector:selector |
275 completionHandler:callCompletionHandlerOnMainThread]); | 331 completionHandler:callCompletionHandlerOnMainThread]); |
276 | 332 |
277 if (operationType == RESTORE || operationType == STASH) { | |
278 _mode = SYNCHRONIZING; | |
279 _lastDispatchedStashOrRestoreOperation.reset([operation retain]); | |
280 } | |
281 | 333 |
282 NSOperationQueue* queue = nil; | 334 NSOperationQueue* queue = nil; |
283 switch (operationType) { | 335 switch (operationType) { |
284 case STASH: | 336 case STASH: |
285 case RESTORE: | 337 case RESTORE: |
286 queue = [CRWBrowsingDataStore operationQueueForStashAndRestoreOperations]; | 338 queue = [CRWBrowsingDataStore operationQueueForStashAndRestoreOperations]; |
287 break; | 339 break; |
288 case REMOVE: | 340 case REMOVE: |
289 queue = [CRWBrowsingDataStore operationQueueForRemoveOperations]; | 341 queue = [CRWBrowsingDataStore operationQueueForRemoveOperations]; |
290 break; | 342 break; |
(...skipping 27 matching lines...) Expand all Loading... |
318 DCHECK(queue); | 370 DCHECK(queue); |
319 | 371 |
320 if (_lastDispatchedOperation) { | 372 if (_lastDispatchedOperation) { |
321 [operation addDependency:_lastDispatchedOperation]; | 373 [operation addDependency:_lastDispatchedOperation]; |
322 } | 374 } |
323 _lastDispatchedOperation.reset([operation retain]); | 375 _lastDispatchedOperation.reset([operation retain]); |
324 [queue addOperation:operation]; | 376 [queue addOperation:operation]; |
325 } | 377 } |
326 | 378 |
327 @end | 379 @end |
OLD | NEW |