1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_SEARCH_SUGGESTIONS_IMAGE_MANAGER_IMPL_H_ 6 #define CHROME_BROWSER_SEARCH_SUGGESTIONS_IMAGE_MANAGER_IMPL_H_ 7 8 #include <map> 9 #include <utility> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/callback.h" 14 #include "base/containers/hash_tables.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/weak_ptr.h" 17 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" 18 #include "components/leveldb_proto/proto_database.h" 19 #include "components/suggestions/image_manager.h" 20 #include "components/suggestions/proto/suggestions.pb.h" 21 #include "ui/gfx/image/image_skia.h" 22 #include "url/gurl.h" 23 24 namespace net { 25 class URLRequestContextGetter; 26 } 27 28 namespace suggestions { 29 30 class ImageData; 31 class SuggestionsProfile; 32 33 // A class used to fetch server images asynchronously and manage the caching 34 // layer (both in memory and on disk). 35 class ImageManagerImpl : public ImageManager, 36 public chrome::BitmapFetcherDelegate { 37 public: 38 typedef std::vector<ImageData> ImageDataVector; 39 40 ImageManagerImpl( 41 net::URLRequestContextGetter* url_request_context, 42 scoped_ptr<leveldb_proto::ProtoDatabase<ImageData> > database, 43 const base::FilePath& database_dir); 44 virtual ~ImageManagerImpl(); 45 46 // Overrides from ImageManager. 47 virtual void Initialize(const SuggestionsProfile& suggestions) OVERRIDE; 48 // Should be called from the UI thread. 49 virtual void GetImageForURL( 50 const GURL& url, 51 base::Callback<void(const GURL&, const SkBitmap*)> callback) OVERRIDE; 52 53 private: 54 friend class MockImageManagerImpl; 55 friend class ImageManagerImplBrowserTest; 56 FRIEND_TEST_ALL_PREFIXES(ImageManagerImplTest, InitializeTest); 57 FRIEND_TEST_ALL_PREFIXES(ImageManagerImplBrowserTest, 58 GetImageForURLNetworkCacheHit); 59 FRIEND_TEST_ALL_PREFIXES(ImageManagerImplBrowserTest, 60 GetImageForURLNetworkCacheNotInitialized); 61 62 // Used for testing. 63 ImageManagerImpl(); 64 65 typedef std::vector<base::Callback<void(const GURL&, const SkBitmap*)> > 66 CallbackVector; 67 typedef base::hash_map<std::string, SkBitmap> ImageMap; 68 69 // State related to an image fetch (associated website url, image_url, 70 // fetcher, pending callbacks). 71 struct ImageRequest { 72 ImageRequest(); 73 explicit ImageRequest(chrome::BitmapFetcher* f); 74 ~ImageRequest(); 75 swapImageRequest76 void swap(ImageRequest* other) { 77 std::swap(url, other->url); 78 std::swap(image_url, other->image_url); 79 std::swap(callbacks, other->callbacks); 80 std::swap(fetcher, other->fetcher); 81 } 82 83 GURL url; 84 GURL image_url; 85 chrome::BitmapFetcher* fetcher; 86 // Queue for pending callbacks, which may accumulate while the request is in 87 // flight. 88 CallbackVector callbacks; 89 }; 90 91 typedef std::map<const GURL, ImageRequest> ImageRequestMap; 92 93 // Looks up image URL for |url|. If found, writes the result to |image_url| 94 // and returns true. Otherwise just returns false. 95 bool GetImageURL(const GURL& url, GURL* image_url); 96 97 void QueueCacheRequest( 98 const GURL& url, const GURL& image_url, 99 base::Callback<void(const GURL&, const SkBitmap*)> callback); 100 101 void ServeFromCacheOrNetwork( 102 const GURL& url, const GURL& image_url, 103 base::Callback<void(const GURL&, const SkBitmap*)> callback); 104 105 // Will return false if no bitmap was found corresponding to |url|, else 106 // return true and call |callback| with the found bitmap. 107 bool ServeFromCache( 108 const GURL& url, 109 base::Callback<void(const GURL&, const SkBitmap*)> callback); 110 111 // Returns null if the |url| had no entry in the cache. 112 SkBitmap* GetBitmapFromCache(const GURL& url); 113 114 void StartOrQueueNetworkRequest( 115 const GURL& url, const GURL& image_url, 116 base::Callback<void(const GURL&, const SkBitmap*)> callback); 117 118 // Inherited from BitmapFetcherDelegate. Runs on the UI thread. 119 virtual void OnFetchComplete(const GURL image_url, 120 const SkBitmap* bitmap) OVERRIDE; 121 122 // Save the image bitmap in the cache and in the database. 123 void SaveImage(const GURL& url, const SkBitmap& bitmap); 124 125 // Database callback methods. 126 // Will initiate loading the entries. 127 void OnDatabaseInit(bool success); 128 // Will transfer the loaded |entries| in memory (|image_map_|). 129 void OnDatabaseLoad(bool success, scoped_ptr<ImageDataVector> entries); 130 void OnDatabaseSave(bool success); 131 132 // Take entries from the database and put them in the local cache. 133 void LoadEntriesInCache(scoped_ptr<ImageDataVector> entries); 134 135 void ServePendingCacheRequests(); 136 137 // From SkBitmap to the vector of JPEG-encoded bytes, |dst|. Visible only for 138 // testing. 139 static bool EncodeImage(const SkBitmap& bitmap, 140 std::vector<unsigned char>* dest); 141 142 // Map from URL to image URL. Should be kept up to date when a new 143 // SuggestionsProfile is available. 144 std::map<GURL, GURL> image_url_map_; 145 146 // Map from each image URL to the request information (associated website 147 // url, fetcher, pending callbacks). 148 ImageRequestMap pending_net_requests_; 149 150 // Map from website URL to request information, used for pending cache 151 // requests while the database hasn't loaded. 152 ImageRequestMap pending_cache_requests_; 153 154 // Holding the bitmaps in memory, keyed by website URL string. 155 ImageMap image_map_; 156 157 net::URLRequestContextGetter* url_request_context_; 158 159 scoped_ptr<leveldb_proto::ProtoDatabase<ImageData> > database_; 160 161 bool database_ready_; 162 163 base::WeakPtrFactory<ImageManagerImpl> weak_ptr_factory_; 164 165 DISALLOW_COPY_AND_ASSIGN(ImageManagerImpl); 166 }; 167 168 } // namespace suggestions 169 170 #endif // CHROME_BROWSER_SEARCH_SUGGESTIONS_IMAGE_MANAGER_IMPL_H_ 171