Chromium Code Reviews| Index: chrome/browser/extensions/image_loader.h |
| diff --git a/chrome/browser/extensions/image_loading_tracker.h b/chrome/browser/extensions/image_loader.h |
| similarity index 39% |
| copy from chrome/browser/extensions/image_loading_tracker.h |
| copy to chrome/browser/extensions/image_loader.h |
| index 5eefcd1840f2a66637a06a13204562ae1f476b04..4a8de964b7630287b316430ec3ce5b1fdb2621f2 100644 |
| --- a/chrome/browser/extensions/image_loading_tracker.h |
| +++ b/chrome/browser/extensions/image_loader.h |
| @@ -2,71 +2,47 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#ifndef CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_ |
| -#define CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_ |
| +#ifndef CHROME_BROWSER_EXTENSIONS_IMAGE_LOADER_H_ |
| +#define CHROME_BROWSER_EXTENSIONS_IMAGE_LOADER_H_ |
| #include <map> |
| -#include <string> |
| -#include <vector> |
| +#include <set> |
| -#include "base/compiler_specific.h" |
| +#include "base/callback_forward.h" |
| #include "base/gtest_prod_util.h" |
| -#include "base/memory/ref_counted.h" |
| -#include "chrome/common/extensions/extension_icon_set.h" |
| #include "chrome/common/extensions/extension_resource.h" |
| #include "content/public/browser/notification_observer.h" |
| #include "content/public/browser/notification_registrar.h" |
| +#include "third_party/skia/include/core/SkBitmap.h" |
| #include "ui/base/layout.h" |
| -#include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/size.h" |
| -class SkBitmap; |
| +template <typename T> struct DefaultSingletonTraits; |
| -namespace extensions { |
| -class Extension; |
| -} |
| +FORWARD_DECLARE_TEST(ImageLoaderTest, Cache); |
| +FORWARD_DECLARE_TEST(ImageLoaderTest, DeleteExtensionWhileWaitingForCache); |
| +FORWARD_DECLARE_TEST(ImageLoaderTest, MultipleImages); |
| namespace gfx { |
| class Image; |
| } |
| -// The views need to load their icons asynchronously but might be deleted before |
| -// the images have loaded. This class encapsulates a loader class that stays |
| -// alive while the request is in progress (manages its own lifetime) and keeps |
| -// track of whether the view still cares about the icon loading. |
| +namespace extensions { |
| + |
| +class Extension; |
| + |
| +// This class is responsible for asynchronously loading extension images and |
| +// calling a callback when an image is loaded. |
| +// The views need to load their icons asynchronously might be deleted before |
| +// the images have loaded. If you pass your callback using a weak_ptr, this |
| +// will make sure the callback won't be called after the view is deleted. |
| // |
| -// To use this class, have your class derive from ImageLoadingTracker::Observer, |
| -// and add a member variable ImageLoadingTracker tracker_. Then override |
| -// Observer::OnImageLoaded and call: |
| -// tracker_.LoadImage(extension, resource, max_size, false); |
| -// ... and wait for OnImageLoaded to be called back on you with a pointer to the |
| -// ImageSkia loaded. |
| -// NOTE: if the image is available already (or the resource is not valid), the |
| -// Observer is notified immediately from the call to LoadImage. In other words, |
| -// by the time LoadImage returns the observer has been notified. |
| +// NOTE: if the image is available already, the callback is called immediately |
| +// from the call to LoadImageAsync. In other words, by the time LoadImageAsync |
| +// returns the callback has been notified. |
| // |
| -class ImageLoadingTracker : public content::NotificationObserver { |
| +class ImageLoader : public content::NotificationObserver { |
| public: |
| - enum CacheParam { |
| - CACHE, |
| - DONT_CACHE |
| - }; |
| - |
| - class Observer { |
| - public: |
| - // Will be called when the image with the given index has loaded. |
| - // |image| can be empty if a valid image was not found or it failed to |
| - // decode. |extension_id| is the ID of the extension the images are loaded |
| - // from. |index| represents the index of the image just loaded (starts at 0 |
| - // and increments every time LoadImage is called). |
| - virtual void OnImageLoaded(const gfx::Image& image, |
| - const std::string& extension_id, |
| - int index) = 0; |
| - |
| - protected: |
| - virtual ~Observer(); |
| - }; |
| - |
| // Information about a singe image representation to load from an extension |
| // resource. |
| struct ImageRepresentation { |
| @@ -78,7 +54,7 @@ class ImageLoadingTracker : public content::NotificationObserver { |
| }; |
| ImageRepresentation(const ExtensionResource& resource, |
| - ResizeCondition resize_method, |
| + ResizeCondition resize_condition, |
| const gfx::Size& desired_size, |
| ui::ScaleFactor scale_factor); |
| ~ImageRepresentation(); |
| @@ -86,7 +62,7 @@ class ImageLoadingTracker : public content::NotificationObserver { |
| // Extension resource to load. |
| ExtensionResource resource; |
| - ResizeCondition resize_method; |
| + ResizeCondition resize_condition; |
| // When |resize_method| is ALWAYS_RESIZE or when the loaded image is larger |
| // than |desired_size| it will be resized to these dimensions. |
| @@ -96,91 +72,115 @@ class ImageLoadingTracker : public content::NotificationObserver { |
| ui::ScaleFactor scale_factor; |
| }; |
| - explicit ImageLoadingTracker(Observer* observer); |
| - virtual ~ImageLoadingTracker(); |
| + static ImageLoader* GetInstance(); |
| + |
| + // Checks whether image is a component extension resource. Returns false |
| + // if a given |resource| does not have a corresponding image in bundled |
| + // resources. Otherwise fills |resource_id|. |
| + static bool IsComponentExtensionResource( |
| + const extensions::Extension* extension, |
| + const FilePath& resource_path, |
| + int* resource_id); |
| // Specify image resource to load. If the loaded image is larger than |
| // |max_size| it will be resized to those dimensions. IMPORTANT NOTE: this |
| - // function may call back your observer synchronously (ie before it returns) |
| + // function may call back your callback synchronously (ie before it returns) |
| // if the image was found in the cache. |
| // Note this method loads a raw bitmap from the resource. All sizes given are |
| // assumed to be in pixels. |
| - void LoadImage(const extensions::Extension* extension, |
| - const ExtensionResource& resource, |
| - const gfx::Size& max_size, |
| - CacheParam cache); |
| + void LoadImageAsync(const extensions::Extension* extension, |
| + const ExtensionResource& resource, |
| + const gfx::Size& max_size, |
| + const base::Callback<void(const gfx::Image&)>& callback); |
| // Same as LoadImage() above except it loads multiple images from the same |
| // extension. This is used to load multiple resolutions of the same image |
| // type. |
| - void LoadImages(const extensions::Extension* extension, |
| - const std::vector<ImageRepresentation>& info_list, |
| - CacheParam cache); |
| - |
| - // Returns the ID used for the next image that is loaded. That is, the return |
| - // value from this method corresponds to the int that is passed to |
| - // OnImageLoaded() the next time LoadImage() is invoked. |
| - int next_id() const { return next_id_; } |
| + void LoadImagesAsync(const extensions::Extension* extension, |
| + const std::vector<ImageRepresentation>& info_list, |
| + const base::Callback<void(const gfx::Image&)>& callback); |
| - // Checks whether image is a component extension resource. Returns false |
| - // if a given |resource| does not have a corresponding image in bundled |
| - // resources. Otherwise fills |resource_id|. |
| - static bool IsComponentExtensionResource( |
| - const extensions::Extension* extension, |
| - const FilePath& resource_path, |
| - int* resource_id); |
| + void SetCachedImage(const ExtensionResource& source, |
| + const SkBitmap& image, |
| + const gfx::Size& original_size) const; |
| private: |
| - // Information for pending resource load operation for one or more image |
| - // representations. |
| + friend struct DefaultSingletonTraits<ImageLoader>; |
| + |
| + // We keep a cache of images loaded from extension resources based on their |
| + // path and a string representation of a size that may have been used to |
| + // scale it (or the empty string if the image is at its original size). |
| + typedef std::pair<FilePath, std::string> ImageCacheKey; |
| + typedef std::map<ImageCacheKey, SkBitmap> ImageCache; |
| + |
| struct PendingLoadInfo { |
| PendingLoadInfo(); |
| ~PendingLoadInfo(); |
| - const extensions::Extension* extension; |
| - // This is cached separate from |extension| in case the extension is |
| - // unloaded. |
| std::string extension_id; |
| - CacheParam cache; |
| - size_t pending_count; |
| - gfx::ImageSkia image_skia; |
| + bool save_to_cache; |
| }; |
| - // Maps an integer identifying a load request to a PendingLoadInfo. |
| - typedef std::map<int, PendingLoadInfo> LoadMap; |
| + typedef std::set<PendingLoadInfo*> LoadSet; |
| + |
| + struct LoadResult { |
| + LoadResult(const SkBitmap& bitmap, |
| + const gfx::Size& original_size, |
| + const ImageRepresentation& image_representation); |
| + ~LoadResult(); |
| + |
| + SkBitmap bitmap; |
| + gfx::Size original_size; |
| + ImageRepresentation image_representation; |
| + }; |
| - class ImageLoader; |
| + ImageLoader(); |
| + virtual ~ImageLoader(); |
| - // Called on the calling thread when the bitmap finishes loading. |
| - // |bitmap| may be null if the image file failed to decode. |
| - void OnBitmapLoaded(const SkBitmap* bitmap, |
| - const ImageRepresentation& image_info, |
| - const gfx::Size& original_size, |
| - int id, |
| - bool should_cache); |
| + void LoadImagesOnBlockingPool( |
| + const std::vector<ImageRepresentation>& info_list, |
| + const std::vector<SkBitmap*>& bitmaps, |
| + PendingLoadInfo* load_info, |
| + const base::Callback<void(const gfx::Image&)>& callback); |
| + |
| + void ReplyBack( |
| + const std::vector<LoadResult>& load_result, |
| + PendingLoadInfo* load_info, |
| + const base::Callback<void(const gfx::Image&)>& callback); |
| // content::NotificationObserver method. If an extension is uninstalled while |
| - // we're waiting for the image we remove the entry from load_map_. |
| + // we're waiting for the image we make sure it won't be cached. |
| virtual void Observe(int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) OVERRIDE; |
| - // The view that is waiting for the image to load. |
| - Observer* observer_; |
| + void SetCachedImageImpl(const std::string& extension_id, |
| + const ImageCacheKey& key, |
| + const SkBitmap& image); |
| + |
| + const SkBitmap* GetCachedImage(const ExtensionResource& source, |
| + const gfx::Size& max_size) const; |
| - // ID to use for next image requested. This is an ever increasing integer. |
| - int next_id_; |
| + bool ShouldCacheImage(const ImageRepresentation& image_info) const; |
| + void SetImageSizesToCache(const std::set<int> image_sizes_); |
| - // The object responsible for loading the image on the File thread. |
| - scoped_refptr<ImageLoader> loader_; |
| + // Cached images for extensions. This should only be touched on the UI thread. |
| + std::map<std::string, ImageCache> image_cache_; |
| - // Information for each LoadImage request is cached here. The integer |
| - // identifies the id assigned to the request. |
| - LoadMap load_map_; |
| + // |
|
xiyuan
2012/10/10 20:30:22
nit: delete it or finish it? :)
Marijn Kruisselbrink
2012/10/10 22:33:03
Done.
|
| + LoadSet pending_; |
| + |
| + // Sizes of images to cache |
| + std::set<int> image_sizes_to_cache_; |
| content::NotificationRegistrar registrar_; |
| - DISALLOW_COPY_AND_ASSIGN(ImageLoadingTracker); |
| + FRIEND_TEST_ALL_PREFIXES(::ImageLoaderTest, Cache); |
| + FRIEND_TEST_ALL_PREFIXES(::ImageLoaderTest, |
| + DeleteExtensionWhileWaitingForCache); |
| + FRIEND_TEST_ALL_PREFIXES(::ImageLoaderTest, MultipleImages); |
| }; |
| -#endif // CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_ |
| +} // namespace extensions |
| + |
| +#endif // CHROME_BROWSER_EXTENSIONS_IMAGE_LOADER_H_ |