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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
// Copyright (c) 2012 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_EXTENSIONS_IMAGE_LOADING_TRACKER_H_
#define CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_
#pragma once
#include <map>
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "chrome/common/extensions/extension_resource.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/gfx/size.h"
class SkBitmap;
namespace extensions {
class Extension;
}
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.
//
// 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
// SkBitmap 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.
//
class ImageLoadingTracker : 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 single image to load from a extension resource.
struct ImageInfo {
ImageInfo(const ExtensionResource& resource, gfx::Size max_size);
~ImageInfo();
ExtensionResource resource;
// If the loaded image is larger than |max_size| it will be resized to those
// dimensions.
gfx::Size max_size;
};
explicit ImageLoadingTracker(Observer* observer);
virtual ~ImageLoadingTracker();
// 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)
// if the image was found in the cache.
void LoadImage(const extensions::Extension* extension,
const ExtensionResource& resource,
const gfx::Size& max_size,
CacheParam cache);
// 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<ImageInfo>& 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_; }
private:
// Information for pending image load operation for one or more images.
struct PendingLoadInfo {
PendingLoadInfo();
~PendingLoadInfo();
const extensions::Extension* extension;
// This is cached separate from |extension| in case the extension in
// unloaded.
std::string extension_id;
CacheParam cache;
size_t pending_count;
std::vector<SkBitmap> bitmaps;
};
// Maps an integer identifying a load request to a PendingLoadInfo.
typedef std::map<int, PendingLoadInfo> LoadMap;
class ImageLoader;
// When an image has finished loaded and been resized on the file thread, it
// is posted back to this method on the original thread. This method then
// calls the observer's OnImageLoaded and deletes the ImageLoadingTracker if
// it was the last image in the list. The |original_size| should be the size
// of the image before any resizing was done.
// |image| may be null if the file failed to decode.
void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource,
const gfx::Size& original_size, int id, bool should_cache);
// 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|.
bool IsComponentExtensionResource(const extensions::Extension* extension,
const ExtensionResource& resource,
int& resource_id) const;
// content::NotificationObserver method. If an extension is uninstalled while
// we're waiting for the image we remove the entry from load_map_.
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_;
// ID to use for next image requested. This is an ever increasing integer.
int next_id_;
// The object responsible for loading the image on the File thread.
scoped_refptr<ImageLoader> loader_;
// Information for each LoadImage request is cached here. The integer
// identifies the id assigned to the request.
LoadMap load_map_;
content::NotificationRegistrar registrar_;
FRIEND_TEST_ALL_PREFIXES(ImageLoadingTrackerTest,
IsComponentExtensionResource);
DISALLOW_COPY_AND_ASSIGN(ImageLoadingTracker);
};
#endif // CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_
|