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..5c639772f9b0a58fa74a19d288e7989889c77429 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,10 @@ class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { |
} |
if (fetch_new_image && source_.get()) { |
+ DCHECK(CalledOnValidThread()) << |
+ "An ImageSkia with an ImageSkiaSource is accessed " |
+ "by more than one thread."; |
+ |
ImageSkiaRep image = source_->GetImageForScale(scale_factor); |
// If the source returned the new image, store it. |
@@ -120,7 +133,8 @@ class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { |
} |
private: |
- ~ImageSkiaStorage() { |
+ virtual ~ImageSkiaStorage() { |
+ DetachFromThread(); |
} |
// Vector of bitmaps and their associated scale factor. |
@@ -175,6 +189,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 +243,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 +279,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()) { |