Home | History | Annotate | Download | only in extensions
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/bookmark_app_helper.h"
      6 
      7 #include "base/strings/utf_string_conversions.h"
      8 #include "chrome/browser/extensions/extension_service.h"
      9 #include "chrome/browser/extensions/extension_service_test_base.h"
     10 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
     11 #include "chrome/test/base/testing_profile.h"
     12 #include "content/public/browser/render_process_host.h"
     13 #include "content/public/browser/web_contents.h"
     14 #include "content/public/test/web_contents_tester.h"
     15 #include "extensions/browser/extension_registry.h"
     16 #include "extensions/common/constants.h"
     17 #include "extensions/common/extension_icon_set.h"
     18 #include "extensions/common/manifest_handlers/icons_handler.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "third_party/skia/include/core/SkBitmap.h"
     21 #include "ui/gfx/skia_util.h"
     22 
     23 namespace {
     24 
     25 const char kAppUrl[] = "http://www.chromium.org";
     26 const char kAppTitle[] = "Test title";
     27 const char kAlternativeAppTitle[] = "Different test title";
     28 const char kAppDescription[] = "Test description";
     29 
     30 const int kIconSizeTiny = extension_misc::EXTENSION_ICON_BITTY;
     31 const int kIconSizeSmall = extension_misc::EXTENSION_ICON_SMALL;
     32 const int kIconSizeMedium = extension_misc::EXTENSION_ICON_MEDIUM;
     33 const int kIconSizeLarge = extension_misc::EXTENSION_ICON_LARGE;
     34 
     35 class BookmarkAppHelperTest : public testing::Test {
     36  public:
     37   BookmarkAppHelperTest() {}
     38   virtual ~BookmarkAppHelperTest() {}
     39 
     40  private:
     41   DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperTest);
     42 };
     43 
     44 class BookmarkAppHelperExtensionServiceTest
     45     : public extensions::ExtensionServiceTestBase {
     46  public:
     47   BookmarkAppHelperExtensionServiceTest() {}
     48   virtual ~BookmarkAppHelperExtensionServiceTest() {}
     49 
     50   virtual void SetUp() OVERRIDE {
     51     extensions::ExtensionServiceTestBase::SetUp();
     52     InitializeEmptyExtensionService();
     53     service_->Init();
     54     EXPECT_EQ(0u, service_->extensions()->size());
     55   }
     56 
     57   virtual void TearDown() OVERRIDE {
     58     ExtensionServiceTestBase::TearDown();
     59     for (content::RenderProcessHost::iterator i(
     60              content::RenderProcessHost::AllHostsIterator());
     61          !i.IsAtEnd();
     62          i.Advance()) {
     63       content::RenderProcessHost* host = i.GetCurrentValue();
     64       if (Profile::FromBrowserContext(host->GetBrowserContext()) ==
     65           profile_.get())
     66         host->Cleanup();
     67     }
     68   }
     69 
     70  private:
     71   DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperExtensionServiceTest);
     72 };
     73 
     74 SkBitmap CreateSquareBitmapWithColor(int size, SkColor color) {
     75   SkBitmap bitmap;
     76   bitmap.allocN32Pixels(size, size);
     77   bitmap.eraseColor(color);
     78   return bitmap;
     79 }
     80 
     81 void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) {
     82   // Obtain pixel lock to access pixels.
     83   SkAutoLockPixels lock(bitmap);
     84   EXPECT_EQ(color, bitmap.getColor(0, 0));
     85   EXPECT_EQ(size, bitmap.width());
     86   EXPECT_EQ(size, bitmap.height());
     87 }
     88 
     89 WebApplicationInfo::IconInfo CreateIconInfoWithBitmap(int size, SkColor color) {
     90   WebApplicationInfo::IconInfo icon_info;
     91   icon_info.width = size;
     92   icon_info.height = size;
     93   icon_info.data = CreateSquareBitmapWithColor(size, color);
     94   return icon_info;
     95 }
     96 
     97 void ValidateWebApplicationInfo(base::Closure callback,
     98                                 const WebApplicationInfo& expected,
     99                                 const WebApplicationInfo& actual) {
    100   EXPECT_EQ(expected.title, actual.title);
    101   EXPECT_EQ(expected.description, actual.description);
    102   EXPECT_EQ(expected.app_url, actual.app_url);
    103   EXPECT_EQ(expected.icons.size(), actual.icons.size());
    104   for (size_t i = 0; i < expected.icons.size(); ++i) {
    105     EXPECT_EQ(expected.icons[i].width, actual.icons[i].width);
    106     EXPECT_EQ(expected.icons[i].height, actual.icons[i].height);
    107     EXPECT_EQ(expected.icons[i].url, actual.icons[i].url);
    108     EXPECT_TRUE(
    109         gfx::BitmapsAreEqual(expected.icons[i].data, actual.icons[i].data));
    110   }
    111   callback.Run();
    112 }
    113 
    114 }  // namespace
    115 
    116 namespace extensions {
    117 
    118 class TestBookmarkAppHelper : public BookmarkAppHelper {
    119  public:
    120   TestBookmarkAppHelper(ExtensionService* service,
    121                         WebApplicationInfo web_app_info,
    122                         content::WebContents* contents)
    123       : BookmarkAppHelper(service, web_app_info, contents) {}
    124 
    125   virtual ~TestBookmarkAppHelper() {}
    126 
    127   void CreationComplete(const extensions::Extension* extension,
    128                         const WebApplicationInfo& web_app_info) {
    129     extension_ = extension;
    130   }
    131 
    132   void CompleteIconDownload(
    133       bool success,
    134       const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
    135     BookmarkAppHelper::OnIconsDownloaded(success, bitmaps);
    136   }
    137 
    138   const Extension* extension() { return extension_; }
    139 
    140  private:
    141   const Extension* extension_;
    142 
    143   DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppHelper);
    144 };
    145 
    146 TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkApp) {
    147   WebApplicationInfo web_app_info;
    148   web_app_info.app_url = GURL(kAppUrl);
    149   web_app_info.title = base::UTF8ToUTF16(kAppTitle);
    150   web_app_info.description = base::UTF8ToUTF16(kAppDescription);
    151 
    152   scoped_ptr<content::WebContents> contents(
    153       content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL));
    154   TestBookmarkAppHelper helper(service_, web_app_info, contents.get());
    155   helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete,
    156                            base::Unretained(&helper)));
    157 
    158   std::map<GURL, std::vector<SkBitmap> > icon_map;
    159   icon_map[GURL(kAppUrl)].push_back(
    160       CreateSquareBitmapWithColor(kIconSizeSmall, SK_ColorRED));
    161   helper.CompleteIconDownload(true, icon_map);
    162 
    163   base::RunLoop().RunUntilIdle();
    164   EXPECT_TRUE(helper.extension());
    165   const Extension* extension =
    166       service_->GetInstalledExtension(helper.extension()->id());
    167   EXPECT_TRUE(extension);
    168   EXPECT_EQ(1u, service_->extensions()->size());
    169   EXPECT_TRUE(extension->from_bookmark());
    170   EXPECT_EQ(kAppTitle, extension->name());
    171   EXPECT_EQ(kAppDescription, extension->description());
    172   EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
    173   EXPECT_FALSE(
    174       IconsInfo::GetIconResource(
    175           extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty());
    176 }
    177 
    178 TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkAppNoContents) {
    179   WebApplicationInfo web_app_info;
    180   web_app_info.app_url = GURL(kAppUrl);
    181   web_app_info.title = base::UTF8ToUTF16(kAppTitle);
    182   web_app_info.description = base::UTF8ToUTF16(kAppDescription);
    183   web_app_info.icons.push_back(
    184       CreateIconInfoWithBitmap(kIconSizeTiny, SK_ColorRED));
    185 
    186   TestBookmarkAppHelper helper(service_, web_app_info, NULL);
    187   helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete,
    188                            base::Unretained(&helper)));
    189 
    190   base::RunLoop().RunUntilIdle();
    191   EXPECT_TRUE(helper.extension());
    192   const Extension* extension =
    193       service_->GetInstalledExtension(helper.extension()->id());
    194   EXPECT_TRUE(extension);
    195   EXPECT_EQ(1u, service_->extensions()->size());
    196   EXPECT_TRUE(extension->from_bookmark());
    197   EXPECT_EQ(kAppTitle, extension->name());
    198   EXPECT_EQ(kAppDescription, extension->description());
    199   EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
    200   EXPECT_FALSE(
    201       IconsInfo::GetIconResource(
    202           extension, kIconSizeTiny, ExtensionIconSet::MATCH_EXACTLY).empty());
    203   EXPECT_FALSE(
    204       IconsInfo::GetIconResource(
    205           extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty());
    206   EXPECT_FALSE(
    207       IconsInfo::GetIconResource(extension,
    208                                  kIconSizeSmall * 2,
    209                                  ExtensionIconSet::MATCH_EXACTLY).empty());
    210   EXPECT_FALSE(
    211       IconsInfo::GetIconResource(
    212           extension, kIconSizeMedium, ExtensionIconSet::MATCH_EXACTLY).empty());
    213   EXPECT_FALSE(
    214       IconsInfo::GetIconResource(extension,
    215                                  kIconSizeMedium * 2,
    216                                  ExtensionIconSet::MATCH_EXACTLY).empty());
    217 }
    218 
    219 TEST_F(BookmarkAppHelperExtensionServiceTest, CreateAndUpdateBookmarkApp) {
    220   EXPECT_EQ(0u, registry()->enabled_extensions().size());
    221   WebApplicationInfo web_app_info;
    222   web_app_info.app_url = GURL(kAppUrl);
    223   web_app_info.title = base::UTF8ToUTF16(kAppTitle);
    224   web_app_info.description = base::UTF8ToUTF16(kAppDescription);
    225   web_app_info.icons.push_back(
    226       CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED));
    227 
    228   extensions::CreateOrUpdateBookmarkApp(service_, web_app_info);
    229   base::RunLoop().RunUntilIdle();
    230 
    231   {
    232     EXPECT_EQ(1u, registry()->enabled_extensions().size());
    233     const Extension* extension = service_->extensions()->begin()->get();
    234     EXPECT_TRUE(extension->from_bookmark());
    235     EXPECT_EQ(kAppTitle, extension->name());
    236     EXPECT_EQ(kAppDescription, extension->description());
    237     EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
    238     EXPECT_FALSE(extensions::IconsInfo::GetIconResource(
    239                      extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY)
    240                      .empty());
    241   }
    242 
    243   web_app_info.title = base::UTF8ToUTF16(kAlternativeAppTitle);
    244   web_app_info.icons[0] = CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorRED);
    245 
    246   extensions::CreateOrUpdateBookmarkApp(service_, web_app_info);
    247   base::RunLoop().RunUntilIdle();
    248 
    249   {
    250     EXPECT_EQ(1u, registry()->enabled_extensions().size());
    251     const Extension* extension = service_->extensions()->begin()->get();
    252     EXPECT_TRUE(extension->from_bookmark());
    253     EXPECT_EQ(kAlternativeAppTitle, extension->name());
    254     EXPECT_EQ(kAppDescription, extension->description());
    255     EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
    256     EXPECT_TRUE(extensions::IconsInfo::GetIconResource(
    257                     extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY)
    258                     .empty());
    259     EXPECT_FALSE(extensions::IconsInfo::GetIconResource(
    260                      extension, kIconSizeLarge, ExtensionIconSet::MATCH_EXACTLY)
    261                      .empty());
    262   }
    263 }
    264 
    265 TEST_F(BookmarkAppHelperExtensionServiceTest, GetWebApplicationInfo) {
    266   WebApplicationInfo web_app_info;
    267   web_app_info.app_url = GURL(kAppUrl);
    268   web_app_info.title = base::UTF8ToUTF16(kAppTitle);
    269   web_app_info.description = base::UTF8ToUTF16(kAppDescription);
    270 
    271   web_app_info.icons.push_back(
    272       CreateIconInfoWithBitmap(kIconSizeSmall, SK_ColorRED));
    273   web_app_info.icons.push_back(
    274       CreateIconInfoWithBitmap(kIconSizeLarge, SK_ColorRED));
    275 
    276   extensions::CreateOrUpdateBookmarkApp(service_, web_app_info);
    277   base::RunLoop().RunUntilIdle();
    278 
    279   EXPECT_EQ(1u, registry()->enabled_extensions().size());
    280   base::RunLoop run_loop;
    281   extensions::GetWebApplicationInfoFromApp(
    282       profile_.get(),
    283       service_->extensions()->begin()->get(),
    284       base::Bind(
    285           &ValidateWebApplicationInfo, run_loop.QuitClosure(), web_app_info));
    286   run_loop.Run();
    287 }
    288 
    289 TEST_F(BookmarkAppHelperTest, ConstrainBitmapsToSizes) {
    290   std::set<int> desired_sizes;
    291   desired_sizes.insert(16);
    292   desired_sizes.insert(32);
    293   desired_sizes.insert(128);
    294   desired_sizes.insert(256);
    295 
    296   {
    297     std::vector<SkBitmap> bitmaps;
    298     bitmaps.push_back(CreateSquareBitmapWithColor(16, SK_ColorRED));
    299     bitmaps.push_back(CreateSquareBitmapWithColor(32, SK_ColorGREEN));
    300     bitmaps.push_back(CreateSquareBitmapWithColor(48, SK_ColorBLUE));
    301     bitmaps.push_back(CreateSquareBitmapWithColor(144, SK_ColorYELLOW));
    302 
    303     std::map<int, SkBitmap> results(
    304         BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
    305 
    306     EXPECT_EQ(3u, results.size());
    307     ValidateBitmapSizeAndColor(results[16], 16, SK_ColorRED);
    308     ValidateBitmapSizeAndColor(results[32], 32, SK_ColorGREEN);
    309     ValidateBitmapSizeAndColor(results[128], 128, SK_ColorYELLOW);
    310   }
    311   {
    312     std::vector<SkBitmap> bitmaps;
    313     bitmaps.push_back(CreateSquareBitmapWithColor(512, SK_ColorRED));
    314     bitmaps.push_back(CreateSquareBitmapWithColor(18, SK_ColorGREEN));
    315     bitmaps.push_back(CreateSquareBitmapWithColor(33, SK_ColorBLUE));
    316     bitmaps.push_back(CreateSquareBitmapWithColor(17, SK_ColorYELLOW));
    317 
    318     std::map<int, SkBitmap> results(
    319         BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
    320 
    321     EXPECT_EQ(3u, results.size());
    322     ValidateBitmapSizeAndColor(results[16], 16, SK_ColorYELLOW);
    323     ValidateBitmapSizeAndColor(results[32], 32, SK_ColorBLUE);
    324     ValidateBitmapSizeAndColor(results[256], 256, SK_ColorRED);
    325   }
    326 }
    327 
    328 TEST_F(BookmarkAppHelperTest, IsValidBookmarkAppUrl) {
    329   EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://www.chromium.org")));
    330   EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("http://www.chromium.org/path")));
    331   EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("ftp://www.chromium.org")));
    332   EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("chrome://flags")));
    333 }
    334 
    335 }  // namespace extensions
    336