Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / extensions / extension_action_icon_factory_unittest.cc
blob45a085aa727ce86b135a9a6558c0d5c103208ea2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/extension_action_icon_factory.h"
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/json/json_file_value_serializer.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/path_service.h"
12 #include "chrome/browser/extensions/extension_action.h"
13 #include "chrome/browser/extensions/extension_action_manager.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/test_extension_system.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/test/test_browser_thread.h"
19 #include "extensions/common/extension.h"
20 #include "grit/theme_resources.h"
21 #include "skia/ext/image_operations.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/gfx/codec/png_codec.h"
25 #include "ui/gfx/image/image_skia.h"
26 #include "ui/gfx/skia_util.h"
28 #if defined(OS_CHROMEOS)
29 #include "chrome/browser/chromeos/login/user_manager.h"
30 #include "chrome/browser/chromeos/settings/cros_settings.h"
31 #include "chrome/browser/chromeos/settings/device_settings_service.h"
32 #endif
34 using content::BrowserThread;
36 namespace extensions {
37 namespace {
39 bool ImageRepsAreEqual(const gfx::ImageSkiaRep& image_rep1,
40 const gfx::ImageSkiaRep& image_rep2) {
41 return image_rep1.scale() == image_rep2.scale() &&
42 gfx::BitmapsAreEqual(image_rep1.sk_bitmap(), image_rep2.sk_bitmap());
45 gfx::Image EnsureImageSize(const gfx::Image& original, int size) {
46 const SkBitmap* original_bitmap = original.ToSkBitmap();
47 if (original_bitmap->width() == size && original_bitmap->height() == size)
48 return original;
50 SkBitmap resized = skia::ImageOperations::Resize(
51 *original.ToSkBitmap(), skia::ImageOperations::RESIZE_LANCZOS3,
52 size, size);
53 return gfx::Image::CreateFrom1xBitmap(resized);
56 gfx::ImageSkiaRep CreateBlankRep(int size_dip, float scale) {
57 SkBitmap bitmap;
58 bitmap.setConfig(SkBitmap::kARGB_8888_Config,
59 static_cast<int>(size_dip * scale),
60 static_cast<int>(size_dip * scale));
61 bitmap.allocPixels();
62 bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
63 return gfx::ImageSkiaRep(bitmap, scale);
66 gfx::Image LoadIcon(const std::string& filename) {
67 base::FilePath path;
68 PathService::Get(chrome::DIR_TEST_DATA, &path);
69 path = path.AppendASCII("extensions/api_test").AppendASCII(filename);
71 std::string file_contents;
72 base::ReadFileToString(path, &file_contents);
73 const unsigned char* data =
74 reinterpret_cast<const unsigned char*>(file_contents.data());
76 SkBitmap bitmap;
77 gfx::PNGCodec::Decode(data, file_contents.length(), &bitmap);
79 return gfx::Image::CreateFrom1xBitmap(bitmap);
82 class ExtensionActionIconFactoryTest
83 : public testing::Test,
84 public ExtensionActionIconFactory::Observer {
85 public:
86 ExtensionActionIconFactoryTest()
87 : quit_in_icon_updated_(false),
88 ui_thread_(BrowserThread::UI, &ui_loop_),
89 file_thread_(BrowserThread::FILE),
90 io_thread_(BrowserThread::IO) {
93 virtual ~ExtensionActionIconFactoryTest() {}
95 void WaitForIconUpdate() {
96 quit_in_icon_updated_ = true;
97 base::MessageLoop::current()->Run();
98 quit_in_icon_updated_ = false;
101 scoped_refptr<Extension> CreateExtension(const char* name,
102 Manifest::Location location) {
103 // Create and load an extension.
104 base::FilePath test_file;
105 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) {
106 EXPECT_FALSE(true);
107 return NULL;
109 test_file = test_file.AppendASCII("extensions/api_test").AppendASCII(name);
110 int error_code = 0;
111 std::string error;
112 JSONFileValueSerializer serializer(test_file.AppendASCII("manifest.json"));
113 scoped_ptr<base::DictionaryValue> valid_value(
114 static_cast<base::DictionaryValue*>(serializer.Deserialize(&error_code,
115 &error)));
116 EXPECT_EQ(0, error_code) << error;
117 if (error_code != 0)
118 return NULL;
120 EXPECT_TRUE(valid_value.get());
121 if (!valid_value)
122 return NULL;
124 scoped_refptr<Extension> extension =
125 Extension::Create(test_file, location, *valid_value,
126 Extension::NO_FLAGS, &error);
127 EXPECT_TRUE(extension.get()) << error;
128 if (extension.get())
129 extension_service_->AddExtension(extension.get());
130 return extension;
133 // testing::Test overrides:
134 virtual void SetUp() OVERRIDE {
135 file_thread_.Start();
136 io_thread_.Start();
137 profile_.reset(new TestingProfile);
138 CommandLine command_line(CommandLine::NO_PROGRAM);
139 extension_service_ = static_cast<extensions::TestExtensionSystem*>(
140 extensions::ExtensionSystem::Get(profile_.get()))->
141 CreateExtensionService(&command_line, base::FilePath(), false);
144 virtual void TearDown() OVERRIDE {
145 profile_.reset(); // Get all DeleteSoon calls sent to ui_loop_.
146 ui_loop_.RunUntilIdle();
149 // ExtensionActionIconFactory::Observer overrides:
150 virtual void OnIconUpdated() OVERRIDE {
151 if (quit_in_icon_updated_)
152 base::MessageLoop::current()->Quit();
155 gfx::ImageSkia GetFavicon() {
156 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
157 IDR_EXTENSIONS_FAVICON);
160 ExtensionAction* GetBrowserAction(const Extension& extension) {
161 return ExtensionActionManager::Get(profile())->GetBrowserAction(extension);
164 TestingProfile* profile() { return profile_.get(); }
166 private:
167 bool quit_in_icon_updated_;
168 base::MessageLoop ui_loop_;
169 content::TestBrowserThread ui_thread_;
170 content::TestBrowserThread file_thread_;
171 content::TestBrowserThread io_thread_;
172 scoped_ptr<TestingProfile> profile_;
173 ExtensionService* extension_service_;
175 #if defined OS_CHROMEOS
176 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
177 chromeos::ScopedTestCrosSettings test_cros_settings_;
178 chromeos::ScopedTestUserManager test_user_manager_;
179 #endif
181 DISALLOW_COPY_AND_ASSIGN(ExtensionActionIconFactoryTest);
184 // If there is no default icon, and the icon has not been set using |SetIcon|,
185 // the factory should return favicon.
186 TEST_F(ExtensionActionIconFactoryTest, NoIcons) {
187 // Load an extension that has browser action without default icon set in the
188 // manifest and does not call |SetIcon| by default.
189 scoped_refptr<Extension> extension(CreateExtension(
190 "browser_action/no_icon", Manifest::INVALID_LOCATION));
191 ASSERT_TRUE(extension.get() != NULL);
192 ExtensionAction* browser_action = GetBrowserAction(*extension.get());
193 ASSERT_TRUE(browser_action);
194 ASSERT_FALSE(browser_action->default_icon());
195 ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
197 gfx::ImageSkia favicon = GetFavicon();
199 ExtensionActionIconFactory icon_factory(
200 profile(), extension.get(), browser_action, this);
202 gfx::Image icon = icon_factory.GetIcon(0);
204 EXPECT_TRUE(ImageRepsAreEqual(
205 favicon.GetRepresentation(1.0f),
206 icon.ToImageSkia()->GetRepresentation(1.0f)));
209 // If the icon has been set using |SetIcon|, the factory should return that
210 // icon.
211 TEST_F(ExtensionActionIconFactoryTest, AfterSetIcon) {
212 // Load an extension that has browser action without default icon set in the
213 // manifest and does not call |SetIcon| by default (but has an browser action
214 // icon resource).
215 scoped_refptr<Extension> extension(CreateExtension(
216 "browser_action/no_icon", Manifest::INVALID_LOCATION));
217 ASSERT_TRUE(extension.get() != NULL);
218 ExtensionAction* browser_action = GetBrowserAction(*extension.get());
219 ASSERT_TRUE(browser_action);
220 ASSERT_FALSE(browser_action->default_icon());
221 ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
223 gfx::Image set_icon = LoadIcon("browser_action/no_icon/icon.png");
224 ASSERT_FALSE(set_icon.IsEmpty());
226 browser_action->SetIcon(0, set_icon);
228 ASSERT_FALSE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
230 ExtensionActionIconFactory icon_factory(
231 profile(), extension.get(), browser_action, this);
233 gfx::Image icon = icon_factory.GetIcon(0);
235 EXPECT_TRUE(ImageRepsAreEqual(
236 set_icon.ToImageSkia()->GetRepresentation(1.0f),
237 icon.ToImageSkia()->GetRepresentation(1.0f)));
239 // It should still return favicon for another tabs.
240 icon = icon_factory.GetIcon(1);
242 EXPECT_TRUE(ImageRepsAreEqual(
243 GetFavicon().GetRepresentation(1.0f),
244 icon.ToImageSkia()->GetRepresentation(1.0f)));
247 // If there is a default icon, and the icon has not been set using |SetIcon|,
248 // the factory should return the default icon.
249 TEST_F(ExtensionActionIconFactoryTest, DefaultIcon) {
250 // Load an extension that has browser action without default icon set in the
251 // manifest and does not call |SetIcon| by default (but has an browser action
252 // icon resource).
253 scoped_refptr<Extension> extension(CreateExtension(
254 "browser_action/no_icon", Manifest::INVALID_LOCATION));
255 ASSERT_TRUE(extension.get() != NULL);
256 ExtensionAction* browser_action = GetBrowserAction(*extension.get());
257 ASSERT_TRUE(browser_action);
258 ASSERT_FALSE(browser_action->default_icon());
259 ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
261 gfx::Image default_icon =
262 EnsureImageSize(LoadIcon("browser_action/no_icon/icon.png"), 19);
263 ASSERT_FALSE(default_icon.IsEmpty());
265 scoped_ptr<ExtensionIconSet> default_icon_set(new ExtensionIconSet());
266 default_icon_set->Add(19, "icon.png");
268 browser_action->set_default_icon(default_icon_set.Pass());
269 ASSERT_TRUE(browser_action->default_icon());
271 ExtensionActionIconFactory icon_factory(
272 profile(), extension.get(), browser_action, this);
274 gfx::Image icon = icon_factory.GetIcon(0);
276 // The icon should be loaded asynchronously. Initially a transparent icon
277 // should be returned.
278 EXPECT_TRUE(ImageRepsAreEqual(
279 CreateBlankRep(19, 1.0f),
280 icon.ToImageSkia()->GetRepresentation(1.0f)));
282 WaitForIconUpdate();
284 icon = icon_factory.GetIcon(0);
286 // The default icon representation should be loaded at this point.
287 EXPECT_TRUE(ImageRepsAreEqual(
288 default_icon.ToImageSkia()->GetRepresentation(1.0f),
289 icon.ToImageSkia()->GetRepresentation(1.0f)));
291 // The same icon should be returned for the other tabs.
292 icon = icon_factory.GetIcon(1);
294 EXPECT_TRUE(ImageRepsAreEqual(
295 default_icon.ToImageSkia()->GetRepresentation(1.0f),
296 icon.ToImageSkia()->GetRepresentation(1.0f)));
300 } // namespace
301 } // namespace extensions