Home | History | Annotate | Download | only in suggestions
      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 
     76     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