1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_BROWSER_EXTENSION_ICON_IMAGE_H_
#define EXTENSIONS_BROWSER_EXTENSION_ICON_IMAGE_H_
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/icons/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 ExtensionRegistryObserver {
public:
class Observer {
public:
// 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) {}
protected:
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(const IconImage&) = delete;
IconImage& operator=(const IconImage&) = delete;
~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; }
bool did_complete_initial_load() const { return did_complete_initial_load_; }
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
private:
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);
// ExtensionRegistryObserver:
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) override;
void OnShutdown(ExtensionRegistry* extension_registry) override;
raw_ptr<content::BrowserContext, AcrossTasksDanglingUntriaged>
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_;
// Set to true when the icon finishes the very first load (which can be
// asynchronous from creation).
bool did_complete_initial_load_;
base::ObserverList<Observer>::Unchecked observers_;
raw_ptr<Source, DanglingUntriaged> 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_;
base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
registry_observation_{this};
base::WeakPtrFactory<IconImage> weak_ptr_factory_{this};
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_EXTENSION_ICON_IMAGE_H_
|