| Index: chrome/browser/android/thumbnail_cache.h
|
| diff --git a/chrome/browser/android/thumbnail_cache.h b/chrome/browser/android/thumbnail_cache.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a1b45b134bdb1e776596108a8194035d88d2c968
|
| --- /dev/null
|
| +++ b/chrome/browser/android/thumbnail_cache.h
|
| @@ -0,0 +1,371 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef CHROME_BROWSER_ANDROID_THUMBNAIL_CACHE_H_
|
| +#define CHROME_BROWSER_ANDROID_THUMBNAIL_CACHE_H_
|
| +
|
| +#include <list>
|
| +#include <set>
|
| +#include <string>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/containers/hash_tables.h"
|
| +#include "base/files/file_path.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/threading/thread.h"
|
| +#include "base/time/time.h"
|
| +#include "content/public/browser/android/ui_resource_listener.h"
|
| +#include "content/public/browser/android/ui_resource_provider.h"
|
| +#include "net/base/linked_hash_map.h"
|
| +#include "skia/ext/refptr.h"
|
| +#include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/gfx/geometry/point.h"
|
| +#include "ui/gfx/geometry/size.h"
|
| +#include "ui/gfx/geometry/size_f.h"
|
| +#include "url/gurl.h"
|
| +
|
| +class SkBitmap;
|
| +class TabThumbnailProvider;
|
| +
|
| +namespace base {
|
| +class File;
|
| +class Time;
|
| +}
|
| +
|
| +namespace content {
|
| +class ContentViewCore;
|
| +class UIResourceProvider;
|
| +}
|
| +
|
| +typedef int TabId;
|
| +typedef std::list<TabId> TabIdList;
|
| +
|
| +class ThumbnailChangeListener {
|
| + public:
|
| + virtual void OnThumbnailChanged(TabId tab_id, bool upgrade) = 0;
|
| + virtual void OnUIResourceUpdated(TabId tab_id,
|
| + cc::UIResourceId ui_resource_id,
|
| + gfx::Size content_size,
|
| + gfx::SizeF scaled_thumbnail_size) = 0;
|
| +};
|
| +
|
| +class ThumbnailCache : public content::UIResourceListener {
|
| + private:
|
| + class Thumbnail : public base::RefCountedThreadSafe<Thumbnail> {
|
| + public:
|
| + enum ThumbnailFormat { DECOMPRESSED, COMPRESSED };
|
| +
|
| + // This constructs a placeholder for the thumbnail. The content is filled
|
| + // by calling ReadThumbnailFromFile.
|
| + Thumbnail(TabId tab_id, content::UIResourceProvider* ui_resource_provider);
|
| +
|
| + Thumbnail(TabId tab_id,
|
| + SkBitmap bitmap,
|
| + float scale,
|
| + content::UIResourceProvider* ui_resource_provider);
|
| + Thumbnail(const Thumbnail& thumbnail);
|
| + void CleanupThumbnail();
|
| + bool AttemptToScheduleRebuildFromData();
|
| + void CleanupCPUData(bool force);
|
| + bool RebuildThumbnail();
|
| + bool CompressionRequired() const;
|
| + bool DataWriteRequired() const;
|
| + bool HasCompressedRawData() const;
|
| + bool IsValid() const;
|
| +
|
| + // Returns the size of the content represented by this thumbnail.
|
| + gfx::Size GetContentSize() const;
|
| +
|
| + TabId tab_id() const { return tab_id_; }
|
| + cc::UIResourceId ui_resource_id() const { return ui_resource_id_; }
|
| +
|
| + // The ratio of the size of the thumbnail to the content size.
|
| + float scale() const { return scale_; }
|
| +
|
| + // Returns the size of the data (pixels) held by this thumbnail. Can be the
|
| + // size of the uncompressed or compressed data.
|
| + gfx::Size data_size() const { return data_size_; }
|
| +
|
| + virtual bool is_approximation() const { return false; }
|
| +
|
| + // Called on the compression thread.
|
| + void Compress();
|
| + // Called on the disk thread. Returns true if writing was successful.
|
| + bool WriteThumbnailToFile(base::File& file);
|
| + // Called on the disk thread. Returns true if reading was successful.
|
| + bool ReadThumbnailFromFile(base::File& file);
|
| +
|
| + // We invalidate the thumbnail content if a read/write/compress has failed.
|
| + void Invalidate();
|
| +
|
| + SkBitmap raw_data() { return raw_data_; }
|
| +
|
| + protected:
|
| + friend class base::RefCountedThreadSafe<Thumbnail>;
|
| + ~Thumbnail();
|
| +
|
| + private:
|
| + void SetRawThumbnailData(SkBitmap bitmap);
|
| + void SetCompressedThumbnailData(skia::RefPtr<SkPixelRef> compressed_data,
|
| + gfx::Size scaled_content_size);
|
| + bool CleanupRequired();
|
| +
|
| + TabId tab_id_;
|
| + SkBitmap raw_data_;
|
| + float scale_;
|
| + content::UIResourceProvider* ui_resource_provider_;
|
| + cc::UIResourceId ui_resource_id_;
|
| + skia::RefPtr<SkPixelRef> compressed_data_;
|
| + gfx::Size data_size_;
|
| + gfx::Size scaled_content_size_;
|
| + ThumbnailFormat format_;
|
| + bool rebuild_pending_;
|
| + bool data_write_pending_;
|
| + bool from_stream_;
|
| + };
|
| +
|
| + class ApproxThumbnail : public Thumbnail {
|
| + public:
|
| + ApproxThumbnail(TabId tab_id,
|
| + SkBitmap bitmap,
|
| + float scale,
|
| + content::UIResourceProvider* ui_resource_provider);
|
| +
|
| + virtual bool is_approximation() const OVERRIDE { return true; }
|
| + };
|
| +
|
| + class ThumbnailBitmap {
|
| + public:
|
| + ThumbnailBitmap();
|
| + ThumbnailBitmap(SkBitmap bitmap, float scale);
|
| + bool IsValid() const;
|
| + SkBitmap bitmap() const { return bitmap_; }
|
| + float scale() const { return scale_; }
|
| + ThumbnailBitmap CreateApproximation() const;
|
| +
|
| + private:
|
| + SkBitmap bitmap_;
|
| + float scale_;
|
| + };
|
| +
|
| + class ThumbnailMetaData {
|
| + public:
|
| + ThumbnailMetaData();
|
| + ThumbnailMetaData(const base::Time& current_time, const GURL& url);
|
| + const GURL& url() const { return url_; }
|
| + base::Time capture_time() const { return capture_time_; }
|
| +
|
| + private:
|
| + base::Time capture_time_;
|
| + GURL url_;
|
| + };
|
| +
|
| + class TabReadbackRequest : public base::RefCounted<TabReadbackRequest> {
|
| + public:
|
| + TabReadbackRequest(
|
| + TabId tab_id,
|
| + content::ContentViewCore* content_view_core,
|
| + float thumbnail_scale,
|
| + base::Callback<void(int, const ThumbnailBitmap&)> end_callback);
|
| +
|
| + bool drop_after_readback() const { return drop_after_readback_; }
|
| +
|
| + void Run();
|
| + void OnFinishGetTabThumbnailBitmap(bool success, const SkBitmap& bitmap);
|
| + void SetDropAfterReadback(bool flag) { drop_after_readback_ = flag; }
|
| +
|
| + private:
|
| + TabId tab_id_;
|
| + content::ContentViewCore* content_view_core_;
|
| + const float thumbnail_scale_;
|
| + base::Callback<void(int, const ThumbnailBitmap&)> end_callback_;
|
| + bool drop_after_readback_;
|
| +
|
| + base::WeakPtrFactory<TabReadbackRequest> weak_factory_;
|
| + };
|
| +
|
| + template <class Key, class Value>
|
| + class LRUExpiringCache {
|
| + private:
|
| + typedef linked_hash_map<Key, Value> LinkedHashMap;
|
| +
|
| + public:
|
| + typedef typename LinkedHashMap::iterator iterator;
|
| + typedef typename LinkedHashMap::const_iterator const_iterator;
|
| +
|
| + explicit LRUExpiringCache(size_t max_cache_size)
|
| + : max_cache_size_(max_cache_size) {}
|
| +
|
| + void Put(const Key& key, const Value& value) {
|
| + map_[key] = value;
|
| + EvictIfFull();
|
| + }
|
| +
|
| + Value Get(const Key& key) {
|
| + iterator iter = map_.find(key);
|
| + if (iter != map_.end())
|
| + return iter->second;
|
| + return Value();
|
| + }
|
| +
|
| + bool Contains(const Key& key) const {
|
| + const_iterator iter = map_.find(key);
|
| + return iter != map_.end();
|
| + }
|
| +
|
| + Value Remove(const Key& key) {
|
| + Value val = Get(key);
|
| + map_.erase(key);
|
| + return val;
|
| + }
|
| +
|
| + iterator begin() { return map_.begin(); }
|
| + iterator end() { return map_.end(); }
|
| + size_t MaximumCacheSize() const { return max_cache_size_; }
|
| + size_t size() const { return map_.size(); }
|
| +
|
| + private:
|
| + void EvictIfFull() {
|
| + while (map_.size() > max_cache_size_) {
|
| + iterator it = map_.begin();
|
| + map_.erase(it);
|
| + }
|
| + }
|
| +
|
| + size_t max_cache_size_;
|
| + LinkedHashMap map_;
|
| + };
|
| +
|
| + typedef LRUExpiringCache<TabId, scoped_refptr<Thumbnail> >
|
| + ExpiringThumbnailCache;
|
| + typedef std::set<ThumbnailChangeListener*> ThumbnailChangeListenerSet;
|
| + typedef base::hash_map<TabId, scoped_refptr<TabReadbackRequest> >
|
| + TabReadbackRequestMap;
|
| + typedef base::hash_map<TabId, ThumbnailMetaData> ThumbnailMetaDataMap;
|
| + typedef std::list<scoped_refptr<Thumbnail> > ThumbnailQueue;
|
| +
|
| + public:
|
| + ThumbnailCache(const std::string& disk_cache_path_str,
|
| + size_t default_cache_size,
|
| + size_t approximation_cache_size,
|
| + size_t compression_queue_max_size,
|
| + size_t write_queue_max_size,
|
| + bool use_approximation_thumbnails,
|
| + float thumbnail_scale);
|
| +
|
| + ~ThumbnailCache();
|
| +
|
| + void AddThumbnailChangeListener(ThumbnailChangeListener* listener);
|
| + void RemoveThumbnailChangeListener(ThumbnailChangeListener* listener);
|
| + void CacheTabThumbnail(const TabThumbnailProvider* tab);
|
| + void CacheTabThumbnailWithBitmap(const TabThumbnailProvider* tab,
|
| + const SkBitmap& bitmap,
|
| + float thumbnail_scale);
|
| + void HandleLowMemory(bool consider_gpu_memory);
|
| + void InvalidateIfChanged(const TabThumbnailProvider* tab);
|
| + void RemoveThumbnailsAndScheduleReload();
|
| + void CacheInTab(TabId tab_id);
|
| + void Remove(TabId tab_id);
|
| + void RemoveFromDiskAtAndAboveId(TabId min_id);
|
| + void RemoveFromDisk(TabId tab_id);
|
| + void UpdateVisibleIds(const TabIdList& last_visible_ids);
|
| + void ThumbnailRequested(TabId tab_id);
|
| + void SetUIResourceProvider(content::UIResourceProvider* ui_resource_provider);
|
| +
|
| + // Implements content::UIResourceListener.
|
| + virtual void OnUIResourcesAreInvalid() OVERRIDE;
|
| + virtual void OnRecreateUIResources() OVERRIDE;
|
| +
|
| + private:
|
| + // The task to run
|
| + static void CompressionTask(scoped_refptr<Thumbnail> thumbnail);
|
| +
|
| + void PostCompressionTask(scoped_refptr<Thumbnail> thumbnail);
|
| +
|
| + static void WriteTask(const base::FilePath& file_path,
|
| + scoped_refptr<Thumbnail> thumbnail);
|
| +
|
| + void PostWriteTask(scoped_refptr<Thumbnail> thumbnail);
|
| +
|
| + static void ReadTask(const base::FilePath& file_path,
|
| + scoped_refptr<Thumbnail> thumbnail);
|
| +
|
| + void PostReadTask(scoped_refptr<Thumbnail> thumbnail);
|
| +
|
| + static void RemoveFromDiskTask(const base::FilePath& file_path);
|
| + static void RemoveFromDiskAtAndAboveIdTask(const base::FilePath& dir_path,
|
| + TabId min_id);
|
| + scoped_refptr<Thumbnail> GetThumbnail(TabId tab_id);
|
| + scoped_refptr<Thumbnail> GetThumbnail(TabId tab_id, bool cache_in_if_missing);
|
| + void EndCacheTabThumbnail(TabId tab_id, const ThumbnailBitmap& bitmap);
|
| + bool CanReadTabContent(const TabThumbnailProvider* tab);
|
| + void PutThumbnail(TabId tab_id, const ThumbnailBitmap& thumbnail_bitmap);
|
| + void PutThumbnail(TabId tab_id,
|
| + const ThumbnailBitmap& thumbnail_bitmap,
|
| + scoped_refptr<Thumbnail> thumbnail);
|
| + bool CheckAndUpdateThumbnailMetaData(const TabThumbnailProvider* tab,
|
| + bool is_native_page);
|
| + void RemoveFromCache(ExpiringThumbnailCache& cache,
|
| + const std::list<TabId>& tab_ids);
|
| + size_t HandleLowMemoryOnQueue(ThumbnailQueue& queue,
|
| + bool consider_gpu_memory);
|
| + void RemoveFromQueues(TabId tab_id);
|
| + bool WriteThumbnailIfNecessary(scoped_refptr<Thumbnail> thumbnail);
|
| + bool CompressThumbnailIfNecessary(scoped_refptr<Thumbnail> thumbnail);
|
| + void WriteNextThumbnail();
|
| + bool RemoveDuplicateIdsFromQueueHelper(ThumbnailQueue& queue,
|
| + scoped_refptr<Thumbnail> thumbnail);
|
| + void ReadNextThumbnail(TabId id);
|
| + void ReadNextThumbnail();
|
| + void CompressNextThumbnail();
|
| + void RebuildThumbnail(scoped_refptr<Thumbnail> thumbnail,
|
| + bool force_cleanup_cpu_data);
|
| + bool ShouldCleanupThumbnail(scoped_refptr<Thumbnail> thumbnail,
|
| + const ExpiringThumbnailCache* forced_source);
|
| + void CleanupThumbnail(scoped_refptr<Thumbnail> thumbnail);
|
| + void CleanupThumbnail(scoped_refptr<Thumbnail> thumbnail,
|
| + const ExpiringThumbnailCache* forced_source);
|
| + void NotifyListenersOfThumbnailChange(TabId tab_id, bool upgrade);
|
| + void NotifyListenersOfUIResourceUpdate(TabId tab_id);
|
| + base::FilePath GetFilePath(TabId tab_id) const;
|
| + bool ThumbnailInputFileExists(TabId tab_id) const;
|
| + void RemoveCorruptThumbnailSource(TabId tab_id);
|
| + void MakeSpaceForNewItemIfNecessary(TabId tab_id);
|
| + void RemoveThumbnailFromCache();
|
| + void AddIdToVisibleIds(TabId tab_id);
|
| + void CleanupPersistentData();
|
| +
|
| + base::Time CurrentTime();
|
| +
|
| + content::UIResourceProvider* ui_resource_provider_;
|
| + const base::FilePath disk_cache_path_;
|
| + const size_t compression_queue_max_size_;
|
| + const size_t write_queue_max_size_;
|
| +
|
| + ExpiringThumbnailCache cache_;
|
| + ExpiringThumbnailCache approximation_cache_;
|
| + const bool use_approximation_thumbnails_;
|
| +
|
| + // All thumbnails are scaled by this value. This accounts for device's DPI
|
| + // (dots per inch).
|
| + const float thumbnail_scale_;
|
| +
|
| + ThumbnailChangeListenerSet thumbnail_change_listeners_;
|
| +
|
| + TabReadbackRequestMap pending_thumbnail_readbacks_;
|
| + ThumbnailMetaDataMap thumbnail_meta_data_;
|
| +
|
| + ThumbnailQueue compression_queue_;
|
| + ThumbnailQueue write_queue_;
|
| + TabIdList read_queue_;
|
| +
|
| + TabIdList last_visible_ids_;
|
| + TabIdList visible_ids_;
|
| +
|
| + base::Thread compression_thread_;
|
| +
|
| + base::WeakPtrFactory<ThumbnailCache> weak_factory_;
|
| +};
|
| +
|
| +#endif // CHROME_BROWSER_ANDROID_THUMBNAIL_CACHE_H_
|
|
|