// 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_user_script.h"

#include <stddef.h>

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

#include "base/base64.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/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/chrome_paths.h"
#include "crypto/sha2.h"
#include "extensions/browser/extension_user_script_loader.h"
#include "extensions/common/api/content_scripts.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/mojom/run_location.mojom-shared.h"
#include "extensions/common/user_script.h"
#include "url/gurl.h"

namespace extensions {

scoped_refptr<Extension> ConvertUserScriptToExtension(
    const base::FilePath& user_script_path,
    const GURL& original_url,
    const base::FilePath& extensions_dir,
    std::u16string* error) {
  using ContentScript = api::content_scripts::ContentScript;

  std::string content;
  if (!base::ReadFileToString(user_script_path, &content)) {
    *error = u"Could not read source file.";
    return nullptr;
  }

  if (!base::IsStringUTF8(content)) {
    *error = u"User script must be UTF8 encoded.";
    return nullptr;
  }

  UserScript script;
  if (!UserScriptLoader::ParseMetadataHeader(content, &script)) {
    *error = u"Invalid script header.";
    return nullptr;
  }

  base::FilePath install_temp_dir =
      file_util::GetInstallTempDir(extensions_dir);
  if (install_temp_dir.empty()) {
    *error = u"Could not get path to profile temporary directory.";
    return nullptr;
  }

  base::ScopedTempDir temp_dir;
  if (!temp_dir.CreateUniqueTempDirUnderPath(install_temp_dir)) {
    *error = u"Could not create temporary directory.";
    return nullptr;
  }

  // Create the manifest
  std::unique_ptr<base::DictionaryValue> root(new base::DictionaryValue);
  std::string script_name;
  if (!script.name().empty() && !script.name_space().empty())
    script_name = script.name_space() + "/" + script.name();
  else
    script_name = original_url.spec();

  // Create the public key.
  // User scripts are not signed, but the public key for an extension doubles as
  // its unique identity, and we need one of those. A user script's unique
  // identity is its namespace+name, so we hash that to create a public key.
  // There will be no corresponding private key, which means user scripts cannot
  // be auto-updated, or claimed in the gallery.
  char raw[crypto::kSHA256Length] = {0};
  std::string key;
  crypto::SHA256HashString(script_name, raw, crypto::kSHA256Length);
  base::Base64Encode(base::StringPiece(raw, crypto::kSHA256Length), &key);

  // The script may not have a name field, but we need one for an extension. If
  // it is missing, use the filename of the original URL.
  if (!script.name().empty())
    root->SetString(manifest_keys::kName, script.name());
  else
    root->SetString(manifest_keys::kName, original_url.ExtractFileName());

  // Not all scripts have a version, but we need one. Default to 1.0 if it is
  // missing.
  if (!script.version().empty())
    root->SetString(manifest_keys::kVersion, script.version());
  else
    root->SetString(manifest_keys::kVersion, "1.0");

  root->SetString(manifest_keys::kDescription, script.description());
  root->SetString(manifest_keys::kPublicKey, key);
  root->SetBoolean(manifest_keys::kConvertedFromUserScript, true);

  // If the script provides its own match patterns, we use those. Otherwise, we
  // generate some using the include globs.
  std::vector<std::string> matches;
  if (!script.url_patterns().is_empty()) {
    matches.reserve(script.url_patterns().size());
    for (const URLPattern& pattern : script.url_patterns())
      matches.push_back(pattern.GetAsString());
  } else {
    // TODO(aa): Derive tighter matches where possible.
    matches.push_back("http://*/*");
    matches.push_back("https://*/*");
  }

  // Read the exclude matches, if any are present.
  std::vector<std::string> exclude_matches;
  exclude_matches.reserve(script.exclude_url_patterns().size());
  for (const URLPattern& pattern : script.exclude_url_patterns())
    exclude_matches.push_back(pattern.GetAsString());

  ContentScript content_script;
  content_script.matches = std::move(matches);
  content_script.exclude_matches =
      std::make_unique<std::vector<std::string>>(std::move(exclude_matches));
  content_script.include_globs =
      std::make_unique<std::vector<std::string>>(script.globs());
  content_script.exclude_globs =
      std::make_unique<std::vector<std::string>>(script.exclude_globs());

  content_script.js = std::make_unique<std::vector<std::string>>();
  content_script.js->push_back("script.js");

  if (script.run_location() == mojom::RunLocation::kDocumentStart) {
    content_script.run_at = api::content_scripts::RUN_AT_DOCUMENT_START;
  } else if (script.run_location() == mojom::RunLocation::kDocumentEnd) {
    content_script.run_at = api::content_scripts::RUN_AT_DOCUMENT_END;
  } else if (script.run_location() == mojom::RunLocation::kDocumentIdle) {
    // This is the default, but store it just in case we change that.
    content_script.run_at = api::content_scripts::RUN_AT_DOCUMENT_IDLE;
  }

  base::Value content_scripts(base::Value::Type::LIST);
  content_scripts.Append(
      base::Value::FromUniquePtrValue(content_script.ToValue()));
  root->SetKey(api::content_scripts::ManifestKeys::kContentScripts,
               std::move(content_scripts));

  base::FilePath manifest_path = temp_dir.GetPath().Append(kManifestFilename);
  JSONFileValueSerializer serializer(manifest_path);
  if (!serializer.Serialize(*root)) {
    *error = u"Could not write JSON.";
    return nullptr;
  }

  // Write the script file.
  if (!base::CopyFile(user_script_path,
                      temp_dir.GetPath().AppendASCII("script.js"))) {
    *error = u"Could not copy script file.";
    return nullptr;
  }

  // TODO(rdevlin.cronin): Continue removing std::string errors and replacing
  // with std::u16string
  std::string utf8_error;
  scoped_refptr<Extension> extension =
      Extension::Create(temp_dir.GetPath(), mojom::ManifestLocation::kInternal,
                        *root, Extension::NO_FLAGS, &utf8_error);
  *error = base::UTF8ToUTF16(utf8_error);
  if (!extension.get()) {
    NOTREACHED() << "Could not init extension " << *error;
    return nullptr;
  }

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

}  // namespace extensions
