// 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 "extensions/browser/extension_icon_image.h"

#include <vector>

#include "base/json/json_file_value_serializer.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "content/public/test/test_browser_context.h"
#include "extensions/browser/extensions_test.h"
#include "extensions/browser/image_loader.h"
#include "extensions/browser/test_image_loader.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_paths.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "skia/ext/image_operations.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/skia_util.h"

namespace extensions {
namespace {

SkBitmap CreateBlankBitmapForScale(int size_dip, ui::ScaleFactor scale_factor) {
  SkBitmap bitmap;
  const float scale = ui::GetScaleForScaleFactor(scale_factor);
  bitmap.allocN32Pixels(static_cast<int>(size_dip * scale),
                        static_cast<int>(size_dip * scale));
  bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
  return bitmap;
}

SkBitmap EnsureBitmapSize(const SkBitmap& original, int size) {
  if (original.width() == size && original.height() == size)
    return original;

  SkBitmap resized = skia::ImageOperations::Resize(
      original, skia::ImageOperations::RESIZE_LANCZOS3, size, size);
  return resized;
}

// Used to test behavior including images defined by an image skia source.
// |GetImageForScale| simply returns image representation from the image given
// in the ctor.
class MockImageSkiaSource : public gfx::ImageSkiaSource {
 public:
  explicit MockImageSkiaSource(const gfx::ImageSkia& image)
      : image_(image) {
  }
  ~MockImageSkiaSource() override {}

  gfx::ImageSkiaRep GetImageForScale(float scale) override {
    return image_.GetRepresentation(scale);
  }

 private:
  gfx::ImageSkia image_;
};

class ExtensionIconImageTest : public ExtensionsTest,
                               public IconImage::Observer {
 public:
  ExtensionIconImageTest()
      : image_loaded_count_(0), quit_in_image_loaded_(false) {}

  ~ExtensionIconImageTest() override {}

  void WaitForImageLoad() {
    quit_in_image_loaded_ = true;
    base::RunLoop().Run();
    quit_in_image_loaded_ = false;
  }

  int ImageLoadedCount() {
    int result = image_loaded_count_;
    image_loaded_count_ = 0;
    return result;
  }

  scoped_refptr<Extension> CreateExtension(const char* name,
                                           Manifest::Location location) {
    // Create and load an extension.
    base::FilePath test_file;
    if (!base::PathService::Get(DIR_TEST_DATA, &test_file)) {
      EXPECT_FALSE(true);
      return NULL;
    }
    test_file = test_file.AppendASCII(name);
    int error_code = 0;
    std::string error;
    JSONFileValueDeserializer deserializer(
        test_file.AppendASCII("manifest.json"));
    std::unique_ptr<base::DictionaryValue> valid_value =
        base::DictionaryValue::From(
            deserializer.Deserialize(&error_code, &error));
    EXPECT_EQ(0, error_code) << error;
    if (error_code != 0)
      return NULL;

    EXPECT_TRUE(valid_value.get());
    if (!valid_value)
      return NULL;

    return Extension::Create(test_file, location, *valid_value,
                             Extension::NO_FLAGS, &error);
  }

  // IconImage::Delegate overrides:
  void OnExtensionIconImageChanged(IconImage* image) override {
    image_loaded_count_++;
    if (quit_in_image_loaded_)
      base::RunLoop::QuitCurrentWhenIdleDeprecated();
  }

  gfx::ImageSkia GetDefaultIcon() {
    return gfx::ImageSkia(gfx::ImageSkiaRep(gfx::Size(16, 16), 1.0f));
  }

 private:
  int image_loaded_count_;
  bool quit_in_image_loaded_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest);
};

}  // namespace

TEST_F(ExtensionIconImageTest, Basic) {
  std::vector<ui::ScaleFactor> supported_factors;
  supported_factors.push_back(ui::SCALE_FACTOR_100P);
  supported_factors.push_back(ui::SCALE_FACTOR_200P);
  ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors);
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  gfx::ImageSkia default_icon = GetDefaultIcon();

  // Load images we expect to find as representations in icon_image, so we
  // can later use them to validate icon_image.
  SkBitmap bitmap_16 =
      TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "16.png", 16);
  ASSERT_FALSE(bitmap_16.empty());

  // There is no image of size 32 defined in the extension manifest, so we
  // should expect manifest image of size 48 resized to size 32.
  SkBitmap bitmap_48_resized_to_32 =
      TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "48.png", 32);
  ASSERT_FALSE(bitmap_48_resized_to_32.empty());

  IconImage image(browser_context(),
                  extension.get(),
                  IconsInfo::GetIcons(extension.get()),
                  16,
                  default_icon,
                  this);

  // No representations in |image_| yet.
  gfx::ImageSkia::ImageSkiaReps image_reps = image.image_skia().image_reps();
  ASSERT_EQ(0u, image_reps.size());

  // Gets representation for a scale factor.
  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);

  // Before the image representation is loaded, image should contain blank
  // image representation.
  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_100P)));

  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  ASSERT_EQ(1u, image.image_skia().image_reps().size());

  representation = image.image_skia().GetRepresentation(1.0f);

  // We should get the right representation now.
  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(), bitmap_16));
  EXPECT_EQ(16, representation.pixel_width());

  // Gets representation for an additional scale factor.
  representation = image.image_skia().GetRepresentation(2.0f);

  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P)));

  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  ASSERT_EQ(2u, image.image_skia().image_reps().size());

  representation = image.image_skia().GetRepresentation(2.0f);

  // Image should have been resized.
  EXPECT_EQ(32, representation.pixel_width());
  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(),
                                   bitmap_48_resized_to_32));
}

// There is no resource with either exact or bigger size, but there is a smaller
// resource.
TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) {
  std::vector<ui::ScaleFactor> supported_factors;
  supported_factors.push_back(ui::SCALE_FACTOR_100P);
  supported_factors.push_back(ui::SCALE_FACTOR_200P);
  ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors);
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  gfx::ImageSkia default_icon = GetDefaultIcon();

  // Load images we expect to find as representations in icon_image, so we
  // can later use them to validate icon_image.
  SkBitmap bitmap_48 =
      TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "48.png", 48);
  ASSERT_FALSE(bitmap_48.empty());

  IconImage image(browser_context(),
                  extension.get(),
                  IconsInfo::GetIcons(extension.get()),
                  32,
                  default_icon,
                  this);

  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(2.0f);

  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  ASSERT_EQ(1u, image.image_skia().image_reps().size());

  representation = image.image_skia().GetRepresentation(2.0f);

  // We should have loaded the biggest smaller resource resized to the actual
  // size.
  EXPECT_EQ(2.0f, representation.scale());
  EXPECT_EQ(64, representation.pixel_width());
  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(),
                                   EnsureBitmapSize(bitmap_48, 64)));
}

// There is no resource with exact size, but there is a smaller and a bigger
// one. The bigger resource should be loaded.
TEST_F(ExtensionIconImageTest, FallbackToBigger) {
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  gfx::ImageSkia default_icon = GetDefaultIcon();

  // Load images we expect to find as representations in icon_image, so we
  // can later use them to validate icon_image.
  SkBitmap bitmap_24 =
      TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "24.png", 24);
  ASSERT_FALSE(bitmap_24.empty());

  IconImage image(browser_context(),
                  extension.get(),
                  IconsInfo::GetIcons(extension.get()),
                  17,
                  default_icon,
                  this);

  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);

  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  ASSERT_EQ(1u, image.image_skia().image_reps().size());

  representation = image.image_skia().GetRepresentation(1.0f);

  // We should have loaded the smallest bigger (resized) resource.
  EXPECT_EQ(1.0f, representation.scale());
  EXPECT_EQ(17, representation.pixel_width());
  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(),
                                   EnsureBitmapSize(bitmap_24, 17)));
}

// If resource set is empty, |GetRepresentation| should synchronously return
// default icon, without notifying observer of image change.
TEST_F(ExtensionIconImageTest, NoResources) {
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  ExtensionIconSet empty_icon_set;
  gfx::ImageSkia default_icon = GetDefaultIcon();

  const int kRequestedSize = 24;
  IconImage image(browser_context(),
                  extension.get(),
                  empty_icon_set,
                  kRequestedSize,
                  default_icon,
                  this);

  // Default icon is loaded asynchronously.
  image.image_skia().GetRepresentation(1.0f);
  base::RunLoop().RunUntilIdle();
  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);

  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
                       kRequestedSize)));

  EXPECT_EQ(1, ImageLoadedCount());
  // We should have a default icon representation.
  ASSERT_EQ(1u, image.image_skia().image_reps().size());

  representation = image.image_skia().GetRepresentation(1.0f);
  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
                       kRequestedSize)));
}

// If resource set is invalid, image load should be done asynchronously and
// the observer should be notified when it's done. |GetRepresentation| should
// return the default icon representation once image load is done.
TEST_F(ExtensionIconImageTest, InvalidResource) {
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  const int kInvalidIconSize = 24;
  ExtensionIconSet invalid_icon_set;
  invalid_icon_set.Add(kInvalidIconSize, "invalid.png");

  gfx::ImageSkia default_icon = GetDefaultIcon();

  IconImage image(browser_context(),
                  extension.get(),
                  invalid_icon_set,
                  kInvalidIconSize,
                  default_icon,
                  this);

  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      CreateBlankBitmapForScale(kInvalidIconSize, ui::SCALE_FACTOR_100P)));

  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  // We should have default icon representation now.
  ASSERT_EQ(1u, image.image_skia().image_reps().size());

  representation = image.image_skia().GetRepresentation(1.0f);
  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
                       kInvalidIconSize)));
}

// Test that IconImage works with lazily (but synchronously) created default
// icon when IconImage returns synchronously.
TEST_F(ExtensionIconImageTest, LazyDefaultIcon) {
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  gfx::ImageSkia default_icon = GetDefaultIcon();
  gfx::ImageSkia lazy_default_icon(
      std::make_unique<MockImageSkiaSource>(default_icon), default_icon.size());

  ExtensionIconSet empty_icon_set;

  const int kRequestedSize = 128;
  IconImage image(browser_context(),
                  extension.get(),
                  empty_icon_set,
                  kRequestedSize,
                  lazy_default_icon,
                  this);

  ASSERT_FALSE(lazy_default_icon.HasRepresentation(1.0f));

  // Default icon is loaded asynchronously.
  image.image_skia().GetRepresentation(1.0f);
  base::RunLoop().RunUntilIdle();
  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);

  // The resouce set is empty, so we should get the result right away.
  EXPECT_TRUE(lazy_default_icon.HasRepresentation(1.0f));
  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
                       kRequestedSize)));

  // We should have a default icon representation.
  ASSERT_EQ(1u, image.image_skia().image_reps().size());
}

// Test that IconImage works with lazily (but synchronously) created default
// icon when IconImage returns asynchronously.
TEST_F(ExtensionIconImageTest, LazyDefaultIcon_AsyncIconImage) {
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  gfx::ImageSkia default_icon = GetDefaultIcon();
  gfx::ImageSkia lazy_default_icon(
      std::make_unique<MockImageSkiaSource>(default_icon), default_icon.size());

  const int kInvalidIconSize = 24;
  ExtensionIconSet invalid_icon_set;
  invalid_icon_set.Add(kInvalidIconSize, "invalid.png");

  IconImage image(browser_context(),
                  extension.get(),
                  invalid_icon_set,
                  kInvalidIconSize,
                  lazy_default_icon,
                  this);

  ASSERT_FALSE(lazy_default_icon.HasRepresentation(1.0f));

  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);

  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  // We should have default icon representation now.
  ASSERT_EQ(1u, image.image_skia().image_reps().size());

  EXPECT_TRUE(lazy_default_icon.HasRepresentation(1.0f));

  representation = image.image_skia().GetRepresentation(1.0f);
  EXPECT_TRUE(gfx::BitmapsAreEqual(
      representation.GetBitmap(),
      EnsureBitmapSize(default_icon.GetRepresentation(1.0f).GetBitmap(),
                       kInvalidIconSize)));
}

// Tests behavior of image created by IconImage after IconImage host goes
// away. The image should still return loaded representations. If requested
// representation was not loaded while IconImage host was around, transparent
// representations should be returned.
TEST_F(ExtensionIconImageTest, IconImageDestruction) {
  scoped_refptr<Extension> extension(CreateExtension(
      "extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);

  gfx::ImageSkia default_icon = GetDefaultIcon();

  // Load images we expect to find as representations in icon_image, so we
  // can later use them to validate icon_image.
  SkBitmap bitmap_16 =
      TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "16.png", 16);
  ASSERT_FALSE(bitmap_16.empty());

  std::unique_ptr<IconImage> image(new IconImage(
      browser_context(), extension.get(), IconsInfo::GetIcons(extension.get()),
      16, default_icon, this));

  // Load an image representation.
  gfx::ImageSkiaRep representation =
      image->image_skia().GetRepresentation(1.0f);

  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  ASSERT_EQ(1u, image->image_skia().image_reps().size());

  // Stash loaded image skia, and destroy |image|.
  gfx::ImageSkia image_skia = image->image_skia();
  image.reset();
  extension = NULL;

  // Image skia should still be able to get previously loaded representation.
  representation = image_skia.GetRepresentation(1.0f);

  EXPECT_EQ(1.0f, representation.scale());
  EXPECT_EQ(16, representation.pixel_width());
  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.GetBitmap(), bitmap_16));

  // When requesting another representation, we should not crash and return some
  // image of the size. It could be blank or a rescale from the existing 1.0f
  // icon.
  representation = image_skia.GetRepresentation(2.0f);

  EXPECT_EQ(16, representation.GetWidth());
  EXPECT_EQ(16, representation.GetHeight());
  EXPECT_EQ(2.0f, representation.scale());
}

// Test that new representations added to the image of an IconImageSkia are
// cached for future use.
TEST_F(ExtensionIconImageTest, ImageCachesNewRepresentations) {
  // Load up an extension and create an icon image.
  scoped_refptr<Extension> extension(
      CreateExtension("extension_icon_image", Manifest::INVALID_LOCATION));
  ASSERT_TRUE(extension.get() != NULL);
  gfx::ImageSkia default_icon = GetDefaultIcon();
  std::unique_ptr<IconImage> icon_image(new IconImage(
      browser_context(), extension.get(), IconsInfo::GetIcons(extension.get()),
      16, default_icon, this));

  // Load an blank image representation.
  EXPECT_EQ(0, ImageLoadedCount());
  icon_image->image_skia().GetRepresentation(1.0f);
  EXPECT_EQ(0, ImageLoadedCount());
  WaitForImageLoad();
  EXPECT_EQ(1, ImageLoadedCount());
  icon_image->image_skia().GetRepresentation(1.0f);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0, ImageLoadedCount());
  icon_image->image_skia().GetRepresentation(1.0f);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0, ImageLoadedCount());
}

}  // namespace extensions
