blob: de859d7afeed256f17c173382115c30254b5eae4 [file] [log] [blame]
// Copyright 2017 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.
#import "ios/chrome/browser/ui/ntp/ntp_tile_saver.h"
#include "base/run_loop.h"
#import "base/strings/sys_string_conversions.h"
#import "base/strings/utf_string_conversions.h"
#include "base/test/scoped_task_environment.h"
#import "components/ntp_tiles/ntp_tile.h"
#import "ios/chrome/browser/ui/favicon/favicon_attributes.h"
#import "ios/chrome/browser/ui/favicon/favicon_attributes_provider.h"
#import "ios/chrome/browser/ui/ntp/ntp_tile.h"
#import "ios/chrome/test/block_cleanup_test.h"
#import "net/base/mac/url_conversions.h"
#import "testing/gtest_mac.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
class NTPTileSaverControllerTest : public BlockCleanupTest {
protected:
void SetUp() override {
BlockCleanupTest::SetUp();
if ([[NSFileManager defaultManager]
fileExistsAtPath:[testFaviconDirectory() path]]) {
[[NSFileManager defaultManager] removeItemAtURL:testFaviconDirectory()
error:nil];
}
}
void TearDown() override {
if ([[NSFileManager defaultManager]
fileExistsAtPath:[testFaviconDirectory() path]]) {
[[NSFileManager defaultManager] removeItemAtURL:testFaviconDirectory()
error:nil];
}
BlockCleanupTest::TearDown();
}
NSURL* testFaviconDirectory() {
return
[[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask]
firstObject] URLByAppendingPathComponent:@"testFaviconFolder"];
}
void setupMockCallback(id mock,
std::set<GURL> imageURLs,
std::set<GURL> fallbackURLs) {
OCMStub([[mock ignoringNonObjectArgs]
fetchFaviconAttributesForURL:GURL()
completion:[OCMArg isNotNil]])
.andDo(^(NSInvocation* invocation) {
GURL* urltest;
[invocation getArgument:&urltest atIndex:2];
if (imageURLs.find(GURL(*urltest)) != imageURLs.end()) {
__unsafe_unretained void (^callback)(id);
[invocation getArgument:&callback atIndex:3];
UIGraphicsBeginImageContext(CGSizeMake(10, 10));
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
callback([FaviconAttributes attributesWithImage:image]);
} else if (fallbackURLs.find(GURL(*urltest)) != fallbackURLs.end()) {
__unsafe_unretained void (^callback)(id);
[invocation getArgument:&callback atIndex:3];
callback([FaviconAttributes
attributesWithMonogram:@"C"
textColor:UIColor.whiteColor
backgroundColor:UIColor.blueColor
defaultBackgroundColor:NO]);
}
});
}
void verifyWithImage(NTPTile* tile,
NSString* expectedTitle,
NSURL* expectedURL) {
EXPECT_NSNE(tile, nil);
EXPECT_NSEQ(tile.title, expectedTitle);
EXPECT_NSEQ(tile.URL, expectedURL);
EXPECT_TRUE(tile.faviconFetched);
EXPECT_NSNE(tile.faviconFileName, nil);
EXPECT_NSEQ(tile.fallbackTextColor, nil);
EXPECT_NSEQ(tile.fallbackBackgroundColor, nil);
EXPECT_TRUE([[NSFileManager defaultManager]
fileExistsAtPath:[[testFaviconDirectory()
URLByAppendingPathComponent:tile.faviconFileName]
path]]);
}
void verifyWithFallback(NTPTile* tile,
NSString* expectedTitle,
NSURL* expectedURL) {
EXPECT_NSNE(tile, nil);
EXPECT_NSEQ(tile.title, expectedTitle);
EXPECT_NSEQ(tile.URL, expectedURL);
EXPECT_TRUE(tile.faviconFetched);
EXPECT_NSEQ(tile.faviconFileName, nil);
EXPECT_NSEQ(tile.fallbackTextColor, UIColor.whiteColor);
EXPECT_NSEQ(tile.fallbackBackgroundColor, UIColor.blueColor);
EXPECT_EQ(tile.fallbackIsDefaultColor, NO);
}
protected:
base::test::ScopedTaskEnvironment scoped_task_evironment_;
};
TEST_F(NTPTileSaverControllerTest, SaveMostVisitedToDisk) {
ntp_tiles::NTPTile imageTile = ntp_tiles::NTPTile();
imageTile.title = base::ASCIIToUTF16("Title");
imageTile.url = GURL("http://image.com");
ntp_tiles::NTPTile fallbackTile = ntp_tiles::NTPTile();
fallbackTile.title = base::ASCIIToUTF16("Title");
fallbackTile.url = GURL("http://fallback.com");
id mockFaviconFetcher = OCMClassMock([FaviconAttributesProvider class]);
setupMockCallback(mockFaviconFetcher, {imageTile.url}, {fallbackTile.url});
ntp_tiles::NTPTilesVector tiles = {
fallbackTile, // NTP tile with fallback data
imageTile, // NTP tile with favicon
};
ntp_tile_saver::SaveMostVisitedToDisk(tiles, mockFaviconFetcher,
testFaviconDirectory());
// Wait for all asynchronous tasks to complete.
scoped_task_evironment_.RunUntilIdle();
// Read most visited from disk.
NSDictionary<NSURL*, NTPTile*>* savedTiles =
ntp_tile_saver::ReadSavedMostVisited();
EXPECT_EQ(savedTiles.count, 2U);
NSString* fallbackTitle = base::SysUTF16ToNSString(fallbackTile.title);
NSURL* fallbackURL = net::NSURLWithGURL(fallbackTile.url);
NTPTile* fallbackSavedTile = [savedTiles objectForKey:fallbackURL];
verifyWithFallback(fallbackSavedTile, fallbackTitle, fallbackURL);
NSString* imageTitle = base::SysUTF16ToNSString(imageTile.title);
NSURL* imageURL = net::NSURLWithGURL(imageTile.url);
NTPTile* imageSavedTile = [savedTiles objectForKey:imageURL];
verifyWithImage(imageSavedTile, imageTitle, imageURL);
}
TEST_F(NTPTileSaverControllerTest, UpdateSingleFaviconFallback) {
// Set up test with 3 saved sites, 2 of which have a favicon.
ntp_tiles::NTPTile imageTile1 = ntp_tiles::NTPTile();
imageTile1.title = base::ASCIIToUTF16("Title1");
imageTile1.url = GURL("http://image1.com");
ntp_tiles::NTPTile imageTile2 = ntp_tiles::NTPTile();
imageTile2.title = base::ASCIIToUTF16("Title2");
imageTile2.url = GURL("http://image2.com");
ntp_tiles::NTPTile fallbackTile = ntp_tiles::NTPTile();
fallbackTile.title = base::ASCIIToUTF16("Title");
fallbackTile.url = GURL("http://fallback.com");
id mockFaviconFetcher = OCMClassMock([FaviconAttributesProvider class]);
setupMockCallback(mockFaviconFetcher, {imageTile1.url, imageTile2.url},
{fallbackTile.url});
ntp_tiles::NTPTilesVector tiles = {imageTile1, fallbackTile, imageTile2};
ntp_tile_saver::SaveMostVisitedToDisk(tiles, mockFaviconFetcher,
testFaviconDirectory());
// Wait for all asynchronous tasks to complete.
scoped_task_evironment_.RunUntilIdle();
// Read most visited from disk.
NSDictionary<NSURL*, NTPTile*>* savedTiles =
ntp_tile_saver::ReadSavedMostVisited();
EXPECT_EQ(savedTiles.count, 3U);
NSString* image1Title = base::SysUTF16ToNSString(imageTile1.title);
NSURL* image1URL = net::NSURLWithGURL(imageTile1.url);
NTPTile* image1SavedTile = [savedTiles objectForKey:image1URL];
verifyWithImage(image1SavedTile, image1Title, image1URL);
NSString* image2Title = base::SysUTF16ToNSString(imageTile2.title);
NSURL* image2URL = net::NSURLWithGURL(imageTile2.url);
NTPTile* image2SavedTile = [savedTiles objectForKey:image2URL];
verifyWithImage(image2SavedTile, image2Title, image2URL);
NSString* fallbackTitle = base::SysUTF16ToNSString(fallbackTile.title);
NSURL* fallbackURL = net::NSURLWithGURL(fallbackTile.url);
NTPTile* fallbackSavedTile = [savedTiles objectForKey:fallbackURL];
verifyWithFallback(fallbackSavedTile, fallbackTitle, fallbackURL);
// Mock returning a fallback value for the first image tile.
id mockFaviconFetcher2 = OCMClassMock([FaviconAttributesProvider class]);
setupMockCallback(mockFaviconFetcher2, {imageTile2.url},
{imageTile1.url, fallbackTile.url});
ntp_tile_saver::UpdateSingleFavicon(imageTile1.url, mockFaviconFetcher2,
testFaviconDirectory());
// Wait for all asynchronous tasks to complete.
scoped_task_evironment_.RunUntilIdle();
// Read most visited from disk.
NSDictionary<NSURL*, NTPTile*>* savedTilesAfterUpdate =
ntp_tile_saver::ReadSavedMostVisited();
EXPECT_EQ(savedTilesAfterUpdate.count, 3U);
// Verify that the first image tile now has callback data.
image1SavedTile = [savedTilesAfterUpdate objectForKey:image1URL];
verifyWithFallback(image1SavedTile, image1Title, image1URL);
// Verify that the other two tiles did not change.
image2SavedTile = [savedTiles objectForKey:image2URL];
verifyWithImage(image2SavedTile, image2Title, image2URL);
fallbackSavedTile = [savedTilesAfterUpdate objectForKey:fallbackURL];
verifyWithFallback(fallbackSavedTile, fallbackTitle, fallbackURL);
}
} // anonymous namespace