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