// Copyright 2017 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_bookmarks/bookmark_model_type_processor.h"

#include <map>
#include <string>
#include <utility>

#include "base/callback_helpers.h"
#include "base/guid.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/test/test_bookmark_client.h"
#include "components/favicon/core/test/mock_favicon_service.h"
#include "components/sync/base/client_tag_hash.h"
#include "components/sync/base/unique_position.h"
#include "components/sync/engine/commit_queue.h"
#include "components/sync/model/data_type_activation_request.h"
#include "components/sync/model/type_entities_count.h"
#include "components/sync_bookmarks/switches.h"
#include "components/undo/bookmark_undo_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::ASCIIToUTF16;
using testing::_;
using testing::Eq;
using testing::IsNull;
using testing::NiceMock;
using testing::NotNull;

namespace sync_bookmarks {

namespace {

const char kBookmarkBarTag[] = "bookmark_bar";
const char kOtherBookmarksTag[] = "other_bookmarks";
const char kMobileBookmarksTag[] = "synced_bookmarks";
const char kBookmarkBarId[] = "bookmark_bar_id";
const char kOtherBookmarksId[] = "other_bookmarks_id";
const char kMobileBookmarksId[] = "mobile_bookmarks_id";
const char kBookmarksRootId[] = "root_id";
const char kCacheGuid[] = "generated_id";

struct BookmarkInfo {
  std::string server_id;
  std::string title;
  std::string url;  // empty for folders.
  std::string parent_id;
  std::string server_tag;
};

syncer::UpdateResponseData CreateUpdateResponseData(
    const BookmarkInfo& bookmark_info,
    const syncer::UniquePosition& unique_position,
    int response_version,
    const base::GUID& guid) {
  syncer::EntityData data;
  data.id = bookmark_info.server_id;
  data.parent_id = bookmark_info.parent_id;
  data.server_defined_unique_tag = bookmark_info.server_tag;
  data.unique_position = unique_position.ToProto();
  data.originator_client_item_id = guid.AsLowercaseString();

  sync_pb::BookmarkSpecifics* bookmark_specifics =
      data.specifics.mutable_bookmark();
  bookmark_specifics->set_guid(guid.AsLowercaseString());
  bookmark_specifics->set_legacy_canonicalized_title(bookmark_info.title);
  bookmark_specifics->set_full_title(bookmark_info.title);
  if (bookmark_info.url.empty()) {
    data.is_folder = true;
  } else {
    bookmark_specifics->set_url(bookmark_info.url);
  }

  syncer::UpdateResponseData response_data;
  response_data.entity = std::move(data);
  response_data.response_version = response_version;
  return response_data;
}

syncer::UpdateResponseData CreateUpdateResponseData(
    const BookmarkInfo& bookmark_info,
    const syncer::UniquePosition& unique_position,
    int response_version) {
  return CreateUpdateResponseData(bookmark_info, unique_position,
                                  response_version,
                                  base::GUID::GenerateRandomV4());
}

sync_pb::ModelTypeState CreateDummyModelTypeState() {
  sync_pb::ModelTypeState model_type_state;
  model_type_state.set_cache_guid(kCacheGuid);
  model_type_state.set_initial_sync_done(true);
  return model_type_state;
}

// |node| must not be nullptr.
sync_pb::BookmarkMetadata CreateNodeMetadata(
    const bookmarks::BookmarkNode* node,
    const std::string& server_id) {
  sync_pb::BookmarkMetadata bookmark_metadata;
  bookmark_metadata.set_id(node->id());
  bookmark_metadata.mutable_metadata()->set_server_id(server_id);
  bookmark_metadata.mutable_metadata()->set_client_tag_hash(
      syncer::ClientTagHash::FromUnhashed(syncer::BOOKMARKS,
                                          node->guid().AsLowercaseString())
          .value());
  return bookmark_metadata;
}

void AssertState(const BookmarkModelTypeProcessor* processor,
                 const std::vector<BookmarkInfo>& bookmarks) {
  const SyncedBookmarkTracker* tracker = processor->GetTrackerForTest();
  ASSERT_THAT(tracker, NotNull());

  // Make sure the tracker contains all bookmarks in |bookmarks| + the
  // 3 permanent nodes.
  ASSERT_THAT(tracker->TrackedEntitiesCountForTest(), Eq(bookmarks.size() + 3));

  for (BookmarkInfo bookmark : bookmarks) {
    const SyncedBookmarkTracker::Entity* entity =
        tracker->GetEntityForSyncId(bookmark.server_id);
    ASSERT_THAT(entity, NotNull());
    const bookmarks::BookmarkNode* node = entity->bookmark_node();
    ASSERT_THAT(node->GetTitle(), Eq(ASCIIToUTF16(bookmark.title)));
    ASSERT_THAT(node->url(), Eq(GURL(bookmark.url)));
    const SyncedBookmarkTracker::Entity* parent_entity =
        tracker->GetEntityForSyncId(bookmark.parent_id);
    ASSERT_THAT(node->parent(), Eq(parent_entity->bookmark_node()));
  }
}

// TODO(crbug.com/516866): Replace with a simpler implementation (e.g. by
// simulating loading from metadata) instead of receiving remote updates.
// Inititalizes the processor with the bookmarks in |bookmarks|.
void InitWithSyncedBookmarks(const std::vector<BookmarkInfo>& bookmarks,
                             BookmarkModelTypeProcessor* processor) {
  syncer::UpdateResponseDataList updates;
  syncer::UniquePosition pos = syncer::UniquePosition::InitialPosition(
      syncer::UniquePosition::RandomSuffix());
  // Add update for the permanent folders "Bookmarks bar", "Other Bookmarks" and
  // "Mobile Bookmarks".
  updates.push_back(
      CreateUpdateResponseData({kBookmarkBarId, std::string(), std::string(),
                                kBookmarksRootId, kBookmarkBarTag},
                               pos, /*response_version=*/0));
  updates.push_back(
      CreateUpdateResponseData({kOtherBookmarksId, std::string(), std::string(),
                                kBookmarksRootId, kOtherBookmarksTag},
                               pos, /*response_version=*/0));
  updates.push_back(CreateUpdateResponseData(
      {kMobileBookmarksId, std::string(), std::string(), kBookmarksRootId,
       kMobileBookmarksTag},
      pos, /*response_version=*/0));
  for (BookmarkInfo bookmark : bookmarks) {
    pos = syncer::UniquePosition::After(pos,
                                        syncer::UniquePosition::RandomSuffix());
    updates.push_back(
        CreateUpdateResponseData(bookmark, pos, /*response_version=*/0));
  }
  processor->OnUpdateReceived(CreateDummyModelTypeState(), std::move(updates));
  AssertState(processor, bookmarks);
}

class MockCommitQueue : public syncer::CommitQueue {
 public:
  MOCK_METHOD(void, NudgeForCommit, (), (override));
};

class ProxyCommitQueue : public syncer::CommitQueue {
 public:
  explicit ProxyCommitQueue(CommitQueue* commit_queue)
      : commit_queue_(commit_queue) {
    DCHECK(commit_queue_);
  }

  void NudgeForCommit() override { commit_queue_->NudgeForCommit(); }

 private:
  CommitQueue* commit_queue_ = nullptr;
};

class TestBookmarkClientWithFavicon : public bookmarks::TestBookmarkClient {
 public:
  // This method must be used to tell the bookmark_model about favicon.
  void SimulateFaviconLoaded(GURL page_url, gfx::Image image, GURL icon_url) {
    ASSERT_NE(0u, last_tasks_.count(page_url));
    SimulateFaviconLoaded(last_tasks_[page_url], std::move(image),
                          std::move(icon_url));
  }

  void SimulateFaviconLoaded(base::CancelableTaskTracker::TaskId task_id,
                             gfx::Image image,
                             GURL icon_url) {
    favicon_base::FaviconImageResult result;
    result.image = std::move(image);
    result.icon_url = std::move(icon_url);
    std::move(favicon_image_callbacks_[task_id]).Run(result);
  }

  size_t GetTasksCount() const { return favicon_image_callbacks_.size(); }

  // bookmarks::TestBookmarkClient implementation.
  base::CancelableTaskTracker::TaskId GetFaviconImageForPageURL(
      const GURL& page_url,
      favicon_base::FaviconImageCallback callback,
      base::CancelableTaskTracker* tracker) override {
    favicon_image_callbacks_[next_task_id_] = std::move(callback);
    last_tasks_[page_url] = next_task_id_;
    return next_task_id_++;
  }

 private:
  base::CancelableTaskTracker::TaskId next_task_id_ = 1;
  base::RepeatingCallback<void()> trigger_favicon_loaded_callback_;
  std::map<base::CancelableTaskTracker::TaskId,
           favicon_base::FaviconImageCallback>
      favicon_image_callbacks_;
  std::map<GURL, base::CancelableTaskTracker::TaskId> last_tasks_;
};

class BookmarkModelTypeProcessorTest : public testing::Test {
 public:
  BookmarkModelTypeProcessorTest()
      : processor_(std::make_unique<BookmarkModelTypeProcessor>(
            &bookmark_undo_service_)),
        bookmark_model_(bookmarks::TestBookmarkClient::CreateModelWithClient(
            std::make_unique<TestBookmarkClientWithFavicon>())) {
    // TODO(crbug.com/516866): This class assumes model is loaded and sync has
    // started before running tests. We should test other variations (i.e. model
    // isn't loaded yet and/or sync didn't start yet).
    processor_->SetFaviconService(&favicon_service_);
  }

  void SimulateModelReadyToSync() {
    processor_->ModelReadyToSync(
        /*metadata_str=*/std::string(), schedule_save_closure_.Get(),
        bookmark_model_.get());
  }

  void SimulateOnSyncStarting() {
    syncer::DataTypeActivationRequest request;
    request.cache_guid = kCacheGuid;
    processor_->OnSyncStarting(request, base::DoNothing());
  }

  void SimulateConnectSync() {
    processor_->ConnectSync(
        std::make_unique<ProxyCommitQueue>(&mock_commit_queue_));
  }

  // Simulate browser restart.
  void ResetModelTypeProcessor() {
    processor_ =
        std::make_unique<BookmarkModelTypeProcessor>(&bookmark_undo_service_);
    processor_->SetFaviconService(&favicon_service_);
  }

  void DestroyBookmarkModel() { bookmark_model_.reset(); }

  bookmarks::BookmarkModel* bookmark_model() { return bookmark_model_.get(); }
  TestBookmarkClientWithFavicon* bookmark_client() {
    return static_cast<TestBookmarkClientWithFavicon*>(
        bookmark_model_->client());
  }
  BookmarkUndoService* bookmark_undo_service() {
    return &bookmark_undo_service_;
  }
  favicon::FaviconService* favicon_service() { return &favicon_service_; }
  MockCommitQueue* mock_commit_queue() { return &mock_commit_queue_; }
  BookmarkModelTypeProcessor* processor() { return processor_.get(); }
  base::MockCallback<base::RepeatingClosure>* schedule_save_closure() {
    return &schedule_save_closure_;
  }

  sync_pb::BookmarkModelMetadata BuildBookmarkModelMetadataWithoutFullTitles() {
    sync_pb::BookmarkModelMetadata model_metadata =
        processor()->GetTrackerForTest()->BuildBookmarkModelMetadata();
    model_metadata.clear_bookmarks_full_title_reuploaded();
    return model_metadata;
  }

 private:
  base::test::TaskEnvironment task_environment_;
  NiceMock<base::MockCallback<base::RepeatingClosure>> schedule_save_closure_;
  BookmarkUndoService bookmark_undo_service_;
  NiceMock<favicon::MockFaviconService> favicon_service_;
  NiceMock<MockCommitQueue> mock_commit_queue_;
  std::unique_ptr<BookmarkModelTypeProcessor> processor_;
  std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_;
};

TEST_F(BookmarkModelTypeProcessorTest, ShouldDoInitialMerge) {
  const syncer::UniquePosition kRandomPosition =
      syncer::UniquePosition::InitialPosition(
          syncer::UniquePosition::RandomSuffix());

  SimulateModelReadyToSync();
  SimulateOnSyncStarting();

  syncer::UpdateResponseDataList updates;
  // Add update for the permanent folders.
  updates.push_back(
      CreateUpdateResponseData({kBookmarkBarId, std::string(), std::string(),
                                kBookmarksRootId, kBookmarkBarTag},
                               kRandomPosition, /*response_version=*/0));
  updates.push_back(
      CreateUpdateResponseData({kOtherBookmarksId, std::string(), std::string(),
                                kBookmarksRootId, kOtherBookmarksTag},
                               kRandomPosition, /*response_version=*/0));
  updates.push_back(CreateUpdateResponseData(
      {kMobileBookmarksId, std::string(), std::string(), kBookmarksRootId,
       kMobileBookmarksTag},
      kRandomPosition, /*response_version=*/0));

  ASSERT_THAT(processor()->GetTrackerForTest(), IsNull());

  base::HistogramTester histogram_tester;
  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));
  EXPECT_THAT(processor()->GetTrackerForTest(), NotNull());

  histogram_tester.ExpectUniqueSample(
      "Sync.ModelTypeInitialUpdateReceived",
      /*sample=*/syncer::ModelTypeHistogramValue(syncer::BOOKMARKS),
      /*expected_count=*/3);
}

TEST_F(BookmarkModelTypeProcessorTest, ShouldUpdateModelAfterRemoteCreation) {
  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  InitWithSyncedBookmarks(/*bookmarks=*/{}, processor());

  // Add update for another node under the bookmarks bar.
  const std::string kNodeId = "node_id";
  const std::string kTitle = "title";
  const std::string kUrl = "http://www.url.com";
  const syncer::UniquePosition kRandomPosition =
      syncer::UniquePosition::InitialPosition(
          syncer::UniquePosition::RandomSuffix());

  syncer::UpdateResponseDataList updates;
  updates.push_back(
      CreateUpdateResponseData({kNodeId, kTitle, kUrl, kBookmarkBarId,
                                /*server_tag=*/std::string()},
                               kRandomPosition, /*response_version=*/0));

  const bookmarks::BookmarkNode* bookmark_bar =
      bookmark_model()->bookmark_bar_node();
  ASSERT_TRUE(bookmark_bar->children().empty());

  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));

  ASSERT_THAT(bookmark_bar->children().front().get(), NotNull());
  EXPECT_THAT(bookmark_bar->children().front()->GetTitle(),
              Eq(ASCIIToUTF16(kTitle)));
  EXPECT_THAT(bookmark_bar->children().front()->url(), Eq(GURL(kUrl)));
}

TEST_F(BookmarkModelTypeProcessorTest, ShouldUpdateModelAfterRemoteUpdate) {
  const std::string kNodeId = "node_id";
  const std::string kTitle = "title";
  const std::string kUrl = "http://www.url.com";
  const syncer::UniquePosition kRandomPosition =
      syncer::UniquePosition::InitialPosition(
          syncer::UniquePosition::RandomSuffix());

  std::vector<BookmarkInfo> bookmarks = {
      {kNodeId, kTitle, kUrl, kBookmarkBarId, /*server_tag=*/std::string()}};

  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  InitWithSyncedBookmarks(bookmarks, processor());

  // Make sure original bookmark exists.
  const bookmarks::BookmarkNode* bookmark_bar =
      bookmark_model()->bookmark_bar_node();
  const bookmarks::BookmarkNode* bookmark_node =
      bookmark_bar->children().front().get();
  ASSERT_THAT(bookmark_node, NotNull());
  ASSERT_THAT(bookmark_node->GetTitle(), Eq(ASCIIToUTF16(kTitle)));
  ASSERT_THAT(bookmark_node->url(), Eq(GURL(kUrl)));

  // Process an update for the same bookmark.
  const std::string kNewTitle = "new-title";
  const std::string kNewUrl = "http://www.new-url.com";
  syncer::UpdateResponseDataList updates;
  updates.push_back(CreateUpdateResponseData(
      {kNodeId, kNewTitle, kNewUrl, kBookmarkBarId,
       /*server_tag=*/std::string()},
      kRandomPosition, /*response_version=*/1, bookmark_node->guid()));

  base::HistogramTester histogram_tester;
  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));

  // Check if the bookmark has been updated properly.
  EXPECT_THAT(bookmark_bar->children().front().get(), Eq(bookmark_node));
  EXPECT_THAT(bookmark_node->GetTitle(), Eq(ASCIIToUTF16(kNewTitle)));
  EXPECT_THAT(bookmark_node->url(), Eq(GURL(kNewUrl)));

  histogram_tester.ExpectUniqueSample(
      "Sync.ModelTypeIncrementalUpdateReceived",
      /*sample=*/syncer::ModelTypeHistogramValue(syncer::BOOKMARKS),
      /*expected_count=*/1);
}

TEST_F(
    BookmarkModelTypeProcessorTest,
    ShouldScheduleSaveAfterRemoteUpdateWithOnlyMetadataChangeAndReflections) {
  const std::string kNodeId = "node_id";
  const std::string kTitle = "title";
  const std::string kUrl = "http://www.url.com";
  const syncer::UniquePosition kRandomPosition =
      syncer::UniquePosition::InitialPosition(
          syncer::UniquePosition::RandomSuffix());

  std::vector<BookmarkInfo> bookmarks = {
      {kNodeId, kTitle, kUrl, kBookmarkBarId, /*server_tag=*/std::string()}};

  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  InitWithSyncedBookmarks(bookmarks, processor());

  // Make sure original bookmark exists.
  const bookmarks::BookmarkNode* bookmark_bar =
      bookmark_model()->bookmark_bar_node();
  const bookmarks::BookmarkNode* bookmark_node =
      bookmark_bar->children().front().get();
  ASSERT_THAT(bookmark_node, NotNull());

  // Process an update for the same bookmark with the same data.
  syncer::UpdateResponseDataList updates;
  updates.push_back(CreateUpdateResponseData(
      {kNodeId, kTitle, kUrl, kBookmarkBarId,
       /*server_tag=*/std::string()},
      kRandomPosition, /*response_version=*/1, bookmark_node->guid()));
  updates[0].response_version++;

  EXPECT_CALL(*schedule_save_closure(), Run());
  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));
}

TEST_F(BookmarkModelTypeProcessorTest, ShouldDecodeSyncMetadata) {
  const std::string kNodeId = "node_id1";
  const std::string kTitle = "title1";
  const std::string kUrl = "http://www.url1.com";

  std::vector<BookmarkInfo> bookmarks = {
      {kNodeId, kTitle, kUrl, kBookmarkBarId, /*server_tag=*/std::string()}};

  const bookmarks::BookmarkNode* bookmark_bar_node =
      bookmark_model()->bookmark_bar_node();
  const bookmarks::BookmarkNode* bookmarknode = bookmark_model()->AddURL(
      /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16(kTitle),
      GURL(kUrl));

  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  // TODO(crbug.com/516866): Remove this after initial sync done is properly set
  // within the processor.
  sync_pb::BookmarkModelMetadata model_metadata;
  model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
  // Add entries for the permanent nodes. TestBookmarkClient adds all of them.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_bar_node->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId);
  bookmark_metadata->mutable_metadata()->set_client_tag_hash(
      SyncedBookmarkTracker::GetClientTagHashFromGUID(bookmark_bar_node->guid())
          .value());

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_model()->other_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kOtherBookmarksId);
  bookmark_metadata->mutable_metadata()->set_client_tag_hash(
      SyncedBookmarkTracker::GetClientTagHashFromGUID(
          bookmark_model()->other_node()->guid())
          .value());

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_model()->mobile_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kMobileBookmarksId);
  bookmark_metadata->mutable_metadata()->set_client_tag_hash(
      SyncedBookmarkTracker::GetClientTagHashFromGUID(
          bookmark_model()->mobile_node()->guid())
          .value());

  // Add an entry for the bookmark node.
  *model_metadata.add_bookmarks_metadata() =
      CreateNodeMetadata(bookmarknode, kNodeId);

  // Create a new processor and init it with the metadata str.
  BookmarkModelTypeProcessor new_processor(bookmark_undo_service());

  std::string metadata_str;
  model_metadata.SerializeToString(&metadata_str);
  new_processor.ModelReadyToSync(metadata_str, base::DoNothing(),
                                 bookmark_model());

  AssertState(&new_processor, bookmarks);
}

TEST_F(BookmarkModelTypeProcessorTest, ShouldDecodeEncodedSyncMetadata) {
  const std::string kNodeId1 = "node_id1";
  const std::string kTitle1 = "title1";
  const std::string kUrl1 = "http://www.url1.com";

  const std::string kNodeId2 = "node_id2";
  const std::string kTitle2 = "title2";
  const std::string kUrl2 = "http://www.url2.com";

  std::vector<BookmarkInfo> bookmarks = {
      {kNodeId1, kTitle1, kUrl1, kBookmarkBarId, /*server_tag=*/std::string()},
      {kNodeId2, kTitle2, kUrl2, kBookmarkBarId,
       /*server_tag=*/std::string()}};
  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  InitWithSyncedBookmarks(bookmarks, processor());

  std::string metadata_str = processor()->EncodeSyncMetadata();
  // TODO(crbug.com/516866): Remove this after initial sync done is properly set
  // within the processor.
  sync_pb::BookmarkModelMetadata model_metadata;
  model_metadata.ParseFromString(metadata_str);
  model_metadata.mutable_model_type_state()->set_initial_sync_done(true);

  // Create a new processor and init it with the same metadata str.
  BookmarkModelTypeProcessor new_processor(bookmark_undo_service());
  model_metadata.SerializeToString(&metadata_str);
  new_processor.ModelReadyToSync(metadata_str, base::DoNothing(),
                                 bookmark_model());

  AssertState(&new_processor, bookmarks);

  // Make sure shutdown doesn't crash.
  DestroyBookmarkModel();
  EXPECT_FALSE(processor()->IsConnectedForTest());
  EXPECT_FALSE(new_processor.IsConnectedForTest());
  EXPECT_THAT(processor()->GetTrackerForTest(), NotNull());
  EXPECT_THAT(new_processor.GetTrackerForTest(), NotNull());
}

TEST_F(BookmarkModelTypeProcessorTest, ShouldDecodeEmptyMetadata) {
  // No save should be scheduled.
  EXPECT_CALL(*schedule_save_closure(), Run()).Times(0);
  SimulateModelReadyToSync();
  EXPECT_THAT(processor()->GetTrackerForTest(), IsNull());
}

TEST_F(BookmarkModelTypeProcessorTest,
       ShouldIgnoreNonEmptyMetadataWhileSyncNotDone) {
  sync_pb::BookmarkModelMetadata model_metadata;
  model_metadata.mutable_model_type_state()->set_initial_sync_done(false);
  // Add entries to the metadata.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_model()->bookmark_bar_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId);

  // Create a new processor and init it with the metadata str.
  BookmarkModelTypeProcessor new_processor(bookmark_undo_service());

  // A save should be scheduled.
  NiceMock<base::MockCallback<base::RepeatingClosure>>
      new_schedule_save_closure;
  EXPECT_CALL(new_schedule_save_closure, Run());

  std::string metadata_str;
  model_metadata.SerializeToString(&metadata_str);
  new_processor.ModelReadyToSync(metadata_str, new_schedule_save_closure.Get(),
                                 bookmark_model());
  // Metadata are corrupted, so no tracker should have been created.
  EXPECT_THAT(new_processor.GetTrackerForTest(), IsNull());
}

TEST_F(BookmarkModelTypeProcessorTest,
       ShouldIgnoreMetadataNotMatchingTheModel) {
  sync_pb::BookmarkModelMetadata model_metadata;
  model_metadata.mutable_model_type_state()->set_initial_sync_done(true);
  // Add entries for only the bookmark bar. However, the TestBookmarkClient will
  // create all the 3 permanent nodes.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_model()->bookmark_bar_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId);

  // Create a new processor and init it with the metadata str.
  BookmarkModelTypeProcessor new_processor(bookmark_undo_service());

  // A save should be scheduled.
  NiceMock<base::MockCallback<base::RepeatingClosure>>
      new_schedule_save_closure;
  EXPECT_CALL(new_schedule_save_closure, Run());

  std::string metadata_str;
  model_metadata.SerializeToString(&metadata_str);
  new_processor.ModelReadyToSync(metadata_str, new_schedule_save_closure.Get(),
                                 bookmark_model());

  // Metadata are corrupted, so no tracker should have been created.
  EXPECT_THAT(new_processor.GetTrackerForTest(), IsNull());
}

// Verifies that the model type state stored in the tracker gets
// updated upon handling remote updates by assigning a new encryption
// key name.
TEST_F(BookmarkModelTypeProcessorTest,
       ShouldUpdateModelTypeStateUponHandlingRemoteUpdates) {
  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  // Initialize the process to make sure the tracker has been created.
  InitWithSyncedBookmarks({}, processor());
  const SyncedBookmarkTracker* tracker = processor()->GetTrackerForTest();
  // The encryption key name should be empty.
  ASSERT_TRUE(tracker->model_type_state().encryption_key_name().empty());

  // Build a model type state with an encryption key name.
  const std::string kEncryptionKeyName = "new_encryption_key_name";
  sync_pb::ModelTypeState model_type_state(CreateDummyModelTypeState());
  model_type_state.set_encryption_key_name(kEncryptionKeyName);

  // Push empty updates list to the processor together with the updated model
  // type state.
  syncer::UpdateResponseDataList empty_updates_list;
  processor()->OnUpdateReceived(model_type_state,
                                std::move(empty_updates_list));

  // The model type state inside the tracker should have been updated, and
  // carries the new encryption key name.
  EXPECT_THAT(tracker->model_type_state().encryption_key_name(),
              Eq(kEncryptionKeyName));
}

// This tests that when the encryption key changes, but the received entities
// are already encrypted with the up-to-date encryption key, no recommit is
// needed.
TEST_F(BookmarkModelTypeProcessorTest,
       ShouldNotRecommitEntitiesWhenEncryptionIsUpToDate) {
  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  SimulateConnectSync();
  // Initialize the process to make sure the tracker has been created.
  InitWithSyncedBookmarks({}, processor());
  const SyncedBookmarkTracker* tracker = processor()->GetTrackerForTest();
  // The encryption key name should be empty.
  ASSERT_TRUE(tracker->model_type_state().encryption_key_name().empty());

  // Build a model type state with an encryption key name.
  const std::string kEncryptionKeyName = "new_encryption_key_name";
  sync_pb::ModelTypeState model_type_state(CreateDummyModelTypeState());
  model_type_state.set_encryption_key_name(kEncryptionKeyName);

  // Push an update that is encrypted with the new encryption key.
  const std::string kNodeId = "node_id";
  syncer::UpdateResponseData response_data = CreateUpdateResponseData(
      {kNodeId, "title", "http://www.url.com", /*parent_id=*/kBookmarkBarId,
       /*server_tag=*/std::string()},
      syncer::UniquePosition::InitialPosition(
          syncer::UniquePosition::RandomSuffix()),
      /*response_version=*/0);
  response_data.encryption_key_name = kEncryptionKeyName;

  EXPECT_CALL(*mock_commit_queue(), NudgeForCommit()).Times(0);
  syncer::UpdateResponseDataList updates;
  updates.push_back(std::move(response_data));
  processor()->OnUpdateReceived(model_type_state, std::move(updates));

  // The bookmarks shouldn't be marked for committing.
  ASSERT_THAT(tracker->GetEntityForSyncId(kNodeId), NotNull());
  EXPECT_THAT(tracker->GetEntityForSyncId(kNodeId)->IsUnsynced(), Eq(false));
}

// Verifies that the processor doesn't crash if sync is stopped before receiving
// remote updates or tracking metadata.
TEST_F(BookmarkModelTypeProcessorTest, ShouldStopBeforeReceivingRemoteUpdates) {
  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  ASSERT_THAT(processor()->GetTrackerForTest(), IsNull());
  processor()->OnSyncStopping(syncer::CLEAR_METADATA);
  EXPECT_THAT(processor()->GetTrackerForTest(), IsNull());
}

TEST_F(BookmarkModelTypeProcessorTest, ShouldStopAfterReceivingRemoteUpdates) {
  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  // Initialize the process to make sure the tracker has been created.
  InitWithSyncedBookmarks({}, processor());
  ASSERT_THAT(processor()->GetTrackerForTest(), NotNull());
  processor()->OnSyncStopping(syncer::CLEAR_METADATA);
  EXPECT_THAT(processor()->GetTrackerForTest(), IsNull());
}

TEST_F(BookmarkModelTypeProcessorTest,
       ShouldReportNoCountersWhenModelIsNotLoaded) {
  SimulateOnSyncStarting();
  ASSERT_THAT(processor()->GetTrackerForTest(), IsNull());
  syncer::TypeEntitiesCount count(syncer::BOOKMARKS);
  // Assign an arbitrary non-zero number of entities to be able to check that
  // actually a 0 has been written to it later.
  count.non_tombstone_entities = 1000;
  processor()->GetTypeEntitiesCountForDebugging(base::BindLambdaForTesting(
      [&](const syncer::TypeEntitiesCount& returned_count) {
        count = returned_count;
      }));
  EXPECT_EQ(0, count.non_tombstone_entities);
}

TEST_F(BookmarkModelTypeProcessorTest,
       ShouldNotCommitEntitiesWithoutLoadedFavicons) {
  const std::string kNodeId = "node_id1";
  const std::string kTitle = "title1";
  const std::string kUrl = "http://www.url1.com";
  const std::string kIconUrl = "http://www.url1.com/favicon";

  const bookmarks::BookmarkNode* bookmark_bar_node =
      bookmark_model()->bookmark_bar_node();
  const bookmarks::BookmarkNode* node = bookmark_model()->AddURL(
      /*parent=*/bookmark_bar_node, /*index=*/0, base::UTF8ToUTF16(kTitle),
      GURL(kUrl));

  sync_pb::BookmarkModelMetadata model_metadata;
  *model_metadata.mutable_model_type_state() = CreateDummyModelTypeState();

  // Add entries for the permanent nodes. TestBookmarkClient adds all of them.
  sync_pb::BookmarkMetadata* bookmark_metadata =
      model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_bar_node->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kBookmarkBarId);
  bookmark_metadata->mutable_metadata()->set_client_tag_hash(
      SyncedBookmarkTracker::GetClientTagHashFromGUID(bookmark_bar_node->guid())
          .value());

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_model()->other_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kOtherBookmarksId);
  bookmark_metadata->mutable_metadata()->set_client_tag_hash(
      SyncedBookmarkTracker::GetClientTagHashFromGUID(
          bookmark_model()->other_node()->guid())
          .value());

  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  bookmark_metadata->set_id(bookmark_model()->mobile_node()->id());
  bookmark_metadata->mutable_metadata()->set_server_id(kMobileBookmarksId);
  bookmark_metadata->mutable_metadata()->set_client_tag_hash(
      SyncedBookmarkTracker::GetClientTagHashFromGUID(
          bookmark_model()->mobile_node()->guid())
          .value());

  // Add an entry for the bookmark node.
  bookmark_metadata = model_metadata.add_bookmarks_metadata();
  *bookmark_metadata = CreateNodeMetadata(node, kNodeId);
  // Mark the entity as unsynced.
  bookmark_metadata->mutable_metadata()->set_sequence_number(2);
  bookmark_metadata->mutable_metadata()->set_acked_sequence_number(1);

  SimulateOnSyncStarting();
  processor()->ModelReadyToSync(model_metadata.SerializeAsString(),
                                schedule_save_closure()->Get(),
                                bookmark_model());

  base::MockOnceCallback<void(
      std::vector<std::unique_ptr<syncer::CommitRequestData>> &&)>
      callback;
  std::vector<std::unique_ptr<syncer::CommitRequestData>> callback_result;
  ON_CALL(callback, Run)
      .WillByDefault(
          [&callback_result](
              std::vector<std::unique_ptr<syncer::CommitRequestData>>&&
                  commit_data) { callback_result = std::move(commit_data); });

  ASSERT_EQ(0u, bookmark_client()->GetTasksCount());
  EXPECT_CALL(callback, Run);
  processor()->GetLocalChanges(/*max_entries=*/10, callback.Get());
  EXPECT_TRUE(callback_result.empty());
  EXPECT_TRUE(node->is_favicon_loading());

  bookmark_client()->SimulateFaviconLoaded(GURL(kUrl), gfx::Image(),
                                           GURL(kIconUrl));
  ASSERT_TRUE(node->is_favicon_loaded());
  EXPECT_CALL(callback, Run);
  processor()->GetLocalChanges(/*max_entries=*/10, callback.Get());
  EXPECT_FALSE(callback_result.empty());
}

TEST_F(BookmarkModelTypeProcessorTest, ShouldReuploadLegacyBookmarksOnStart) {
  const std::string kNodeId = "node_id";
  const std::string kTitle = "title";
  const std::string kUrl = "http://www.url.com";

  std::vector<BookmarkInfo> bookmarks = {
      {kNodeId, kTitle, kUrl, kBookmarkBarId, /*server_tag=*/std::string()}};

  SimulateModelReadyToSync();
  SimulateOnSyncStarting();
  SimulateConnectSync();
  InitWithSyncedBookmarks(bookmarks, processor());

  sync_pb::BookmarkModelMetadata model_metadata =
      BuildBookmarkModelMetadataWithoutFullTitles();
  ASSERT_FALSE(processor()->GetTrackerForTest()->HasLocalChanges());

  // Simulate browser restart, enable sync reupload and initialize the processor
  // again.
  ResetModelTypeProcessor();

  base::test::ScopedFeatureList features;
  features.InitAndEnableFeature(switches::kSyncReuploadBookmarkFullTitles);

  std::string metadata_str;
  model_metadata.SerializeToString(&metadata_str);
  processor()->ModelReadyToSync(metadata_str, base::DoNothing(),
                                bookmark_model());
  SimulateOnSyncStarting();
  SimulateConnectSync();

  ASSERT_THAT(processor()->GetTrackerForTest(), NotNull());
  const SyncedBookmarkTracker::Entity* entity =
      processor()->GetTrackerForTest()->GetEntityForSyncId(kNodeId);
  ASSERT_THAT(entity, NotNull());

  // Entity should be synced before until first update is received.
  ASSERT_FALSE(entity->IsUnsynced());
  ASSERT_FALSE(processor()
                   ->GetTrackerForTest()
                   ->BuildBookmarkModelMetadata()
                   .bookmarks_full_title_reuploaded());

  // Synchronize with the server and get any updates.
  EXPECT_CALL(*mock_commit_queue(), NudgeForCommit());
  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                syncer::UpdateResponseDataList());

  // Check that all entities are unsynced now and metadata is marked as
  // reuploaded.
  EXPECT_TRUE(entity->IsUnsynced());
  EXPECT_TRUE(processor()
                  ->GetTrackerForTest()
                  ->BuildBookmarkModelMetadata()
                  .bookmarks_full_title_reuploaded());
}

}  // namespace

}  // namespace sync_bookmarks
