blob: b0629bfb4d761d6bec24c4730f9585fc58c4d4e6 [file] [log] [blame]
// Copyright 2014 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.
#include <map>
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "extensions/common/extension_icon_set.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"
namespace content {
class BrowserContext;
namespace extensions {
class Extension;
namespace gfx {
class Image;
namespace extensions {
// A class that provides an ImageSkia for UI code to use. It handles extension
// icon resource loading, screen scale factor change etc. UI code that uses
// extension icon should host this class. In painting code, UI code paints with
// the ImageSkia provided by this class. If the required extension icon resource
// is not already present, this class tries to load it and calls its observer
// interface when the image get updated. Until the resource is loaded, the UI
// code will be provided with a blank, transparent image.
// If the requested resource doesn't exist or can't be loaded and a default
// icon was supplied in the constructor, icon image will be updated with the
// default icon's resource.
// The default icon doesn't need to be supplied, but in that case, icon image
// representation will be left blank if the resource loading fails.
// If default icon is supplied, it is assumed that it contains or can
// synchronously create (when |GetRepresentation| is called on it)
// representations for all the scale factors supported by the current platform.
// Note that |IconImage| is not thread safe.
class IconImage : public content::NotificationObserver {
class Observer {
// Invoked when a new image rep for an additional scale factor
// is loaded and added to |image|.
virtual void OnExtensionIconImageChanged(IconImage* image) = 0;
// Called when this object is deleted. Objects should observe this if there
// is a question about the lifetime of the icon image vs observer.
virtual void OnExtensionIconImageDestroyed(IconImage* image) {}
virtual ~Observer() {}
// |context| is required by the underlying implementation to retrieve the
// |ImageLoader| instance associated with the given context. |ImageLoader| is
// used to perform the asynchronous image load work.
// Set |keep_original_size| to true to load the icon at the original size
// without resizing. In this case |resource_size_in_dip| will still be used to
// pick the correct icon representation. This is useful if the client code
// performs its own resizing.
IconImage(content::BrowserContext* context,
const Extension* extension,
const ExtensionIconSet& icon_set,
int resource_size_in_dip,
bool keep_original_size,
const gfx::ImageSkia& default_icon,
Observer* observer);
IconImage(content::BrowserContext* context,
const Extension* extension,
const ExtensionIconSet& icon_set,
int resource_size_in_dip,
const gfx::ImageSkia& default_icon,
Observer* observer);
~IconImage() override;
gfx::Image image() const { return image_; }
const gfx::ImageSkia& image_skia() const { return image_skia_; }
// Returns true if the icon is attached to an existing extension.
bool is_valid() const { return extension_ ? true : false; }
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
class Source;
// Loads an image representation for the scale factor asynchronously. Result
// is passed to OnImageRepLoaded.
void LoadImageForScaleAsync(float scale);
void OnImageLoaded(float scale, const gfx::Image& image);
void OnImageRepLoaded(const gfx::ImageSkiaRep& rep);
// content::NotificationObserver overrides:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
content::BrowserContext* browser_context_;
scoped_refptr<const Extension> extension_;
ExtensionIconSet icon_set_;
const int resource_size_in_dip_;
// Whether the loaded icon should be kept at the original size.
const bool keep_original_size_;
base::ObserverList<Observer>::Unchecked observers_;
Source* source_; // Owned by ImageSkia storage.
gfx::ImageSkia image_skia_;
// The icon with whose representation |image_skia_| should be updated if
// its own representation load fails.
gfx::ImageSkia default_icon_;
// The image wrapper around |image_skia_|.
// Note: this is reset each time a new representation is loaded.
gfx::Image image_;
content::NotificationRegistrar registrar_;
base::WeakPtrFactory<IconImage> weak_ptr_factory_;
} // namespace extensions