// 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/ui/webui/extensions/extension_icon_source.h"

#include <stddef.h>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/ref_counted_memory.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/url_constants.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/image_loader.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_resource.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/grit/extensions_browser_resources.h"
#include "grit/component_extension_resources_map.h"
#include "skia/ext/image_operations.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/skbitmap_operations.h"
#include "url/gurl.h"

namespace extensions {

namespace {

scoped_refptr<base::RefCountedMemory> BitmapToMemory(const SkBitmap* image) {
  base::RefCountedBytes* image_bytes = new base::RefCountedBytes;
  gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_bytes->data());
  return image_bytes;
}

SkBitmap DesaturateImage(const SkBitmap* image) {
  color_utils::HSL shift = {-1, 0, 0.6};
  return SkBitmapOperations::CreateHSLShiftedBitmap(*image, shift);
}

SkBitmap* ToBitmap(const unsigned char* data, size_t size) {
  SkBitmap* decoded = new SkBitmap();
  bool success = gfx::PNGCodec::Decode(data, size, decoded);
  DCHECK(success);
  return decoded;
}

}  // namespace

ExtensionIconSource::ExtensionIconSource(Profile* profile) : profile_(profile) {
}

struct ExtensionIconSource::ExtensionIconRequest {
  content::URLDataSource::GotDataCallback callback;
  scoped_refptr<const Extension> extension;
  bool grayscale;
  int size;
  ExtensionIconSet::MatchType match;
};

// static
GURL ExtensionIconSource::GetIconURL(const Extension* extension,
                                     int icon_size,
                                     ExtensionIconSet::MatchType match,
                                     bool grayscale,
                                     bool* exists) {
  if (exists) {
    *exists =
        IconsInfo::GetIconURL(extension, icon_size, match) != GURL::EmptyGURL();
  }

  GURL icon_url(base::StringPrintf("%s%s/%d/%d%s",
                                   chrome::kChromeUIExtensionIconURL,
                                   extension->id().c_str(),
                                   icon_size,
                                   match,
                                   grayscale ? "?grayscale=true" : ""));
  CHECK(icon_url.is_valid());
  return icon_url;
}

// static
SkBitmap* ExtensionIconSource::LoadImageByResourceId(int resource_id) {
  std::string contents = ResourceBundle::GetSharedInstance()
      .GetRawDataResourceForScale(resource_id,
                                  ui::SCALE_FACTOR_100P).as_string();

  // Convert and return it.
  const unsigned char* data =
      reinterpret_cast<const unsigned char*>(contents.data());
  return ToBitmap(data, contents.length());
}

std::string ExtensionIconSource::GetSource() const {
  return chrome::kChromeUIExtensionIconHost;
}

std::string ExtensionIconSource::GetMimeType(const std::string&) const {
  // We need to explicitly return a mime type, otherwise if the user tries to
  // drag the image they get no extension.
  return "image/png";
}

void ExtensionIconSource::StartDataRequest(
    const std::string& path,
    int render_process_id,
    int render_frame_id,
    const content::URLDataSource::GotDataCallback& callback) {
  // This is where everything gets started. First, parse the request and make
  // the request data available for later.
  static int next_id = 0;
  if (!ParseData(path, ++next_id, callback)) {
    // If the request data cannot be parsed, request parameters will not be
    // added to |request_map_|.
    // Send back the default application icon (not resized or desaturated) as
    // the default response.
    callback.Run(BitmapToMemory(GetDefaultAppImage()).get());
    return;
  }

  ExtensionIconRequest* request = GetData(next_id);
  ExtensionResource icon = IconsInfo::GetIconResource(
      request->extension.get(), request->size, request->match);

  if (icon.relative_path().empty()) {
    LoadIconFailed(next_id);
  } else {
    LoadExtensionImage(icon, next_id);
  }
}

ExtensionIconSource::~ExtensionIconSource() {
  // Clean up all the temporary data we're holding for requests.
  STLDeleteValues(&request_map_);
}

const SkBitmap* ExtensionIconSource::GetDefaultAppImage() {
  if (!default_app_data_.get())
    default_app_data_.reset(LoadImageByResourceId(IDR_APP_DEFAULT_ICON));

  return default_app_data_.get();
}

const SkBitmap* ExtensionIconSource::GetDefaultExtensionImage() {
  if (!default_extension_data_.get()) {
    default_extension_data_.reset(
        LoadImageByResourceId(IDR_EXTENSION_DEFAULT_ICON));
  }

  return default_extension_data_.get();
}

void ExtensionIconSource::FinalizeImage(const SkBitmap* image,
                                        int request_id) {
  SkBitmap bitmap;
  ExtensionIconRequest* request = GetData(request_id);
  if (request->grayscale)
    bitmap = DesaturateImage(image);
  else
    bitmap = *image;

  request->callback.Run(BitmapToMemory(&bitmap).get());
  ClearData(request_id);
}

void ExtensionIconSource::LoadDefaultImage(int request_id) {
  ExtensionIconRequest* request = GetData(request_id);
  const SkBitmap* default_image = NULL;

  if (request->extension->is_app())
    default_image = GetDefaultAppImage();
  else
    default_image = GetDefaultExtensionImage();

  SkBitmap resized_image(skia::ImageOperations::Resize(
      *default_image, skia::ImageOperations::RESIZE_LANCZOS3,
      request->size, request->size));

  // There are cases where Resize returns an empty bitmap, for example if you
  // ask for an image too large. In this case it is better to return the default
  // image than returning nothing at all.
  if (resized_image.empty())
    resized_image = *default_image;

  FinalizeImage(&resized_image, request_id);
}

void ExtensionIconSource::LoadExtensionImage(const ExtensionResource& icon,
                                             int request_id) {
  ExtensionIconRequest* request = GetData(request_id);
  ImageLoader::Get(profile_)->LoadImageAsync(
      request->extension.get(),
      icon,
      gfx::Size(request->size, request->size),
      base::Bind(&ExtensionIconSource::OnImageLoaded, AsWeakPtr(), request_id));
}

void ExtensionIconSource::LoadFaviconImage(int request_id) {
  favicon::FaviconService* favicon_service =
      FaviconServiceFactory::GetForProfile(profile_,
                                           ServiceAccessType::EXPLICIT_ACCESS);
  // Fall back to the default icons if the service isn't available.
  if (favicon_service == NULL) {
    LoadDefaultImage(request_id);
    return;
  }

  GURL favicon_url =
      AppLaunchInfo::GetFullLaunchURL(GetData(request_id)->extension.get());
  favicon_service->GetRawFaviconForPageURL(
      favicon_url,
      favicon_base::FAVICON,
      gfx::kFaviconSize,
      base::Bind(&ExtensionIconSource::OnFaviconDataAvailable,
                 base::Unretained(this),
                 request_id),
      &cancelable_task_tracker_);
}

void ExtensionIconSource::OnFaviconDataAvailable(
    int request_id,
    const favicon_base::FaviconRawBitmapResult& bitmap_result) {
  ExtensionIconRequest* request = GetData(request_id);

  // Fallback to the default icon if there wasn't a favicon.
  if (!bitmap_result.is_valid()) {
    LoadDefaultImage(request_id);
    return;
  }

  if (!request->grayscale) {
    // If we don't need a grayscale image, then we can bypass FinalizeImage
    // to avoid unnecessary conversions.
    request->callback.Run(bitmap_result.bitmap_data.get());
    ClearData(request_id);
  } else {
    FinalizeImage(ToBitmap(bitmap_result.bitmap_data->front(),
                           bitmap_result.bitmap_data->size()), request_id);
  }
}

void ExtensionIconSource::OnImageLoaded(int request_id,
                                        const gfx::Image& image) {
  if (image.IsEmpty())
    LoadIconFailed(request_id);
  else
    FinalizeImage(image.ToSkBitmap(), request_id);
}

void ExtensionIconSource::LoadIconFailed(int request_id) {
  ExtensionIconRequest* request = GetData(request_id);
  ExtensionResource icon = IconsInfo::GetIconResource(
      request->extension.get(), request->size, request->match);

  if (request->size == extension_misc::EXTENSION_ICON_BITTY)
    LoadFaviconImage(request_id);
  else
    LoadDefaultImage(request_id);
}

bool ExtensionIconSource::ParseData(
    const std::string& path,
    int request_id,
    const content::URLDataSource::GotDataCallback& callback) {
  // Extract the parameters from the path by lower casing and splitting.
  std::string path_lower = base::ToLowerASCII(path);
  std::vector<std::string> path_parts = base::SplitString(
      path_lower, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (path_lower.empty() || path_parts.size() < 3)
    return false;

  std::string size_param = path_parts.at(1);
  std::string match_param = path_parts.at(2);
  match_param = match_param.substr(0, match_param.find('?'));

  int size;
  if (!base::StringToInt(size_param, &size))
    return false;
  if (size <= 0 || size > extension_misc::EXTENSION_ICON_GIGANTOR)
    return false;

  ExtensionIconSet::MatchType match_type;
  int match_num;
  if (!base::StringToInt(match_param, &match_num))
    return false;
  match_type = static_cast<ExtensionIconSet::MatchType>(match_num);
  if (!(match_type == ExtensionIconSet::MATCH_EXACTLY ||
        match_type == ExtensionIconSet::MATCH_SMALLER ||
        match_type == ExtensionIconSet::MATCH_BIGGER))
    match_type = ExtensionIconSet::MATCH_EXACTLY;

  std::string extension_id = path_parts.at(0);
  const Extension* extension = ExtensionSystem::Get(profile_)->
      extension_service()->GetInstalledExtension(extension_id);
  if (!extension)
    return false;

  bool grayscale = path_lower.find("grayscale=true") != std::string::npos;

  SetData(request_id, callback, extension, grayscale, size, match_type);

  return true;
}

void ExtensionIconSource::SetData(
    int request_id,
    const content::URLDataSource::GotDataCallback& callback,
    const Extension* extension,
    bool grayscale,
    int size,
    ExtensionIconSet::MatchType match) {
  ExtensionIconRequest* request = new ExtensionIconRequest();
  request->callback = callback;
  request->extension = extension;
  request->grayscale = grayscale;
  request->size = size;
  request->match = match;
  request_map_[request_id] = request;
}

ExtensionIconSource::ExtensionIconRequest* ExtensionIconSource::GetData(
    int request_id) {
  return request_map_[request_id];
}

void ExtensionIconSource::ClearData(int request_id) {
  std::map<int, ExtensionIconRequest*>::iterator i =
      request_map_.find(request_id);
  if (i == request_map_.end())
    return;

  delete i->second;
  request_map_.erase(i);
}

}  // namespace extensions
