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

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

Issue 1215433003: CL for Objective-C readability (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: y Created 5 years, 5 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
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 #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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #import "base/mac/scoped_nsobject.h" 12 #import "base/mac/scoped_nsobject.h"
13 #import "ios/web/browsing_data_managers/crw_cookie_browsing_data_manager.h" 13 #import "ios/web/browsing_data_managers/crw_cookie_browsing_data_manager.h"
14 #include "ios/web/public/active_state_manager.h" 14 #include "ios/web/public/active_state_manager.h"
15 #include "ios/web/public/browser_state.h" 15 #include "ios/web/public/browser_state.h"
16 16
17 namespace { 17 namespace {
18 // Represents the type of operations that a CRWBrowsingDataStore can perform. 18 // Represents the type of operations that a CRWBrowsingDataStore can perform.
19 enum OperationType { 19 enum OperationType {
20 // Represents NOP. 20 // Represents NOP.
21 NONE = 1, 21 NONE = 1,
22 // Stash operation involves stashing browsing data that web views create to 22 // Stash operation involves stashing browsing data that web views create to
23 // the associated BrowserState's state path. 23 // the associated BrowserState's state path.
24 STASH, 24 STASH,
25 // Restore operation involves restoring browsing data from the 25 // Restore operation involves restoring browsing data from the
26 // associated BrowserState's state path so that web views (UIWebViews and 26 // associated BrowserState's state path so that web views can read from them.
27 // WKWebViews) can read from them.
28 RESTORE, 27 RESTORE,
29 // Remove operation involves removing the data that web views create. 28 // Remove operation involves removing the data that web views create.
30 REMOVE, 29 REMOVE,
31 }; 30 };
32 31
33 // The name of the NSOperation that performs a restore operation. 32 // The name of the NSOperation that performs a |RESTORE| operation.
stuartmorgan 2015/07/09 16:33:50 FWIW, while the | are okay here, they are only req
shreyasv1 2015/07/09 17:18:01 My concern is with consistency. I noticed that som
34 NSString* const kRestoreOperationName = @"CRWBrowsingDataStore.RESTORE"; 33 NSString* const kRestoreOperationName = @"CRWBrowsingDataStore.RESTORE";
35 // The name of the NSOperation that performs a stash operation. 34 // The name of the NSOperation that performs a |STASH| operation.
36 NSString* const kStashOperationName = @"CRWBrowsingDataStore.STASH"; 35 NSString* const kStashOperationName = @"CRWBrowsingDataStore.STASH";
37 } // namespace 36 } // namespace
38 37
38 // CRWBrowsingDataStore is implemented using 2 queues.
39 // 1) operationQueueForStashAndRestoreOperations:
40 // - This queue is used to perform |STASH| and |RESTORE| operations.
41 // - |STASH|, |RESTORE| operations are the core bits that need to be performed
42 // in order to change the mode of a CRWBrowsingDataStore and hence they are
43 // prioritized with a QoS of NSQualityOfServiceUserInteractive.
44 // - |STASH|, |RESTORE| operations from 2 different CRWBrowsingDataStores are
45 // not re-entrant. Hence this is a serial queue.
46 // 2) operationQueueForRemoveOperations:
47 // - This queue is used to perform |REMOVE| operations.
48 // - |REMOVE| operations are not as critical as |STASH|, |RESTORE|. Hence they
49 // the queue has a QoS of NSQualityOfServiceUserInitiated -- in order to not
50 // overwhelm the system.
51 // - |REMOVE| operations from 2 different CRWBrowingDataStores can be run in
52 // parallel. Hence this is a concurrent queue.
53 //
54 // |STASH|, |RESTORE|, |REMOVE| operations of a particular CRWBrowsingDataStore
55 // are not re-entrant. Hence these operations are serialized.
56
39 @interface CRWBrowsingDataStore () 57 @interface CRWBrowsingDataStore ()
58 // Redefined to be read-write. Must be called from the main thread.
59 @property(nonatomic, assign) web::BrowsingDataStoreMode mode;
60 // The array of all browsing data managers. Must be called from the main
61 // thread.
62 @property(nonatomic, readonly) NSArray* allBrowsingDataManagers;
63 // The number of stash or restore operations that are still pending. Must be
64 // called from the main thread.
65 @property(nonatomic, assign) NSUInteger numberOfPendingStashOrRestoreOperations;
66
40 // Returns a serial queue on which stash and restore operations can be scheduled 67 // Returns a serial queue on which stash and restore operations can be scheduled
41 // to be run. All stash/restore operations need to be run on the same queue 68 // to be run. All |STASH|/|RESTORE| operations need to be run on the same queue
42 // hence it is shared with all CRWBrowsingDataStores. 69 // hence it is shared with all CRWBrowsingDataStores.
43 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations; 70 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations;
44 // Returns a concurrent queue on which remove operations can be scheduled to be 71 // Returns a concurrent queue on which remove operations can be scheduled to be
45 // run. All remove operations need to be run on the same queue hence it is 72 // run. All |REMOVE| operations need to be run on the same queue hence it is
46 // shared with all CRWBrowsingDataStores. 73 // shared with all CRWBrowsingDataStores.
47 + (NSOperationQueue*)operationQueueForRemoveOperations; 74 + (NSOperationQueue*)operationQueueForRemoveOperations;
48 - (instancetype)init NS_UNAVAILABLE;
49 75
50 // The array of all browsing data managers. Must be accessed from the main 76 // Returns an array of CRWBrowsingDataManagers for the given
51 // thread. 77 // |browsingDataTypes|.
52 @property(nonatomic, readonly) NSArray* allBrowsingDataManagers;
53 // Returns an array of browsing data managers for the given |browsingDataTypes|.
54 - (NSArray*)browsingDataManagersForBrowsingDataTypes: 78 - (NSArray*)browsingDataManagersForBrowsingDataTypes:
55 (web::BrowsingDataTypes)browsingDataTypes; 79 (web::BrowsingDataTypes)browsingDataTypes;
56 // Returns the selector that needs to be performed on the 80 // Returns the selector that needs to be performed on the
57 // CRWBrowsingDataManagers for the |operationType|. |operationType| cannot be 81 // CRWBrowsingDataManagers for the |operationType|. |operationType| cannot be
58 // |NONE|. 82 // |NONE|.
59 - (SEL)browsingDataManagerSelectorForOperationType:(OperationType)operationType; 83 - (SEL)browsingDataManagerSelectorForOperationType:(OperationType)operationType;
60 // Returns the selector that needs to be performed on the 84 // Returns the selector that needs to be performed on the
61 // CRWBrowsingDataManagers for a REMOVE operation. 85 // CRWBrowsingDataManagers for a |REMOVE| operation.
62 - (SEL)browsingDataManagerSelectorForRemoveOperationType; 86 - (SEL)browsingDataManagerSelectorForRemoveOperationType;
63 87
64 // Redefined to be read-write. Must be called from the main thread. 88 // Sets the mode iff there are no more |STASH| or |RESTORE| operations that are
65 @property(nonatomic, assign) web::BrowsingDataStoreMode mode;
66 // Sets the mode iff there are no more stash or restore operations that are
67 // still pending. |mode| can only be either |ACTIVE| or |INACTIVE|. 89 // still pending. |mode| can only be either |ACTIVE| or |INACTIVE|.
68 // |handler| is called immediately (in the same runloop) with a BOOL indicating 90 // |handler| is called immediately (in the same runloop) with a BOOL indicating
69 // whether the mode change was successful or not. |handler| can be nil. 91 // whether the mode change was successful or not. |handler| can be nil.
70 - (void)finalizeChangeToMode:(web::BrowsingDataStoreMode)mode 92 - (void)finalizeChangeToMode:(web::BrowsingDataStoreMode)mode
71 andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler; 93 andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler;
72
73 // Changes the mode of the CRWBrowsingDataStore to |mode|. This is an 94 // Changes the mode of the CRWBrowsingDataStore to |mode|. This is an
74 // asynchronous operation and the mode is not changed immediately. 95 // asynchronous operation and the mode is not changed immediately.
75 // |completionHandler| can be nil. 96 // |completionHandler| can be nil.
76 // |completionHandler| is called on the main thread. This block has no return 97 // |completionHandler| is called on the main thread. This block has no return
77 // value and takes a single BOOL argument that indicates whether or not the 98 // value and takes a single BOOL argument that indicates whether or not the
78 // mode change was successfully changed to |mode|. 99 // mode change was successfully changed to |mode|.
79 - (void)changeMode:(web::BrowsingDataStoreMode)mode 100 - (void)changeMode:(web::BrowsingDataStoreMode)mode
80 completionHandler:(void (^)(BOOL modeChangeWasSuccessful))completionHandler; 101 completionHandler:(void (^)(BOOL modeChangeWasSuccessful))completionHandler;
81 102
82 // The number of stash or restore operations that are still pending. 103 // Returns the OperationType (that needs to be performed) in order to change the
83 @property(nonatomic, assign) NSUInteger numberOfPendingStashOrRestoreOperations; 104 // mode to |mode|. Consults the delegate if one is present. |mode| cannot be
84 105 // |CHANGING|.
85 // Performs operations of type |operationType| on each of the 106 - (OperationType)operationTypeToChangeMode:(web::BrowsingDataStoreMode)mode;
107 // Performs an operation of type |operationType| on each of the
86 // |browsingDataManagers|. |operationType| cannot be |NONE|. 108 // |browsingDataManagers|. |operationType| cannot be |NONE|.
87 // Precondition: There must be no web views associated with the BrowserState. 109 // Precondition: There must be no web views associated with the BrowserState.
88 // |completionHandler| is called on the main thread and cannot be nil. 110 // |completionHandler| is called on the main thread and cannot be nil.
89 - (void)performOperationWithType:(OperationType)operationType 111 - (void)performOperationWithType:(OperationType)operationType
90 browsingDataManagers:(NSArray*)browsingDataManagers 112 browsingDataManagers:(NSArray*)browsingDataManagers
91 completionHandler:(ProceduralBlock)completionHandler; 113 completionHandler:(ProceduralBlock)completionHandler;
92 114 // Returns an NSOperation that calls |selector| on all the
93 // Creates an NSOperation that calls |selector| on all the
94 // |browsingDataManagers|. |selector| needs to be one of the methods in 115 // |browsingDataManagers|. |selector| needs to be one of the methods in
95 // CRWBrowsingDataManager. 116 // CRWBrowsingDataManager.
96 - (NSOperation*) 117 - (NSOperation*)operationWithBrowsingDataManagers:(NSArray*)browsingDataManagers
97 newOperationWithBrowsingDataManagers:(NSArray*)browsingDataManagers 118 selector:(SEL)selector;
98 selector:(SEL)selector;
99 // Enqueues |operation| to be run on |queue|. All operations are serialized to 119 // Enqueues |operation| to be run on |queue|. All operations are serialized to
100 // be run one after another. 120 // be run one after another.
101 - (void)addOperation:(NSOperation*)operation toQueue:(NSOperationQueue*)queue; 121 - (void)addOperation:(NSOperation*)operation toQueue:(NSOperationQueue*)queue;
102 @end 122 @end
103 123
104 @implementation CRWBrowsingDataStore { 124 @implementation CRWBrowsingDataStore {
105 web::BrowserState* _browserState; // Weak, owns this object. 125 web::BrowserState* _browserState; // Weak, owns this object.
106 // The delegate. 126 // The delegate.
107 base::WeakNSProtocol<id<CRWBrowsingDataStoreDelegate>> _delegate; 127 base::WeakNSProtocol<id<CRWBrowsingDataStoreDelegate>> _delegate;
108 // The mode of the CRWBrowsingDataStore. 128 // The mode of the CRWBrowsingDataStore.
109 web::BrowsingDataStoreMode _mode; 129 web::BrowsingDataStoreMode _mode;
110 // The dictionary that maps a browsing data type to its 130 // The dictionary that maps a browsing data type to its
111 // CRWBrowsingDataManager. 131 // CRWBrowsingDataManager.
112 base::scoped_nsobject<NSDictionary> _browsingDataTypeMap; 132 base::scoped_nsobject<NSDictionary> _browsingDataTypeMap;
113 // The last operation that was enqueued to be run. Can be stash, restore or a 133 // The last operation that was enqueued to be run. Can be a |STASH|, |RESTORE|
114 // delete operation. 134 // or a |REMOVE| operation.
115 base::scoped_nsobject<NSOperation> _lastDispatchedOperation; 135 base::scoped_nsobject<NSOperation> _lastDispatchedOperation;
116 // The last dispatched stash or restore operation that was enqueued to be run. 136 // The last dispatched |STASH| or |RESTORE| operation that was enqueued to be
137 // run.
117 base::scoped_nsobject<NSOperation> _lastDispatchedStashOrRestoreOperation; 138 base::scoped_nsobject<NSOperation> _lastDispatchedStashOrRestoreOperation;
118 // The number of stash or restore operations that are still pending. If this 139 // The number of |STASH| or |RESTORE| operations that are still pending. If
119 // value > 0 the mode of the CRWBrowsingDataStore is |CHANGING|. The mode 140 // the number of stash or restore operations > 0U, the mode of the
120 // can be made ACTIVE or INACTIVE only be set when this value is 0. 141 // CRWBrowsingDataStore is |CHANGING|. The mode can be made ACTIVE or INACTIVE
142 // only be set when this value is 0U.
121 NSUInteger _numberOfPendingStashOrRestoreOperations; 143 NSUInteger _numberOfPendingStashOrRestoreOperations;
122 } 144 }
123 145
124 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations { 146 #pragma mark -
125 static dispatch_once_t onceToken = 0; 147 #pragma mark NSObject Methods
126 static NSOperationQueue* operationQueueForStashAndRestoreOperations = nil;
127 dispatch_once(&onceToken, ^{
128 operationQueueForStashAndRestoreOperations =
129 [[NSOperationQueue alloc] init];
130 [operationQueueForStashAndRestoreOperations
131 setMaxConcurrentOperationCount:1U];
132 if (base::ios::IsRunningOnIOS8OrLater()) {
133 [operationQueueForStashAndRestoreOperations
134 setQualityOfService:NSQualityOfServiceUserInteractive];
135 }
136 });
137 return operationQueueForStashAndRestoreOperations;
138 }
139
140 + (NSOperationQueue*)operationQueueForRemoveOperations {
141 static dispatch_once_t onceToken = 0;
142 static NSOperationQueue* operationQueueForRemoveOperations = nil;
143 dispatch_once(&onceToken, ^{
144 operationQueueForRemoveOperations = [[NSOperationQueue alloc] init];
145 [operationQueueForRemoveOperations
146 setMaxConcurrentOperationCount:NSUIntegerMax];
147 if (base::ios::IsRunningOnIOS8OrLater()) {
148 [operationQueueForRemoveOperations
149 setQualityOfService:NSQualityOfServiceUserInitiated];
150 }
151 });
152 return operationQueueForRemoveOperations;
153 }
154 148
155 - (instancetype)initWithBrowserState:(web::BrowserState*)browserState { 149 - (instancetype)initWithBrowserState:(web::BrowserState*)browserState {
156 self = [super init]; 150 self = [super init];
157 if (self) { 151 if (self) {
158 DCHECK([NSThread isMainThread]); 152 DCHECK([NSThread isMainThread]);
153 DCHECK(browserState);
159 // TODO(shreyasv): Instantiate the necessary CRWBrowsingDataManagers that 154 // TODO(shreyasv): Instantiate the necessary CRWBrowsingDataManagers that
160 // are encapsulated within this class. crbug.com/480654. 155 // are encapsulated within this class. crbug.com/480654.
161 _browserState = browserState; 156 _browserState = browserState;
162 web::ActiveStateManager* activeStateManager = 157 web::ActiveStateManager* activeStateManager =
163 web::BrowserState::GetActiveStateManager(browserState); 158 web::BrowserState::GetActiveStateManager(browserState);
164 DCHECK(activeStateManager); 159 DCHECK(activeStateManager);
165 _mode = activeStateManager->IsActive() ? web::ACTIVE : web::INACTIVE; 160 _mode = activeStateManager->IsActive() ? web::ACTIVE : web::INACTIVE;
166 // TODO(shreyasv): If the creation of CRWBrowsingDataManagers turns out to 161 // TODO(shreyasv): If the creation of CRWBrowsingDataManagers turns out to
167 // be an expensive operations re-visit this with a lazy-evaluation approach. 162 // be an expensive operations re-visit this with a lazy-evaluation approach.
168 base::scoped_nsobject<CRWCookieBrowsingDataManager> 163 base::scoped_nsobject<CRWCookieBrowsingDataManager>
169 cookieBrowsingDataManager([[CRWCookieBrowsingDataManager alloc] 164 cookieBrowsingDataManager([[CRWCookieBrowsingDataManager alloc]
170 initWithBrowserState:browserState]); 165 initWithBrowserState:browserState]);
171 _browsingDataTypeMap.reset([@{ 166 _browsingDataTypeMap.reset([@{
172 @(web::BROWSING_DATA_TYPE_COOKIES) : cookieBrowsingDataManager, 167 @(web::BROWSING_DATA_TYPE_COOKIES) : cookieBrowsingDataManager,
173 } retain]); 168 } retain]);
174 } 169 }
175 return self; 170 return self;
176 } 171 }
177 172
178 - (instancetype)init { 173 - (instancetype)init {
179 NOTREACHED(); 174 NOTREACHED();
180 return nil; 175 return nil;
181 } 176 }
182 177
183 - (NSString*)description { 178 - (NSString*)description {
184 NSString* format = @"<%@: %p; hasPendingOperations = { %@ }>"; 179 NSString* format = @"<%@: %p; hasPendingOperations = { %@ }; mode = { %@ }>";
185 NSString* hasPendingOperationsString = 180 NSString* hasPendingOperationsString =
186 [self hasPendingOperations] ? @"YES" : @"NO"; 181 [self hasPendingOperations] ? @"YES" : @"NO";
187 NSString* result = 182 NSString* modeString = nil;
188 [NSString stringWithFormat:format, NSStringFromClass(self.class), self, 183 switch (self.mode) {
189 hasPendingOperationsString]; 184 case web::ACTIVE:
185 modeString = @"ACTIVE";
186 break;
187 case web::CHANGING:
188 modeString = @"CHANGING";
189 break;
190 case web::INACTIVE:
191 modeString = @"INACTIVE";
192 break;
193 }
194 NSString* result = [NSString stringWithFormat:format,
195 NSStringFromClass(self.class), self, hasPendingOperationsString,
196 modeString];
stuartmorgan 2015/07/09 16:33:50 This shouldn't be indented any more than the line
190 return result; 197 return result;
191 } 198 }
192 199
200 + (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
201 // It is necessary to override this for |mode| because the default KVO
202 // behavior in NSObject is to fire a notification irrespective of if an actual
203 // change was made to the ivar or not. The |mode| property needs fine grained
204 // control over the actual notifications being fired since observers need to
205 // be notified iff the |mode| actually changed.
206 if ([key isEqual:@"mode"]) {
207 return NO;
208 }
209 return [super automaticallyNotifiesObserversForKey:(NSString*)key];
stuartmorgan 2015/07/09 16:33:50 Remove (NSString*)
shreyasv1 2015/07/09 17:18:01 Done.
210 }
211
212 #pragma mark -
213 #pragma mark Public Properties
214
215 - (id<CRWBrowsingDataStoreDelegate>)delegate {
216 return _delegate;
217 }
218
219 - (void)setDelegate:(id<CRWBrowsingDataStoreDelegate>)delegate {
220 _delegate.reset(delegate);
221 }
222
223 - (web::BrowsingDataStoreMode)mode {
224 DCHECK([NSThread isMainThread]);
225 return _mode;
226 }
227
228 - (BOOL)hasPendingOperations {
229 if (!_lastDispatchedOperation) {
230 return NO;
231 }
232 return ![_lastDispatchedOperation isFinished];
233 }
234
235 #pragma mark -
236 #pragma mark Public Methods
237
238 - (void)makeActiveWithCompletionHandler:
239 (void (^)(BOOL success))completionHandler {
240 DCHECK([NSThread isMainThread]);
241 // TODO(shreyasv): Verify the preconditions for this method when
242 // web::WebViewCounter class is implemented. crbug.com/480507.
243
244 [self changeMode:web::ACTIVE completionHandler:completionHandler];
245 }
246
247 - (void)makeInactiveWithCompletionHandler:
248 (void (^)(BOOL success))completionHandler {
249 DCHECK([NSThread isMainThread]);
250 // TODO(shreyasv): Verify the preconditions for this method when
251 // web::WebViewCounter class is implemented. crbug.com/480507.
252
253 [self changeMode:web::INACTIVE completionHandler:completionHandler];
254 }
255
256 - (void)removeDataOfTypes:(web::BrowsingDataTypes)browsingDataTypes
257 completionHandler:(ProceduralBlock)completionHandler {
258 DCHECK([NSThread isMainThread]);
259 // TODO(shreyasv): Verify the preconditions for this method when
260 // web::WebViewCounter class is implemented. crbug.com/480507.
261
262 NSArray* browsingDataManagers =
263 [self browsingDataManagersForBrowsingDataTypes:browsingDataTypes];
264 [self performOperationWithType:REMOVE
265 browsingDataManagers:browsingDataManagers
266 completionHandler:completionHandler];
267 }
268
269 #pragma mark -
270 #pragma mark Private Properties
271
272 - (void)setMode:(web::BrowsingDataStoreMode)mode {
273 DCHECK([NSThread isMainThread]);
274
275 if (_mode == mode) {
276 return;
277 }
278 if (mode == web::ACTIVE || mode == web::INACTIVE) {
279 DCHECK(!self.numberOfPendingStashOrRestoreOperations);
280 }
281 [self willChangeValueForKey:@"mode"];
282 _mode = mode;
283 [self didChangeValueForKey:@"mode"];
284 }
193 285
194 - (NSArray*)allBrowsingDataManagers { 286 - (NSArray*)allBrowsingDataManagers {
195 DCHECK([NSThread isMainThread]); 287 DCHECK([NSThread isMainThread]);
196 return [_browsingDataTypeMap allValues]; 288 return [_browsingDataTypeMap allValues];
197 } 289 }
198 290
291 - (NSUInteger)numberOfPendingStashOrRestoreOperations {
292 DCHECK([NSThread isMainThread]);
293 return _numberOfPendingStashOrRestoreOperations;
294 }
295
296 - (void)setNumberOfPendingStashOrRestoreOperations:
297 (NSUInteger)numberOfPendingStashOrRestoreOperations {
298 DCHECK([NSThread isMainThread]);
299 _numberOfPendingStashOrRestoreOperations =
300 numberOfPendingStashOrRestoreOperations;
301 }
302
303 #pragma mark -
304 #pragma mark Private Class Methods
305
306 + (NSOperationQueue*)operationQueueForStashAndRestoreOperations {
307 static dispatch_once_t onceToken = 0;
308 static NSOperationQueue* operationQueueForStashAndRestoreOperations = nil;
309 dispatch_once(&onceToken, ^{
310 operationQueueForStashAndRestoreOperations =
311 [[NSOperationQueue alloc] init];
312 [operationQueueForStashAndRestoreOperations
313 setMaxConcurrentOperationCount:1U];
314 if (base::ios::IsRunningOnIOS8OrLater()) {
315 [operationQueueForStashAndRestoreOperations
316 setQualityOfService:NSQualityOfServiceUserInteractive];
317 }
318 });
319 return operationQueueForStashAndRestoreOperations;
320 }
321
322 + (NSOperationQueue*)operationQueueForRemoveOperations {
323 static dispatch_once_t onceToken = 0;
324 static NSOperationQueue* operationQueueForRemoveOperations = nil;
325 dispatch_once(&onceToken, ^{
326 operationQueueForRemoveOperations = [[NSOperationQueue alloc] init];
327 [operationQueueForRemoveOperations
328 setMaxConcurrentOperationCount:NSUIntegerMax];
329 if (base::ios::IsRunningOnIOS8OrLater()) {
330 [operationQueueForRemoveOperations
331 setQualityOfService:NSQualityOfServiceUserInitiated];
332 }
333 });
334 return operationQueueForRemoveOperations;
335 }
336
337 #pragma mark -
338 #pragma mark Private Methods
339
199 - (NSArray*)browsingDataManagersForBrowsingDataTypes: 340 - (NSArray*)browsingDataManagersForBrowsingDataTypes:
200 (web::BrowsingDataTypes)browsingDataTypes { 341 (web::BrowsingDataTypes)browsingDataTypes {
201 __block NSMutableArray* result = [NSMutableArray array]; 342 __block NSMutableArray* result = [NSMutableArray array];
202 [_browsingDataTypeMap 343 [_browsingDataTypeMap
203 enumerateKeysAndObjectsUsingBlock:^(NSNumber* dataType, 344 enumerateKeysAndObjectsUsingBlock:^(NSNumber* dataType,
204 id<CRWBrowsingDataManager> manager, 345 id<CRWBrowsingDataManager> manager,
205 BOOL*) { 346 BOOL*) {
206 if ([dataType unsignedIntegerValue] & browsingDataTypes) { 347 if ([dataType unsignedIntegerValue] & browsingDataTypes) {
207 [result addObject:manager]; 348 [result addObject:manager];
208 } 349 }
209 }]; 350 }];
210 return result; 351 return result;
211 } 352 }
212 353
213 - (id<CRWBrowsingDataStoreDelegate>)delegate {
214 return _delegate;
215 }
216
217 - (void)setDelegate:(id<CRWBrowsingDataStoreDelegate>)delegate {
218 _delegate.reset(delegate);
219 }
220
221 - (SEL)browsingDataManagerSelectorForOperationType: 354 - (SEL)browsingDataManagerSelectorForOperationType:
222 (OperationType)operationType { 355 (OperationType)operationType {
223 switch (operationType) { 356 switch (operationType) {
224 case NONE: 357 case NONE:
225 NOTREACHED(); 358 NOTREACHED();
226 return nullptr; 359 return nullptr;
227 case STASH: 360 case STASH:
228 return @selector(stashData); 361 return @selector(stashData);
229 case RESTORE: 362 case RESTORE:
230 return @selector(restoreData); 363 return @selector(restoreData);
231 case REMOVE: 364 case REMOVE:
232 return [self browsingDataManagerSelectorForRemoveOperationType]; 365 return [self browsingDataManagerSelectorForRemoveOperationType];
233 }; 366 };
234 NOTREACHED();
235 return nullptr;
236 } 367 }
237 368
238 - (SEL)browsingDataManagerSelectorForRemoveOperationType { 369 - (SEL)browsingDataManagerSelectorForRemoveOperationType {
239 if (self.mode == web::ACTIVE) { 370 if (self.mode == web::ACTIVE) {
240 return @selector(removeDataAtCanonicalPath); 371 return @selector(removeDataAtCanonicalPath);
241 } 372 }
242 if (self.mode == web::INACTIVE) { 373 if (self.mode == web::INACTIVE) {
243 return @selector(removeDataAtStashPath); 374 return @selector(removeDataAtStashPath);
244 } 375 }
376 // Since the mode is |CHANGING|, find the last |STASH| or |RESTORE| operation
377 // that was enqueued in order to find out the eventual mode that the
378 // CRWBrowsingDataStore will be in when this |REMOVE| operation is run.
245 DCHECK(_lastDispatchedStashOrRestoreOperation); 379 DCHECK(_lastDispatchedStashOrRestoreOperation);
246 NSString* lastDispatchedStashOrRestoreOperationName = 380 NSString* lastDispatchedStashOrRestoreOperationName =
247 [_lastDispatchedStashOrRestoreOperation name]; 381 [_lastDispatchedStashOrRestoreOperation name];
248 if ([lastDispatchedStashOrRestoreOperationName 382 if ([lastDispatchedStashOrRestoreOperationName
249 isEqual:kRestoreOperationName]) { 383 isEqual:kRestoreOperationName]) {
250 return @selector(removeDataAtCanonicalPath); 384 return @selector(removeDataAtCanonicalPath);
251 } 385 }
252 if ([lastDispatchedStashOrRestoreOperationName isEqual:kStashOperationName]) { 386 if ([lastDispatchedStashOrRestoreOperationName isEqual:kStashOperationName]) {
253 return @selector(removeDataAtStashPath); 387 return @selector(removeDataAtStashPath);
254 } 388 }
255 NOTREACHED(); 389 NOTREACHED();
256 return nullptr; 390 return nullptr;
257 } 391 }
258 392
259 + (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
260 // It is necessary to override this for |mode| because the default KVO
261 // behavior in NSObject is to fire a notification irrespective of if an actual
262 // change was made to the ivar or not. The |mode| property needs fine grained
263 // control over the actual notifications being fired since observers need to
264 // be notified iff the |mode| actually changed.
265 if ([key isEqual:@"mode"]) {
266 return NO;
267 }
268 return [super automaticallyNotifiesObserversForKey:(NSString*)key];
269 }
270
271 - (web::BrowsingDataStoreMode)mode {
272 DCHECK([NSThread isMainThread]);
273 return _mode;
274 }
275
276 - (void)setMode:(web::BrowsingDataStoreMode)mode {
277 DCHECK([NSThread isMainThread]);
278 if (_mode == mode) {
279 return;
280 }
281 if (mode == web::ACTIVE || mode == web::INACTIVE) {
282 DCHECK(!self.numberOfPendingStashOrRestoreOperations);
283 }
284 [self willChangeValueForKey:@"mode"];
285 _mode = mode;
286 [self didChangeValueForKey:@"mode"];
287 }
288
289 - (void)finalizeChangeToMode:(web::BrowsingDataStoreMode)mode 393 - (void)finalizeChangeToMode:(web::BrowsingDataStoreMode)mode
290 andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler { 394 andCallCompletionHandler:(void (^)(BOOL modeChangeWasSuccessful))handler {
291 DCHECK([NSThread isMainThread]); 395 DCHECK([NSThread isMainThread]);
292 DCHECK_NE(web::CHANGING, mode); 396 DCHECK_NE(web::CHANGING, mode);
293 397
294 BOOL modeChangeWasSuccessful = NO; 398 BOOL modeChangeWasSuccessful = NO;
295 if (!self.numberOfPendingStashOrRestoreOperations) { 399 if (!self.numberOfPendingStashOrRestoreOperations) {
296 [self setMode:mode]; 400 [self setMode:mode];
297 modeChangeWasSuccessful = YES; 401 modeChangeWasSuccessful = YES;
298 } 402 }
299 if (handler) { 403 if (handler) {
300 handler(modeChangeWasSuccessful); 404 handler(modeChangeWasSuccessful);
301 } 405 }
302 } 406 }
303 407
304 - (NSUInteger)numberOfPendingStashOrRestoreOperations {
305 DCHECK([NSThread isMainThread]);
306 return _numberOfPendingStashOrRestoreOperations;
307 }
308
309 - (void)setNumberOfPendingStashOrRestoreOperations:
310 (NSUInteger)numberOfPendingStashOrRestoreOperations {
311 DCHECK([NSThread isMainThread]);
312 _numberOfPendingStashOrRestoreOperations =
313 numberOfPendingStashOrRestoreOperations;
314 }
315
316 - (void)makeActiveWithCompletionHandler:
317 (void (^)(BOOL success))completionHandler {
318 DCHECK([NSThread isMainThread]);
319
320 [self changeMode:web::ACTIVE completionHandler:completionHandler];
321 }
322
323 - (void)makeInactiveWithCompletionHandler:
324 (void (^)(BOOL success))completionHandler {
325 DCHECK([NSThread isMainThread]);
326
327 [self changeMode:web::INACTIVE completionHandler:completionHandler];
328 }
329
330 - (void)changeMode:(web::BrowsingDataStoreMode)mode 408 - (void)changeMode:(web::BrowsingDataStoreMode)mode
331 completionHandler: 409 completionHandler:
332 (void (^)(BOOL modeChangeWasSuccessful))completionHandler { 410 (void (^)(BOOL modeChangeWasSuccessful))completionHandler {
333 DCHECK([NSThread isMainThread]); 411 DCHECK([NSThread isMainThread]);
334 412
335 ProceduralBlock completionHandlerAfterPerformingOperation = ^{ 413 ProceduralBlock completionHandlerAfterPerformingOperation = ^{
336 [self finalizeChangeToMode:mode andCallCompletionHandler:completionHandler]; 414 [self finalizeChangeToMode:mode andCallCompletionHandler:completionHandler];
337 }; 415 };
338 416
339 // Already in the desired mode. 417 OperationType operationType = [self operationTypeToChangeMode:mode];
340 if (self.mode == mode) { 418 if (operationType == NONE) {
341 // As a caller of this API, it is awkward to get the callback before the 419 // As a caller of this API, it is awkward to get the callback before the
342 // method call has completed, hence defer it. 420 // method call has completed, hence defer it.
343 dispatch_async(dispatch_get_main_queue(), ^{ 421 dispatch_async(dispatch_get_main_queue(),
344 completionHandlerAfterPerformingOperation(); 422 completionHandlerAfterPerformingOperation);
345 }); 423 } else {
346 return; 424 [self performOperationWithType:operationType
425 browsingDataManagers:[self allBrowsingDataManagers]
426 completionHandler:completionHandlerAfterPerformingOperation];
347 } 427 }
428 }
429
430 - (OperationType)operationTypeToChangeMode:(web::BrowsingDataStoreMode)mode {
431 DCHECK_NE(web::CHANGING, mode);
348 432
349 OperationType operationType = NONE; 433 OperationType operationType = NONE;
350 if (mode == web::ACTIVE) { 434 if (mode == self.mode) {
435 // Already in the desired mode.
436 operationType = NONE;
437 } else if (mode == web::ACTIVE) {
351 // By default a |RESTORE| operation is performed when the mode is changed 438 // By default a |RESTORE| operation is performed when the mode is changed
352 // to |ACTIVE|. 439 // to |ACTIVE|.
353 operationType = RESTORE; 440 operationType = RESTORE;
354 web::BrowsingDataStoreMakeActivePolicy makeActivePolicy = 441 web::BrowsingDataStoreMakeActivePolicy makeActivePolicy =
355 [_delegate decideMakeActiveOperationPolicyForBrowsingDataStore:self]; 442 [_delegate decideMakeActiveOperationPolicyForBrowsingDataStore:self];
356 operationType = (makeActivePolicy == web::ADOPT) ? REMOVE : RESTORE; 443 operationType = (makeActivePolicy == web::ADOPT) ? REMOVE : RESTORE;
357 } else { 444 } else {
358 // By default a |STASH| operation is performed when the mode is changed to 445 // By default a |STASH| operation is performed when the mode is changed to
359 // |INACTIVE|. 446 // |INACTIVE|.
360 operationType = STASH; 447 operationType = STASH;
361 web::BrowsingDataStoreMakeInactivePolicy makeInactivePolicy = 448 web::BrowsingDataStoreMakeInactivePolicy makeInactivePolicy =
362 [_delegate decideMakeInactiveOperationPolicyForBrowsingDataStore:self]; 449 [_delegate decideMakeInactiveOperationPolicyForBrowsingDataStore:self];
363 operationType = (makeInactivePolicy == web::DELETE) ? REMOVE : STASH; 450 operationType = (makeInactivePolicy == web::DELETE) ? REMOVE : STASH;
364 } 451 }
365 DCHECK_NE(NONE, operationType); 452 return operationType;
366 [self performOperationWithType:operationType
367 browsingDataManagers:[self allBrowsingDataManagers]
368 completionHandler:completionHandlerAfterPerformingOperation];
369 }
370
371 - (void)removeDataOfTypes:(web::BrowsingDataTypes)browsingDataTypes
372 completionHandler:(ProceduralBlock)completionHandler {
373 DCHECK([NSThread isMainThread]);
374
375 NSArray* browsingDataManagers =
376 [self browsingDataManagersForBrowsingDataTypes:browsingDataTypes];
377 [self performOperationWithType:REMOVE
378 browsingDataManagers:browsingDataManagers
379 completionHandler:^{
380 // Since this may be called on a background thread, bounce to
381 // the main thread.
382 dispatch_async(dispatch_get_main_queue(), completionHandler);
383 }];
384 }
385
386 - (BOOL)hasPendingOperations {
387 if (!_lastDispatchedOperation) {
388 return NO;
389 }
390 return ![_lastDispatchedOperation isFinished];
391 } 453 }
392 454
393 - (void)performOperationWithType:(OperationType)operationType 455 - (void)performOperationWithType:(OperationType)operationType
394 browsingDataManagers:(NSArray*)browsingDataManagers 456 browsingDataManagers:(NSArray*)browsingDataManagers
395 completionHandler:(ProceduralBlock)completionHandler { 457 completionHandler:(ProceduralBlock)completionHandler {
396 DCHECK([NSThread isMainThread]); 458 DCHECK([NSThread isMainThread]);
397 DCHECK(completionHandler); 459 DCHECK(completionHandler);
398 DCHECK_NE(NONE, operationType); 460 DCHECK_NE(NONE, operationType);
399 461
400 SEL selector = 462 SEL selector =
401 [self browsingDataManagerSelectorForOperationType:operationType]; 463 [self browsingDataManagerSelectorForOperationType:operationType];
402 DCHECK(selector); 464 DCHECK(selector);
403 465
404 if (operationType == RESTORE || operationType == STASH) { 466 if (operationType == RESTORE || operationType == STASH) {
405 [self setMode:web::CHANGING]; 467 [self setMode:web::CHANGING];
406 ++self.numberOfPendingStashOrRestoreOperations; 468 ++self.numberOfPendingStashOrRestoreOperations;
407 completionHandler = ^{ 469 completionHandler = ^{
408 --self.numberOfPendingStashOrRestoreOperations; 470 --self.numberOfPendingStashOrRestoreOperations;
409 // It is safe to this and does not lead to the block (|completionHandler|) 471 // It is safe to this and does not lead to the block (|completionHandler|)
410 // retaining itself. 472 // retaining itself.
411 completionHandler(); 473 completionHandler();
412 }; 474 };
413 } 475 }
414 476
415 ProceduralBlock callCompletionHandlerOnMainThread = ^{ 477 ProceduralBlock callCompletionHandlerOnMainThread = ^{
416 // This is called on a background thread, hence the need to bounce to the 478 // This is called on a background thread, hence the need to bounce to the
417 // main thread. 479 // main thread.
418 dispatch_async(dispatch_get_main_queue(), ^{ 480 dispatch_async(dispatch_get_main_queue(), completionHandler);
419 completionHandler();
420 });
421 }; 481 };
422 base::scoped_nsobject<NSOperation> operation( 482 NSOperation* operation =
423 [self newOperationWithBrowsingDataManagers:browsingDataManagers 483 [self operationWithBrowsingDataManagers:browsingDataManagers
424 selector:selector]); 484 selector:selector];
425 485
426 if (operationType == RESTORE || operationType == STASH) { 486 if (operationType == RESTORE || operationType == STASH) {
427 [operation setName:(RESTORE ? kRestoreOperationName : kStashOperationName)]; 487 [operation setName:(RESTORE ? kRestoreOperationName : kStashOperationName)];
428 _lastDispatchedStashOrRestoreOperation.reset([operation retain]); 488 _lastDispatchedStashOrRestoreOperation.reset([operation retain]);
429 } 489 }
430 490
431 NSOperationQueue* queue = nil; 491 NSOperationQueue* queue = nil;
432 switch (operationType) { 492 switch (operationType) {
493 case NONE:
494 NOTREACHED();
495 break;
433 case STASH: 496 case STASH:
434 case RESTORE: 497 case RESTORE:
435 queue = [CRWBrowsingDataStore operationQueueForStashAndRestoreOperations]; 498 queue = [CRWBrowsingDataStore operationQueueForStashAndRestoreOperations];
436 break; 499 break;
437 case REMOVE: 500 case REMOVE:
438 queue = [CRWBrowsingDataStore operationQueueForRemoveOperations]; 501 queue = [CRWBrowsingDataStore operationQueueForRemoveOperations];
439 break; 502 break;
440 default:
441 NOTREACHED();
442 break;
443 } 503 }
444 504
445 NSOperation* completionHandlerOperation = [NSBlockOperation 505 NSOperation* completionHandlerOperation = [NSBlockOperation
446 blockOperationWithBlock:callCompletionHandlerOnMainThread]; 506 blockOperationWithBlock:callCompletionHandlerOnMainThread];
447 507
448 [self addOperation:operation toQueue:queue]; 508 [self addOperation:operation toQueue:queue];
449 [self addOperation:completionHandlerOperation toQueue:queue]; 509 [self addOperation:completionHandlerOperation toQueue:queue];
450 } 510 }
451 511
452 - (NSOperation*) 512 - (NSOperation*)operationWithBrowsingDataManagers:(NSArray*)browsingDataManagers
453 newOperationWithBrowsingDataManagers:(NSArray*)browsingDataManagers 513 selector:(SEL)selector {
454 selector:(SEL)selector { 514 NSBlockOperation* operation = [[[NSBlockOperation alloc] init] autorelease];
455 NSBlockOperation* operation = [[NSBlockOperation alloc] init];
456 for (id<CRWBrowsingDataManager> manager : browsingDataManagers) { 515 for (id<CRWBrowsingDataManager> manager : browsingDataManagers) {
457 // |addExecutionBlock| farms out the different blocks added to it. hence the 516 // |addExecutionBlock| farms out the different blocks added to it. hence the
458 // operations are implicitly parallelized. 517 // operations are implicitly parallelized.
459 [operation addExecutionBlock:^{ 518 [operation addExecutionBlock:^{
460 [manager performSelector:selector]; 519 [manager performSelector:selector];
461 }]; 520 }];
462 } 521 }
463 return operation; 522 return operation;
464 } 523 }
465 524
466 - (void)addOperation:(NSOperation*)operation toQueue:(NSOperationQueue*)queue { 525 - (void)addOperation:(NSOperation*)operation toQueue:(NSOperationQueue*)queue {
467 DCHECK([NSThread isMainThread]); 526 DCHECK([NSThread isMainThread]);
468 DCHECK(operation); 527 DCHECK(operation);
469 DCHECK(queue); 528 DCHECK(queue);
470 529
471 if (_lastDispatchedOperation) { 530 if (_lastDispatchedOperation) {
472 [operation addDependency:_lastDispatchedOperation]; 531 [operation addDependency:_lastDispatchedOperation];
473 } 532 }
474 _lastDispatchedOperation.reset([operation retain]); 533 _lastDispatchedOperation.reset([operation retain]);
475 [queue addOperation:operation]; 534 [queue addOperation:operation];
476 } 535 }
477 536
478 @end 537 @end
OLDNEW
« no previous file with comments | « no previous file | ios/web/crw_browsing_data_store_unittest.mm » ('j') | ios/web/crw_browsing_data_store_unittest.mm » ('J')

Powered by Google App Engine
This is Rietveld 408576698