// 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 <string>
#include <utility>
#include <vector>

#include "testing/gtest/include/gtest/gtest.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_backend.h"
#include "chrome/browser/history/history_db_task.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_service.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/history_types.h"
#include "chrome/browser/invalidation/fake_invalidation_service.h"
#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/sync/abstract_profile_sync_service_test.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
#include "chrome/browser/sync/glue/typed_url_change_processor.h"
#include "chrome/browser/sync/glue/typed_url_data_type_controller.h"
#include "chrome/browser/sync/glue/typed_url_model_associator.h"
#include "chrome/browser/sync/profile_sync_components_factory.h"
#include "chrome/browser/sync/profile_sync_components_factory_mock.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/sync/profile_sync_test_util.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/invalidation/invalidation_service.h"
#include "components/invalidation/profile_invalidation_provider.h"
#include "components/keyed_service/content/refcounted_browser_context_keyed_service.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/sync_driver/data_type_error_handler_mock.h"
#include "content/public/browser/notification_service.h"
#include "google_apis/gaia/gaia_constants.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
#include "sync/protocol/typed_url_specifics.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"

using base::Thread;
using base::Time;
using browser_sync::TypedUrlChangeProcessor;
using browser_sync::TypedUrlDataTypeController;
using browser_sync::TypedUrlModelAssociator;
using history::HistoryBackend;
using history::URLID;
using history::URLRow;
using syncer::syncable::WriteTransaction;
using testing::DoAll;
using testing::Return;
using testing::SetArgumentPointee;
using testing::_;

namespace content {
class BrowserContext;
}

namespace {

const char kTestProfileName[] = "test-profile";

// Visits with this timestamp are treated as expired.
static const int EXPIRED_VISIT = -1;

class HistoryBackendMock : public HistoryBackend {
 public:
  HistoryBackendMock() : HistoryBackend(base::FilePath(), NULL, NULL) {}
  virtual bool IsExpiredVisitTime(const base::Time& time) OVERRIDE {
    return time.ToInternalValue() == EXPIRED_VISIT;
  }
  MOCK_METHOD1(GetAllTypedURLs, bool(history::URLRows* entries));
  MOCK_METHOD3(GetMostRecentVisitsForURL, bool(history::URLID id,
                                               int max_visits,
                                               history::VisitVector* visits));
  MOCK_METHOD2(UpdateURL, bool(history::URLID id, const history::URLRow& url));
  MOCK_METHOD3(AddVisits, bool(const GURL& url,
                               const std::vector<history::VisitInfo>& visits,
                               history::VisitSource visit_source));
  MOCK_METHOD1(RemoveVisits, bool(const history::VisitVector& visits));
  MOCK_METHOD2(GetURL, bool(const GURL& url_id, history::URLRow* url_row));
  MOCK_METHOD2(SetPageTitle, void(const GURL& url,
                                  const base::string16& title));
  MOCK_METHOD1(DeleteURL, void(const GURL& url));

 private:
  virtual ~HistoryBackendMock() {}
};

class HistoryServiceMock : public HistoryService {
 public:
  HistoryServiceMock(history::HistoryClient* client, Profile* profile)
      : HistoryService(client, profile), backend_(NULL) {}

  virtual void ScheduleDBTask(scoped_ptr<history::HistoryDBTask> task,
                              base::CancelableTaskTracker* tracker) OVERRIDE {
    history::HistoryDBTask* task_raw = task.get();
    task_runner_->PostTaskAndReply(
        FROM_HERE,
        base::Bind(&HistoryServiceMock::RunTaskOnDBThread,
                   base::Unretained(this), task_raw),
        base::Bind(&base::DeletePointer<history::HistoryDBTask>,
                   task.release()));
  }

  MOCK_METHOD0(Shutdown, void());

  void ShutdownBaseService() {
    HistoryService::Shutdown();
  }

  void set_task_runner(
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    DCHECK(task_runner);
    task_runner_ = task_runner;
  }

  void set_backend(scoped_refptr<history::HistoryBackend> backend) {
    backend_ = backend;
  }

 private:
  virtual ~HistoryServiceMock() {}

  void RunTaskOnDBThread(history::HistoryDBTask* task) {
    EXPECT_TRUE(task->RunOnDBThread(backend_, NULL));
  }

  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  scoped_refptr<history::HistoryBackend> backend_;
};

KeyedService* BuildFakeProfileInvalidationProvider(
    content::BrowserContext* context) {
  return new invalidation::ProfileInvalidationProvider(
      scoped_ptr<invalidation::InvalidationService>(
          new invalidation::FakeInvalidationService));
}

KeyedService* BuildHistoryService(content::BrowserContext* profile) {
  return new HistoryServiceMock(NULL, static_cast<Profile*>(profile));
}

class TestTypedUrlModelAssociator : public TypedUrlModelAssociator {
 public:
  TestTypedUrlModelAssociator(
      ProfileSyncService* sync_service,
      history::HistoryBackend* history_backend,
      sync_driver::DataTypeErrorHandler* error_handler) :
      TypedUrlModelAssociator(sync_service, history_backend, error_handler) {}

 protected:
  // Don't clear error stats - that way we can verify their values in our
  // tests.
  virtual void ClearErrorStats() OVERRIDE {}
};

ACTION_P2(ShutdownHistoryService, thread, service) {
  service->ShutdownBaseService();
  delete thread;
}

ACTION_P6(MakeTypedUrlSyncComponents,
              profile,
              service,
              hb,
              dtc,
              error_handler,
              model_associator) {
  *model_associator =
      new TestTypedUrlModelAssociator(service, hb, error_handler);
  TypedUrlChangeProcessor* change_processor =
      new TypedUrlChangeProcessor(profile, *model_associator, hb, dtc);
  return ProfileSyncComponentsFactory::SyncComponents(*model_associator,
                                                      change_processor);
}

class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest {
 public:
  void AddTypedUrlSyncNode(const history::URLRow& url,
                           const history::VisitVector& visits) {
    syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
    syncer::ReadNode typed_url_root(&trans);
    ASSERT_EQ(syncer::BaseNode::INIT_OK,
              typed_url_root.InitTypeRoot(syncer::TYPED_URLS));

    syncer::WriteNode node(&trans);
    std::string tag = url.url().spec();
    syncer::WriteNode::InitUniqueByCreationResult result =
        node.InitUniqueByCreation(syncer::TYPED_URLS, typed_url_root, tag);
    ASSERT_EQ(syncer::WriteNode::INIT_SUCCESS, result);
    TypedUrlModelAssociator::WriteToSyncNode(url, visits, &node);
  }

 protected:
  ProfileSyncServiceTypedUrlTest()
      : profile_manager_(TestingBrowserProcess::GetGlobal()) {
    history_thread_.reset(new Thread("history"));
  }

  virtual void SetUp() {
    AbstractProfileSyncServiceTest::SetUp();
    ASSERT_TRUE(profile_manager_.SetUp());
    TestingProfile::TestingFactories testing_factories;
    testing_factories.push_back(std::make_pair(
        ProfileOAuth2TokenServiceFactory::GetInstance(),
        BuildAutoIssuingFakeProfileOAuth2TokenService));
    profile_ = profile_manager_.CreateTestingProfile(
        kTestProfileName,
        scoped_ptr<PrefServiceSyncable>(),
        base::UTF8ToUTF16(kTestProfileName),
        0,
        std::string(),
        testing_factories);
    invalidation::ProfileInvalidationProviderFactory::GetInstance()->
        SetTestingFactory(profile_, BuildFakeProfileInvalidationProvider);
    history_thread_->Start();
    history_backend_ = new HistoryBackendMock();
    history_service_ = static_cast<HistoryServiceMock*>(
        HistoryServiceFactory::GetInstance()->SetTestingFactoryAndUse(
            profile_, BuildHistoryService));
    history_service_->set_task_runner(history_thread_->task_runner());
    history_service_->set_backend(history_backend_);
  }

  virtual void TearDown() {
    EXPECT_CALL((*history_service_), Shutdown())
        .WillOnce(ShutdownHistoryService(history_thread_.release(),
                                         history_service_));
    profile_ = NULL;
    profile_manager_.DeleteTestingProfile(kTestProfileName);
    AbstractProfileSyncServiceTest::TearDown();
  }

  TypedUrlModelAssociator* StartSyncService(const base::Closure& callback) {
    TypedUrlModelAssociator* model_associator = NULL;
    if (!sync_service_) {
      SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile_);
      signin->SetAuthenticatedUsername("test");
      sync_service_ = TestProfileSyncService::BuildAutoStartAsyncInit(profile_,
                                                                      callback);
      ProfileSyncComponentsFactoryMock* components =
          sync_service_->components_factory_mock();
      TypedUrlDataTypeController* data_type_controller =
          new TypedUrlDataTypeController(components, profile_, sync_service_);

      EXPECT_CALL(*components, CreateTypedUrlSyncComponents(_, _, _)).
          WillOnce(MakeTypedUrlSyncComponents(profile_,
                                              sync_service_,
                                              history_backend_.get(),
                                              data_type_controller,
                                              &error_handler_,
                                              &model_associator));
      EXPECT_CALL(*components, CreateDataTypeManager(_, _, _, _, _, _)).
          WillOnce(ReturnNewDataTypeManager());

      ProfileOAuth2TokenService* oauth2_token_service =
          ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
      oauth2_token_service->UpdateCredentials("test", "oauth2_login_token");

      sync_service_->RegisterDataTypeController(data_type_controller);

      sync_service_->Initialize();
      base::MessageLoop::current()->Run();
    }
    return model_associator;
  }

  void GetTypedUrlsFromSyncDB(history::URLRows* urls) {
    urls->clear();
    syncer::ReadTransaction trans(FROM_HERE, sync_service_->GetUserShare());
    syncer::ReadNode typed_url_root(&trans);
    if (typed_url_root.InitTypeRoot(syncer::TYPED_URLS) !=
        syncer::BaseNode::INIT_OK)
      return;

    int64 child_id = typed_url_root.GetFirstChildId();
    while (child_id != syncer::kInvalidId) {
      syncer::ReadNode child_node(&trans);
      if (child_node.InitByIdLookup(child_id) != syncer::BaseNode::INIT_OK)
        return;

      const sync_pb::TypedUrlSpecifics& typed_url(
          child_node.GetTypedUrlSpecifics());
      history::URLRow new_url(GURL(typed_url.url()));

      new_url.set_title(base::UTF8ToUTF16(typed_url.title()));
      DCHECK(typed_url.visits_size());
      DCHECK_EQ(typed_url.visits_size(), typed_url.visit_transitions_size());
      new_url.set_last_visit(base::Time::FromInternalValue(
          typed_url.visits(typed_url.visits_size() - 1)));
      new_url.set_hidden(typed_url.hidden());

      urls->push_back(new_url);
      child_id = child_node.GetSuccessorId();
    }
  }

  void SetIdleChangeProcessorExpectations() {
    EXPECT_CALL((*history_backend_.get()), SetPageTitle(_, _)).Times(0);
    EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)).Times(0);
    EXPECT_CALL((*history_backend_.get()), GetURL(_, _)).Times(0);
    EXPECT_CALL((*history_backend_.get()), DeleteURL(_)).Times(0);
  }

  static bool URLsEqual(history::URLRow& lhs, history::URLRow& rhs) {
    // Only verify the fields we explicitly sync (i.e. don't verify typed_count
    // or visit_count because we rely on the history DB to manage those values
    // and they are left unchanged by HistoryBackendMock).
    return (lhs.url().spec().compare(rhs.url().spec()) == 0) &&
           (lhs.title().compare(rhs.title()) == 0) &&
           (lhs.last_visit() == rhs.last_visit()) &&
           (lhs.hidden() == rhs.hidden());
  }

  static history::URLRow MakeTypedUrlEntry(const char* url,
                                           const char* title,
                                           int typed_count,
                                           int64 last_visit,
                                           bool hidden,
                                           history::VisitVector* visits) {
    // Give each URL a unique ID, to mimic the behavior of the real database.
    static int unique_url_id = 0;
    GURL gurl(url);
    URLRow history_url(gurl, ++unique_url_id);
    history_url.set_title(base::UTF8ToUTF16(title));
    history_url.set_typed_count(typed_count);
    history_url.set_last_visit(
        base::Time::FromInternalValue(last_visit));
    history_url.set_hidden(hidden);
    visits->push_back(history::VisitRow(
        history_url.id(), history_url.last_visit(), 0,
        content::PAGE_TRANSITION_TYPED, 0));
    history_url.set_visit_count(visits->size());
    return history_url;
  }

  scoped_ptr<Thread> history_thread_;
  TestingProfileManager profile_manager_;
  TestingProfile* profile_;
  scoped_refptr<HistoryBackendMock> history_backend_;
  HistoryServiceMock* history_service_;
  sync_driver::DataTypeErrorHandlerMock error_handler_;
};

void AddTypedUrlEntries(ProfileSyncServiceTypedUrlTest* test,
                        const history::URLRows& entries) {
  test->CreateRoot(syncer::TYPED_URLS);
  for (size_t i = 0; i < entries.size(); ++i) {
    history::VisitVector visits;
    visits.push_back(history::VisitRow(
        entries[i].id(), entries[i].last_visit(), 0,
        content::PageTransitionFromInt(0), 0));
    test->AddTypedUrlSyncNode(entries[i], visits);
  }
}

} // namespace

TEST_F(ProfileSyncServiceTypedUrlTest, EmptyNativeEmptySync) {
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(Return(true));
  SetIdleChangeProcessorExpectations();
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  TypedUrlModelAssociator* associator =
      StartSyncService(create_root.callback());
  history::URLRows sync_entries;
  GetTypedUrlsFromSyncDB(&sync_entries);
  EXPECT_EQ(0U, sync_entries.size());
  ASSERT_EQ(0, associator->GetErrorPercentage());
}

TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeEmptySync) {
  history::URLRows entries;
  history::VisitVector visits;
  entries.push_back(MakeTypedUrlEntry("http://foo.com", "bar",
                                      2, 15, false, &visits));

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(visits), Return(true)));
  SetIdleChangeProcessorExpectations();
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  TypedUrlModelAssociator* associator =
      StartSyncService(create_root.callback());
  history::URLRows sync_entries;
  GetTypedUrlsFromSyncDB(&sync_entries);
  ASSERT_EQ(1U, sync_entries.size());
  EXPECT_TRUE(URLsEqual(entries[0], sync_entries[0]));
  ASSERT_EQ(0, associator->GetErrorPercentage());
}

TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeErrorReadingVisits) {
  history::URLRows entries;
  history::VisitVector visits;
  history::URLRow native_entry1(MakeTypedUrlEntry("http://foo.com", "bar",
                                                  2, 15, false, &visits));
  history::URLRow native_entry2(MakeTypedUrlEntry("http://foo2.com", "bar",
                                                  3, 15, false, &visits));
  entries.push_back(native_entry1);
  entries.push_back(native_entry2);
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
  // Return an error from GetMostRecentVisitsForURL() for the second URL.
  EXPECT_CALL((*history_backend_.get()),
              GetMostRecentVisitsForURL(native_entry1.id(), _, _)).
                  WillRepeatedly(Return(true));
  EXPECT_CALL((*history_backend_.get()),
              GetMostRecentVisitsForURL(native_entry2.id(), _, _)).
                  WillRepeatedly(Return(false));
  SetIdleChangeProcessorExpectations();
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());
  history::URLRows sync_entries;
  GetTypedUrlsFromSyncDB(&sync_entries);
  ASSERT_EQ(1U, sync_entries.size());
  EXPECT_TRUE(URLsEqual(native_entry1, sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeWithBlankEmptySync) {
  std::vector<history::URLRow> entries;
  history::VisitVector visits;
  // Add an empty URL.
  entries.push_back(MakeTypedUrlEntry("", "bar",
                                      2, 15, false, &visits));
  entries.push_back(MakeTypedUrlEntry("http://foo.com", "bar",
                                      2, 15, false, &visits));
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(visits), Return(true)));
  SetIdleChangeProcessorExpectations();
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());
  std::vector<history::URLRow> sync_entries;
  GetTypedUrlsFromSyncDB(&sync_entries);
  // The empty URL should be ignored.
  ASSERT_EQ(1U, sync_entries.size());
  EXPECT_TRUE(URLsEqual(entries[1], sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeHasSyncNoMerge) {
  history::VisitVector native_visits;
  history::VisitVector sync_visits;
  history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
                                                 2, 15, false, &native_visits));
  history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry",
                                               3, 16, false, &sync_visits));

  history::URLRows native_entries;
  native_entries.push_back(native_entry);
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(native_visits), Return(true)));
  EXPECT_CALL((*history_backend_.get()),
      AddVisits(_, _, history::SOURCE_SYNCED)).WillRepeatedly(Return(true));

  history::URLRows sync_entries;
  sync_entries.push_back(sync_entry);

  EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)).
      WillRepeatedly(Return(true));
  StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));

  std::map<std::string, history::URLRow> expected;
  expected[native_entry.url().spec()] = native_entry;
  expected[sync_entry.url().spec()] = sync_entry;

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);

  EXPECT_TRUE(new_sync_entries.size() == expected.size());
  for (history::URLRows::iterator entry = new_sync_entries.begin();
       entry != new_sync_entries.end(); ++entry) {
    EXPECT_TRUE(URLsEqual(expected[entry->url().spec()], *entry));
  }
}

TEST_F(ProfileSyncServiceTypedUrlTest, EmptyNativeExpiredSync) {
  history::VisitVector sync_visits;
  history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry",
                                               3, EXPIRED_VISIT, false,
                                               &sync_visits));
  history::URLRows sync_entries;
  sync_entries.push_back(sync_entry);

  // Since all our URLs are expired, no backend calls to add new URLs will be
  // made.
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(Return(true));
  SetIdleChangeProcessorExpectations();

  StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
}

TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeHasSyncMerge) {
  history::VisitVector native_visits;
  history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
                                                 2, 15, false, &native_visits));
  history::VisitVector sync_visits;
  history::URLRow sync_entry(MakeTypedUrlEntry("http://native.com", "name",
                                               1, 17, false, &sync_visits));
  history::VisitVector merged_visits;
  merged_visits.push_back(history::VisitRow(
      sync_entry.id(), base::Time::FromInternalValue(15), 0,
      content::PageTransitionFromInt(0), 0));

  history::URLRow merged_entry(MakeTypedUrlEntry("http://native.com", "name",
                                                 2, 17, false, &merged_visits));

  history::URLRows native_entries;
  native_entries.push_back(native_entry);
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(native_visits), Return(true)));
  EXPECT_CALL((*history_backend_.get()),
      AddVisits(_, _, history::SOURCE_SYNCED)). WillRepeatedly(Return(true));

  history::URLRows sync_entries;
  sync_entries.push_back(sync_entry);

  EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)).
      WillRepeatedly(Return(true));
  EXPECT_CALL((*history_backend_.get()), SetPageTitle(_, _)).
      WillRepeatedly(Return());
  StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(merged_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, HasNativeWithErrorHasSyncMerge) {
  history::VisitVector native_visits;
  history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "native",
                                                 2, 15, false, &native_visits));
  history::VisitVector sync_visits;
  history::URLRow sync_entry(MakeTypedUrlEntry("http://native.com", "sync",
                                               1, 17, false, &sync_visits));

  history::URLRows native_entries;
  native_entries.push_back(native_entry);
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true)));
  // Return an error getting the visits for the native URL.
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(Return(false));
  EXPECT_CALL((*history_backend_.get()), GetURL(_, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<1>(native_entry), Return(true)));
  EXPECT_CALL((*history_backend_.get()),
      AddVisits(_, _, history::SOURCE_SYNCED)). WillRepeatedly(Return(true));

  history::URLRows sync_entries;
  sync_entries.push_back(sync_entry);

  EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)).
      WillRepeatedly(Return(true));
  EXPECT_CALL((*history_backend_.get()), SetPageTitle(_, _)).
      WillRepeatedly(Return());
  StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(sync_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeAdd) {
  history::VisitVector added_visits;
  history::URLRow added_entry(MakeTypedUrlEntry("http://added.com", "entry",
                                                2, 15, false, &added_visits));

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(Return(true));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillOnce(DoAll(SetArgumentPointee<2>(added_visits), Return(true)));

  SetIdleChangeProcessorExpectations();
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::URLsModifiedDetails details;
  details.changed_urls.push_back(added_entry);
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsModifiedDetails>(&details));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(added_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeAddWithBlank) {
  history::VisitVector added_visits;
  history::URLRow empty_entry(MakeTypedUrlEntry("", "entry",
                                                2, 15, false, &added_visits));
  history::URLRow added_entry(MakeTypedUrlEntry("http://added.com", "entry",
                                                2, 15, false, &added_visits));

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(Return(true));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(added_visits), Return(true)));

  SetIdleChangeProcessorExpectations();
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::URLsModifiedDetails details;
  details.changed_urls.push_back(empty_entry);
  details.changed_urls.push_back(added_entry);
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsModifiedDetails>(&details));

  std::vector<history::URLRow> new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(added_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeUpdate) {
  history::VisitVector original_visits;
  history::URLRow original_entry(MakeTypedUrlEntry("http://mine.com", "entry",
                                                   2, 15, false,
                                                   &original_visits));
  history::URLRows original_entries;
  original_entries.push_back(original_entry);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillOnce(DoAll(SetArgumentPointee<2>(original_visits),
                     Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::VisitVector updated_visits;
  history::URLRow updated_entry(MakeTypedUrlEntry("http://mine.com", "entry",
                                                  7, 17, false,
                                                  &updated_visits));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillOnce(DoAll(SetArgumentPointee<2>(updated_visits),
                     Return(true)));

  history::URLsModifiedDetails details;
  details.changed_urls.push_back(updated_entry);
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsModifiedDetails>(&details));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(updated_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeAddFromVisit) {
  history::VisitVector added_visits;
  history::URLRow added_entry(MakeTypedUrlEntry("http://added.com", "entry",
                                                2, 15, false, &added_visits));

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(Return(true));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillOnce(DoAll(SetArgumentPointee<2>(added_visits), Return(true)));

  SetIdleChangeProcessorExpectations();
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::URLVisitedDetails details;
  details.row = added_entry;
  details.transition = content::PAGE_TRANSITION_TYPED;
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLVisitedDetails>(&details));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(added_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeUpdateFromVisit) {
  history::VisitVector original_visits;
  history::URLRow original_entry(MakeTypedUrlEntry("http://mine.com", "entry",
                                                   2, 15, false,
                                                   &original_visits));
  history::URLRows original_entries;
  original_entries.push_back(original_entry);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillOnce(DoAll(SetArgumentPointee<2>(original_visits),
                           Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::VisitVector updated_visits;
  history::URLRow updated_entry(MakeTypedUrlEntry("http://mine.com", "entry",
                                                  7, 17, false,
                                                  &updated_visits));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillOnce(DoAll(SetArgumentPointee<2>(updated_visits),
                           Return(true)));

  history::URLVisitedDetails details;
  details.row = updated_entry;
  details.transition = content::PAGE_TRANSITION_TYPED;
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLVisitedDetails>(&details));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(updated_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserIgnoreChangeUpdateFromVisit) {
  history::VisitVector original_visits;
  history::URLRow original_entry(MakeTypedUrlEntry("http://mine.com", "entry",
                                                   2, 15, false,
                                                   &original_visits));
  history::URLRows original_entries;
  original_entries.push_back(original_entry);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(original_visits),
                           Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());
  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(original_entry, new_sync_entries[0]));

  history::VisitVector updated_visits;
  history::URLRow updated_entry(MakeTypedUrlEntry("http://mine.com", "entry",
                                                  7, 15, false,
                                                  &updated_visits));
  history::URLVisitedDetails details;
  details.row = updated_entry;

  // Should ignore this change because it's not TYPED.
  details.transition = content::PAGE_TRANSITION_RELOAD;
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLVisitedDetails>(&details));

  GetTypedUrlsFromSyncDB(&new_sync_entries);

  // Should be no changes to the sync DB from this notification.
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(original_entry, new_sync_entries[0]));

  // Now, try updating it with a large number of visits not divisible by 10
  // (should ignore this visit).
  history::URLRow twelve_visits(MakeTypedUrlEntry("http://mine.com", "entry",
                                                  12, 15, false,
                                                  &updated_visits));
  details.row = twelve_visits;
  details.transition = content::PAGE_TRANSITION_TYPED;
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLVisitedDetails>(&details));
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  // Should be no changes to the sync DB from this notification.
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(original_entry, new_sync_entries[0]));

  // Now, try updating it with a large number of visits that is divisible by 10
  // (should *not* be ignored).
  history::URLRow twenty_visits(MakeTypedUrlEntry("http://mine.com", "entry",
                                                  20, 15, false,
                                                  &updated_visits));
  details.row = twenty_visits;
  details.transition = content::PAGE_TRANSITION_TYPED;
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URL_VISITED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLVisitedDetails>(&details));
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(twenty_visits, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemove) {
  history::VisitVector original_visits1;
  history::URLRow original_entry1(MakeTypedUrlEntry("http://mine.com", "entry",
                                                    2, 15, false,
                                                    &original_visits1));
  history::VisitVector original_visits2;
  history::URLRow original_entry2(MakeTypedUrlEntry("http://mine2.com",
                                                    "entry2",
                                                    3, 15, false,
                                                    &original_visits2));
  history::URLRows original_entries;
  original_entries.push_back(original_entry1);
  original_entries.push_back(original_entry2);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(original_visits1),
                           Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::URLsDeletedDetails changes;
  changes.all_history = false;
  changes.rows.push_back(history::URLRow(GURL("http://mine.com")));
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsDeletedDetails>(&changes));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(original_entry2, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemoveExpired) {
  history::VisitVector original_visits1;
  history::URLRow original_entry1(MakeTypedUrlEntry("http://mine.com", "entry",
                                                    2, 15, false,
                                                    &original_visits1));
  history::VisitVector original_visits2;
  history::URLRow original_entry2(MakeTypedUrlEntry("http://mine2.com",
                                                    "entry2",
                                                    3, 15, false,
                                                    &original_visits2));
  history::URLRows original_entries;
  original_entries.push_back(original_entry1);
  original_entries.push_back(original_entry2);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(original_visits1),
                           Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::URLsDeletedDetails changes;
  changes.all_history = false;
  // Setting expired=true should cause the sync code to ignore this deletion.
  changes.expired = true;
  changes.rows.push_back(history::URLRow(GURL("http://mine.com")));
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsDeletedDetails>(&changes));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  // Both URLs should still be there.
  ASSERT_EQ(2U, new_sync_entries.size());
}

TEST_F(ProfileSyncServiceTypedUrlTest, ProcessUserChangeRemoveAll) {
  history::VisitVector original_visits1;
  history::URLRow original_entry1(MakeTypedUrlEntry("http://mine.com", "entry",
                                                    2, 15, false,
                                                    &original_visits1));
  history::VisitVector original_visits2;
  history::URLRow original_entry2(MakeTypedUrlEntry("http://mine2.com",
                                                    "entry2",
                                                    3, 15, false,
                                                    &original_visits2));
  history::URLRows original_entries;
  original_entries.push_back(original_entry1);
  original_entries.push_back(original_entry2);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(original_visits1),
                           Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(2U, new_sync_entries.size());

  history::URLsDeletedDetails changes;
  changes.all_history = true;
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsDeletedDetails>(&changes));

  GetTypedUrlsFromSyncDB(&new_sync_entries);
  ASSERT_EQ(0U, new_sync_entries.size());
}

TEST_F(ProfileSyncServiceTypedUrlTest, FailWriteToHistoryBackend) {
  history::VisitVector native_visits;
  history::VisitVector sync_visits;
  history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
                                                 2, 15, false, &native_visits));
  history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry",
                                               3, 16, false, &sync_visits));

  history::URLRows native_entries;
  native_entries.push_back(native_entry);
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetURL(_, _)).
      WillOnce(DoAll(SetArgumentPointee<1>(native_entry), Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(native_visits), Return(true)));
  EXPECT_CALL((*history_backend_.get()),
      AddVisits(_, _, history::SOURCE_SYNCED)).WillRepeatedly(Return(false));

  history::URLRows sync_entries;
  sync_entries.push_back(sync_entry);

  EXPECT_CALL((*history_backend_.get()), UpdateURL(_, _)).
      WillRepeatedly(Return(false));
  TypedUrlModelAssociator* associator =
      StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
  // Errors writing to the DB should be recorded, but should not cause an
  // unrecoverable error.
  ASSERT_FALSE(
      sync_service_->failed_data_types_handler().GetFailedTypes().Has(
          syncer::TYPED_URLS));
  // Some calls should have succeeded, so the error percentage should be
  // somewhere > 0 and < 100.
  ASSERT_NE(0, associator->GetErrorPercentage());
  ASSERT_NE(100, associator->GetErrorPercentage());
}

TEST_F(ProfileSyncServiceTypedUrlTest, FailToGetTypedURLs) {
  history::VisitVector native_visits;
  history::VisitVector sync_visits;
  history::URLRow native_entry(MakeTypedUrlEntry("http://native.com", "entry",
                                                 2, 15, false, &native_visits));
  history::URLRow sync_entry(MakeTypedUrlEntry("http://sync.com", "entry",
                                               3, 16, false, &sync_visits));

  history::URLRows native_entries;
  native_entries.push_back(native_entry);
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillOnce(DoAll(SetArgumentPointee<0>(native_entries), Return(false)));

  history::URLRows sync_entries;
  sync_entries.push_back(sync_entry);

  EXPECT_CALL(error_handler_, CreateAndUploadError(_, _, _)).
              WillOnce(Return(syncer::SyncError(
                                  FROM_HERE,
                                  syncer::SyncError::DATATYPE_ERROR,
                                  "Unit test",
                                  syncer::TYPED_URLS)));
  StartSyncService(base::Bind(&AddTypedUrlEntries, this, sync_entries));
  // Errors getting typed URLs will cause an unrecoverable error (since we can
  // do *nothing* in that case).
  ASSERT_TRUE(
      sync_service_->failed_data_types_handler().GetFailedTypes().Has(
          syncer::TYPED_URLS));
  ASSERT_EQ(
      1u, sync_service_->failed_data_types_handler().GetFailedTypes().Size());
  // Can't check GetErrorPercentage(), because generating an unrecoverable
  // error will free the model associator.
}

TEST_F(ProfileSyncServiceTypedUrlTest, IgnoreLocalFileURL) {
  history::VisitVector original_visits;
  // Create http and file url.
  history::URLRow url_entry(MakeTypedUrlEntry("http://yey.com",
                                              "yey", 12, 15, false,
                                              &original_visits));
  history::URLRow file_entry(MakeTypedUrlEntry("file:///kitty.jpg",
                                               "kitteh", 12, 15, false,
                                               &original_visits));

  history::URLRows original_entries;
  original_entries.push_back(url_entry);
  original_entries.push_back(file_entry);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillRepeatedly(DoAll(SetArgumentPointee<0>(original_entries),
                     Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(original_visits),
                     Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::VisitVector updated_visits;
  // Create updates for the previous urls + a new file one.
  history::URLRow updated_url_entry(MakeTypedUrlEntry("http://yey.com",
                                                      "yey", 20, 15, false,
                                                      &updated_visits));
  history::URLRow updated_file_entry(MakeTypedUrlEntry("file:///cat.jpg",
                                                       "cat", 20, 15, false,
                                                       &updated_visits));
  history::URLRow new_file_entry(MakeTypedUrlEntry("file:///dog.jpg",
                                                   "dog", 20, 15, false,
                                                   &updated_visits));
  history::URLsModifiedDetails details;
  details.changed_urls.push_back(updated_url_entry);
  details.changed_urls.push_back(updated_file_entry);
  details.changed_urls.push_back(new_file_entry);
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsModifiedDetails>(&details));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);

  // We should ignore the local file urls (existing and updated),
  // and only be left with the updated http url.
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(updated_url_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, IgnoreLocalhostURL) {
  history::VisitVector original_visits;
  // Create http and localhost url.
  history::URLRow url_entry(MakeTypedUrlEntry("http://yey.com",
                                              "yey", 12, 15, false,
                                              &original_visits));
  history::URLRow localhost_entry(MakeTypedUrlEntry("http://localhost",
                                              "localhost", 12, 15, false,
                                              &original_visits));

  history::URLRows original_entries;
  original_entries.push_back(url_entry);
  original_entries.push_back(localhost_entry);

  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillRepeatedly(DoAll(SetArgumentPointee<0>(original_entries),
                     Return(true)));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(DoAll(SetArgumentPointee<2>(original_visits),
                     Return(true)));
  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::VisitVector updated_visits;
  // Update the previous entries and add a new localhost.
  history::URLRow updated_url_entry(MakeTypedUrlEntry("http://yey.com",
                                                  "yey", 20, 15, false,
                                                  &updated_visits));
  history::URLRow updated_localhost_entry(MakeTypedUrlEntry(
                                                  "http://localhost:80",
                                                  "localhost", 20, 15, false,
                                                  &original_visits));
  history::URLRow localhost_ip_entry(MakeTypedUrlEntry("http://127.0.0.1",
                                                  "localhost", 12, 15, false,
                                                  &original_visits));
  history::URLsModifiedDetails details;
  details.changed_urls.push_back(updated_url_entry);
  details.changed_urls.push_back(updated_localhost_entry);
  details.changed_urls.push_back(localhost_ip_entry);
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsModifiedDetails>(&details));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);

  // We should ignore the localhost urls and left only with http url.
  ASSERT_EQ(1U, new_sync_entries.size());
  EXPECT_TRUE(URLsEqual(updated_url_entry, new_sync_entries[0]));
}

TEST_F(ProfileSyncServiceTypedUrlTest, IgnoreModificationWithoutValidVisit) {
  EXPECT_CALL((*history_backend_.get()), GetAllTypedURLs(_)).
      WillRepeatedly(Return(true));
  EXPECT_CALL((*history_backend_.get()), GetMostRecentVisitsForURL(_, _, _)).
      WillRepeatedly(Return(true));

  CreateRootHelper create_root(this, syncer::TYPED_URLS);
  StartSyncService(create_root.callback());

  history::VisitVector updated_visits;
  history::URLRow updated_url_entry(MakeTypedUrlEntry("http://yey.com",
                                                  "yey", 20, 0, false,
                                                  &updated_visits));
  history::URLsModifiedDetails details;
  details.changed_urls.push_back(updated_url_entry);
  scoped_refptr<ThreadNotifier> notifier(
      new ThreadNotifier(history_thread_.get()));
  notifier->Notify(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
                   content::Source<Profile>(profile_),
                   content::Details<history::URLsModifiedDetails>(&details));

  history::URLRows new_sync_entries;
  GetTypedUrlsFromSyncDB(&new_sync_entries);

  // The change should be ignored.
  ASSERT_EQ(0U, new_sync_entries.size());
}
