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/image_loader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/files/file_path.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h"
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "base/strings/string_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/constants.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension_icon_set.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/common/extension_paths.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/extension_resource.h"
213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h"
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gfx/image/image_family.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using content::NotificationService;
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace extensions {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ImageLoaderTest : public testing::Test {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ImageLoaderTest()
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : image_loaded_count_(0),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        quit_in_image_loaded_(false),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui_thread_(BrowserThread::UI, &ui_loop_),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_thread_(BrowserThread::FILE),
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        io_thread_(BrowserThread::IO),
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        notification_service_(NotificationService::Create()) {}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnImageLoaded(const gfx::Image& image) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_count_++;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (quit_in_image_loaded_)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_ = image;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void OnImageFamilyLoaded(const gfx::ImageFamily& image_family) {
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    image_loaded_count_++;
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (quit_in_image_loaded_)
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::MessageLoop::current()->Quit();
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    image_family_ = image_family;
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForImageLoad() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_image_loaded_ = true;
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->Run();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    quit_in_image_loaded_ = false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int image_loaded_count() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = image_loaded_count_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_loaded_count_ = 0;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<Extension> CreateExtension(const char* dir_name,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           Manifest::Location location) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create and load an extension.
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::FilePath extension_dir;
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!PathService::Get(DIR_TEST_DATA, &extension_dir)) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE(true);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    extension_dir = extension_dir.AppendASCII(dir_name);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int error_code = 0;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string error;
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    JSONFileValueSerializer serializer(
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extension_dir.AppendASCII("manifest.json"));
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> valid_value(
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<base::DictionaryValue*>(serializer.Deserialize(&error_code,
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                                   &error)));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0, error_code) << error;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_code != 0)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(valid_value.get());
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!valid_value)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return Extension::Create(
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extension_dir, location, *valid_value, Extension::NO_FLAGS, &error);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Image image_;
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::ImageFamily image_family_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    testing::Test::SetUp();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_thread_.Start();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    io_thread_.Start();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int image_loaded_count_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool quit_in_image_loaded_;
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop ui_loop_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread file_thread_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread io_thread_;
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<NotificationService> notification_service_;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests loading an image works correctly.
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ImageLoaderTest, LoadImage) {
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<Extension> extension(
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CreateExtension("image_loader", Manifest::INVALID_LOCATION));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ExtensionResource image_resource =
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      IconsInfo::GetIconResource(extension.get(),
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 extension_misc::EXTENSION_ICON_SMALLISH,
1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 ExtensionIconSet::MATCH_EXACTLY);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     extension_misc::EXTENSION_ICON_SMALLISH);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ImageLoader loader;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loader.LoadImageAsync(extension.get(),
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        image_resource,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        max_size,
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        base::Bind(&ImageLoaderTest::OnImageLoaded,
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   base::Unretained(this)));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The image isn't cached, so we should not have received notification.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, image_loaded_count());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have gotten the image.
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_FALSE(image_.IsEmpty());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, image_loaded_count());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the image was loaded.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            image_.ToSkBitmap()->width());
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests deleting an extension while waiting for the image to load doesn't cause
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// problems.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ImageLoaderTest, DeleteExtensionWhileWaitingForCache) {
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<Extension> extension(
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CreateExtension("image_loader", Manifest::INVALID_LOCATION));
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ExtensionResource image_resource =
1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      IconsInfo::GetIconResource(extension.get(),
1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 extension_misc::EXTENSION_ICON_SMALLISH,
1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 ExtensionIconSet::MATCH_EXACTLY);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH,
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     extension_misc::EXTENSION_ICON_SMALLISH);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ImageLoader loader;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::set<int> sizes;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sizes.insert(extension_misc::EXTENSION_ICON_SMALLISH);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loader.LoadImageAsync(extension.get(),
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        image_resource,
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        max_size,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        base::Bind(&ImageLoaderTest::OnImageLoaded,
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   base::Unretained(this)));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The image isn't cached, so we should not have received notification.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, image_loaded_count());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send out notification the extension was uninstalled.
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  UnloadedExtensionInfo details(extension.get(),
1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                UnloadedExtensionInfo::REASON_UNINSTALL);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources(),
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      content::Details<UnloadedExtensionInfo>(&details));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chuck the extension, that way if anyone tries to access it we should crash
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or get valgrind errors.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extension = NULL;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Even though we deleted the extension, we should still get the image.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should still have gotten the image.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, image_loaded_count());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the image was loaded.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            image_.ToSkBitmap()->width());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests loading multiple dimensions of the same image.
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(ImageLoaderTest, MultipleImages) {
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<Extension> extension(
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CreateExtension("image_loader", Manifest::INVALID_LOCATION));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<ImageLoader::ImageRepresentation> info_list;
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int sizes[] = {extension_misc::EXTENSION_ICON_BITTY,
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 extension_misc::EXTENSION_ICON_SMALLISH, };
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(sizes); ++i) {
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionResource resource = IconsInfo::GetIconResource(
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        extension.get(), sizes[i], ExtensionIconSet::MATCH_EXACTLY);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    info_list.push_back(ImageLoader::ImageRepresentation(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resource,
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gfx::Size(sizes[i], sizes[i]),
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ui::SCALE_FACTOR_NONE));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ImageLoader loader;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  loader.LoadImagesAsync(extension.get(), info_list,
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         base::Bind(&ImageLoaderTest::OnImageLoaded,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    base::Unretained(this)));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The image isn't cached, so we should not have received notification.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, image_loaded_count());
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitForImageLoad();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have gotten the image.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1, image_loaded_count());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that all images were loaded.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<gfx::ImageSkiaRep> image_reps =
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_.ToImageSkia()->image_reps();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, image_reps.size());
235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkiaRep* img_rep1 = &image_reps[0];
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::ImageSkiaRep* img_rep2 = &image_reps[1];
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            img_rep1->pixel_width());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            img_rep2->pixel_width());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Tests loading multiple dimensions of the same image into an image family.
245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ImageLoaderTest, LoadImageFamily) {
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<Extension> extension(
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      CreateExtension("image_loader", Manifest::INVALID_LOCATION));
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_TRUE(extension.get() != NULL);
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<ImageLoader::ImageRepresentation> info_list;
251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int sizes[] = {extension_misc::EXTENSION_ICON_BITTY,
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 extension_misc::EXTENSION_ICON_SMALLISH, };
253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < arraysize(sizes); ++i) {
2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionResource resource = IconsInfo::GetIconResource(
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        extension.get(), sizes[i], ExtensionIconSet::MATCH_EXACTLY);
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    info_list.push_back(ImageLoader::ImageRepresentation(
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        resource,
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ImageLoader::ImageRepresentation::NEVER_RESIZE,
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        gfx::Size(sizes[i], sizes[i]),
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ui::SCALE_FACTOR_100P));
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Add a second icon of 200P which should get grouped with the smaller icon's
264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // ImageSkia.
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ExtensionResource resource =
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      IconsInfo::GetIconResource(extension.get(),
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 extension_misc::EXTENSION_ICON_SMALLISH,
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                 ExtensionIconSet::MATCH_EXACTLY);
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  info_list.push_back(ImageLoader::ImageRepresentation(
270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      resource,
271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ImageLoader::ImageRepresentation::NEVER_RESIZE,
272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      gfx::Size(extension_misc::EXTENSION_ICON_BITTY,
273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                extension_misc::EXTENSION_ICON_BITTY),
274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ui::SCALE_FACTOR_200P));
275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ImageLoader loader;
277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  loader.LoadImageFamilyAsync(extension.get(),
278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              info_list,
279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              base::Bind(&ImageLoaderTest::OnImageFamilyLoaded,
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                         base::Unretained(this)));
281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The image isn't cached, so we should not have received notification.
283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(0, image_loaded_count());
284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  WaitForImageLoad();
286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // We should have gotten the image.
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, image_loaded_count());
289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Check that all images were loaded.
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < arraysize(sizes); ++i) {
292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const gfx::Image* image = image_family_.GetBest(sizes[i], sizes[i]);
293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EXPECT_EQ(sizes[i], image->Width());
294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Check the smaller image has 2 representations of different scale factors.
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::vector<gfx::ImageSkiaRep> image_reps =
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      image_family_.GetBest(extension_misc::EXTENSION_ICON_BITTY,
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            extension_misc::EXTENSION_ICON_BITTY)
300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          ->ToImageSkia()
301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          ->image_reps();
302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(2u, image_reps.size());
304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::ImageSkiaRep* img_rep1 = &image_reps[0];
306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::ImageSkiaRep* img_rep2 = &image_reps[1];
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, img_rep1->pixel_width());
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1.0f, img_rep1->scale());
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, img_rep2->pixel_width());
310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(2.0f, img_rep2->scale());
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace extensions
314