Chromium Code Reviews| Index: ui/gfx/image/image_skia.cc |
| diff --git a/ui/gfx/image/image_skia.cc b/ui/gfx/image/image_skia.cc |
| index 65f2d48741233911458e18986c57f6ea12c4d56c..21de0877b23b8c3a390da998909ba448da63ab21 100644 |
| --- a/ui/gfx/image/image_skia.cc |
| +++ b/ui/gfx/image/image_skia.cc |
| @@ -10,6 +10,7 @@ |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| +#include "base/threading/non_thread_safe.h" |
| #include "ui/gfx/image/image_skia_operations.h" |
| #include "ui/gfx/image/image_skia_source.h" |
| #include "ui/gfx/rect.h" |
| @@ -48,11 +49,15 @@ class Matcher { |
| // A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a |
| // refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's |
| // information. |
| -class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { |
| +class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage>, |
| + public base::NonThreadSafe { |
| public: |
| ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size) |
| : source_(source), |
| size_(size) { |
| + // We only care if the storage is modified by the same thread. |
| + // Don't blow up even if someone else created/deleted the ImageSkia. |
| + DetachFromThread(); |
| } |
| bool has_source() const { return source_.get() != NULL; } |
| @@ -61,6 +66,10 @@ class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { |
| const gfx::Size& size() const { return size_; } |
| + void DeleteSource() { |
| + source_.reset(); |
| + } |
| + |
| // Returns the iterator of the image rep whose density best matches |
| // |scale_factor|. If the image for the |scale_factor| doesn't exist |
| // in the storage and |storage| is set, it fetches new image by calling |
| @@ -96,6 +105,11 @@ class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { |
| } |
| if (fetch_new_image && source_.get()) { |
| + // TODO(oshima): Make this DCHECK for M23. crbug.com/144367. |
|
oshima
2012/08/23 14:21:09
Looks like NonThreadSafe is no-op in release build
|
| + CHECK(CalledOnValidThread()) << |
| + "More than one thread is tring to access ImageSkia which has " |
| + "ImageSkiaSource. This is thread unsafe operation and not allowed"; |
| + |
| ImageSkiaRep image = source_->GetImageForScale(scale_factor); |
| // If the source returned the new image, store it. |
| @@ -120,7 +134,8 @@ class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { |
| } |
| private: |
| - ~ImageSkiaStorage() { |
| + virtual ~ImageSkiaStorage() { |
| + DetachFromThread(); |
| } |
| // Vector of bitmaps and their associated scale factor. |
| @@ -175,6 +190,13 @@ bool ImageSkia::BackedBySameObjectAs(const gfx::ImageSkia& other) const { |
| void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) { |
| DCHECK(!image_rep.is_null()); |
| + // TODO(oshima): This method should be called |SetRepresentation| |
| + // and replace the existing rep if there is already one with the |
| + // same scale factor so that we can guarantee that a ImageSkia |
| + // instance contians only one image rep per scale factor. This is |
| + // not possible now as ImageLoadingTracker currently stores need |
| + // this feature, but this needs to be fixed. |
| + |
| if (isNull()) |
| Init(image_rep); |
| else |
| @@ -222,15 +244,7 @@ std::vector<ImageSkiaRep> ImageSkia::GetRepresentations() const { |
| if (!storage_->has_source()) |
| return image_reps(); |
| - |
| - // Attempt to generate image reps for as many scale factors supported by |
| - // this platform as possible. |
| - // Do not build return array here because the mapping from scale factor to |
| - // image rep is one to many in some cases. |
| - std::vector<ui::ScaleFactor> supported_scale_factors = |
| - ui::GetSupportedScaleFactors(); |
| - for (size_t i = 0; i < supported_scale_factors.size(); ++i) |
| - storage_->FindRepresentation(supported_scale_factors[i], true); |
| + EnsureRepsForSupportedScaleFactors(); |
| return image_reps(); |
| } |
| @@ -266,6 +280,20 @@ std::vector<ImageSkiaRep> ImageSkia::image_reps() const { |
| return image_reps; |
| } |
| +void ImageSkia::DeleteSource() { |
| + if (storage_) |
| + storage_->DeleteSource(); |
| +} |
| + |
| +void ImageSkia::EnsureRepsForSupportedScaleFactors() const { |
| + if (storage_ && storage_->has_source()) { |
| + std::vector<ui::ScaleFactor> supported_scale_factors = |
| + ui::GetSupportedScaleFactors(); |
| + for (size_t i = 0; i < supported_scale_factors.size(); ++i) |
| + storage_->FindRepresentation(supported_scale_factors[i], true); |
| + } |
| +} |
| + |
| void ImageSkia::Init(const ImageSkiaRep& image_rep) { |
| // TODO(pkotwicz): The image should be null whenever image rep is null. |
| if (image_rep.sk_bitmap().empty()) { |