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