// Copyright (c) 2012 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 "chrome/browser/favicon/favicon_service.h"

#include <cmath>

#include "base/hash.h"
#include "base/message_loop/message_loop_proxy.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
#include "chrome/common/importer/imported_favicon_usage.h"
#include "chrome/common/url_constants.h"
#include "components/favicon_base/favicon_types.h"
#include "components/favicon_base/favicon_util.h"
#include "components/favicon_base/select_favicon_frames.h"
#include "extensions/common/constants.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image_skia.h"

using base::Bind;

namespace {

void CancelOrRunFaviconResultsCallback(
    const base::CancelableTaskTracker::IsCanceledCallback& is_canceled,
    const favicon_base::FaviconResultsCallback& callback,
    const std::vector<favicon_base::FaviconRawBitmapResult>& results) {
  if (is_canceled.Run())
    return;
  callback.Run(results);
}

// Helper to run callback with empty results if we cannot get the history
// service.
base::CancelableTaskTracker::TaskId RunWithEmptyResultAsync(
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  return tracker->PostTask(
      base::MessageLoopProxy::current().get(),
      FROM_HERE,
      Bind(callback, std::vector<favicon_base::FaviconRawBitmapResult>()));
}

// Return the TaskId to retreive the favicon from chrome specific URL.
base::CancelableTaskTracker::TaskId GetFaviconForChromeURL(
    Profile* profile,
    const GURL& page_url,
    const std::vector<int>& desired_sizes_in_pixel,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  base::CancelableTaskTracker::IsCanceledCallback is_canceled_cb;
  base::CancelableTaskTracker::TaskId id =
      tracker->NewTrackedTaskId(&is_canceled_cb);
  favicon_base::FaviconResultsCallback cancelable_cb =
      Bind(&CancelOrRunFaviconResultsCallback, is_canceled_cb, callback);
  ChromeWebUIControllerFactory::GetInstance()->GetFaviconForURL(
      profile, page_url, desired_sizes_in_pixel, cancelable_cb);
  return id;
}

// Returns a vector of pixel edge sizes from |size_in_dip| and
// favicon_base::GetFaviconScales().
std::vector<int> GetPixelSizesForFaviconScales(int size_in_dip) {
  std::vector<float> scales = favicon_base::GetFaviconScales();
  std::vector<int> sizes_in_pixel;
  for (size_t i = 0; i < scales.size(); ++i) {
    sizes_in_pixel.push_back(std::ceil(size_in_dip * scales[i]));
  }
  return sizes_in_pixel;
}

}  // namespace

FaviconService::FaviconService(Profile* profile, FaviconClient* favicon_client)
    : history_service_(
          HistoryServiceFactory::GetForProfile(profile,
                                               Profile::EXPLICIT_ACCESS)),
      profile_(profile),
      favicon_client_(favicon_client) {
}

// static
void FaviconService::FaviconResultsCallbackRunner(
    const favicon_base::FaviconResultsCallback& callback,
    const std::vector<favicon_base::FaviconRawBitmapResult>* results) {
  callback.Run(*results);
}

base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImage(
    const GURL& icon_url,
    const favicon_base::FaviconImageCallback& callback,
    base::CancelableTaskTracker* tracker) {
  favicon_base::FaviconResultsCallback callback_runner =
      Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
           base::Unretained(this), callback, gfx::kFaviconSize);
  if (history_service_) {
    std::vector<GURL> icon_urls;
    icon_urls.push_back(icon_url);
    return history_service_->GetFavicons(
        icon_urls,
        favicon_base::FAVICON,
        GetPixelSizesForFaviconScales(gfx::kFaviconSize),
        callback_runner,
        tracker);
  }
  return RunWithEmptyResultAsync(callback_runner, tracker);
}

base::CancelableTaskTracker::TaskId FaviconService::GetRawFavicon(
    const GURL& icon_url,
    favicon_base::IconType icon_type,
    int desired_size_in_pixel,
    const favicon_base::FaviconRawBitmapCallback& callback,
    base::CancelableTaskTracker* tracker) {
  favicon_base::FaviconResultsCallback callback_runner =
      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
           base::Unretained(this),
           callback,
           desired_size_in_pixel);

  if (history_service_) {
    std::vector<GURL> icon_urls;
    icon_urls.push_back(icon_url);
    std::vector<int> desired_sizes_in_pixel;
    desired_sizes_in_pixel.push_back(desired_size_in_pixel);

    return history_service_->GetFavicons(
        icon_urls, icon_type, desired_sizes_in_pixel, callback_runner, tracker);
  }
  return RunWithEmptyResultAsync(callback_runner, tracker);
}

base::CancelableTaskTracker::TaskId FaviconService::GetFavicon(
    const GURL& icon_url,
    favicon_base::IconType icon_type,
    int desired_size_in_dip,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  if (history_service_) {
    std::vector<GURL> icon_urls;
    icon_urls.push_back(icon_url);
    return history_service_->GetFavicons(
        icon_urls,
        icon_type,
        GetPixelSizesForFaviconScales(desired_size_in_dip),
        callback,
        tracker);
  }
  return RunWithEmptyResultAsync(callback, tracker);
}

base::CancelableTaskTracker::TaskId FaviconService::GetFaviconImageForPageURL(
    const GURL& page_url,
    const favicon_base::FaviconImageCallback& callback,
    base::CancelableTaskTracker* tracker) {
  return GetFaviconForPageURLImpl(
      page_url,
      favicon_base::FAVICON,
      GetPixelSizesForFaviconScales(gfx::kFaviconSize),
      Bind(&FaviconService::RunFaviconImageCallbackWithBitmapResults,
           base::Unretained(this),
           callback,
           gfx::kFaviconSize),
      tracker);
}

base::CancelableTaskTracker::TaskId FaviconService::GetRawFaviconForPageURL(
    const GURL& page_url,
    int icon_types,
    int desired_size_in_pixel,
    const favicon_base::FaviconRawBitmapCallback& callback,
    base::CancelableTaskTracker* tracker) {
  std::vector<int> desired_sizes_in_pixel;
  desired_sizes_in_pixel.push_back(desired_size_in_pixel);
  return GetFaviconForPageURLImpl(
      page_url,
      icon_types,
      desired_sizes_in_pixel,
      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
           base::Unretained(this),
           callback,
           desired_size_in_pixel),
      tracker);
}

base::CancelableTaskTracker::TaskId
FaviconService::GetLargestRawFaviconForPageURL(
    const GURL& page_url,
    const std::vector<int>& icon_types,
    int minimum_size_in_pixels,
    const favicon_base::FaviconRawBitmapCallback& callback,
    base::CancelableTaskTracker* tracker) {
  favicon_base::FaviconResultsCallback favicon_results_callback =
      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
           base::Unretained(this),
           callback,
           0);
  if (page_url.SchemeIs(content::kChromeUIScheme) ||
      page_url.SchemeIs(extensions::kExtensionScheme)) {
    std::vector<int> desired_sizes_in_pixel;
    desired_sizes_in_pixel.push_back(0);
    return GetFaviconForChromeURL(profile_,
                                  page_url,
                                  desired_sizes_in_pixel,
                                  favicon_results_callback,
                                  tracker);
  }
  if (history_service_) {
    return history_service_->GetLargestFaviconForURL(page_url, icon_types,
        minimum_size_in_pixels, callback, tracker);
  }
  return RunWithEmptyResultAsync(favicon_results_callback, tracker);
}

base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURL(
    const GURL& page_url,
    int icon_types,
    int desired_size_in_dip,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  return GetFaviconForPageURLImpl(
      page_url,
      icon_types,
      GetPixelSizesForFaviconScales(desired_size_in_dip),
      callback,
      tracker);
}

base::CancelableTaskTracker::TaskId
FaviconService::UpdateFaviconMappingsAndFetch(
    const GURL& page_url,
    const std::vector<GURL>& icon_urls,
    int icon_types,
    int desired_size_in_dip,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  if (history_service_) {
    return history_service_->UpdateFaviconMappingsAndFetch(
        page_url,
        icon_urls,
        icon_types,
        GetPixelSizesForFaviconScales(desired_size_in_dip),
        callback,
        tracker);
  }
  return RunWithEmptyResultAsync(callback, tracker);
}

base::CancelableTaskTracker::TaskId FaviconService::GetLargestRawFaviconForID(
    favicon_base::FaviconID favicon_id,
    const favicon_base::FaviconRawBitmapCallback& callback,
    base::CancelableTaskTracker* tracker) {
  // Use 0 as |desired_size| to get the largest bitmap for |favicon_id| without
  // any resizing.
  int desired_size = 0;
  favicon_base::FaviconResultsCallback callback_runner =
      Bind(&FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults,
           base::Unretained(this),
           callback,
           desired_size);

  if (history_service_) {
    return history_service_->GetFaviconForID(
        favicon_id, desired_size, callback_runner, tracker);
  }
  return RunWithEmptyResultAsync(callback_runner, tracker);
}

void FaviconService::SetFaviconOutOfDateForPage(const GURL& page_url) {
  if (history_service_)
    history_service_->SetFaviconsOutOfDateForPage(page_url);
}

void FaviconService::CloneFavicon(const GURL& old_page_url,
                                  const GURL& new_page_url) {
  if (history_service_)
    history_service_->CloneFavicons(old_page_url, new_page_url);
}

void FaviconService::SetImportedFavicons(
    const std::vector<ImportedFaviconUsage>& favicon_usage) {
  if (history_service_)
    history_service_->SetImportedFavicons(favicon_usage);
}

void FaviconService::MergeFavicon(
    const GURL& page_url,
    const GURL& icon_url,
    favicon_base::IconType icon_type,
    scoped_refptr<base::RefCountedMemory> bitmap_data,
    const gfx::Size& pixel_size) {
  if (history_service_) {
    history_service_->MergeFavicon(page_url, icon_url, icon_type, bitmap_data,
                                   pixel_size);
  }
}

void FaviconService::SetFavicons(const GURL& page_url,
                                 const GURL& icon_url,
                                 favicon_base::IconType icon_type,
                                 const gfx::Image& image) {
  if (!history_service_)
    return;

  gfx::ImageSkia image_skia = image.AsImageSkia();
  image_skia.EnsureRepsForSupportedScales();
  const std::vector<gfx::ImageSkiaRep>& image_reps = image_skia.image_reps();
  std::vector<favicon_base::FaviconRawBitmapData> favicon_bitmap_data;
  const std::vector<float> favicon_scales = favicon_base::GetFaviconScales();
  for (size_t i = 0; i < image_reps.size(); ++i) {
    // Don't save if the scale isn't one of supported favicon scale.
    if (std::find(favicon_scales.begin(),
                  favicon_scales.end(),
                  image_reps[i].scale()) == favicon_scales.end()) {
      continue;
    }

    scoped_refptr<base::RefCountedBytes> bitmap_data(
        new base::RefCountedBytes());
    if (gfx::PNGCodec::EncodeBGRASkBitmap(image_reps[i].sk_bitmap(),
                                          false,
                                          &bitmap_data->data())) {
      gfx::Size pixel_size(image_reps[i].pixel_width(),
                           image_reps[i].pixel_height());
      favicon_base::FaviconRawBitmapData bitmap_data_element;
      bitmap_data_element.bitmap_data = bitmap_data;
      bitmap_data_element.pixel_size = pixel_size;
      bitmap_data_element.icon_url = icon_url;

      favicon_bitmap_data.push_back(bitmap_data_element);
    }
  }
  history_service_->SetFavicons(page_url, icon_type, favicon_bitmap_data);
}

void FaviconService::UnableToDownloadFavicon(const GURL& icon_url) {
  MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
  missing_favicon_urls_.insert(url_hash);
}

bool FaviconService::WasUnableToDownloadFavicon(const GURL& icon_url) const {
  MissingFaviconURLHash url_hash = base::Hash(icon_url.spec());
  return missing_favicon_urls_.find(url_hash) != missing_favicon_urls_.end();
}

void FaviconService::ClearUnableToDownloadFavicons() {
  missing_favicon_urls_.clear();
}

FaviconService::~FaviconService() {}

base::CancelableTaskTracker::TaskId FaviconService::GetFaviconForPageURLImpl(
    const GURL& page_url,
    int icon_types,
    const std::vector<int>& desired_sizes_in_pixel,
    const favicon_base::FaviconResultsCallback& callback,
    base::CancelableTaskTracker* tracker) {
  if (page_url.SchemeIs(content::kChromeUIScheme) ||
      page_url.SchemeIs(extensions::kExtensionScheme)) {
    return GetFaviconForChromeURL(
        profile_, page_url, desired_sizes_in_pixel, callback, tracker);
  }
  if (history_service_) {
    return history_service_->GetFaviconsForURL(page_url,
                                               icon_types,
                                               desired_sizes_in_pixel,
                                               callback,
                                               tracker);
  }
  return RunWithEmptyResultAsync(callback, tracker);
}

void FaviconService::RunFaviconImageCallbackWithBitmapResults(
    const favicon_base::FaviconImageCallback& callback,
    int desired_size_in_dip,
    const std::vector<favicon_base::FaviconRawBitmapResult>&
        favicon_bitmap_results) {
  favicon_base::FaviconImageResult image_result;
  image_result.image = favicon_base::SelectFaviconFramesFromPNGs(
      favicon_bitmap_results,
      favicon_base::GetFaviconScales(),
      desired_size_in_dip);
  favicon_base::SetFaviconColorSpace(&image_result.image);

  image_result.icon_url = image_result.image.IsEmpty() ?
      GURL() : favicon_bitmap_results[0].icon_url;
  callback.Run(image_result);
}

void FaviconService::RunFaviconRawBitmapCallbackWithBitmapResults(
    const favicon_base::FaviconRawBitmapCallback& callback,
    int desired_size_in_pixel,
    const std::vector<favicon_base::FaviconRawBitmapResult>&
        favicon_bitmap_results) {
  if (favicon_bitmap_results.empty() || !favicon_bitmap_results[0].is_valid()) {
    callback.Run(favicon_base::FaviconRawBitmapResult());
    return;
  }

  favicon_base::FaviconRawBitmapResult bitmap_result =
      favicon_bitmap_results[0];

  // If the desired size is 0, SelectFaviconFrames() will return the largest
  // bitmap without doing any resizing. As |favicon_bitmap_results| has bitmap
  // data for a single bitmap, return it and avoid an unnecessary decode.
  if (desired_size_in_pixel == 0) {
    callback.Run(bitmap_result);
    return;
  }

  // If history bitmap is already desired pixel size, return early.
  if (bitmap_result.pixel_size.width() == desired_size_in_pixel &&
      bitmap_result.pixel_size.height() == desired_size_in_pixel) {
    callback.Run(bitmap_result);
    return;
  }

  // Convert raw bytes to SkBitmap, resize via SelectFaviconFrames(), then
  // convert back.
  std::vector<float> desired_favicon_scales;
  desired_favicon_scales.push_back(1.0f);
  gfx::Image resized_image = favicon_base::SelectFaviconFramesFromPNGs(
      favicon_bitmap_results, desired_favicon_scales, desired_size_in_pixel);

  std::vector<unsigned char> resized_bitmap_data;
  if (!gfx::PNGCodec::EncodeBGRASkBitmap(resized_image.AsBitmap(), false,
                                         &resized_bitmap_data)) {
    callback.Run(favicon_base::FaviconRawBitmapResult());
    return;
  }

  bitmap_result.bitmap_data = base::RefCountedBytes::TakeVector(
      &resized_bitmap_data);
  callback.Run(bitmap_result);
}
