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

Unified Diff: chrome/browser/extensions/image_loading_tracker.cc

Issue 10825012: chromeos: Fix pixelated icons in app list and launcher (part 2) (by xiyuan) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/image_loading_tracker.cc
diff --git a/chrome/browser/extensions/image_loading_tracker.cc b/chrome/browser/extensions/image_loading_tracker.cc
index 02fd19bce02b7f5af03ea567368a1296649b24ed..2500988c7494febe8296a60196b59577994e5cb0 100644
--- a/chrome/browser/extensions/image_loading_tracker.cc
+++ b/chrome/browser/extensions/image_loading_tracker.cc
@@ -20,28 +20,78 @@
#include "grit/theme_resources.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "webkit/glue/image_decoder.h"
using content::BrowserThread;
using extensions::Extension;
+namespace {
+
+struct ComponentExtensionResource {
+ const char* extension_id;
+ const int resource_id;
+};
+
+const ComponentExtensionResource kSpecialComponentExtensionResources[] = {
+ { extension_misc::kWebStoreAppId, IDR_WEBSTORE_ICON },
+ { extension_misc::kChromeAppId, IDR_PRODUCT_LOGO_128 },
+};
+
+// Finds special component extension resource id for given extension id.
+bool FindSpecialExtensionResourceId(const std::string& extension_id,
+ int* out_resource_id) {
+ for (size_t i = 0; i < arraysize(kSpecialComponentExtensionResources); ++i) {
+ if (extension_id == kSpecialComponentExtensionResources[i].extension_id) {
+ if (out_resource_id)
+ *out_resource_id = kSpecialComponentExtensionResources[i].resource_id;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ShouldResizeImageRepresentation(
+ ImageLoadingTracker::ImageRepresentation::ResizeCondition resize_method,
+ const gfx::Size& decoded_size,
+ const gfx::Size& desired_size) {
+ switch (resize_method) {
+ case ImageLoadingTracker::ImageRepresentation::ALWAYS_RESIZE:
+ return decoded_size != desired_size;
+ case ImageLoadingTracker::ImageRepresentation::RESIZE_WHEN_LARGER:
+ return decoded_size.width() > desired_size.width() ||
+ decoded_size.height() > desired_size.height();
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
+} // namespace
+
////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker::Observer
ImageLoadingTracker::Observer::~Observer() {}
////////////////////////////////////////////////////////////////////////////////
-// ImageLoadingTracker::ImageInfo
+// ImageLoadingTracker::ImageRepresentation
-ImageLoadingTracker::ImageInfo::ImageInfo(
- const ExtensionResource& resource, gfx::Size max_size)
- : resource(resource), max_size(max_size) {
+ImageLoadingTracker::ImageRepresentation::ImageRepresentation(
+ const ExtensionResource& resource,
+ ResizeCondition resize_method,
+ const gfx::Size& desired_size,
+ ui::ScaleFactor scale_factor)
+ : resource(resource),
+ resize_method(resize_method),
+ desired_size(desired_size),
+ scale_factor(scale_factor) {
}
-ImageLoadingTracker::ImageInfo::~ImageInfo() {
+ImageLoadingTracker::ImageRepresentation::~ImageRepresentation() {
}
////////////////////////////////////////////////////////////////////////////////
@@ -58,8 +108,8 @@ ImageLoadingTracker::PendingLoadInfo::~PendingLoadInfo() {}
////////////////////////////////////////////////////////////////////////////////
// ImageLoadingTracker::ImageLoader
-// A RefCounted class for loading images on the File thread and reporting back
-// on the UI thread.
+// A RefCounted class for loading bitmaps/image reps on the File thread and
+// reporting back on the UI thread.
class ImageLoadingTracker::ImageLoader
: public base::RefCountedThreadSafe<ImageLoader> {
public:
@@ -76,106 +126,104 @@ class ImageLoadingTracker::ImageLoader
}
// Instructs the loader to load a task on the File thread.
- void LoadImage(const ExtensionResource& resource,
- const gfx::Size& max_size,
- int id) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ void LoadImage(const ImageRepresentation& image_info, int id) {
+ DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_));
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&ImageLoader::LoadOnFileThread, this, resource,
- max_size, id));
+ base::Bind(&ImageLoader::LoadOnFileThread, this, image_info, id));
}
- void LoadOnFileThread(const ExtensionResource& resource,
- const gfx::Size& max_size,
- int id) {
+ void LoadOnFileThread(const ImageRepresentation& image_info, int id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
// Read the file from disk.
std::string file_contents;
- FilePath path = resource.GetFilePath();
+ FilePath path = image_info.resource.GetFilePath();
if (path.empty() || !file_util::ReadFileToString(path, &file_contents)) {
- ReportBack(NULL, resource, gfx::Size(), id);
+ ReportBack(NULL, image_info, gfx::Size(), id, false);
return;
}
- // Decode the image using WebKit's image decoder.
+ // Decode the bitmap using WebKit's image decoder.
const unsigned char* data =
reinterpret_cast<const unsigned char*>(file_contents.data());
webkit_glue::ImageDecoder decoder;
scoped_ptr<SkBitmap> decoded(new SkBitmap());
- // Note: This class only decodes images from extension resources. Chrome
+ // Note: This class only decodes bitmaps from extension resources. Chrome
// doesn't (for security reasons) directly load extension resources provided
// by the extension author, but instead decodes them in a separate
// locked-down utility process. Only if the decoding succeeds is the image
// saved from memory to disk and subsequently used in the Chrome UI.
- // Chrome is therefore decoding images here that were generated by Chrome.
+ // Chrome is therefore decoding bitmaps here that were generated by Chrome.
*decoded = decoder.Decode(data, file_contents.length());
if (decoded->empty()) {
- ReportBack(NULL, resource, gfx::Size(), id);
+ ReportBack(NULL, image_info, gfx::Size(), id, false);
return; // Unable to decode.
}
gfx::Size original_size(decoded->width(), decoded->height());
-
- if (decoded->width() > max_size.width() ||
- decoded->height() > max_size.height()) {
- // The bitmap is too big, re-sample.
+ if (ShouldResizeImageRepresentation(image_info.resize_method,
+ original_size,
+ image_info.desired_size)) {
*decoded = skia::ImageOperations::Resize(
*decoded, skia::ImageOperations::RESIZE_LANCZOS3,
- max_size.width(), max_size.height());
+ image_info.desired_size.width(), image_info.desired_size.height());
}
- ReportBack(decoded.release(), resource, original_size, id);
+ ReportBack(decoded.release(), image_info, original_size, id,
+ true /* delete bitmap */);
}
// Instructs the loader to load a resource on the File thread.
- void LoadResource(const ExtensionResource& resource,
- const gfx::Size& max_size,
+ void LoadResource(const ImageRepresentation& image_info,
int id,
int resource_id) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_));
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&ImageLoader::LoadResourceOnFileThread, this, resource,
- max_size, id, resource_id));
+ base::Bind(&ImageLoader::LoadResourceOnFileThread, this, image_info,
+ id, resource_id));
}
- void LoadResourceOnFileThread(const ExtensionResource& resource,
- const gfx::Size& max_size,
+ void LoadResourceOnFileThread(const ImageRepresentation& image_info,
int id,
int resource_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- SkBitmap* image = ExtensionIconSource::LoadImageByResourceId(
- resource_id);
- ReportBack(image, resource, max_size, id);
+ const SkBitmap* bitmap = ResourceBundle::GetSharedInstance().GetImageNamed(
+ resource_id).ToSkBitmap();
+ ReportBack(bitmap, image_info, image_info.desired_size, id,
+ false /* don't delete bitmap */);
}
- void ReportBack(SkBitmap* image, const ExtensionResource& resource,
- const gfx::Size& original_size, int id) {
+ void ReportBack(const SkBitmap* bitmap, const ImageRepresentation& image_info,
+ const gfx::Size& original_size, int id, bool delete_bitmap) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
BrowserThread::PostTask(
callback_thread_id_, FROM_HERE,
- base::Bind(&ImageLoader::ReportOnUIThread, this,
- image, resource, original_size, id));
+ base::Bind(&ImageLoader::ReportOnCallingThread, this,
+ bitmap, image_info, original_size, id, delete_bitmap));
}
- void ReportOnUIThread(SkBitmap* image, const ExtensionResource& resource,
- const gfx::Size& original_size, int id) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ void ReportOnCallingThread(const SkBitmap* bitmap,
+ const ImageRepresentation& image_info,
+ const gfx::Size& original_size,
+ int id,
+ bool delete_bitmap) {
+ DCHECK(BrowserThread::CurrentlyOn(callback_thread_id_));
if (tracker_)
- tracker_->OnImageLoaded(image, resource, original_size, id, true);
+ tracker_->OnBitmapLoaded(bitmap, image_info, original_size, id, true);
- delete image;
+ if (bitmap && delete_bitmap)
+ delete bitmap;
}
private:
friend class base::RefCountedThreadSafe<ImageLoader>;
~ImageLoader() {}
- // The tracker we are loading the image for. If NULL, it means the tracker is
+ // The tracker we are loading the bitmap for. If NULL, it means the tracker is
// no longer interested in the reply.
ImageLoadingTracker* tracker_;
@@ -206,14 +254,19 @@ void ImageLoadingTracker::LoadImage(const Extension* extension,
const ExtensionResource& resource,
const gfx::Size& max_size,
CacheParam cache) {
- std::vector<ImageInfo> info_list;
- info_list.push_back(ImageInfo(resource, max_size));
+ std::vector<ImageRepresentation> info_list;
+ info_list.push_back(ImageRepresentation(
+ resource,
+ ImageRepresentation::RESIZE_WHEN_LARGER,
+ max_size,
+ ui::SCALE_FACTOR_100P));
LoadImages(extension, info_list, cache);
}
-void ImageLoadingTracker::LoadImages(const Extension* extension,
- const std::vector<ImageInfo>& info_list,
- CacheParam cache) {
+void ImageLoadingTracker::LoadImages(
+ const Extension* extension,
+ const std::vector<ImageRepresentation>& info_list,
+ CacheParam cache) {
PendingLoadInfo load_info;
load_info.extension = extension;
load_info.cache = cache;
@@ -222,37 +275,32 @@ void ImageLoadingTracker::LoadImages(const Extension* extension,
int id = next_id_++;
load_map_[id] = load_info;
- for (std::vector<ImageInfo>::const_iterator it = info_list.begin();
+ for (std::vector<ImageRepresentation>::const_iterator it = info_list.begin();
it != info_list.end(); ++it) {
+ int resource_id = -1;
+
// Load resources for special component extensions.
- if (load_info.extension_id == extension_misc::kWebStoreAppId) {
- if (!loader_)
- loader_ = new ImageLoader(this);
- loader_->LoadResource(it->resource, it->max_size, id, IDR_WEBSTORE_ICON);
- continue;
- } else if (load_info.extension_id == extension_misc::kChromeAppId) {
+ if (FindSpecialExtensionResourceId(load_info.extension_id, &resource_id)) {
if (!loader_)
loader_ = new ImageLoader(this);
- loader_->LoadResource(it->resource,
- it->max_size,
- id,
- IDR_PRODUCT_LOGO_128);
+ loader_->LoadResource(*it, id, resource_id);
continue;
}
// If we don't have a path we don't need to do any further work, just
// respond back.
if (it->resource.relative_path().empty()) {
- OnImageLoaded(NULL, it->resource, it->max_size, id, false);
+ OnBitmapLoaded(NULL, *it, it->desired_size, id, false);
continue;
}
DCHECK(extension->path() == it->resource.extension_root());
- // See if the extension has the image already.
- if (extension->HasCachedImage(it->resource, it->max_size)) {
- SkBitmap image = extension->GetCachedImage(it->resource, it->max_size);
- OnImageLoaded(&image, it->resource, it->max_size, id, false);
+ // See if the extension has the bitmap already.
+ if (extension->HasCachedImage(it->resource, it->desired_size)) {
+ SkBitmap bitmap = extension->GetCachedImage(it->resource,
+ it->desired_size);
+ OnBitmapLoaded(&bitmap, *it, it->desired_size, id, false);
continue;
}
@@ -261,11 +309,10 @@ void ImageLoadingTracker::LoadImages(const Extension* extension,
if (!loader_)
loader_ = new ImageLoader(this);
- int resource_id;
if (IsComponentExtensionResource(extension, it->resource, resource_id))
- loader_->LoadResource(it->resource, it->max_size, id, resource_id);
+ loader_->LoadResource(*it, id, resource_id);
else
- loader_->LoadImage(it->resource, it->max_size, id);
+ loader_->LoadImage(*it, id);
}
}
@@ -293,9 +340,9 @@ bool ImageLoadingTracker::IsComponentExtensionResource(
return false;
}
-void ImageLoadingTracker::OnImageLoaded(
- SkBitmap* image,
- const ExtensionResource& resource,
+void ImageLoadingTracker::OnBitmapLoaded(
+ const SkBitmap* bitmap,
+ const ImageRepresentation& image_info,
const gfx::Size& original_size,
int id,
bool should_cache) {
@@ -304,38 +351,33 @@ void ImageLoadingTracker::OnImageLoaded(
PendingLoadInfo* info = &load_map_it->second;
// Save the pending results.
- DCHECK(info->pending_count > 0);
+ DCHECK_GT(info->pending_count, 0u);
info->pending_count--;
- if (image)
- info->bitmaps.push_back(*image);
+ if (bitmap) {
+ info->image_skia.AddRepresentation(gfx::ImageSkiaRep(*bitmap,
+ image_info.scale_factor));
+ }
- // Add to the extension's image cache if requested.
+ // Add to the extension's bitmap cache if requested.
DCHECK(info->cache != CACHE || info->extension);
- if (should_cache && info->cache == CACHE && !resource.empty() &&
- !info->extension->HasCachedImage(resource, original_size)) {
- info->extension->SetCachedImage(resource, image ? *image : SkBitmap(),
+ if (should_cache && info->cache == CACHE && !image_info.resource.empty() &&
+ !info->extension->HasCachedImage(image_info.resource, original_size)) {
+ info->extension->SetCachedImage(image_info.resource,
+ bitmap ? *bitmap : SkBitmap(),
original_size);
}
- // If all pending images are done then report back.
+ // If all pending bitmaps are done then report back.
if (info->pending_count == 0) {
gfx::Image image;
std::string extension_id = info->extension_id;
- if (info->bitmaps.size() > 0) {
- gfx::ImageSkia image_skia;
- for (std::vector<SkBitmap>::const_iterator it = info->bitmaps.begin();
- it != info->bitmaps.end(); ++it) {
- // TODO(pkotwicz): Do something better but ONLY when DIP is enabled.
- image_skia.AddRepresentation(
- gfx::ImageSkiaRep(*it, ui::SCALE_FACTOR_100P));
- }
- image = gfx::Image(image_skia);
- }
+ if (!info->image_skia.empty())
+ image = gfx::Image(info->image_skia);
load_map_.erase(load_map_it);
- // ImageLoadingTracker might be deleted after the callback so don't
+ // ImageLoadingTracker might be deleted after the callback so don't do
// anything after this statement.
observer_->OnImageLoaded(image, extension_id, id);
}
@@ -350,7 +392,7 @@ void ImageLoadingTracker::Observe(int type,
content::Details<extensions::UnloadedExtensionInfo>(details)->extension;
// Remove reference to this extension from all pending load entries. This
- // ensures we don't attempt to cache the image when the load completes.
+ // ensures we don't attempt to cache the bitmap when the load completes.
for (LoadMap::iterator i = load_map_.begin(); i != load_map_.end(); ++i) {
PendingLoadInfo* info = &i->second;
if (info->extension == extension) {
« no previous file with comments | « chrome/browser/extensions/image_loading_tracker.h ('k') | chrome/browser/extensions/image_loading_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698