OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/suggestions/image_manager.h" | 5 #include "components/suggestions/image_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" |
| 9 #include "base/task_runner_util.h" |
8 #include "components/suggestions/image_encoder.h" | 10 #include "components/suggestions/image_encoder.h" |
9 #include "components/suggestions/image_fetcher.h" | 11 #include "components/suggestions/image_fetcher.h" |
10 | 12 |
11 using leveldb_proto::ProtoDatabase; | 13 using leveldb_proto::ProtoDatabase; |
12 | 14 |
| 15 namespace { |
| 16 |
| 17 scoped_ptr<SkBitmap> DecodeImage( |
| 18 scoped_refptr<base::RefCountedMemory> encoded_data) { |
| 19 return scoped_ptr<SkBitmap>(suggestions::DecodeJPEGToSkBitmap( |
| 20 encoded_data->front(), encoded_data->size())); |
| 21 } |
| 22 |
| 23 } // namespace |
| 24 |
13 namespace suggestions { | 25 namespace suggestions { |
14 | 26 |
15 ImageManager::ImageManager() : weak_ptr_factory_(this) {} | 27 ImageManager::ImageManager() : weak_ptr_factory_(this) {} |
16 | 28 |
17 ImageManager::ImageManager(scoped_ptr<ImageFetcher> image_fetcher, | 29 ImageManager::ImageManager( |
18 scoped_ptr<ProtoDatabase<ImageData> > database, | 30 scoped_ptr<ImageFetcher> image_fetcher, |
19 const base::FilePath& database_dir) | 31 scoped_ptr<ProtoDatabase<ImageData>> database, |
| 32 const base::FilePath& database_dir, |
| 33 scoped_refptr<base::TaskRunner> background_task_runner) |
20 : image_fetcher_(image_fetcher.Pass()), | 34 : image_fetcher_(image_fetcher.Pass()), |
21 database_(database.Pass()), | 35 database_(database.Pass()), |
| 36 background_task_runner_(background_task_runner), |
22 database_ready_(false), | 37 database_ready_(false), |
23 weak_ptr_factory_(this) { | 38 weak_ptr_factory_(this) { |
24 image_fetcher_->SetImageFetcherDelegate(this); | 39 image_fetcher_->SetImageFetcherDelegate(this); |
25 database_->Init(database_dir, base::Bind(&ImageManager::OnDatabaseInit, | 40 database_->Init(database_dir, base::Bind(&ImageManager::OnDatabaseInit, |
26 weak_ptr_factory_.GetWeakPtr())); | 41 weak_ptr_factory_.GetWeakPtr())); |
27 } | 42 } |
28 | 43 |
29 ImageManager::~ImageManager() {} | 44 ImageManager::~ImageManager() {} |
30 | 45 |
31 ImageManager::ImageCacheRequest::ImageCacheRequest() {} | 46 ImageManager::ImageCacheRequest::ImageCacheRequest() {} |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 request.url = url; | 103 request.url = url; |
89 request.image_url = image_url; | 104 request.image_url = image_url; |
90 request.callbacks.push_back(callback); | 105 request.callbacks.push_back(callback); |
91 pending_cache_requests_[url] = request; | 106 pending_cache_requests_[url] = request; |
92 } else { | 107 } else { |
93 // Request already queued for this url. | 108 // Request already queued for this url. |
94 it->second.callbacks.push_back(callback); | 109 it->second.callbacks.push_back(callback); |
95 } | 110 } |
96 } | 111 } |
97 | 112 |
98 void ImageManager::ServeFromCacheOrNetwork( | 113 void ImageManager::OnCacheImageDecoded( |
99 const GURL& url, const GURL& image_url, | 114 const GURL& url, |
100 base::Callback<void(const GURL&, const SkBitmap*)> callback) { | 115 const GURL& image_url, |
101 // If there is a image available in memory, return it. | 116 base::Callback<void(const GURL&, const SkBitmap*)> callback, |
102 if (!ServeFromCache(url, callback)) { | 117 scoped_ptr<SkBitmap> bitmap) { |
| 118 if (bitmap.get()) { |
| 119 callback.Run(url, bitmap.get()); |
| 120 } else { |
103 image_fetcher_->StartOrQueueNetworkRequest(url, image_url, callback); | 121 image_fetcher_->StartOrQueueNetworkRequest(url, image_url, callback); |
104 } | 122 } |
105 } | 123 } |
106 | 124 |
107 bool ImageManager::ServeFromCache( | 125 scoped_refptr<base::RefCountedMemory> ImageManager::GetEncodedImageFromCache( |
108 const GURL& url, | 126 const GURL& url) { |
109 base::Callback<void(const GURL&, const SkBitmap*)> callback) { | 127 ImageMap::iterator image_iter = image_map_.find(url.spec()); |
110 SkBitmap* bitmap = GetBitmapFromCache(url); | 128 if (image_iter != image_map_.end()) { |
111 if (bitmap) { | 129 return image_iter->second; |
112 callback.Run(url, bitmap); | |
113 return true; | |
114 } | 130 } |
115 return false; | 131 return nullptr; |
116 } | 132 } |
117 | 133 |
118 SkBitmap* ImageManager::GetBitmapFromCache(const GURL& url) { | 134 void ImageManager::ServeFromCacheOrNetwork( |
119 ImageMap::iterator image_iter = image_map_.find(url.spec()); | 135 const GURL& url, |
120 if (image_iter != image_map_.end()) { | 136 const GURL& image_url, |
121 return &image_iter->second; | 137 base::Callback<void(const GURL&, const SkBitmap*)> callback) { |
| 138 scoped_refptr<base::RefCountedMemory> encoded_data = |
| 139 GetEncodedImageFromCache(url); |
| 140 if (encoded_data.get()) { |
| 141 base::PostTaskAndReplyWithResult( |
| 142 background_task_runner_.get(), FROM_HERE, |
| 143 base::Bind(&DecodeImage, encoded_data), |
| 144 base::Bind(&ImageManager::OnCacheImageDecoded, |
| 145 weak_ptr_factory_.GetWeakPtr(), url, image_url, callback)); |
| 146 } else { |
| 147 image_fetcher_->StartOrQueueNetworkRequest(url, image_url, callback); |
122 } | 148 } |
123 return NULL; | |
124 } | 149 } |
125 | 150 |
126 void ImageManager::SaveImage(const GURL& url, const SkBitmap& bitmap) { | 151 void ImageManager::SaveImage(const GURL& url, const SkBitmap& bitmap) { |
| 152 scoped_refptr<base::RefCountedBytes> encoded_data( |
| 153 new base::RefCountedBytes()); |
| 154 if (!EncodeSkBitmapToJPEG(bitmap, &encoded_data->data())) { |
| 155 return; |
| 156 } |
| 157 |
127 // Update the image map. | 158 // Update the image map. |
128 image_map_.insert(std::make_pair(url.spec(), bitmap)); | 159 image_map_.insert({url.spec(), encoded_data}); |
129 | 160 |
130 if (!database_ready_) return; | 161 if (!database_ready_) return; |
131 | 162 |
132 // Attempt to save a JPEG representation to the database. If not successful, | 163 // Save the resulting bitmap to the database. |
133 // the fetched bitmap will still be inserted in the cache, above. | 164 ImageData data; |
134 std::vector<unsigned char> encoded_data; | 165 data.set_url(url.spec()); |
135 if (EncodeSkBitmapToJPEG(bitmap, &encoded_data)) { | 166 data.set_data(encoded_data->front(), encoded_data->size()); |
136 // Save the resulting bitmap to the database. | 167 scoped_ptr<ProtoDatabase<ImageData>::KeyEntryVector> entries_to_save( |
137 ImageData data; | 168 new ProtoDatabase<ImageData>::KeyEntryVector()); |
138 data.set_url(url.spec()); | 169 scoped_ptr<std::vector<std::string>> keys_to_remove( |
139 data.set_data(std::string(encoded_data.begin(), encoded_data.end())); | 170 new std::vector<std::string>()); |
140 scoped_ptr<ProtoDatabase<ImageData>::KeyEntryVector> entries_to_save( | 171 entries_to_save->push_back(std::make_pair(data.url(), data)); |
141 new ProtoDatabase<ImageData>::KeyEntryVector()); | 172 database_->UpdateEntries(entries_to_save.Pass(), keys_to_remove.Pass(), |
142 scoped_ptr<std::vector<std::string> > keys_to_remove( | 173 base::Bind(&ImageManager::OnDatabaseSave, |
143 new std::vector<std::string>()); | 174 weak_ptr_factory_.GetWeakPtr())); |
144 entries_to_save->push_back(std::make_pair(data.url(), data)); | |
145 database_->UpdateEntries(entries_to_save.Pass(), keys_to_remove.Pass(), | |
146 base::Bind(&ImageManager::OnDatabaseSave, | |
147 weak_ptr_factory_.GetWeakPtr())); | |
148 } | |
149 } | 175 } |
150 | 176 |
151 void ImageManager::OnDatabaseInit(bool success) { | 177 void ImageManager::OnDatabaseInit(bool success) { |
152 if (!success) { | 178 if (!success) { |
153 DVLOG(1) << "Image database init failed."; | 179 DVLOG(1) << "Image database init failed."; |
154 database_.reset(); | 180 database_.reset(); |
155 ServePendingCacheRequests(); | 181 ServePendingCacheRequests(); |
156 return; | 182 return; |
157 } | 183 } |
158 database_->LoadEntries(base::Bind(&ImageManager::OnDatabaseLoad, | 184 database_->LoadEntries(base::Bind(&ImageManager::OnDatabaseLoad, |
(...skipping 21 matching lines...) Expand all Loading... |
180 database_ready_ = false; | 206 database_ready_ = false; |
181 } | 207 } |
182 } | 208 } |
183 | 209 |
184 void ImageManager::LoadEntriesInCache(scoped_ptr<ImageDataVector> entries) { | 210 void ImageManager::LoadEntriesInCache(scoped_ptr<ImageDataVector> entries) { |
185 for (ImageDataVector::iterator it = entries->begin(); it != entries->end(); | 211 for (ImageDataVector::iterator it = entries->begin(); it != entries->end(); |
186 ++it) { | 212 ++it) { |
187 std::vector<unsigned char> encoded_data(it->data().begin(), | 213 std::vector<unsigned char> encoded_data(it->data().begin(), |
188 it->data().end()); | 214 it->data().end()); |
189 | 215 |
190 scoped_ptr<SkBitmap> bitmap(DecodeJPEGToSkBitmap(encoded_data)); | 216 image_map_.insert( |
191 if (bitmap.get()) { | 217 {it->url(), base::RefCountedBytes::TakeVector(&encoded_data)}); |
192 image_map_.insert(std::make_pair(it->url(), *bitmap)); | |
193 } | |
194 } | 218 } |
195 } | 219 } |
196 | 220 |
197 void ImageManager::ServePendingCacheRequests() { | 221 void ImageManager::ServePendingCacheRequests() { |
198 for (ImageCacheRequestMap::iterator it = pending_cache_requests_.begin(); | 222 for (ImageCacheRequestMap::iterator it = pending_cache_requests_.begin(); |
199 it != pending_cache_requests_.end(); ++it) { | 223 it != pending_cache_requests_.end(); ++it) { |
200 const ImageCacheRequest& request = it->second; | 224 const ImageCacheRequest& request = it->second; |
201 for (CallbackVector::const_iterator callback_it = request.callbacks.begin(); | 225 for (CallbackVector::const_iterator callback_it = request.callbacks.begin(); |
202 callback_it != request.callbacks.end(); ++callback_it) { | 226 callback_it != request.callbacks.end(); ++callback_it) { |
203 ServeFromCacheOrNetwork(request.url, request.image_url, *callback_it); | 227 ServeFromCacheOrNetwork(request.url, request.image_url, *callback_it); |
204 } | 228 } |
205 } | 229 } |
206 } | 230 } |
207 | 231 |
208 } // namespace suggestions | 232 } // namespace suggestions |
OLD | NEW |