chromium/chrome/browser/extensions/chrome_app_icon_unittest.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/run_loop.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/extensions/chrome_app_icon.h"
#include "chrome/browser/extensions/chrome_app_icon_delegate.h"
#include "chrome/browser/extensions/chrome_app_icon_loader.h"
#include "chrome/browser/extensions/chrome_app_icon_service.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_icon_loader_delegate.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/test/base/testing_profile.h"
#include "extensions/common/constants.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/image/image_unittest_util.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/components/arc/test/fake_app_instance.h"
#include "ash/public/cpp/app_list/app_list_config.h"
#include "chrome/browser/ash/app_list/arc/arc_app_test.h"
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/ash/extensions/gfx_utils.h"
#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

namespace extensions {

namespace {

constexpr char kTestAppId[] =;

// Receives icon image updates from ChromeAppIcon.
class TestAppIcon : public ChromeAppIconDelegate {};

// Receives icon image updates from ChromeAppIconLoader.
class TestAppIconLoader : public AppIconLoaderDelegate {};

// Returns true if provided |image| consists from only empty pixels.
bool IsBlankImage(const gfx::ImageSkia& image) {}

// Returns true if provided |image| is grayscale.
bool IsGrayscaleImage(const gfx::ImageSkia& image) {}

// Returns true if provided |image1| and |image2| are equal.
bool AreEqual(const gfx::ImageSkia& image1, const gfx::ImageSkia& image2) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
// Returns true if |res| image is the |src| image with badge identified by
// |badge_type| resource. If |grayscale| is true applies HSL shift for the
// comparison.
bool IsBadgeApplied(const gfx::ImageSkia& src,
                    const gfx::ImageSkia& res,
                    ChromeAppIcon::Badge badge_type,
                    bool grayscale) {
  src.EnsureRepsForSupportedScales();
  gfx::ImageSkia reference_src = src.DeepCopy();
  if (grayscale) {
    constexpr color_utils::HSL shift = {-1, 0, 0.6};
    reference_src =
        gfx::ImageSkiaOperations::CreateHSLShiftedImage(reference_src, shift);
  }
  util::ApplyBadge(&reference_src, badge_type);

  return AreEqual(reference_src, res);
}
#endif

}  // namespace

class ChromeAppIconTest : public ExtensionServiceTestBase {};

TEST_F(ChromeAppIconTest, IconLifeCycle) {}

// Validates that icon release is safe.
TEST_F(ChromeAppIconTest, IconRelease) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(ChromeAppIconTest, ChromeBadging) {
  ArcAppTest arc_test;
  arc_test.SetUp(profile());

  TestAppIcon reference_icon(profile(), kTestAppId,
                             extension_misc::EXTENSION_ICON_MEDIUM);
  // Wait until reference data is loaded.
  EXPECT_FALSE(reference_icon.image_skia().GetRepresentation(1.0f).is_null());
  reference_icon.WaitForIconUpdates();
  EXPECT_FALSE(IsBlankImage(reference_icon.image_skia()));

  reference_icon.GetIconUpdateCountAndReset();
  const gfx::ImageSkia image_before_badging = reference_icon.image_skia();

  // Badging should be applied once package is installed.
  std::vector<arc::mojom::AppInfoPtr> fake_apps =
      ArcAppTest::CloneApps(arc_test.fake_apps());
  fake_apps[0]->package_name = arc_test.fake_packages()[0]->package_name;
  arc_test.app_instance()->SendRefreshAppList(fake_apps);
  arc_test.app_instance()->SendRefreshPackageList(
      ArcAppTest::ClonePackages(arc_test.fake_packages()));

  // Expect the package list refresh to generate two icon updates - one called
  // by ArcAppListPrefs, and one called by LaunchExtensionAppUpdate.
  EXPECT_EQ(2U, reference_icon.icon_update_count());
  EXPECT_FALSE(AreEqual(reference_icon.image_skia(), image_before_badging));
  EXPECT_TRUE(IsBadgeApplied(image_before_badging, reference_icon.image_skia(),
                             ChromeAppIcon::Badge::kChrome,
                             false /* grayscale */));

  // Opts out the Play Store. Badge should be gone and icon image is the same
  // as it was before badging.
  arc::SetArcPlayStoreEnabledForProfile(profile(), false);
  // Wait for the asynchronous ArcAppListPrefs::RemoveAllAppsAndPackages to be
  // called.
  arc_test.WaitForRemoveAllApps();
  EXPECT_TRUE(AreEqual(reference_icon.image_skia(), image_before_badging));
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

}  // namespace extensions