OLD | NEW |
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/chrome/browser/ui/tab_switcher/tab_switcher_cache.h" | 5 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_cache.h" |
6 | 6 |
7 #include <unordered_map> | 7 #include <unordered_map> |
8 | 8 |
9 #import "base/ios/weak_nsobject.h" | |
10 #include "base/logging.h" | 9 #include "base/logging.h" |
11 #include "base/mac/scoped_nsobject.h" | |
12 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
13 #include "base/synchronization/lock.h" | 11 #include "base/synchronization/lock.h" |
14 #import "ios/chrome/browser/tabs/tab.h" | 12 #import "ios/chrome/browser/tabs/tab.h" |
15 #import "ios/chrome/browser/tabs/tab_model.h" | 13 #import "ios/chrome/browser/tabs/tab_model.h" |
16 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 14 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
17 #include "ios/chrome/common/ios_app_bundle_id_prefix.h" | 15 #include "ios/chrome/common/ios_app_bundle_id_prefix.h" |
18 #include "ios/web/public/navigation_item.h" | 16 #include "ios/web/public/navigation_item.h" |
19 | 17 |
| 18 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 19 #error "This file requires ARC support." |
| 20 #endif |
| 21 |
20 namespace { | 22 namespace { |
21 // The maximum amount of pixels the cache should hold. | 23 // The maximum amount of pixels the cache should hold. |
22 NSUInteger kCacheMaxPixelCount = 2048 * 1536 * 4; | 24 NSUInteger kCacheMaxPixelCount = 2048 * 1536 * 4; |
23 // Two floats that are different from less than |kMaxFloatDelta| are considered | 25 // Two floats that are different from less than |kMaxFloatDelta| are considered |
24 // equals. | 26 // equals. |
25 const CGFloat kMaxFloatDelta = 0.01; | 27 const CGFloat kMaxFloatDelta = 0.01; |
26 } // namespace | 28 } // namespace |
27 | 29 |
28 @interface TabSwitcherCache () | 30 @interface TabSwitcherCache () |
29 // Clears the cache. Called when a low memory warning was received. | 31 // Clears the cache. Called when a low memory warning was received. |
30 - (void)lowMemoryWarningReceived; | 32 - (void)lowMemoryWarningReceived; |
31 // Returns a autoreleased resized image of |image|. | 33 // Returns a autoreleased resized image of |image|. |
32 + (UIImage*)resizedImage:(UIImage*)image toSize:(CGSize)size; | 34 + (UIImage*)resizedImage:(UIImage*)image toSize:(CGSize)size; |
33 | 35 |
34 @end | 36 @end |
35 | 37 |
36 @implementation TabSwitcherCache { | 38 @implementation TabSwitcherCache { |
37 base::scoped_nsobject<NSCache> _cache; | 39 NSCache* _cache; |
38 dispatch_queue_t _cacheQueue; | 40 dispatch_queue_t _cacheQueue; |
39 // The tab models. | 41 // The tab models. |
40 TabModel* _mainTabModel; // weak | 42 __weak TabModel* _mainTabModel; |
41 TabModel* _otrTabModel; // weak | 43 __weak TabModel* _otrTabModel; |
42 | 44 |
43 // Lock protecting the pending requests map. | 45 // Lock protecting the pending requests map. |
44 base::Lock _lock; | 46 base::Lock _lock; |
45 std::unordered_map<NSUInteger, PendingSnapshotRequest> _pendingRequests; | 47 std::unordered_map<NSUInteger, PendingSnapshotRequest> _pendingRequests; |
46 } | 48 } |
47 | 49 |
48 @synthesize mainTabModel = _mainTabModel; | 50 @synthesize mainTabModel = _mainTabModel; |
49 | 51 |
50 - (instancetype)init { | 52 - (instancetype)init { |
51 self = [super init]; | 53 self = [super init]; |
52 if (self) { | 54 if (self) { |
53 _cache.reset([[NSCache alloc] init]); | 55 _cache = [[NSCache alloc] init]; |
54 [_cache setTotalCostLimit:kCacheMaxPixelCount]; | 56 [_cache setTotalCostLimit:kCacheMaxPixelCount]; |
55 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 57 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
56 [nc addObserver:self | 58 [nc addObserver:self |
57 selector:@selector(lowMemoryWarningReceived) | 59 selector:@selector(lowMemoryWarningReceived) |
58 name:UIApplicationDidReceiveMemoryWarningNotification | 60 name:UIApplicationDidReceiveMemoryWarningNotification |
59 object:nil]; | 61 object:nil]; |
60 std::string queueName = | 62 std::string queueName = |
61 base::StringPrintf("%s.chrome.ios.TabSwitcherCacheQueue", | 63 base::StringPrintf("%s.chrome.ios.TabSwitcherCacheQueue", |
62 BUILDFLAG(IOS_APP_BUNDLE_ID_PREFIX)); | 64 BUILDFLAG(IOS_APP_BUNDLE_ID_PREFIX)); |
63 _cacheQueue = | 65 _cacheQueue = |
64 dispatch_queue_create(queueName.c_str(), DISPATCH_QUEUE_SERIAL); | 66 dispatch_queue_create(queueName.c_str(), DISPATCH_QUEUE_SERIAL); |
65 } | 67 } |
66 return self; | 68 return self; |
67 } | 69 } |
68 | 70 |
69 - (void)dealloc { | 71 - (void)dealloc { |
70 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 72 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
71 [nc removeObserver:self | 73 [nc removeObserver:self |
72 name:UIApplicationDidReceiveMemoryWarningNotification | 74 name:UIApplicationDidReceiveMemoryWarningNotification |
73 object:nil]; | 75 object:nil]; |
74 dispatch_release(_cacheQueue); | |
75 [_mainTabModel removeObserver:self]; | 76 [_mainTabModel removeObserver:self]; |
76 [_otrTabModel removeObserver:self]; | 77 [_otrTabModel removeObserver:self]; |
77 [super dealloc]; | |
78 } | 78 } |
79 | 79 |
80 - (PendingSnapshotRequest)requestSnapshotForTab:(Tab*)tab | 80 - (PendingSnapshotRequest)requestSnapshotForTab:(Tab*)tab |
81 withSize:(CGSize)size | 81 withSize:(CGSize)size |
82 completionBlock: | 82 completionBlock: |
83 (SnapshotCompletionBlock)completionBlock { | 83 (SnapshotCompletionBlock)completionBlock { |
84 DCHECK([NSThread isMainThread]); | 84 DCHECK([NSThread isMainThread]); |
85 DCHECK(tab); | 85 DCHECK(tab); |
86 DCHECK(completionBlock); | 86 DCHECK(completionBlock); |
87 DCHECK(!CGSizeEqualToSize(size, CGSizeZero)); | 87 DCHECK(!CGSizeEqualToSize(size, CGSizeZero)); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 | 224 |
225 + (UIImage*)resizedImage:(UIImage*)image toSize:(CGSize)size { | 225 + (UIImage*)resizedImage:(UIImage*)image toSize:(CGSize)size { |
226 DCHECK(image.scale == 1); | 226 DCHECK(image.scale == 1); |
227 CGFloat screenScale = [[UIScreen mainScreen] scale]; | 227 CGFloat screenScale = [[UIScreen mainScreen] scale]; |
228 CGSize pixelSize = size; | 228 CGSize pixelSize = size; |
229 pixelSize.width *= screenScale; | 229 pixelSize.width *= screenScale; |
230 pixelSize.height *= screenScale; | 230 pixelSize.height *= screenScale; |
231 UIImage* resizedSnapshot = | 231 UIImage* resizedSnapshot = |
232 ResizeImage(image, pixelSize, ProjectionMode::kAspectFillNoClipping, YES); | 232 ResizeImage(image, pixelSize, ProjectionMode::kAspectFillNoClipping, YES); |
233 // Creates a new image with the correct |scale| attribute. | 233 // Creates a new image with the correct |scale| attribute. |
234 return [[[UIImage alloc] initWithCGImage:resizedSnapshot.CGImage | 234 return [[UIImage alloc] initWithCGImage:resizedSnapshot.CGImage |
235 scale:screenScale | 235 scale:screenScale |
236 orientation:UIImageOrientationUp] autorelease]; | 236 orientation:UIImageOrientationUp]; |
237 } | 237 } |
238 | 238 |
239 - (void)lowMemoryWarningReceived { | 239 - (void)lowMemoryWarningReceived { |
240 [_cache removeAllObjects]; | 240 [_cache removeAllObjects]; |
241 } | 241 } |
242 | 242 |
| 243 - (void)setMainTabModel:(TabModel*)mainTabModel { |
| 244 if (mainTabModel == _mainTabModel) { |
| 245 return; |
| 246 } |
| 247 |
| 248 [_mainTabModel removeObserver:self]; |
| 249 _mainTabModel = mainTabModel; |
| 250 [_mainTabModel addObserver:self]; |
| 251 } |
| 252 |
| 253 - (void)setOTRTabModel:(TabModel*)otrTabModel { |
| 254 if (_otrTabModel == otrTabModel) { |
| 255 return; |
| 256 } |
| 257 |
| 258 [_otrTabModel removeObserver:self]; |
| 259 _otrTabModel = otrTabModel; |
| 260 [_otrTabModel addObserver:self]; |
| 261 } |
| 262 |
243 - (void)setMainTabModel:(TabModel*)mainTabModel | 263 - (void)setMainTabModel:(TabModel*)mainTabModel |
244 otrTabModel:(TabModel*)otrTabModel { | 264 otrTabModel:(TabModel*)otrTabModel { |
245 if (mainTabModel != _mainTabModel) | 265 [self setMainTabModel:mainTabModel]; |
246 [self replaceOldTabModel:&_mainTabModel withTabModel:mainTabModel]; | 266 [self setOTRTabModel:otrTabModel]; |
247 if (otrTabModel != _otrTabModel) | |
248 [self replaceOldTabModel:&_otrTabModel withTabModel:otrTabModel]; | |
249 } | |
250 | |
251 - (void)replaceOldTabModel:(TabModel**)oldTabModel | |
252 withTabModel:(TabModel*)newTabModel { | |
253 [*oldTabModel removeObserver:self]; | |
254 *oldTabModel = newTabModel; | |
255 [newTabModel addObserver:self]; | |
256 } | 267 } |
257 | 268 |
258 #pragma mark - TabModelObserver | 269 #pragma mark - TabModelObserver |
259 | 270 |
260 - (void)tabModel:(TabModel*)model | 271 - (void)tabModel:(TabModel*)model |
261 didRemoveTab:(Tab*)tab | 272 didRemoveTab:(Tab*)tab |
262 atIndex:(NSUInteger)index { | 273 atIndex:(NSUInteger)index { |
263 [self removePendingSnapshotRequestForTab:tab]; | 274 [self removePendingSnapshotRequestForTab:tab]; |
264 [_cache removeObjectForKey:[self keyForTab:tab]]; | 275 [_cache removeObjectForKey:[self keyForTab:tab]]; |
265 } | 276 } |
266 | 277 |
267 - (void)tabModel:(TabModel*)model | 278 - (void)tabModel:(TabModel*)model |
268 didChangeTabSnapshot:(Tab*)tab | 279 didChangeTabSnapshot:(Tab*)tab |
269 withImage:image { | 280 withImage:image { |
270 [self removePendingSnapshotRequestForTab:tab]; | 281 [self removePendingSnapshotRequestForTab:tab]; |
271 [_cache removeObjectForKey:[self keyForTab:tab]]; | 282 [_cache removeObjectForKey:[self keyForTab:tab]]; |
272 } | 283 } |
273 | 284 |
274 @end | 285 @end |
OLD | NEW |