15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_icon_factory.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/test_extension_system.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
24a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "ui/gfx/codec/png_codec.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chromeos/login/users/user_manager.h"
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h"
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_settings_service.h"
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ImageRepsAreEqual(const gfx::ImageSkiaRep& image_rep1,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const gfx::ImageSkiaRep& image_rep2) {
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return image_rep1.scale() == image_rep2.scale() &&
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         gfx::BitmapsAreEqual(image_rep1.sk_bitmap(), image_rep2.sk_bitmap());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image EnsureImageSize(const gfx::Image& original, int size) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SkBitmap* original_bitmap = original.ToSkBitmap();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (original_bitmap->width() == size && original_bitmap->height() == size)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return original;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap resized = skia::ImageOperations::Resize(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *original.ToSkBitmap(), skia::ImageOperations::RESIZE_LANCZOS3,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size, size);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Image::CreateFrom1xBitmap(resized);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)gfx::ImageSkiaRep CreateBlankRep(int size_dip, float scale) {
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SkBitmap bitmap;
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bitmap.setConfig(SkBitmap::kARGB_8888_Config,
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                   static_cast<int>(size_dip * scale),
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                   static_cast<int>(size_dip * scale));
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bitmap.allocPixels();
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return gfx::ImageSkiaRep(bitmap, scale);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image LoadIcon(const std::string& filename) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(chrome::DIR_TEST_DATA, &path);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  path = path.AppendASCII("extensions/api_test").AppendASCII(filename);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file_contents;
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  base::ReadFileToString(path, &file_contents);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned char* data =
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(file_contents.data());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap bitmap;
77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  gfx::PNGCodec::Decode(data, file_contents.length(), &bitmap);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Image::CreateFrom1xBitmap(bitmap);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionActionIconFactoryTest
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public testing::Test,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public ExtensionActionIconFactory::Observer {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionActionIconFactoryTest()
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : quit_in_icon_updated_(false),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui_thread_(BrowserThread::UI, &ui_loop_),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_thread_(BrowserThread::FILE),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_thread_(BrowserThread::IO) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ExtensionActionIconFactoryTest() {}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForIconUpdate() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_icon_updated_ = true;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->Run();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_icon_updated_ = false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> CreateExtension(const char* name,
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           Manifest::Location location) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create and load an extension.
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath test_file;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(true);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_file = test_file.AppendASCII("extensions/api_test").AppendASCII(name);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int error_code = 0;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string error;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JSONFileValueSerializer serializer(test_file.AppendASCII("manifest.json"));
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> valid_value(
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<base::DictionaryValue*>(serializer.Deserialize(&error_code,
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                                   &error)));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, error_code) << error;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_code != 0)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(valid_value.get());
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!valid_value)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<Extension> extension =
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Extension::Create(test_file, location, *valid_value,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          Extension::NO_FLAGS, &error);
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_TRUE(extension.get()) << error;
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (extension.get())
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      extension_service_->AddExtension(extension.get());
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test overrides:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_thread_.Start();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_thread_.Start();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_.reset(new TestingProfile);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine command_line(CommandLine::NO_PROGRAM);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_service_ = static_cast<extensions::TestExtensionSystem*>(
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::ExtensionSystem::Get(profile_.get()))->
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CreateExtensionService(&command_line, base::FilePath(), false);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_.reset();  // Get all DeleteSoon calls sent to ui_loop_.
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui_loop_.RunUntilIdle();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionActionIconFactory::Observer overrides:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIconUpdated() OVERRIDE {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (quit_in_icon_updated_)
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia GetFavicon() {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDR_EXTENSIONS_FAVICON);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAction* GetBrowserAction(const Extension& extension) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ExtensionActionManager::Get(profile())->GetBrowserAction(extension);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestingProfile* profile() { return profile_.get(); }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_in_icon_updated_;
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop ui_loop_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread file_thread_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread io_thread_;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestingProfile> profile_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionService* extension_service_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined OS_CHROMEOS
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::ScopedTestCrosSettings test_cros_settings_;
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::ScopedTestUserManager test_user_manager_;
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionActionIconFactoryTest);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there is no default icon, and the icon has not been set using |SetIcon|,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the factory should return favicon.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionActionIconFactoryTest, NoIcons) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an extension that has browser action without default icon set in the
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manifest and does not call |SetIcon| by default.
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "browser_action/no_icon", Manifest::INVALID_LOCATION));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionAction* browser_action = GetBrowserAction(*extension.get());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->default_icon());
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia favicon = GetFavicon();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionActionIconFactory icon_factory(
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile(), extension.get(), browser_action, this);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image icon = icon_factory.GetIcon(0);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      favicon.GetRepresentation(1.0f),
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(1.0f)));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the icon has been set using |SetIcon|, the factory should return that
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// icon.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionActionIconFactoryTest, AfterSetIcon) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an extension that has browser action without default icon set in the
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manifest and does not call |SetIcon| by default (but has an browser action
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // icon resource).
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "browser_action/no_icon", Manifest::INVALID_LOCATION));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionAction* browser_action = GetBrowserAction(*extension.get());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->default_icon());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image set_icon = LoadIcon("browser_action/no_icon/icon.png");
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(set_icon.IsEmpty());
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_action->SetIcon(0, set_icon);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionActionIconFactory icon_factory(
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile(), extension.get(), browser_action, this);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image icon = icon_factory.GetIcon(0);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      set_icon.ToImageSkia()->GetRepresentation(1.0f),
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(1.0f)));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It should still return favicon for another tabs.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon = icon_factory.GetIcon(1);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      GetFavicon().GetRepresentation(1.0f),
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(1.0f)));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there is a default icon, and the icon has not been set using |SetIcon|,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the factory should return the default icon.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionActionIconFactoryTest, DefaultIcon) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an extension that has browser action without default icon set in the
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manifest and does not call |SetIcon| by default (but has an browser action
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // icon resource).
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "browser_action/no_icon", Manifest::INVALID_LOCATION));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionAction* browser_action = GetBrowserAction(*extension.get());
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->default_icon());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image default_icon =
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EnsureImageSize(LoadIcon("browser_action/no_icon/icon.png"), 19);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(default_icon.IsEmpty());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionIconSet> default_icon_set(new ExtensionIconSet());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default_icon_set->Add(19, "icon.png");
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_action->set_default_icon(default_icon_set.Pass());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->default_icon());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionActionIconFactory icon_factory(
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile(), extension.get(), browser_action, this);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image icon = icon_factory.GetIcon(0);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The icon should be loaded asynchronously. Initially a transparent icon
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be returned.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      CreateBlankRep(19, 1.0f),
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(1.0f)));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForIconUpdate();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon = icon_factory.GetIcon(0);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The default icon representation should be loaded at this point.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      default_icon.ToImageSkia()->GetRepresentation(1.0f),
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(1.0f)));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The same icon should be returned for the other tabs.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon = icon_factory.GetIcon(1);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      default_icon.ToImageSkia()->GetRepresentation(1.0f),
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(1.0f)));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
302