16d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// Copyright 2014 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)
56d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/extension_icon_image.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <vector>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
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"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/notification_service.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/test/test_browser_context.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extensions_test.h"
166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/image_loader.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "extensions/common/extension_paths.h"
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.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"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_source.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/skia_util.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace extensions {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkBitmap CreateBlankBitmapForScale(int size_dip, ui::ScaleFactor scale_factor) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap bitmap;
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const float scale = ui::GetScaleForScaleFactor(scale_factor);
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bitmap.allocN32Pixels(static_cast<int>(size_dip * scale),
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        static_cast<int>(size_dip * scale));
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bitmap;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkBitmap EnsureBitmapSize(const SkBitmap& original, int size) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (original.width() == size && original.height() == size)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return original;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap resized = skia::ImageOperations::Resize(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      original, skia::ImageOperations::RESIZE_LANCZOS3, size, size);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return resized;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to test behavior including images defined by an image skia source.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |GetImageForScale| simply returns image representation from the image given
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the ctor.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockImageSkiaSource : public gfx::ImageSkiaSource {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit MockImageSkiaSource(const gfx::ImageSkia& image)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : image_(image) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockImageSkiaSource() {}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual gfx::ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return image_.GetRepresentation(scale);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia image_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class for synchronously loading extension image resource.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TestImageLoader {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TestImageLoader(const Extension* extension)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : extension_(extension),
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        waiting_(false),
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        image_loaded_(false) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~TestImageLoader() {}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnImageLoaded(const gfx::Image& image) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_ = image;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_ = true;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (waiting_)
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap LoadBitmap(const std::string& path,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      int size) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_ = false;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    image_loader_.LoadImageAsync(
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension_, extension_->GetResource(path), gfx::Size(size, size),
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&TestImageLoader::OnImageLoaded,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this)));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If |image_| still hasn't been loaded (i.e. it is being loaded
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // asynchronously), wait for it.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!image_loaded_) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_ = true;
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Run();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_ = false;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(image_loaded_);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return image_.IsEmpty() ? SkBitmap() : *image_.ToSkBitmap();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool waiting_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool image_loaded_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image image_;
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ImageLoader image_loader_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestImageLoader);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ExtensionIconImageTest : public ExtensionsTest,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               public IconImage::Observer {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconImageTest()
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : image_loaded_count_(0),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        quit_in_image_loaded_(false),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui_thread_(BrowserThread::UI, &ui_loop_),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_thread_(BrowserThread::FILE),
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        io_thread_(BrowserThread::IO),
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        notification_service_(content::NotificationService::Create()) {}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ExtensionIconImageTest() {}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForImageLoad() {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_image_loaded_ = true;
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->Run();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_image_loaded_ = false;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ImageLoadedCount() {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = image_loaded_count_;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_count_ = 0;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> CreateExtension(const char* name,
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           Manifest::Location location) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create and load an extension.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath test_file;
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!PathService::Get(DIR_TEST_DATA, &test_file)) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(true);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    test_file = test_file.AppendASCII(name);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int error_code = 0;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string error;
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    JSONFileValueSerializer serializer(test_file.AppendASCII("manifest.json"));
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> valid_value(
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<base::DictionaryValue*>(serializer.Deserialize(&error_code,
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                                   &error)));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, error_code) << error;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_code != 0)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(valid_value.get());
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!valid_value)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Extension::Create(test_file, location, *valid_value,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             Extension::NO_FLAGS, &error);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test overrides:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_thread_.Start();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_thread_.Start();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IconImage::Delegate overrides:
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnExtensionIconImageChanged(IconImage* image) OVERRIDE {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_count_++;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (quit_in_image_loaded_)
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia GetDefaultIcon() {
1836d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return gfx::ImageSkia(gfx::ImageSkiaRep(gfx::Size(16, 16), 1.0f));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loads an image to be used in test from the extension.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The image will be loaded from the relative path |path|.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap GetTestBitmap(const Extension* extension,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& path,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         int size) {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestImageLoader image_loader(extension);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return image_loader.LoadBitmap(path, size);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int image_loaded_count_;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_in_image_loaded_;
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop ui_loop_;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread file_thread_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread io_thread_;
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<content::NotificationService> notification_service_;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, Basic) {
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<ui::ScaleFactor> supported_factors;
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  supported_factors.push_back(ui::SCALE_FACTOR_100P);
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  supported_factors.push_back(ui::SCALE_FACTOR_200P);
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors);
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)
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IconImage image(browser_context(),
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  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.
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Before the image representation is loaded, image should contain blank
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // image representation.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_100P)));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(1.0f);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should get the right representation now.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(16, representation.pixel_width());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets representation for an additional scale factor.
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(2.0f);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P)));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, image.image_skia().image_reps().size());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(2.0f);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Image should have been resized.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(32, representation.pixel_width());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bitmap_48_resized_to_32));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There is no resource with either exact or bigger size, but there is a smaller
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resource.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) {
28368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<ui::ScaleFactor> supported_factors;
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  supported_factors.push_back(ui::SCALE_FACTOR_100P);
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  supported_factors.push_back(ui::SCALE_FACTOR_200P);
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load images we expect to find as representations in icon_image, so we
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later use them to validate icon_image.
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkBitmap bitmap_48 = GetTestBitmap(extension.get(), "48.png", 48);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bitmap_48.empty());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IconImage image(browser_context(),
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  IconsInfo::GetIcons(extension.get()),
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  32,
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(2.0f);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(2.0f);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have loaded the biggest smaller resource resized to the actual
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // size.
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(2.0f, representation.scale());
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(64, representation.pixel_width());
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   EnsureBitmapSize(bitmap_48, 64)));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There is no resource with exact size, but there is a smaller and a bigger
32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// one. The bigger resource should be loaded.
32303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(ExtensionIconImageTest, FallbackToBigger) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load images we expect to find as representations in icon_image, so we
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later use them to validate icon_image.
33203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  SkBitmap bitmap_24 = GetTestBitmap(extension.get(), "24.png", 24);
33303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ASSERT_FALSE(bitmap_24.empty());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IconImage image(browser_context(),
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                  IconsInfo::GetIcons(extension.get()),
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  17,
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(1.0f);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // We should have loaded the smallest bigger (resized) resource.
35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(1.0f, representation.scale());
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(17, representation.pixel_width());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
35403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                   EnsureBitmapSize(bitmap_24, 17)));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If resource set is empty, |GetRepresentation| should synchronously return
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// default icon, without notifying observer of image change.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, NoResources) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet empty_icon_set;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kRequestedSize = 24;
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IconImage image(browser_context(),
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  empty_icon_set,
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kRequestedSize,
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          default_icon.GetRepresentation(1.0f).sk_bitmap(),
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kRequestedSize)));
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, ImageLoadedCount());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have a default icon representation.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(1.0f);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          default_icon.GetRepresentation(1.0f).sk_bitmap(),
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kRequestedSize)));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If resource set is invalid, image load should be done asynchronously and
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the observer should be notified when it's done. |GetRepresentation| should
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return the default icon representation once image load is done.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, InvalidResource) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kInvalidIconSize = 24;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet invalid_icon_set;
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_icon_set.Add(kInvalidIconSize, "invalid.png");
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IconImage image(browser_context(),
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  invalid_icon_set,
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kInvalidIconSize,
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  default_icon,
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateBlankBitmapForScale(kInvalidIconSize, ui::SCALE_FACTOR_100P)));
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have default icon representation now.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(1.0f);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          default_icon.GetRepresentation(1.0f).sk_bitmap(),
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kInvalidIconSize)));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that IconImage works with lazily (but synchronously) created default
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// icon when IconImage returns synchronously.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, LazyDefaultIcon) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon),
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    default_icon.size());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet empty_icon_set;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kRequestedSize = 128;
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IconImage image(browser_context(),
448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  empty_icon_set,
450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kRequestedSize,
451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  lazy_default_icon,
452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ASSERT_FALSE(lazy_default_icon.HasRepresentation(1.0f));
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The resouce set is empty, so we should get the result right away.
45968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(lazy_default_icon.HasRepresentation(1.0f));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
46368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          default_icon.GetRepresentation(1.0f).sk_bitmap(),
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kRequestedSize)));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have a default icon representation.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that IconImage works with lazily (but synchronously) created default
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// icon when IconImage returns asynchronously.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, LazyDefaultIcon_AsyncIconImage) {
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon),
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    default_icon.size());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kInvalidIconSize = 24;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionIconSet invalid_icon_set;
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  invalid_icon_set.Add(kInvalidIconSize, "invalid.png");
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  IconImage image(browser_context(),
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  extension.get(),
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  invalid_icon_set,
488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  kInvalidIconSize,
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  lazy_default_icon,
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                  this);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ASSERT_FALSE(lazy_default_icon.HasRepresentation(1.0f));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have default icon representation now.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image.image_skia().image_reps().size());
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_TRUE(lazy_default_icon.HasRepresentation(1.0f));
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image.image_skia().GetRepresentation(1.0f);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      representation.sk_bitmap(),
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EnsureBitmapSize(
50768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          default_icon.GetRepresentation(1.0f).sk_bitmap(),
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          kInvalidIconSize)));
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests behavior of image created by IconImage after IconImage host goes
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// away. The image should still return loaded representations. If requested
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representation was not loaded while IconImage host was around, transparent
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representations should be returned.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionIconImageTest, IconImageDestruction) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Extension> extension(CreateExtension(
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "extension_icon_image", Manifest::INVALID_LOCATION));
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia default_icon = GetDefaultIcon();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load images we expect to find as representations in icon_image, so we
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can later use them to validate icon_image.
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(bitmap_16.empty());
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<IconImage> image(
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new IconImage(browser_context(),
529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    extension.get(),
5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    IconsInfo::GetIcons(extension.get()),
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    16,
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    default_icon,
533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                    this));
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load an image representation.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkiaRep representation =
53768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      image->image_skia().GetRepresentation(1.0f);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, ImageLoadedCount());
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, image->image_skia().image_reps().size());
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stash loaded image skia, and destroy |image|.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::ImageSkia image_skia = image->image_skia();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image.reset();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension = NULL;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Image skia should still be able to get previously loaded representation.
54968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image_skia.GetRepresentation(1.0f);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  EXPECT_EQ(1.0f, representation.scale());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(16, representation.pixel_width());
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // When requesting another representation, we should not crash and return some
556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // image of the size. It could be blank or a rescale from the existing 1.0f
557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // icon.
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  representation = image_skia.GetRepresentation(2.0f);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(16, representation.GetWidth());
561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(16, representation.GetHeight());
562cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_EQ(2.0f, representation.scale());
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace extensions
566