blob: cb8e248456d45f3c868c96c9b466dc4274965f9a [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/strings/string_util.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
#include "chrome/browser/sync/test/integration/sync_service_impl_harness.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/features.h"
#include "components/sync/base/user_selectable_type.h"
#include "components/sync/engine/cycle/entity_change_metric_recording.h"
#include "components/sync/protocol/sync.pb.h"
#include "components/sync/service/glue/sync_transport_data_prefs.h"
#include "components/sync/service/sync_service_impl.h"
#include "components/sync/test/bookmark_entity_builder.h"
#include "components/sync/test/entity_builder_factory.h"
#include "content/public/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_CHROMEOS)
// To control Floating SSO (= sync of cookies) on ChromeOS.
#include "chromeos/constants/pref_names.h"
#include "components/prefs/pref_service.h"
#endif // BUILDFLAG(IS_CHROMEOS)
namespace {
using fake_server::FakeServer;
using syncer::DataType;
using syncer::DataTypeSet;
using syncer::DataTypeToDebugString;
using syncer::UserSelectableType;
using syncer::UserSelectableTypeSet;
using testing::ElementsAre;
using testing::IsEmpty;
const char kSyncedBookmarkURL[] = "http://www.mybookmark.com";
// Non-utf8 string to make sure it gets handled well.
const char kTestServerChips[] = "\xed\xa0\x80\xed\xbf\xbf";
// A FakeServer observer than saves all issued GetUpdates requests to a vector.
class GetUpdatesRequestRecorder : public FakeServer::Observer {
public:
explicit GetUpdatesRequestRecorder(FakeServer* fake_server) {
CHECK(fake_server);
observation_.Observe(fake_server);
}
~GetUpdatesRequestRecorder() override = default;
const std::vector<sync_pb::ClientToServerMessage>& recorded_requests() const {
return recorded_requests_;
}
// FakeServer::Observer overrides.
void OnWillGetUpdates(
const sync_pb::ClientToServerMessage& message) override {
recorded_requests_.push_back(message);
}
private:
std::vector<sync_pb::ClientToServerMessage> recorded_requests_;
base::ScopedObservation<FakeServer, FakeServer::Observer> observation_{this};
};
MATCHER_P2(MatchesGetUpdatesRequest, origin, data_type_set, "") {
if (!testing::ExplainMatchResult(
origin, arg.get_updates().get_updates_origin(), result_listener)) {
*result_listener << "Unexpected origin "
<< arg.get_updates().get_updates_origin();
return false;
}
DataTypeSet actual_data_types;
for (const sync_pb::DataTypeProgressMarker& marker :
arg.get_updates().from_progress_marker()) {
actual_data_types.Put(
syncer::GetDataTypeFromSpecificsFieldNumber(marker.data_type_id()));
}
return testing::ExplainMatchResult(data_type_set, actual_data_types,
result_listener);
}
// Some types show up in multiple groups. This means that there are at least two
// user selectable groups that will cause these types to become enabled. This
// affects our tests because we cannot assume that before enabling a multi type
// it will be disabled, because the other selectable type(s) could already be
// enabling it. And vice versa for disabling.
DataTypeSet MultiGroupTypes(const DataTypeSet& registered_types) {
DataTypeSet seen;
DataTypeSet multi;
for (UserSelectableType type : UserSelectableTypeSet::All()) {
const DataTypeSet grouped_types =
syncer::UserSelectableTypeToAllDataTypes(type);
for (DataType grouped_type : grouped_types) {
if (seen.Has(grouped_type)) {
multi.Put(grouped_type);
} else {
seen.Put(grouped_type);
}
}
}
multi.RetainAll(registered_types);
return multi;
}
// This test enables and disables types and verifies the type is active via
// SyncService::GetActiveDataTypes().
class EnableDisableSingleClientTest : public SyncTest {
public:
EnableDisableSingleClientTest() : SyncTest(SINGLE_CLIENT) {}
EnableDisableSingleClientTest(const EnableDisableSingleClientTest&) = delete;
EnableDisableSingleClientTest& operator=(
const EnableDisableSingleClientTest&) = delete;
~EnableDisableSingleClientTest() override = default;
// Don't use self-notifications as they can trigger additional sync cycles.
bool TestUsesSelfNotifications() override { return false; }
bool IsDataTypeActive(DataType type) {
return GetSyncService(0)->GetActiveDataTypes().Has(type);
}
void InjectSyncedBookmark() {
fake_server::BookmarkEntityBuilder bookmark_builder =
entity_builder_factory_.NewBookmarkEntityBuilder("My Bookmark");
GetFakeServer()->InjectEntity(
bookmark_builder.BuildBookmark(GURL(kSyncedBookmarkURL)));
}
int GetNumUpdatesDownloadedInLastCycle() {
return GetSyncService(0)
->GetLastCycleSnapshotForDebugging()
.model_neutral_state()
.num_updates_downloaded_total;
}
protected:
void SetupTest(bool all_types_enabled) {
ASSERT_TRUE(SetupClients());
#if BUILDFLAG(IS_CHROMEOS)
// This unblocks sync of cookies on ChromeOS, see dedicated controller
// CookieSyncDataTypeController. The tests in this file are not prepared
// to handle selectable datatypes which are disabled by default via their
// DataTypeController, so we have to enable the pref for them to pass.
// TODO(crbug.com/378091718): think if we can also make the tests pass with
// this preference disabled.
GetProfile(0)->GetPrefs()->SetBoolean(chromeos::prefs::kFloatingSsoEnabled,
true);
#endif // BUILDFLAG(IS_CHROMEOS)
ASSERT_TRUE(
GetClient(0)->SetupSyncWithCustomSettings(base::BindLambdaForTesting(
[all_types_enabled](syncer::SyncUserSettings* user_settings) {
user_settings->SetSelectedTypes(all_types_enabled, {});
#if !BUILDFLAG(IS_CHROMEOS)
user_settings->SetInitialSyncFeatureSetupComplete(
syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM);
#endif // !BUILDFLAG(IS_CHROMEOS)
})));
registered_data_types_ = GetSyncService(0)->GetRegisteredDataTypesForTest();
multi_grouped_types_ = MultiGroupTypes(registered_data_types_);
registered_selectable_types_ = GetRegisteredSelectableTypes(0);
}
DataTypeSet ResolveGroup(UserSelectableType type) {
DataTypeSet grouped_types = syncer::UserSelectableTypeToAllDataTypes(type);
grouped_types.RetainAll(registered_data_types_);
return grouped_types;
}
DataTypeSet WithoutMultiTypes(const DataTypeSet& input) {
return Difference(input, multi_grouped_types_);
}
DataTypeSet registered_data_types_;
DataTypeSet multi_grouped_types_;
UserSelectableTypeSet registered_selectable_types_;
private:
fake_server::EntityBuilderFactory entity_builder_factory_;
};
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, PRE_EnableAndRestart) {
GetUpdatesRequestRecorder get_updates_recorder(GetFakeServer());
SetupTest(/*all_types_enabled=*/true);
// Commit-only types don't issue GetUpdates (by definition) and supervised
// user types are also excluded in this test, because the account being used
// isn't supervised. Finally, a few types aren't launched so they should also
// be excluded.
const DataTypeSet types_without_updates =
Union(syncer::CommitOnlyTypes(),
{syncer::SUPERVISED_USER_SETTINGS, syncer::PLUS_ADDRESS,
syncer::PLUS_ADDRESS_SETTING});
// High priority types in this test are a subset of
// syncer::HighPriorityUserTypes(), excluding those identified earlier.
const DataTypeSet high_priority_types = Difference(
Intersection(syncer::HighPriorityUserTypes(), registered_data_types_),
types_without_updates);
// Similarly, low priority types in this test are a subset of
// syncer::LowPriorityUserTypes().
const DataTypeSet low_priority_types = Difference(
Intersection(syncer::LowPriorityUserTypes(), registered_data_types_),
types_without_updates);
// All other types have regular priority.
const DataTypeSet regular_priority_types = Difference(
registered_data_types_,
Union(types_without_updates, Union(syncer::HighPriorityUserTypes(),
syncer::LowPriorityUserTypes())));
// Initial sync takes four GetUpdates requests to the server to download:
// 1. Control types (NIGORI).
// 2. High-priority user types.
// 3. Regular-priority types.
// 4. Low-priority types.
//
// The sequence of GetUpdatesOrigin below matches what is empirically
// observed outside tests when Sync is turned on during desktop FRE using the
// advanced sync setup flow (open settings), which is also what tests mimic.
EXPECT_THAT(
get_updates_recorder.recorded_requests(),
ElementsAre(MatchesGetUpdatesRequest(sync_pb::SyncEnums::NEW_CLIENT,
syncer::ControlTypes()),
MatchesGetUpdatesRequest(
sync_pb::SyncEnums::NEW_CLIENT,
Union(syncer::ControlTypes(), high_priority_types)),
MatchesGetUpdatesRequest(
sync_pb::SyncEnums::NEW_CLIENT,
Union(syncer::ControlTypes(), regular_priority_types)),
MatchesGetUpdatesRequest(
sync_pb::SyncEnums::NEW_CLIENT,
Union(syncer::ControlTypes(), low_priority_types))));
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableAndRestart) {
GetUpdatesRequestRecorder get_updates_recorder(GetFakeServer());
ASSERT_TRUE(SetupClients());
EXPECT_TRUE(GetClient(0)->AwaitEngineInitialization());
for (UserSelectableType type : UserSelectableTypeSet::All()) {
for (DataType data_type : ResolveGroup(type)) {
EXPECT_TRUE(IsDataTypeActive(data_type))
<< " for " << DataTypeToDebugString(data_type);
}
}
EXPECT_THAT(get_updates_recorder.recorded_requests(), IsEmpty());
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableOneAtATime) {
// Setup sync with no enabled types.
SetupTest(/*all_types_enabled=*/false);
// Certain datatypes like SESSIONS can be configured by multiple
// user-selectable types. Hence, enabling a new user-selectable type doesn't
// necessarily mean that the datatype (SESSIONS) will be newly-configured. In
// this particular test, this influences whether the engine will issue UMA
// corresponding to the configuration cycle.
syncer::DataTypeSet previously_active_types;
for (UserSelectableType type : registered_selectable_types_) {
const DataTypeSet grouped_types = ResolveGroup(type);
for (DataType single_grouped_type : WithoutMultiTypes(grouped_types)) {
ASSERT_FALSE(IsDataTypeActive(single_grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
base::HistogramTester histogram_tester;
EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
for (DataType grouped_type : grouped_types) {
EXPECT_TRUE(IsDataTypeActive(grouped_type))
<< " for " << GetUserSelectableTypeName(type);
if (!syncer::ProtocolTypes().Has(grouped_type) ||
syncer::CommitOnlyTypes().Has(grouped_type)) {
EXPECT_EQ(0,
histogram_tester.GetBucketCount(
"Sync.PostedDataTypeGetUpdatesRequest",
static_cast<int>(DataTypeHistogramValue(grouped_type))))
<< " for " << DataTypeToDebugString(grouped_type);
} else if (previously_active_types.Has(grouped_type)) {
// If the type was already configured, no additional configuration cycle
// is expected, but it's impossible to rule out that the type has issued
// a GetUpdates request for different reasons (since it's actively
// sync-ing).
} else {
EXPECT_NE(0,
histogram_tester.GetBucketCount(
"Sync.PostedDataTypeGetUpdatesRequest",
static_cast<int>(DataTypeHistogramValue(grouped_type))))
<< " for " << DataTypeToDebugString(grouped_type);
}
previously_active_types.Put(grouped_type);
}
}
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, DisableOneAtATime) {
// Setup sync with no disabled types.
SetupTest(/*all_types_enabled=*/true);
for (UserSelectableType type : registered_selectable_types_) {
const DataTypeSet grouped_types = ResolveGroup(type);
for (DataType grouped_type : grouped_types) {
ASSERT_TRUE(IsDataTypeActive(grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
for (DataType single_grouped_type : WithoutMultiTypes(grouped_types)) {
EXPECT_FALSE(IsDataTypeActive(single_grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
}
// Lastly make sure that all the multi grouped times are all gone, since we
// did not check these after disabling inside the above loop.
for (DataType multi_grouped_type : multi_grouped_types_) {
EXPECT_FALSE(IsDataTypeActive(multi_grouped_type))
<< " for " << DataTypeToDebugString(multi_grouped_type);
}
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
FastEnableDisableOneAtATime) {
// Setup sync with no enabled types.
SetupTest(/*all_types_enabled=*/false);
for (UserSelectableType type : registered_selectable_types_) {
const DataTypeSet grouped_types = ResolveGroup(type);
const DataTypeSet single_grouped_types = WithoutMultiTypes(grouped_types);
for (DataType single_grouped_type : single_grouped_types) {
ASSERT_FALSE(IsDataTypeActive(single_grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
// Enable and then disable immediately afterwards, before the datatype has
// had the chance to finish startup (which usually involves task posting).
EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
for (DataType single_grouped_type : single_grouped_types) {
EXPECT_FALSE(IsDataTypeActive(single_grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
}
// Lastly make sure that all the multi grouped times are all gone, since we
// did not check these after disabling inside the above loop.
for (DataType multi_grouped_type : multi_grouped_types_) {
EXPECT_FALSE(IsDataTypeActive(multi_grouped_type))
<< " for " << DataTypeToDebugString(multi_grouped_type);
}
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
FastDisableEnableOneAtATime) {
// Setup sync with no disabled types.
SetupTest(/*all_types_enabled=*/true);
for (UserSelectableType type : registered_selectable_types_) {
const DataTypeSet grouped_types = ResolveGroup(type);
for (DataType grouped_type : grouped_types) {
ASSERT_TRUE(IsDataTypeActive(grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
// Disable and then reenable immediately afterwards, before the datatype has
// had the chance to stop fully (which usually involves task posting).
EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
for (DataType grouped_type : grouped_types) {
EXPECT_TRUE(IsDataTypeActive(grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
}
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
FastEnableDisableEnableOneAtATime) {
// Setup sync with no enabled types.
SetupTest(/*all_types_enabled=*/false);
for (UserSelectableType type : registered_selectable_types_) {
const DataTypeSet single_grouped_types =
WithoutMultiTypes(ResolveGroup(type));
for (DataType single_grouped_type : single_grouped_types) {
ASSERT_FALSE(IsDataTypeActive(single_grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
// Fast enable-disable-enable sequence, before the datatype has had the
// chance to transition fully across states (usually involves task posting).
EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
EXPECT_TRUE(GetClient(0)->DisableSyncForType(type));
EXPECT_TRUE(GetClient(0)->EnableSyncForType(type));
for (DataType single_grouped_type : single_grouped_types) {
EXPECT_TRUE(IsDataTypeActive(single_grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
}
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, EnableDisable) {
SetupTest(/*all_types_enabled=*/false);
// Enable all, and then disable immediately afterwards, before datatypes
// have had the chance to finish startup (which usually involves task
// posting).
ASSERT_TRUE(GetClient(0)->EnableSyncForRegisteredDatatypes());
ASSERT_TRUE(GetClient(0)->DisableSyncForAllDatatypes());
for (UserSelectableType type : UserSelectableTypeSet::All()) {
for (DataType grouped_type : ResolveGroup(type)) {
EXPECT_FALSE(IsDataTypeActive(grouped_type))
<< " for " << GetUserSelectableTypeName(type);
}
}
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, FastEnableDisableEnable) {
SetupTest(/*all_types_enabled=*/false);
// Enable all, and then disable+reenable immediately afterwards, before
// datatypes have had the chance to finish startup (which usually involves
// task posting).
ASSERT_TRUE(GetClient(0)->EnableSyncForRegisteredDatatypes());
ASSERT_TRUE(GetClient(0)->DisableSyncForAllDatatypes());
ASSERT_TRUE(GetClient(0)->EnableSyncForRegisteredDatatypes());
for (UserSelectableType type : UserSelectableTypeSet::All()) {
for (DataType data_type : ResolveGroup(type)) {
EXPECT_TRUE(IsDataTypeActive(data_type))
<< " for " << DataTypeToDebugString(data_type);
}
}
}
// This test makes sure that after a signout, Sync data gets redownloaded
// when Sync is started again. This does not actually verify that the data is
// gone from disk (which seems infeasible); it's mostly here as a baseline for
// the following tests.
//
// ChromeOS does not support signing out of a primary account.
#if !BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest, RedownloadsAfterSignout) {
ASSERT_TRUE(SetupClients());
ASSERT_FALSE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
GURL(kSyncedBookmarkURL)));
// Create a bookmark on the server, then turn on Sync on the client.
InjectSyncedBookmark();
// Disable any LowPriorityUserTypes() (in practice, history, and incoming
// password sharing invitations controlled by Passwords data type): This test
// inspects the last-sync-cycle state. If low-prio types are active, they
// cause another (uninteresting) cycle and mess up the stats we're interested
// in.
// TODO(crbug.com/40215602): Rewrite this test to avoid disabling low priotiy
// types.
ASSERT_TRUE(GetClient(0)->SetupSyncWithCustomSettings(
base::BindOnce([](syncer::SyncUserSettings* settings) {
UserSelectableTypeSet types = settings->GetRegisteredSelectableTypes();
types.Remove(syncer::UserSelectableType::kHistory);
types.Remove(syncer::UserSelectableType::kPasswords);
settings->SetSelectedTypes(/*sync_everything=*/false, types);
#if !BUILDFLAG(IS_CHROMEOS)
settings->SetInitialSyncFeatureSetupComplete(
syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM);
#endif // !BUILDFLAG(IS_CHROMEOS)
})));
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_FALSE(GetSyncService(0)->GetActiveDataTypes().HasAny(
syncer::LowPriorityUserTypes()));
// Make sure the bookmark got synced down.
ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
GURL(kSyncedBookmarkURL)));
// Note: The response may also contain permanent nodes, so we can't check the
// exact count.
const int initial_updates_downloaded = GetNumUpdatesDownloadedInLastCycle();
ASSERT_GT(initial_updates_downloaded, 0);
// Stop and restart Sync.
GetClient(0)->SignOutPrimaryAccount();
ASSERT_TRUE(GetClient(0)->SetupSync());
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
// Everything should have been redownloaded.
ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
GURL(kSyncedBookmarkURL)));
EXPECT_EQ(GetNumUpdatesDownloadedInLastCycle(), initial_updates_downloaded);
}
#endif // !BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
DoesNotRedownloadAfterSyncUnpaused) {
ASSERT_TRUE(SetupClients());
ASSERT_FALSE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
GURL(kSyncedBookmarkURL)));
// Create a bookmark on the server, then turn on Sync on the client.
InjectSyncedBookmark();
// Disable any LowPriorityUserTypes() (in practice, history, and incoming
// password sharing invitations controlled by Passwords data type): This test
// inspects the last-sync-cycle state. If low-prio types are active, they
// cause another (uninteresting) cycle and mess up the stats we're interested
// in.
// TODO(crbug.com/40215602): Rewrite this test to avoid disabling low priotiy
// types.
ASSERT_TRUE(GetClient(0)->SetupSyncWithCustomSettings(
base::BindOnce([](syncer::SyncUserSettings* settings) {
UserSelectableTypeSet types = settings->GetRegisteredSelectableTypes();
types.Remove(syncer::UserSelectableType::kHistory);
types.Remove(syncer::UserSelectableType::kPasswords);
settings->SetSelectedTypes(/*sync_everything=*/false, types);
#if !BUILDFLAG(IS_CHROMEOS)
settings->SetInitialSyncFeatureSetupComplete(
syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM);
#endif // !BUILDFLAG(IS_CHROMEOS)
})));
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
ASSERT_FALSE(GetSyncService(0)->GetActiveDataTypes().HasAny(
syncer::LowPriorityUserTypes()));
// Make sure the bookmark got synced down.
ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
GURL(kSyncedBookmarkURL)));
// Note: The response may also contain permanent nodes, so we can't check the
// exact count.
ASSERT_GT(GetNumUpdatesDownloadedInLastCycle(), 0);
// Pause sync.
GetClient(0)->EnterSyncPausedStateForPrimaryAccount();
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive());
// Resume sync.
base::HistogramTester histogram_tester;
GetClient(0)->ExitSyncPausedStateForPrimaryAccount();
ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureActive());
// The bookmark should still be there, *without* having been redownloaded.
ASSERT_TRUE(SetupSync());
ASSERT_TRUE(bookmarks_helper::GetBookmarkModel(0)->IsBookmarked(
GURL(kSyncedBookmarkURL)));
EXPECT_EQ(0, histogram_tester.GetBucketCount(
"Sync.DataTypeEntityChange.BOOKMARK",
syncer::DataTypeEntityChange::kRemoteNonInitialUpdate));
EXPECT_EQ(0, histogram_tester.GetBucketCount(
"Sync.DataTypeEntityChange.BOOKMARK",
syncer::DataTypeEntityChange::kRemoteInitialUpdate));
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientTest,
DoesNotClearPrefsWithKeepData) {
SetupTest(/*all_types_enabled=*/true);
syncer::SyncTransportDataPrefs prefs(
GetProfile(0)->GetPrefs(),
GetClient(0)->GetGaiaIdHashForPrimaryAccount());
const std::string cache_guid = prefs.GetCacheGuid();
ASSERT_NE("", cache_guid);
GetClient(0)->EnterSyncPausedStateForPrimaryAccount();
EXPECT_EQ(cache_guid, prefs.GetCacheGuid());
}
class EnableDisableSingleClientSelfNotifyTest
: public EnableDisableSingleClientTest {
public:
// UpdatedProgressMarkerChecker relies on the 'self-notify' feature.
bool TestUsesSelfNotifications() override { return true; }
sync_pb::ClientToServerMessage TriggerGetUpdatesCycleAndWait() {
TriggerSyncForDataTypes(0, {syncer::BOOKMARKS});
EXPECT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait());
sync_pb::ClientToServerMessage message;
EXPECT_TRUE(GetFakeServer()->GetLastGetUpdatesMessage(&message));
return message;
}
};
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientSelfNotifyTest,
PRE_ResendsBagOfChips) {
sync_pb::ChipBag bag_of_chips;
bag_of_chips.set_server_chips(kTestServerChips);
ASSERT_FALSE(base::IsStringUTF8(bag_of_chips.SerializeAsString()));
GetFakeServer()->SetBagOfChips(bag_of_chips);
SetupTest(/*all_types_enabled=*/true);
syncer::SyncTransportDataPrefs prefs(
GetProfile(0)->GetPrefs(),
GetClient(0)->GetGaiaIdHashForPrimaryAccount());
EXPECT_EQ(bag_of_chips.SerializeAsString(), prefs.GetBagOfChips());
sync_pb::ClientToServerMessage message = TriggerGetUpdatesCycleAndWait();
EXPECT_TRUE(message.has_bag_of_chips());
EXPECT_EQ(kTestServerChips, message.bag_of_chips().server_chips());
}
IN_PROC_BROWSER_TEST_F(EnableDisableSingleClientSelfNotifyTest,
ResendsBagOfChips) {
ASSERT_TRUE(SetupClients());
syncer::SyncTransportDataPrefs prefs(
GetProfile(0)->GetPrefs(),
GetClient(0)->GetGaiaIdHashForPrimaryAccount());
ASSERT_NE("", prefs.GetBagOfChips());
ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
sync_pb::ClientToServerMessage message = TriggerGetUpdatesCycleAndWait();
EXPECT_TRUE(message.has_bag_of_chips());
EXPECT_EQ(kTestServerChips, message.bag_of_chips().server_chips());
}
} // namespace