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_icon_image.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h"
8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/image_loader.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/manifest.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/testing_profile.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "skia/ext/image_operations.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_source.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::IconImage;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using extensions::Manifest;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkBitmap CreateBlankBitmapForScale(int size_dip, ui::ScaleFactor scale_factor) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap bitmap;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const float scale = ui::GetScaleFactorScale(scale_factor);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap.setConfig(SkBitmap::kARGB_8888_Config,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   static_cast<int>(size_dip * scale),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   static_cast<int>(size_dip * scale));
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap.allocPixels();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bitmap;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkBitmap EnsureBitmapSize(const SkBitmap& original, int size) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (original.width() == size && original.height() == size)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return original;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap resized = skia::ImageOperations::Resize(
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      original, skia::ImageOperations::RESIZE_LANCZOS3, size, size);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return resized;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to test behavior including images defined by an image skia source.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |GetImageForScale| simply returns image representation from the image given
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the ctor.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockImageSkiaSource : public gfx::ImageSkiaSource {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MockImageSkiaSource(const gfx::ImageSkia& image)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : image_(image) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockImageSkiaSource() {}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual gfx::ImageSkiaRep GetImageForScale(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::ScaleFactor scale_factor) OVERRIDE {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return image_.GetRepresentation(scale_factor);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia image_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class for synchronously loading extension image resource.
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestImageLoader {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestImageLoader(const Extension* extension)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : extension_(extension),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        waiting_(false),
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        image_loaded_(false) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestImageLoader() {}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnImageLoaded(const gfx::Image& image) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_ = image;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_ = true;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (waiting_)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap LoadBitmap(const std::string& path,
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      int size) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_ = false;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    image_loader_.LoadImageAsync(
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension_, extension_->GetResource(path), gfx::Size(size, size),
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&TestImageLoader::OnImageLoaded,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this)));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If |image_| still hasn't been loaded (i.e. it is being loaded
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // asynchronously), wait for it.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!image_loaded_) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_ = true;
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Run();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_ = false;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(image_loaded_);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return image_.IsEmpty() ? SkBitmap() : *image_.ToSkBitmap();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool waiting_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool image_loaded_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image image_;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  extensions::ImageLoader image_loader_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestImageLoader);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionIconImageTest : public testing::Test,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               public IconImage::Observer {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconImageTest()
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : image_loaded_count_(0),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        quit_in_image_loaded_(false),
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui_thread_(BrowserThread::UI, &ui_loop_),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_thread_(BrowserThread::FILE),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_thread_(BrowserThread::IO) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ExtensionIconImageTest() {}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForImageLoad() {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_image_loaded_ = true;
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->Run();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_image_loaded_ = false;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ImageLoadedCount() {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = image_loaded_count_;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_count_ = 0;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> CreateExtension(const char* name,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           Manifest::Location location) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create and load an extension.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath test_file;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(true);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_file = test_file.AppendASCII("extensions").AppendASCII(name);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int error_code = 0;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string error;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JSONFileValueSerializer serializer(test_file.AppendASCII("app.json"));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DictionaryValue> valid_value(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<DictionaryValue*>(serializer.Deserialize(&error_code,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                             &error)));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, error_code) << error;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_code != 0)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(valid_value.get());
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!valid_value)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Extension::Create(test_file, location, *valid_value,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             Extension::NO_FLAGS, &error);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test overrides:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_thread_.Start();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_thread_.Start();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IconImage::Delegate overrides:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnExtensionIconImageChanged(IconImage* image) OVERRIDE {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_count_++;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (quit_in_image_loaded_)
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia GetDefaultIcon() {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IDR_EXTENSIONS_FAVICON);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads an image to be used in test from the extension.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The image will be loaded from the relative path |path|.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap GetTestBitmap(const Extension* extension,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& path,
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         int size) {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestImageLoader image_loader(extension);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return image_loader.LoadBitmap(path, size);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int image_loaded_count_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_in_image_loaded_;
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop ui_loop_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread file_thread_;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread io_thread_;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, Basic) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load images we expect to find as representations in icon_image, so we
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later use them to validate icon_image.
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bitmap_16.empty());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no image of size 32 defined in the extension manifest, so we
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should expect manifest image of size 48 resized to size 32.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap bitmap_48_resized_to_32 =
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GetTestBitmap(extension.get(), "48.png", 32);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bitmap_48_resized_to_32.empty());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IconImage image(profile.get(),
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extensions::IconsInfo::GetIcons(extension.get()),
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  16,
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No representations in |image_| yet.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia::ImageSkiaReps image_reps = image.image_skia().image_reps();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0u, image_reps.size());
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets representation for a scale factor.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Before the image representation is loaded, image should contain blank
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // image representation.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_100P)));
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should get the right representation now.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(16, representation.pixel_width());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets representation for an additional scale factor.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P)));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, image.image_skia().image_reps().size());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Image should have been resized.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(32, representation.pixel_width());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bitmap_48_resized_to_32));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There is no resource with either exact or bigger size, but there is a smaller
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) {
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load images we expect to find as representations in icon_image, so we
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later use them to validate icon_image.
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkBitmap bitmap_48 = GetTestBitmap(extension.get(), "48.png", 48);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bitmap_48.empty());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IconImage image(profile.get(),
297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extensions::IconsInfo::GetIcons(extension.get()),
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  32,
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have loaded the biggest smaller resource resized to the actual
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // size.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::SCALE_FACTOR_200P, representation.scale_factor());
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(64, representation.pixel_width());
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   EnsureBitmapSize(bitmap_48, 64)));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There is no resource with exact size, but there is a smaller and a bigger
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one. Requested size is smaller than 32 though, so the smaller resource should
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be loaded.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, FallbackToSmaller) {
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load images we expect to find as representations in icon_image, so we
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later use them to validate icon_image.
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bitmap_16.empty());
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IconImage image(profile.get(),
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extensions::IconsInfo::GetIcons(extension.get()),
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  17,
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have loaded smaller (resized) resource.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor());
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(17, representation.pixel_width());
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   EnsureBitmapSize(bitmap_16, 17)));
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If resource set is empty, |GetRepresentation| should synchronously return
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// default icon, without notifying observer of image change.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, NoResources) {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet empty_icon_set;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kRequestedSize = 24;
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IconImage image(profile.get(),
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  empty_icon_set,
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kRequestedSize,
375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kRequestedSize)));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, ImageLoadedCount());
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have a default icon representation.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kRequestedSize)));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If resource set is invalid, image load should be done asynchronously and
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the observer should be notified when it's done. |GetRepresentation| should
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return the default icon representation once image load is done.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, InvalidResource) {
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kInvalidIconSize = 24;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet invalid_icon_set;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_icon_set.Add(kInvalidIconSize, "invalid.png");
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IconImage image(profile.get(),
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  invalid_icon_set,
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kInvalidIconSize,
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateBlankBitmapForScale(kInvalidIconSize, ui::SCALE_FACTOR_100P)));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have default icon representation now.
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kInvalidIconSize)));
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that IconImage works with lazily (but synchronously) created default
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// icon when IconImage returns synchronously.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, LazyDefaultIcon) {
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon),
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    default_icon.size());
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet empty_icon_set;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kRequestedSize = 128;
454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IconImage image(profile.get(),
455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  empty_icon_set,
457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kRequestedSize,
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  lazy_default_icon,
459868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The resouce set is empty, so we should get the result right away.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kRequestedSize)));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have a default icon representation.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that IconImage works with lazily (but synchronously) created default
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// icon when IconImage returns asynchronously.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, LazyDefaultIcon_AsyncIconImage) {
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon),
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    default_icon.size());
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kInvalidIconSize = 24;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet invalid_icon_set;
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_icon_set.Add(kInvalidIconSize, "invalid.png");
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  IconImage image(profile.get(),
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  invalid_icon_set,
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kInvalidIconSize,
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  lazy_default_icon,
499868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have default icon representation now.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kInvalidIconSize)));
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests behavior of image created by IconImage after IconImage host goes
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// away. The image should still return loaded representations. If requested
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representation was not loaded while IconImage host was around, transparent
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representations should be returned.
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, IconImageDestruction) {
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Profile> profile(new TestingProfile());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load images we expect to find as representations in icon_image, so we
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later use them to validate icon_image.
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bitmap_16.empty());
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<IconImage> image(
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new IconImage(profile.get(),
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    extension.get(),
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    extensions::IconsInfo::GetIcons(extension.get()),
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    16,
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    default_icon,
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    this));
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an image representation.
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image->image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image->image_skia().image_reps().size());
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stash loaded image skia, and destroy |image|.
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia image_skia = image->image_skia();
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image.reset();
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension = NULL;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Image skia should still be able to get previously loaded representation.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor());
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(16, representation.pixel_width());
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When requesting another representation, we should get blank image.
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P)));
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
573