// 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 <tuple>

#include "base/containers/lru_cache.h"
#include "base/functional/bind.h"
#include "components/favicon/core/favicon_service.h"
#include "components/omnibox/browser/autocomplete_result.h"

namespace {

size_t GetFaviconCacheSize() {
  // Set cache size to twice the number of maximum results in either the
  // on-focus or prefix-suggest mode to avoid favicon refetches as the user
  // types. Favicon fetches are uncached and can hit disk.
  return 2 * std::max(AutocompleteResult::GetMaxMatches(),
                      AutocompleteResult::GetMaxMatches(true));
}

}  // namespace

bool FaviconCache::Request::operator<(const Request& rhs) const {
  // Compare |type| first, and if equal, compare |url|.
  return std::tie(type, url) < std::tie(rhs.type, rhs.url);
}

FaviconCache::FaviconCache(favicon::FaviconService* favicon_service,
                           history::HistoryService* history_service)
    : favicon_service_(favicon_service),
      lru_cache_(GetFaviconCacheSize()),
      responses_without_favicons_(GetFaviconCacheSize()) {
  if (history_service) {
    history_observation_.Observe(history_service);

    favicons_changed_subscription_ =
        history_service->AddFaviconsChangedCallback(base::BindRepeating(
            &FaviconCache::OnFaviconsChanged, weak_factory_.GetWeakPtr()));
  }
}

FaviconCache::~FaviconCache() {}

gfx::Image FaviconCache::GetFaviconForPageUrl(
    const GURL& page_url,
    FaviconFetchedCallback on_favicon_fetched) {
  return GetFaviconInternal({RequestType::BY_PAGE_URL, page_url},
                            std::move(on_favicon_fetched));
}

gfx::Image FaviconCache::GetLargestFaviconForPageUrl(
    const GURL& page_url,
    FaviconFetchedCallback on_favicon_fetched) {
  return GetFaviconInternal({RequestType::RAW_BY_PAGE_URL, page_url},
                            std::move(on_favicon_fetched));
}

gfx::Image FaviconCache::GetFaviconForIconUrl(
    const GURL& icon_url,
    FaviconFetchedCallback on_favicon_fetched) {
  return GetFaviconInternal({RequestType::BY_ICON_URL, icon_url},
                            std::move(on_favicon_fetched));
}

gfx::Image FaviconCache::GetFaviconInternal(
    const Request& request,
    FaviconFetchedCallback on_favicon_fetched) {
  if (!favicon_service_)
    return gfx::Image();

  if (request.url.is_empty() || !request.url.is_valid())
    return gfx::Image();

  // Early exit if we have a cached favicon ready.
  auto cache_iterator = lru_cache_.Get(request);
  if (cache_iterator != lru_cache_.end())
    return cache_iterator->second;

  // Early exit if we've already established that we don't have the favicon.
  if (responses_without_favicons_.Peek(request) !=
      responses_without_favicons_.end()) {
    return gfx::Image();
  }

  // We have an outstanding request for this page. Add one more waiting callback
  // and return an empty gfx::Image.
  auto it = pending_requests_.find(request);
  if (it != pending_requests_.end()) {
    it->second.push_back(std::move(on_favicon_fetched));
    return gfx::Image();
  }

  if (request.type == RequestType::BY_PAGE_URL) {
    favicon_service_->GetFaviconImageForPageURL(
        request.url,
        base::BindRepeating(&FaviconCache::OnFaviconFetched,
                            weak_factory_.GetWeakPtr(), request),
        &task_tracker_);
  } else if (request.type == RequestType::RAW_BY_PAGE_URL) {
    favicon_service_->GetRawFaviconForPageURL(
        request.url, {favicon_base::IconType::kFavicon},
        /*icon_size_in_pixels=*/0, /*fallback_to_host=*/false,
        base::BindRepeating(&FaviconCache::OnFaviconRawBitmapFetched,
                            weak_factory_.GetWeakPtr(), request),
        &task_tracker_);
  } else if (request.type == RequestType::BY_ICON_URL) {
    favicon_service_->GetFaviconImage(
        request.url,
        base::BindRepeating(&FaviconCache::OnFaviconFetched,
                            weak_factory_.GetWeakPtr(), request),
        &task_tracker_);
  } else {
    NOTREACHED();
  }

  pending_requests_[request].push_back(std::move(on_favicon_fetched));

  return gfx::Image();
}

void FaviconCache::OnFaviconFetched(
    const Request& request,
    const favicon_base::FaviconImageResult& result) {
  if (result.image.IsEmpty()) {
    responses_without_favicons_.Put(request, true);
    pending_requests_.erase(request);
    return;
  }

  InvokeRequestCallbackWithFavicon(request, result.image);
}

void FaviconCache::OnFaviconRawBitmapFetched(
    const Request& request,
    const favicon_base::FaviconRawBitmapResult& bitmap_result) {
  if (!bitmap_result.is_valid()) {
    responses_without_favicons_.Put(request, true);
    pending_requests_.erase(request);
    return;
  }

  InvokeRequestCallbackWithFavicon(
      request, gfx::Image::CreateFrom1xPNGBytes(bitmap_result.bitmap_data));
}

void FaviconCache::InvokeRequestCallbackWithFavicon(const Request& request,
                                                    const gfx::Image& image) {
  DCHECK(!image.IsEmpty());
  lru_cache_.Put(request, image);

  auto it = pending_requests_.find(request);
  DCHECK(it != pending_requests_.end());
  for (auto& callback : it->second) {
    std::move(callback).Run(image);
  }
  pending_requests_.erase(it);
}

void FaviconCache::OnURLVisited(history::HistoryService* history_service,
                                const history::URLRow& url_row,
                                const history::VisitRow& new_visit) {
  auto it = responses_without_favicons_.Peek(
      {RequestType::BY_PAGE_URL, url_row.url()});
  if (it != responses_without_favicons_.end())
    responses_without_favicons_.Erase(it);
}

void FaviconCache::InvalidateCachedRequests(const Request& request) {
  {
    auto it = lru_cache_.Peek(request);
    if (it != lru_cache_.end())
      lru_cache_.Erase(it);
  }

  {
    auto it = responses_without_favicons_.Peek(request);
    if (it != responses_without_favicons_.end())
      responses_without_favicons_.Erase(it);
  }
}

void FaviconCache::OnURLsDeleted(history::HistoryService* history_service,
                                 const history::DeletionInfo& deletion_info) {
  // We only care about actual user (or sync) deletions.
  if (deletion_info.is_from_expiration())
    return;

  if (deletion_info.IsAllHistory()) {
    lru_cache_.Clear();
    responses_without_favicons_.Clear();
    return;
  }

  for (const history::URLRow& row : deletion_info.deleted_rows()) {
    InvalidateCachedRequests({RequestType::BY_PAGE_URL, row.url()});
  }
}

void FaviconCache::OnFaviconsChanged(const std::set<GURL>& page_urls,
                                     const GURL& icon_url) {
  for (GURL page_url : page_urls) {
    InvalidateCachedRequests({RequestType::BY_PAGE_URL, page_url});
  }

  InvalidateCachedRequests({RequestType::BY_ICON_URL, icon_url});
}
