blob: accb0b6433017c72998472fd5205a04503691571 [file] [log] [blame]
// Copyright 2018 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 <stdint.h>
#include "base/macros.h"
#include "chrome/browser/consent_auditor/consent_auditor_factory.h"
#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
#include "chrome/browser/sync/test/integration/status_change_checker.h"
#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "components/consent_auditor/consent_auditor.h"
#include "components/sync/driver/sync_driver_switches.h"
#include "components/sync/protocol/user_consent_specifics.pb.h"
using consent_auditor::ConsentStatus;
using consent_auditor::Feature;
using fake_server::FakeServer;
using sync_pb::SyncEntity;
using sync_pb::UserConsentSpecifics;
using sync_pb::UserConsentTypes;
using SyncConsent = sync_pb::UserConsentTypes::SyncConsent;
namespace {
std::string GetAccountId() {
#if defined(OS_CHROMEOS)
// TODO(vitaliii): Unify the two, because it takes ages to debug and
// impossible to discover otherwise.
return "user@gmail.com";
#else
return "gaia_id_for_user_gmail.com";
#endif
}
class UserConsentEqualityChecker : public SingleClientStatusChangeChecker {
public:
UserConsentEqualityChecker(
browser_sync::ProfileSyncService* service,
FakeServer* fake_server,
std::vector<UserConsentSpecifics> expected_specifics)
: SingleClientStatusChangeChecker(service), fake_server_(fake_server) {
for (const UserConsentSpecifics& specifics : expected_specifics) {
expected_specifics_.insert(std::pair<int64_t, UserConsentSpecifics>(
specifics.consent_case(), specifics));
}
}
bool IsExitConditionSatisfied() override {
std::vector<SyncEntity> entities =
fake_server_->GetSyncEntitiesByModelType(syncer::USER_CONSENTS);
// |entities.size()| is only going to grow, if |entities.size()| ever
// becomes bigger then all hope is lost of passing, stop now.
EXPECT_GE(expected_specifics_.size(), entities.size());
if (expected_specifics_.size() > entities.size()) {
return false;
}
// Number of events on server matches expected, exit condition can be
// satisfied. Let's verify that content matches as well. It is safe to
// modify |expected_specifics_|.
for (const SyncEntity& entity : entities) {
UserConsentSpecifics server_specifics = entity.specifics().user_consent();
auto iter = expected_specifics_.find(server_specifics.consent_case());
EXPECT_TRUE(expected_specifics_.end() != iter);
if (expected_specifics_.end() == iter) {
return false;
}
EXPECT_EQ(iter->second.account_id(), server_specifics.account_id());
expected_specifics_.erase(iter);
}
return true;
}
std::string GetDebugMessage() const override {
return "Waiting server side USER_CONSENTS to match expected.";
}
private:
FakeServer* fake_server_;
// TODO(markusheintz): User a string with the serialized proto instead of an
// int. The requires creating better expectations with a proper creation
// time.
std::multimap<int64_t, UserConsentSpecifics> expected_specifics_;
DISALLOW_COPY_AND_ASSIGN(UserConsentEqualityChecker);
};
class SingleClientUserConsentsSyncTest : public SyncTest {
public:
SingleClientUserConsentsSyncTest() : SyncTest(SINGLE_CLIENT) {
DisableVerifier();
}
bool ExpectUserConsents(
std::vector<UserConsentSpecifics> expected_specifics) {
return UserConsentEqualityChecker(GetSyncService(0), GetFakeServer(),
expected_specifics)
.Wait();
}
private:
DISALLOW_COPY_AND_ASSIGN(SingleClientUserConsentsSyncTest);
};
IN_PROC_BROWSER_TEST_F(SingleClientUserConsentsSyncTest, ShouldSubmit) {
ASSERT_TRUE(SetupSync());
ASSERT_EQ(0u, GetFakeServer()
->GetSyncEntitiesByModelType(syncer::USER_CONSENTS)
.size());
consent_auditor::ConsentAuditor* consent_service =
ConsentAuditorFactory::GetForProfile(GetProfile(0));
UserConsentSpecifics specifics;
specifics.mutable_sync_consent()->set_confirmation_grd_id(1);
specifics.set_account_id(GetAccountId());
SyncConsent sync_consent;
sync_consent.set_confirmation_grd_id(1);
sync_consent.set_status(UserConsentTypes::GIVEN);
consent_service->RecordSyncConsent(GetAccountId(), sync_consent);
EXPECT_TRUE(ExpectUserConsents({specifics}));
}
IN_PROC_BROWSER_TEST_F(
SingleClientUserConsentsSyncTest,
ShouldPreserveConsentsOnDisableSyncAndResubmitWhenReenabled) {
UserConsentSpecifics specifics;
specifics.mutable_sync_consent()->set_confirmation_grd_id(1);
// Account id may be compared to the synced account, thus, we need them to
// match.
specifics.set_account_id(GetAccountId());
ASSERT_TRUE(SetupSync());
consent_auditor::ConsentAuditor* consent_service =
ConsentAuditorFactory::GetForProfile(GetProfile(0));
SyncConsent sync_consent;
sync_consent.set_confirmation_grd_id(1);
sync_consent.set_status(UserConsentTypes::GIVEN);
consent_service->RecordSyncConsent(GetAccountId(), sync_consent);
GetClient(0)->StopSyncServiceAndClearData();
ASSERT_TRUE(GetClient(0)->StartSyncService());
EXPECT_TRUE(ExpectUserConsents({specifics}));
}
IN_PROC_BROWSER_TEST_F(SingleClientUserConsentsSyncTest,
ShouldPreserveConsentsLoggedBeforeSyncSetup) {
SyncConsent consent1;
consent1.set_confirmation_grd_id(1);
consent1.set_status(UserConsentTypes::GIVEN);
SyncConsent consent2;
consent2.set_confirmation_grd_id(2);
consent2.set_status(UserConsentTypes::GIVEN);
UserConsentSpecifics specifics1;
*specifics1.mutable_sync_consent() = consent1;
specifics1.set_account_id(GetAccountId());
UserConsentSpecifics specifics2;
*specifics2.mutable_sync_consent() = consent2;
specifics2.set_account_id(GetAccountId());
// Set up the clients (profiles), but do *not* set up Sync yet.
ASSERT_TRUE(SetupClients());
// Now we can already record a consent, but of course it won't make it to the
// server yet.
consent_auditor::ConsentAuditor* consent_service =
ConsentAuditorFactory::GetForProfile(GetProfile(0));
consent_service->RecordSyncConsent(GetAccountId(), consent1);
EXPECT_TRUE(ExpectUserConsents({}));
// Once we turn on Sync, the consent gets uploaded.
ASSERT_TRUE(SetupSync());
EXPECT_TRUE(ExpectUserConsents({specifics1}));
// Another consent can also be added now.
consent_service->RecordSyncConsent(GetAccountId(), consent2);
EXPECT_TRUE(ExpectUserConsents({specifics1, specifics2}));
}
// ChromeOS does not support late signin after profile creation, so the test
// below does not apply, at least in the current form.
#if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(SingleClientUserConsentsSyncTest,
ShouldSubmitIfSignedInAlthoughFullSyncNotEnabled) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(switches::kSyncStandaloneTransport);
// We avoid calling SetupSync(), because we don't want to turn on full sync,
// only sign in such that the standalone transport starts.
ASSERT_TRUE(SetupClients());
ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
ASSERT_TRUE(GetClient(0)->AwaitEngineInitialization());
ASSERT_TRUE(AwaitQuiescence());
ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureActive())
<< "Full sync should be disabled";
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
GetSyncService(0)->GetTransportState());
ASSERT_TRUE(
GetSyncService(0)->GetActiveDataTypes().Has(syncer::USER_CONSENTS));
SyncConsent sync_consent;
sync_consent.set_confirmation_grd_id(1);
sync_consent.set_status(UserConsentTypes::GIVEN);
ConsentAuditorFactory::GetForProfile(GetProfile(0))
->RecordSyncConsent(GetAccountId(), sync_consent);
UserConsentSpecifics specifics;
SyncConsent* expected_sync_consent = specifics.mutable_sync_consent();
expected_sync_consent->set_confirmation_grd_id(1);
expected_sync_consent->set_status(UserConsentTypes::GIVEN);
// Account id may be compared to the synced account, thus, we need them to
// match.
specifics.set_account_id(GetAccountId());
EXPECT_TRUE(ExpectUserConsents({specifics}));
}
#endif // !defined(OS_CHROMEOS)
} // namespace