Commit 8eb38982 authored by jif's avatar jif Committed by Commit bot

Fix the snapshot_cache unittests.

This fix is necessary to enable by default the iPad tab switcher.
It is a partial reland of https://codereview.chromium.org/1725533004

This CL:
-Always register/deregister for notifications.
-Centralizes the logic to use a LRU cache.
-Centralizes the logic to use an in-memory cache.
-Replaces msarda with jif in OWNERS.
-Triggers memory warning instead of calling |handleLowMemory| from tests.

BUG=None

Review-Url: https://codereview.chromium.org/2394253002
Cr-Commit-Position: refs/heads/master@{#427302}
parent 7bda5b2d
...@@ -403,6 +403,7 @@ source_set("browser") { ...@@ -403,6 +403,7 @@ source_set("browser") {
"snapshots/lru_cache.mm", "snapshots/lru_cache.mm",
"snapshots/snapshot_cache.h", "snapshots/snapshot_cache.h",
"snapshots/snapshot_cache.mm", "snapshots/snapshot_cache.mm",
"snapshots/snapshot_cache_internal.h",
"snapshots/snapshot_manager.h", "snapshots/snapshot_manager.h",
"snapshots/snapshot_manager.mm", "snapshots/snapshot_manager.mm",
"snapshots/snapshot_overlay.h", "snapshots/snapshot_overlay.h",
......
jif@chromium.org
justincohen@chromium.org justincohen@chromium.org
msarda@chromium.org
...@@ -18,13 +18,12 @@ ...@@ -18,13 +18,12 @@
#include "base/task_runner_util.h" #include "base/task_runner_util.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "ios/chrome/browser/experimental_flags.h" #include "ios/chrome/browser/experimental_flags.h"
#import "ios/chrome/browser/snapshots/snapshot_cache_internal.h"
#include "ios/chrome/browser/ui/ui_util.h" #include "ios/chrome/browser/ui/ui_util.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h" #import "ios/chrome/browser/ui/uikit_ui_util.h"
#include "ios/web/public/web_thread.h" #include "ios/web/public/web_thread.h"
@interface SnapshotCache () @interface SnapshotCache ()
+ (base::FilePath)imagePathForSessionID:(NSString*)sessionID;
+ (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
// Returns the directory where the thumbnails are saved. // Returns the directory where the thumbnails are saved.
+ (base::FilePath)cacheDirectory; + (base::FilePath)cacheDirectory;
// Returns the directory where the thumbnails were stored in M28 and earlier. // Returns the directory where the thumbnails were stored in M28 and earlier.
...@@ -144,17 +143,13 @@ void ConvertAndSaveGreyImage( ...@@ -144,17 +143,13 @@ void ConvertAndSaveGreyImage(
DCHECK_CURRENTLY_ON(web::WebThread::UI); DCHECK_CURRENTLY_ON(web::WebThread::UI);
propertyReleaser_SnapshotCache_.Init(self, [SnapshotCache class]); propertyReleaser_SnapshotCache_.Init(self, [SnapshotCache class]);
// Always use the LRUCache when the tab switcher is enabled. if ([self usesLRUCache]) {
if (experimental_flags::IsTabSwitcherEnabled() ||
experimental_flags::IsLRUSnapshotCacheEnabled()) {
lruCache_.reset( lruCache_.reset(
[[LRUCache alloc] initWithCacheSize:kLRUCacheMaxCapacity]); [[LRUCache alloc] initWithCacheSize:kLRUCacheMaxCapacity]);
} else { } else {
imageDictionary_.reset( imageDictionary_.reset(
[[NSMutableDictionary alloc] initWithCapacity:kCacheInitialCapacity]); [[NSMutableDictionary alloc] initWithCapacity:kCacheInitialCapacity]);
} }
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) {
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self addObserver:self
selector:@selector(handleLowMemory) selector:@selector(handleLowMemory)
...@@ -171,12 +166,10 @@ void ConvertAndSaveGreyImage( ...@@ -171,12 +166,10 @@ void ConvertAndSaveGreyImage(
name:UIApplicationDidBecomeActiveNotification name:UIApplicationDidBecomeActiveNotification
object:nil]; object:nil];
} }
}
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) {
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
removeObserver:self removeObserver:self
name:UIApplicationDidReceiveMemoryWarningNotification name:UIApplicationDidReceiveMemoryWarningNotification
...@@ -189,7 +182,6 @@ void ConvertAndSaveGreyImage( ...@@ -189,7 +182,6 @@ void ConvertAndSaveGreyImage(
removeObserver:self removeObserver:self
name:UIApplicationDidBecomeActiveNotification name:UIApplicationDidBecomeActiveNotification
object:nil]; object:nil];
}
[super dealloc]; [super dealloc];
} }
...@@ -210,9 +202,7 @@ void ConvertAndSaveGreyImage( ...@@ -210,9 +202,7 @@ void ConvertAndSaveGreyImage(
DCHECK_CURRENTLY_ON(web::WebThread::UI); DCHECK_CURRENTLY_ON(web::WebThread::UI);
DCHECK(sessionID); DCHECK(sessionID);
// Cache on iPad is enabled only when the tab switcher is enabled. if (![self inMemoryCacheIsEnabled] && !callback)
if ((IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled()) &&
!callback)
return; return;
UIImage* img = nil; UIImage* img = nil;
...@@ -236,9 +226,7 @@ void ConvertAndSaveGreyImage( ...@@ -236,9 +226,7 @@ void ConvertAndSaveGreyImage(
[SnapshotCache imagePathForSessionID:sessionID]) retain]); [SnapshotCache imagePathForSessionID:sessionID]) retain]);
}), }),
base::BindBlock(^(base::scoped_nsobject<UIImage> image) { base::BindBlock(^(base::scoped_nsobject<UIImage> image) {
// Cache on iPad is enabled only when the tab switcher is enabled. if ([self inMemoryCacheIsEnabled] && image) {
if ((!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) &&
image) {
if (lruCache_) if (lruCache_)
[lruCache_ setObject:image forKey:sessionID]; [lruCache_ setObject:image forKey:sessionID];
else else
...@@ -254,8 +242,7 @@ void ConvertAndSaveGreyImage( ...@@ -254,8 +242,7 @@ void ConvertAndSaveGreyImage(
if (!img || !sessionID) if (!img || !sessionID)
return; return;
// Cache on iPad is enabled only when the tab switcher is enabled. if ([self inMemoryCacheIsEnabled]) {
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) {
if (lruCache_) if (lruCache_)
[lruCache_ setObject:img forKey:sessionID]; [lruCache_ setObject:img forKey:sessionID];
else else
...@@ -386,8 +373,18 @@ void ConvertAndSaveGreyImage( ...@@ -386,8 +373,18 @@ void ConvertAndSaveGreyImage(
} }
} }
- (BOOL)inMemoryCacheIsEnabled {
// In-memory cache on iPad is enabled only when the tab switcher is enabled.
return !IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled();
}
- (BOOL)usesLRUCache {
// Always use the LRUCache when the tab switcher is enabled.
return experimental_flags::IsTabSwitcherEnabled() ||
experimental_flags::IsLRUSnapshotCacheEnabled();
}
- (void)handleLowMemory { - (void)handleLowMemory {
DCHECK(!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
DCHECK_CURRENTLY_ON(web::WebThread::UI); DCHECK_CURRENTLY_ON(web::WebThread::UI);
base::scoped_nsobject<NSMutableDictionary> dictionary( base::scoped_nsobject<NSMutableDictionary> dictionary(
[[NSMutableDictionary alloc] initWithCapacity:2]); [[NSMutableDictionary alloc] initWithCapacity:2]);
...@@ -411,14 +408,12 @@ void ConvertAndSaveGreyImage( ...@@ -411,14 +408,12 @@ void ConvertAndSaveGreyImage(
} }
- (void)handleEnterBackground { - (void)handleEnterBackground {
DCHECK(!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
DCHECK_CURRENTLY_ON(web::WebThread::UI); DCHECK_CURRENTLY_ON(web::WebThread::UI);
[imageDictionary_ removeAllObjects]; [imageDictionary_ removeAllObjects];
[lruCache_ removeAllObjects]; [lruCache_ removeAllObjects];
} }
- (void)handleBecomeActive { - (void)handleBecomeActive {
DCHECK(!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled());
DCHECK_CURRENTLY_ON(web::WebThread::UI); DCHECK_CURRENTLY_ON(web::WebThread::UI);
for (NSString* sessionID in pinnedIDs_) for (NSString* sessionID in pinnedIDs_)
[self retrieveImageForSessionID:sessionID callback:nil]; [self retrieveImageForSessionID:sessionID callback:nil];
...@@ -569,11 +564,12 @@ void ConvertAndSaveGreyImage( ...@@ -569,11 +564,12 @@ void ConvertAndSaveGreyImage(
@implementation SnapshotCache (TestingAdditions) @implementation SnapshotCache (TestingAdditions)
- (BOOL)hasImageInMemory:(NSString*)sessionID { - (BOOL)hasImageInMemory:(NSString*)sessionID {
if (experimental_flags::IsLRUSnapshotCacheEnabled()) if ([self usesLRUCache])
return [lruCache_ objectForKey:sessionID] != nil; return [lruCache_ objectForKey:sessionID] != nil;
else else
return [imageDictionary_ objectForKey:sessionID] != nil; return [imageDictionary_ objectForKey:sessionID] != nil;
} }
- (BOOL)hasGreyImageInMemory:(NSString*)sessionID { - (BOOL)hasGreyImageInMemory:(NSString*)sessionID {
return [greyImageDictionary_ objectForKey:sessionID] != nil; return [greyImageDictionary_ objectForKey:sessionID] != nil;
} }
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_CACHE_INTERNAL_H_
#define IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_CACHE_INTERNAL_H_
#import "ios/chrome/browser/snapshots/snapshot_cache_internal.h"
namespace base {
class FilePath;
}
@class NSString;
@interface SnapshotCache (Internal)
// Returns filepath to the color snapshot of |sessionID|.
+ (base::FilePath)imagePathForSessionID:(NSString*)sessionID;
// Returns filepath to the greyscale snapshot of |sessionID|.
+ (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
// Returns whether the snapshots are cached in a LRU cache.
- (BOOL)usesLRUCache;
// Returns whether the in-memory cache (as opposed to the on-disk cache) is
// enabled.
- (BOOL)inMemoryCacheIsEnabled;
@end
#endif // IOS_CHROME_BROWSER_SNAPSHOTS_SNAPSHOT_CACHE_INTERNAL_H_
\ No newline at end of file
...@@ -9,15 +9,13 @@ ...@@ -9,15 +9,13 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/format_macros.h" #include "base/format_macros.h"
#include "base/ios/ios_util.h"
#include "base/location.h" #include "base/location.h"
#include "base/mac/bind_objc_block.h" #include "base/mac/bind_objc_block.h"
#include "base/mac/scoped_nsautorelease_pool.h" #include "base/mac/scoped_nsautorelease_pool.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "ios/chrome/browser/experimental_flags.h" #import "ios/chrome/browser/snapshots/snapshot_cache_internal.h"
#include "ios/chrome/browser/ui/ui_util.h"
#include "ios/web/public/test/test_web_thread_bundle.h" #include "ios/web/public/test/test_web_thread_bundle.h"
#include "ios/web/public/web_thread.h" #include "ios/web/public/web_thread.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -27,13 +25,6 @@ ...@@ -27,13 +25,6 @@
static const NSUInteger kSessionCount = 10; static const NSUInteger kSessionCount = 10;
static const NSUInteger kSnapshotPixelSize = 8; static const NSUInteger kSnapshotPixelSize = 8;
// Promote some implementation methods to public.
@interface SnapshotCache (Testing)
+ (base::FilePath)imagePathForSessionID:(NSString*)sessionID;
+ (base::FilePath)greyImagePathForSessionID:(NSString*)sessionID;
- (void)handleLowMemory;
@end
namespace { namespace {
class SnapshotCacheTest : public PlatformTest { class SnapshotCacheTest : public PlatformTest {
...@@ -204,6 +195,13 @@ class SnapshotCacheTest : public PlatformTest { ...@@ -204,6 +195,13 @@ class SnapshotCacheTest : public PlatformTest {
return reinterpret_cast<const char*>(CFDataGetBytePtr(data)); return reinterpret_cast<const char*>(CFDataGetBytePtr(data));
} }
void TriggerMemoryWarning() {
// _performMemoryWarning is a private API and must not be compiled into
// official builds.
[[UIApplication sharedApplication]
performSelector:@selector(_performMemoryWarning)];
}
web::TestWebThreadBundle thread_bundle_; web::TestWebThreadBundle thread_bundle_;
base::scoped_nsobject<SnapshotCache> snapshotCache_; base::scoped_nsobject<SnapshotCache> snapshotCache_;
base::scoped_nsobject<NSMutableArray> testSessions_; base::scoped_nsobject<NSMutableArray> testSessions_;
...@@ -214,16 +212,13 @@ class SnapshotCacheTest : public PlatformTest { ...@@ -214,16 +212,13 @@ class SnapshotCacheTest : public PlatformTest {
// As the snapshots are kept in memory, the same pointer can be retrieved. // As the snapshots are kept in memory, the same pointer can be retrieved.
// This test also checks that images are correctly removed from the disk. // This test also checks that images are correctly removed from the disk.
TEST_F(SnapshotCacheTest, Cache) { TEST_F(SnapshotCacheTest, Cache) {
// Don't run on tablets because color snapshots are not cached so this test
// can't compare the UIImage pointers directly.
if (IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled()) {
return;
}
SnapshotCache* cache = GetSnapshotCache(); SnapshotCache* cache = GetSnapshotCache();
if (![cache inMemoryCacheIsEnabled])
return;
NSUInteger expectedCacheSize = kSessionCount; NSUInteger expectedCacheSize = kSessionCount;
if (experimental_flags::IsLRUSnapshotCacheEnabled()) if ([cache usesLRUCache])
expectedCacheSize = MIN(kSessionCount, [cache lruCacheMaxSize]); expectedCacheSize = MIN(kSessionCount, [cache lruCacheMaxSize]);
// Put all images in the cache. // Put all images in the cache.
...@@ -347,17 +342,8 @@ TEST_F(SnapshotCacheTest, Purge) { ...@@ -347,17 +342,8 @@ TEST_F(SnapshotCacheTest, Purge) {
} }
// Loads the color images into the cache, and pins two of them. Ensures that // Loads the color images into the cache, and pins two of them. Ensures that
// only the two pinned IDs remain in memory after a call to -handleLowMemory. // only the two pinned IDs remain in memory after a memory warning.
TEST_F(SnapshotCacheTest, HandleLowMemory) { TEST_F(SnapshotCacheTest, HandleMemoryWarning) {
// TODO(crbug.com/455209): This test failed on iPad iOS8 device, but may no
// longer be failing on iOS 9 and up. Should test by re-enabling and monitor.
#if !TARGET_IPHONE_SIMULATOR
if (IsIPadIdiom()) {
LOG(WARNING) << "Test disabled on iPad device.";
return;
}
#endif
LoadAllColorImagesIntoCache(true); LoadAllColorImagesIntoCache(true);
SnapshotCache* cache = GetSnapshotCache(); SnapshotCache* cache = GetSnapshotCache();
...@@ -369,15 +355,15 @@ TEST_F(SnapshotCacheTest, HandleLowMemory) { ...@@ -369,15 +355,15 @@ TEST_F(SnapshotCacheTest, HandleLowMemory) {
[set addObject:secondPinnedID]; [set addObject:secondPinnedID];
cache.pinnedIDs = set; cache.pinnedIDs = set;
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) TriggerMemoryWarning();
[cache handleLowMemory];
BOOL expectedValue = YES;
if (IsIPadIdiom() && !experimental_flags::IsTabSwitcherEnabled())
expectedValue = NO;
EXPECT_EQ(expectedValue, [cache hasImageInMemory:firstPinnedID]); if ([cache inMemoryCacheIsEnabled]) {
EXPECT_EQ(expectedValue, [cache hasImageInMemory:secondPinnedID]); EXPECT_EQ(YES, [cache hasImageInMemory:firstPinnedID]);
EXPECT_EQ(YES, [cache hasImageInMemory:secondPinnedID]);
} else {
EXPECT_EQ(NO, [cache hasImageInMemory:firstPinnedID]);
EXPECT_EQ(NO, [cache hasImageInMemory:secondPinnedID]);
}
NSString* notPinnedID = [testSessions_ objectAtIndex:2]; NSString* notPinnedID = [testSessions_ objectAtIndex:2];
EXPECT_FALSE([cache hasImageInMemory:notPinnedID]); EXPECT_FALSE([cache hasImageInMemory:notPinnedID]);
...@@ -424,8 +410,7 @@ TEST_F(SnapshotCacheTest, CreateGreyCacheFromDisk) { ...@@ -424,8 +410,7 @@ TEST_F(SnapshotCacheTest, CreateGreyCacheFromDisk) {
// Remove color images from in-memory cache. // Remove color images from in-memory cache.
SnapshotCache* cache = GetSnapshotCache(); SnapshotCache* cache = GetSnapshotCache();
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) TriggerMemoryWarning();
[cache handleLowMemory];
// Request the creation of a grey image cache for all images. // Request the creation of a grey image cache for all images.
[cache createGreyCache:testSessions_]; [cache createGreyCache:testSessions_];
...@@ -466,8 +451,7 @@ TEST_F(SnapshotCacheTest, MostRecentGreyBlock) { ...@@ -466,8 +451,7 @@ TEST_F(SnapshotCacheTest, MostRecentGreyBlock) {
LoadColorImagesIntoCache(kNumImages, true); LoadColorImagesIntoCache(kNumImages, true);
// Make sure the color images are only on disk, to ensure the background // Make sure the color images are only on disk, to ensure the background
// thread is slow enough to queue up the requests. // thread is slow enough to queue up the requests.
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) TriggerMemoryWarning();
[cache handleLowMemory];
// Enable the grey image cache. // Enable the grey image cache.
[cache createGreyCache:sessionIDs]; [cache createGreyCache:sessionIDs];
...@@ -538,8 +522,7 @@ TEST_F(SnapshotCacheTest, SizeAndScalePreservation) { ...@@ -538,8 +522,7 @@ TEST_F(SnapshotCacheTest, SizeAndScalePreservation) {
NSString* const kSession = @"foo"; NSString* const kSession = @"foo";
[cache setImage:image withSessionID:kSession]; [cache setImage:image withSessionID:kSession];
FlushRunLoops(); // ensure the file is written to disk. FlushRunLoops(); // ensure the file is written to disk.
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) TriggerMemoryWarning();
[cache handleLowMemory];
// Retrive the image and have the callback verify the size and scale. // Retrive the image and have the callback verify the size and scale.
__block BOOL callbackComplete = NO; __block BOOL callbackComplete = NO;
...@@ -575,8 +558,7 @@ TEST_F(SnapshotCacheTest, DeleteRetinaImages) { ...@@ -575,8 +558,7 @@ TEST_F(SnapshotCacheTest, DeleteRetinaImages) {
NSString* const kSession = @"foo"; NSString* const kSession = @"foo";
[cache setImage:image withSessionID:kSession]; [cache setImage:image withSessionID:kSession];
FlushRunLoops(); // ensure the file is written to disk. FlushRunLoops(); // ensure the file is written to disk.
if (!IsIPadIdiom() || experimental_flags::IsTabSwitcherEnabled()) TriggerMemoryWarning();
[cache handleLowMemory];
// Verify the file was writted with @2x in the file name. // Verify the file was writted with @2x in the file name.
base::FilePath retinaFile = [SnapshotCache imagePathForSessionID:kSession]; base::FilePath retinaFile = [SnapshotCache imagePathForSessionID:kSession];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment