// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/sync/engine/commit_contribution_impl.h"

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

#include "base/feature_list.h"
#include "base/logging.h"
#include "base/uuid.h"
#include "components/sync/base/data_type_histogram.h"
#include "components/sync/base/passphrase_enums.h"
#include "components/sync/base/time.h"
#include "components/sync/base/unique_position.h"
#include "components/sync/engine/commit_and_get_updates_types.h"
#include "components/sync/engine/cycle/entity_change_metric_recording.h"
#include "components/sync/engine/sync_protocol_error.h"
#include "components/sync/protocol/entity_specifics.pb.h"
#include "components/sync/protocol/proto_value_conversions.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync/protocol/sync_entity.pb.h"

namespace syncer {

namespace {

// When enabled, all the fields for SyncEntity are populated for commit-only
// data types (otherwise, only `specifics` and `id_string` were populated).
BASE_FEATURE(kSyncPopulateAllFieldsForCommitOnlyTypes,
             base::FEATURE_ENABLED_BY_DEFAULT);

CommitResponseData BuildCommitResponseData(
    const CommitRequestData& commit_request,
    const sync_pb::CommitResponse_EntryResponse& entry_response) {
  CommitResponseData response_data;
  response_data.id = entry_response.id_string();
  response_data.response_version = entry_response.version();
  response_data.client_tag_hash = commit_request.entity->client_tag_hash;
  response_data.sequence_number = commit_request.sequence_number;
  response_data.specifics_hash = commit_request.specifics_hash;
  return response_data;
}

FailedCommitResponseData BuildFailedCommitResponseData(
    const CommitRequestData& commit_request,
    const sync_pb::CommitResponse_EntryResponse& entry_response) {
  FailedCommitResponseData response_data;
  response_data.client_tag_hash = commit_request.entity->client_tag_hash;
  response_data.response_type = entry_response.response_type();
  response_data.datatype_specific_error =
      entry_response.datatype_specific_error();
  return response_data;
}

}  // namespace

CommitContributionImpl::CommitContributionImpl(
    DataType type,
    const sync_pb::DataTypeContext& context,
    CommitRequestDataList commit_requests,
    base::OnceCallback<void(const CommitResponseDataList&,
                            const FailedCommitResponseDataList&)>
        on_commit_response_callback,
    base::OnceCallback<void(SyncCommitError)> on_full_commit_failure_callback,
    PassphraseType passphrase_type)
    : type_(type),
      on_commit_response_callback_(std::move(on_commit_response_callback)),
      on_full_commit_failure_callback_(
          std::move(on_full_commit_failure_callback)),
      passphrase_type_(passphrase_type),
      context_(context),
      commit_requests_(std::move(commit_requests)) {}

CommitContributionImpl::~CommitContributionImpl() = default;

void CommitContributionImpl::AddToCommitMessage(
    sync_pb::ClientToServerMessage* msg) {
  sync_pb::CommitMessage* commit_message = msg->mutable_commit();
  entries_start_index_ = commit_message->entries_size();

  commit_message->mutable_entries()->Reserve(commit_message->entries_size() +
                                             commit_requests_.size());

  for (const std::unique_ptr<CommitRequestData>& commit_request :
       commit_requests_) {
    sync_pb::SyncEntity* sync_entity = commit_message->add_entries();

    // Commit-only data types must never be encrypted or deleted.
    if (CommitOnlyTypes().Has(type_)) {
      CHECK(!commit_request->entity->specifics.has_encrypted());
      CHECK(!commit_request->entity->is_deleted());
    }

    if (CommitOnlyTypes().Has(type_) &&
        !base::FeatureList::IsEnabled(
            kSyncPopulateAllFieldsForCommitOnlyTypes)) {
      // Only send specifics to server for commit-only types.
      sync_entity->mutable_specifics()->CopyFrom(
          commit_request->entity->specifics);

      // Populate randomly-generated ID string similar to an uncommitted version
      // of normal data types.
      sync_entity->set_id_string(
          base::Uuid::GenerateRandomV4().AsLowercaseString());
    } else {
      PopulateCommitProto(type_, *commit_request, sync_entity);
      AdjustCommitProto(sync_entity);
    }

    // Purposefully crash if we have client only data, as this could result in
    // sending password in plain text.
    CHECK(
        !sync_entity->specifics().password().has_client_only_encrypted_data());
    CHECK(!sync_entity->specifics()
               .outgoing_password_sharing_invitation()
               .has_client_only_unencrypted_data());
    CHECK(!sync_entity->specifics()
               .incoming_password_sharing_invitation()
               .has_client_only_unencrypted_data());

    // Purposefully crash since no metadata should be uploaded if a custom
    // passphrase is set.
    CHECK(!IsExplicitPassphrase(passphrase_type_) ||
          !sync_entity->specifics().password().has_unencrypted_metadata());

    // Record the size of the sync entity being committed.
    syncer::SyncRecordDataTypeEntitySizeHistogram(
        type_, commit_request->entity->is_deleted(),
        sync_entity->specifics().ByteSizeLong(), sync_entity->ByteSizeLong());

    if (commit_request->entity->is_deleted()) {
      RecordEntityChangeMetrics(type_, DataTypeEntityChange::kLocalDeletion);
    } else if (commit_request->base_version <= 0) {
      RecordEntityChangeMetrics(type_, DataTypeEntityChange::kLocalCreation);
    } else {
      RecordEntityChangeMetrics(type_, DataTypeEntityChange::kLocalUpdate);
    }
  }

  if (!context_.context().empty()) {
    commit_message->add_client_contexts()->CopyFrom(context_);
  }
}

SyncerError CommitContributionImpl::ProcessCommitResponse(
    const sync_pb::ClientToServerResponse& response,
    StatusController* status) {
  CommitResponseDataList success_response_list;
  FailedCommitResponseDataList error_response_list;
  bool has_invalid_messages = false;
  bool has_conflicting_commits = false;
  bool has_transient_error_commits = false;

  for (size_t i = 0; i < commit_requests_.size(); ++i) {
    // Fill `success_response_list` or `error_response_list`.
    const sync_pb::CommitResponse_EntryResponse& entry_response =
        response.commit().entryresponse(entries_start_index_ + i);
    if (entry_response.response_type() == sync_pb::CommitResponse::SUCCESS) {
      success_response_list.push_back(
          BuildCommitResponseData(*commit_requests_[i], entry_response));
    } else {
      error_response_list.push_back(
          BuildFailedCommitResponseData(*commit_requests_[i], entry_response));
    }

    // Update `status` and mark the presence of specific errors (e.g.
    // conflicting commits).
    switch (entry_response.response_type()) {
      case sync_pb::CommitResponse::SUCCESS:
        status->increment_num_successful_commits();
        if (type_ == BOOKMARKS) {
          status->increment_num_successful_bookmark_commits();
        }
        break;
      case sync_pb::CommitResponse::INVALID_MESSAGE:
        DLOG(ERROR) << "Server reports commit message is invalid.";
        has_invalid_messages = true;
        break;
      case sync_pb::CommitResponse::CONFLICT:
        DVLOG(1) << "Server reports conflict for commit message.";
        status->increment_num_server_conflicts();
        has_conflicting_commits = true;
        break;
      case sync_pb::CommitResponse::OVER_QUOTA:
      case sync_pb::CommitResponse::RETRY:
      case sync_pb::CommitResponse::TRANSIENT_ERROR:
        DLOG(WARNING) << "Entity commit blocked by transient error.";
        has_transient_error_commits = true;
        break;
    }
  }

  // Send whatever successful and failed responses we did get back to our
  // parent. It's the schedulers job to handle the failures, but parent may
  // react to them as well.
  std::move(on_commit_response_callback_)
      .Run(success_response_list, error_response_list);

  // Commit was successfully processed. We do not want to call both
  // `on_commit_response_callback_` and `on_full_commit_failure_callback_`.
  on_full_commit_failure_callback_.Reset();

  // Let the scheduler know about the failures.
  if (has_invalid_messages) {
    return SyncerError::ProtocolError(SyncProtocolErrorType::INVALID_MESSAGE);
  }
  if (has_transient_error_commits) {
    return SyncerError::ProtocolError(SyncProtocolErrorType::TRANSIENT_ERROR);
  }
  if (has_conflicting_commits) {
    return SyncerError::ProtocolError(SyncProtocolErrorType::CONFLICT);
  }
  return SyncerError::Success();
}

void CommitContributionImpl::ProcessCommitFailure(
    SyncCommitError commit_error) {
  std::move(on_full_commit_failure_callback_).Run(commit_error);
  on_commit_response_callback_.Reset();
}

size_t CommitContributionImpl::GetNumEntries() const {
  return commit_requests_.size();
}

// static
void CommitContributionImpl::PopulateCommitProto(
    DataType type,
    const CommitRequestData& commit_entity,
    sync_pb::SyncEntity* commit_proto) {
  const EntityData& entity_data = *commit_entity.entity;

  commit_proto->set_id_string(entity_data.id);

  if (type == NIGORI) {
    // Client tags are irrelevant for NIGORI since it uses the root node. For
    // historical reasons (although it's unclear if this continues to be
    // needed), the root node is considered a folder.
    commit_proto->set_folder(true);
  } else if (type != BOOKMARKS ||
             !entity_data.client_tag_hash.value().empty()) {
    // The client tag is mandatory for all datatypes except bookmarks, and
    // for bookmarks it depends on the version of the browser that was used
    // to originally create the bookmark.
    commit_proto->set_client_tag_hash(entity_data.client_tag_hash.value());
  }

  commit_proto->set_version(commit_entity.base_version);
  commit_proto->set_deleted(entity_data.is_deleted());
  commit_proto->set_name(entity_data.name);
  commit_proto->set_mtime(TimeToProtoTime(entity_data.modification_time));
  if (entity_data.collaboration_metadata.has_value()) {
    // Only the collaboration ID is needed for the commit. Other fields are
    // populated by the server.
    commit_proto->mutable_collaboration()->set_collaboration_id(
        entity_data.collaboration_metadata->collaboration_id().value());
  }

  if (entity_data.is_deleted()) {
    if (entity_data.deletion_origin.has_value()) {
      *commit_proto->mutable_deletion_origin() = *entity_data.deletion_origin;
    }
  } else {
    // Handle bookmarks separately.
    if (type == BOOKMARKS) {
      // Populate SyncEntity.folder for backward-compatibility.
      commit_proto->set_folder(commit_entity.deprecated_bookmark_folder);
      CHECK(commit_entity.deprecated_bookmark_unique_position.IsValid());
      *commit_proto->mutable_unique_position() =
          commit_entity.deprecated_bookmark_unique_position.ToProto();

      // parent_id field is set only for legacy clients only, before M99.
      if (!entity_data.legacy_parent_id.empty()) {
        commit_proto->set_parent_id_string(entity_data.legacy_parent_id);
      }
    }
    commit_proto->set_ctime(TimeToProtoTime(entity_data.creation_time));
    commit_proto->mutable_specifics()->CopyFrom(entity_data.specifics);
  }
}

void CommitContributionImpl::AdjustCommitProto(
    sync_pb::SyncEntity* commit_proto) {
  if (commit_proto->version() == kUncommittedVersion) {
    commit_proto->set_version(0);
    // Initial commits need our help to generate a client ID if they don't have
    // any. Bookmarks create their own IDs on the frontend side to be able to
    // match them after commits. For other data types we generate one here. And
    // since bookmarks don't have client tags, their server id should be stable
    // across restarts in case of recommitting an item, it doesn't result in
    // creating a duplicate.
    if (commit_proto->id_string().empty()) {
      commit_proto->set_id_string(
          base::Uuid::GenerateRandomV4().AsLowercaseString());
    }
  }

  // See crbug.com/915133: Certain versions of Chrome (e.g. M71) handle corrupt
  // SESSIONS data poorly. Let's guard against future versions from committing
  // problematic data that could cause crashes on other syncing devices.
  if (commit_proto->specifics().session().has_tab()) {
    CHECK_GE(commit_proto->specifics().session().tab_node_id(), 0);
  }

  // Always include enough specifics to identify the type. Do this even in
  // deletion requests, where the specifics are otherwise invalid.
  AddDefaultFieldValue(type_, commit_proto->mutable_specifics());
}

}  // namespace syncer
