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

#include "chrome/browser/ui/thumbnails/thumbnail_image.h"

#include <memory>
#include <utility>

#include "base/functional/callback_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image_skia.h"

namespace {

constexpr int kTestBitmapWidth = 200;
constexpr int kTestBitmapHeight = 123;

class CallbackWaiter {
 public:
  CallbackWaiter() {
    callback_ = base::BindRepeating(&CallbackWaiter::HandleCallback,
                                    weak_ptr_factory_.GetWeakPtr());
  }

  base::RepeatingClosure callback() { return callback_; }

  bool called() const { return called_; }

  void Reset() { called_ = false; }

  void Wait() {
    if (called_)
      return;

    base::RunLoop run_loop;
    quit_closure_ = run_loop.QuitClosure();
    run_loop.Run();
  }

 private:
  void HandleCallback() {
    if (quit_closure_)
      std::move(quit_closure_).Run();
    called_ = true;
  }

  base::RepeatingClosure callback_;
  base::OnceClosure quit_closure_;
  bool called_ = false;

  base::WeakPtrFactory<CallbackWaiter> weak_ptr_factory_{this};
};

class StubDelegate : public ThumbnailImage::Delegate {
 public:
  StubDelegate() = default;
  ~StubDelegate() override = default;

  // ThumbnailImage::Delegate:
  void ThumbnailImageBeingObservedChanged(bool is_being_observed) override {}
};

}  // anonymous namespace

class ThumbnailImageTest : public testing::Test,
                           public ThumbnailImage::Delegate {
 public:
  ThumbnailImageTest() = default;

  ThumbnailImageTest(const ThumbnailImageTest&) = delete;
  ThumbnailImageTest& operator=(const ThumbnailImageTest&) = delete;

 protected:
  static SkBitmap CreateBitmap(int width, int height) {
    SkBitmap bitmap;
    bitmap.allocN32Pixels(width, height);
    bitmap.eraseARGB(255, 0, 255, 0);
    return bitmap;
  }

  std::vector<uint8_t> Compress(SkBitmap bitmap) const {
    return ThumbnailImage::CompressBitmap(bitmap, absl::nullopt);
  }

  bool is_being_observed() const { return is_being_observed_; }

 private:
  void ThumbnailImageBeingObservedChanged(bool is_being_observed) override {
    is_being_observed_ = is_being_observed;
  }

  bool is_being_observed_ = false;
  base::test::TaskEnvironment task_environment_;
};

using Subscription = ThumbnailImage::Subscription;

TEST_F(ThumbnailImageTest, AddRemoveSubscriber) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);
  EXPECT_FALSE(is_being_observed());

  std::unique_ptr<Subscription> subscription = image->Subscribe();
  EXPECT_TRUE(is_being_observed());

  subscription.reset();
  EXPECT_FALSE(is_being_observed());
}

TEST_F(ThumbnailImageTest, AddRemoveMultipleObservers) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);
  EXPECT_FALSE(is_being_observed());

  std::unique_ptr<Subscription> subscription1 = image->Subscribe();
  EXPECT_TRUE(is_being_observed());

  std::unique_ptr<Subscription> subscription2 = image->Subscribe();
  EXPECT_TRUE(is_being_observed());

  subscription1.reset();
  EXPECT_TRUE(is_being_observed());

  subscription2.reset();
  EXPECT_FALSE(is_being_observed());
}

TEST_F(ThumbnailImageTest, AssignSkBitmapNotifiesObservers) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription1 = image->Subscribe();
  std::unique_ptr<Subscription> subscription2 = image->Subscribe();

  CallbackWaiter waiter1;
  subscription1->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(waiter1.callback()));

  CallbackWaiter waiter2;
  subscription2->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(waiter2.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);

  waiter1.Wait();
  waiter2.Wait();
  EXPECT_TRUE(waiter1.called());
  EXPECT_TRUE(waiter2.called());
}

TEST_F(ThumbnailImageTest, AssignSkBitmap_NotifiesObserversAgain) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription1 = image->Subscribe();
  std::unique_ptr<Subscription> subscription2 = image->Subscribe();

  CallbackWaiter waiter1;
  subscription1->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(waiter1.callback()));

  CallbackWaiter waiter2;
  subscription2->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(waiter2.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);

  waiter1.Wait();
  waiter2.Wait();
  EXPECT_TRUE(waiter1.called());
  EXPECT_TRUE(waiter2.called());

  waiter1.Reset();
  waiter2.Reset();

  image->AssignSkBitmap(bitmap, absl::nullopt);

  waiter1.Wait();
  waiter2.Wait();
  EXPECT_TRUE(waiter1.called());
  EXPECT_TRUE(waiter2.called());
}

TEST_F(ThumbnailImageTest, AssignSkBitmap_NotifiesCompressedObservers) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription1 = image->Subscribe();
  std::unique_ptr<Subscription> subscription2 = image->Subscribe();

  CallbackWaiter waiter1;
  subscription1->SetCompressedImageCallback(
      base::IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(
          waiter1.callback()));

  CallbackWaiter waiter2;
  subscription2->SetCompressedImageCallback(
      base::IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(
          waiter2.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);

  waiter1.Wait();
  waiter2.Wait();
  EXPECT_TRUE(waiter1.called());
  EXPECT_TRUE(waiter2.called());
}

TEST_F(ThumbnailImageTest, AssignSkBitmap_NotifiesCompressedObserversAgain) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription1 = image->Subscribe();
  std::unique_ptr<Subscription> subscription2 = image->Subscribe();

  CallbackWaiter waiter1;
  subscription1->SetCompressedImageCallback(
      base::IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(
          waiter1.callback()));

  CallbackWaiter waiter2;
  subscription2->SetCompressedImageCallback(
      base::IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(
          waiter2.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);

  waiter1.Wait();
  waiter2.Wait();
  EXPECT_TRUE(waiter1.called());
  EXPECT_TRUE(waiter2.called());

  waiter1.Reset();
  waiter2.Reset();

  image->AssignSkBitmap(bitmap, absl::nullopt);

  waiter1.Wait();
  waiter2.Wait();
  EXPECT_TRUE(waiter1.called());
  EXPECT_TRUE(waiter2.called());
}

TEST_F(ThumbnailImageTest, RequestThumbnailImage) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription1 = image->Subscribe();

  CallbackWaiter waiter1;
  subscription1->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(waiter1.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);
  waiter1.Wait();
  EXPECT_TRUE(waiter1.called());
  waiter1.Reset();

  std::unique_ptr<Subscription> subscription2 = image->Subscribe();

  CallbackWaiter waiter2;
  subscription2->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(waiter2.callback()));

  image->RequestThumbnailImage();
  waiter1.Wait();
  waiter2.Wait();
  EXPECT_TRUE(waiter1.called());
  EXPECT_TRUE(waiter2.called());
}

TEST_F(ThumbnailImageTest, RequestCompressedThumbnailData) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription = image->Subscribe();

  CallbackWaiter waiter;
  subscription->SetCompressedImageCallback(
      base::IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(
          waiter.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);
  waiter.Wait();
  EXPECT_TRUE(waiter.called());
  waiter.Reset();

  image->RequestCompressedThumbnailData();
  waiter.Wait();
  EXPECT_TRUE(waiter.called());
}

TEST_F(ThumbnailImageTest, ClearThumbnailAfterAssignBitmap) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription = image->Subscribe();

  CallbackWaiter uncompressed_image_waiter;
  subscription->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(uncompressed_image_waiter.callback()));

  CallbackWaiter compressed_image_waiter;
  subscription->SetCompressedImageCallback(
      base::IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(
          compressed_image_waiter.callback()));

  CallbackWaiter async_operation_finished_waiter;
  image->set_async_operation_finished_callback_for_testing(
      async_operation_finished_waiter.callback());

  // No observers should be notified if the thumbnail is cleared just
  // after assigning a bitmap.
  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);
  image->ClearData();
  async_operation_finished_waiter.Wait();
  EXPECT_TRUE(async_operation_finished_waiter.called());
  EXPECT_FALSE(uncompressed_image_waiter.called());
  EXPECT_FALSE(compressed_image_waiter.called());
}

TEST_F(ThumbnailImageTest, ClearExistingThumbnailNotifiesObservers) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription = image->Subscribe();

  CallbackWaiter uncompressed_image_waiter;
  subscription->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(uncompressed_image_waiter.callback()));

  CallbackWaiter compressed_image_waiter;
  subscription->SetCompressedImageCallback(
      base::IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(
          compressed_image_waiter.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);
  compressed_image_waiter.Wait();
  uncompressed_image_waiter.Wait();
  EXPECT_TRUE(compressed_image_waiter.called());
  EXPECT_TRUE(uncompressed_image_waiter.called());
  compressed_image_waiter.Reset();
  uncompressed_image_waiter.Reset();

  image->ClearData();
  compressed_image_waiter.Wait();
  uncompressed_image_waiter.Wait();
  EXPECT_TRUE(compressed_image_waiter.called());
  EXPECT_TRUE(uncompressed_image_waiter.called());
}

// Makes sure a null dereference does not happen. Regression test for
// crbug.com/1159701.
TEST_F(ThumbnailImageTest, UnsubscribeAfterDelegateDestroyed) {
  auto delegate = std::make_unique<StubDelegate>();
  auto image = base::MakeRefCounted<ThumbnailImage>(delegate.get());

  std::unique_ptr<Subscription> subscription = image->Subscribe();

  // Normally |image| will notify its delegate when the last
  // subscription is destroyed. When there is no delegate it shouldn't
  // do anything.
  delegate.reset();
  subscription.reset();
}

// Ensures subscribers with a size hint get notified correctly on
// thumbnail clear. Regression test for crbug.com/1168483 where
// CropPreviewImage was called on blank thumbnails resulting in a
// DCHECK.
TEST_F(ThumbnailImageTest, DoesNotCropBlankThumbnails) {
  auto image = base::MakeRefCounted<ThumbnailImage>(this);

  std::unique_ptr<Subscription> subscription = image->Subscribe();
  subscription->SetSizeHint(
      gfx::Size(kTestBitmapWidth / 2, kTestBitmapHeight / 2));

  CallbackWaiter uncompressed_image_waiter;
  subscription->SetUncompressedImageCallback(
      base::IgnoreArgs<gfx::ImageSkia>(uncompressed_image_waiter.callback()));

  SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
  image->AssignSkBitmap(bitmap, absl::nullopt);
  uncompressed_image_waiter.Wait();
  EXPECT_TRUE(uncompressed_image_waiter.called());
  uncompressed_image_waiter.Reset();

  image->ClearData();
  uncompressed_image_waiter.Wait();
  EXPECT_TRUE(uncompressed_image_waiter.called());
}
