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.
5 #include "chrome/browser/extensions/bookmark_app_helper.h"
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"
25 const char kAppUrl
[] = "http://www.chromium.org";
26 const char kAlternativeAppUrl
[] = "http://www.notchromium.org";
27 const char kAppTitle
[] = "Test title";
28 const char kAppShortName
[] = "Test short name";
29 const char kAlternativeAppTitle
[] = "Different test title";
30 const char kAppDescription
[] = "Test description";
31 const char kAppIcon1
[] = "fav1.png";
32 const char kAppIcon2
[] = "fav2.png";
33 const char kAppIcon3
[] = "fav3.png";
35 const int kIconSizeTiny
= extension_misc::EXTENSION_ICON_BITTY
;
36 const int kIconSizeSmall
= extension_misc::EXTENSION_ICON_SMALL
;
37 const int kIconSizeMedium
= extension_misc::EXTENSION_ICON_MEDIUM
;
38 const int kIconSizeLarge
= extension_misc::EXTENSION_ICON_LARGE
;
40 class BookmarkAppHelperTest
: public testing::Test
{
42 BookmarkAppHelperTest() {}
43 ~BookmarkAppHelperTest() override
{}
46 DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperTest
);
49 class BookmarkAppHelperExtensionServiceTest
50 : public extensions::ExtensionServiceTestBase
{
52 BookmarkAppHelperExtensionServiceTest() {}
53 ~BookmarkAppHelperExtensionServiceTest() override
{}
55 void SetUp() override
{
56 extensions::ExtensionServiceTestBase::SetUp();
57 InitializeEmptyExtensionService();
59 EXPECT_EQ(0u, registry()->enabled_extensions().size());
62 void TearDown() override
{
63 ExtensionServiceTestBase::TearDown();
64 for (content::RenderProcessHost::iterator
i(
65 content::RenderProcessHost::AllHostsIterator());
68 content::RenderProcessHost
* host
= i
.GetCurrentValue();
69 if (Profile::FromBrowserContext(host
->GetBrowserContext()) ==
76 DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperExtensionServiceTest
);
79 SkBitmap
CreateSquareBitmapWithColor(int size
, SkColor color
) {
81 bitmap
.allocN32Pixels(size
, size
);
82 bitmap
.eraseColor(color
);
86 WebApplicationInfo::IconInfo
CreateIconInfoWithBitmap(int size
, SkColor color
) {
87 WebApplicationInfo::IconInfo icon_info
;
88 icon_info
.width
= size
;
89 icon_info
.height
= size
;
90 icon_info
.data
= CreateSquareBitmapWithColor(size
, color
);
94 void ValidateWebApplicationInfo(base::Closure callback
,
95 const WebApplicationInfo
& expected
,
96 const WebApplicationInfo
& actual
) {
97 EXPECT_EQ(expected
.title
, actual
.title
);
98 EXPECT_EQ(expected
.description
, actual
.description
);
99 EXPECT_EQ(expected
.app_url
, actual
.app_url
);
100 EXPECT_EQ(expected
.icons
.size(), actual
.icons
.size());
101 for (size_t i
= 0; i
< expected
.icons
.size(); ++i
) {
102 EXPECT_EQ(expected
.icons
[i
].width
, actual
.icons
[i
].width
);
103 EXPECT_EQ(expected
.icons
[i
].height
, actual
.icons
[i
].height
);
104 EXPECT_EQ(expected
.icons
[i
].url
, actual
.icons
[i
].url
);
106 gfx::BitmapsAreEqual(expected
.icons
[i
].data
, actual
.icons
[i
].data
));
113 namespace extensions
{
115 class TestBookmarkAppHelper
: public BookmarkAppHelper
{
117 TestBookmarkAppHelper(ExtensionService
* service
,
118 WebApplicationInfo web_app_info
,
119 content::WebContents
* contents
)
120 : BookmarkAppHelper(service
->profile(), web_app_info
, contents
) {}
122 ~TestBookmarkAppHelper() override
{}
124 void CreationComplete(const extensions::Extension
* extension
,
125 const WebApplicationInfo
& web_app_info
) {
126 extension_
= extension
;
129 void CompleteGetManifest(const content::Manifest
& manifest
) {
130 BookmarkAppHelper::OnDidGetManifest(manifest
);
133 void CompleteIconDownload(
135 const std::map
<GURL
, std::vector
<SkBitmap
> >& bitmaps
) {
136 BookmarkAppHelper::OnIconsDownloaded(success
, bitmaps
);
139 const Extension
* extension() { return extension_
; }
142 const Extension
* extension_
;
144 DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppHelper
);
147 TEST_F(BookmarkAppHelperExtensionServiceTest
, CreateBookmarkApp
) {
148 WebApplicationInfo web_app_info
;
149 web_app_info
.app_url
= GURL(kAppUrl
);
150 web_app_info
.title
= base::UTF8ToUTF16(kAppTitle
);
151 web_app_info
.description
= base::UTF8ToUTF16(kAppDescription
);
153 scoped_ptr
<content::WebContents
> contents(
154 content::WebContentsTester::CreateTestWebContents(profile_
.get(), NULL
));
155 TestBookmarkAppHelper
helper(service_
, web_app_info
, contents
.get());
156 helper
.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete
,
157 base::Unretained(&helper
)));
159 std::map
<GURL
, std::vector
<SkBitmap
> > icon_map
;
160 icon_map
[GURL(kAppUrl
)].push_back(
161 CreateSquareBitmapWithColor(kIconSizeSmall
, SK_ColorRED
));
162 helper
.CompleteIconDownload(true, icon_map
);
164 base::RunLoop().RunUntilIdle();
165 EXPECT_TRUE(helper
.extension());
166 const Extension
* extension
=
167 service_
->GetInstalledExtension(helper
.extension()->id());
168 EXPECT_TRUE(extension
);
169 EXPECT_EQ(1u, registry()->enabled_extensions().size());
170 EXPECT_TRUE(extension
->from_bookmark());
171 EXPECT_EQ(kAppTitle
, extension
->name());
172 EXPECT_EQ(kAppDescription
, extension
->description());
173 EXPECT_EQ(GURL(kAppUrl
), AppLaunchInfo::GetLaunchWebURL(extension
));
175 IconsInfo::GetIconResource(
176 extension
, kIconSizeSmall
, ExtensionIconSet::MATCH_EXACTLY
).empty());
179 TEST_F(BookmarkAppHelperExtensionServiceTest
, CreateBookmarkAppWithManifest
) {
180 WebApplicationInfo web_app_info
;
182 scoped_ptr
<content::WebContents
> contents(
183 content::WebContentsTester::CreateTestWebContents(profile_
.get(), NULL
));
184 TestBookmarkAppHelper
helper(service_
, web_app_info
, contents
.get());
185 helper
.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete
,
186 base::Unretained(&helper
)));
188 content::Manifest manifest
;
189 manifest
.start_url
= GURL(kAppUrl
);
190 manifest
.name
= base::NullableString16(base::UTF8ToUTF16(kAppTitle
), false);
191 helper
.CompleteGetManifest(manifest
);
193 std::map
<GURL
, std::vector
<SkBitmap
> > icon_map
;
194 helper
.CompleteIconDownload(true, icon_map
);
196 base::RunLoop().RunUntilIdle();
197 EXPECT_TRUE(helper
.extension());
198 const Extension
* extension
=
199 service_
->GetInstalledExtension(helper
.extension()->id());
200 EXPECT_TRUE(extension
);
201 EXPECT_EQ(1u, registry()->enabled_extensions().size());
202 EXPECT_TRUE(extension
->from_bookmark());
203 EXPECT_EQ(kAppTitle
, extension
->name());
204 EXPECT_EQ(GURL(kAppUrl
), AppLaunchInfo::GetLaunchWebURL(extension
));
207 TEST_F(BookmarkAppHelperExtensionServiceTest
, CreateBookmarkAppNoContents
) {
208 WebApplicationInfo web_app_info
;
209 web_app_info
.app_url
= GURL(kAppUrl
);
210 web_app_info
.title
= base::UTF8ToUTF16(kAppTitle
);
211 web_app_info
.description
= base::UTF8ToUTF16(kAppDescription
);
212 web_app_info
.icons
.push_back(
213 CreateIconInfoWithBitmap(kIconSizeTiny
, SK_ColorRED
));
215 TestBookmarkAppHelper
helper(service_
, web_app_info
, NULL
);
216 helper
.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete
,
217 base::Unretained(&helper
)));
219 base::RunLoop().RunUntilIdle();
220 EXPECT_TRUE(helper
.extension());
221 const Extension
* extension
=
222 service_
->GetInstalledExtension(helper
.extension()->id());
223 EXPECT_TRUE(extension
);
224 EXPECT_EQ(1u, registry()->enabled_extensions().size());
225 EXPECT_TRUE(extension
->from_bookmark());
226 EXPECT_EQ(kAppTitle
, extension
->name());
227 EXPECT_EQ(kAppDescription
, extension
->description());
228 EXPECT_EQ(GURL(kAppUrl
), AppLaunchInfo::GetLaunchWebURL(extension
));
229 // The tiny icon should have been removed and only the generated ones used.
231 IconsInfo::GetIconResource(extension
, kIconSizeTiny
,
232 ExtensionIconSet::MATCH_EXACTLY
).empty());
234 IconsInfo::GetIconResource(
235 extension
, kIconSizeSmall
, ExtensionIconSet::MATCH_EXACTLY
).empty());
237 IconsInfo::GetIconResource(extension
,
239 ExtensionIconSet::MATCH_EXACTLY
).empty());
241 IconsInfo::GetIconResource(
242 extension
, kIconSizeMedium
, ExtensionIconSet::MATCH_EXACTLY
).empty());
244 IconsInfo::GetIconResource(extension
,
246 ExtensionIconSet::MATCH_EXACTLY
).empty());
249 TEST_F(BookmarkAppHelperExtensionServiceTest
, CreateAndUpdateBookmarkApp
) {
250 EXPECT_EQ(0u, registry()->enabled_extensions().size());
251 WebApplicationInfo web_app_info
;
252 web_app_info
.app_url
= GURL(kAppUrl
);
253 web_app_info
.title
= base::UTF8ToUTF16(kAppTitle
);
254 web_app_info
.description
= base::UTF8ToUTF16(kAppDescription
);
255 web_app_info
.icons
.push_back(
256 CreateIconInfoWithBitmap(kIconSizeSmall
, SK_ColorRED
));
258 extensions::CreateOrUpdateBookmarkApp(service_
, &web_app_info
);
259 base::RunLoop().RunUntilIdle();
262 EXPECT_EQ(1u, registry()->enabled_extensions().size());
263 const Extension
* extension
=
264 registry()->enabled_extensions().begin()->get();
265 EXPECT_TRUE(extension
->from_bookmark());
266 EXPECT_EQ(kAppTitle
, extension
->name());
267 EXPECT_EQ(kAppDescription
, extension
->description());
268 EXPECT_EQ(GURL(kAppUrl
), AppLaunchInfo::GetLaunchWebURL(extension
));
269 EXPECT_FALSE(extensions::IconsInfo::GetIconResource(
270 extension
, kIconSizeSmall
, ExtensionIconSet::MATCH_EXACTLY
)
274 web_app_info
.title
= base::UTF8ToUTF16(kAlternativeAppTitle
);
275 web_app_info
.icons
[0] = CreateIconInfoWithBitmap(kIconSizeLarge
, SK_ColorRED
);
277 extensions::CreateOrUpdateBookmarkApp(service_
, &web_app_info
);
278 base::RunLoop().RunUntilIdle();
281 EXPECT_EQ(1u, registry()->enabled_extensions().size());
282 const Extension
* extension
=
283 registry()->enabled_extensions().begin()->get();
284 EXPECT_TRUE(extension
->from_bookmark());
285 EXPECT_EQ(kAlternativeAppTitle
, extension
->name());
286 EXPECT_EQ(kAppDescription
, extension
->description());
287 EXPECT_EQ(GURL(kAppUrl
), AppLaunchInfo::GetLaunchWebURL(extension
));
288 EXPECT_TRUE(extensions::IconsInfo::GetIconResource(
289 extension
, kIconSizeSmall
, ExtensionIconSet::MATCH_EXACTLY
)
291 EXPECT_FALSE(extensions::IconsInfo::GetIconResource(
292 extension
, kIconSizeLarge
, ExtensionIconSet::MATCH_EXACTLY
)
297 TEST_F(BookmarkAppHelperExtensionServiceTest
, GetWebApplicationInfo
) {
298 WebApplicationInfo web_app_info
;
299 web_app_info
.app_url
= GURL(kAppUrl
);
300 web_app_info
.title
= base::UTF8ToUTF16(kAppTitle
);
301 web_app_info
.description
= base::UTF8ToUTF16(kAppDescription
);
303 web_app_info
.icons
.push_back(
304 CreateIconInfoWithBitmap(kIconSizeSmall
, SK_ColorRED
));
305 web_app_info
.icons
.push_back(
306 CreateIconInfoWithBitmap(kIconSizeLarge
, SK_ColorRED
));
308 extensions::CreateOrUpdateBookmarkApp(service_
, &web_app_info
);
309 base::RunLoop().RunUntilIdle();
311 EXPECT_EQ(1u, registry()->enabled_extensions().size());
312 base::RunLoop run_loop
;
313 extensions::GetWebApplicationInfoFromApp(
314 profile_
.get(), registry()->enabled_extensions().begin()->get(),
315 base::Bind(&ValidateWebApplicationInfo
, run_loop
.QuitClosure(),
320 TEST_F(BookmarkAppHelperTest
, UpdateWebAppInfoFromManifest
) {
321 WebApplicationInfo web_app_info
;
322 web_app_info
.title
= base::UTF8ToUTF16(kAlternativeAppTitle
);
323 web_app_info
.app_url
= GURL(kAlternativeAppUrl
);
324 WebApplicationInfo::IconInfo info
;
325 info
.url
= GURL(kAppIcon1
);
326 web_app_info
.icons
.push_back(info
);
328 content::Manifest manifest
;
329 manifest
.start_url
= GURL(kAppUrl
);
330 manifest
.short_name
= base::NullableString16(base::UTF8ToUTF16(kAppShortName
),
333 BookmarkAppHelper::UpdateWebAppInfoFromManifest(manifest
, &web_app_info
);
334 EXPECT_EQ(base::UTF8ToUTF16(kAppShortName
), web_app_info
.title
);
335 EXPECT_EQ(GURL(kAppUrl
), web_app_info
.app_url
);
337 // The icon info from |web_app_info| should be left as is, since the manifest
338 // doesn't have any icon information.
339 EXPECT_EQ(1u, web_app_info
.icons
.size());
340 EXPECT_EQ(GURL(kAppIcon1
), web_app_info
.icons
[0].url
);
342 // Test that |manifest.name| takes priority over |manifest.short_name|, and
343 // that icons provided by the manifest replace icons in |web_app_info|.
344 manifest
.name
= base::NullableString16(base::UTF8ToUTF16(kAppTitle
), false);
346 content::Manifest::Icon icon
;
347 icon
.src
= GURL(kAppIcon2
);
348 manifest
.icons
.push_back(icon
);
349 icon
.src
= GURL(kAppIcon3
);
350 manifest
.icons
.push_back(icon
);
352 BookmarkAppHelper::UpdateWebAppInfoFromManifest(manifest
, &web_app_info
);
353 EXPECT_EQ(base::UTF8ToUTF16(kAppTitle
), web_app_info
.title
);
355 EXPECT_EQ(2u, web_app_info
.icons
.size());
356 EXPECT_EQ(GURL(kAppIcon2
), web_app_info
.icons
[0].url
);
357 EXPECT_EQ(GURL(kAppIcon3
), web_app_info
.icons
[1].url
);
360 TEST_F(BookmarkAppHelperTest
, IsValidBookmarkAppUrl
) {
361 EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("https://www.chromium.org")));
362 EXPECT_TRUE(IsValidBookmarkAppUrl(GURL("http://www.chromium.org/path")));
363 EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("ftp://www.chromium.org")));
364 EXPECT_FALSE(IsValidBookmarkAppUrl(GURL("chrome://flags")));
367 } // namespace extensions