// Copyright 2014 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/android/thumbnail/thumbnail_cache.h"

#include <algorithm>
#include <cmath>
#include <utility>

#include "base/android/application_status_listener.h"
#include "base/android/path_utils.h"
#include "base/big_endian.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/android_opengl/etc1/etc1.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "ui/android/resources/ui_resource_provider.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/size_conversions.h"

namespace {

const float kApproximationScaleFactor = 4.f;
const base::TimeDelta kCaptureMinRequestTimeMs(
    base::TimeDelta::FromMilliseconds(1000));

const int kCompressedKey = 0xABABABAB;
const int kCurrentExtraVersion = 1;

// Indicates whether we prefer to have more free CPU memory over GPU memory.
const bool kPreferCPUMemory = true;

size_t NextPowerOfTwo(size_t x) {
  --x;
  x |= x >> 1;
  x |= x >> 2;
  x |= x >> 4;
  x |= x >> 8;
  x |= x >> 16;
  return x + 1;
}

size_t RoundUpMod4(size_t x) {
  return (x + 3) & ~3;
}

gfx::Size GetEncodedSize(const gfx::Size& bitmap_size, bool supports_npot) {
  DCHECK(!bitmap_size.IsEmpty());
  if (!supports_npot)
    return gfx::Size(NextPowerOfTwo(bitmap_size.width()),
                     NextPowerOfTwo(bitmap_size.height()));
  else
    return gfx::Size(RoundUpMod4(bitmap_size.width()),
                     RoundUpMod4(bitmap_size.height()));
}

template<typename T>
bool ReadBigEndianFromFile(base::File& file, T* out) {
  char buffer[sizeof(T)];
  if (file.ReadAtCurrentPos(buffer, sizeof(T)) != sizeof(T))
    return false;
  base::ReadBigEndian(buffer, out);
  return true;
}

template<typename T>
bool WriteBigEndianToFile(base::File& file, T val) {
  char buffer[sizeof(T)];
  base::WriteBigEndian(buffer, val);
  return file.WriteAtCurrentPos(buffer, sizeof(T)) == sizeof(T);
}

bool ReadBigEndianFloatFromFile(base::File& file, float* out) {
  char buffer[sizeof(float)];
  if (file.ReadAtCurrentPos(buffer, sizeof(buffer)) != sizeof(buffer))
    return false;

#if defined(ARCH_CPU_LITTLE_ENDIAN)
  for (size_t i = 0; i < sizeof(float) / 2; i++) {
    char tmp = buffer[i];
    buffer[i] = buffer[sizeof(float) - 1 - i];
    buffer[sizeof(float) - 1 - i] = tmp;
  }
#endif
  memcpy(out, buffer, sizeof(buffer));

  return true;
}

bool WriteBigEndianFloatToFile(base::File& file, float val) {
  char buffer[sizeof(float)];
  memcpy(buffer, &val, sizeof(buffer));

#if defined(ARCH_CPU_LITTLE_ENDIAN)
  for (size_t i = 0; i < sizeof(float) / 2; i++) {
    char tmp = buffer[i];
    buffer[i] = buffer[sizeof(float) - 1 - i];
    buffer[sizeof(float) - 1 - i] = tmp;
  }
#endif
  return file.WriteAtCurrentPos(buffer, sizeof(buffer)) == sizeof(buffer);
}

}  // anonymous namespace

ThumbnailCache::ThumbnailCache(size_t default_cache_size,
                               size_t approximation_cache_size,
                               size_t compression_queue_max_size,
                               size_t write_queue_max_size,
                               bool use_approximation_thumbnail)
    : file_sequenced_task_runner_(
          base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})),
      compression_queue_max_size_(compression_queue_max_size),
      write_queue_max_size_(write_queue_max_size),
      use_approximation_thumbnail_(use_approximation_thumbnail),
      compression_tasks_count_(0),
      write_tasks_count_(0),
      read_in_progress_(false),
      cache_(default_cache_size),
      approximation_cache_(approximation_cache_size),
      ui_resource_provider_(NULL),
      weak_factory_(this) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  memory_pressure_.reset(new base::MemoryPressureListener(
      base::Bind(&ThumbnailCache::OnMemoryPressure, base::Unretained(this))));
}

ThumbnailCache::~ThumbnailCache() {
  SetUIResourceProvider(NULL);
}

void ThumbnailCache::SetUIResourceProvider(
    ui::UIResourceProvider* ui_resource_provider) {
  if (ui_resource_provider_ == ui_resource_provider)
    return;

  approximation_cache_.Clear();
  cache_.Clear();

  ui_resource_provider_ = ui_resource_provider;
}

void ThumbnailCache::AddThumbnailCacheObserver(
    ThumbnailCacheObserver* observer) {
  if (!observers_.HasObserver(observer))
    observers_.AddObserver(observer);
}

void ThumbnailCache::RemoveThumbnailCacheObserver(
    ThumbnailCacheObserver* observer) {
  if (observers_.HasObserver(observer))
    observers_.RemoveObserver(observer);
}

void ThumbnailCache::Put(TabId tab_id,
                         const SkBitmap& bitmap,
                         float thumbnail_scale) {
  if (!ui_resource_provider_ || bitmap.empty() || thumbnail_scale <= 0)
    return;

  if (thumbnail_meta_data_.find(tab_id) == thumbnail_meta_data_.end()) {
    DVLOG(1) << "Thumbnail meta data was removed for tab id " << tab_id;
    return;
  }

  base::Time time_stamp = thumbnail_meta_data_[tab_id].capture_time();
  std::unique_ptr<Thumbnail> thumbnail = Thumbnail::Create(
      tab_id, time_stamp, thumbnail_scale, ui_resource_provider_, this);
  thumbnail->SetBitmap(bitmap);

  RemoveFromReadQueue(tab_id);
  MakeSpaceForNewItemIfNecessary(tab_id);
  cache_.Put(tab_id, std::move(thumbnail));

  if (use_approximation_thumbnail_) {
    std::pair<SkBitmap, float> approximation =
        CreateApproximation(bitmap, thumbnail_scale);
    std::unique_ptr<Thumbnail> approx_thumbnail = Thumbnail::Create(
        tab_id, time_stamp, approximation.second, ui_resource_provider_, this);
    approx_thumbnail->SetBitmap(approximation.first);
    approximation_cache_.Put(tab_id, std::move(approx_thumbnail));
  }
  CompressThumbnailIfNecessary(tab_id, time_stamp, bitmap, thumbnail_scale);
}

void ThumbnailCache::Remove(TabId tab_id) {
  cache_.Remove(tab_id);
  approximation_cache_.Remove(tab_id);
  thumbnail_meta_data_.erase(tab_id);
  RemoveFromDisk(tab_id);
  RemoveFromReadQueue(tab_id);
}

Thumbnail* ThumbnailCache::Get(TabId tab_id,
                               bool force_disk_read,
                               bool allow_approximation) {
  Thumbnail* thumbnail = cache_.Get(tab_id);
  if (thumbnail) {
    thumbnail->CreateUIResource();
    return thumbnail;
  }

  if (force_disk_read && primary_tab_id_ != tab_id &&
      base::ContainsValue(visible_ids_, tab_id) &&
      !base::ContainsValue(read_queue_, tab_id)) {
    read_queue_.push_back(tab_id);
    ReadNextThumbnail();
  }

  if (allow_approximation) {
    thumbnail = approximation_cache_.Get(tab_id);
    if (thumbnail) {
      thumbnail->CreateUIResource();
      return thumbnail;
    }
  }

  return NULL;
}

void ThumbnailCache::InvalidateThumbnailIfChanged(TabId tab_id,
                                                  const GURL& url) {
  ThumbnailMetaDataMap::iterator meta_data_iter =
      thumbnail_meta_data_.find(tab_id);
  if (meta_data_iter == thumbnail_meta_data_.end()) {
    thumbnail_meta_data_[tab_id] = ThumbnailMetaData(base::Time(), url);
  } else if (meta_data_iter->second.url() != url) {
    Remove(tab_id);
  }
}

base::FilePath ThumbnailCache::GetCacheDirectory() {
  base::FilePath path;
  base::android::GetThumbnailCacheDirectory(&path);
  return path;
}

base::FilePath ThumbnailCache::GetFilePath(TabId tab_id) {
  base::FilePath path = GetCacheDirectory();
  return path.Append(base::IntToString(tab_id));
}

bool ThumbnailCache::CheckAndUpdateThumbnailMetaData(TabId tab_id,
                                                     const GURL& url) {
  base::Time current_time = base::Time::Now();
  ThumbnailMetaDataMap::iterator meta_data_iter =
      thumbnail_meta_data_.find(tab_id);
  if (meta_data_iter != thumbnail_meta_data_.end() &&
      meta_data_iter->second.url() == url &&
      (current_time - meta_data_iter->second.capture_time()) <
          kCaptureMinRequestTimeMs) {
    return false;
  }

  thumbnail_meta_data_[tab_id] = ThumbnailMetaData(current_time, url);
  return true;
}

void ThumbnailCache::UpdateVisibleIds(const TabIdList& priority,
                                      TabId primary_tab_id) {
  bool needs_update = false;
  if (primary_tab_id_ != primary_tab_id) {
    // The primary screen-filling tab (if any) is not pushed onto the read
    // queue, under the assumption that it either has a live layer or will have
    // one very soon.
    primary_tab_id_ = primary_tab_id;
    needs_update = true;
  }

  size_t ids_size = std::min(priority.size(), cache_.MaximumCacheSize());
  if (visible_ids_.size() != ids_size) {
    needs_update = true;
  } else {
    // Early out if called with the same input as last time (We only care
    // about the first mCache.MaximumCacheSize() entries).
    TabIdList::const_iterator visible_iter = visible_ids_.begin();
    TabIdList::const_iterator priority_iter = priority.begin();
    while (visible_iter != visible_ids_.end() &&
           priority_iter != priority.end()) {
      if (*priority_iter != *visible_iter || !cache_.Get(*priority_iter)) {
        needs_update = true;
        break;
      }
      visible_iter++;
      priority_iter++;
    }
  }

  if (!needs_update)
    return;

  read_queue_.clear();
  visible_ids_.clear();
  size_t count = 0;
  TabIdList::const_iterator iter = priority.begin();
  while (iter != priority.end() && count < ids_size) {
    TabId tab_id = *iter;
    visible_ids_.push_back(tab_id);
    if (!cache_.Get(tab_id) && primary_tab_id_ != tab_id &&
        !base::ContainsValue(read_queue_, tab_id))
      read_queue_.push_back(tab_id);
    iter++;
    count++;
  }

  ReadNextThumbnail();
}

void ThumbnailCache::DecompressThumbnailFromFile(
    TabId tab_id,
    const base::Callback<void(bool, SkBitmap)>&
        post_decompress_callback) {
  base::Callback<void(sk_sp<SkPixelRef>, float, const gfx::Size&)>
      decompress_task = base::Bind(
          &ThumbnailCache::DecompressionTask, post_decompress_callback);

  file_sequenced_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&ThumbnailCache::ReadTask, true, tab_id, decompress_task));
}

void ThumbnailCache::RemoveFromDisk(TabId tab_id) {
  file_sequenced_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&ThumbnailCache::RemoveFromDiskTask, tab_id));
}

void ThumbnailCache::RemoveFromDiskTask(TabId tab_id) {
  base::FilePath file_path = GetFilePath(tab_id);
  if (base::PathExists(file_path))
    base::DeleteFile(file_path, false);
}

void ThumbnailCache::WriteThumbnailIfNecessary(
    TabId tab_id,
    sk_sp<SkPixelRef> compressed_data,
    float scale,
    const gfx::Size& content_size) {
  if (write_tasks_count_ >= write_queue_max_size_)
    return;

  write_tasks_count_++;

  base::Callback<void()> post_write_task =
      base::Bind(&ThumbnailCache::PostWriteTask, weak_factory_.GetWeakPtr());
  file_sequenced_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&ThumbnailCache::WriteTask, tab_id, compressed_data, scale,
                     content_size, post_write_task));
}

void ThumbnailCache::CompressThumbnailIfNecessary(
    TabId tab_id,
    const base::Time& time_stamp,
    const SkBitmap& bitmap,
    float scale) {
  if (compression_tasks_count_ >= compression_queue_max_size_) {
    RemoveOnMatchedTimeStamp(tab_id, time_stamp);
    return;
  }

  compression_tasks_count_++;

  base::Callback<void(sk_sp<SkPixelRef>, const gfx::Size&)>
      post_compression_task = base::Bind(&ThumbnailCache::PostCompressionTask,
                                         weak_factory_.GetWeakPtr(),
                                         tab_id,
                                         time_stamp,
                                         scale);

  gfx::Size raw_data_size(bitmap.width(), bitmap.height());
  gfx::Size encoded_size = GetEncodedSize(
      raw_data_size, ui_resource_provider_->SupportsETC1NonPowerOfTwo());

  base::PostTaskWithTraits(FROM_HERE,
                           {base::TaskPriority::BEST_EFFORT,
                            base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
                           base::Bind(&ThumbnailCache::CompressionTask, bitmap,
                                      encoded_size, post_compression_task));
}

void ThumbnailCache::ReadNextThumbnail() {
  if (read_queue_.empty() || read_in_progress_)
    return;

  TabId tab_id = read_queue_.front();
  read_in_progress_ = true;

  base::Callback<void(sk_sp<SkPixelRef>, float, const gfx::Size&)>
      post_read_task = base::Bind(
          &ThumbnailCache::PostReadTask, weak_factory_.GetWeakPtr(), tab_id);

  file_sequenced_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&ThumbnailCache::ReadTask, false, tab_id, post_read_task));
}

void ThumbnailCache::MakeSpaceForNewItemIfNecessary(TabId tab_id) {
  if (cache_.Get(tab_id) || !base::ContainsValue(visible_ids_, tab_id) ||
      cache_.size() < cache_.MaximumCacheSize()) {
    return;
  }

  TabId key_to_remove;
  bool found_key_to_remove = false;

  // 1. Find a cached item not in this list
  for (ExpiringThumbnailCache::iterator iter = cache_.begin();
       iter != cache_.end();
       iter++) {
    if (!base::ContainsValue(visible_ids_, iter->first)) {
      key_to_remove = iter->first;
      found_key_to_remove = true;
      break;
    }
  }

  if (!found_key_to_remove) {
    // 2. Find the least important id we can remove.
    for (TabIdList::reverse_iterator riter = visible_ids_.rbegin();
         riter != visible_ids_.rend();
         riter++) {
      if (cache_.Get(*riter)) {
        key_to_remove = *riter;
        break;
        found_key_to_remove = true;
      }
    }
  }

  if (found_key_to_remove)
    cache_.Remove(key_to_remove);
}

void ThumbnailCache::RemoveFromReadQueue(TabId tab_id) {
  TabIdList::iterator read_iter =
      std::find(read_queue_.begin(), read_queue_.end(), tab_id);
  if (read_iter != read_queue_.end())
    read_queue_.erase(read_iter);
}

void ThumbnailCache::OnUIResourcesWereEvicted() {
  if (visible_ids_.empty()) {
    cache_.Clear();
    approximation_cache_.Clear();
  } else {
    TabId last_tab = visible_ids_.front();
    std::unique_ptr<Thumbnail> thumbnail = cache_.Remove(last_tab);
    cache_.Clear();
    std::unique_ptr<Thumbnail> approximation =
        approximation_cache_.Remove(last_tab);
    approximation_cache_.Clear();

    // Keep the thumbnail for app resume if it wasn't uploaded yet.
    if (thumbnail.get() && !thumbnail->ui_resource_id())
      cache_.Put(last_tab, std::move(thumbnail));
    if (approximation.get() && !approximation->ui_resource_id())
      approximation_cache_.Put(last_tab, std::move(approximation));
  }
}

void ThumbnailCache::InvalidateCachedThumbnail(Thumbnail* thumbnail) {
  DCHECK(thumbnail);
  TabId tab_id = thumbnail->tab_id();
  cc::UIResourceId uid = thumbnail->ui_resource_id();

  Thumbnail* cached_thumbnail = cache_.Get(tab_id);
  if (cached_thumbnail && cached_thumbnail->ui_resource_id() == uid)
    cache_.Remove(tab_id);

  cached_thumbnail = approximation_cache_.Get(tab_id);
  if (cached_thumbnail && cached_thumbnail->ui_resource_id() == uid)
    approximation_cache_.Remove(tab_id);
}

namespace {

bool WriteToFile(base::File& file,
                 const gfx::Size& content_size,
                 const float scale,
                 sk_sp<SkPixelRef> compressed_data) {
  if (!file.IsValid())
    return false;

  if (!WriteBigEndianToFile(file, kCompressedKey))
    return false;

  if (!WriteBigEndianToFile(file, content_size.width()))
    return false;

  if (!WriteBigEndianToFile(file, content_size.height()))
    return false;

  // Write ETC1 header.
  unsigned char etc1_buffer[ETC_PKM_HEADER_SIZE];
  etc1_pkm_format_header(etc1_buffer, compressed_data->width(),
                         compressed_data->height());

  int header_bytes_written = file.WriteAtCurrentPos(
      reinterpret_cast<char*>(etc1_buffer), ETC_PKM_HEADER_SIZE);
  if (header_bytes_written != ETC_PKM_HEADER_SIZE)
    return false;

  int data_size = etc1_get_encoded_data_size(compressed_data->width(),
                                             compressed_data->height());
  int pixel_bytes_written = file.WriteAtCurrentPos(
      reinterpret_cast<char*>(compressed_data->pixels()),
      data_size);
  if (pixel_bytes_written != data_size)
    return false;

  if (!WriteBigEndianToFile(file, kCurrentExtraVersion))
    return false;

  if (!WriteBigEndianFloatToFile(file, 1.f / scale))
    return false;

  return true;
}

}  // anonymous namespace

void ThumbnailCache::WriteTask(TabId tab_id,
                               sk_sp<SkPixelRef> compressed_data,
                               float scale,
                               const gfx::Size& content_size,
                               const base::Callback<void()>& post_write_task) {
  DCHECK(compressed_data);

  base::FilePath file_path = GetFilePath(tab_id);

  base::File file(file_path,
                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);

  bool success = WriteToFile(file,
                             content_size,
                             scale,
                             compressed_data);

  file.Close();

  if (!success)
    base::DeleteFile(file_path, false);

  content::BrowserThread::PostTask(
      content::BrowserThread::UI, FROM_HERE, post_write_task);
}

void ThumbnailCache::PostWriteTask() {
  write_tasks_count_--;
}

void ThumbnailCache::CompressionTask(
    SkBitmap raw_data,
    gfx::Size encoded_size,
    const base::Callback<void(sk_sp<SkPixelRef>, const gfx::Size&)>&
        post_compression_task) {
  sk_sp<SkPixelRef> compressed_data;
  gfx::Size content_size;

  if (!raw_data.empty()) {
    gfx::Size raw_data_size(raw_data.width(), raw_data.height());
    size_t pixel_size = 4;  // Pixel size is 4 bytes for kARGB_8888_Config.
    size_t stride = pixel_size * raw_data_size.width();

    size_t encoded_bytes =
        etc1_get_encoded_data_size(encoded_size.width(), encoded_size.height());
    SkImageInfo info = SkImageInfo::Make(encoded_size.width(),
                                         encoded_size.height(),
                                         kUnknown_SkColorType,
                                         kUnpremul_SkAlphaType);
    sk_sp<SkData> etc1_pixel_data(SkData::MakeUninitialized(encoded_bytes));
    sk_sp<SkPixelRef> etc1_pixel_ref(
        SkMallocPixelRef::MakeWithData(info, 0, std::move(etc1_pixel_data)));

    bool success = etc1_encode_image(
        reinterpret_cast<unsigned char*>(raw_data.getPixels()),
        raw_data_size.width(),
        raw_data_size.height(),
        pixel_size,
        stride,
        reinterpret_cast<unsigned char*>(etc1_pixel_ref->pixels()),
        encoded_size.width(),
        encoded_size.height());
    etc1_pixel_ref->setImmutable();

    if (success) {
      compressed_data = std::move(etc1_pixel_ref);
      content_size = raw_data_size;
    }
  }

  content::BrowserThread::PostTask(
      content::BrowserThread::UI,
      FROM_HERE,
      base::Bind(post_compression_task, std::move(compressed_data),
                 content_size));
}

void ThumbnailCache::PostCompressionTask(
    TabId tab_id,
    const base::Time& time_stamp,
    float scale,
    sk_sp<SkPixelRef> compressed_data,
    const gfx::Size& content_size) {
  compression_tasks_count_--;
  if (!compressed_data) {
    RemoveOnMatchedTimeStamp(tab_id, time_stamp);
    return;
  }

  Thumbnail* thumbnail = cache_.Get(tab_id);
  if (thumbnail) {
    if (thumbnail->time_stamp() != time_stamp)
      return;
    thumbnail->SetCompressedBitmap(compressed_data, content_size);
    // Don't upload the texture if we are being paused/stopped because
    // the context will go away anyways.
    if (base::android::ApplicationStatusListener::GetState() ==
        base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
      thumbnail->CreateUIResource();
    }
  }
  WriteThumbnailIfNecessary(tab_id, std::move(compressed_data), scale,
                            content_size);
}

namespace {

bool ReadFromFile(base::File& file,
                  gfx::Size* out_content_size,
                  float* out_scale,
                  sk_sp<SkPixelRef>* out_pixels) {
  if (!file.IsValid())
    return false;

  int key = 0;
  if (!ReadBigEndianFromFile(file, &key))
    return false;

  if (key != kCompressedKey)
    return false;

  int content_width = 0;
  if (!ReadBigEndianFromFile(file, &content_width) || content_width <= 0)
    return false;

  int content_height = 0;
  if (!ReadBigEndianFromFile(file, &content_height) || content_height <= 0)
    return false;

  out_content_size->SetSize(content_width, content_height);

  // Read ETC1 header.
  int header_bytes_read = 0;
  unsigned char etc1_buffer[ETC_PKM_HEADER_SIZE];
  header_bytes_read = file.ReadAtCurrentPos(
      reinterpret_cast<char*>(etc1_buffer),
      ETC_PKM_HEADER_SIZE);
  if (header_bytes_read != ETC_PKM_HEADER_SIZE)
    return false;

  if (!etc1_pkm_is_valid(etc1_buffer))
    return false;

  int raw_width = 0;
  raw_width = etc1_pkm_get_width(etc1_buffer);
  if (raw_width <= 0)
    return false;

  int raw_height = 0;
  raw_height = etc1_pkm_get_height(etc1_buffer);
  if (raw_height <= 0)
    return false;

  // Do some simple sanity check validation.  We can't have thumbnails larger
  // than the max display size of the screen.  We also can't have etc1 texture
  // data larger than the next power of 2 up from that.
  gfx::Size display_size =
      display::Screen::GetScreen()->GetPrimaryDisplay().GetSizeInPixel();
  int max_dimension = std::max(display_size.width(), display_size.height());

  if (content_width > max_dimension
      || content_height > max_dimension
      || static_cast<size_t>(raw_width) > NextPowerOfTwo(max_dimension)
      || static_cast<size_t>(raw_height) > NextPowerOfTwo(max_dimension)) {
    return false;
  }

  int data_size = etc1_get_encoded_data_size(raw_width, raw_height);
  sk_sp<SkData> etc1_pixel_data(SkData::MakeUninitialized(data_size));

  int pixel_bytes_read = file.ReadAtCurrentPos(
      reinterpret_cast<char*>(etc1_pixel_data->writable_data()),
      data_size);

  if (pixel_bytes_read != data_size)
    return false;

  SkImageInfo info = SkImageInfo::Make(raw_width,
                                       raw_height,
                                       kUnknown_SkColorType,
                                       kUnpremul_SkAlphaType);

  *out_pixels =
      SkMallocPixelRef::MakeWithData(info, 0, std::move(etc1_pixel_data));

  int extra_data_version = 0;
  if (!ReadBigEndianFromFile(file, &extra_data_version))
    return false;

  *out_scale = 1.f;
  if (extra_data_version == 1) {
    if (!ReadBigEndianFloatFromFile(file, out_scale))
      return false;

    if (*out_scale == 0.f)
      return false;

    *out_scale = 1.f / *out_scale;
  }

  return true;
}

}// anonymous namespace

void ThumbnailCache::ReadTask(
    bool decompress,
    TabId tab_id,
    const base::Callback<
        void(sk_sp<SkPixelRef>, float, const gfx::Size&)>&
        post_read_task) {
  gfx::Size content_size;
  float scale = 0.f;
  sk_sp<SkPixelRef> compressed_data;
  base::FilePath file_path = GetFilePath(tab_id);

  if (base::PathExists(file_path)) {
    base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);


    bool valid_contents = ReadFromFile(file,
                                       &content_size,
                                       &scale,
                                       &compressed_data);
    file.Close();

    if (!valid_contents) {
      content_size.SetSize(0, 0);
            scale = 0.f;
            compressed_data.reset();
            base::DeleteFile(file_path, false);
    }
  }

  if (decompress) {
    base::PostTaskWithTraits(
        FROM_HERE, {base::TaskPriority::BEST_EFFORT},
        base::Bind(post_read_task, std::move(compressed_data), scale,
                   content_size));
  } else {
    content::BrowserThread::PostTask(
        content::BrowserThread::UI,
        FROM_HERE,
        base::Bind(post_read_task, std::move(compressed_data), scale,
                   content_size));
  }
}

void ThumbnailCache::PostReadTask(TabId tab_id,
                                  sk_sp<SkPixelRef> compressed_data,
                                  float scale,
                                  const gfx::Size& content_size) {
  read_in_progress_ = false;

  TabIdList::iterator iter =
      std::find(read_queue_.begin(), read_queue_.end(), tab_id);
  if (iter == read_queue_.end()) {
    ReadNextThumbnail();
    return;
  }

  read_queue_.erase(iter);

  if (!cache_.Get(tab_id) && compressed_data) {
    ThumbnailMetaDataMap::iterator meta_iter =
        thumbnail_meta_data_.find(tab_id);
    base::Time time_stamp = base::Time::Now();
    if (meta_iter != thumbnail_meta_data_.end())
      time_stamp = meta_iter->second.capture_time();

    MakeSpaceForNewItemIfNecessary(tab_id);
    std::unique_ptr<Thumbnail> thumbnail = Thumbnail::Create(
        tab_id, time_stamp, scale, ui_resource_provider_, this);
    thumbnail->SetCompressedBitmap(std::move(compressed_data),
                                   content_size);
    if (kPreferCPUMemory)
      thumbnail->CreateUIResource();

    cache_.Put(tab_id, std::move(thumbnail));
    NotifyObserversOfThumbnailRead(tab_id);
  }

  ReadNextThumbnail();
}

void ThumbnailCache::NotifyObserversOfThumbnailRead(TabId tab_id) {
  for (ThumbnailCacheObserver& observer : observers_)
    observer.OnFinishedThumbnailRead(tab_id);
}

void ThumbnailCache::RemoveOnMatchedTimeStamp(TabId tab_id,
                                              const base::Time& time_stamp) {
  // We remove the cached version if it matches the tab_id and the time_stamp.
  Thumbnail* thumbnail = cache_.Get(tab_id);
  Thumbnail* approx_thumbnail = approximation_cache_.Get(tab_id);
  if ((thumbnail && thumbnail->time_stamp() == time_stamp) ||
      (approx_thumbnail && approx_thumbnail->time_stamp() == time_stamp)) {
    Remove(tab_id);
  }
  return;
}

void ThumbnailCache::DecompressionTask(
    const base::Callback<void(bool, SkBitmap)>&
        post_decompression_callback,
    sk_sp<SkPixelRef> compressed_data,
    float scale,
    const gfx::Size& content_size) {
  SkBitmap raw_data_small;
  bool success = false;

  if (compressed_data.get()) {
    gfx::Size buffer_size =
        gfx::Size(compressed_data->width(), compressed_data->height());

    SkBitmap raw_data;
    raw_data.allocPixels(SkImageInfo::Make(buffer_size.width(),
                                           buffer_size.height(),
                                           kRGBA_8888_SkColorType,
                                           kOpaque_SkAlphaType));
    success = etc1_decode_image(
        reinterpret_cast<unsigned char*>(compressed_data->pixels()),
        reinterpret_cast<unsigned char*>(raw_data.getPixels()),
        buffer_size.width(),
        buffer_size.height(),
        raw_data.bytesPerPixel(),
        raw_data.rowBytes());
    raw_data.setImmutable();

    if (!success) {
      // Leave raw_data_small empty for consistency with other failure modes.
    } else if (content_size == buffer_size) {
      // Shallow copy the pixel reference.
      raw_data_small = raw_data;
    } else {
      // The content size is smaller than the buffer size (likely because of
      // a power-of-two rounding), so deep copy the bitmap.
      raw_data_small.allocPixels(SkImageInfo::Make(content_size.width(),
                                                   content_size.height(),
                                                   kRGBA_8888_SkColorType,
                                                   kOpaque_SkAlphaType));
      SkCanvas small_canvas(raw_data_small);
      small_canvas.drawBitmap(raw_data, 0, 0);
      raw_data_small.setImmutable();
    }
  }

  content::BrowserThread::PostTask(
      content::BrowserThread::UI,
      FROM_HERE,
      base::Bind(post_decompression_callback, success, raw_data_small));
}

ThumbnailCache::ThumbnailMetaData::ThumbnailMetaData() {
}

ThumbnailCache::ThumbnailMetaData::ThumbnailMetaData(
    const base::Time& current_time,
    const GURL& url)
    : capture_time_(current_time), url_(url) {
}

std::pair<SkBitmap, float> ThumbnailCache::CreateApproximation(
    const SkBitmap& bitmap,
    float scale) {
  DCHECK(!bitmap.empty());
  DCHECK_GT(scale, 0);
  float new_scale = 1.f / kApproximationScaleFactor;

  gfx::Size dst_size = gfx::ScaleToFlooredSize(
      gfx::Size(bitmap.width(), bitmap.height()), new_scale);
  SkBitmap dst_bitmap;
  dst_bitmap.allocPixels(SkImageInfo::Make(dst_size.width(),
                                           dst_size.height(),
                                           bitmap.info().colorType(),
                                           bitmap.info().alphaType()));
  dst_bitmap.eraseColor(0);
  SkCanvas canvas(dst_bitmap);
  canvas.scale(new_scale, new_scale);
  canvas.drawBitmap(bitmap, 0, 0, NULL);
  dst_bitmap.setImmutable();

  return std::make_pair(dst_bitmap, new_scale * scale);
}

void ThumbnailCache::OnMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel level) {
  if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
    cache_.Clear();
    approximation_cache_.Clear();
  }
}
