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

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