Commit eff5ce7f authored by Toni Barzic's avatar Toni Barzic Committed by Chromium LUCI CQ

Fix holding space image lifetime issues

HoldingSpaceImage's image source has a pointer to the HoldingSpaceImage,
so it can notify it that new image representation has been loaded.
Image source is owned by the image itself, and may outlive the
associated HoldingSpaceItem, which owns HoldingSpaceImage. If the
thumbnail generation for the item finishes after the item has been
destroyed, the holding space image source may attempt to access the
HoldingSpaceImage object after destruction.
To fix this, pass a weak pointer to HoldingSpaceImage source, so it can
verify the HoldingSpaceImage is still around before notifying it that
the image has changed.

HoldingSpcareTrayIconPreview contents image had a similar issue where it
was getting the item image from the item ptr. This was done in
GetImageForScale, which may get called as long as the associated image
skia is around, which doesn't guarantee that the item has not already
been deleted - instead, have the contents image use the image skia
directly.

BUG=1156776

Change-Id: I6e6c6d14ed5a25739e8b4366225f29dfa8706c8e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2587655Reviewed-by: default avatarDavid Black <dmblack@google.com>
Commit-Queue: Toni Baržić <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836402}
parent febe5152
...@@ -17,7 +17,7 @@ namespace ash { ...@@ -17,7 +17,7 @@ namespace ash {
class HoldingSpaceImage::ImageSkiaSource : public gfx::ImageSkiaSource { class HoldingSpaceImage::ImageSkiaSource : public gfx::ImageSkiaSource {
public: public:
ImageSkiaSource(HoldingSpaceImage* owner, ImageSkiaSource(const base::WeakPtr<HoldingSpaceImage>& owner,
const gfx::ImageSkia& placeholder, const gfx::ImageSkia& placeholder,
AsyncBitmapResolver async_bitmap_resolver) AsyncBitmapResolver async_bitmap_resolver)
: owner_(owner), : owner_(owner),
...@@ -48,11 +48,12 @@ class HoldingSpaceImage::ImageSkiaSource : public gfx::ImageSkiaSource { ...@@ -48,11 +48,12 @@ class HoldingSpaceImage::ImageSkiaSource : public gfx::ImageSkiaSource {
void CacheImageForScale(float scale, const SkBitmap* bitmap) { void CacheImageForScale(float scale, const SkBitmap* bitmap) {
if (bitmap) { if (bitmap) {
cache_[scale].AddRepresentation(gfx::ImageSkiaRep(*bitmap, scale)); cache_[scale].AddRepresentation(gfx::ImageSkiaRep(*bitmap, scale));
owner_->NotifyUpdated(scale); if (owner_)
owner_->NotifyUpdated(scale);
} }
} }
HoldingSpaceImage* const owner_; const base::WeakPtr<HoldingSpaceImage> owner_;
const gfx::ImageSkia placeholder_; const gfx::ImageSkia placeholder_;
AsyncBitmapResolver async_bitmap_resolver_; AsyncBitmapResolver async_bitmap_resolver_;
std::map<float, gfx::ImageSkia> cache_; std::map<float, gfx::ImageSkia> cache_;
...@@ -62,12 +63,14 @@ class HoldingSpaceImage::ImageSkiaSource : public gfx::ImageSkiaSource { ...@@ -62,12 +63,14 @@ class HoldingSpaceImage::ImageSkiaSource : public gfx::ImageSkiaSource {
// HoldingSpaceImage ----------------------------------------------------------- // HoldingSpaceImage -----------------------------------------------------------
HoldingSpaceImage::HoldingSpaceImage(const gfx::ImageSkia& placeholder, HoldingSpaceImage::HoldingSpaceImage(
AsyncBitmapResolver async_bitmap_resolver) const gfx::ImageSkia& placeholder,
: image_skia_(std::make_unique<ImageSkiaSource>(/*owner=*/this, AsyncBitmapResolver async_bitmap_resolver) {
placeholder, image_skia_ = gfx::ImageSkia(
async_bitmap_resolver), std::make_unique<ImageSkiaSource>(/*owner=*/weak_factory_.GetWeakPtr(),
placeholder.size()) {} placeholder, async_bitmap_resolver),
placeholder.size());
}
HoldingSpaceImage::~HoldingSpaceImage() = default; HoldingSpaceImage::~HoldingSpaceImage() = default;
......
...@@ -51,6 +51,8 @@ class ASH_PUBLIC_EXPORT HoldingSpaceImage { ...@@ -51,6 +51,8 @@ class ASH_PUBLIC_EXPORT HoldingSpaceImage {
// Mutable to allow const access from `AddImageSkiaChangedCallback()`. // Mutable to allow const access from `AddImageSkiaChangedCallback()`.
mutable CallbackList callback_list_; mutable CallbackList callback_list_;
base::WeakPtrFactory<HoldingSpaceImage> weak_factory_{this};
}; };
} // namespace ash } // namespace ash
......
...@@ -67,7 +67,8 @@ void SetUpAnimation(ui::ScopedLayerAnimationSettings* animation_settings) { ...@@ -67,7 +67,8 @@ void SetUpAnimation(ui::ScopedLayerAnimationSettings* animation_settings) {
class ContentsImageSource : public gfx::ImageSkiaSource { class ContentsImageSource : public gfx::ImageSkiaSource {
public: public:
explicit ContentsImageSource(const HoldingSpaceItem* item) : item_(item) {} explicit ContentsImageSource(gfx::ImageSkia item_image)
: item_image_(item_image) {}
ContentsImageSource(const ContentsImageSource&) = delete; ContentsImageSource(const ContentsImageSource&) = delete;
ContentsImageSource& operator=(const ContentsImageSource&) = delete; ContentsImageSource& operator=(const ContentsImageSource&) = delete;
~ContentsImageSource() override = default; ~ContentsImageSource() override = default;
...@@ -75,7 +76,7 @@ class ContentsImageSource : public gfx::ImageSkiaSource { ...@@ -75,7 +76,7 @@ class ContentsImageSource : public gfx::ImageSkiaSource {
private: private:
// gfx::ImageSkiaSource: // gfx::ImageSkiaSource:
gfx::ImageSkiaRep GetImageForScale(float scale) override { gfx::ImageSkiaRep GetImageForScale(float scale) override {
gfx::ImageSkia image = item_->image().image_skia(); gfx::ImageSkia image = item_image_;
// Crop to square (if necessary). // Crop to square (if necessary).
gfx::Size square_size = image.size(); gfx::Size square_size = image.size();
...@@ -105,7 +106,7 @@ class ContentsImageSource : public gfx::ImageSkiaSource { ...@@ -105,7 +106,7 @@ class ContentsImageSource : public gfx::ImageSkiaSource {
return gfx::ImageSkiaRep(canvas.GetBitmap(), scale); return gfx::ImageSkiaRep(canvas.GetBitmap(), scale);
} }
const HoldingSpaceItem* item_; const gfx::ImageSkia item_image_;
}; };
// ContentsImage --------------------------------------------------------------- // ContentsImage ---------------------------------------------------------------
...@@ -114,8 +115,9 @@ class ContentsImage : public gfx::ImageSkia { ...@@ -114,8 +115,9 @@ class ContentsImage : public gfx::ImageSkia {
public: public:
ContentsImage(const HoldingSpaceItem* item, ContentsImage(const HoldingSpaceItem* item,
base::RepeatingClosure image_invalidated_closure) base::RepeatingClosure image_invalidated_closure)
: gfx::ImageSkia(std::make_unique<ContentsImageSource>(item), : gfx::ImageSkia(
GetPreviewSize()), std::make_unique<ContentsImageSource>(item->image().image_skia()),
GetPreviewSize()),
image_invalidated_closure_(image_invalidated_closure) { image_invalidated_closure_(image_invalidated_closure) {
image_subscription_ = item->image().AddImageSkiaChangedCallback( image_subscription_ = item->image().AddImageSkiaChangedCallback(
base::BindRepeating(&ContentsImage::OnHoldingSpaceItemImageChanged, base::BindRepeating(&ContentsImage::OnHoldingSpaceItemImageChanged,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment