blob: bf6b34c8eae34301e0739c7be4489e1545a4e0bd [file] [log] [blame]
// Copyright 2014 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 "base/command_line.h"
#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
#include "chrome/browser/sync/test/integration/preferences_helper.h"
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "sync/internal_api/public/util/sync_db_util.h"
#include "sync/test/fake_server/fake_server_verifier.h"
#include "sync/util/time.h"
using bookmarks_helper::AddFolder;
using bookmarks_helper::AddURL;
using bookmarks_helper::GetOtherNode;
using bookmarks_helper::ModelMatchesVerifier;
using bookmarks_helper::Move;
using bookmarks_helper::Remove;
using sync_integration_test_util::AwaitCommitActivityCompletion;
namespace {
const char kUrl1[] = "http://www.google.com";
const char kUrl2[] = "http://map.google.com";
const char kUrl3[] = "http://plus.google.com";
} // anonymous namespace
class SingleClientBackupRollbackTest : public SyncTest {
public:
SingleClientBackupRollbackTest() : SyncTest(SINGLE_CLIENT) {}
virtual ~SingleClientBackupRollbackTest() {}
void DisableBackup() {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kSyncDisableBackup);
}
void DisableRollback() {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kSyncDisableRollback);
}
base::Time GetBackupDbLastModified() {
base::RunLoop run_loop;
base::Time backup_time;
syncer::CheckSyncDbLastModifiedTime(
GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")),
base::MessageLoopProxy::current(),
base::Bind(&SingleClientBackupRollbackTest::CheckDbCallback,
base::Unretained(this), &backup_time));
base::MessageLoopProxy::current()->PostTask(
FROM_HERE, run_loop.QuitClosure());
run_loop.Run();
return backup_time;
}
private:
void CheckDbCallback(base::Time* time_out, base::Time time_in) {
*time_out = syncer::ProtoTimeToTime(syncer::TimeToProtoTime(time_in));
}
DISALLOW_COPY_AND_ASSIGN(SingleClientBackupRollbackTest);
};
// Waits until the ProfileSyncService's backend is in IDLE mode.
class SyncBackendStoppedChecker : public ProfileSyncServiceBase::Observer {
public:
explicit SyncBackendStoppedChecker(ProfileSyncService* service)
: pss_(service),
timeout_(TestTimeouts::action_max_timeout()),
done_(false) {}
void OnStateChanged() override {
if (ProfileSyncService::IDLE == pss_->backend_mode()) {
done_ = true;
run_loop_.Quit();
}
}
bool Wait() {
pss_->AddObserver(this);
if (ProfileSyncService::IDLE == pss_->backend_mode())
return true;
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
run_loop_.QuitClosure(),
timeout_);
run_loop_.Run();
pss_->RemoveObserver(this);
return done_;
}
private:
ProfileSyncService* const pss_;
const base::TimeDelta timeout_;
base::RunLoop run_loop_;
bool done_;
};
// Waits until a rollback finishes.
class SyncRollbackChecker : public ProfileSyncServiceBase::Observer,
public BrowsingDataRemover::Observer {
public:
explicit SyncRollbackChecker(ProfileSyncService* service)
: pss_(service),
timeout_(TestTimeouts::action_max_timeout()),
rollback_started_(false),
clear_done_(false) {}
// ProfileSyncServiceBase::Observer implementation.
void OnStateChanged() override {
if (ProfileSyncService::ROLLBACK == pss_->backend_mode()) {
rollback_started_ = true;
if (clear_done_)
run_loop_.Quit();
}
}
// BrowsingDataRemoverObserver::Observer implementation.
void OnBrowsingDataRemoverDone() override {
clear_done_ = true;
if (rollback_started_) {
run_loop_.Quit();
}
}
bool Wait() {
pss_->AddObserver(this);
pss_->SetBrowsingDataRemoverObserverForTesting(this);
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
run_loop_.QuitClosure(),
timeout_);
run_loop_.Run();
pss_->RemoveObserver(this);
return rollback_started_ && clear_done_;
}
ProfileSyncService* const pss_;
const base::TimeDelta timeout_;
base::RunLoop run_loop_;
bool rollback_started_;
bool clear_done_;
};
#if defined(ENABLE_PRE_SYNC_BACKUP)
#define MAYBE_TestBackup TestBackup
#else
#define MAYBE_TestBackup DISABLED_TestBackup
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_TestBackup) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Verify backup DB is created and backup time is set on device info.
base::Time backup_time = GetBackupDbLastModified();
ASSERT_FALSE(backup_time.is_null());
ASSERT_EQ(backup_time, GetSyncService(0)->GetDeviceBackupTimeForTesting());
}
#if defined(ENABLE_PRE_SYNC_BACKUP)
#define MAYBE_TestBackupDisabled TestBackupDisabled
#else
#define MAYBE_TestBackupDisabled DISABLED_TestBackupDisabled
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_TestBackupDisabled) {
DisableBackup();
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Verify backup DB is not created and backup time is not set on device info.
ASSERT_FALSE(base::PathExists(
GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup"))));
ASSERT_TRUE(GetSyncService(0)->GetDeviceBackupTimeForTesting().is_null());
}
#if defined(ENABLE_PRE_SYNC_BACKUP)
#define MAYBE_TestRollback TestRollback
#else
#define MAYBE_TestRollback DISABLED_TestRollback
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_TestRollback) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
// Starting state:
// other_node
// -> top
// -> tier1_a
// -> http://mail.google.com "tier1_a_url0"
// -> tier1_b
// -> http://www.nhl.com "tier1_b_url0"
const BookmarkNode* top = AddFolder(0, GetOtherNode(0), 0, "top");
const BookmarkNode* tier1_a = AddFolder(0, top, 0, "tier1_a");
const BookmarkNode* tier1_b = AddFolder(0, top, 1, "tier1_b");
ASSERT_TRUE(AddURL(0, tier1_a, 0, "tier1_a_url0",
GURL("http://mail.google.com")));
ASSERT_TRUE(AddURL(0, tier1_b, 0, "tier1_b_url0",
GURL("http://www.nhl.com")));
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Made bookmark changes while sync is on.
Move(0, tier1_a->GetChild(0), tier1_b, 1);
Remove(0, tier1_b, 0);
ASSERT_TRUE(AddFolder(0, tier1_b, 1, "tier2_c"));
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Let server to return rollback command on next sync request.
ASSERT_TRUE(GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK));
// Make another change to trigger downloading of rollback command.
Remove(0, tier1_b, 0);
// Wait for rollback to finish and sync backend is completely shut down.
SyncRollbackChecker rollback_checker(GetSyncService(0));
ASSERT_TRUE(rollback_checker.Wait());
SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
ASSERT_TRUE(shutdown_checker.Wait());
// Verify bookmarks are restored.
ASSERT_EQ(1, tier1_a->child_count());
const BookmarkNode* url1 = tier1_a->GetChild(0);
ASSERT_EQ(GURL("http://mail.google.com"), url1->url());
ASSERT_EQ(1, tier1_b->child_count());
const BookmarkNode* url2 = tier1_b->GetChild(0);
ASSERT_EQ(GURL("http://www.nhl.com"), url2->url());
}
#if defined(ENABLE_PRE_SYNC_BACKUP)
#define MAYBE_TestRollbackDisabled TestRollbackDisabled
#else
#define MAYBE_TestRollbackDisabled DISABLED_TestRollbackDisabled
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_TestRollbackDisabled) {
DisableRollback();
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
// Starting state:
// other_node
// -> http://mail.google.com "url0"
// -> http://www.nhl.com "url1"
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
GURL("http://mail.google.com")));
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
GURL("http://www.nhl.com")));
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Made bookmark changes while sync is on.
Remove(0, GetOtherNode(0), 1);
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url2",
GURL("http://www.yahoo.com")));
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Let server to return rollback command on next sync request.
ASSERT_TRUE(GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK));
// Make another change to trigger downloading of rollback command.
Remove(0, GetOtherNode(0), 0);
// Wait for sync backend is completely shut down.
SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
ASSERT_TRUE(shutdown_checker.Wait());
// With rollback disabled, bookmarks in backup DB should not be restored.
// Only bookmark added during sync is present.
ASSERT_EQ(1, GetOtherNode(0)->child_count());
ASSERT_EQ(GURL("http://www.yahoo.com"),
GetOtherNode(0)->GetChild(0)->url());
}
#if defined(ENABLE_PRE_SYNC_BACKUP)
#define MAYBE_TestSyncDisabled TestSyncDisabled
#else
#define MAYBE_TestSyncDisabled DISABLED_TestSyncDisabled
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_TestSyncDisabled) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
// Starting state:
// other_node
// -> http://mail.google.com "url0"
// -> http://www.nhl.com "url1"
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
GURL("http://mail.google.com")));
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
GURL("http://www.nhl.com")));
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Made bookmark changes while sync is on.
Remove(0, GetOtherNode(0), 1);
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url2",
GURL("http://www.yahoo.com")));
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Let server to return birthday error on next sync request.
ASSERT_TRUE(GetFakeServer()->TriggerError(
sync_pb::SyncEnums::NOT_MY_BIRTHDAY));
// Make another change to trigger downloading of rollback command.
Remove(0, GetOtherNode(0), 0);
// Wait sync backend is completely shut down.
SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
ASSERT_TRUE(shutdown_checker.Wait());
// Shouldn't restore bookmarks with sign-out only.
ASSERT_EQ(1, GetOtherNode(0)->child_count());
ASSERT_EQ(GURL("http://www.yahoo.com"),
GetOtherNode(0)->GetChild(0)->url());
}
#if defined(ENABLE_PRE_SYNC_BACKUP)
#define MAYBE_RollbackNoBackup RollbackNoBackup
#else
#define MAYBE_RollbackNoBackup DISABLED_RollbackNoBackup
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_RollbackNoBackup) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
// Starting state:
// other_node
// -> http://mail.google.com "url0"
// -> http://www.nhl.com "url1"
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, "url0",
GURL("http://mail.google.com")));
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
ASSERT_TRUE(ModelMatchesVerifier(0));
ASSERT_TRUE(AddURL(0, GetOtherNode(0), 1, "url1",
GURL("http://www.nhl.com")));
// Delete backup DB.
base::DeleteFile(
GetProfile(0)->GetPath().Append(FILE_PATH_LITERAL("Sync Data Backup")),
true);
// Let server to return rollback command on next sync request.
ASSERT_TRUE(GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK));
// Make another change to trigger downloading of rollback command.
Remove(0, GetOtherNode(0), 0);
// Wait for rollback to finish and sync backend is completely shut down.
SyncRollbackChecker rollback_checker(GetSyncService(0));
ASSERT_TRUE(rollback_checker.Wait());
SyncBackendStoppedChecker checker(GetSyncService(0));
ASSERT_TRUE(checker.Wait());
// Without backup DB, bookmarks remain at the state when sync stops.
ASSERT_EQ(1, GetOtherNode(0)->child_count());
ASSERT_EQ(GURL("http://www.nhl.com"),
GetOtherNode(0)->GetChild(0)->url());
}
#if defined(ENABLE_PRE_SYNC_BACKUP)
#define MAYBE_DontChangeBookmarkOrdering DontChangeBookmarkOrdering
#else
#define MAYBE_DontChangeBookmarkOrdering DISABLED_DontChangeBookmarkOrdering
#endif
IN_PROC_BROWSER_TEST_F(SingleClientBackupRollbackTest,
MAYBE_DontChangeBookmarkOrdering) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
const BookmarkNode* sub_folder = AddFolder(0, GetOtherNode(0), 0, "test");
ASSERT_TRUE(AddURL(0, sub_folder, 0, "", GURL(kUrl1)));
ASSERT_TRUE(AddURL(0, sub_folder, 1, "", GURL(kUrl2)));
ASSERT_TRUE(AddURL(0, sub_folder, 2, "", GURL(kUrl3)));
// Setup sync, wait for its completion, and make sure changes were synced.
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Made bookmark changes while sync is on.
Remove(0, sub_folder, 0);
Remove(0, sub_folder, 0);
ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService(0)));
ASSERT_TRUE(ModelMatchesVerifier(0));
// Let server to return rollback command on next sync request.
ASSERT_TRUE(GetFakeServer()->TriggerError(sync_pb::SyncEnums::USER_ROLLBACK));
// Make another change to trigger downloading of rollback command.
Remove(0, sub_folder, 0);
// Wait for rollback to finish and sync backend is completely shut down.
SyncRollbackChecker rollback_checker(GetSyncService(0));
ASSERT_TRUE(rollback_checker.Wait());
SyncBackendStoppedChecker shutdown_checker(GetSyncService(0));
ASSERT_TRUE(shutdown_checker.Wait());
// Verify bookmarks are unchanged.
ASSERT_EQ(3, sub_folder->child_count());
ASSERT_EQ(GURL(kUrl1), sub_folder->GetChild(0)->url());
ASSERT_EQ(GURL(kUrl2), sub_folder->GetChild(1)->url());
ASSERT_EQ(GURL(kUrl3), sub_folder->GetChild(2)->url());
}