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

Side by Side Diff: ios/chrome/browser/snapshots/snapshot_cache.mm

Issue 1725533004: Enable iPad Tab Switcher by default on iOS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed unittests. Created 4 years, 10 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 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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/chrome/browser/snapshots/snapshot_cache.h" 5 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
6 6
7 #import <UIKit/UIKit.h> 7 #import <UIKit/UIKit.h>
8 8
9 #include "base/critical_closure.h" 9 #include "base/critical_closure.h"
10 #include "base/files/file_enumerator.h" 10 #include "base/files/file_enumerator.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/mac/bind_objc_block.h" 15 #include "base/mac/bind_objc_block.h"
16 #include "base/mac/scoped_cftyperef.h" 16 #include "base/mac/scoped_cftyperef.h"
17 #include "base/strings/sys_string_conversions.h" 17 #include "base/strings/sys_string_conversions.h"
18 #include "base/task_runner_util.h" 18 #include "base/task_runner_util.h"
19 #include "base/threading/thread_restrictions.h" 19 #include "base/threading/thread_restrictions.h"
20 #include "ios/chrome/browser/experimental_flags.h" 20 #include "ios/chrome/browser/experimental_flags.h"
21 #include "ios/chrome/browser/ui/ui_util.h" 21 #include "ios/chrome/browser/ui/ui_util.h"
22 #import "ios/chrome/browser/ui/uikit_ui_util.h" 22 #import "ios/chrome/browser/ui/uikit_ui_util.h"
23 #include "ios/web/public/web_thread.h" 23 #include "ios/web/public/web_thread.h"
24 24
25 @interface SnapshotCache () 25 @interface SnapshotCache ()
26 + (base::FilePath)imagePathForSessionID:(NSString*)sessionID; 26 + (base::FilePath)imagePathForSessionID:(NSString*)sessionID;
27 + (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID; 27 + (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
28 // Returns the directory where the thumbnails are saved. 28 // Returns the directory where the thumbnails are saved.
29 + (base::FilePath)cacheDirectory; 29 + (base::FilePath)cacheDirectory;
30 // Returns whether the in-memory cache (as opposed to the on-disk cache) is
31 // enabled.
32 - (BOOL)inMemoryCacheIsEnabled;
33 // Returns whether the snapshots are cached in a LRU cache.
34 - (BOOL)useLRUCache;
30 // Returns the directory where the thumbnails were stored in M28 and earlier. 35 // Returns the directory where the thumbnails were stored in M28 and earlier.
31 - (base::FilePath)oldCacheDirectory; 36 - (base::FilePath)oldCacheDirectory;
32 // Remove all UIImages from |imageDictionary_|. 37 // Remove all UIImages from |imageDictionary_|.
33 - (void)handleEnterBackground; 38 - (void)handleEnterBackground;
34 // Remove all but adjacent UIImages from |imageDictionary_|. 39 // Remove all but adjacent UIImages from |imageDictionary_|.
35 - (void)handleLowMemory; 40 - (void)handleLowMemory;
36 // Restore adjacent UIImages to |imageDictionary_|. 41 // Restore adjacent UIImages to |imageDictionary_|.
37 - (void)handleBecomeActive; 42 - (void)handleBecomeActive;
38 // Clear most recent caller information. 43 // Clear most recent caller information.
39 - (void)clearGreySessionInfo; 44 - (void)clearGreySessionInfo;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 + (SnapshotCache*)sharedInstance { 142 + (SnapshotCache*)sharedInstance {
138 static SnapshotCache* instance = [[SnapshotCache alloc] init]; 143 static SnapshotCache* instance = [[SnapshotCache alloc] init];
139 return instance; 144 return instance;
140 } 145 }
141 146
142 - (id)init { 147 - (id)init {
143 if ((self = [super init])) { 148 if ((self = [super init])) {
144 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 149 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
145 propertyReleaser_SnapshotCache_.Init(self, [SnapshotCache class]); 150 propertyReleaser_SnapshotCache_.Init(self, [SnapshotCache class]);
146 151
147 // Always use the LRUCache when the tab switcher is enabled. 152 if ([self useLRUCache]) {
148 if (experimental_flags::IsTabSwitcherEnabled() ||
149 experimental_flags::IsLRUSnapshotCacheEnabled()) {
150 lruCache_.reset( 153 lruCache_.reset(
151 [[LRUCache alloc] initWithCacheSize:kLRUCacheMaxCapacity]); 154 [[LRUCache alloc] initWithCacheSize:kLRUCacheMaxCapacity]);
152 } else { 155 } else {
153 imageDictionary_.reset( 156 imageDictionary_.reset(
154 [[NSMutableDictionary alloc] initWithCapacity:kCacheInitialCapacity]); 157 [[NSMutableDictionary alloc] initWithCapacity:kCacheInitialCapacity]);
155 } 158 }
156 159 [[NSNotificationCenter defaultCenter]
157 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) { 160 addObserver:self
158 [[NSNotificationCenter defaultCenter] 161 selector:@selector(handleLowMemory)
159 addObserver:self 162 name:UIApplicationDidReceiveMemoryWarningNotification
160 selector:@selector(handleLowMemory) 163 object:nil];
161 name:UIApplicationDidReceiveMemoryWarningNotification 164 [[NSNotificationCenter defaultCenter]
162 object:nil]; 165 addObserver:self
163 [[NSNotificationCenter defaultCenter] 166 selector:@selector(handleEnterBackground)
164 addObserver:self 167 name:UIApplicationDidEnterBackgroundNotification
165 selector:@selector(handleEnterBackground) 168 object:nil];
166 name:UIApplicationDidEnterBackgroundNotification 169 [[NSNotificationCenter defaultCenter]
167 object:nil]; 170 addObserver:self
168 [[NSNotificationCenter defaultCenter] 171 selector:@selector(handleBecomeActive)
169 addObserver:self 172 name:UIApplicationDidBecomeActiveNotification
170 selector:@selector(handleBecomeActive) 173 object:nil];
171 name:UIApplicationDidBecomeActiveNotification
172 object:nil];
173 }
174 } 174 }
175 return self; 175 return self;
176 } 176 }
177 177
178 - (void)dealloc { 178 - (void)dealloc {
179 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) { 179 [[NSNotificationCenter defaultCenter]
180 [[NSNotificationCenter defaultCenter] 180 removeObserver:self
181 removeObserver:self 181 name:UIApplicationDidReceiveMemoryWarningNotification
182 name:UIApplicationDidReceiveMemoryWarningNotification 182 object:nil];
183 object:nil]; 183 [[NSNotificationCenter defaultCenter]
184 [[NSNotificationCenter defaultCenter] 184 removeObserver:self
185 removeObserver:self 185 name:UIApplicationDidEnterBackgroundNotification
186 name:UIApplicationDidEnterBackgroundNotification 186 object:nil];
187 object:nil]; 187 [[NSNotificationCenter defaultCenter]
188 [[NSNotificationCenter defaultCenter] 188 removeObserver:self
189 removeObserver:self 189 name:UIApplicationDidBecomeActiveNotification
190 name:UIApplicationDidBecomeActiveNotification 190 object:nil];
191 object:nil];
192 }
193 [super dealloc]; 191 [super dealloc];
194 } 192 }
195 193
196 + (CGFloat)snapshotScaleForDevice { 194 + (CGFloat)snapshotScaleForDevice {
197 // On handset, the color snapshot is used for the stack view, so the scale of 195 // On handset, the color snapshot is used for the stack view, so the scale of
198 // the snapshot images should match the scale of the device. 196 // the snapshot images should match the scale of the device.
199 // On tablet, the color snapshot is only used to generate the grey snapshot, 197 // On tablet, the color snapshot is only used to generate the grey snapshot,
200 // which does not have to be high quality, so use scale of 1.0 on all tablets. 198 // which does not have to be high quality, so use scale of 1.0 on all tablets.
201 if (IsIPadIdiom()) { 199 if (IsIPadIdiom()) {
202 return 1.0; 200 return 1.0;
203 } 201 }
204 // Cap snapshot resolution to 2x to reduce the amount of memory they use. 202 // Cap snapshot resolution to 2x to reduce the amount of memory they use.
205 return MIN([UIScreen mainScreen].scale, 2.0); 203 return MIN([UIScreen mainScreen].scale, 2.0);
206 } 204 }
207 205
208 - (void)retrieveImageForSessionID:(NSString*)sessionID 206 - (void)retrieveImageForSessionID:(NSString*)sessionID
209 callback:(void (^)(UIImage*))callback { 207 callback:(void (^)(UIImage*))callback {
210 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 208 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
211 DCHECK(sessionID); 209 DCHECK(sessionID);
212 210
213 // Cache on iPad is enabled only when the tab switcher is enabled. 211 if (![self inMemoryCacheIsEnabled] && !callback)
214 if ((IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled()) &&
215 !callback)
216 return; 212 return;
217 213
218 UIImage* img = nil; 214 UIImage* img = nil;
219 if (lruCache_) 215 if (lruCache_)
220 img = [lruCache_ objectForKey:sessionID]; 216 img = [lruCache_ objectForKey:sessionID];
221 else 217 else
222 img = [imageDictionary_ objectForKey:sessionID]; 218 img = [imageDictionary_ objectForKey:sessionID];
223 219
224 if (img) { 220 if (img) {
225 if (callback) 221 if (callback)
226 callback(img); 222 callback(img);
227 return; 223 return;
228 } 224 }
229 225
230 base::PostTaskAndReplyWithResult( 226 base::PostTaskAndReplyWithResult(
231 web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE_USER_BLOCKING) 227 web::WebThread::GetTaskRunnerForThread(web::WebThread::FILE_USER_BLOCKING)
232 .get(), 228 .get(),
233 FROM_HERE, base::BindBlock(^base::scoped_nsobject<UIImage>() { 229 FROM_HERE, base::BindBlock(^base::scoped_nsobject<UIImage>() {
234 // Retrieve the image on a high priority thread. 230 // Retrieve the image on a high priority thread.
235 return base::scoped_nsobject<UIImage>([ReadImageFromDisk( 231 return base::scoped_nsobject<UIImage>([ReadImageFromDisk(
236 [SnapshotCache imagePathForSessionID:sessionID]) retain]); 232 [SnapshotCache imagePathForSessionID:sessionID]) retain]);
237 }), 233 }),
238 base::BindBlock(^(base::scoped_nsobject<UIImage> image) { 234 base::BindBlock(^(base::scoped_nsobject<UIImage> image) {
239 // Cache on iPad is enabled only when the tab switcher is enabled. 235 if ([self inMemoryCacheIsEnabled] && image) {
240 if ((!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) &&
241 image) {
242 if (lruCache_) 236 if (lruCache_)
243 [lruCache_ setObject:image forKey:sessionID]; 237 [lruCache_ setObject:image forKey:sessionID];
244 else 238 else
245 [imageDictionary_ setObject:image forKey:sessionID]; 239 [imageDictionary_ setObject:image forKey:sessionID];
246 } 240 }
247 if (callback) 241 if (callback)
248 callback(image); 242 callback(image);
249 })); 243 }));
250 } 244 }
251 245
252 - (void)setImage:(UIImage*)img withSessionID:(NSString*)sessionID { 246 - (void)setImage:(UIImage*)img withSessionID:(NSString*)sessionID {
253 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 247 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
254 if (!img || !sessionID) 248 if (!img || !sessionID)
255 return; 249 return;
256 250
257 // Cache on iPad is enabled only when the tab switcher is enabled. 251 if ([self inMemoryCacheIsEnabled]) {
258 if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) {
259 if (lruCache_) 252 if (lruCache_)
260 [lruCache_ setObject:img forKey:sessionID]; 253 [lruCache_ setObject:img forKey:sessionID];
261 else 254 else
262 [imageDictionary_ setObject:img forKey:sessionID]; 255 [imageDictionary_ setObject:img forKey:sessionID];
263 } 256 }
264 // Save the image to disk. 257 // Save the image to disk.
265 web::WebThread::PostBlockingPoolSequencedTask( 258 web::WebThread::PostBlockingPoolSequencedTask(
266 kSequenceToken, FROM_HERE, 259 kSequenceToken, FROM_HERE,
267 base::BindBlock(^{ 260 base::BindBlock(^{
268 base::scoped_nsobject<UIImage> image([img retain]); 261 base::scoped_nsobject<UIImage> image([img retain]);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 return; 372 return;
380 backgroundingImageSessionId_.reset([sessionID copy]); 373 backgroundingImageSessionId_.reset([sessionID copy]);
381 if (lruCache_) { 374 if (lruCache_) {
382 backgroundingColorImage_.reset([[lruCache_ objectForKey:sessionID] retain]); 375 backgroundingColorImage_.reset([[lruCache_ objectForKey:sessionID] retain]);
383 } else { 376 } else {
384 backgroundingColorImage_.reset( 377 backgroundingColorImage_.reset(
385 [[imageDictionary_ objectForKey:sessionID] retain]); 378 [[imageDictionary_ objectForKey:sessionID] retain]);
386 } 379 }
387 } 380 }
388 381
382 - (BOOL)inMemoryCacheIsEnabled {
383 // In-memory cache on iPad is enabled only when the tab switcher is enabled.
384 return !IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled();
385 }
386
387 - (BOOL)useLRUCache {
388 // Always use the LRUCache when the tab switcher is enabled.
389 return experimental_flags::IsTabSwitcherEnabled() ||
390 experimental_flags::IsLRUSnapshotCacheEnabled();
391 }
392
389 - (void)handleLowMemory { 393 - (void)handleLowMemory {
390 DCHECK(!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
391 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 394 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
392 NSMutableDictionary* dictionary = 395 NSMutableDictionary* dictionary =
393 [[NSMutableDictionary alloc] initWithCapacity:2]; 396 [[NSMutableDictionary alloc] initWithCapacity:2];
394 for (NSString* sessionID in pinnedIDs_) { 397 for (NSString* sessionID in pinnedIDs_) {
395 UIImage* image = nil; 398 UIImage* image = nil;
396 if (lruCache_) 399 if (lruCache_)
397 image = [lruCache_ objectForKey:sessionID]; 400 image = [lruCache_ objectForKey:sessionID];
398 else 401 else
399 image = [imageDictionary_ objectForKey:sessionID]; 402 image = [imageDictionary_ objectForKey:sessionID];
400 if (image) 403 if (image)
401 [dictionary setObject:image forKey:sessionID]; 404 [dictionary setObject:image forKey:sessionID];
402 } 405 }
403 if (lruCache_) { 406 if (lruCache_) {
404 [lruCache_ removeAllObjects]; 407 [lruCache_ removeAllObjects];
405 for (NSString* sessionID in pinnedIDs_) 408 for (NSString* sessionID in pinnedIDs_)
406 [lruCache_ setObject:dictionary[sessionID] forKey:sessionID]; 409 [lruCache_ setObject:dictionary[sessionID] forKey:sessionID];
407 } else { 410 } else {
408 imageDictionary_.reset(dictionary); 411 imageDictionary_.reset(dictionary);
409 } 412 }
410 } 413 }
411 414
412 - (void)handleEnterBackground { 415 - (void)handleEnterBackground {
413 DCHECK(!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
414 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 416 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
415 [imageDictionary_ removeAllObjects]; 417 [imageDictionary_ removeAllObjects];
416 [lruCache_ removeAllObjects]; 418 [lruCache_ removeAllObjects];
417 } 419 }
418 420
419 - (void)handleBecomeActive { 421 - (void)handleBecomeActive {
420 DCHECK(!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
421 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 422 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
422 for (NSString* sessionID in pinnedIDs_) 423 for (NSString* sessionID in pinnedIDs_)
423 [self retrieveImageForSessionID:sessionID callback:nil]; 424 [self retrieveImageForSessionID:sessionID callback:nil];
424 } 425 }
425 426
426 - (void)saveGreyImage:(UIImage*)greyImage forKey:(NSString*)sessionID { 427 - (void)saveGreyImage:(UIImage*)greyImage forKey:(NSString*)sessionID {
427 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); 428 DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI);
428 if (greyImage) 429 if (greyImage)
429 [greyImageDictionary_ setObject:greyImage forKey:sessionID]; 430 [greyImageDictionary_ setObject:greyImage forKey:sessionID];
430 if ([sessionID isEqualToString:mostRecentGreySessionId_]) { 431 if ([sessionID isEqualToString:mostRecentGreySessionId_]) {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 web::WebThread::PostBlockingPoolTask( 562 web::WebThread::PostBlockingPoolTask(
562 FROM_HERE, base::Bind(&ConvertAndSaveGreyImage, colorImagePath, 563 FROM_HERE, base::Bind(&ConvertAndSaveGreyImage, colorImagePath,
563 greyImagePath, backgroundingColorImage_)); 564 greyImagePath, backgroundingColorImage_));
564 } 565 }
565 566
566 @end 567 @end
567 568
568 @implementation SnapshotCache (TestingAdditions) 569 @implementation SnapshotCache (TestingAdditions)
569 570
570 - (BOOL)hasImageInMemory:(NSString*)sessionID { 571 - (BOOL)hasImageInMemory:(NSString*)sessionID {
571 if (experimental_flags::IsLRUSnapshotCacheEnabled()) 572 if ([self useLRUCache])
572 return [lruCache_ objectForKey:sessionID] != nil; 573 return [lruCache_ objectForKey:sessionID] != nil;
573 else 574 else
574 return [imageDictionary_ objectForKey:sessionID] != nil; 575 return [imageDictionary_ objectForKey:sessionID] != nil;
575 } 576 }
577
576 - (BOOL)hasGreyImageInMemory:(NSString*)sessionID { 578 - (BOOL)hasGreyImageInMemory:(NSString*)sessionID {
577 return [greyImageDictionary_ objectForKey:sessionID] != nil; 579 return [greyImageDictionary_ objectForKey:sessionID] != nil;
578 } 580 }
579 581
580 - (NSUInteger)lruCacheMaxSize { 582 - (NSUInteger)lruCacheMaxSize {
581 return [lruCache_ maxCacheSize]; 583 return [lruCache_ maxCacheSize];
582 } 584 }
583 585
584 @end 586 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698