blob: 033b85a3fbc2151f72fb9c44211adb35436fd5c4 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_IMAGE_H_
#define CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_IMAGE_H_
#include <utility>
#include <vector>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "ui/gfx/image/image_skia.h"
// Stores compressed thumbnail data for a tab and can vend that data as an
// uncompressed image to observers.
class ThumbnailImage : public base::RefCounted<ThumbnailImage> {
public:
// Smart pointer to reference-counted compressed image data; in this case
// JPEG format.
using CompressedThumbnailData =
scoped_refptr<base::RefCountedData<std::vector<uint8_t>>>;
// Observes uncompressed and/or compressed versions of the thumbnail image as
// they are available.
class Observer : public base::CheckedObserver {
public:
// Receives uncompressed thumbnail image data. Default is no-op.
virtual void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image);
// Receives compressed thumbnail image data. Default is no-op.
virtual void OnCompressedThumbnailDataAvailable(
CompressedThumbnailData thumbnail_data);
};
// Represents the endpoint
class Delegate {
public:
// Called whenever the thumbnail starts or stops being observed.
// Because updating the thumbnail could be an expensive operation, it's
// useful to track when there are no observers. Default behavior is no-op.
virtual void ThumbnailImageBeingObservedChanged(bool is_being_observed) = 0;
protected:
virtual ~Delegate();
private:
friend class ThumbnailImage;
ThumbnailImage* thumbnail_ = nullptr;
};
explicit ThumbnailImage(Delegate* delegate);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
bool HasObserver(const Observer* observer) const;
// Sets the SkBitmap data and notifies observers with the resulting image.
void AssignSkBitmap(SkBitmap bitmap);
// Requests that a thumbnail image be made available to observers. Does not
// guarantee that Observer::OnThumbnailImageAvailable() will be called, or how
// long it will take, though in most cases it should happen very quickly.
virtual void RequestThumbnailImage();
void set_async_operation_finished_callback_for_testing(
base::RepeatingClosure callback) {
async_operation_finished_callback_ = std::move(callback);
}
private:
friend class Delegate;
friend class ThumbnailImageTest;
friend class base::RefCounted<ThumbnailImage>;
virtual ~ThumbnailImage();
void AssignJPEGData(std::vector<uint8_t> data);
bool ConvertJPEGDataToImageSkiaAndNotifyObservers();
void NotifyUncompressedDataObservers(gfx::ImageSkia image);
void NotifyCompressedDataObservers(CompressedThumbnailData data);
static std::vector<uint8_t> CompressBitmap(SkBitmap bitmap);
static gfx::ImageSkia UncompressImage(CompressedThumbnailData compressed);
Delegate* delegate_;
CompressedThumbnailData data_;
base::ObserverList<Observer> observers_;
// Called when an asynchronous operation (such as encoding image data upon
// assignment or decoding image data for observers) finishes or fails.
// Intended for unit tests that want to wait for internal operations following
// AssignSkBitmap() or RequestThumbnailImage() calls.
base::RepeatingClosure async_operation_finished_callback_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<ThumbnailImage> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ThumbnailImage);
};
#endif // CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_IMAGE_H_