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

#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/convert_web_app.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/common/extensions/manifest_handlers/app_icon_color_info.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/extensions/manifest_handlers/app_theme_color_info.h"
#include "chrome/common/extensions/manifest_handlers/linked_app_icons.h"
#include "components/crx_file/id_util.h"
#include "components/sync/model/sync_data.h"
#include "components/sync/protocol/app_specifics.pb.h"
#include "components/sync/protocol/extension_specifics.pb.h"
#include "components/sync/protocol/sync.pb.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_url_handlers.h"

using syncer::StringOrdinal;

namespace extensions {

namespace {

std::string GetExtensionSpecificsLogMessage(
    const sync_pb::ExtensionSpecifics& specifics) {
  return base::StringPrintf(
      "id: %s\nversion: %s\nupdate_url: %s\nenabled: %i\ndisable_reasons: %i",
      specifics.id().c_str(),
      specifics.version().c_str(),
      specifics.update_url().c_str(),
      specifics.enabled(),
      specifics.disable_reasons());
}

enum BadSyncDataReason {
  // Invalid extension ID.
  BAD_EXTENSION_ID,

  // Invalid version.
  BAD_VERSION,

  // Invalid update URL.
  BAD_UPDATE_URL,

  // No ExtensionSpecifics in the EntitySpecifics.
  NO_EXTENSION_SPECIFICS,

  // Not used anymore; still here because of UMA.
  DEPRECATED_BAD_DISABLE_REASONS,

  // Must be at the end.
  NUM_BAD_SYNC_DATA_REASONS
};

void RecordBadSyncData(BadSyncDataReason reason) {
  UMA_HISTOGRAM_ENUMERATION("Extensions.BadSyncDataReason", reason,
                            NUM_BAD_SYNC_DATA_REASONS);
}

}  // namespace

ExtensionSyncData::LinkedAppIconInfo::LinkedAppIconInfo() {
}

ExtensionSyncData::LinkedAppIconInfo::~LinkedAppIconInfo() {
}

ExtensionSyncData::ExtensionSyncData()
    : is_app_(false),
      uninstalled_(false),
      enabled_(false),
      supports_disable_reasons_(false),
      disable_reasons_(disable_reason::DISABLE_NONE),
      incognito_enabled_(false),
      remote_install_(false),
      installed_by_custodian_(false),
      launch_type_(LAUNCH_TYPE_INVALID) {}

ExtensionSyncData::ExtensionSyncData(const Extension& extension,
                                     bool enabled,
                                     int disable_reasons,
                                     bool incognito_enabled,
                                     bool remote_install,
                                     bool installed_by_custodian)
    : ExtensionSyncData(extension,
                        enabled,
                        disable_reasons,
                        incognito_enabled,
                        remote_install,
                        installed_by_custodian,
                        StringOrdinal(),
                        StringOrdinal(),
                        LAUNCH_TYPE_INVALID) {}

ExtensionSyncData::ExtensionSyncData(const Extension& extension,
                                     bool enabled,
                                     int disable_reasons,
                                     bool incognito_enabled,
                                     bool remote_install,
                                     bool installed_by_custodian,
                                     const StringOrdinal& app_launch_ordinal,
                                     const StringOrdinal& page_ordinal,
                                     extensions::LaunchType launch_type)
    : is_app_(extension.is_app()),
      id_(extension.id()),
      uninstalled_(false),
      enabled_(enabled),
      supports_disable_reasons_(true),
      disable_reasons_(disable_reasons),
      incognito_enabled_(incognito_enabled),
      remote_install_(remote_install),
      installed_by_custodian_(installed_by_custodian),
      version_(extension.from_bookmark() ? base::Version("0")
                                         : extension.version()),
      update_url_(ManifestURL::GetUpdateURL(&extension)),
      name_(extension.non_localized_name()),
      app_launch_ordinal_(app_launch_ordinal),
      page_ordinal_(page_ordinal),
      launch_type_(launch_type) {
  if (is_app_ && extension.from_bookmark()) {
    bookmark_app_description_ = extension.description();
    bookmark_app_url_ = AppLaunchInfo::GetLaunchWebURL(&extension).spec();
    bookmark_app_scope_ = GetScopeURLFromBookmarkApp(&extension).spec();
    bookmark_app_icon_color_ = AppIconColorInfo::GetIconColorString(&extension);
    bookmark_app_theme_color_ = AppThemeColorInfo::GetThemeColor(&extension);
    extensions::LinkedAppIcons icons =
        LinkedAppIcons::GetLinkedAppIcons(&extension);
    for (const auto& icon : icons.icons) {
      LinkedAppIconInfo linked_icon;
      linked_icon.url = icon.url;
      linked_icon.size = icon.size;
      linked_icons_.push_back(linked_icon);
    }
  }
}

ExtensionSyncData::ExtensionSyncData(const ExtensionSyncData& other) = default;

ExtensionSyncData::~ExtensionSyncData() {}

// static
std::unique_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncData(
    const syncer::SyncData& sync_data) {
  std::unique_ptr<ExtensionSyncData> data(new ExtensionSyncData);
  if (data->PopulateFromSyncData(sync_data))
    return data;
  return nullptr;
}

// static
std::unique_ptr<ExtensionSyncData> ExtensionSyncData::CreateFromSyncChange(
    const syncer::SyncChange& sync_change) {
  std::unique_ptr<ExtensionSyncData> data(
      CreateFromSyncData(sync_change.sync_data()));
  if (!data.get())
    return nullptr;

  if (sync_change.change_type() == syncer::SyncChange::ACTION_DELETE)
    data->uninstalled_ = true;
  return data;
}

syncer::SyncData ExtensionSyncData::GetSyncData() const {
  sync_pb::EntitySpecifics specifics;
  if (is_app_)
    ToAppSpecifics(specifics.mutable_app());
  else
    ToExtensionSpecifics(specifics.mutable_extension());

  return syncer::SyncData::CreateLocalData(id_, name_, specifics);
}

syncer::SyncChange ExtensionSyncData::GetSyncChange(
    syncer::SyncChange::SyncChangeType change_type) const {
  return syncer::SyncChange(FROM_HERE, change_type, GetSyncData());
}

void ExtensionSyncData::ToExtensionSpecifics(
    sync_pb::ExtensionSpecifics* specifics) const {
  DCHECK(crx_file::id_util::IdIsValid(id_));
  specifics->set_id(id_);
  specifics->set_update_url(update_url_.spec());
  specifics->set_version(version_.GetString());
  specifics->set_enabled(enabled_);
  if (supports_disable_reasons_)
    specifics->set_disable_reasons(disable_reasons_);
  specifics->set_incognito_enabled(incognito_enabled_);
  specifics->set_remote_install(remote_install_);
  specifics->set_installed_by_custodian(installed_by_custodian_);
  specifics->set_name(name_);
}

void ExtensionSyncData::ToAppSpecifics(sync_pb::AppSpecifics* specifics) const {
  DCHECK(specifics);
  // Only sync the ordinal values and launch type if they are valid.
  if (app_launch_ordinal_.IsValid())
    specifics->set_app_launch_ordinal(app_launch_ordinal_.ToInternalValue());
  if (page_ordinal_.IsValid())
    specifics->set_page_ordinal(page_ordinal_.ToInternalValue());

  sync_pb::AppSpecifics::LaunchType sync_launch_type =
      static_cast<sync_pb::AppSpecifics::LaunchType>(launch_type_);

  // The corresponding validation of this value during processing of an
  // ExtensionSyncData is in ExtensionSyncService::ApplySyncData.
  if (launch_type_ >= LAUNCH_TYPE_FIRST && launch_type_ < NUM_LAUNCH_TYPES &&
      sync_pb::AppSpecifics_LaunchType_IsValid(sync_launch_type)) {
    specifics->set_launch_type(sync_launch_type);
  }

  if (!bookmark_app_url_.empty())
    specifics->set_bookmark_app_url(bookmark_app_url_);

  if (!bookmark_app_description_.empty())
    specifics->set_bookmark_app_description(bookmark_app_description_);

  if (!bookmark_app_scope_.empty())
    specifics->set_bookmark_app_scope(bookmark_app_scope_);

  if (!bookmark_app_icon_color_.empty())
    specifics->set_bookmark_app_icon_color(bookmark_app_icon_color_);

  if (bookmark_app_theme_color_)
    specifics->set_bookmark_app_theme_color(bookmark_app_theme_color_.value());

  for (const auto& linked_icon : linked_icons_) {
    sync_pb::LinkedAppIconInfo* linked_app_icon_info =
        specifics->add_linked_app_icons();
    DCHECK(linked_icon.url.is_valid());
    linked_app_icon_info->set_url(linked_icon.url.spec());
    linked_app_icon_info->set_size(linked_icon.size);
  }

  ToExtensionSpecifics(specifics->mutable_extension());
}

bool ExtensionSyncData::PopulateFromExtensionSpecifics(
    const sync_pb::ExtensionSpecifics& specifics) {
  if (!crx_file::id_util::IdIsValid(specifics.id())) {
    LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad ID):\n"
               << GetExtensionSpecificsLogMessage(specifics);
    RecordBadSyncData(BAD_EXTENSION_ID);
    return false;
  }

  base::Version specifics_version(specifics.version());
  if (!specifics_version.IsValid()) {
    LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad version):\n"
               << GetExtensionSpecificsLogMessage(specifics);
    RecordBadSyncData(BAD_VERSION);
    return false;
  }

  // The update URL must be either empty or valid.
  GURL specifics_update_url(specifics.update_url());
  if (!specifics_update_url.is_empty() && !specifics_update_url.is_valid()) {
    LOG(ERROR) << "Attempt to sync bad ExtensionSpecifics (bad update URL):\n"
               << GetExtensionSpecificsLogMessage(specifics);
    RecordBadSyncData(BAD_UPDATE_URL);
    return false;
  }

  id_ = specifics.id();
  update_url_ = specifics_update_url;
  version_ = specifics_version;
  enabled_ = specifics.enabled();
  supports_disable_reasons_ = specifics.has_disable_reasons();
  disable_reasons_ = specifics.disable_reasons();
  incognito_enabled_ = specifics.incognito_enabled();
  remote_install_ = specifics.remote_install();
  installed_by_custodian_ = specifics.installed_by_custodian();
  name_ = specifics.name();
  return true;
}

bool ExtensionSyncData::PopulateFromAppSpecifics(
    const sync_pb::AppSpecifics& specifics) {
  if (!PopulateFromExtensionSpecifics(specifics.extension()))
    return false;

  is_app_ = true;

  app_launch_ordinal_ = syncer::StringOrdinal(specifics.app_launch_ordinal());
  page_ordinal_ = syncer::StringOrdinal(specifics.page_ordinal());

  launch_type_ = specifics.has_launch_type()
      ? static_cast<extensions::LaunchType>(specifics.launch_type())
      : LAUNCH_TYPE_INVALID;

  bookmark_app_url_ = specifics.bookmark_app_url();
  bookmark_app_description_ = specifics.bookmark_app_description();
  bookmark_app_scope_ = specifics.bookmark_app_scope();
  bookmark_app_icon_color_ = specifics.bookmark_app_icon_color();
  if (specifics.has_bookmark_app_theme_color())
    bookmark_app_theme_color_ = specifics.bookmark_app_theme_color();

  for (int i = 0; i < specifics.linked_app_icons_size(); ++i) {
    const sync_pb::LinkedAppIconInfo& linked_app_icon_info =
        specifics.linked_app_icons(i);
    if (linked_app_icon_info.has_url() && linked_app_icon_info.has_size()) {
      LinkedAppIconInfo linked_icon;
      linked_icon.url = GURL(linked_app_icon_info.url());
      linked_icon.size = linked_app_icon_info.size();
      linked_icons_.push_back(linked_icon);
    }
  }

  return true;
}

bool ExtensionSyncData::PopulateFromSyncData(
    const syncer::SyncData& sync_data) {
  const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics();

  if (entity_specifics.has_app())
    return PopulateFromAppSpecifics(entity_specifics.app());

  if (entity_specifics.has_extension())
    return PopulateFromExtensionSpecifics(entity_specifics.extension());

  LOG(ERROR) << "Attempt to sync bad EntitySpecifics: no extension data.";
  RecordBadSyncData(NO_EXTENSION_SPECIFICS);
  return false;
}

}  // namespace extensions
