blob: f9c7f8d5e9f90cacf3bec462af2f6dc4ad43dbc1 [file] [log] [blame]
// Copyright 2018 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.
#include "chrome/browser/web_applications/web_app_icon_manager.h"
#include <memory>
#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "chrome/browser/web_applications/components/web_app_constants.h"
#include "chrome/browser/web_applications/components/web_app_icon_generator.h"
#include "chrome/browser/web_applications/test/test_file_utils.h"
#include "chrome/browser/web_applications/test/test_web_app_database_factory.h"
#include "chrome/browser/web_applications/test/test_web_app_registry_controller.h"
#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
#include "chrome/browser/web_applications/test/web_app_test.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include "chrome/test/base/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace web_app {
class WebAppIconManagerTest : public WebAppTest {
void SetUp() override {
WebAppTest::SetUp();
test_registry_controller_ =
std::make_unique<TestWebAppRegistryController>();
test_registry_controller_->SetUp(profile());
auto file_utils = std::make_unique<TestFileUtils>();
file_utils_ = file_utils.get();
icon_manager_ = std::make_unique<WebAppIconManager>(profile(), registrar(),
std::move(file_utils));
controller().Init();
}
protected:
void WriteIcons(const AppId& app_id,
const GURL& app_url,
const std::vector<int>& sizes_px,
const std::vector<SkColor>& colors) {
DCHECK_EQ(sizes_px.size(), colors.size());
auto web_app_info = std::make_unique<WebApplicationInfo>();
web_app_info->icons.reserve(sizes_px.size());
for (size_t i = 0; i < sizes_px.size(); ++i) {
std::string icon_name = base::StringPrintf("app-%d.ico", sizes_px[i]);
GURL icon_url = app_url.Resolve(icon_name);
web_app_info->icons.push_back(
GenerateIconInfo(icon_url, sizes_px[i], colors[i]));
}
base::RunLoop run_loop;
icon_manager_->WriteData(app_id, std::move(web_app_info),
base::BindLambdaForTesting([&](bool success) {
EXPECT_TRUE(success);
run_loop.Quit();
}));
run_loop.Run();
}
WebApp::Icons ListIcons(const GURL& app_url,
const std::vector<int>& sizes_px) {
WebApp::Icons icons;
icons.reserve(sizes_px.size());
for (size_t i = 0; i < sizes_px.size(); ++i) {
std::string icon_name = base::StringPrintf("app-%d.ico", sizes_px[i]);
GURL icon_url = app_url.Resolve(icon_name);
icons.push_back({icon_url, sizes_px[i]});
}
return icons;
}
std::unique_ptr<WebApp> CreateWebApp() {
const GURL app_url = GURL("https://example.com/path");
const AppId app_id = GenerateAppIdFromURL(app_url);
auto web_app = std::make_unique<WebApp>(app_id);
web_app->AddSource(Source::kSync);
web_app->SetLaunchContainer(LaunchContainer::kWindow);
web_app->SetName("Name");
web_app->SetLaunchUrl(app_url);
return web_app;
}
TestWebAppRegistryController& controller() {
return *test_registry_controller_;
}
WebAppRegistrar& registrar() { return controller().registrar(); }
WebAppSyncBridge& sync_bridge() { return controller().sync_bridge(); }
WebAppIconManager& icon_manager() { return *icon_manager_; }
private:
std::unique_ptr<TestWebAppRegistryController> test_registry_controller_;
std::unique_ptr<WebAppIconManager> icon_manager_;
// Owned by icon_manager_:
TestFileUtils* file_utils_ = nullptr;
};
TEST_F(WebAppIconManagerTest, WriteAndReadIcon) {
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();
const std::vector<int> sizes_px{icon_size::k512};
const std::vector<SkColor> colors{SK_ColorYELLOW};
WriteIcons(app_id, web_app->launch_url(), sizes_px, colors);
web_app->SetIcons(ListIcons(web_app->launch_url(), sizes_px));
controller().RegisterApp(std::move(web_app));
{
base::RunLoop run_loop;
const bool icon_requested = icon_manager().ReadIcon(
app_id, sizes_px[0], base::BindLambdaForTesting([&](SkBitmap bitmap) {
EXPECT_FALSE(bitmap.empty());
EXPECT_EQ(colors[0], bitmap.getColor(0, 0));
run_loop.Quit();
}));
EXPECT_TRUE(icon_requested);
run_loop.Run();
}
}
TEST_F(WebAppIconManagerTest, ReadIconFailed) {
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();
const GURL icon_url = GURL("https://example.com/app.ico");
const int icon_size_px = icon_size::k256;
// Set icon meta-info but don't write bitmap to disk.
WebApp::Icons icons;
icons.push_back({icon_url, icon_size_px});
web_app->SetIcons(std::move(icons));
controller().RegisterApp(std::move(web_app));
// Request non-existing icon size.
EXPECT_FALSE(
icon_manager().ReadIcon(app_id, icon_size::k96, base::DoNothing()));
// Request existing icon size which doesn't exist on disk.
base::RunLoop run_loop;
const bool icon_requested = icon_manager().ReadIcon(
app_id, icon_size_px, base::BindLambdaForTesting([&](SkBitmap bitmap) {
EXPECT_TRUE(bitmap.empty());
run_loop.Quit();
}));
EXPECT_TRUE(icon_requested);
run_loop.Run();
}
TEST_F(WebAppIconManagerTest, FindExact) {
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();
const std::vector<int> sizes_px{10, 60, 50, 20, 30};
const std::vector<SkColor> colors{SK_ColorRED, SK_ColorYELLOW, SK_ColorGREEN,
SK_ColorBLUE, SK_ColorMAGENTA};
WriteIcons(app_id, web_app->launch_url(), sizes_px, colors);
web_app->SetIcons(ListIcons(web_app->launch_url(), sizes_px));
controller().RegisterApp(std::move(web_app));
{
const bool icon_requested = icon_manager().ReadIcon(
app_id, 40,
base::BindLambdaForTesting([&](SkBitmap bitmap) { NOTREACHED(); }));
EXPECT_FALSE(icon_requested);
}
{
base::RunLoop run_loop;
const bool icon_requested = icon_manager().ReadIcon(
app_id, 20, base::BindLambdaForTesting([&](SkBitmap bitmap) {
EXPECT_FALSE(bitmap.empty());
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(0, 0));
run_loop.Quit();
}));
EXPECT_TRUE(icon_requested);
run_loop.Run();
}
}
TEST_F(WebAppIconManagerTest, FindSmallest) {
auto web_app = CreateWebApp();
const AppId app_id = web_app->app_id();
const std::vector<int> sizes_px{10, 60, 50, 20, 30};
const std::vector<SkColor> colors{SK_ColorRED, SK_ColorYELLOW, SK_ColorGREEN,
SK_ColorBLUE, SK_ColorMAGENTA};
WriteIcons(app_id, web_app->launch_url(), sizes_px, colors);
web_app->SetIcons(ListIcons(web_app->launch_url(), sizes_px));
controller().RegisterApp(std::move(web_app));
{
const bool icon_requested = icon_manager().ReadSmallestIcon(
app_id, 70,
base::BindLambdaForTesting([&](SkBitmap bitmap) { NOTREACHED(); }));
EXPECT_FALSE(icon_requested);
}
{
base::RunLoop run_loop;
const bool icon_requested = icon_manager().ReadSmallestIcon(
app_id, 40, base::BindLambdaForTesting([&](SkBitmap bitmap) {
EXPECT_FALSE(bitmap.empty());
EXPECT_EQ(SK_ColorGREEN, bitmap.getColor(0, 0));
run_loop.Quit();
}));
EXPECT_TRUE(icon_requested);
run_loop.Run();
}
{
base::RunLoop run_loop;
const bool icon_requested = icon_manager().ReadSmallestIcon(
app_id, 20, base::BindLambdaForTesting([&](SkBitmap bitmap) {
EXPECT_FALSE(bitmap.empty());
EXPECT_EQ(SK_ColorBLUE, bitmap.getColor(0, 0));
run_loop.Quit();
}));
EXPECT_TRUE(icon_requested);
run_loop.Run();
}
}
} // namespace web_app