| 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 |