summaryrefslogtreecommitdiffstats
path: root/components/suggestions/image_manager.h
blob: b3fd15ee3939666881c40e2c360f6321e56b2aaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// 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 COMPONENTS_SUGGESTIONS_IMAGE_MANAGER_H_
#define COMPONENTS_SUGGESTIONS_IMAGE_MANAGER_H_

#include <map>
#include <string>
#include <vector>

#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task_runner.h"
#include "base/threading/thread_checker.h"
#include "components/leveldb_proto/proto_database.h"
#include "components/suggestions/image_fetcher_delegate.h"
#include "components/suggestions/proto/suggestions.pb.h"
#include "ui/gfx/image/image_skia.h"
#include "url/gurl.h"

namespace net {
class URLRequestContextGetter;
}

namespace suggestions {

class ImageData;
class ImageFetcher;
class SuggestionsProfile;

// A class used to fetch server images asynchronously and manage the caching
// layer (both in memory and on disk).
class ImageManager : public ImageFetcherDelegate {
 public:
  typedef std::vector<ImageData> ImageDataVector;

  ImageManager(scoped_ptr<ImageFetcher> image_fetcher,
               scoped_ptr<leveldb_proto::ProtoDatabase<ImageData>> database,
               const base::FilePath& database_dir,
               scoped_refptr<base::TaskRunner> background_task_runner);
  ~ImageManager() override;

  virtual void Initialize(const SuggestionsProfile& suggestions);

  // Should be called from the UI thread.
  virtual void AddImageURL(const GURL& url, const GURL& image_url);

  // Should be called from the UI thread.
  virtual void GetImageForURL(
      const GURL& url,
      base::Callback<void(const GURL&, const SkBitmap*)> callback);

 protected:
  // Perform additional tasks when an image has been fetched.
  void OnImageFetched(const GURL& url, const SkBitmap* bitmap) override;

 private:
  friend class MockImageManager;
  friend class ImageManagerTest;
  FRIEND_TEST_ALL_PREFIXES(ImageManagerTest, InitializeTest);
  FRIEND_TEST_ALL_PREFIXES(ImageManagerTest, AddImageURL);
  FRIEND_TEST_ALL_PREFIXES(ImageManagerTest, GetImageForURLNetworkCacheHit);
  FRIEND_TEST_ALL_PREFIXES(ImageManagerTest,
                           GetImageForURLNetworkCacheNotInitialized);

  // Used for testing.
  ImageManager();

  typedef std::vector<base::Callback<void(const GURL&, const SkBitmap*)> >
      CallbackVector;
  typedef base::hash_map<std::string, scoped_refptr<base::RefCountedMemory>>
      ImageMap;

  // State related to an image fetch (associated website url, image_url,
  // pending callbacks).
  struct ImageCacheRequest {
    ImageCacheRequest();
    ImageCacheRequest(const ImageCacheRequest& other);
    ~ImageCacheRequest();

    GURL url;
    GURL image_url;
    // Queue for pending callbacks, which may accumulate while the request is in
    // flight.
    CallbackVector callbacks;
  };

  typedef std::map<const GURL, ImageCacheRequest> ImageCacheRequestMap;

  // Looks up image URL for |url|. If found, writes the result to |image_url|
  // and returns true. Otherwise just returns false.
  bool GetImageURL(const GURL& url, GURL* image_url);

  void QueueCacheRequest(
      const GURL& url, const GURL& image_url,
      base::Callback<void(const GURL&, const SkBitmap*)> callback);

  void ServeFromCacheOrNetwork(
      const GURL& url, const GURL& image_url,
      base::Callback<void(const GURL&, const SkBitmap*)> callback);

  void OnCacheImageDecoded(
      const GURL& url,
      const GURL& image_url,
      base::Callback<void(const GURL&, const SkBitmap*)> callback,
      scoped_ptr<SkBitmap> bitmap);

  // Returns null if the |url| had no entry in the cache.
  scoped_refptr<base::RefCountedMemory> GetEncodedImageFromCache(
      const GURL& url);

  // Save the image bitmap in the cache and in the database.
  void SaveImage(const GURL& url, const SkBitmap& bitmap);

  // Database callback methods.
  // Will initiate loading the entries.
  void OnDatabaseInit(bool success);
  // Will transfer the loaded |entries| in memory (|image_map_|).
  void OnDatabaseLoad(bool success, scoped_ptr<ImageDataVector> entries);
  void OnDatabaseSave(bool success);

  // Take entries from the database and put them in the local cache.
  void LoadEntriesInCache(scoped_ptr<ImageDataVector> entries);

  void ServePendingCacheRequests();

  // Map from URL to image URL. Should be kept up to date when a new
  // SuggestionsProfile is available.
  std::map<GURL, GURL> image_url_map_;

  // Map from website URL to request information, used for pending cache
  // requests while the database hasn't loaded.
  ImageCacheRequestMap pending_cache_requests_;

  // Holding the bitmaps in memory, keyed by website URL string.
  ImageMap image_map_;

  scoped_ptr<ImageFetcher> image_fetcher_;

  scoped_ptr<leveldb_proto::ProtoDatabase<ImageData> > database_;

  scoped_refptr<base::TaskRunner> background_task_runner_;

  bool database_ready_;

  base::ThreadChecker thread_checker_;

  base::WeakPtrFactory<ImageManager> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(ImageManager);
};

}  // namespace suggestions

#endif  // COMPONENTS_SUGGESTIONS_IMAGE_MANAGER_H_