// 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 "components/sync/syncable/write_node.h"

#include <memory>

#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/sync/base/cryptographer.h"
#include "components/sync/base/hash_util.h"
#include "components/sync/base/sync_features.h"
#include "components/sync/engine/engine_util.h"
#include "components/sync/protocol/bookmark_specifics.pb.h"
#include "components/sync/protocol/typed_url_specifics.pb.h"
#include "components/sync/syncable/base_transaction.h"
#include "components/sync/syncable/mutable_entry.h"
#include "components/sync/syncable/nigori_util.h"
#include "components/sync/syncable/write_transaction.h"

using std::string;
using std::vector;

namespace syncer {

using syncable::kEncryptedString;
using syncable::SPECIFICS;

static const char kDefaultNameForNewNodes[] = " ";

void WriteNode::SetIsFolder(bool folder) {
  if (entry_->GetIsDir() == folder)
    return;  // Skip redundant changes.

  entry_->PutIsDir(folder);
  MarkForSyncing();
}

void WriteNode::SetTitle(const std::string& title) {
  DCHECK_NE(GetModelType(), UNSPECIFIED);
  ModelType type = GetModelType();
  // It's possible the nigori lost the set of encrypted types. If the current
  // specifics are already encrypted, we want to ensure we continue encrypting.
  bool needs_encryption = GetTransaction()->GetEncryptedTypes().Has(type) ||
                          entry_->GetSpecifics().has_encrypted();

  // If this datatype is encrypted and is not a bookmark, we disregard the
  // specified title in favor of kEncryptedString. For encrypted bookmarks the
  // NON_UNIQUE_NAME will still be kEncryptedString, but we store the real title
  // into the specifics. All strings compared are server legal strings.
  std::string new_legal_title;
  if (type != BOOKMARKS && needs_encryption) {
    new_legal_title = kEncryptedString;
  } else {
    DCHECK(base::IsStringUTF8(title));
    SyncAPINameToServerName(title, &new_legal_title);
    base::TruncateUTF8ToByteSize(new_legal_title, 255, &new_legal_title);
  }

  std::string current_legal_title;
  if (BOOKMARKS == type && entry_->GetSpecifics().has_encrypted()) {
    // Encrypted bookmarks only have their title in the unencrypted specifics.
    current_legal_title = GetBookmarkSpecifics().title();
  } else {
    // Non-bookmarks and legacy bookmarks (those with no title in their
    // specifics) store their title in NON_UNIQUE_NAME. Non-legacy bookmarks
    // store their title in specifics as well as NON_UNIQUE_NAME.
    current_legal_title = entry_->GetNonUniqueName();
  }

  bool title_matches = (current_legal_title == new_legal_title);
  bool encrypted_without_overwriting_name =
      (needs_encryption && entry_->GetNonUniqueName() != kEncryptedString);

  // For bookmarks, we also set the title field in the specifics.
  // TODO(zea): refactor bookmarks to not need this functionality.
  sync_pb::EntitySpecifics specifics = GetEntitySpecifics();
  if (GetModelType() == BOOKMARKS &&
      specifics.bookmark().title() != new_legal_title) {
    specifics.mutable_bookmark()->set_title(new_legal_title);
    SetEntitySpecifics(specifics);  // Does it's own encryption checking.
    title_matches = false;
  }

  // If the title matches and the NON_UNIQUE_NAME is properly overwritten as
  // necessary, nothing needs to change.
  if (title_matches && !encrypted_without_overwriting_name) {
    DVLOG(2) << "Title matches, dropping change.";
    return;
  }

  // For bookmarks, this has to happen after we set the title in the specifics,
  // because the presence of a title in the NON_UNIQUE_NAME is what controls
  // the logic deciding whether this is an empty node or a legacy bookmark.
  // See BaseNode::GetUnencryptedSpecific(..).
  if (needs_encryption)
    entry_->PutNonUniqueName(kEncryptedString);
  else
    entry_->PutNonUniqueName(new_legal_title);

  DVLOG(1) << "Overwriting title of type " << ModelTypeToString(type)
           << " and marking for syncing.";
  MarkForSyncing();
}

void WriteNode::SetBookmarkSpecifics(
    const sync_pb::BookmarkSpecifics& new_value) {
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_bookmark()->CopyFrom(new_value);
  SetEntitySpecifics(entity_specifics);
}

void WriteNode::SetNigoriSpecifics(const sync_pb::NigoriSpecifics& new_value) {
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_nigori()->CopyFrom(new_value);
  SetEntitySpecifics(entity_specifics);
}

void WriteNode::SetPasswordSpecifics(
    const sync_pb::PasswordSpecificsData& data) {
  DCHECK_EQ(GetModelType(), PASSWORDS);

  Cryptographer* cryptographer = GetTransaction()->GetCryptographer();

  // We have to do the idempotency check here (vs in UpdateEntryWithEncryption)
  // because Passwords have their encrypted data within the PasswordSpecifics,
  // vs within the EntitySpecifics like all the other types.
  const sync_pb::EntitySpecifics& old_specifics = GetEntitySpecifics();
  sync_pb::EntitySpecifics entity_specifics;
  // Copy over the old specifics if they exist.
  if (GetModelTypeFromSpecifics(old_specifics) == PASSWORDS) {
    entity_specifics.CopyFrom(old_specifics);
  } else {
    AddDefaultFieldValue(PASSWORDS, &entity_specifics);
  }
  sync_pb::PasswordSpecifics* password_specifics =
      entity_specifics.mutable_password();

  const std::string metadata_url(data.signon_realm());
  if (!IsExplicitPassphrase(GetTransaction()->GetPassphraseType()) &&
      base::FeatureList::IsEnabled(kFillPasswordMetadata) &&
      password_specifics->unencrypted_metadata().url() != metadata_url) {
    password_specifics->mutable_unencrypted_metadata()->set_url(metadata_url);
  }

  // This will only update password_specifics if the underlying unencrypted blob
  // was different from |data| or was not encrypted with the proper passphrase.
  if (!cryptographer->Encrypt(data, password_specifics->mutable_encrypted())) {
    LOG(ERROR) << "Failed to encrypt password, possibly due to sync node "
               << "corruption";
    return;
  }
  SetEntitySpecifics(entity_specifics);
}

void WriteNode::SetEntitySpecifics(const sync_pb::EntitySpecifics& new_value) {
  ModelType new_specifics_type = GetModelTypeFromSpecifics(new_value);
  CHECK(!new_value.password().has_client_only_encrypted_data());
  DCHECK_NE(new_specifics_type, UNSPECIFIED);
  DVLOG(1) << "Writing entity specifics of type "
           << ModelTypeToString(new_specifics_type);
  DCHECK_EQ(new_specifics_type, GetModelType());

  // Preserve unknown fields.
  const sync_pb::EntitySpecifics& old_specifics = entry_->GetSpecifics();
  sync_pb::EntitySpecifics new_specifics;
  new_specifics.CopyFrom(new_value);
  new_specifics.mutable_unknown_fields()->append(
      old_specifics.unknown_fields());

  // Will update the entry if encryption was necessary.
  if (!UpdateEntryWithEncryption(GetTransaction()->GetWrappedTrans(),
                                 new_specifics, entry_)) {
    return;
  }
  if (entry_->GetSpecifics().has_encrypted()) {
    // EncryptIfNecessary already updated the entry for us and marked for
    // syncing if it was needed. Now we just make a copy of the unencrypted
    // specifics so that if this node is updated, we do not have to decrypt the
    // old data. Note that this only modifies the node's local data, not the
    // entry itself.
    SetUnencryptedSpecifics(new_value);
  }

  DCHECK_EQ(new_specifics_type, GetModelType());
}

void WriteNode::ResetFromSpecifics() {
  SetEntitySpecifics(GetEntitySpecifics());
}

void WriteNode::SetTypedUrlSpecifics(
    const sync_pb::TypedUrlSpecifics& new_value) {
  sync_pb::EntitySpecifics entity_specifics;
  entity_specifics.mutable_typed_url()->CopyFrom(new_value);
  SetEntitySpecifics(entity_specifics);
}

void WriteNode::SetExternalId(int64_t id) {
  if (GetExternalId() != id)
    entry_->PutLocalExternalId(id);
}

WriteNode::WriteNode(WriteTransaction* transaction)
    : entry_(nullptr), transaction_(transaction) {
  DCHECK(transaction);
}

WriteNode::~WriteNode() {
  delete entry_;
}

// Find an existing node matching the ID |id|, and bind this WriteNode to it.
// Return true on success.
BaseNode::InitByLookupResult WriteNode::InitByIdLookup(int64_t id) {
  DCHECK(!entry_) << "Init called twice";
  DCHECK_NE(id, kInvalidId);
  entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
                                      syncable::GET_BY_HANDLE, id);
  if (!entry_->good())
    return INIT_FAILED_ENTRY_NOT_GOOD;
  if (entry_->GetIsDel())
    return INIT_FAILED_ENTRY_IS_DEL;
  return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY;
}

// Find a node by client tag, and bind this WriteNode to it.
// Return true if the write node was found, and was not deleted.
// Undeleting a deleted node is possible by ClientTag.
BaseNode::InitByLookupResult WriteNode::InitByClientTagLookup(
    ModelType model_type,
    const std::string& tag) {
  DCHECK(!entry_) << "Init called twice";
  if (tag.empty())
    return INIT_FAILED_PRECONDITION;

  const std::string hash = GenerateSyncableHash(model_type, tag);

  entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
                                      syncable::GET_BY_CLIENT_TAG, hash);
  if (!entry_->good())
    return INIT_FAILED_ENTRY_NOT_GOOD;
  if (entry_->GetIsDel())
    return INIT_FAILED_ENTRY_IS_DEL;
  return DecryptIfNecessary() ? INIT_OK : INIT_FAILED_DECRYPT_IF_NECESSARY;
}

BaseNode::InitByLookupResult WriteNode::InitTypeRoot(ModelType type) {
  DCHECK(!entry_) << "Init called twice";
  if (!IsRealDataType(type))
    return INIT_FAILED_PRECONDITION;
  entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
                                      syncable::GET_TYPE_ROOT, type);
  if (!entry_->good())
    return INIT_FAILED_ENTRY_NOT_GOOD;
  if (entry_->GetIsDel())
    return INIT_FAILED_ENTRY_IS_DEL;
  ModelType model_type = GetModelType();
  DCHECK_EQ(model_type, NIGORI);
  return INIT_OK;
}

// Create a new node with default properties, and bind this WriteNode to it.
// Return true on success.
bool WriteNode::InitBookmarkByCreation(const BaseNode& parent,
                                       const BaseNode* predecessor) {
  DCHECK(!entry_) << "Init called twice";
  // |predecessor| must be a child of |parent| or null.
  if (predecessor && predecessor->GetParentId() != parent.GetId()) {
    DCHECK(false);
    return false;
  }

  syncable::Id parent_id = parent.GetSyncId();
  DCHECK(!parent_id.IsNull());

  // Start out with a dummy name.  We expect
  // the caller to set a meaningful name after creation.
  string dummy(kDefaultNameForNewNodes);

  entry_ =
      new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
                                 syncable::CREATE, BOOKMARKS, parent_id, dummy);

  if (!entry_->good())
    return false;

  // Entries are untitled folders by default.
  entry_->PutIsDir(true);

  if (!PutPredecessor(predecessor)) {
    return false;
  }

  // Mark this entry as unsynced, to wake up the syncer.
  MarkForSyncing();
  return true;
}

WriteNode::InitUniqueByCreationResult WriteNode::InitUniqueByCreation(
    ModelType model_type,
    const BaseNode& parent,
    const std::string& tag) {
  return InitUniqueByCreationImpl(model_type, parent.GetSyncId(), tag);
}

WriteNode::InitUniqueByCreationResult WriteNode::InitUniqueByCreation(
    ModelType model_type,
    const std::string& tag) {
  return InitUniqueByCreationImpl(model_type, syncable::Id(), tag);
}

// Create a new node with default properties and a client defined unique tag,
// and bind this WriteNode to it.
// Return true on success. If the tag exists in the database, then
// we will attempt to undelete the node.
WriteNode::InitUniqueByCreationResult WriteNode::InitUniqueByCreationImpl(
    ModelType model_type,
    const syncable::Id& parent_id,
    const std::string& tag) {
  // This DCHECK will only fail if init is called twice.
  DCHECK(!entry_);
  if (tag.empty()) {
    LOG(WARNING) << "InitUniqueByCreation failed due to empty tag.";
    return INIT_FAILED_EMPTY_TAG;
  }

  const std::string hash = GenerateSyncableHash(model_type, tag);

  // Start out with a dummy name.  We expect
  // the caller to set a meaningful name after creation.
  string dummy(kDefaultNameForNewNodes);

  // Check if we have this locally and need to undelete it.
  std::unique_ptr<syncable::MutableEntry> existing_entry(
      new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
                                 syncable::GET_BY_CLIENT_TAG, hash));

  if (existing_entry->good()) {
    bool entry_undeleted = false;
    if (existing_entry->GetIsDel()) {
      // Rules for undelete:
      // BASE_VERSION: Must keep the same.
      // ID: Essential to keep the same.
      // META_HANDLE: Must be the same, so we can't "split" the entry.
      // IS_DEL: Must be set to false, will cause reindexing.
      //         This one is weird because IS_DEL is true for "update only"
      //         items. It should be OK to undelete an update only.
      // MTIME/CTIME: Seems reasonable to just leave them alone.
      // IS_UNSYNCED: Must set this to true or face database insurrection.
      //              We do this below this block.
      // IS_UNAPPLIED_UPDATE: Either keep it the same or also set BASE_VERSION
      //                      to SERVER_VERSION. We keep it the same here.
      // IS_DIR: We'll leave it the same.
      // SPECIFICS: Reset it.

      // Put specifics to define the entry's model type to handle the case
      // where this is not actually an undeletion, but instead a collision
      // with a newly downloaded, processed, and unapplied server update.
      // This should be done first before inserting the entry into the
      // directory's ParentChildIndex by clearing its "deleted" flag below.
      // This is a fix for http://crbug.com/505761.
      sync_pb::EntitySpecifics specifics;
      AddDefaultFieldValue(model_type, &specifics);
      existing_entry->PutSpecifics(specifics);

      existing_entry->PutIsDel(false);

      // Client tags are immutable and must be paired with the ID.
      // If a server update comes down with an ID and client tag combo,
      // and it already exists, always overwrite it and store only one copy.
      // We have to undelete entries because we can't disassociate IDs from
      // tags and updates.

      existing_entry->PutNonUniqueName(dummy);
      existing_entry->PutParentId(parent_id);
      entry_undeleted = true;
    }  // Else just reuse the existing entry.
    entry_ = existing_entry.release();
    // If entry is undeleted, its specifics are reset to default, unencrypted
    // value, and therefore no decryption is necessary. Moreover trying to
    // decrypt the password entry will fail because passwords are expected to be
    // encrypted.
    if (!entry_undeleted && !DecryptIfNecessary())
      return INIT_FAILED_DECRYPT_EXISTING_ENTRY;
  } else {
    entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(),
                                        syncable::CREATE, model_type, parent_id,
                                        dummy);
  }

  if (!entry_->good())
    return INIT_FAILED_COULD_NOT_CREATE_ENTRY;

  // Has no impact if the client tag is already set.
  entry_->PutUniqueClientTag(hash);

  // We don't support directory and tag combinations.
  entry_->PutIsDir(false);

  if (entry_->ShouldMaintainPosition()) {
    if (!entry_->PutPredecessor(syncable::Id()))
      return INIT_FAILED_SET_PREDECESSOR;
  }

  // Mark this entry as unsynced, to wake up the syncer.
  MarkForSyncing();

  return INIT_SUCCESS;
}

bool WriteNode::SetPosition(const BaseNode& new_parent,
                            const BaseNode* predecessor) {
  // |predecessor| must be a child of |new_parent| or null.
  if (predecessor && predecessor->GetParentId() != new_parent.GetId()) {
    DCHECK(false);
    return false;
  }

  syncable::Id new_parent_id = new_parent.GetSyncId();
  DCHECK(!new_parent_id.IsNull());

  // Filter out redundant changes if both the parent and the predecessor match.
  if (new_parent_id == entry_->GetParentId()) {
    const syncable::Id& old = entry_->GetPredecessorId();
    if ((!predecessor && old.IsNull()) ||
        (predecessor && (old == predecessor->GetSyncId()))) {
      return true;
    }
  }

  entry_->PutParentId(new_parent_id);

  if (!PutPredecessor(predecessor)) {
    return false;
  }

  // Mark this entry as unsynced, to wake up the syncer.
  MarkForSyncing();
  return true;
}

void WriteNode::SetAttachmentMetadata(
    const sync_pb::AttachmentMetadata& attachment_metadata) {
  entry_->PutAttachmentMetadata(attachment_metadata);
}

const syncable::Entry* WriteNode::GetEntry() const {
  return entry_;
}

const BaseTransaction* WriteNode::GetTransaction() const {
  return transaction_;
}

syncable::MutableEntry* WriteNode::GetMutableEntryForTest() {
  return entry_;
}

void WriteNode::Tombstone() {
  // These lines must be in this order.  The call to Put(IS_DEL) might choose to
  // unset the IS_UNSYNCED bit if the item was not known to the server at the
  // time of deletion.  It's important that the bit not be reset in that case.
  MarkForSyncing();
  entry_->PutIsDel(true);
}

void WriteNode::Drop() {
  if (entry_->GetId().ServerKnows()) {
    entry_->PutIsDel(true);
  }
}

bool WriteNode::PutPredecessor(const BaseNode* predecessor) {
  DCHECK(!entry_->GetParentId().IsNull());
  syncable::Id predecessor_id =
      predecessor ? predecessor->GetSyncId() : syncable::Id();
  return entry_->PutPredecessor(predecessor_id);
}

void WriteNode::MarkForSyncing() {
  syncable::MarkForSyncing(entry_);
}

}  // namespace syncer
