1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
24a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
34a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// found in the LICENSE file.
44a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
54a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/extensions/convert_web_app.h"
64a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
74a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <string>
84a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <vector>
94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/file_path.h"
114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/file_util.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h"
134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/path_service.h"
144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/stringprintf.h"
154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/time.h"
164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/utf_string_conversions.h"
174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/version.h"
184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/chrome_paths.h"
194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/extensions/extension.h"
204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/extensions/extension_icon_set.h"
214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/extensions/extension_resource.h"
224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/extensions/url_pattern.h"
234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/web_apps.h"
244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "googleurl/src/gurl.h"
254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "testing/gtest/include/gtest/gtest.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/codec/png_codec.h"
274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "webkit/glue/image_decoder.h"
284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochnamespace {
304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Returns an icon info corresponding to a canned icon.
324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochWebApplicationInfo::IconInfo GetIconInfo(const GURL& url, int size) {
334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  WebApplicationInfo::IconInfo result;
344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  FilePath icon_file;
364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!PathService::Get(chrome::DIR_TEST_DATA, &icon_file)) {
374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    ADD_FAILURE() << "Could not get test data directory.";
384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return result;
394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  icon_file = icon_file.AppendASCII("extensions")
424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       .AppendASCII("convert_web_app")
434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       .AppendASCII(StringPrintf("%i.png", size));
444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  result.url = url;
464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  result.width = size;
474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  result.height = size;
484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  std::string icon_data;
504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!file_util::ReadFileToString(icon_file, &icon_data)) {
514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    ADD_FAILURE() << "Could not read test icon.";
524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return result;
534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  webkit_glue::ImageDecoder decoder;
564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  result.data = decoder.Decode(
574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      reinterpret_cast<const unsigned char*>(icon_data.c_str()),
584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      icon_data.size());
594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_FALSE(result.data.isNull()) << "Could not decode test icon.";
604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return result;
624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbase::Time GetTestTime(int year, int month, int day, int hour, int minute,
654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       int second, int millisecond) {
664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  base::Time::Exploded exploded = {0};
674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  exploded.year = year;
684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  exploded.month = month;
694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  exploded.day_of_month = day;
704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  exploded.hour = hour;
714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  exploded.minute = minute;
724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  exploded.second = second;
734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  exploded.millisecond = millisecond;
744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return base::Time::FromUTCExploded(exploded);
754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}  // namespace
784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST(ExtensionFromWebApp, GenerateVersion) {
814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("2010.1.1.0",
824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            ConvertTimeToExtensionVersion(
834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                GetTestTime(2010, 1, 1, 0, 0, 0, 0)));
844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("2010.12.31.22111",
854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            ConvertTimeToExtensionVersion(
864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                GetTestTime(2010, 12, 31, 8, 5, 50, 500)));
874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("2010.10.1.65535",
884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            ConvertTimeToExtensionVersion(
894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                GetTestTime(2010, 10, 1, 23, 59, 59, 999)));
904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST(ExtensionFromWebApp, Basic) {
934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  WebApplicationInfo web_app;
944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.manifest_url = GURL("http://aaronboodman.com/gearpad/manifest.json");
954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.title = ASCIIToUTF16("Gearpad");
964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.description = ASCIIToUTF16("The best text editor in the universe!");
974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.app_url = GURL("http://aaronboodman.com/gearpad/");
984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.permissions.push_back("geolocation");
994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.permissions.push_back("notifications");
1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.urls.push_back(GURL("http://aaronboodman.com/gearpad/"));
1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const int sizes[] = {16, 48, 128};
1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (size_t i = 0; i < arraysize(sizes); ++i) {
1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    GURL icon_url(web_app.app_url.Resolve(StringPrintf("%i.png", sizes[i])));
1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    web_app.icons.push_back(GetIconInfo(icon_url, sizes[i]));
1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_refptr<Extension> extension = ConvertWebAppToExtension(
1094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      web_app, GetTestTime(1978, 12, 11, 0, 0, 0, 0));
1104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ASSERT_TRUE(extension.get());
1114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ScopedTempDir extension_dir;
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(extension_dir.Set(extension->path()));
1144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(extension->is_app());
1164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(extension->is_hosted_app());
1174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_FALSE(extension->is_packaged_app());
1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("lJqm1+jncOHClAuwif1QxNJKfeV9Fbl9IBZx7FkNwkA=",
1204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            extension->public_key());
1214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("ncnbaadanljoanockmphfdkimpdedemj", extension->id());
1224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("1978.12.11.0", extension->version()->GetString());
1234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(UTF16ToUTF8(web_app.title), extension->name());
1244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(UTF16ToUTF8(web_app.description), extension->description());
1254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(web_app.app_url, extension->GetFullLaunchURL());
1264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(2u, extension->api_permissions().size());
1274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(extension->HasApiPermission("geolocation"));
1284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(extension->HasApiPermission("notifications"));
1294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ASSERT_EQ(1u, extension->web_extent().patterns().size());
1304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("http://aaronboodman.com/gearpad/*",
1314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            extension->web_extent().patterns()[0].GetAsString());
1324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(web_app.icons.size(), extension->icons().map().size());
1344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (size_t i = 0; i < web_app.icons.size(); ++i) {
135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    EXPECT_EQ(StringPrintf("icons/%i.png", web_app.icons[i].width),
1364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch              extension->icons().Get(web_app.icons[i].width,
1374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                     ExtensionIconSet::MATCH_EXACTLY));
1384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    ExtensionResource resource = extension->GetIconResource(
1394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        web_app.icons[i].width, ExtensionIconSet::MATCH_EXACTLY);
1404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    ASSERT_TRUE(!resource.empty());
1414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    EXPECT_TRUE(file_util::PathExists(resource.GetFilePath()));
1424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
1444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochTEST(ExtensionFromWebApp, Minimal) {
1464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  WebApplicationInfo web_app;
1474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.manifest_url = GURL("http://aaronboodman.com/gearpad/manifest.json");
1484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.title = ASCIIToUTF16("Gearpad");
1494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  web_app.app_url = GURL("http://aaronboodman.com/gearpad/");
1504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_refptr<Extension> extension = ConvertWebAppToExtension(
1524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      web_app, GetTestTime(1978, 12, 11, 0, 0, 0, 0));
1534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ASSERT_TRUE(extension.get());
1544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ScopedTempDir extension_dir;
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(extension_dir.Set(extension->path()));
1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(extension->is_app());
1594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_TRUE(extension->is_hosted_app());
1604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_FALSE(extension->is_packaged_app());
1614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("lJqm1+jncOHClAuwif1QxNJKfeV9Fbl9IBZx7FkNwkA=",
1634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            extension->public_key());
1644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("ncnbaadanljoanockmphfdkimpdedemj", extension->id());
1654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("1978.12.11.0", extension->version()->GetString());
1664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(UTF16ToUTF8(web_app.title), extension->name());
1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("", extension->description());
1684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(web_app.app_url, extension->GetFullLaunchURL());
1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(0u, extension->icons().map().size());
1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ(0u, extension->api_permissions().size());
1714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  ASSERT_EQ(1u, extension->web_extent().patterns().size());
1724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  EXPECT_EQ("*://aaronboodman.com/*",
1734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            extension->web_extent().patterns()[0].GetAsString());
1744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
175