blob: bd309759d743b4ea541f8fe99112dc938f712ca9 [file] [log] [blame]
// Copyright 2015 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 "chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl.h"
#include <memory>
#include <string>
#include <utility>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/cryptohome/system_salt_getter.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "components/invalidation/impl/fake_invalidation_handler.h"
#include "components/invalidation/impl/fake_invalidation_service.h"
#include "components/invalidation/impl/profile_invalidation_provider.h"
#include "components/invalidation/impl/ticl_invalidation_service.h"
#include "components/invalidation/public/invalidation_service.h"
#include "components/invalidation/public/invalidator_state.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
namespace {
const char kAffiliatedUserID1[] = "test_1@example.com";
const char kAffiliatedUserID2[] = "test_2@example.com";
const char kUnaffiliatedUserID[] = "test@other_domain.test";
std::unique_ptr<KeyedService> BuildProfileInvalidationProvider(
content::BrowserContext* context) {
std::unique_ptr<invalidation::FakeInvalidationService> invalidation_service(
new invalidation::FakeInvalidationService);
invalidation_service->SetInvalidatorState(
syncer::TRANSIENT_INVALIDATION_ERROR);
return std::make_unique<invalidation::ProfileInvalidationProvider>(
std::move(invalidation_service));
}
} // namespace
// A simple AffiliatedInvalidationServiceProvider::Consumer that registers a
// syncer::FakeInvalidationHandler with the invalidation::InvalidationService
// that is currently being made available.
class FakeConsumer : public AffiliatedInvalidationServiceProvider::Consumer {
public:
explicit FakeConsumer(AffiliatedInvalidationServiceProviderImpl* provider);
~FakeConsumer() override;
// AffiliatedInvalidationServiceProvider::Consumer:
void OnInvalidationServiceSet(
invalidation::InvalidationService* invalidation_service) override;
int GetAndClearInvalidationServiceSetCount();
const invalidation::InvalidationService* GetInvalidationService() const;
private:
AffiliatedInvalidationServiceProviderImpl* provider_;
syncer::FakeInvalidationHandler invalidation_handler_;
int invalidation_service_set_count_ = 0;
invalidation::InvalidationService* invalidation_service_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeConsumer);
};
class AffiliatedInvalidationServiceProviderImplTest : public testing::Test {
public:
AffiliatedInvalidationServiceProviderImplTest();
// testing::Test:
void SetUp() override;
void TearDown() override;
// Both functions don't pass ownership of the profile. The Profile is owned
// by the global ProfileManager.
Profile* LogInAndReturnAffiliatedProfile(const std::string& user_id);
Profile* LogInAndReturnNonAffiliatedProfile(const std::string& user_id);
// Logs in as an affiliated user and indicates that the per-profile
// invalidation service for this user connected. Verifies that this
// invalidation service is made available to the |consumer_| and the
// device-global invalidation service is destroyed.
void LogInAsAffiliatedUserAndConnectInvalidationService();
// Logs in as an unaffiliated user and indicates that the per-profile
// invalidation service for this user connected. Verifies that this
// invalidation service is ignored and the device-global invalidation service
// is not destroyed.
void LogInAsUnaffiliatedUserAndConnectInvalidationService();
// Indicates that the device-global invalidation service connected. Verifies
// that the |consumer_| is informed about this.
void ConnectDeviceGlobalInvalidationService();
// Indicates that the logged-in user's per-profile invalidation service
// disconnected. Verifies that the |consumer_| is informed about this and a
// device-global invalidation service is created.
void DisconnectPerProfileInvalidationService();
invalidation::FakeInvalidationService* GetProfileInvalidationService(
Profile* profile,
bool create);
protected:
// Ownership is not passed. The Profile is owned by the global ProfileManager.
Profile* LogInAndReturnProfile(const std::string& user_id,
bool is_affiliated);
std::unique_ptr<AffiliatedInvalidationServiceProviderImpl> provider_;
std::unique_ptr<FakeConsumer> consumer_;
invalidation::TiclInvalidationService* device_invalidation_service_;
invalidation::FakeInvalidationService* profile_invalidation_service_;
private:
content::TestBrowserThreadBundle thread_bundle_;
chromeos::FakeChromeUserManager* fake_user_manager_;
user_manager::ScopedUserManager user_manager_enabler_;
chromeos::ScopedStubInstallAttributes install_attributes_;
std::unique_ptr<chromeos::ScopedTestDeviceSettingsService>
test_device_settings_service_;
std::unique_ptr<chromeos::ScopedTestCrosSettings> test_cros_settings_;
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
test_shared_loader_factory_;
TestingProfileManager profile_manager_;
};
FakeConsumer::FakeConsumer(AffiliatedInvalidationServiceProviderImpl* provider)
: provider_(provider) {
provider_->RegisterConsumer(this);
}
FakeConsumer::~FakeConsumer() {
if (invalidation_service_) {
invalidation_service_->UnregisterInvalidationHandler(
&invalidation_handler_);
}
provider_->UnregisterConsumer(this);
EXPECT_EQ(0, invalidation_service_set_count_);
}
void FakeConsumer::OnInvalidationServiceSet(
invalidation::InvalidationService* invalidation_service) {
++invalidation_service_set_count_;
if (invalidation_service_) {
invalidation_service_->UnregisterInvalidationHandler(
&invalidation_handler_);
}
invalidation_service_ = invalidation_service;
if (invalidation_service_) {
// Regression test for http://crbug.com/455504: The |invalidation_service|
// was sometimes destroyed without notifying consumers and giving them a
// chance to unregister their invalidation handlers. Register an
// invalidation handler so that |invalidation_service| CHECK()s in its
// destructor if this regresses.
invalidation_service_->RegisterInvalidationHandler(&invalidation_handler_);
}
}
int FakeConsumer::GetAndClearInvalidationServiceSetCount() {
const int invalidation_service_set_count = invalidation_service_set_count_;
invalidation_service_set_count_ = 0;
return invalidation_service_set_count;
}
const invalidation::InvalidationService*
FakeConsumer::GetInvalidationService() const {
return invalidation_service_;
}
AffiliatedInvalidationServiceProviderImplTest::
AffiliatedInvalidationServiceProviderImplTest()
: device_invalidation_service_(nullptr),
profile_invalidation_service_(nullptr),
fake_user_manager_(new chromeos::FakeChromeUserManager),
user_manager_enabler_(base::WrapUnique(fake_user_manager_)),
install_attributes_(
chromeos::ScopedStubInstallAttributes::CreateCloudManaged(
"example.com",
"device_id")),
test_shared_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)),
profile_manager_(TestingBrowserProcess::GetGlobal()) {}
void AffiliatedInvalidationServiceProviderImplTest::SetUp() {
chromeos::SystemSaltGetter::Initialize();
chromeos::DBusThreadManager::Initialize();
ASSERT_TRUE(profile_manager_.SetUp());
test_device_settings_service_.reset(new
chromeos::ScopedTestDeviceSettingsService);
test_cros_settings_.reset(new chromeos::ScopedTestCrosSettings);
chromeos::DeviceOAuth2TokenServiceFactory::Initialize(
test_shared_loader_factory_);
invalidation::ProfileInvalidationProviderFactory::GetInstance()->
RegisterTestingFactory(BuildProfileInvalidationProvider);
provider_.reset(new AffiliatedInvalidationServiceProviderImpl);
}
void AffiliatedInvalidationServiceProviderImplTest::TearDown() {
consumer_.reset();
provider_->Shutdown();
provider_.reset();
test_shared_loader_factory_->Detach();
invalidation::ProfileInvalidationProviderFactory::GetInstance()->
RegisterTestingFactory(nullptr);
chromeos::DeviceOAuth2TokenServiceFactory::Shutdown();
chromeos::DBusThreadManager::Shutdown();
chromeos::SystemSaltGetter::Shutdown();
}
Profile*
AffiliatedInvalidationServiceProviderImplTest::LogInAndReturnAffiliatedProfile(
const std::string& user_id) {
return LogInAndReturnProfile(user_id, true);
}
Profile* AffiliatedInvalidationServiceProviderImplTest::
LogInAndReturnNonAffiliatedProfile(const std::string& user_id) {
return LogInAndReturnProfile(user_id, false);
}
Profile* AffiliatedInvalidationServiceProviderImplTest::LogInAndReturnProfile(
const std::string& user_id,
bool is_affiliated) {
fake_user_manager_->AddUserWithAffiliation(AccountId::FromUserEmail(user_id),
is_affiliated);
Profile* profile = profile_manager_.CreateTestingProfile(user_id);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
content::NotificationService::AllSources(),
content::Details<Profile>(profile));
return profile;
}
void AffiliatedInvalidationServiceProviderImplTest::
LogInAsAffiliatedUserAndConnectInvalidationService() {
// Log in as an affiliated user.
Profile* profile = LogInAndReturnAffiliatedProfile(kAffiliatedUserID1);
EXPECT_TRUE(profile);
// Verify that a per-profile invalidation service has been created.
profile_invalidation_service_ =
GetProfileInvalidationService(profile, false /* create */);
ASSERT_TRUE(profile_invalidation_service_);
// Verify that the device-global invalidation service still exists.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Indicate that the per-profile invalidation service has connected. Verify
// that the consumer is informed about this.
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
profile_invalidation_service_->SetInvalidatorState(
syncer::INVALIDATIONS_ENABLED);
EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(profile_invalidation_service_, consumer_->GetInvalidationService());
// Verify that the device-global invalidation service has been destroyed.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
}
void AffiliatedInvalidationServiceProviderImplTest::
LogInAsUnaffiliatedUserAndConnectInvalidationService() {
// Log in as an unaffiliated user.
Profile* profile = LogInAndReturnNonAffiliatedProfile(kUnaffiliatedUserID);
EXPECT_TRUE(profile);
// Verify that a per-profile invalidation service has been created.
profile_invalidation_service_ =
GetProfileInvalidationService(profile, false /* create */);
ASSERT_TRUE(profile_invalidation_service_);
// Verify that the device-global invalidation service still exists.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Indicate that the per-profile invalidation service has connected. Verify
// that the consumer is not called back.
profile_invalidation_service_->SetInvalidatorState(
syncer::INVALIDATIONS_ENABLED);
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
// Verify that the device-global invalidation service still exists.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
}
void AffiliatedInvalidationServiceProviderImplTest::
ConnectDeviceGlobalInvalidationService() {
// Verify that a device-global invalidation service has been created.
device_invalidation_service_ =
provider_->GetDeviceInvalidationServiceForTest();
ASSERT_TRUE(device_invalidation_service_);
// Indicate that the device-global invalidation service has connected. Verify
// that the consumer is informed about this.
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
device_invalidation_service_->OnInvalidatorStateChange(
syncer::INVALIDATIONS_ENABLED);
EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(device_invalidation_service_, consumer_->GetInvalidationService());
}
void AffiliatedInvalidationServiceProviderImplTest::
DisconnectPerProfileInvalidationService() {
ASSERT_TRUE(profile_invalidation_service_);
// Indicate that the per-profile invalidation service has disconnected. Verify
// that the consumer is informed about this.
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
profile_invalidation_service_->SetInvalidatorState(
syncer::INVALIDATION_CREDENTIALS_REJECTED);
EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(nullptr, consumer_->GetInvalidationService());
// Verify that a device-global invalidation service has been created.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
}
invalidation::FakeInvalidationService*
AffiliatedInvalidationServiceProviderImplTest::GetProfileInvalidationService(
Profile* profile, bool create) {
invalidation::ProfileInvalidationProvider* invalidation_provider =
static_cast<invalidation::ProfileInvalidationProvider*>(
invalidation::ProfileInvalidationProviderFactory::GetInstance()->
GetServiceForBrowserContext(profile, create));
if (!invalidation_provider)
return nullptr;
return static_cast<invalidation::FakeInvalidationService*>(
invalidation_provider->GetInvalidationService());
}
// No consumers are registered with the
// AffiliatedInvalidationServiceProviderImpl. Verifies that no device-global
// invalidation service is created, whether an affiliated user is logged in or
// not.
TEST_F(AffiliatedInvalidationServiceProviderImplTest, NoConsumers) {
// Verify that no device-global invalidation service has been created.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
// Log in as an affiliated user.
EXPECT_TRUE(LogInAndReturnAffiliatedProfile(kAffiliatedUserID1));
// Verify that no device-global invalidation service has been created.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
}
// Verifies that when no connected invalidation service is available for use,
// none is made available to consumers.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
NoInvalidationServiceAvailable) {
// Register a consumer. Verify that the consumer is not called back
// immediately as no connected invalidation service exists yet.
consumer_.reset(new FakeConsumer(provider_.get()));
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// Verifies that when no per-profile invalidation service belonging to an
// affiliated user is available, a device-global invalidation service is
// created. Further verifies that when the device-global invalidation service
// connects, it is made available to the consumer.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
UseDeviceInvalidationService) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Indicate that the device-global invalidation service connected. Verify that
// that the consumer is informed about this.
ConnectDeviceGlobalInvalidationService();
// Indicate that the device-global invalidation service has disconnected.
// Verify that the consumer is informed about this.
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
device_invalidation_service_->OnInvalidatorStateChange(
syncer::INVALIDATION_CREDENTIALS_REJECTED);
EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(nullptr, consumer_->GetInvalidationService());
// Verify that the device-global invalidation service still exists.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// Verifies that when a per-profile invalidation service belonging to an
// affiliated user connects, it is made available to the consumer.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
UseAffiliatedProfileInvalidationService) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Verify that a device-global invalidation service has been created.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Log in as an affiliated user and indicate that the per-profile invalidation
// service for this user connected. Verify that this invalidation service is
// made available to the |consumer_| and the device-global invalidation
// service is destroyed.
LogInAsAffiliatedUserAndConnectInvalidationService();
// Indicate that the logged-in user's per-profile invalidation service
// disconnected. Verify that the consumer is informed about this and a
// device-global invalidation service is created.
DisconnectPerProfileInvalidationService();
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// Verifies that when a per-profile invalidation service belonging to an
// unaffiliated user connects, it is ignored.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
DoNotUseUnaffiliatedProfileInvalidationService) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Verify that a device-global invalidation service has been created.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Log in as an unaffiliated user and indicate that the per-profile
// invalidation service for this user connected. Verify that this invalidation
// service is ignored and the device-global invalidation service is not
// destroyed.
LogInAsUnaffiliatedUserAndConnectInvalidationService();
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// A device-global invalidation service exists, is connected and is made
// available to the consumer. Verifies that when a per-profile invalidation
// service belonging to an affiliated user connects, it is made available to the
// consumer instead and the device-global invalidation service is destroyed.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
SwitchToAffiliatedProfileInvalidationService) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Indicate that the device-global invalidation service connected. Verify that
// that the consumer is informed about this.
ConnectDeviceGlobalInvalidationService();
// Log in as an affiliated user and indicate that the per-profile invalidation
// service for this user connected. Verify that this invalidation service is
// made available to the |consumer_| and the device-global invalidation
// service is destroyed.
LogInAsAffiliatedUserAndConnectInvalidationService();
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// A device-global invalidation service exists, is connected and is made
// available to the consumer. Verifies that when a per-profile invalidation
// service belonging to an unaffiliated user connects, it is ignored and the
// device-global invalidation service continues to be made available to the
// consumer.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
DoNotSwitchToUnaffiliatedProfileInvalidationService) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Indicate that the device-global invalidation service connected. Verify that
// that the consumer is informed about this.
ConnectDeviceGlobalInvalidationService();
// Log in as an unaffiliated user and indicate that the per-profile
// invalidation service for this user connected. Verify that this invalidation
// service is ignored and the device-global invalidation service is not
// destroyed.
LogInAsUnaffiliatedUserAndConnectInvalidationService();
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// A per-profile invalidation service belonging to an affiliated user exists, is
// connected and is made available to the consumer. Verifies that when the
// per-profile invalidation service disconnects, a device-global invalidation
// service is created. Further verifies that when the device-global invalidation
// service connects, it is made available to the consumer.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
SwitchToDeviceInvalidationService) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Verify that a device-global invalidation service has been created.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Log in as an affiliated user and indicate that the per-profile invalidation
// service for this user connected. Verify that this invalidation service is
// made available to the |consumer_| and the device-global invalidation
// service is destroyed.
LogInAsAffiliatedUserAndConnectInvalidationService();
// Indicate that the logged-in user's per-profile invalidation service
// disconnected. Verify that the consumer is informed about this and a
// device-global invalidation service is created.
DisconnectPerProfileInvalidationService();
// Indicate that the device-global invalidation service connected. Verify that
// that the consumer is informed about this.
ConnectDeviceGlobalInvalidationService();
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// A per-profile invalidation service belonging to a first affiliated user
// exists, is connected and is made available to the consumer. A per-profile
// invalidation service belonging to a second affiliated user also exists and is
// connected. Verifies that when the per-profile invalidation service belonging
// to the first user disconnects, the per-profile invalidation service belonging
// to the second user is made available to the consumer instead.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
SwitchBetweenAffiliatedProfileInvalidationServices) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Verify that a device-global invalidation service has been created.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Log in as a first affiliated user and indicate that the per-profile
// invalidation service for this user connected. Verify that this invalidation
// service is made available to the |consumer_| and the device-global
// invalidation service is destroyed.
LogInAsAffiliatedUserAndConnectInvalidationService();
// Log in as a second affiliated user.
Profile* second_profile = LogInAndReturnAffiliatedProfile(kAffiliatedUserID2);
EXPECT_TRUE(second_profile);
// Verify that the device-global invalidation service still does not exist.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
// Verify that a per-profile invalidation service for the second user has been
// created.
invalidation::FakeInvalidationService* second_profile_invalidation_service =
GetProfileInvalidationService(second_profile, false /* create */);
ASSERT_TRUE(second_profile_invalidation_service);
// Indicate that the second user's per-profile invalidation service has
// connected. Verify that the consumer is not called back.
second_profile_invalidation_service->SetInvalidatorState(
syncer::INVALIDATIONS_ENABLED);
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
// Indicate that the first user's per-profile invalidation service has
// disconnected. Verify that the consumer is informed that the second user's
// per-profile invalidation service should be used instead of the first
// user's.
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
profile_invalidation_service_->SetInvalidatorState(
syncer::INVALIDATION_CREDENTIALS_REJECTED);
EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(second_profile_invalidation_service,
consumer_->GetInvalidationService());
// Verify that the device-global invalidation service still does not exist.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// A device-global invalidation service exists, is connected and is made
// available to the consumer. Verifies that when a second consumer registers,
// the device-global invalidation service is made available to it as well.
// Further verifies that when the first consumer unregisters, the device-global
// invalidation service is not destroyed and remains available to the second
// consumer. Further verifies that when the second consumer also unregisters,
// the device-global invalidation service is destroyed.
TEST_F(AffiliatedInvalidationServiceProviderImplTest, MultipleConsumers) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Indicate that the device-global invalidation service connected. Verify that
// that the consumer is informed about this.
ConnectDeviceGlobalInvalidationService();
// Register a second consumer. Verify that the consumer is called back
// immediately as a connected invalidation service is available.
std::unique_ptr<FakeConsumer> second_consumer(
new FakeConsumer(provider_.get()));
EXPECT_EQ(1, second_consumer->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(device_invalidation_service_,
second_consumer->GetInvalidationService());
// Unregister the first consumer.
consumer_.reset();
// Verify that the device-global invalidation service still exists.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Unregister the second consumer.
second_consumer.reset();
// Verify that the device-global invalidation service has been destroyed.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// A per-profile invalidation service belonging to a first affiliated user
// exists, is connected and is made available to the consumer. Verifies that
// when the provider is shut down, the consumer is informed that no
// invalidation service is available for use anymore. Also verifies that no
// device-global invalidation service is created and a per-profile invalidation
// service belonging to a second affiliated user that subsequently connects is
// ignored.
TEST_F(AffiliatedInvalidationServiceProviderImplTest, NoServiceAfterShutdown) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Verify that a device-global invalidation service has been created.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Log in as a first affiliated user and indicate that the per-profile
// invalidation service for this user connected. Verify that this invalidation
// service is made available to the |consumer_| and the device-global
// invalidation service is destroyed.
LogInAsAffiliatedUserAndConnectInvalidationService();
// Shut down the |provider_|. Verify that the |consumer_| is informed that no
// invalidation service is available for use anymore.
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
provider_->Shutdown();
EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(nullptr, consumer_->GetInvalidationService());
// Verify that the device-global invalidation service still does not exist.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
// Log in as a second affiliated user.
Profile* second_profile = LogInAndReturnAffiliatedProfile(kAffiliatedUserID2);
EXPECT_TRUE(second_profile);
// Verify that the device-global invalidation service still does not exist.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
// Create a per-profile invalidation service for the second user.
invalidation::FakeInvalidationService* second_profile_invalidation_service =
GetProfileInvalidationService(second_profile, true /* create */);
ASSERT_TRUE(second_profile_invalidation_service);
// Indicate that the second user's per-profile invalidation service has
// connected. Verify that the consumer is not called back.
second_profile_invalidation_service->SetInvalidatorState(
syncer::INVALIDATIONS_ENABLED);
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
// Verify that the device-global invalidation service still does not exist.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
}
// A consumer is registered with the AffiliatedInvalidationServiceProviderImpl.
// A device-global invalidation service exists, is connected and is made
// available to the consumer. Verifies that when the provider is shut down, the
// consumer is informed that no invalidation service is available for use
// anymore before the device-global invalidation service is destroyed.
// This is a regression test for http://crbug.com/455504.
TEST_F(AffiliatedInvalidationServiceProviderImplTest,
ConnectedDeviceGlobalInvalidationServiceOnShutdown) {
consumer_.reset(new FakeConsumer(provider_.get()));
// Verify that a device-global invalidation service has been created.
EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
// Indicate that the device-global invalidation service connected. Verify that
// that the consumer is informed about this.
ConnectDeviceGlobalInvalidationService();
// Shut down the |provider_|. Verify that the |consumer_| is informed that no
// invalidation service is available for use anymore. This also serves as a
// regression test which verifies that the invalidation service is not
// destroyed until the |consumer_| has been informed: If the invalidation
// service was destroyed too early, the |consumer_| would still be registered
// as an observer and the invalidation service's destructor would DCHECK().
EXPECT_EQ(0, consumer_->GetAndClearInvalidationServiceSetCount());
provider_->Shutdown();
EXPECT_EQ(1, consumer_->GetAndClearInvalidationServiceSetCount());
EXPECT_EQ(nullptr, consumer_->GetInvalidationService());
// Verify that the device-global invalidation service has been destroyed.
EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
}
} // namespace policy