123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- // Copyright 2014 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 <string>
- #include "base/files/file.h"
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/path_service.h"
- #include "base/strings/string_split.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "extensions/common/extension_paths.h"
- #include "extensions/common/image_util.h"
- #include "extensions/test/logging_timer.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/skia/include/core/SkBitmap.h"
- #include "third_party/skia/include/core/SkColor.h"
- #include "ui/gfx/codec/png_codec.h"
- #include "ui/gfx/color_utils.h"
- #include "url/gurl.h"
- namespace extensions {
- TEST(ImageUtilTest, IsIconSufficientlyVisible) {
- base::FilePath test_dir;
- ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir));
- base::FilePath icon_path;
- const std::string metric_name =
- "Extensions.IsRenderedIconSufficientlyVisibleTime";
- {
- base::HistogramTester histogram_tester;
- // This icon has all transparent pixels, so it will fail.
- icon_path = test_dir.AppendASCII("transparent_icon.png");
- SkBitmap transparent_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &transparent_icon));
- EXPECT_FALSE(image_util::IsIconSufficientlyVisible(transparent_icon));
- EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(transparent_icon,
- SK_ColorWHITE));
- histogram_tester.ExpectTotalCount(metric_name, 1);
- }
- {
- base::HistogramTester histogram_tester;
- // Test with an icon that has one opaque pixel.
- icon_path = test_dir.AppendASCII("one_pixel_opaque_icon.png");
- SkBitmap visible_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
- EXPECT_FALSE(image_util::IsIconSufficientlyVisible(visible_icon));
- EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
- SK_ColorWHITE));
- histogram_tester.ExpectTotalCount(metric_name, 1);
- }
- {
- base::HistogramTester histogram_tester;
- // Test with an icon that has one transparent pixel.
- icon_path = test_dir.AppendASCII("one_pixel_transparent_icon.png");
- SkBitmap visible_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
- EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
- EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
- SK_ColorWHITE));
- histogram_tester.ExpectTotalCount(metric_name, 1);
- }
- {
- base::HistogramTester histogram_tester;
- // Test with an icon that is completely opaque.
- icon_path = test_dir.AppendASCII("opaque_icon.png");
- SkBitmap visible_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
- EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
- EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
- SK_ColorWHITE));
- histogram_tester.ExpectTotalCount(metric_name, 1);
- }
- {
- base::HistogramTester histogram_tester;
- // Test with an icon that is rectangular.
- icon_path = test_dir.AppendASCII("rectangle.png");
- SkBitmap visible_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
- EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
- EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
- SK_ColorWHITE));
- histogram_tester.ExpectTotalCount(metric_name, 1);
- }
- {
- base::HistogramTester histogram_tester;
- // Test with a solid color icon that is completely opaque. Use the icon's
- // color as the background color in the call to analyze its visibility.
- // It should be invisible in this case.
- icon_path = test_dir.AppendASCII("grey_21x21.png");
- SkBitmap solid_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &solid_icon));
- const SkColor pixel_color = solid_icon.getColor(0, 0);
- EXPECT_FALSE(
- image_util::IsRenderedIconSufficientlyVisible(solid_icon, pixel_color));
- histogram_tester.ExpectTotalCount(metric_name, 1);
- }
- {
- base::HistogramTester histogram_tester;
- // Test with a two-color icon that is completely opaque. Use one of the
- // icon's colors as the background color in the call to analyze its
- // visibility. It should be visible in this case.
- icon_path = test_dir.AppendASCII("two_color_21x21.png");
- SkBitmap two_color_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &two_color_icon));
- const SkColor pixel_color = two_color_icon.getColor(0, 0);
- EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(two_color_icon,
- pixel_color));
- histogram_tester.ExpectTotalCount(metric_name, 1);
- }
- }
- TEST(ImageUtilTest, IconTooLargeForAnalysis) {
- base::FilePath test_dir;
- ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir));
- // This is a large icon which is entirely black, so it would be
- // visible. However, it exceeds the max allowed size for analysis,
- // so it will fail.
- base::FilePath icon_path = test_dir.AppendASCII("3000x3000.png");
- SkBitmap large_icon;
- SkBitmap rendered_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &large_icon));
- EXPECT_FALSE(image_util::RenderIconForVisibilityAnalysis(
- large_icon, SK_ColorWHITE, &rendered_icon));
- // Shrink the icon so it's under the limit. It should be visible.
- const SkImageInfo& image_info = large_icon.info();
- SkImageInfo new_image_info = SkImageInfo::Make(
- 128, 128, image_info.colorType(), image_info.alphaType());
- ASSERT_TRUE(large_icon.setInfo(new_image_info));
- EXPECT_TRUE(image_util::RenderIconForVisibilityAnalysis(
- large_icon, SK_ColorWHITE, &rendered_icon));
- EXPECT_FALSE(rendered_icon.empty());
- }
- TEST(ImageUtilTest, MANUAL_IsIconSufficientlyVisiblePerfTest) {
- base::FilePath test_dir;
- ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir));
- base::FilePath icon_path;
- // This icon has all transparent pixels.
- icon_path = test_dir.AppendASCII("transparent_icon.png");
- SkBitmap invisible_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &invisible_icon));
- // This icon is completely opaque.
- icon_path = test_dir.AppendASCII("opaque_icon.png");
- SkBitmap visible_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, &visible_icon));
- static constexpr char kInvisibleTimerId[] = "InvisibleIcon";
- static constexpr char kVisibleTimerId[] = "VisibleIcon";
- static constexpr char kInvisibleRenderedTimerId[] = "InvisibleRenderedIcon";
- static constexpr char kVisibleRenderedTimerId[] = "VisibleRenderedIcon";
- constexpr int kIterations = 100000;
- for (int i = 0; i < kIterations; ++i) {
- LoggingTimer timer(kInvisibleTimerId);
- EXPECT_FALSE(image_util::IsIconSufficientlyVisible(invisible_icon));
- }
- for (int i = 0; i < kIterations; ++i) {
- LoggingTimer timer(kVisibleTimerId);
- EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
- }
- for (int i = 0; i < kIterations; ++i) {
- LoggingTimer timer(kInvisibleRenderedTimerId);
- EXPECT_FALSE(image_util::IsRenderedIconSufficientlyVisible(invisible_icon,
- SK_ColorWHITE));
- }
- for (int i = 0; i < kIterations; ++i) {
- LoggingTimer timer(kVisibleRenderedTimerId);
- EXPECT_TRUE(image_util::IsRenderedIconSufficientlyVisible(visible_icon,
- SK_ColorWHITE));
- }
- LoggingTimer::Print();
- }
- namespace {
- void WriteRenderedIcon(const SkBitmap& icon,
- SkColor background_color,
- const base::FilePath& rendered_icon_path) {
- SkBitmap bitmap;
- DCHECK(image_util::RenderIconForVisibilityAnalysis(icon, background_color,
- &bitmap));
- std::vector<unsigned char> output_data;
- ASSERT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output_data));
- const int bytes_to_write = output_data.size();
- ASSERT_EQ(bytes_to_write,
- base::WriteFile(rendered_icon_path,
- reinterpret_cast<const char*>(&output_data[0]),
- bytes_to_write));
- }
- } // namespace
- TEST(ImageUtilTest, DISABLED_AnalyzeAllDownloadedIcons) {
- // See the README in extensions/test/data/icon_visibility for more details
- // on running this test.
- // TODO(crbug.com/805600): Remove this test when the bug is closed.
- base::FilePath test_dir;
- ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir));
- test_dir = test_dir.AppendASCII("icon_visibility");
- base::FilePath icons_file_path = test_dir.AppendASCII("source_urls.txt");
- std::string file_data;
- ASSERT_TRUE(base::ReadFileToString(icons_file_path, &file_data));
- base::FilePath output_file_path =
- test_dir.AppendASCII("invisible_source_urls.txt");
- base::File output_file(output_file_path, base::File::FLAG_CREATE_ALWAYS |
- base::File::FLAG_WRITE);
- ASSERT_TRUE(output_file.IsValid());
- base::FilePath rendered_icon_path = test_dir.AppendASCII("rendered_pngs");
- ASSERT_TRUE(base::CreateDirectory(rendered_icon_path));
- base::FilePath downloaded_icons_path = test_dir.AppendASCII("pngs");
- ASSERT_TRUE(base::DirectoryExists(downloaded_icons_path));
- const std::vector<base::StringPiece> urls = base::SplitStringPiece(
- file_data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- for (const base::StringPiece url : urls) {
- const std::string file_name = GURL(url).ExtractFileName();
- base::FilePath icon_path = downloaded_icons_path.AppendASCII(file_name);
- SkBitmap current_icon;
- ASSERT_TRUE(image_util::LoadPngFromFile(icon_path, ¤t_icon));
- if (!image_util::IsRenderedIconSufficientlyVisible(current_icon,
- SK_ColorWHITE)) {
- output_file.WriteAtCurrentPos(url.data(), url.length());
- output_file.WriteAtCurrentPos("\n", 1);
- WriteRenderedIcon(current_icon, SK_ColorWHITE,
- rendered_icon_path.AppendASCII(file_name + ".png"));
- }
- }
- }
- } // namespace extensions
|