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

#include "components/omnibox/browser/favicon_cache.h"

#include "base/functional/bind.h"
#include "components/favicon/core/test/mock_favicon_service.h"
#include "components/history/core/browser/history_types.h"
#include "components/variations/scoped_variations_ids_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/favicon_size.h"

using testing::_;
using testing::DoAll;
using testing::Return;

namespace {

favicon_base::FaviconImageResult GetDummyFaviconResult() {
  favicon_base::FaviconImageResult result;

  result.icon_url = GURL("http://example.com/favicon.ico");

  SkBitmap bitmap;
  bitmap.allocN32Pixels(gfx::kFaviconSize, gfx::kFaviconSize);
  bitmap.eraseColor(SK_ColorBLUE);
  result.image = gfx::Image::CreateFrom1xBitmap(bitmap);

  return result;
}

favicon_base::FaviconRawBitmapResult GetDummyRawFaviconResult() {
  favicon_base::FaviconRawBitmapResult result;

  result.bitmap_data = GetDummyFaviconResult().image.As1xPNGBytes();

  return result;
}

void VerifyFetchedFaviconAndCount(int* count, const gfx::Image& favicon) {
  DCHECK(count);
  EXPECT_FALSE(favicon.IsEmpty());
  ++(*count);
}

void VerifyFetchedFavicon(const gfx::Image& favicon) {
  EXPECT_FALSE(favicon.IsEmpty());
}

void Fail(const gfx::Image& favicon) {
  FAIL() << "This asynchronous callback should never have been called.";
}

}  // namespace

class FaviconCacheTest : public testing::Test {
 protected:
  const GURL kUrlA = GURL("http://www.a.com/");
  const GURL kUrlB = GURL("http://www.b.com/");
  const GURL kIconUrl = GURL("http://a.com/favicon.ico");

  FaviconCacheTest()
      : cache_(&favicon_service_, nullptr /* history_service */) {}

  testing::NiceMock<favicon::MockFaviconService> favicon_service_;

  void ExpectFaviconServiceForPageUrlCalls(int a_site_calls, int b_site_calls) {
    if (a_site_calls > 0) {
      EXPECT_CALL(
          favicon_service_,
          GetFaviconImageForPageURL(kUrlA, _ /* callback */, _ /* tracker */))
          .Times(a_site_calls)
          .WillRepeatedly(
              [&](auto, favicon_base::FaviconImageCallback callback, auto) {
                favicon_service_a_site_response_ = std::move(callback);
                return base::CancelableTaskTracker::kBadTaskId;
              });
    }

    if (b_site_calls > 0) {
      EXPECT_CALL(
          favicon_service_,
          GetFaviconImageForPageURL(kUrlB, _ /* callback */, _ /* tracker */))
          .Times(b_site_calls)
          .WillRepeatedly(
              [&](auto, favicon_base::FaviconImageCallback callback, auto) {
                favicon_service_b_site_response_ = std::move(callback);
                return base::CancelableTaskTracker::kBadTaskId;
              });
    }
  }

  void ExpectFaviconServiceForLargestFaviconPageUrlCalls(int a_site_calls,
                                                         int b_site_calls) {
    if (a_site_calls > 0) {
      EXPECT_CALL(favicon_service_,
                  GetRawFaviconForPageURL(kUrlA, _ /*icon_types */,
                                          0 /* desired_size_in_pixel */,
                                          false /* fallback_to_host */,
                                          _ /* callback */, _ /* tracker */))
          .Times(a_site_calls)
          .WillRepeatedly([&](auto, auto, auto, auto,
                              favicon_base::FaviconRawBitmapCallback callback,
                              auto) {
            favicon_service_a_site_raw_favicon_response_ = std::move(callback);
            return base::CancelableTaskTracker::kBadTaskId;
          });
    }

    if (b_site_calls > 0) {
      EXPECT_CALL(favicon_service_,
                  GetRawFaviconForPageURL(kUrlB, _ /*icon_types */,
                                          0 /* desired_size_in_pixel */,
                                          false /* fallback_to_host */,
                                          _ /* callback */, _ /* tracker */))
          .Times(b_site_calls)
          .WillRepeatedly([&](auto, auto, auto, auto,
                              favicon_base::FaviconRawBitmapCallback callback,
                              auto) {
            favicon_service_b_site_raw_favicon_response_ = std::move(callback);
            return base::CancelableTaskTracker::kBadTaskId;
          });
    }
  }

  void ExpectFaviconServiceForIconUrlCalls(int calls) {
    EXPECT_CALL(favicon_service_,
                GetFaviconImage(kIconUrl, _ /* callback */, _ /* tracker */))
        .Times(calls);
  }

  variations::test::ScopedVariationsIdsProvider scoped_variations_ids_provider_{
      variations::VariationsIdsProvider::Mode::kUseSignedInState};
  favicon_base::FaviconImageCallback favicon_service_a_site_response_;
  favicon_base::FaviconImageCallback favicon_service_b_site_response_;
  favicon_base::FaviconRawBitmapCallback
      favicon_service_a_site_raw_favicon_response_;
  favicon_base::FaviconRawBitmapCallback
      favicon_service_b_site_raw_favicon_response_;

  FaviconCache cache_;
};

TEST_F(FaviconCacheTest, Basic) {
  ExpectFaviconServiceForPageUrlCalls(1, 0);
  ExpectFaviconServiceForIconUrlCalls(0);

  int response_count = 0;
  gfx::Image result = cache_.GetFaviconForPageUrl(
      kUrlA, base::BindOnce(&VerifyFetchedFaviconAndCount, &response_count));

  // Expect the synchronous result to be empty.
  EXPECT_TRUE(result.IsEmpty());

  std::move(favicon_service_a_site_response_).Run(GetDummyFaviconResult());

  // Re-request the same favicon and expect a non-empty result now that the
  // cache is populated. The above EXPECT_CALL will also verify that the
  // backing FaviconService is not hit again.
  result = cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail));

  EXPECT_FALSE(result.IsEmpty());
  EXPECT_EQ(1, response_count);
}

TEST_F(FaviconCacheTest, Largest) {
  ExpectFaviconServiceForLargestFaviconPageUrlCalls(1, 0);
  ExpectFaviconServiceForIconUrlCalls(0);

  int response_count = 0;
  gfx::Image result = cache_.GetLargestFaviconForPageUrl(
      kUrlA, base::BindOnce(&VerifyFetchedFaviconAndCount, &response_count));

  // Expect the synchronous result to be empty.
  EXPECT_TRUE(result.IsEmpty());

  std::move(favicon_service_a_site_raw_favicon_response_)
      .Run(GetDummyRawFaviconResult());

  // Re-request the same favicon and expect a non-empty result now that the
  // cache is populated. The above EXPECT_CALL will also verify that the
  // backing FaviconService is not hit again.
  result = cache_.GetLargestFaviconForPageUrl(kUrlA, base::BindOnce(&Fail));

  EXPECT_FALSE(result.IsEmpty());
  EXPECT_EQ(1, response_count);
}

TEST_F(FaviconCacheTest, GetFaviconForIconUrl) {
  // Verify that the service receives a request by the icon URL.
  ExpectFaviconServiceForPageUrlCalls(0, 0);
  ExpectFaviconServiceForIconUrlCalls(1);

  // Since the other tests are comprehensive, we don't simulate or verify the
  // actual result.
  gfx::Image result =
      cache_.GetFaviconForIconUrl(kIconUrl, base::BindOnce(&Fail));
  EXPECT_TRUE(result.IsEmpty());
}

TEST_F(FaviconCacheTest, MultipleRequestsAreCoalesced) {
  ExpectFaviconServiceForPageUrlCalls(1, 0);

  int response_count = 0;
  for (int i = 0; i < 10; ++i) {
    cache_.GetFaviconForPageUrl(
        kUrlA, base::BindOnce(&VerifyFetchedFaviconAndCount, &response_count));
  }

  std::move(favicon_service_a_site_response_).Run(GetDummyFaviconResult());

  EXPECT_EQ(10, response_count);
}

TEST_F(FaviconCacheTest, SeparateOriginsAreCachedSeparately) {
  ExpectFaviconServiceForPageUrlCalls(1, 1);

  int a_site_response_count = 0;
  int b_site_response_count = 0;

  gfx::Image a_site_return = cache_.GetFaviconForPageUrl(
      kUrlA,
      base::BindOnce(&VerifyFetchedFaviconAndCount, &a_site_response_count));
  gfx::Image b_site_return = cache_.GetFaviconForPageUrl(
      kUrlB,
      base::BindOnce(&VerifyFetchedFaviconAndCount, &b_site_response_count));

  EXPECT_TRUE(a_site_return.IsEmpty());
  EXPECT_TRUE(b_site_return.IsEmpty());
  EXPECT_EQ(0, a_site_response_count);
  EXPECT_EQ(0, b_site_response_count);

  std::move(favicon_service_b_site_response_).Run(GetDummyFaviconResult());

  EXPECT_EQ(0, a_site_response_count);
  EXPECT_EQ(1, b_site_response_count);

  a_site_return = cache_.GetFaviconForPageUrl(
      kUrlA,
      base::BindOnce(&VerifyFetchedFaviconAndCount, &a_site_response_count));
  b_site_return = cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&Fail));

  EXPECT_TRUE(a_site_return.IsEmpty());
  EXPECT_FALSE(b_site_return.IsEmpty());
  EXPECT_EQ(0, a_site_response_count);
  EXPECT_EQ(1, b_site_response_count);

  std::move(favicon_service_a_site_response_).Run(GetDummyFaviconResult());

  EXPECT_EQ(2, a_site_response_count);
  EXPECT_EQ(1, b_site_response_count);

  a_site_return = cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail));
  b_site_return = cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&Fail));

  EXPECT_FALSE(a_site_return.IsEmpty());
  EXPECT_FALSE(b_site_return.IsEmpty());
}

TEST_F(FaviconCacheTest, ClearIconsWithHistoryDeletions) {
  ExpectFaviconServiceForPageUrlCalls(3, 2);

  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&VerifyFetchedFavicon))
          .IsEmpty());
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&VerifyFetchedFavicon))
          .IsEmpty());

  std::move(favicon_service_a_site_response_).Run(GetDummyFaviconResult());
  std::move(favicon_service_b_site_response_).Run(GetDummyFaviconResult());

  EXPECT_FALSE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
  EXPECT_FALSE(
      cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&Fail)).IsEmpty());

  // Delete just the entry for kUrlA.
  history::URLRows a_rows = {history::URLRow(kUrlA)};
  cache_.OnHistoryDeletions(
      nullptr /* history_service */,
      history::DeletionInfo::ForUrls(a_rows, {} /* favicon_urls */));

  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&VerifyFetchedFavicon))
          .IsEmpty());
  EXPECT_FALSE(
      cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&Fail)).IsEmpty());

  // Restore the cache entry for kUrlA.
  std::move(favicon_service_a_site_response_).Run(GetDummyFaviconResult());

  // Delete all history.
  cache_.OnHistoryDeletions(nullptr /* history_service */,
                            history::DeletionInfo::ForAllHistory());

  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&VerifyFetchedFavicon))
          .IsEmpty());
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&VerifyFetchedFavicon))
          .IsEmpty());
}

TEST_F(FaviconCacheTest, CacheNullFavicons) {
  ExpectFaviconServiceForPageUrlCalls(1, 0);

  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
  std::move(favicon_service_a_site_response_)
      .Run(favicon_base::FaviconImageResult());

  // The mock FaviconService's EXPECT_CALL verifies that we do not make another
  // call to FaviconService.
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
}

TEST_F(FaviconCacheTest, ExpireNullFaviconsByHistory) {
  ExpectFaviconServiceForPageUrlCalls(2, 0);

  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
  std::move(favicon_service_a_site_response_)
      .Run(favicon_base::FaviconImageResult());

  cache_.OnURLVisited(
      nullptr /* history_service */,
      history::VisitedURLInfo(history::URLRow(kUrlA), history::VisitRow(),
                              history::VisitResponseCodeCategory::kNot404));

  // Now the empty favicon should have been expired and we expect our second
  // call to the mock underlying FaviconService.
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&VerifyFetchedFavicon))
          .IsEmpty());
  std::move(favicon_service_a_site_response_).Run(GetDummyFaviconResult());
  EXPECT_FALSE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
}

TEST_F(FaviconCacheTest, ObserveFaviconsChanged) {
  ExpectFaviconServiceForPageUrlCalls(2, 1);

  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&Fail)).IsEmpty());

  // Simulate responses to both requests.
  std::move(favicon_service_a_site_response_)
      .Run(favicon_base::FaviconImageResult());
  std::move(favicon_service_b_site_response_)
      .Run(favicon_base::FaviconImageResult());

  cache_.OnFaviconsChanged({kUrlA}, GURL());

  // Request the two favicons again.
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlB, base::BindOnce(&Fail)).IsEmpty());

  // Our call to |ExpectFaviconServiceForPageUrlCalls(expected A calls, expected
  // B calls)| above should verify that we re-request the icon for kUrlA only
  // (because the null result has been invalidated by OnFaviconsChanged).
}

TEST_F(FaviconCacheTest, DoNotExpireNullFaviconsFor404) {
  ExpectFaviconServiceForPageUrlCalls(1, 0);

  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
  std::move(favicon_service_a_site_response_)
      .Run(favicon_base::FaviconImageResult());

  cache_.OnURLVisited(
      nullptr /* history_service */,
      history::VisitedURLInfo(history::URLRow(kUrlA), history::VisitRow(),
                              history::VisitResponseCodeCategory::k404));

  // The empty favicon should not have been expired. We do not expect another
  // call to the mock underlying FaviconService.
  EXPECT_TRUE(
      cache_.GetFaviconForPageUrl(kUrlA, base::BindOnce(&Fail)).IsEmpty());
}
