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/common/extensions/extension.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.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)
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/login/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) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return image_rep1.scale_factor() == image_rep2.scale_factor() &&
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)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::ImageSkiaRep CreateBlankRep(int size_dip, ui::ScaleFactor scale_factor) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkBitmap bitmap;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const float scale = ui::GetScaleFactorScale(scale_factor);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.setConfig(SkBitmap::kARGB_8888_Config,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     static_cast<int>(size_dip * scale),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     static_cast<int>(size_dip * scale));
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.allocPixels();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gfx::ImageSkiaRep(bitmap, scale_factor);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Image LoadIcon(const std::string& filename) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(chrome::DIR_TEST_DATA, &path);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  path = path.AppendASCII("extensions/api_test").AppendASCII(filename);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string file_contents;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::ReadFileToString(path, &file_contents);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned char* data =
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(file_contents.data());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap bitmap;
78a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  gfx::PNGCodec::Decode(data, file_contents.length(), &bitmap);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return gfx::Image::CreateFrom1xBitmap(bitmap);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionActionIconFactoryTest
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public testing::Test,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public ExtensionActionIconFactory::Observer {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionActionIconFactoryTest()
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : quit_in_icon_updated_(false),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui_thread_(BrowserThread::UI, &ui_loop_),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_thread_(BrowserThread::FILE),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_thread_(BrowserThread::IO) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ExtensionActionIconFactoryTest() {}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForIconUpdate() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_icon_updated_ = true;
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->Run();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_icon_updated_ = false;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> CreateExtension(const char* name,
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           Manifest::Location location) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create and load an extension.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath test_file;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(true);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_file = test_file.AppendASCII("extensions/api_test").AppendASCII(name);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int error_code = 0;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string error;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JSONFileValueSerializer serializer(test_file.AppendASCII("manifest.json"));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DictionaryValue> valid_value(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<DictionaryValue*>(serializer.Deserialize(&error_code,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                             &error)));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, error_code) << error;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_code != 0)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(valid_value.get());
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!valid_value)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<Extension> extension =
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Extension::Create(test_file, location, *valid_value,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          Extension::NO_FLAGS, &error);
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_TRUE(extension.get()) << error;
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (extension.get())
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      extension_service_->AddExtension(extension.get());
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test overrides:
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_thread_.Start();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_thread_.Start();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_.reset(new TestingProfile);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandLine command_line(CommandLine::NO_PROGRAM);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_service_ = static_cast<extensions::TestExtensionSystem*>(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extensions::ExtensionSystem::Get(profile_.get()))->
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CreateExtensionService(&command_line, base::FilePath(), false);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile_.reset();  // Get all DeleteSoon calls sent to ui_loop_.
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui_loop_.RunUntilIdle();
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ExtensionActionIconFactory::Observer overrides:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIconUpdated() OVERRIDE {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (quit_in_icon_updated_)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia GetFavicon() {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDR_EXTENSIONS_FAVICON);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAction* GetBrowserAction(const Extension& extension) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ExtensionActionManager::Get(profile())->GetBrowserAction(extension);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestingProfile* profile() { return profile_.get(); }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_in_icon_updated_;
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop ui_loop_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread file_thread_;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread io_thread_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestingProfile> profile_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionService* extension_service_;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined OS_CHROMEOS
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::ScopedTestCrosSettings test_cros_settings_;
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  chromeos::ScopedTestUserManager test_user_manager_;
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionActionIconFactoryTest);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there is no default icon, and the icon has not been set using |SetIcon|,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the factory should return favicon.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionActionIconFactoryTest, NoIcons) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an extension that has browser action without default icon set in the
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manifest and does not call |SetIcon| by default.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "browser_action/no_icon", Manifest::INVALID_LOCATION));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionAction* browser_action = GetBrowserAction(*extension.get());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->default_icon());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia favicon = GetFavicon();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionActionIconFactory icon_factory(
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile(), extension.get(), browser_action, this);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image icon = icon_factory.GetIcon(0);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicon.GetRepresentation(ui::SCALE_FACTOR_100P),
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the icon has been set using |SetIcon|, the factory should return that
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// icon.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionActionIconFactoryTest, AfterSetIcon) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an extension that has browser action without default icon set in the
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manifest and does not call |SetIcon| by default (but has an browser action
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // icon resource).
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "browser_action/no_icon", Manifest::INVALID_LOCATION));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionAction* browser_action = GetBrowserAction(*extension.get());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->default_icon());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image set_icon = LoadIcon("browser_action/no_icon/icon.png");
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(set_icon.IsEmpty());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_action->SetIcon(0, set_icon);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionActionIconFactory icon_factory(
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile(), extension.get(), browser_action, this);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image icon = icon_factory.GetIcon(0);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      set_icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P),
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It should still return favicon for another tabs.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon = icon_factory.GetIcon(1);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetFavicon().GetRepresentation(ui::SCALE_FACTOR_100P),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there is a default icon, and the icon has not been set using |SetIcon|,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the factory should return the default icon.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionActionIconFactoryTest, DefaultIcon) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an extension that has browser action without default icon set in the
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // manifest and does not call |SetIcon| by default (but has an browser action
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // icon resource).
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "browser_action/no_icon", Manifest::INVALID_LOCATION));
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ExtensionAction* browser_action = GetBrowserAction(*extension.get());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(browser_action->default_icon());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->GetExplicitlySetIcon(0 /*tab id*/).isNull());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image default_icon =
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EnsureImageSize(LoadIcon("browser_action/no_icon/icon.png"), 19);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(default_icon.IsEmpty());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ExtensionIconSet> default_icon_set(new ExtensionIconSet());
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default_icon_set->Add(19, "icon.png");
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_action->set_default_icon(default_icon_set.Pass());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(browser_action->default_icon());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExtensionActionIconFactory icon_factory(
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile(), extension.get(), browser_action, this);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image icon = icon_factory.GetIcon(0);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The icon should be loaded asynchronously. Initially a transparent icon
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be returned.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateBlankRep(19, ui::SCALE_FACTOR_100P),
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForIconUpdate();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon = icon_factory.GetIcon(0);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The default icon representation should be loaded at this point.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default_icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P),
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The same icon should be returned for the other tabs.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icon = icon_factory.GetIcon(1);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ImageRepsAreEqual(
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default_icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P),
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon.ToImageSkia()->GetRepresentation(ui::SCALE_FACTOR_100P)));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
303