• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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