// 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 "extensions/common/manifest_url_handlers.h"

#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "extensions/strings/grit/extensions_strings.h"
#include "ui/base/l10n/l10n_util.h"

namespace extensions {

namespace keys = manifest_keys;
namespace errors = manifest_errors;

// static
const GURL& ManifestURL::Get(const Extension* extension,
                             const std::string& key) {
  ManifestURL* manifest_url =
      static_cast<ManifestURL*>(extension->GetManifestData(key));
  return manifest_url ? manifest_url->url_ : GURL::EmptyGURL();
}

// static
const GURL ManifestURL::GetHomepageURL(const Extension* extension) {
  const GURL& homepage_url = Get(extension, keys::kHomepageURL);
  if (homepage_url.is_valid())
    return homepage_url;
  bool use_webstore_url = UpdatesFromGallery(extension) &&
                          !SharedModuleInfo::IsSharedModule(extension);
  return use_webstore_url
             ? GURL(extension_urls::GetWebstoreItemDetailURLPrefix() +
                    extension->id())
             : GURL::EmptyGURL();
}

// static
bool ManifestURL::SpecifiedHomepageURL(const Extension* extension) {
  return Get(extension, keys::kHomepageURL).is_valid();
}

// static
const GURL& ManifestURL::GetUpdateURL(const Extension* extension) {
  return Get(extension, keys::kUpdateURL);
}

// static
bool ManifestURL::UpdatesFromGallery(const Extension* extension) {
  return extension_urls::IsWebstoreUpdateUrl(GetUpdateURL(extension));
}

// static
bool  ManifestURL::UpdatesFromGallery(const base::DictionaryValue* manifest) {
  std::string url;
  if (!manifest->GetString(keys::kUpdateURL, &url))
    return false;
  return extension_urls::IsWebstoreUpdateUrl(GURL(url));
}

// static
const GURL& ManifestURL::GetAboutPage(const Extension* extension) {
  return Get(extension, keys::kAboutPage);
}

// static
const GURL ManifestURL::GetDetailsURL(const Extension* extension) {
  return extension->from_webstore() ?
      GURL(extension_urls::GetWebstoreItemDetailURLPrefix() + extension->id()) :
      GURL::EmptyGURL();
}

HomepageURLHandler::HomepageURLHandler() {
}

HomepageURLHandler::~HomepageURLHandler() {
}

bool HomepageURLHandler::Parse(Extension* extension, base::string16* error) {
  scoped_ptr<ManifestURL> manifest_url(new ManifestURL);
  std::string homepage_url_str;
  if (!extension->manifest()->GetString(keys::kHomepageURL,
                                        &homepage_url_str)) {
    *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidHomepageURL,
                                                 std::string());
    return false;
  }
  manifest_url->url_ = GURL(homepage_url_str);
  if (!manifest_url->url_.is_valid() ||
      !manifest_url->url_.SchemeIsHTTPOrHTTPS()) {
    *error = ErrorUtils::FormatErrorMessageUTF16(
        errors::kInvalidHomepageURL, homepage_url_str);
    return false;
  }
  extension->SetManifestData(keys::kHomepageURL, manifest_url.release());
  return true;
}

const std::vector<std::string> HomepageURLHandler::Keys() const {
  return SingleKey(keys::kHomepageURL);
}

UpdateURLHandler::UpdateURLHandler() {
}

UpdateURLHandler::~UpdateURLHandler() {
}

bool UpdateURLHandler::Parse(Extension* extension, base::string16* error) {
  scoped_ptr<ManifestURL> manifest_url(new ManifestURL);
  std::string tmp_update_url;

  if (!extension->manifest()->GetString(keys::kUpdateURL, &tmp_update_url)) {
    *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidUpdateURL,
                                                 std::string());
    return false;
  }

  manifest_url->url_ = GURL(tmp_update_url);
  if (!manifest_url->url_.is_valid() ||
      manifest_url->url_.has_ref()) {
    *error = ErrorUtils::FormatErrorMessageUTF16(
        errors::kInvalidUpdateURL, tmp_update_url);
    return false;
  }

  extension->SetManifestData(keys::kUpdateURL, manifest_url.release());
  return true;
}

const std::vector<std::string> UpdateURLHandler::Keys() const {
  return SingleKey(keys::kUpdateURL);
}

AboutPageHandler::AboutPageHandler() {
}

AboutPageHandler::~AboutPageHandler() {
}

bool AboutPageHandler::Parse(Extension* extension, base::string16* error) {
  scoped_ptr<ManifestURL> manifest_url(new ManifestURL);
  std::string about_str;
  if (!extension->manifest()->GetString(keys::kAboutPage, &about_str)) {
    *error = base::ASCIIToUTF16(errors::kInvalidAboutPage);
    return false;
  }

  GURL absolute(about_str);
  if (absolute.is_valid()) {
    *error = base::ASCIIToUTF16(errors::kInvalidAboutPageExpectRelativePath);
    return false;
  }
  manifest_url->url_ = extension->GetResourceURL(about_str);
  if (!manifest_url->url_.is_valid()) {
    *error = base::ASCIIToUTF16(errors::kInvalidAboutPage);
    return false;
  }
  extension->SetManifestData(keys::kAboutPage, manifest_url.release());
  return true;
}

bool AboutPageHandler::Validate(const Extension* extension,
                                std::string* error,
                                std::vector<InstallWarning>* warnings) const {
  // Validate path to the options page.
  if (!extensions::ManifestURL::GetAboutPage(extension).is_empty()) {
    const base::FilePath about_path =
        extensions::file_util::ExtensionURLToRelativeFilePath(
            extensions::ManifestURL::GetAboutPage(extension));
    const base::FilePath path =
        extension->GetResource(about_path).GetFilePath();
    if (path.empty() || !base::PathExists(path)) {
      *error = l10n_util::GetStringFUTF8(IDS_EXTENSION_LOAD_ABOUT_PAGE_FAILED,
                                         about_path.LossyDisplayName());
      return false;
    }
  }
  return true;
}

const std::vector<std::string> AboutPageHandler::Keys() const {
  return SingleKey(keys::kAboutPage);
}

}  // namespace extensions
