15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/android/thumbnail/thumbnail_store.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <algorithm>
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <cmath>
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/big_endian.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/file.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/file_enumerator.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/file_path.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/threading/worker_pool.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/time/time.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/android/ui_resource_provider.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/android_opengl/etc1/etc1.h"
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h"
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/skia/include/core/SkData.h"
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/skia/include/core/SkMallocPixelRef.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/skia/include/core/SkPixelRef.h"
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/gfx/android/device_display_info.h"
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/geometry/size_conversions.h"
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const float kApproximationScaleFactor = 4.f;
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const base::TimeDelta kCaptureMinRequestTimeMs(
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::TimeDelta::FromMilliseconds(1000));
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const int kCompressedKey = 0xABABABAB;
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const int kCurrentExtraVersion = 1;
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Indicates whether we prefer to have more free CPU memory over GPU memory.
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const bool kPreferCPUMemory = true;
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t NextPowerOfTwo(size_t x) {
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  --x;
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  x |= x >> 1;
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  x |= x >> 2;
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  x |= x >> 4;
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  x |= x >> 8;
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  x |= x >> 16;
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return x + 1;
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccisize_t RoundUpMod4(size_t x) {
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return (x + 3) & ~3;
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Size GetEncodedSize(const gfx::Size& bitmap_size, bool supports_npot) {
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!bitmap_size.IsEmpty());
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!supports_npot)
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return gfx::Size(NextPowerOfTwo(bitmap_size.width()),
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     NextPowerOfTwo(bitmap_size.height()));
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  else
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return gfx::Size(RoundUpMod4(bitmap_size.width()),
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                     RoundUpMod4(bitmap_size.height()));
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)template<typename T>
6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ReadBigEndianFromFile(base::File& file, T* out) {
6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  char buffer[sizeof(T)];
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (file.ReadAtCurrentPos(buffer, sizeof(T)) != sizeof(T))
6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::ReadBigEndian(buffer, out);
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)template<typename T>
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool WriteBigEndianToFile(base::File& file, T val) {
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  char buffer[sizeof(T)];
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  base::WriteBigEndian(buffer, val);
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return file.WriteAtCurrentPos(buffer, sizeof(T)) == sizeof(T);
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ReadBigEndianFloatFromFile(base::File& file, float* out) {
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  char buffer[sizeof(float)];
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (file.ReadAtCurrentPos(buffer, sizeof(buffer)) != sizeof(buffer))
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(ARCH_CPU_LITTLE_ENDIAN)
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < sizeof(float) / 2; i++) {
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    char tmp = buffer[i];
8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    buffer[i] = buffer[sizeof(float) - 1 - i];
9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    buffer[sizeof(float) - 1 - i] = tmp;
9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif
9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  memcpy(out, buffer, sizeof(buffer));
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool WriteBigEndianFloatToFile(base::File& file, float val) {
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  char buffer[sizeof(float)];
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  memcpy(buffer, &val, sizeof(buffer));
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#if defined(ARCH_CPU_LITTLE_ENDIAN)
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < sizeof(float) / 2; i++) {
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    char tmp = buffer[i];
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    buffer[i] = buffer[sizeof(float) - 1 - i];
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    buffer[sizeof(float) - 1 - i] = tmp;
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return file.WriteAtCurrentPos(buffer, sizeof(buffer)) == sizeof(buffer);
11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // anonymous namespace
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ThumbnailStore::ThumbnailStore(const std::string& disk_cache_path_str,
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               size_t default_cache_size,
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               size_t approximation_cache_size,
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               size_t compression_queue_max_size,
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               size_t write_queue_max_size,
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               bool use_approximation_thumbnail)
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : disk_cache_path_(disk_cache_path_str),
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      compression_queue_max_size_(compression_queue_max_size),
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      write_queue_max_size_(write_queue_max_size),
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      use_approximation_thumbnail_(use_approximation_thumbnail),
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      compression_tasks_count_(0),
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      write_tasks_count_(0),
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      read_in_progress_(false),
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      cache_(default_cache_size),
1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      approximation_cache_(approximation_cache_size),
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ui_resource_provider_(NULL),
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      weak_factory_(this) {
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ThumbnailStore::~ThumbnailStore() {
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetUIResourceProvider(NULL);
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::SetUIResourceProvider(
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    content::UIResourceProvider* ui_resource_provider) {
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (ui_resource_provider_ == ui_resource_provider)
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  approximation_cache_.Clear();
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  cache_.Clear();
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ui_resource_provider_ = ui_resource_provider;
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::AddThumbnailStoreObserver(
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ThumbnailStoreObserver* observer) {
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!observers_.HasObserver(observer))
1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    observers_.AddObserver(observer);
1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::RemoveThumbnailStoreObserver(
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ThumbnailStoreObserver* observer) {
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (observers_.HasObserver(observer))
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    observers_.RemoveObserver(observer);
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::Put(TabId tab_id,
1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         const SkBitmap& bitmap,
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         float thumbnail_scale) {
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!ui_resource_provider_ || bitmap.empty() || thumbnail_scale <= 0)
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(thumbnail_meta_data_.find(tab_id) != thumbnail_meta_data_.end());
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::Time time_stamp = thumbnail_meta_data_[tab_id].capture_time();
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<Thumbnail> thumbnail = Thumbnail::Create(
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      tab_id, time_stamp, thumbnail_scale, ui_resource_provider_, this);
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  thumbnail->SetBitmap(bitmap);
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RemoveFromReadQueue(tab_id);
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MakeSpaceForNewItemIfNecessary(tab_id);
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  cache_.Put(tab_id, thumbnail.Pass());
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (use_approximation_thumbnail_) {
1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    std::pair<SkBitmap, float> approximation =
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        CreateApproximation(bitmap, thumbnail_scale);
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<Thumbnail> approx_thumbnail = Thumbnail::Create(
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tab_id, time_stamp, approximation.second, ui_resource_provider_, this);
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    approx_thumbnail->SetBitmap(approximation.first);
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    approximation_cache_.Put(tab_id, approx_thumbnail.Pass());
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  CompressThumbnailIfNecessary(tab_id, time_stamp, bitmap, thumbnail_scale);
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::Remove(TabId tab_id) {
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  cache_.Remove(tab_id);
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  approximation_cache_.Remove(tab_id);
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  thumbnail_meta_data_.erase(tab_id);
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RemoveFromDisk(tab_id);
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RemoveFromReadQueue(tab_id);
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
19729b820f8d84e3bc97d62552e54923c42407f2f29Ben MurdochThumbnail* ThumbnailStore::Get(TabId tab_id,
19829b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch                               bool force_disk_read,
19929b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch                               bool allow_approximation) {
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Thumbnail* thumbnail = cache_.Get(tab_id);
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (thumbnail) {
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    thumbnail->CreateUIResource();
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return thumbnail;
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (force_disk_read &&
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::find(visible_ids_.begin(), visible_ids_.end(), tab_id) !=
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          visible_ids_.end() &&
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::find(read_queue_.begin(), read_queue_.end(), tab_id) ==
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          read_queue_.end()) {
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    read_queue_.push_back(tab_id);
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ReadNextThumbnail();
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
21529b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch  if (allow_approximation) {
21629b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    thumbnail = approximation_cache_.Get(tab_id);
21729b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    if (thumbnail) {
21829b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch      thumbnail->CreateUIResource();
21929b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch      return thumbnail;
22029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch    }
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return NULL;
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::RemoveFromDiskAtAndAboveId(TabId min_id) {
2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::Closure remove_task =
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&ThumbnailStore::RemoveFromDiskAtAndAboveIdTask,
2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 disk_cache_path_,
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 min_id);
2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::PostTask(
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserThread::FILE, FROM_HERE, remove_task);
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::InvalidateThumbnailIfChanged(TabId tab_id,
2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                  const GURL& url) {
2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ThumbnailMetaDataMap::iterator meta_data_iter =
2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      thumbnail_meta_data_.find(tab_id);
2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (meta_data_iter == thumbnail_meta_data_.end()) {
2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    thumbnail_meta_data_[tab_id] = ThumbnailMetaData(base::Time(), url);
2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  } else if (meta_data_iter->second.url() != url) {
2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Remove(tab_id);
2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ThumbnailStore::CheckAndUpdateThumbnailMetaData(TabId tab_id,
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                     const GURL& url) {
2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::Time current_time = base::Time::Now();
2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ThumbnailMetaDataMap::iterator meta_data_iter =
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      thumbnail_meta_data_.find(tab_id);
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (meta_data_iter != thumbnail_meta_data_.end() &&
2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      meta_data_iter->second.url() == url &&
2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (current_time - meta_data_iter->second.capture_time()) <
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          kCaptureMinRequestTimeMs) {
2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  thumbnail_meta_data_[tab_id] = ThumbnailMetaData(current_time, url);
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::UpdateVisibleIds(const TabIdList& priority) {
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (priority.empty()) {
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    visible_ids_.clear();
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t ids_size = std::min(priority.size(), cache_.MaximumCacheSize());
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (visible_ids_.size() == ids_size) {
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Early out if called with the same input as last time (We only care
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // about the first mCache.MaximumCacheSize() entries).
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool lists_differ = false;
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabIdList::const_iterator visible_iter = visible_ids_.begin();
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabIdList::const_iterator priority_iter = priority.begin();
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    while (visible_iter != visible_ids_.end() &&
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           priority_iter != priority.end()) {
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (*priority_iter != *visible_iter) {
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        lists_differ = true;
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      visible_iter++;
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      priority_iter++;
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!lists_differ)
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  read_queue_.clear();
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  visible_ids_.clear();
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t count = 0;
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TabIdList::const_iterator iter = priority.begin();
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (iter != priority.end() && count < ids_size) {
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabId tab_id = *iter;
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    visible_ids_.push_back(tab_id);
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!cache_.Get(tab_id) &&
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        std::find(read_queue_.begin(), read_queue_.end(), tab_id) ==
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            read_queue_.end()) {
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      read_queue_.push_back(tab_id);
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    iter++;
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    count++;
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ReadNextThumbnail();
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ThumbnailStore::DecompressThumbnailFromFile(
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    TabId tab_id,
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Callback<void(bool, SkBitmap)>&
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        post_decompress_callback) {
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::FilePath file_path = GetFilePath(tab_id);
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::Callback<void(skia::RefPtr<SkPixelRef>, float, const gfx::Size&)>
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      decompress_task = base::Bind(
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          &ThumbnailStore::DecompressionTask, post_decompress_callback);
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  content::BrowserThread::PostTask(
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::BrowserThread::FILE,
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ThumbnailStore::ReadTask, true, file_path, decompress_task));
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::RemoveFromDisk(TabId tab_id) {
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FilePath file_path = GetFilePath(tab_id);
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::Closure task =
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&ThumbnailStore::RemoveFromDiskTask, file_path);
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::PostTask(
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserThread::FILE, FROM_HERE, task);
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::RemoveFromDiskTask(const base::FilePath& file_path) {
3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (base::PathExists(file_path))
3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::DeleteFile(file_path, false);
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::RemoveFromDiskAtAndAboveIdTask(
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::FilePath& dir_path,
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabId min_id) {
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FileEnumerator enumerator(dir_path, false, base::FileEnumerator::FILES);
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (true) {
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::FilePath path = enumerator.Next();
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (path.empty())
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::FileEnumerator::FileInfo info = enumerator.GetInfo();
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabId tab_id;
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool success = base::StringToInt(info.GetName().value(), &tab_id);
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (success && tab_id >= min_id)
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::DeleteFile(path, false);
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::WriteThumbnailIfNecessary(
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabId tab_id,
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    skia::RefPtr<SkPixelRef> compressed_data,
3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    float scale,
3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& content_size) {
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (write_tasks_count_ >= write_queue_max_size_)
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  write_tasks_count_++;
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::Callback<void()> post_write_task =
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&ThumbnailStore::PostWriteTask, weak_factory_.GetWeakPtr());
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::FILE,
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   FROM_HERE,
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   base::Bind(&ThumbnailStore::WriteTask,
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              GetFilePath(tab_id),
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              compressed_data,
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              scale,
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              content_size,
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              post_write_task));
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::CompressThumbnailIfNecessary(
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabId tab_id,
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Time& time_stamp,
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SkBitmap& bitmap,
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    float scale) {
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (compression_tasks_count_ >= compression_queue_max_size_) {
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RemoveOnMatchedTimeStamp(tab_id, time_stamp);
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  compression_tasks_count_++;
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::Callback<void(skia::RefPtr<SkPixelRef>, const gfx::Size&)>
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      post_compression_task = base::Bind(&ThumbnailStore::PostCompressionTask,
3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         weak_factory_.GetWeakPtr(),
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         tab_id,
3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         time_stamp,
3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         scale);
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size raw_data_size(bitmap.width(), bitmap.height());
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gfx::Size encoded_size = GetEncodedSize(
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      raw_data_size, ui_resource_provider_->SupportsETC1NonPowerOfTwo());
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WorkerPool::PostTask(FROM_HERE,
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             base::Bind(&ThumbnailStore::CompressionTask,
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        bitmap,
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        encoded_size,
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        post_compression_task),
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             true);
4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::ReadNextThumbnail() {
4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (read_queue_.empty() || read_in_progress_)
4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TabId tab_id = read_queue_.front();
4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  read_in_progress_ = true;
4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FilePath file_path = GetFilePath(tab_id);
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::Callback<void(skia::RefPtr<SkPixelRef>, float, const gfx::Size&)>
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      post_read_task = base::Bind(
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          &ThumbnailStore::PostReadTask, weak_factory_.GetWeakPtr(), tab_id);
4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::PostTask(
4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserThread::FILE,
4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FROM_HERE,
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ThumbnailStore::ReadTask, false, file_path, post_read_task));
4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::MakeSpaceForNewItemIfNecessary(TabId tab_id) {
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (cache_.Get(tab_id) ||
4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::find(visible_ids_.begin(), visible_ids_.end(), tab_id) ==
4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          visible_ids_.end() ||
4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      cache_.size() < cache_.MaximumCacheSize()) {
4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TabId key_to_remove;
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool found_key_to_remove = false;
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // 1. Find a cached item not in this list
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (ExpiringThumbnailCache::iterator iter = cache_.begin();
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter != cache_.end();
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       iter++) {
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (std::find(visible_ids_.begin(), visible_ids_.end(), iter->first) ==
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        visible_ids_.end()) {
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      key_to_remove = iter->first;
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      found_key_to_remove = true;
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!found_key_to_remove) {
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // 2. Find the least important id we can remove.
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (TabIdList::reverse_iterator riter = visible_ids_.rbegin();
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         riter != visible_ids_.rend();
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)         riter++) {
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (cache_.Get(*riter)) {
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        key_to_remove = *riter;
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        found_key_to_remove = true;
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (found_key_to_remove)
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cache_.Remove(key_to_remove);
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::RemoveFromReadQueue(TabId tab_id) {
4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TabIdList::iterator read_iter =
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::find(read_queue_.begin(), read_queue_.end(), tab_id);
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (read_iter != read_queue_.end())
4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    read_queue_.erase(read_iter);
4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::InvalidateCachedThumbnail(Thumbnail* thumbnail) {
4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(thumbnail);
4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TabId tab_id = thumbnail->tab_id();
4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  cc::UIResourceId uid = thumbnail->ui_resource_id();
4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Thumbnail* cached_thumbnail = cache_.Get(tab_id);
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (cached_thumbnail && cached_thumbnail->ui_resource_id() == uid)
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cache_.Remove(tab_id);
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  cached_thumbnail = approximation_cache_.Get(tab_id);
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (cached_thumbnail && cached_thumbnail->ui_resource_id() == uid)
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    approximation_cache_.Remove(tab_id);
4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)base::FilePath ThumbnailStore::GetFilePath(TabId tab_id) const {
4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return disk_cache_path_.Append(base::IntToString(tab_id));
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
49003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace {
49103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
49203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool WriteToFile(base::File& file,
49303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 const gfx::Size& content_size,
49403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 const float scale,
49503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                 skia::RefPtr<SkPixelRef> compressed_data) {
49603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!file.IsValid())
49703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
49803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
49903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!WriteBigEndianToFile(file, kCompressedKey))
50003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
50103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
50203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!WriteBigEndianToFile(file, content_size.width()))
50303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
50403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
50503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!WriteBigEndianToFile(file, content_size.height()))
50603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Write ETC1 header.
50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  compressed_data->lockPixels();
51003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
51103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  unsigned char etc1_buffer[ETC_PKM_HEADER_SIZE];
51203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  etc1_pkm_format_header(etc1_buffer,
51303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         compressed_data->info().width(),
51403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         compressed_data->info().height());
51503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
51603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int header_bytes_written = file.WriteAtCurrentPos(
51703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      reinterpret_cast<char*>(etc1_buffer), ETC_PKM_HEADER_SIZE);
51803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (header_bytes_written != ETC_PKM_HEADER_SIZE)
51903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
52003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
52103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int data_size = etc1_get_encoded_data_size(
52203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      compressed_data->info().width(),
52303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      compressed_data->info().height());
52403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int pixel_bytes_written = file.WriteAtCurrentPos(
52503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      reinterpret_cast<char*>(compressed_data->pixels()),
52603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      data_size);
52703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (pixel_bytes_written != data_size)
52803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
52903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
53003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  compressed_data->unlockPixels();
53103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
53203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!WriteBigEndianToFile(file, kCurrentExtraVersion))
53303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
53403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
53503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!WriteBigEndianFloatToFile(file, 1.f / scale))
53603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
53703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
53803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
53903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
54003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
54103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}  // anonymous namespace
54203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::WriteTask(const base::FilePath& file_path,
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               skia::RefPtr<SkPixelRef> compressed_data,
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               float scale,
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               const gfx::Size& content_size,
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               const base::Callback<void()>& post_write_task) {
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(compressed_data);
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::File file(file_path,
5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  bool success = WriteToFile(file,
55403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                             content_size,
55503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                             scale,
55603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                             compressed_data);
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  file.Close();
5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!success)
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::DeleteFile(file_path, false);
5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::PostTask(
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserThread::UI, FROM_HERE, post_write_task);
5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::PostWriteTask() {
5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  write_tasks_count_--;
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::CompressionTask(
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SkBitmap raw_data,
5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::Size encoded_size,
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Callback<void(skia::RefPtr<SkPixelRef>, const gfx::Size&)>&
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        post_compression_task) {
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  skia::RefPtr<SkPixelRef> compressed_data;
5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Size content_size;
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!raw_data.empty()) {
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SkAutoLockPixels raw_data_lock(raw_data);
5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    gfx::Size raw_data_size(raw_data.width(), raw_data.height());
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t pixel_size = 4;  // Pixel size is 4 bytes for kARGB_8888_Config.
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t stride = pixel_size * raw_data_size.width();
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t encoded_bytes =
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        etc1_get_encoded_data_size(encoded_size.width(), encoded_size.height());
5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SkImageInfo info = SkImageInfo::Make(encoded_size.width(),
5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         encoded_size.height(),
5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         kUnknown_SkColorType,
5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                         kUnpremul_SkAlphaType);
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    skia::RefPtr<SkData> etc1_pixel_data = skia::AdoptRef(
5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        SkData::NewUninitialized(encoded_bytes));
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    skia::RefPtr<SkMallocPixelRef> etc1_pixel_ref = skia::AdoptRef(
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        SkMallocPixelRef::NewWithData(info, 0, NULL, etc1_pixel_data.get()));
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    etc1_pixel_ref->lockPixels();
5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool success = etc1_encode_image(
5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        reinterpret_cast<unsigned char*>(raw_data.getPixels()),
5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        raw_data_size.width(),
6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        raw_data_size.height(),
6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        pixel_size,
6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        stride,
6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        reinterpret_cast<unsigned char*>(etc1_pixel_ref->pixels()),
6045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        encoded_size.width(),
6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        encoded_size.height());
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    etc1_pixel_ref->setImmutable();
6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    etc1_pixel_ref->unlockPixels();
6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (success) {
6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      compressed_data = etc1_pixel_ref;
6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content_size = raw_data_size;
6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  content::BrowserThread::PostTask(
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      content::BrowserThread::UI,
6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FROM_HERE,
6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(post_compression_task, compressed_data, content_size));
6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::PostCompressionTask(
6225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TabId tab_id,
6235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Time& time_stamp,
6245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    float scale,
6255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    skia::RefPtr<SkPixelRef> compressed_data,
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const gfx::Size& content_size) {
6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  compression_tasks_count_--;
6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!compressed_data) {
6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RemoveOnMatchedTimeStamp(tab_id, time_stamp);
6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Thumbnail* thumbnail = cache_.Get(tab_id);
6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (thumbnail) {
6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (thumbnail->time_stamp() != time_stamp)
6365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
6375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    thumbnail->SetCompressedBitmap(compressed_data, content_size);
6385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    thumbnail->CreateUIResource();
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  WriteThumbnailIfNecessary(tab_id, compressed_data, scale, content_size);
6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
64303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace {
64403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
64503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ReadFromFile(base::File& file,
64603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                  gfx::Size* out_content_size,
64703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                  float* out_scale,
64803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                  skia::RefPtr<SkPixelRef>* out_pixels) {
64903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!file.IsValid())
65003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
65103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
65203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int key = 0;
65303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!ReadBigEndianFromFile(file, &key))
65403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
65503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
65603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (key != kCompressedKey)
65703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
65803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
65903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int content_width = 0;
66003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!ReadBigEndianFromFile(file, &content_width) || content_width <= 0)
66103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
66203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
66303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int content_height = 0;
66403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!ReadBigEndianFromFile(file, &content_height) || content_height <= 0)
66503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
66603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
66703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  out_content_size->SetSize(content_width, content_height);
66803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
66903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Read ETC1 header.
67003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int header_bytes_read = 0;
67103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  unsigned char etc1_buffer[ETC_PKM_HEADER_SIZE];
67203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  header_bytes_read = file.ReadAtCurrentPos(
67303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      reinterpret_cast<char*>(etc1_buffer),
67403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      ETC_PKM_HEADER_SIZE);
67503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (header_bytes_read != ETC_PKM_HEADER_SIZE)
67603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
67703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
67803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!etc1_pkm_is_valid(etc1_buffer))
67903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
68003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
68103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int raw_width = 0;
68203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  raw_width = etc1_pkm_get_width(etc1_buffer);
68303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (raw_width <= 0)
68403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
68503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
68603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int raw_height = 0;
68703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  raw_height = etc1_pkm_get_height(etc1_buffer);
68803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (raw_height <= 0)
68903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
69003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
69103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Do some simple sanity check validation.  We can't have thumbnails larger
69203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // than the max display size of the screen.  We also can't have etc1 texture
69303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // data larger than the next power of 2 up from that.
69403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  gfx::DeviceDisplayInfo display_info;
69503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int max_dimension = std::max(display_info.GetDisplayWidth(),
69603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                               display_info.GetDisplayHeight());
69703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
69803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (content_width > max_dimension
69903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      || content_height > max_dimension
70003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      || static_cast<size_t>(raw_width) > NextPowerOfTwo(max_dimension)
70103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      || static_cast<size_t>(raw_height) > NextPowerOfTwo(max_dimension)) {
70203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
70303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
70403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
70503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int data_size = etc1_get_encoded_data_size(raw_width, raw_height);
7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  skia::RefPtr<SkData> etc1_pixel_data =
7071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      skia::AdoptRef(SkData::NewUninitialized(data_size));
70803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
70903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int pixel_bytes_read = file.ReadAtCurrentPos(
7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      reinterpret_cast<char*>(etc1_pixel_data->writable_data()),
71103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      data_size);
71203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
71303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (pixel_bytes_read != data_size)
71403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
71503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkImageInfo info = SkImageInfo::Make(raw_width,
7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       raw_height,
7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       kUnknown_SkColorType,
7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                       kUnpremul_SkAlphaType);
72003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
72103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  *out_pixels = skia::AdoptRef(
72203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      SkMallocPixelRef::NewWithData(info,
72303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                    0,
72403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                    NULL,
72503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                    etc1_pixel_data.get()));
72603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
72703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int extra_data_version = 0;
72803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!ReadBigEndianFromFile(file, &extra_data_version))
72903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return false;
73003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
73103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  *out_scale = 1.f;
73203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (extra_data_version == 1) {
73303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!ReadBigEndianFloatFromFile(file, out_scale))
73403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return false;
73503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
73603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (*out_scale == 0.f)
73703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      return false;
73803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
73903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    *out_scale = 1.f / *out_scale;
74003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
74103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
74203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return true;
74303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
74403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
74503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}// anonymous namespace
74603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::ReadTask(
7481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool decompress,
7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::FilePath& file_path,
7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Callback<
7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        void(skia::RefPtr<SkPixelRef>, float, const gfx::Size&)>&
7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        post_read_task) {
7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Size content_size;
75403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  float scale = 0.f;
75503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  skia::RefPtr<SkPixelRef> compressed_data;
7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (base::PathExists(file_path)) {
7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
76103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    bool valid_contents = ReadFromFile(file,
76203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                       &content_size,
76303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                       &scale,
76403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                       &compressed_data);
7655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    file.Close();
7665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
76703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (!valid_contents) {
76803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      content_size.SetSize(0, 0);
76903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            scale = 0.f;
77003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            compressed_data.clear();
77103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            base::DeleteFile(file_path, false);
7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (decompress) {
7761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::WorkerPool::PostTask(
7771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
7781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(post_read_task, compressed_data, scale, content_size),
7791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        true);
7801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
7811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    content::BrowserThread::PostTask(
7821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        content::BrowserThread::UI,
7831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
7841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(post_read_task, compressed_data, scale, content_size));
7851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::PostReadTask(TabId tab_id,
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  skia::RefPtr<SkPixelRef> compressed_data,
7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  float scale,
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                  const gfx::Size& content_size) {
7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  read_in_progress_ = false;
7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TabIdList::iterator iter =
7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      std::find(read_queue_.begin(), read_queue_.end(), tab_id);
7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (iter == read_queue_.end()) {
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ReadNextThumbnail();
7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  read_queue_.erase(iter);
8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!cache_.Get(tab_id) && compressed_data) {
8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ThumbnailMetaDataMap::iterator meta_iter =
8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        thumbnail_meta_data_.find(tab_id);
8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::Time time_stamp = base::Time::Now();
8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (meta_iter != thumbnail_meta_data_.end())
8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      time_stamp = meta_iter->second.capture_time();
8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    MakeSpaceForNewItemIfNecessary(tab_id);
8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<Thumbnail> thumbnail = Thumbnail::Create(
8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        tab_id, time_stamp, scale, ui_resource_provider_, this);
8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    thumbnail->SetCompressedBitmap(compressed_data,
8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   content_size);
8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (kPreferCPUMemory)
8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      thumbnail->CreateUIResource();
8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    cache_.Put(tab_id, thumbnail.Pass());
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NotifyObserversOfThumbnailRead(tab_id);
8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ReadNextThumbnail();
8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::NotifyObserversOfThumbnailRead(TabId tab_id) {
8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  FOR_EACH_OBSERVER(
8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ThumbnailStoreObserver, observers_, OnFinishedThumbnailRead(tab_id));
8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ThumbnailStore::RemoveOnMatchedTimeStamp(TabId tab_id,
8315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                              const base::Time& time_stamp) {
8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // We remove the cached version if it matches the tab_id and the time_stamp.
8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Thumbnail* thumbnail = cache_.Get(tab_id);
8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Thumbnail* approx_thumbnail = approximation_cache_.Get(tab_id);
8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if ((thumbnail && thumbnail->time_stamp() == time_stamp) ||
8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (approx_thumbnail && approx_thumbnail->time_stamp() == time_stamp)) {
8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Remove(tab_id);
8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return;
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
8421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ThumbnailStore::DecompressionTask(
8431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::Callback<void(bool, SkBitmap)>&
8441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        post_decompression_callback,
8451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    skia::RefPtr<SkPixelRef> compressed_data,
8461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    float scale,
8471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const gfx::Size& content_size) {
8481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SkBitmap raw_data_small;
8491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool success = false;
8501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (compressed_data.get()) {
8521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    gfx::Size buffer_size = gfx::Size(compressed_data->info().width(),
8531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                      compressed_data->info().height());
8541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SkBitmap raw_data;
8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    raw_data.allocPixels(SkImageInfo::Make(buffer_size.width(),
8571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           buffer_size.height(),
8581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           kRGBA_8888_SkColorType,
8591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                           kOpaque_SkAlphaType));
8601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SkAutoLockPixels raw_data_lock(raw_data);
8611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    compressed_data->lockPixels();
8621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    success = etc1_decode_image(
8631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        reinterpret_cast<unsigned char*>(compressed_data->pixels()),
8641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        reinterpret_cast<unsigned char*>(raw_data.getPixels()),
8651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        buffer_size.width(),
8661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        buffer_size.height(),
8671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        raw_data.bytesPerPixel(),
8681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        raw_data.rowBytes());
8691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    compressed_data->unlockPixels();
8701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    raw_data.setImmutable();
8711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!success) {
8731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Leave raw_data_small empty for consistency with other failure modes.
8741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else if (content_size == buffer_size) {
8751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Shallow copy the pixel reference.
8761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      raw_data_small = raw_data;
8771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
8781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // The content size is smaller than the buffer size (likely because of
8791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // a power-of-two rounding), so deep copy the bitmap.
8801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      raw_data_small.allocPixels(SkImageInfo::Make(content_size.width(),
8811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                   content_size.height(),
8821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                   kRGBA_8888_SkColorType,
8831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                   kOpaque_SkAlphaType));
8841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SkAutoLockPixels raw_data_small_lock(raw_data_small);
8851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      SkCanvas small_canvas(raw_data_small);
8861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      small_canvas.drawBitmap(raw_data, 0, 0);
8871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      raw_data_small.setImmutable();
8881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
8891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
8901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  content::BrowserThread::PostTask(
8921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::BrowserThread::UI,
8931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      FROM_HERE,
8941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(post_decompression_callback, success, raw_data_small));
8951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
8961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ThumbnailStore::ThumbnailMetaData::ThumbnailMetaData() {
8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ThumbnailStore::ThumbnailMetaData::ThumbnailMetaData(
9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Time& current_time,
9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const GURL& url)
9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : capture_time_(current_time), url_(url) {
9045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
9055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)std::pair<SkBitmap, float> ThumbnailStore::CreateApproximation(
9075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SkBitmap& bitmap,
9085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    float scale) {
9095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!bitmap.empty());
9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_GT(scale, 0);
9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SkAutoLockPixels bitmap_lock(bitmap);
9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  float new_scale = 1.f / kApproximationScaleFactor;
9135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  gfx::Size dst_size = gfx::ToFlooredSize(
9155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      gfx::ScaleSize(gfx::Size(bitmap.width(), bitmap.height()), new_scale));
9165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SkBitmap dst_bitmap;
9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  dst_bitmap.allocPixels(SkImageInfo::Make(dst_size.width(),
9185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                           dst_size.height(),
9195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                           bitmap.info().fColorType,
9205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                           bitmap.info().fAlphaType));
9215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  dst_bitmap.eraseColor(0);
9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SkAutoLockPixels dst_bitmap_lock(dst_bitmap);
9235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SkCanvas canvas(dst_bitmap);
9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  canvas.scale(new_scale, new_scale);
9265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  canvas.drawBitmap(bitmap, 0, 0, NULL);
9275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  dst_bitmap.setImmutable();
9285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return std::make_pair(dst_bitmap, new_scale * scale);
9305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
931