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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
// 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.
#include "base/json/json_file_value_serializer.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_icon_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/testing_profile.h"
#include "components/crx_file/id_util.h"
#include "content/public/test/test_browser_thread.h"
#include "extensions/common/extension.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/skia_util.h"
using content::BrowserThread;
using extensions::Extension;
using extensions::Manifest;
// Our test class that takes care of managing the necessary threads for loading
// extension icons, and waiting for those loads to happen.
class ExtensionIconManagerTest : public testing::Test {
public:
ExtensionIconManagerTest() :
unwaited_image_loads_(0),
waiting_(false),
ui_thread_(BrowserThread::UI, &ui_loop_),
file_thread_(BrowserThread::FILE),
io_thread_(BrowserThread::IO) {}
~ExtensionIconManagerTest() override {}
void ImageLoadObserved() {
unwaited_image_loads_++;
if (waiting_) {
base::MessageLoop::current()->Quit();
}
}
void WaitForImageLoad() {
if (unwaited_image_loads_ == 0) {
waiting_ = true;
base::MessageLoop::current()->Run();
waiting_ = false;
}
ASSERT_GT(unwaited_image_loads_, 0);
unwaited_image_loads_--;
}
private:
void SetUp() override {
file_thread_.Start();
io_thread_.Start();
}
// The number of observed image loads that have not been waited for.
int unwaited_image_loads_;
// Whether we are currently waiting for an image load.
bool waiting_;
base::MessageLoop ui_loop_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
content::TestBrowserThread io_thread_;
DISALLOW_COPY_AND_ASSIGN(ExtensionIconManagerTest);
};
// This is a specialization of ExtensionIconManager, with a special override to
// call back to the test when an icon has completed loading.
class TestIconManager : public ExtensionIconManager {
public:
explicit TestIconManager(ExtensionIconManagerTest* test) : test_(test) {}
~TestIconManager() override {}
// Overrides the ImageLoader callback, and calls through to the base class'
// implementation. Then it lets the test know that an image load was observed.
void OnImageLoaded(const std::string& extension_id,
const gfx::Image& image) override {
ExtensionIconManager::OnImageLoaded(extension_id, image);
test_->ImageLoadObserved();
}
private:
ExtensionIconManagerTest* test_;
DISALLOW_COPY_AND_ASSIGN(TestIconManager);
};
// Returns the default icon that ExtensionIconManager gives when an extension
// doesn't have an icon.
SkBitmap GetDefaultIcon() {
std::string dummy_id = crx_file::id_util::GenerateId("whatever");
ExtensionIconManager manager;
return manager.GetIcon(dummy_id);
}
// Tests loading an icon for an extension, removing it, then re-loading it.
TEST_F(ExtensionIconManagerTest, LoadRemoveLoad) {
scoped_ptr<Profile> profile(new TestingProfile());
SkBitmap default_icon = GetDefaultIcon();
base::FilePath test_dir;
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
base::FilePath manifest_path = test_dir.AppendASCII(
"extensions/image_loading_tracker/app.json");
JSONFileValueDeserializer deserializer(manifest_path);
scoped_ptr<base::DictionaryValue> manifest(
static_cast<base::DictionaryValue*>(deserializer.Deserialize(NULL,
NULL)));
ASSERT_TRUE(manifest.get() != NULL);
std::string error;
scoped_refptr<Extension> extension(Extension::Create(
manifest_path.DirName(), Manifest::INVALID_LOCATION, *manifest.get(),
Extension::NO_FLAGS, &error));
ASSERT_TRUE(extension.get());
TestIconManager icon_manager(this);
// Load the icon and grab the bitmap.
icon_manager.LoadIcon(profile.get(), extension.get());
WaitForImageLoad();
SkBitmap first_icon = icon_manager.GetIcon(extension->id());
EXPECT_FALSE(gfx::BitmapsAreEqual(first_icon, default_icon));
// Remove the icon from the manager.
icon_manager.RemoveIcon(extension->id());
// Now re-load the icon - we should get the same result bitmap (and not the
// default icon).
icon_manager.LoadIcon(profile.get(), extension.get());
WaitForImageLoad();
SkBitmap second_icon = icon_manager.GetIcon(extension->id());
EXPECT_FALSE(gfx::BitmapsAreEqual(second_icon, default_icon));
EXPECT_TRUE(gfx::BitmapsAreEqual(first_icon, second_icon));
}
#if defined(OS_CHROMEOS)
// Tests loading an icon for a component extension.
TEST_F(ExtensionIconManagerTest, LoadComponentExtensionResource) {
scoped_ptr<Profile> profile(new TestingProfile());
SkBitmap default_icon = GetDefaultIcon();
base::FilePath test_dir;
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir));
base::FilePath manifest_path = test_dir.AppendASCII(
"extensions/file_manager/app.json");
JSONFileValueDeserializer deserializer(manifest_path);
scoped_ptr<base::DictionaryValue> manifest(
static_cast<base::DictionaryValue*>(deserializer.Deserialize(NULL,
NULL)));
ASSERT_TRUE(manifest.get() != NULL);
std::string error;
scoped_refptr<Extension> extension(Extension::Create(
manifest_path.DirName(), Manifest::COMPONENT, *manifest.get(),
Extension::NO_FLAGS, &error));
ASSERT_TRUE(extension.get());
TestIconManager icon_manager(this);
// Load the icon and grab the bitmap.
icon_manager.LoadIcon(profile.get(), extension.get());
WaitForImageLoad();
SkBitmap first_icon = icon_manager.GetIcon(extension->id());
EXPECT_FALSE(gfx::BitmapsAreEqual(first_icon, default_icon));
// Remove the icon from the manager.
icon_manager.RemoveIcon(extension->id());
// Now re-load the icon - we should get the same result bitmap (and not the
// default icon).
icon_manager.LoadIcon(profile.get(), extension.get());
WaitForImageLoad();
SkBitmap second_icon = icon_manager.GetIcon(extension->id());
EXPECT_FALSE(gfx::BitmapsAreEqual(second_icon, default_icon));
EXPECT_TRUE(gfx::BitmapsAreEqual(first_icon, second_icon));
}
#endif
|