Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Side by Side Diff: ios/web/crw_browsing_data_store.mm

Issue 1154923003: Fixing an edge case in CRWBrowsingDataStore (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: y Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ios/web/crw_browsing_data_store_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #import "base/ios/weak_nsobject.h" 9 #import "base/ios/weak_nsobject.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // |browsingDataType|. 43 // |browsingDataType|.
44 - (id<CRWBrowsingDataManager>)browsingDataManagerForBrowsingDataType: 44 - (id<CRWBrowsingDataManager>)browsingDataManagerForBrowsingDataType:
45 (NSString*)browsingDataType; 45 (NSString*)browsingDataType;
46 // Returns an array of browsing data managers for all the |browsingDataType|. 46 // Returns an array of browsing data managers for all the |browsingDataType|.
47 - (NSArray*)browsingDataManagersForBrowsingDataTypes:(NSSet*)browsingDataTypes; 47 - (NSArray*)browsingDataManagersForBrowsingDataTypes:(NSSet*)browsingDataTypes;
48 48
49 // Redefined to be read-write. Must be called from the main thread. 49 // Redefined to be read-write. Must be called from the main thread.
50 @property(nonatomic, assign) CRWBrowsingDataStoreMode mode; 50 @property(nonatomic, assign) CRWBrowsingDataStoreMode mode;
51 // Sets the mode iff there are no more stash or restore operations that are 51 // Sets the mode iff there are no more stash or restore operations that are
52 // still pending. |mode| can only be either |ACTIVE| or |INACTIVE|. 52 // still pending. |mode| can only be either |ACTIVE| or |INACTIVE|.
53 - (void)setModeIfNotStashingOrRestoring:(CRWBrowsingDataStoreMode)mode; 53 // Returns YES if the mode change was successful.
54 - (BOOL)setModeIfNoPendingStashOrRestoreOperations:
55 (CRWBrowsingDataStoreMode)mode;
56
57 // The number of stash or restore operations that are still pending.
58 @property(nonatomic, assign) NSUInteger numberOfPendingStashOrRestoreOperations;
54 59
55 // Performs operations of type |operationType| on each of the 60 // Performs operations of type |operationType| on each of the
56 // |browsingDataManagers|. 61 // |browsingDataManagers|.
57 // The kind of operations are: 62 // The kind of operations are:
58 // 1) STASH: Stash operation involves stashing browsing data that web views 63 // 1) STASH: Stash operation involves stashing browsing data that web views
59 // (UIWebViews and WKWebViews) create to the associated BrowserState's state 64 // (UIWebViews and WKWebViews) create to the associated BrowserState's state
60 // path. 65 // path.
61 // 2) RESTORE: Restore operation involves restoring browsing data from the 66 // 2) RESTORE: Restore operation involves restoring browsing data from the
62 // associated BrowserState's state path so that web views (UIWebViews and 67 // associated BrowserState's state path so that web views (UIWebViews and
63 // WKWebViews) can read from them. 68 // WKWebViews) can read from them.
(...skipping 21 matching lines...) Expand all
85 @implementation CRWBrowsingDataStore { 90 @implementation CRWBrowsingDataStore {
86 web::BrowserState* _browserState; // Weak, owns this object. 91 web::BrowserState* _browserState; // Weak, owns this object.
87 // The mode of the CRWBrowsingDataStore. 92 // The mode of the CRWBrowsingDataStore.
88 CRWBrowsingDataStoreMode _mode; 93 CRWBrowsingDataStoreMode _mode;
89 // The dictionary that maps a browsing data type to its 94 // The dictionary that maps a browsing data type to its
90 // CRWBrowsingDataManager. 95 // CRWBrowsingDataManager.
91 base::scoped_nsobject<NSDictionary> _browsingDataTypeMap; 96 base::scoped_nsobject<NSDictionary> _browsingDataTypeMap;
92 // The last operation that was enqueued to be run. Can be stash, restore or a 97 // The last operation that was enqueued to be run. Can be stash, restore or a
93 // delete operation. 98 // delete operation.
94 base::scoped_nsobject<NSOperation> _lastDispatchedOperation; 99 base::scoped_nsobject<NSOperation> _lastDispatchedOperation;
95 // The last stash or restore operations that was dispatched to be run. 100 // The number of stash or restore operations that are still pending. If this
96 base::scoped_nsobject<NSOperation> _lastDispatchedStashOrRestoreOperation; 101 // value > 0 the mode of the CRWBrowsingDataStore is SYNCHRONIZING. The mode
102 // can be made ACTIVE or INACTIVE only be set when this value is 0.
103 NSUInteger _numberOfPendingStashOrRestoreOperations;
97 } 104 }
98 105
99 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations { 106 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations {
100 static dispatch_once_t onceToken = 0; 107 static dispatch_once_t onceToken = 0;
101 static NSOperationQueue* operationQueueForStashAndRestoreOperations = nil; 108 static NSOperationQueue* operationQueueForStashAndRestoreOperations = nil;
102 dispatch_once(&onceToken, ^{ 109 dispatch_once(&onceToken, ^{
103 operationQueueForStashAndRestoreOperations = 110 operationQueueForStashAndRestoreOperations =
104 [[NSOperationQueue alloc] init]; 111 [[NSOperationQueue alloc] init];
105 [operationQueueForStashAndRestoreOperations 112 [operationQueueForStashAndRestoreOperations
106 setMaxConcurrentOperationCount:1U]; 113 setMaxConcurrentOperationCount:1U];
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 - (id<CRWBrowsingDataManager>)browsingDataManagerForBrowsingDataType: 174 - (id<CRWBrowsingDataManager>)browsingDataManagerForBrowsingDataType:
168 (NSString*)browsingDataType { 175 (NSString*)browsingDataType {
169 return [_browsingDataTypeMap objectForKey:browsingDataType]; 176 return [_browsingDataTypeMap objectForKey:browsingDataType];
170 } 177 }
171 178
172 - (NSArray*)browsingDataManagersForBrowsingDataTypes:(NSSet*)browsingDataTypes { 179 - (NSArray*)browsingDataManagersForBrowsingDataTypes:(NSSet*)browsingDataTypes {
173 return [_browsingDataTypeMap objectsForKeys:[browsingDataTypes allObjects] 180 return [_browsingDataTypeMap objectsForKeys:[browsingDataTypes allObjects]
174 notFoundMarker:[NSNull null]]; 181 notFoundMarker:[NSNull null]];
175 } 182 }
176 183
184 + (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
185 // It is necessary to override this for |mode| because the default KVO
186 // behavior in NSObject is to fire a notification irrespective of if an actual
187 // change was made to the ivar or not. The |mode| property needs fine grained
188 // control over the actual notifications being fired since observers need to
189 // be notified iff the |mode| actually changed.
190 if ([key isEqual:@"mode"]) {
191 return NO;
192 }
193 return [super automaticallyNotifiesObserversForKey:(NSString*)key];
194 }
195
177 - (CRWBrowsingDataStoreMode)mode { 196 - (CRWBrowsingDataStoreMode)mode {
178 DCHECK([NSThread isMainThread]); 197 DCHECK([NSThread isMainThread]);
179 return _mode; 198 return _mode;
180 } 199 }
181 200
182 - (void)setMode:(CRWBrowsingDataStoreMode)mode { 201 - (void)setMode:(CRWBrowsingDataStoreMode)mode {
183 DCHECK([NSThread isMainThread]); 202 DCHECK([NSThread isMainThread]);
203 if (_mode == mode) {
204 return;
205 }
206 if (mode == ACTIVE || mode == INACTIVE) {
207 DCHECK(!self.numberOfPendingStashOrRestoreOperations);
208 }
209 [self willChangeValueForKey:@"mode"];
184 _mode = mode; 210 _mode = mode;
211 [self didChangeValueForKey:@"mode"];
185 } 212 }
186 213
187 - (void)setModeIfNotStashingOrRestoring:(CRWBrowsingDataStoreMode)mode { 214 - (BOOL)setModeIfNoPendingStashOrRestoreOperations:
215 (CRWBrowsingDataStoreMode)mode {
188 DCHECK([NSThread isMainThread]); 216 DCHECK([NSThread isMainThread]);
189 DCHECK_NE(SYNCHRONIZING, mode); 217 DCHECK_NE(SYNCHRONIZING, mode);
190 if ([_lastDispatchedStashOrRestoreOperation isFinished]) { 218
191 _mode = mode; 219 if (!self.numberOfPendingStashOrRestoreOperations) {
220 [self setMode:mode];
221 return YES;
192 } 222 }
223 return NO;
193 } 224 }
194 225
195 - (void)makeActiveWithCompletionHandler:(ProceduralBlock)completionHandler { 226 - (NSUInteger)numberOfPendingStashOrRestoreOperations {
227 DCHECK([NSThread isMainThread]);
228 return _numberOfPendingStashOrRestoreOperations;
229 }
230
231 - (void)setNumberOfPendingStashOrRestoreOperations:
232 (NSUInteger)numberOfPendingStashOrRestoreOperations {
233 DCHECK([NSThread isMainThread]);
234 _numberOfPendingStashOrRestoreOperations =
235 numberOfPendingStashOrRestoreOperations;
236 }
237
238 - (void)makeActiveWithCompletionHandler:
239 (void (^)(BOOL success))completionHandler {
196 DCHECK([NSThread isMainThread]); 240 DCHECK([NSThread isMainThread]);
197 241
198 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self); 242 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self);
199 [self performOperationWithType:RESTORE 243 [self performOperationWithType:RESTORE
200 browsingDataManagers:[self allBrowsingDataManagers] 244 browsingDataManagers:[self allBrowsingDataManagers]
201 completionHandler:^{ 245 completionHandler:^{
202 [weakSelf setModeIfNotStashingOrRestoring:ACTIVE]; 246 BOOL modeUpdateWasSuccessful = [weakSelf
247 setModeIfNoPendingStashOrRestoreOperations:ACTIVE];
203 if (completionHandler) { 248 if (completionHandler) {
204 completionHandler(); 249 completionHandler(modeUpdateWasSuccessful);
205 } 250 }
206 }]; 251 }];
207 } 252 }
208 253
209 - (void)makeInactiveWithCompletionHandler:(ProceduralBlock)completionHandler { 254 - (void)makeInactiveWithCompletionHandler:
255 (void (^)(BOOL success))completionHandler {
210 DCHECK([NSThread isMainThread]); 256 DCHECK([NSThread isMainThread]);
211 257
212 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self); 258 base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self);
213 [self performOperationWithType:STASH 259 [self performOperationWithType:STASH
214 browsingDataManagers:[self allBrowsingDataManagers] 260 browsingDataManagers:[self allBrowsingDataManagers]
215 completionHandler:^{ 261 completionHandler:^{
216 [weakSelf setModeIfNotStashingOrRestoring:INACTIVE]; 262 BOOL modeUpdateWasSuccessful = [weakSelf
263 setModeIfNoPendingStashOrRestoreOperations:INACTIVE];
217 if (completionHandler) { 264 if (completionHandler) {
218 completionHandler(); 265 completionHandler(modeUpdateWasSuccessful);
219 } 266 }
220 }]; 267 }];
221 } 268 }
222 269
223 - (void)removeDataOfTypes:(NSSet*)browsingDataTypes 270 - (void)removeDataOfTypes:(NSSet*)browsingDataTypes
224 completionHandler:(ProceduralBlock)completionHandler { 271 completionHandler:(ProceduralBlock)completionHandler {
225 DCHECK([NSThread isMainThread]); 272 DCHECK([NSThread isMainThread]);
226 273
227 NSArray* browsingDataManagers = 274 NSArray* browsingDataManagers =
228 [self browsingDataManagersForBrowsingDataTypes:browsingDataTypes]; 275 [self browsingDataManagersForBrowsingDataTypes:browsingDataTypes];
(...skipping 28 matching lines...) Expand all
257 selector = @selector(restoreData); 304 selector = @selector(restoreData);
258 break; 305 break;
259 case REMOVE: 306 case REMOVE:
260 selector = @selector(removeData); 307 selector = @selector(removeData);
261 break; 308 break;
262 default: 309 default:
263 NOTREACHED(); 310 NOTREACHED();
264 break; 311 break;
265 }; 312 };
266 313
314 if (operationType == RESTORE || operationType == STASH) {
315 [self setMode:SYNCHRONIZING];
316 ++self.numberOfPendingStashOrRestoreOperations;
317 completionHandler = ^{
318 --self.numberOfPendingStashOrRestoreOperations;
319 completionHandler();
Eugene But (OOO till 7-30) 2015/05/29 22:38:28 Is this (retaining self) ok from memory management
shreyasv1 2015/06/01 18:31:54 Yes. That is right thing to do here, There is no n
320 };
321 }
322
267 id callCompletionHandlerOnMainThread = ^{ 323 id callCompletionHandlerOnMainThread = ^{
268 // This can be called on a background thread, hence the need to bounce to 324 // This is called on a background thread, hence the need to bounce to the
269 // the main thread. 325 // main thread.
270 dispatch_async(dispatch_get_main_queue(), ^{ 326 dispatch_async(dispatch_get_main_queue(), ^{
271 completionHandler(); 327 completionHandler();
272 }); 328 });
273 }; 329 };
274 base::scoped_nsobject<NSOperation> operation([self 330 base::scoped_nsobject<NSOperation> operation([self
275 newOperationWithBrowsingDataManagers:browsingDataManagers 331 newOperationWithBrowsingDataManagers:browsingDataManagers
276 selector:selector 332 selector:selector
277 completionHandler:callCompletionHandlerOnMainThread]); 333 completionHandler:callCompletionHandlerOnMainThread]);
278 334
279 if (operationType == RESTORE || operationType == STASH) {
280 _mode = SYNCHRONIZING;
281 _lastDispatchedStashOrRestoreOperation.reset([operation retain]);
282 }
283 335
284 NSOperationQueue* queue = nil; 336 NSOperationQueue* queue = nil;
285 switch (operationType) { 337 switch (operationType) {
286 case STASH: 338 case STASH:
287 case RESTORE: 339 case RESTORE:
288 queue = [CRWBrowsingDataStore operationQueueForStashAndRestoreOperations]; 340 queue = [CRWBrowsingDataStore operationQueueForStashAndRestoreOperations];
289 break; 341 break;
290 case REMOVE: 342 case REMOVE:
291 queue = [CRWBrowsingDataStore operationQueueForRemoveOperations]; 343 queue = [CRWBrowsingDataStore operationQueueForRemoveOperations];
292 break; 344 break;
(...skipping 27 matching lines...) Expand all
320 DCHECK(queue); 372 DCHECK(queue);
321 373
322 if (_lastDispatchedOperation) { 374 if (_lastDispatchedOperation) {
323 [operation addDependency:_lastDispatchedOperation]; 375 [operation addDependency:_lastDispatchedOperation];
324 } 376 }
325 _lastDispatchedOperation.reset([operation retain]); 377 _lastDispatchedOperation.reset([operation retain]);
326 [queue addOperation:operation]; 378 [queue addOperation:operation];
327 } 379 }
328 380
329 @end 381 @end
OLDNEW
« no previous file with comments | « no previous file | ios/web/crw_browsing_data_store_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698