Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: chrome/browser/extensions/image_loading_tracker.cc

Issue 10701087: chromeos: Fix pixelated icons in app list and launcher (part 2) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: for comments in #3, add an ImageSource and makes ImageLoadingTracker auto load image for additional… Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" 12 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
13 #include "chrome/common/chrome_notification_types.h" 13 #include "chrome/common/chrome_notification_types.h"
14 #include "chrome/common/extensions/extension.h" 14 #include "chrome/common/extensions/extension.h"
15 #include "chrome/common/extensions/extension_constants.h" 15 #include "chrome/common/extensions/extension_constants.h"
16 #include "chrome/common/extensions/extension_resource.h" 16 #include "chrome/common/extensions/extension_resource.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_service.h" 18 #include "content/public/browser/notification_service.h"
19 #include "grit/component_extension_resources_map.h" 19 #include "grit/component_extension_resources_map.h"
20 #include "grit/theme_resources.h" 20 #include "grit/theme_resources.h"
21 #include "skia/ext/image_operations.h" 21 #include "skia/ext/image_operations.h"
22 #include "third_party/skia/include/core/SkBitmap.h" 22 #include "third_party/skia/include/core/SkBitmap.h"
23 #include "ui/gfx/image/image.h" 23 #include "ui/gfx/image/image.h"
24 #include "ui/gfx/image/image_skia.h"
25 #include "ui/gfx/image/image_skia_rep.h" 24 #include "ui/gfx/image/image_skia_rep.h"
25 #include "ui/gfx/image/image_skia_source.h"
26 #include "ui/gfx/screen.h"
26 #include "webkit/glue/image_decoder.h" 27 #include "webkit/glue/image_decoder.h"
27 28
28 using content::BrowserThread; 29 using content::BrowserThread;
29 using extensions::Extension; 30 using extensions::Extension;
30 31
31 //////////////////////////////////////////////////////////////////////////////// 32 ////////////////////////////////////////////////////////////////////////////////
32 // ImageLoadingTracker::Observer 33 // ImageLoadingTracker::Observer
33 34
34 ImageLoadingTracker::Observer::~Observer() {} 35 ImageLoadingTracker::Observer::~Observer() {}
35 36
36 //////////////////////////////////////////////////////////////////////////////// 37 ////////////////////////////////////////////////////////////////////////////////
37 // ImageLoadingTracker::ImageInfo 38 // ImageLoadingTracker::ImageInfo
38 39
39 ImageLoadingTracker::ImageInfo::ImageInfo( 40 ImageLoadingTracker::ImageInfo::ImageInfo(
40 const ExtensionResource& resource, gfx::Size max_size) 41 const ExtensionResource& resource,
41 : resource(resource), max_size(max_size) { 42 const gfx::Size& max_size,
43 ui::ScaleFactor scale_factor)
44 : resource(resource),
45 max_size(max_size),
46 scale_factor(scale_factor) {
42 } 47 }
43 48
44 ImageLoadingTracker::ImageInfo::~ImageInfo() { 49 ImageLoadingTracker::ImageInfo::~ImageInfo() {
45 } 50 }
46 51
47 //////////////////////////////////////////////////////////////////////////////// 52 ////////////////////////////////////////////////////////////////////////////////
48 // ImageLoadingTracker::PendingLoadInfo 53 // ImageLoadingTracker::PendingLoadInfo
49 54
50 ImageLoadingTracker::PendingLoadInfo::PendingLoadInfo() 55 ImageLoadingTracker::PendingLoadInfo::PendingLoadInfo()
51 : extension(NULL), 56 : extension(NULL),
57 resource_size_in_dip(ExtensionIconSet::EXTENSION_ICON_INVALID),
58 resource_match_type(ExtensionIconSet::MATCH_BIGGER),
59 image_source(NULL),
52 cache(CACHE), 60 cache(CACHE),
53 pending_count(0) { 61 pending_count(0) {
54 } 62 }
55 63
56 ImageLoadingTracker::PendingLoadInfo::~PendingLoadInfo() {} 64 ImageLoadingTracker::PendingLoadInfo::~PendingLoadInfo() {}
57 65
58 //////////////////////////////////////////////////////////////////////////////// 66 ////////////////////////////////////////////////////////////////////////////////
59 // ImageLoadingTracker::ImageLoader 67 // ImageLoadingTracker::ImageLoader
60 68
61 // A RefCounted class for loading images on the File thread and reporting back 69 // A RefCounted class for loading images on the File thread and reporting back
62 // on the UI thread. 70 // on the UI thread.
63 class ImageLoadingTracker::ImageLoader 71 class ImageLoadingTracker::ImageLoader
64 : public base::RefCountedThreadSafe<ImageLoader> { 72 : public base::RefCountedThreadSafe<ImageLoader> {
65 public: 73 public:
66 explicit ImageLoader(ImageLoadingTracker* tracker) 74 explicit ImageLoader(ImageLoadingTracker* tracker)
67 : tracker_(tracker) { 75 : tracker_(tracker) {
68 CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_)); 76 CHECK(BrowserThread::GetCurrentThreadIdentifier(&callback_thread_id_));
69 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); 77 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
70 } 78 }
71 79
72 // Lets this class know that the tracker is no longer interested in the 80 // Lets this class know that the tracker is no longer interested in the
73 // results. 81 // results.
74 void StopTracking() { 82 void StopTracking() {
75 tracker_ = NULL; 83 tracker_ = NULL;
76 } 84 }
77 85
78 // Instructs the loader to load a task on the File thread. 86 // Instructs the loader to load a task on the File thread.
79 void LoadImage(const ExtensionResource& resource, 87 void LoadImage(const ImageInfo& image_info, int id) {
80 const gfx::Size& max_size,
81 int id) {
82 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); 88 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
83 BrowserThread::PostTask( 89 BrowserThread::PostTask(
84 BrowserThread::FILE, FROM_HERE, 90 BrowserThread::FILE, FROM_HERE,
oshima 2012/07/16 17:22:33 this is not the scope of this change, but at some
xiyuan 2012/07/16 20:11:27 Agree. But I'd prefer to do it in a follow up CL s
85 base::Bind(&ImageLoader::LoadOnFileThread, this, resource, 91 base::Bind(&ImageLoader::LoadOnFileThread, this, image_info, id));
86 max_size, id));
87 } 92 }
88 93
89 void LoadOnFileThread(const ExtensionResource& resource, 94 void LoadOnFileThread(const ImageInfo& image_info, int id) {
90 const gfx::Size& max_size,
91 int id) {
92 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
93 96
94 // Read the file from disk. 97 // Read the file from disk.
95 std::string file_contents; 98 std::string file_contents;
96 FilePath path = resource.GetFilePath(); 99 FilePath path = image_info.resource.GetFilePath();
97 if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) { 100 if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) {
98 ReportBack(NULL, resource, gfx::Size(), id); 101 ReportBack(NULL, image_info, gfx::Size(), id);
99 return; 102 return;
100 } 103 }
101 104
102 // Decode the image using WebKit's image decoder. 105 // Decode the image using WebKit's image decoder.
103 const unsigned char* data = 106 const unsigned char* data =
104 reinterpret_cast<const unsigned char*>(file_contents.data()); 107 reinterpret_cast<const unsigned char*>(file_contents.data());
105 webkit_glue::ImageDecoder decoder; 108 webkit_glue::ImageDecoder decoder;
106 scoped_ptr<SkBitmap> decoded(new SkBitmap()); 109 scoped_ptr<SkBitmap> decoded(new SkBitmap());
107 // Note: This class only decodes images from extension resources. Chrome 110 // Note: This class only decodes images from extension resources. Chrome
108 // doesn't (for security reasons) directly load extension resources provided 111 // doesn't (for security reasons) directly load extension resources provided
109 // by the extension author, but instead decodes them in a separate 112 // by the extension author, but instead decodes them in a separate
110 // locked-down utility process. Only if the decoding succeeds is the image 113 // locked-down utility process. Only if the decoding succeeds is the image
111 // saved from memory to disk and subsequently used in the Chrome UI. 114 // saved from memory to disk and subsequently used in the Chrome UI.
112 // Chrome is therefore decoding images here that were generated by Chrome. 115 // Chrome is therefore decoding images here that were generated by Chrome.
113 *decoded = decoder.Decode(data, file_contents.length()); 116 *decoded = decoder.Decode(data, file_contents.length());
114 if (decoded->empty()) { 117 if (decoded->empty()) {
115 ReportBack(NULL, resource, gfx::Size(), id); 118 ReportBack(NULL, image_info, gfx::Size(), id);
116 return; // Unable to decode. 119 return; // Unable to decode.
117 } 120 }
118 121
119 gfx::Size original_size(decoded->width(), decoded->height()); 122 gfx::Size original_size(decoded->width(), decoded->height());
120 123
121 if (decoded->width() > max_size.width() || 124 if (decoded->width() > image_info.max_size.width() ||
122 decoded->height() > max_size.height()) { 125 decoded->height() > image_info.max_size.height()) {
123 // The bitmap is too big, re-sample. 126 // The bitmap is too big, re-sample.
124 *decoded = skia::ImageOperations::Resize( 127 *decoded = skia::ImageOperations::Resize(
125 *decoded, skia::ImageOperations::RESIZE_LANCZOS3, 128 *decoded, skia::ImageOperations::RESIZE_LANCZOS3,
126 max_size.width(), max_size.height()); 129 image_info.max_size.width(), image_info.max_size.height());
127 } 130 }
128 131
129 ReportBack(decoded.release(), resource, original_size, id); 132 ReportBack(decoded.release(), image_info, original_size, id);
130 } 133 }
131 134
132 // Instructs the loader to load a resource on the File thread. 135 // Instructs the loader to load a resource on the File thread.
133 void LoadResource(const ExtensionResource& resource, 136 void LoadResource(const ImageInfo& image_info, int id, int resource_id) {
134 const gfx::Size& max_size,
135 int id,
136 int resource_id) {
137 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); 137 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
138 BrowserThread::PostTask( 138 BrowserThread::PostTask(
139 BrowserThread::FILE, FROM_HERE, 139 BrowserThread::FILE, FROM_HERE,
140 base::Bind(&ImageLoader::LoadResourceOnFileThread, this, resource, 140 base::Bind(&ImageLoader::LoadResourceOnFileThread, this, image_info,
141 max_size, id, resource_id)); 141 id, resource_id));
142 } 142 }
143 143
144 void LoadResourceOnFileThread(const ExtensionResource& resource, 144 void LoadResourceOnFileThread(const ImageInfo& image_info,
145 const gfx::Size& max_size,
146 int id, 145 int id,
147 int resource_id) { 146 int resource_id) {
148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
149 SkBitmap* image = ExtensionIconSource::LoadImageByResourceId( 148 SkBitmap* image = ExtensionIconSource::LoadImageByResourceId(
150 resource_id); 149 resource_id);
151 ReportBack(image, resource, max_size, id); 150 ReportBack(image, image_info, image_info.max_size, id);
152 } 151 }
153 152
154 void ReportBack(SkBitmap* image, const ExtensionResource& resource, 153 void ReportBack(SkBitmap* image, const ImageInfo& image_info,
155 const gfx::Size& original_size, int id) { 154 const gfx::Size& original_size, int id) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
157 156
158 BrowserThread::PostTask( 157 BrowserThread::PostTask(
159 callback_thread_id_, FROM_HERE, 158 callback_thread_id_, FROM_HERE,
160 base::Bind(&ImageLoader::ReportOnUIThread, this, 159 base::Bind(&ImageLoader::ReportOnUIThread, this,
161 image, resource, original_size, id)); 160 image, image_info, original_size, id));
162 } 161 }
163 162
164 void ReportOnUIThread(SkBitmap* image, const ExtensionResource& resource, 163 void ReportOnUIThread(SkBitmap* image, const ImageInfo& image_info,
165 const gfx::Size& original_size, int id) { 164 const gfx::Size& original_size, int id) {
166 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE)); 165 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
167 166
168 if (tracker_) 167 if (tracker_)
169 tracker_->OnImageLoaded(image, resource, original_size, id, true); 168 tracker_->OnImageLoaded(image, image_info, original_size, id, true);
170 169
171 delete image; 170 delete image;
172 } 171 }
173 172
174 private: 173 private:
175 friend class base::RefCountedThreadSafe<ImageLoader>; 174 friend class base::RefCountedThreadSafe<ImageLoader>;
176 ~ImageLoader() {} 175 ~ImageLoader() {}
177 176
178 // The tracker we are loading the image for. If NULL, it means the tracker is 177 // The tracker we are loading the image for. If NULL, it means the tracker is
179 // no longer interested in the reply. 178 // no longer interested in the reply.
180 ImageLoadingTracker* tracker_; 179 ImageLoadingTracker* tracker_;
181 180
182 // The thread that we need to call back on to report that we are done. 181 // The thread that we need to call back on to report that we are done.
183 BrowserThread::ID callback_thread_id_; 182 BrowserThread::ID callback_thread_id_;
184 183
185 DISALLOW_COPY_AND_ASSIGN(ImageLoader); 184 DISALLOW_COPY_AND_ASSIGN(ImageLoader);
186 }; 185 };
187 186
188 //////////////////////////////////////////////////////////////////////////////// 187 ////////////////////////////////////////////////////////////////////////////////
188 // ImageLoadingTracker::ImageSource
189
190 // An ImageSkiaSource to load image for additional scale factor.
pkotwicz 2012/07/16 17:33:52 Nit: factors
xiyuan 2012/07/16 20:11:27 Done.
191 class ImageLoadingTracker::ImageSource : public gfx::ImageSkiaSource {
192 public:
193 ImageSource(ImageLoadingTracker* tracker, int id);
194 virtual ~ImageSource();
195
196 void StopTracking();
197
198 // gfx::ImageSkiaSource overrides:
199 virtual gfx::ImageSkiaRep GetImageForScale(
200 ui::ScaleFactor scale_factor) OVERRIDE;
201
202 private:
203 ImageLoadingTracker* tracker_;
204 int id_;
205
206 DISALLOW_COPY_AND_ASSIGN(ImageSource);
207 };
208
209 ImageLoadingTracker::ImageSource::ImageSource(ImageLoadingTracker* tracker,
210 int id)
211 : tracker_(tracker),
212 id_(id) {
213 }
214
215 ImageLoadingTracker::ImageSource::~ImageSource() {
216 }
217
218 void ImageLoadingTracker::ImageSource::StopTracking() {
219 tracker_ = NULL;
220 }
221
222 gfx::ImageSkiaRep ImageLoadingTracker::ImageSource::GetImageForScale(
223 ui::ScaleFactor scale_factor) {
224 // Asks tracker to load new images for |scale_factor|.
225 if (tracker_)
226 tracker_->LoadImageForScaleFactor(id_, scale_factor);
227
228 // Returns an empty representation for |scale_factor| here. If |tracker_| is
229 // valid, it loads image asynchronously. When loading is done, it updates
230 // existing ImageSkia and notifies its observer.
231 return gfx::ImageSkiaRep();
232 }
233
234 ////////////////////////////////////////////////////////////////////////////////
189 // ImageLoadingTracker 235 // ImageLoadingTracker
190 236
191 ImageLoadingTracker::ImageLoadingTracker(Observer* observer) 237 ImageLoadingTracker::ImageLoadingTracker(Observer* observer)
192 : observer_(observer), 238 : observer_(observer),
193 next_id_(0) { 239 next_id_(0) {
194 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 240 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
195 content::NotificationService::AllSources()); 241 content::NotificationService::AllSources());
196 } 242 }
197 243
198 ImageLoadingTracker::~ImageLoadingTracker() { 244 ImageLoadingTracker::~ImageLoadingTracker() {
199 // The loader is created lazily and is NULL if the tracker is destroyed before 245 // The loader is created lazily and is NULL if the tracker is destroyed before
200 // any valid image load tasks have been posted. 246 // any valid image load tasks have been posted.
201 if (loader_) 247 if (loader_)
202 loader_->StopTracking(); 248 loader_->StopTracking();
249
250 for (LoadMap::iterator it = load_map_.begin(); it != load_map_.end(); ++it) {
251 if (it->second.image_source)
252 it->second.image_source->StopTracking();
253 }
203 } 254 }
204 255
205 void ImageLoadingTracker::LoadImage(const Extension* extension, 256 void ImageLoadingTracker::LoadImage(const Extension* extension,
206 const ExtensionResource& resource, 257 const ExtensionResource& resource,
207 const gfx::Size& max_size, 258 const gfx::Size& max_size,
208 CacheParam cache) { 259 CacheParam cache) {
209 std::vector<ImageInfo> info_list; 260 std::vector<ImageInfo> info_list;
210 info_list.push_back(ImageInfo(resource, max_size)); 261 info_list.push_back(ImageInfo(resource, max_size, ui::SCALE_FACTOR_NONE));
pkotwicz 2012/07/16 17:33:52 Just use SCALE_FACTOR_100P. (SCALE_FACTOR_NONE is
xiyuan 2012/07/16 20:11:27 Done.
211 LoadImages(extension, info_list, cache); 262 LoadImages(extension, info_list, cache);
212 } 263 }
213 264
265 void ImageLoadingTracker::LoadImageInDIP(
266 const Extension* extension,
267 int resource_size,
268 ExtensionIconSet::MatchType resource_match_type,
269 const gfx::Size& max_size,
270 CacheParam cache) {
271 typedef std::vector<ui::ScaleFactor> ScaleFactors;
272
273 // TODO(xiyuan): Update the following.
274 // gfx::Screen::GetScaleFactorsInUse is in peter's pending CL.
275 // const ScaleFactors scale_factors_in_use =
276 // gfx::Screen::GetScaleFactorsInUse();
oshima 2012/07/16 17:22:33 I thought we're going to load the correct image fo
xiyuan 2012/07/16 20:11:27 You are correct. The code is in comment because ht
277 ScaleFactors scale_factors_in_use;
278 if (gfx::Screen::IsDIPEnabled())
279 scale_factors_in_use.push_back(ui::SCALE_FACTOR_200P);
280 else
281 scale_factors_in_use.push_back(ui::SCALE_FACTOR_100P);
282
283 std::vector<ImageInfo> info_list;
284 for (ScaleFactors::const_iterator it = scale_factors_in_use.begin();
285 it != scale_factors_in_use.end(); ++it) {
286 const float scale = ui::GetScaleFactorScale(*it);
287
288 ExtensionResource resource = extension->GetIconResource(
289 static_cast<int>(resource_size * scale),
290 resource_match_type);
291
292 info_list.push_back(ImageInfo(resource, max_size.Scale(scale), *it));
293 }
294
295 PendingLoadInfo load_info;
296 load_info.extension = extension;
297 load_info.extension_id = extension->id();
298 load_info.cache = cache;
299
300 load_info.resource_size_in_dip = resource_size;
301 load_info.resource_match_type = resource_match_type;
302 load_info.max_size_in_dip = max_size;
303
304 int id = next_id_++;
305 load_info.image_source = new ImageSource(this, id);
306 load_info.images = gfx::ImageSkia(load_info.image_source,
307 load_info.max_size_in_dip);
pkotwicz 2012/07/16 17:33:52 The loaded bitmap is not always resized to max_siz
xiyuan 2012/07/16 20:11:27 Done.
308
309 load_map_[id] = load_info;
310
311 DoLoadImages(id, info_list);
pkotwicz 2012/07/16 17:33:52 Call this DoLoadImage. You are still loading a sin
xiyuan 2012/07/16 20:11:27 Done.
312 }
313
214 void ImageLoadingTracker::LoadImages(const Extension* extension, 314 void ImageLoadingTracker::LoadImages(const Extension* extension,
215 const std::vector<ImageInfo>& info_list, 315 const std::vector<ImageInfo>& info_list,
216 CacheParam cache) { 316 CacheParam cache) {
217 PendingLoadInfo load_info; 317 PendingLoadInfo load_info;
218 load_info.extension = extension; 318 load_info.extension = extension;
319 load_info.extension_id = extension->id();
219 load_info.cache = cache; 320 load_info.cache = cache;
220 load_info.extension_id = extension->id(); 321
221 load_info.pending_count = info_list.size();
222 int id = next_id_++; 322 int id = next_id_++;
223 load_map_[id] = load_info; 323 load_map_[id] = load_info;
224 324
325 DoLoadImages(id, info_list);
326 }
327
328 void ImageLoadingTracker::DoLoadImages(
329 int id,
330 const std::vector<ImageInfo>& info_list) {
331 LoadMap::iterator load_map_it = load_map_.find(id);
332 DCHECK(load_map_it != load_map_.end());
333
334 PendingLoadInfo* load_info = &load_map_it->second;
335 load_info->pending_count = info_list.size();
336 const extensions::Extension* extension = load_info->extension;
337
225 for (std::vector<ImageInfo>::const_iterator it = info_list.begin(); 338 for (std::vector<ImageInfo>::const_iterator it = info_list.begin();
226 it != info_list.end(); ++it) { 339 it != info_list.end(); ++it) {
227 // Load resources for special component extensions. 340 // Load resources for special component extensions.
228 if (load_info.extension_id == extension_misc::kWebStoreAppId) { 341 if (load_info->extension_id == extension_misc::kWebStoreAppId) {
229 if (!loader_) 342 if (!loader_)
230 loader_ = new ImageLoader(this); 343 loader_ = new ImageLoader(this);
231 loader_->LoadResource(it->resource, it->max_size, id, IDR_WEBSTORE_ICON); 344 loader_->LoadResource(*it, id, IDR_WEBSTORE_ICON);
232 continue; 345 continue;
233 } else if (load_info.extension_id == extension_misc::kChromeAppId) { 346 } else if (load_info->extension_id == extension_misc::kChromeAppId) {
234 if (!loader_) 347 if (!loader_)
235 loader_ = new ImageLoader(this); 348 loader_ = new ImageLoader(this);
236 loader_->LoadResource(it->resource, 349 loader_->LoadResource(*it, id, IDR_PRODUCT_LOGO_128);
237 it->max_size,
238 id,
239 IDR_PRODUCT_LOGO_128);
240 continue; 350 continue;
241 } 351 }
242 352
243 // If we don't have a path we don't need to do any further work, just 353 // If we don't have a path we don't need to do any further work, just
244 // respond back. 354 // respond back.
245 if (it->resource.relative_path().empty()) { 355 if (it->resource.relative_path().empty()) {
246 OnImageLoaded(NULL, it->resource, it->max_size, id, false); 356 OnImageLoaded(NULL, *it, it->max_size, id, false);
247 continue; 357 continue;
248 } 358 }
249 359
250 DCHECK(extension->path() == it->resource.extension_root()); 360 DCHECK(extension->path() == it->resource.extension_root());
251 361
252 // See if the extension has the image already. 362 // See if the extension has the image already.
253 if (extension->HasCachedImage(it->resource, it->max_size)) { 363 if (extension->HasCachedImage(it->resource, it->max_size)) {
254 SkBitmap image = extension->GetCachedImage(it->resource, it->max_size); 364 SkBitmap image = extension->GetCachedImage(it->resource, it->max_size);
255 OnImageLoaded(&image, it->resource, it->max_size, id, false); 365 OnImageLoaded(&image, *it, it->max_size, id, false);
pkotwicz 2012/07/16 17:33:52 Rename image->bitmap. Can you add a TODO to suppor
xiyuan 2012/07/16 20:11:27 Rename done. Caching is supported on the bitmap/i
256 continue; 366 continue;
257 } 367 }
258 368
259 // Instruct the ImageLoader to load this on the File thread. LoadImage and 369 // Instruct the ImageLoader to load this on the File thread. LoadImage and
260 // LoadResource do not block. 370 // LoadResource do not block.
261 if (!loader_) 371 if (!loader_)
262 loader_ = new ImageLoader(this); 372 loader_ = new ImageLoader(this);
263 373
264 int resource_id; 374 int resource_id;
265 if (IsComponentExtensionResource(extension, it->resource, resource_id)) 375 if (IsComponentExtensionResource(extension, it->resource, resource_id))
266 loader_->LoadResource(it->resource, it->max_size, id, resource_id); 376 loader_->LoadResource(*it, id, resource_id);
267 else 377 else
268 loader_->LoadImage(it->resource, it->max_size, id); 378 loader_->LoadImage(*it, id);
269 } 379 }
270 } 380 }
271 381
382 void ImageLoadingTracker::LoadImageForScaleFactor(
383 int id,
384 ui::ScaleFactor scale_factor) {
385 LoadMap::iterator load_map_it = load_map_.find(id);
386 DCHECK(load_map_it != load_map_.end());
387 PendingLoadInfo* load_info = &load_map_it->second;
388
389 // Do nothing if extension is unloaded.
390 if (load_info->extension == NULL)
391 return;
pkotwicz 2012/07/16 17:33:52 You need to check here if |load_info->pending_coun
xiyuan 2012/07/16 20:11:27 Good catch. Think we should allow LoadImageForScal
392
393 const float scale = ui::GetScaleFactorScale(scale_factor);
394 const int resource_size_in_pixel =
395 static_cast<int>(load_info->resource_size_in_dip * scale);
396
397 ExtensionResource resource = load_info->extension->GetIconResource(
398 resource_size_in_pixel,
399 load_info->resource_match_type);
400
401 std::vector<ImageInfo> info_list;
402 info_list.push_back(ImageInfo(resource,
403 load_info->max_size_in_dip.Scale(scale),
404 scale_factor));
405 DoLoadImages(id, info_list);
406 }
407
272 bool ImageLoadingTracker::IsComponentExtensionResource( 408 bool ImageLoadingTracker::IsComponentExtensionResource(
273 const Extension* extension, 409 const Extension* extension,
274 const ExtensionResource& resource, 410 const ExtensionResource& resource,
275 int& resource_id) const { 411 int& resource_id) const {
276 if (extension->location() != Extension::COMPONENT) 412 if (extension->location() != Extension::COMPONENT)
277 return false; 413 return false;
278 414
279 FilePath directory_path = extension->path(); 415 FilePath directory_path = extension->path();
280 FilePath relative_path = directory_path.BaseName().Append( 416 FilePath relative_path = directory_path.BaseName().Append(
281 resource.relative_path()); 417 resource.relative_path());
282 418
283 for (size_t i = 0; i < kComponentExtensionResourcesSize; ++i) { 419 for (size_t i = 0; i < kComponentExtensionResourcesSize; ++i) {
284 FilePath resource_path = 420 FilePath resource_path =
285 FilePath().AppendASCII(kComponentExtensionResources[i].name); 421 FilePath().AppendASCII(kComponentExtensionResources[i].name);
286 resource_path = resource_path.NormalizePathSeparators(); 422 resource_path = resource_path.NormalizePathSeparators();
287 423
288 if (relative_path == resource_path) { 424 if (relative_path == resource_path) {
289 resource_id = kComponentExtensionResources[i].value; 425 resource_id = kComponentExtensionResources[i].value;
290 return true; 426 return true;
291 } 427 }
292 } 428 }
293 return false; 429 return false;
294 } 430 }
295 431
296 void ImageLoadingTracker::OnImageLoaded( 432 void ImageLoadingTracker::OnImageLoaded(
297 SkBitmap* image, 433 SkBitmap* image,
298 const ExtensionResource& resource, 434 const ImageInfo& image_info,
299 const gfx::Size& original_size, 435 const gfx::Size& original_size,
300 int id, 436 int id,
301 bool should_cache) { 437 bool should_cache) {
302 LoadMap::iterator load_map_it = load_map_.find(id); 438 LoadMap::iterator load_map_it = load_map_.find(id);
303 DCHECK(load_map_it != load_map_.end()); 439 DCHECK(load_map_it != load_map_.end());
304 PendingLoadInfo* info = &load_map_it->second; 440 PendingLoadInfo* info = &load_map_it->second;
305 441
306 // Save the pending results. 442 // Save the pending results.
307 DCHECK(info->pending_count > 0); 443 DCHECK(info->pending_count > 0);
308 info->pending_count--; 444 info->pending_count--;
309 if (image) 445 if (image) {
oshima 2012/07/16 17:22:33 DCHECK(!images.HasRepresentation(image_info.scale_
xiyuan 2012/07/16 20:11:28 This DCHECK actually would fail because ImageLoadi
310 info->bitmaps.push_back(*image); 446 info->images.AddRepresentation(gfx::ImageSkiaRep(*image,
447 image_info.scale_factor));
448 }
311 449
312 // Add to the extension's image cache if requested. 450 // Add to the extension's image cache if requested.
313 DCHECK(info->cache != CACHE || info->extension); 451 DCHECK(info->cache != CACHE || info->extension);
314 if (should_cache && info->cache == CACHE && 452 if (should_cache && info->cache == CACHE &&
315 !info->extension->HasCachedImage(resource, original_size)) { 453 !info->extension->HasCachedImage(image_info.resource, original_size)) {
316 info->extension->SetCachedImage(resource, image ? *image : SkBitmap(), 454 info->extension->SetCachedImage(image_info.resource,
455 image ? *image : SkBitmap(),
pkotwicz 2012/07/16 17:33:52 Rename image->bitmap
xiyuan 2012/07/16 20:11:28 Done.
317 original_size); 456 original_size);
318 } 457 }
319 458
320 // If all pending images are done then report back. 459 // If all pending images are done then report back.
321 if (info->pending_count == 0) { 460 if (info->pending_count == 0) {
322 gfx::Image image; 461 gfx::Image image(info->images);
323 std::string extension_id = info->extension_id; 462 std::string extension_id = info->extension_id;
324 463
325 if (info->bitmaps.size() > 0) { 464 if (info->image_source == NULL)
326 gfx::ImageSkia image_skia; 465 load_map_.erase(load_map_it);
327 for (std::vector<SkBitmap>::const_iterator it = info->bitmaps.begin();
328 it != info->bitmaps.end(); ++it) {
329 // TODO(pkotwicz): Do something better but ONLY when DIP is enabled.
330 image_skia.AddRepresentation(
331 gfx::ImageSkiaRep(*it, ui::SCALE_FACTOR_100P));
332 }
333 image = gfx::Image(image_skia);
334 }
335
336 load_map_.erase(load_map_it);
337 466
338 // ImageLoadingTracker might be deleted after the callback so don't 467 // ImageLoadingTracker might be deleted after the callback so don't
339 // anything after this statement. 468 // anything after this statement.
340 observer_->OnImageLoaded(image, extension_id, id); 469 observer_->OnImageLoaded(image, extension_id, id);
341 } 470 }
342 } 471 }
343 472
344 void ImageLoadingTracker::Observe(int type, 473 void ImageLoadingTracker::Observe(int type,
345 const content::NotificationSource& source, 474 const content::NotificationSource& source,
346 const content::NotificationDetails& details) { 475 const content::NotificationDetails& details) {
347 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED); 476 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED);
348 477
349 const Extension* extension = 478 const Extension* extension =
350 content::Details<extensions::UnloadedExtensionInfo>(details)->extension; 479 content::Details<extensions::UnloadedExtensionInfo>(details)->extension;
351 480
352 // Remove reference to this extension from all pending load entries. This 481 // Remove reference to this extension from all pending load entries. This
353 // ensures we don't attempt to cache the image when the load completes. 482 // ensures we don't attempt to cache the image when the load completes.
354 for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end(); ++i) { 483 for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end(); ++i) {
355 PendingLoadInfo* info = &i->second; 484 PendingLoadInfo* info = &i->second;
356 if (info->extension == extension) { 485 if (info->extension == extension) {
357 info->extension = NULL; 486 info->extension = NULL;
358 info->cache = DONT_CACHE; 487 info->cache = DONT_CACHE;
359 } 488 }
360 } 489 }
361 } 490 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698