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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | ios/web/crw_browsing_data_store_unittest.mm » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/web/crw_browsing_data_store.mm
diff --git a/ios/web/crw_browsing_data_store.mm b/ios/web/crw_browsing_data_store.mm
index 45242072b3b3b4dd3a99e54618c06c0241d0dfa5..646bb5ae107a2b5bcfe0be2aa801415accd0fcd0 100644
--- a/ios/web/crw_browsing_data_store.mm
+++ b/ios/web/crw_browsing_data_store.mm
@@ -44,7 +44,13 @@ enum OperationType {
@property(nonatomic, assign) CRWBrowsingDataStoreMode mode;
// Sets the mode iff there are no more stash or restore operations that are
// still pending. |mode| can only be either |ACTIVE| or |INACTIVE|.
-- (void)setModeIfNotStashingOrRestoring:(CRWBrowsingDataStoreMode)mode;
+// |handler| is called immediately (in the same runloop) with a BOOL indicating
+// whether the mode change was successful or not. |handler| can be nil.
+- (void)finalizeChangeToMode:(CRWBrowsingDataStoreMode)mode
+ andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler;
+
+// The number of stash or restore operations that are still pending.
+@property(nonatomic, assign) NSUInteger numberOfPendingStashOrRestoreOperations;
// Performs operations of type |operationType| on each of the
// |browsingDataManagers|.
@@ -86,8 +92,10 @@ enum OperationType {
// The last operation that was enqueued to be run. Can be stash, restore or a
// delete operation.
base::scoped_nsobject<NSOperation> _lastDispatchedOperation;
- // The last stash or restore operations that was dispatched to be run.
- base::scoped_nsobject<NSOperation> _lastDispatchedStashOrRestoreOperation;
+ // The number of stash or restore operations that are still pending. If this
+ // value > 0 the mode of the CRWBrowsingDataStore is SYNCHRONIZING. The mode
+ // can be made ACTIVE or INACTIVE only be set when this value is 0.
+ NSUInteger _numberOfPendingStashOrRestoreOperations;
}
+ (NSOperationQueue*)operationQueueForStashAndRestoreOperations {
@@ -172,6 +180,18 @@ enum OperationType {
return result;
}
++ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
+ // It is necessary to override this for |mode| because the default KVO
+ // behavior in NSObject is to fire a notification irrespective of if an actual
+ // change was made to the ivar or not. The |mode| property needs fine grained
+ // control over the actual notifications being fired since observers need to
+ // be notified iff the |mode| actually changed.
+ if ([key isEqual:@"mode"]) {
+ return NO;
+ }
+ return [super automaticallyNotifiesObserversForKey:(NSString*)key];
+}
+
- (CRWBrowsingDataStoreMode)mode {
DCHECK([NSThread isMainThread]);
return _mode;
@@ -179,42 +199,67 @@ enum OperationType {
- (void)setMode:(CRWBrowsingDataStoreMode)mode {
DCHECK([NSThread isMainThread]);
+ if (_mode == mode) {
+ return;
+ }
+ if (mode == ACTIVE || mode == INACTIVE) {
+ DCHECK(!self.numberOfPendingStashOrRestoreOperations);
+ }
+ [self willChangeValueForKey:@"mode"];
_mode = mode;
+ [self didChangeValueForKey:@"mode"];
}
-- (void)setModeIfNotStashingOrRestoring:(CRWBrowsingDataStoreMode)mode {
+- (void)finalizeChangeToMode:(CRWBrowsingDataStoreMode)mode
+ andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler {
DCHECK([NSThread isMainThread]);
DCHECK_NE(SYNCHRONIZING, mode);
- if ([_lastDispatchedStashOrRestoreOperation isFinished]) {
- _mode = mode;
+
+ BOOL modeChangeWasSuccessful = NO;
+ if (!self.numberOfPendingStashOrRestoreOperations) {
+ [self setMode:mode];
+ modeChangeWasSuccessful = YES;
+ }
+ if (handler) {
+ handler(modeChangeWasSuccessful);
}
}
-- (void)makeActiveWithCompletionHandler:(ProceduralBlock)completionHandler {
+- (NSUInteger)numberOfPendingStashOrRestoreOperations {
+ DCHECK([NSThread isMainThread]);
+ return _numberOfPendingStashOrRestoreOperations;
+}
+
+- (void)setNumberOfPendingStashOrRestoreOperations:
+ (NSUInteger)numberOfPendingStashOrRestoreOperations {
+ DCHECK([NSThread isMainThread]);
+ _numberOfPendingStashOrRestoreOperations =
+ numberOfPendingStashOrRestoreOperations;
+}
+
+- (void)makeActiveWithCompletionHandler:
+ (void (^)(BOOL success))completionHandler {
DCHECK([NSThread isMainThread]);
base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self);
[self performOperationWithType:RESTORE
browsingDataManagers:[self allBrowsingDataManagers]
completionHandler:^{
- [weakSelf setModeIfNotStashingOrRestoring:ACTIVE];
- if (completionHandler) {
- completionHandler();
- }
+ [weakSelf finalizeChangeToMode:ACTIVE
+ andCallCompletionHandler:completionHandler];
}];
}
-- (void)makeInactiveWithCompletionHandler:(ProceduralBlock)completionHandler {
+- (void)makeInactiveWithCompletionHandler:
+ (void (^)(BOOL success))completionHandler {
DCHECK([NSThread isMainThread]);
base::WeakNSObject<CRWBrowsingDataStore> weakSelf(self);
[self performOperationWithType:STASH
browsingDataManagers:[self allBrowsingDataManagers]
completionHandler:^{
- [weakSelf setModeIfNotStashingOrRestoring:INACTIVE];
- if (completionHandler) {
- completionHandler();
- }
+ [weakSelf finalizeChangeToMode:INACTIVE
+ andCallCompletionHandler:completionHandler];
}];
}
@@ -262,9 +307,20 @@ enum OperationType {
break;
};
+ if (operationType == RESTORE || operationType == STASH) {
+ [self setMode:SYNCHRONIZING];
+ ++self.numberOfPendingStashOrRestoreOperations;
+ completionHandler = ^{
+ --self.numberOfPendingStashOrRestoreOperations;
+ // It is safe to this and does not lead to the block (|completionHandler|)
+ // retaining itself.
+ completionHandler();
+ };
+ }
+
id callCompletionHandlerOnMainThread = ^{
- // This can be called on a background thread, hence the need to bounce to
- // the main thread.
+ // This is called on a background thread, hence the need to bounce to the
+ // main thread.
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler();
});
@@ -274,10 +330,6 @@ enum OperationType {
selector:selector
completionHandler:callCompletionHandlerOnMainThread]);
- if (operationType == RESTORE || operationType == STASH) {
- _mode = SYNCHRONIZING;
- _lastDispatchedStashOrRestoreOperation.reset([operation retain]);
- }
NSOperationQueue* queue = nil;
switch (operationType) {
« 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