OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/extensions/image_loading_tracker.h" | 5 #include "chrome/browser/extensions/image_loading_tracker.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "chrome/common/chrome_notification_types.h" | 9 #include "chrome/common/chrome_notification_types.h" |
10 #include "chrome/common/extensions/extension.h" | 10 #include "chrome/common/extensions/extension.h" |
11 #include "chrome/common/extensions/extension_resource.h" | 11 #include "chrome/common/extensions/extension_resource.h" |
12 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
13 #include "content/public/browser/notification_service.h" | 13 #include "content/public/browser/notification_service.h" |
14 #include "skia/ext/image_operations.h" | 14 #include "skia/ext/image_operations.h" |
15 #include "third_party/skia/include/core/SkBitmap.h" | 15 #include "third_party/skia/include/core/SkBitmap.h" |
16 #include "ui/gfx/image/image.h" | |
16 #include "webkit/glue/image_decoder.h" | 17 #include "webkit/glue/image_decoder.h" |
17 | 18 |
18 using content::BrowserThread; | 19 using content::BrowserThread; |
19 | 20 |
20 ImageLoadingTracker::Observer::~Observer() {} | 21 ImageLoadingTracker::Observer::~Observer() {} |
21 | 22 |
23 ImageLoadingTracker::ImageInfo::ImageInfo( | |
24 const ExtensionResource resource, gfx::Size max_size) | |
25 : resource(resource), max_size(max_size) { | |
26 } | |
27 | |
28 ImageLoadingTracker::PendingLoadInfo::PendingLoadInfo() | |
29 : extension(NULL), | |
30 pending_count(0) { | |
31 } | |
32 | |
33 ImageLoadingTracker::PendingLoadInfo::~PendingLoadInfo() { | |
34 } | |
35 | |
22 //////////////////////////////////////////////////////////////////////////////// | 36 //////////////////////////////////////////////////////////////////////////////// |
23 // ImageLoadingTracker::ImageLoader | 37 // ImageLoadingTracker::ImageLoader |
24 | 38 |
25 // A RefCounted class for loading images on the File thread and reporting back | 39 // A RefCounted class for loading images on the File thread and reporting back |
26 // on the UI thread. | 40 // on the UI thread. |
27 class ImageLoadingTracker::ImageLoader | 41 class ImageLoadingTracker::ImageLoader |
28 : public base::RefCountedThreadSafe<ImageLoader> { | 42 : public base::RefCountedThreadSafe<ImageLoader> { |
29 public: | 43 public: |
30 explicit ImageLoader(ImageLoadingTracker* tracker) | 44 explicit ImageLoader(ImageLoadingTracker* tracker) |
31 : tracker_(tracker) { | 45 : tracker_(tracker) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 // The loader is created lazily and is NULL if the tracker is destroyed before | 146 // The loader is created lazily and is NULL if the tracker is destroyed before |
133 // any valid image load tasks have been posted. | 147 // any valid image load tasks have been posted. |
134 if (loader_) | 148 if (loader_) |
135 loader_->StopTracking(); | 149 loader_->StopTracking(); |
136 } | 150 } |
137 | 151 |
138 void ImageLoadingTracker::LoadImage(const Extension* extension, | 152 void ImageLoadingTracker::LoadImage(const Extension* extension, |
139 const ExtensionResource& resource, | 153 const ExtensionResource& resource, |
140 const gfx::Size& max_size, | 154 const gfx::Size& max_size, |
141 CacheParam cache) { | 155 CacheParam cache) { |
142 // If we don't have a path we don't need to do any further work, just respond | 156 std::vector<ImageInfo> info_list; |
143 // back. | 157 info_list.push_back(ImageInfo(resource, max_size)); |
158 LoadImages(extension, info_list, cache); | |
159 } | |
160 | |
161 void ImageLoadingTracker::LoadImages(const Extension* extension, | |
162 const std::vector<ImageInfo>& info_list, | |
163 CacheParam cache) { | |
164 PendingLoadInfo load_info; | |
165 load_info.extension = extension; | |
166 load_info.cache = cache; | |
167 load_info.extension_id = extension->id(); | |
168 load_info.pending_count = info_list.size(); | |
144 int id = next_id_++; | 169 int id = next_id_++; |
145 if (resource.relative_path().empty()) { | 170 load_map_[id] = load_info; |
146 OnImageLoaded(NULL, resource, max_size, id); | 171 |
147 return; | 172 for (std::vector<ImageInfo>::const_iterator it = info_list.begin(); |
173 it != info_list.end(); ++it) { | |
174 // If we don't have a path we don't need to do any further work, just | |
175 // respond back. | |
176 if (it->resource.relative_path().empty()) { | |
177 OnImageLoaded(NULL, it->resource, it->max_size, id); | |
178 continue; | |
179 } | |
180 | |
181 DCHECK(extension->path() == it->resource.extension_root()); | |
182 | |
183 // See if the extension has the image already. | |
184 if (extension->HasCachedImage(it->resource, it->max_size)) { | |
185 SkBitmap image = extension->GetCachedImage(it->resource, it->max_size); | |
186 OnImageLoaded(&image, it->resource, it->max_size, id); | |
187 continue; | |
188 } | |
189 | |
190 // Instruct the ImageLoader to load this on the File thread. LoadImage does | |
191 // not block. | |
192 if (!loader_) | |
193 loader_ = new ImageLoader(this); | |
194 loader_->LoadImage(it->resource, it->max_size, id); | |
148 } | 195 } |
149 | |
150 DCHECK(extension->path() == resource.extension_root()); | |
151 | |
152 // See if the extension has the image already. | |
153 if (extension->HasCachedImage(resource, max_size)) { | |
154 SkBitmap image = extension->GetCachedImage(resource, max_size); | |
155 OnImageLoaded(&image, resource, max_size, id); | |
156 return; | |
157 } | |
158 | |
159 if (cache == CACHE) | |
160 load_map_[id] = extension; | |
161 | |
162 // Instruct the ImageLoader to load this on the File thread. LoadImage does | |
163 // not block. | |
164 if (!loader_) | |
165 loader_ = new ImageLoader(this); | |
166 loader_->LoadImage(resource, max_size, id); | |
167 } | 196 } |
168 | 197 |
169 void ImageLoadingTracker::OnImageLoaded( | 198 void ImageLoadingTracker::OnImageLoaded( |
170 SkBitmap* image, | 199 SkBitmap* image, |
171 const ExtensionResource& resource, | 200 const ExtensionResource& resource, |
172 const gfx::Size& original_size, | 201 const gfx::Size& original_size, |
173 int id) { | 202 int id) { |
174 LoadMap::iterator i = load_map_.find(id); | 203 LoadMap::iterator it = load_map_.find(id); |
175 if (i != load_map_.end()) { | 204 if (it == load_map_.end()) |
176 i->second->SetCachedImage(resource, image ? *image : SkBitmap(), | 205 return; |
177 original_size); | 206 |
178 load_map_.erase(i); | 207 PendingLoadInfo* info = &it->second; |
208 | |
209 // Save the pending results. | |
210 DCHECK(info->pending_count > 0); | |
211 info->pending_count--; | |
212 if (image) | |
213 info->bitmaps.push_back(*image); | |
214 | |
215 // Add to the extension's image cache if requested. | |
216 if (info->cache == CACHE && info->extension && | |
217 !info->extension->HasCachedImage(resource, original_size)) { | |
218 info->extension->SetCachedImage(resource, image ? *image : SkBitmap(), | |
219 original_size); | |
179 } | 220 } |
180 | 221 |
181 observer_->OnImageLoaded(image, resource, id); | 222 // If all pending images are done report back. |
223 if (info->pending_count == 0) { | |
224 if (info->bitmaps.size() > 0) { | |
225 std::vector<const SkBitmap*> bitmaps; | |
226 for (std::vector<SkBitmap>::const_iterator it = info->bitmaps.begin(); | |
227 it != info->bitmaps.end(); ++it) { | |
228 bitmaps.push_back(new SkBitmap(*it)); | |
Mihai Parparita -not on Chrome
2012/02/23 00:19:41
Why make a new SkBitmap when you could just use a
sail
2012/02/23 02:54:27
The gfx::Image constructor takes ownership of the
| |
229 } | |
230 gfx::Image gfx_image(bitmaps); | |
231 observer_->OnImageLoaded(&gfx_image, info->extension_id, id); | |
232 } else { | |
233 observer_->OnImageLoaded(NULL, info->extension_id, id); | |
234 } | |
235 load_map_.erase(it); | |
236 } | |
182 } | 237 } |
183 | 238 |
184 void ImageLoadingTracker::Observe(int type, | 239 void ImageLoadingTracker::Observe(int type, |
185 const content::NotificationSource& source, | 240 const content::NotificationSource& source, |
186 const content::NotificationDetails& details) { | 241 const content::NotificationDetails& details) { |
187 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED); | 242 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED); |
188 | 243 |
189 const Extension* extension = | 244 const Extension* extension = |
190 content::Details<UnloadedExtensionInfo>(details)->extension; | 245 content::Details<UnloadedExtensionInfo>(details)->extension; |
191 | 246 |
192 // Remove all entries in the load_map_ referencing the extension. This ensures | 247 // Remove reference to this extension from all pending load entries. This |
Mihai Parparita -not on Chrome
2012/02/23 00:19:41
Why not remove the map entry? The check at line 20
sail
2012/02/23 02:54:27
This doesn't match the old behavior. In the old co
| |
193 // we don't attempt to cache the image when the load completes. | 248 // ensures we don't attempt to cache the image when the load completes. |
194 for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end();) { | 249 for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end(); ++i) { |
195 if (i->second == extension) | 250 PendingLoadInfo* info = &i->second; |
196 load_map_.erase(i++); | 251 if (info->extension == extension) { |
197 else | 252 info->extension = NULL; |
198 ++i; | 253 info->cache = DONT_CACHE; |
254 } | |
199 } | 255 } |
200 } | 256 } |
OLD | NEW |