// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/convert_web_app.h"

#include <stddef.h>
#include <stdint.h>

#include <limits>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/base64.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_file_value_serializer.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h"
#include "chrome/common/extensions/manifest_handlers/app_theme_color_info.h"
#include "chrome/common/web_application_info.h"
#include "content/public/common/url_constants.h"
#include "crypto/sha2.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/file_util.h"
#include "extensions/common/image_util.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/file_handler_info.h"
#include "net/base/url_util.h"
#include "third_party/blink/public/common/manifest/manifest_util.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "url/gurl.h"

namespace extensions {

namespace keys = manifest_keys;

namespace {
const char kIconsDirName[] = "icons";
const char kScopeUrlHandlerId[] = "scope";
const char kShortcutIconsDirName[] = "shortcut_icons";

bool IsValidFileExtension(const std::string& file_extension) {
  return !file_extension.empty() && file_extension[0] == '.';
}

base::Value CreateFileHandlersForBookmarkApp(
    const std::vector<blink::Manifest::FileHandler>& manifest_file_handlers) {
  base::Value file_handlers(base::Value::Type::DICTIONARY);

  for (const auto& entry : manifest_file_handlers) {
    base::Value file_handler(base::Value::Type::DICTIONARY);
    file_handler.SetKey(keys::kFileHandlerIncludeDirectories,
                        base::Value(false));
    file_handler.SetKey(keys::kFileHandlerVerb,
                        base::Value(apps::file_handler_verbs::kOpenWith));

    base::Value mime_types(base::Value::Type::LIST);
    base::Value file_extensions(base::Value::Type::LIST);

    for (const auto& it : entry.accept) {
      std::string type = base::UTF16ToUTF8(it.first);
      if (type.empty())
        continue;

      mime_types.Append(base::Value(type));
      for (const auto& extensionUTF16 : it.second) {
        std::string extension = base::UTF16ToUTF8(extensionUTF16);
        if (!IsValidFileExtension(extension))
          continue;

        // Remove the '.' before appending.
        file_extensions.Append(base::Value(extension.substr(1)));
      }
    }

    file_handler.SetKey(keys::kFileHandlerTypes, std::move(mime_types));
    file_handler.SetKey(keys::kFileHandlerExtensions,
                        std::move(file_extensions));

    file_handlers.SetKey(entry.action.spec(), std::move(file_handler));
  }

  return file_handlers;
}

base::Value CreateWebAppFileHandlersForBookmarkApp(
    const std::vector<blink::Manifest::FileHandler>& manifest_file_handlers) {
  base::Value file_handlers(base::Value::Type::LIST);

  for (const auto& manifest_file_handler : manifest_file_handlers) {
    base::Value file_handler(base::Value::Type::DICTIONARY);
    base::Value accept(base::Value::Type::DICTIONARY);

    for (const auto& manifest_accept_entry : manifest_file_handler.accept) {
      std::string mime_type = base::UTF16ToUTF8(manifest_accept_entry.first);
      if (mime_type.empty())
        continue;
      base::Value file_extensions(base::Value::Type::LIST);

      for (const auto& manifest_file_extension : manifest_accept_entry.second) {
        std::string file_extension = base::UTF16ToUTF8(manifest_file_extension);
        if (!IsValidFileExtension(file_extension))
          continue;
        file_extensions.Append(base::Value(file_extension));
      }

      accept.SetKey(std::move(mime_type), std::move(file_extensions));
    }

    file_handler.SetKey(keys::kWebAppFileHandlerAction,
                        base::Value(manifest_file_handler.action.spec()));
    file_handler.SetKey(keys::kWebAppFileHandlerAccept, std::move(accept));
    file_handlers.Append(std::move(file_handler));
  }

  return file_handlers;
}

}  // namespace

std::unique_ptr<base::DictionaryValue> CreateURLHandlersForBookmarkApp(
    const GURL& scope_url,
    const base::string16& title) {
  auto matches = std::make_unique<base::ListValue>();
  matches->AppendString(scope_url.GetOrigin().Resolve(scope_url.path()).spec() +
                        "*");

  auto scope_handler = std::make_unique<base::DictionaryValue>();
  scope_handler->SetList(keys::kMatches, std::move(matches));
  // The URL handler title is not used anywhere but we set it to the
  // web app's title just in case.
  scope_handler->SetString(keys::kUrlHandlerTitle, base::UTF16ToUTF8(title));

  auto url_handlers = std::make_unique<base::DictionaryValue>();
  // Use "scope" as the url handler's identifier.
  url_handlers->SetDictionary(kScopeUrlHandlerId, std::move(scope_handler));
  return url_handlers;
}

GURL GetScopeURLFromBookmarkApp(const Extension* extension) {
  DCHECK(extension->from_bookmark());
  const std::vector<UrlHandlerInfo>* url_handlers =
      UrlHandlers::GetUrlHandlers(extension);
  if (!url_handlers)
    return GURL();

  // A Bookmark app created by us should only have a url_handler with id
  // kScopeUrlHandlerId. This URL handler should have a single pattern which
  // corresponds to the web manifest's scope. The URL handler's pattern should
  // be the Web Manifest's scope's origin + path with a wildcard, '*', appended
  // to it.
  auto handler_it = std::find_if(
      url_handlers->begin(), url_handlers->end(),
      [](const UrlHandlerInfo& info) { return info.id == kScopeUrlHandlerId; });
  if (handler_it == url_handlers->end()) {
    return GURL();
  }

  const auto& patterns = handler_it->patterns;
  DCHECK(patterns.size() == 1);
  const auto& pattern_iter = patterns.begin();
  // Remove the '*' character at the end (which was added when creating the URL
  // handler, see CreateURLHandlersForBookmarkApp()).
  const std::string& pattern_str = pattern_iter->GetAsString();
  DCHECK_EQ(pattern_str.back(), '*');
  return GURL(pattern_str.substr(0, pattern_str.size() - 1));
}

// Generates a version for the converted app using the current date. This isn't
// really needed, but it seems like useful information.
std::string ConvertTimeToExtensionVersion(const base::Time& create_time) {
  base::Time::Exploded create_time_exploded;
  create_time.UTCExplode(&create_time_exploded);

  double micros = static_cast<double>(
      (create_time_exploded.millisecond *
       base::Time::kMicrosecondsPerMillisecond) +
      (create_time_exploded.second * base::Time::kMicrosecondsPerSecond) +
      (create_time_exploded.minute * base::Time::kMicrosecondsPerMinute) +
      (create_time_exploded.hour * base::Time::kMicrosecondsPerHour));
  double day_fraction = micros / base::Time::kMicrosecondsPerDay;
  int stamp =
      gfx::ToRoundedInt(day_fraction * std::numeric_limits<uint16_t>::max());

  return base::StringPrintf("%i.%i.%i.%i", create_time_exploded.year,
                            create_time_exploded.month,
                            create_time_exploded.day_of_month, stamp);
}

scoped_refptr<Extension> ConvertWebAppToExtension(
    const WebApplicationInfo& web_app,
    const base::Time& create_time,
    const base::FilePath& extensions_dir,
    int extra_creation_flags,
    Manifest::Location install_source) {
  base::FilePath install_temp_dir =
      file_util::GetInstallTempDir(extensions_dir);
  if (install_temp_dir.empty()) {
    LOG(ERROR) << "Could not get path to profile temporary directory.";
    return nullptr;
  }

  base::ScopedTempDir temp_dir;
  if (!temp_dir.CreateUniqueTempDirUnderPath(install_temp_dir)) {
    LOG(ERROR) << "Could not create temporary directory.";
    return nullptr;
  }

  // Create the manifest
  std::unique_ptr<base::DictionaryValue> root(new base::DictionaryValue);
  root->SetString(keys::kPublicKey,
                  web_app::GenerateAppKeyFromURL(web_app.app_url));
  root->SetString(keys::kName, base::UTF16ToUTF8(web_app.title));
  root->SetString(keys::kVersion, ConvertTimeToExtensionVersion(create_time));
  root->SetString(keys::kDescription, base::UTF16ToUTF8(web_app.description));
  root->SetString(keys::kLaunchWebURL, web_app.app_url.spec());
  if (web_app.generated_icon_color != SK_ColorTRANSPARENT) {
    root->SetString(keys::kAppIconColor, image_util::GenerateHexColorString(
                                             web_app.generated_icon_color));
  }

  if (web_app.theme_color) {
    root->SetString(keys::kAppThemeColor, color_utils::SkColorToRgbaString(
                                              web_app.theme_color.value()));
  }

  // Currently Bookmark Apps don't support chrome-untrusted:// URLHandlers.
  // Adding support for chrome-untrusted:// to URLHandlers would involve adding
  // chrome-untrusted:// as a valid scheme for Extensions which has unfortunate
  // side effects, like making chrome-untrusted:// URLs scriptable. Since
  // Bookmark Apps are being deprecated, just don't add URLHandlers instead of
  // adding support for chrome-untrusted:// and dealing with the side-effects.
#if DCHECK_IS_ON()
  // Not setting URLHandlers for chrome-untrusted:// apps means that the app's
  // scope will fallback to the parent directory of the start URL, which in the
  // case of all SWAs today is equal to the scope they set. This DCHECK ensure
  // we notice if this changes.
  if (!web_app.scope.is_empty() &&
      web_app.app_url.SchemeIs(content::kChromeUIUntrustedScheme)) {
    DCHECK_EQ(web_app.app_url.GetWithoutFilename(), web_app.scope);
  }
#endif  // DCHECK_IS_ON()

  if (!web_app.scope.is_empty() &&
      !web_app.app_url.SchemeIs(content::kChromeUIUntrustedScheme)) {
    root->SetDictionary(keys::kUrlHandlers, CreateURLHandlersForBookmarkApp(
                                                web_app.scope, web_app.title));
  }

  DCHECK_NE(blink::mojom::DisplayMode::kUndefined, web_app.display_mode);
  root->SetString(keys::kAppDisplayMode,
                  blink::DisplayModeToString(web_app.display_mode));

  // TODO(crbug.com/938103): The app's file handlers are serialized twice here,
  // as apps::FileHandlerInfo and apps::FileHandler. This is clearly redundant,
  // but only a temporary measure, until web apps move off Bookmark Apps with
  // the launch of BMO (at which point the apps::FileHandlerInfo representation
  // can be removed).
  if (web_app.file_handlers.size() != 0) {
    root->SetKey(keys::kFileHandlers,
                 CreateFileHandlersForBookmarkApp(web_app.file_handlers));
    root->SetKey(keys::kWebAppFileHandlers,
                 CreateWebAppFileHandlersForBookmarkApp(web_app.file_handlers));
  }

  // Add the icons and linked icon information.
  auto linked_icons = std::make_unique<base::ListValue>();
  for (const WebApplicationIconInfo& icon_info : web_app.icon_infos) {
    DCHECK(icon_info.url.is_valid());
    std::unique_ptr<base::DictionaryValue> linked_icon(
        new base::DictionaryValue());
    linked_icon->SetString(keys::kLinkedAppIconURL, icon_info.url.spec());
    linked_icon->SetInteger(keys::kLinkedAppIconSize, icon_info.square_size_px);
    linked_icons->Append(std::move(linked_icon));
  }
  auto icons = std::make_unique<base::DictionaryValue>();
  for (const std::pair<const SquareSizePx, SkBitmap>& icon :
       web_app.icon_bitmaps) {
    std::string size = base::StringPrintf("%i", icon.first);
    std::string icon_path = base::StringPrintf("%s/%s.png", kIconsDirName,
                                               size.c_str());
    icons->SetString(size, icon_path);
  }
  root->Set(keys::kIcons, std::move(icons));
  root->Set(keys::kLinkedAppIcons, std::move(linked_icons));

  // Add shortcuts icons and linked shortcut items information.
  if (base::FeatureList::IsEnabled(
          features::kDesktopPWAsAppIconShortcutsMenu) &&
      !web_app.shortcut_infos.empty()) {
    // |linked_shortcut_items| is a list of all entries in the Web App
    // Manifest's shortcuts member. It includes the name, url and list of
    // shortcut_icon_infos associated with the shortcut item.
    auto linked_shortcut_items = std::make_unique<base::ListValue>();
    for (const auto& shortcut : web_app.shortcut_infos) {
      auto linked_shortcut_item = std::make_unique<base::DictionaryValue>();
      linked_shortcut_item->SetString(keys::kWebAppLinkedShortcutItemName,
                                      shortcut.name);
      linked_shortcut_item->SetString(keys::kWebAppLinkedShortcutItemURL,
                                      shortcut.url.spec());
      // Add shortcut item icons information.
      auto shortcut_item_icons = std::make_unique<base::ListValue>();
      for (const auto& icon : shortcut.shortcut_icon_infos) {
        DCHECK(icon.url.is_valid());
        std::unique_ptr<base::DictionaryValue> shortcut_item_icon(
            new base::DictionaryValue());
        shortcut_item_icon->SetString(keys::kWebAppLinkedShortcutItemIconURL,
                                      icon.url.spec());
        shortcut_item_icon->SetInteger(keys::kWebAppLinkedShortcutItemIconSize,
                                       icon.square_size_px);
        shortcut_item_icons->Append(std::move(shortcut_item_icon));
      }
      linked_shortcut_item->Set(keys::kWebAppLinkedShortcutItemIcons,
                                std::move(shortcut_item_icons));

      linked_shortcut_items->Append(std::move(linked_shortcut_item));
    }

    // |shortcuts_icons| is a mapping of 'shortcuts_icons' specified in the
    // WebAppManifest and written to disk, keyed to each index in the
    // WebAppManifest's shortcuts vector.
    auto shortcuts_icons = std::make_unique<base::DictionaryValue>();
    for (const auto& shortcut_icon_bitmaps :
         web_app.shortcuts_menu_icons_bitmaps) {
      // |shortcut_icons| is a mapping of filepath keyed to SquareSizePx
      // specified in the WebAppManifest for every icon written to disk for the
      // current shortcut in web_app.shortcut_infos. A shortcut in the
      // WebAppManifest can have different icons for different sizes.
      auto shortcut_icons = std::make_unique<base::DictionaryValue>();
      std::string curr_icon = base::NumberToString(shortcuts_icons->size());
      for (const auto& icon : shortcut_icon_bitmaps) {
        std::string size = base::NumberToString(icon.first);
        std::string icon_path =
            base::StringPrintf("%s/%s/%s.png", kShortcutIconsDirName,
                               curr_icon.c_str(), size.c_str());
        shortcut_icons->SetString(size, icon_path);
      }
      shortcuts_icons->SetDictionary(curr_icon, std::move(shortcut_icons));
    }

    if (!shortcuts_icons->empty())
      root->Set(keys::kWebAppShortcutIcons, std::move(shortcuts_icons));

    if (!linked_shortcut_items->empty()) {
      root->Set(keys::kWebAppLinkedShortcutItems,
                std::move(linked_shortcut_items));
    }
  }

  // Write the manifest.
  base::FilePath manifest_path = temp_dir.GetPath().Append(kManifestFilename);
  JSONFileValueSerializer serializer(manifest_path);
  if (!serializer.Serialize(*root)) {
    LOG(ERROR) << "Could not serialize manifest.";
    return nullptr;
  }

  // Write the icon files.
  base::FilePath icons_dir = temp_dir.GetPath().AppendASCII(kIconsDirName);
  if (!base::CreateDirectory(icons_dir)) {
    LOG(ERROR) << "Could not create icons directory.";
    return nullptr;
  }
  for (const std::pair<const SquareSizePx, SkBitmap>& icon :
       web_app.icon_bitmaps) {
    DCHECK_NE(icon.second.colorType(), kUnknown_SkColorType);

    base::FilePath icon_file =
        icons_dir.AppendASCII(base::StringPrintf("%i.png", icon.first));
    std::vector<unsigned char> image_data;
    if (!gfx::PNGCodec::EncodeBGRASkBitmap(icon.second, false, &image_data)) {
      LOG(ERROR) << "Could not create icon file.";
      return nullptr;
    }

    const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]);
    int size = base::checked_cast<int>(image_data.size());
    if (base::WriteFile(icon_file, image_data_ptr, size) != size) {
      LOG(ERROR) << "Could not write icon file.";
      return nullptr;
    }
  }

  // Write the shortcut icon files.
  if (base::FeatureList::IsEnabled(
          features::kDesktopPWAsAppIconShortcutsMenu) &&
      !web_app.shortcut_infos.empty()) {
    base::FilePath shortcut_icons_dir =
        temp_dir.GetPath().AppendASCII(kShortcutIconsDirName);
    for (size_t i = 0; i < web_app.shortcuts_menu_icons_bitmaps.size(); ++i) {
      if (web_app.shortcuts_menu_icons_bitmaps[i].empty())
        continue;

      base::FilePath icon_dir =
          shortcut_icons_dir.AppendASCII(base::NumberToString(i));
      if (!base::CreateDirectory(icon_dir)) {
        return nullptr;
      }

      for (const std::pair<const SquareSizePx, SkBitmap>& icon :
           web_app.shortcuts_menu_icons_bitmaps[i]) {
        DCHECK_NE(icon.second.colorType(), kUnknown_SkColorType);

        base::FilePath icon_file =
            icon_dir.AppendASCII(base::NumberToString(icon.first) + ".png");
        std::vector<unsigned char> image_data;
        if (!gfx::PNGCodec::EncodeBGRASkBitmap(icon.second, false,
                                               &image_data)) {
          return nullptr;
        }

        const char* image_data_ptr =
            reinterpret_cast<const char*>(&image_data[0]);
        int size = base::checked_cast<int>(image_data.size());
        if (base::WriteFile(icon_file, image_data_ptr, size) != size) {
          return nullptr;
        }
      }
    }
  }

  // Finally, create the extension object to represent the unpacked directory.
  std::string error;
  scoped_refptr<Extension> extension = Extension::Create(
      temp_dir.GetPath(), install_source, *root,
      Extension::FROM_BOOKMARK | extra_creation_flags, &error);
  if (!extension.get()) {
    LOG(ERROR) << error;
    return nullptr;
  }

  temp_dir.Take();  // The caller takes ownership of the directory.
  return extension;
}

}  // namespace extensions
