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