summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.cc343
-rw-r--r--chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.h140
-rw-r--r--chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_unittest.cc627
-rw-r--r--chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc11
-rw-r--r--chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h3
-rw-r--r--chrome/browser/invalidation/profile_invalidation_provider_factory.h2
-rw-r--r--chrome/chrome_browser_chromeos.gypi2
-rw-r--r--chrome/chrome_tests_unit.gypi1
8 files changed, 1129 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.cc
new file mode 100644
index 0000000..7fbbdf3
--- /dev/null
+++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.cc
@@ -0,0 +1,343 @@
+// 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.h"
+
+#include <vector>
+
+#include "base/logging.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part_chromeos.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/policy/ticl_device_settings_provider.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/settings/device_identity_provider.h"
+#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
+#include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/chrome_content_client.h"
+#include "components/invalidation/invalidation_handler.h"
+#include "components/invalidation/invalidation_service.h"
+#include "components/invalidation/invalidation_state_tracker.h"
+#include "components/invalidation/invalidator_state.h"
+#include "components/invalidation/invalidator_storage.h"
+#include "components/invalidation/profile_invalidation_provider.h"
+#include "components/invalidation/ticl_invalidation_service.h"
+#include "components/invalidation/ticl_settings_provider.h"
+#include "components/policy/core/common/cloud/cloud_policy_constants.h"
+#include "components/user_manager/user.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "google_apis/gaia/identity_provider.h"
+
+namespace policy {
+
+AffiliatedInvalidationServiceProvider::Consumer::~Consumer() {
+}
+
+class AffiliatedInvalidationServiceProvider::InvalidationServiceObserver
+ : public syncer::InvalidationHandler {
+ public:
+ explicit InvalidationServiceObserver(
+ AffiliatedInvalidationServiceProvider* parent,
+ invalidation::InvalidationService* invalidation_service);
+ ~InvalidationServiceObserver() override;
+
+ invalidation::InvalidationService* GetInvalidationService();
+ bool IsServiceConnected() const;
+
+ // public syncer::InvalidationHandler:
+ void OnInvalidatorStateChange(syncer::InvalidatorState state) override;
+ void OnIncomingInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map) override;
+ std::string GetOwnerName() const override;
+
+ private:
+ AffiliatedInvalidationServiceProvider* parent_;
+ invalidation::InvalidationService* invalidation_service_;
+ bool is_service_connected_;
+ bool is_observer_ready_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvalidationServiceObserver);
+};
+
+AffiliatedInvalidationServiceProvider::InvalidationServiceObserver::
+ InvalidationServiceObserver(
+ AffiliatedInvalidationServiceProvider* parent,
+ invalidation::InvalidationService* invalidation_service)
+ : parent_(parent),
+ invalidation_service_(invalidation_service),
+ is_service_connected_(false),
+ is_observer_ready_(false) {
+ invalidation_service_->RegisterInvalidationHandler(this);
+ is_service_connected_ = invalidation_service->GetInvalidatorState() ==
+ syncer::INVALIDATIONS_ENABLED;
+ is_observer_ready_ = true;
+}
+
+AffiliatedInvalidationServiceProvider::InvalidationServiceObserver::
+ ~InvalidationServiceObserver() {
+ is_observer_ready_ = false;
+ invalidation_service_->UnregisterInvalidationHandler(this);
+}
+
+invalidation::InvalidationService*
+AffiliatedInvalidationServiceProvider::InvalidationServiceObserver::
+ GetInvalidationService() {
+ return invalidation_service_;
+}
+
+bool AffiliatedInvalidationServiceProvider::InvalidationServiceObserver::
+ IsServiceConnected() const {
+ return is_service_connected_;
+}
+
+void AffiliatedInvalidationServiceProvider::InvalidationServiceObserver::
+ OnInvalidatorStateChange(syncer::InvalidatorState state) {
+ if (!is_observer_ready_)
+ return;
+
+ const bool is_service_connected = (state == syncer::INVALIDATIONS_ENABLED);
+ if (is_service_connected == is_service_connected_)
+ return;
+
+ is_service_connected_ = is_service_connected;
+ if (is_service_connected_)
+ parent_->OnInvalidationServiceConnected(invalidation_service_);
+ else
+ parent_->OnInvalidationServiceDisconnected(invalidation_service_);
+}
+
+void AffiliatedInvalidationServiceProvider::InvalidationServiceObserver::
+ OnIncomingInvalidation(
+ const syncer::ObjectIdInvalidationMap& invalidation_map) {
+}
+
+std::string AffiliatedInvalidationServiceProvider::InvalidationServiceObserver::
+ GetOwnerName() const {
+ return "AffiliatedInvalidationService";
+}
+
+AffiliatedInvalidationServiceProvider::AffiliatedInvalidationServiceProvider()
+ : invalidation_service_(nullptr),
+ consumer_count_(0),
+ is_shut_down_(false) {
+ // The AffiliatedInvalidationServiceProvider should be created before any user
+ // Profiles.
+ DCHECK(g_browser_process->profile_manager()->GetLoadedProfiles().empty());
+
+ // Subscribe to notification about new user profiles becoming available.
+ registrar_.Add(this,
+ chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
+ content::NotificationService::AllSources());
+}
+
+AffiliatedInvalidationServiceProvider::
+~AffiliatedInvalidationServiceProvider() {
+ // Verify that the provider was shut down first.
+ DCHECK(is_shut_down_);
+}
+
+void AffiliatedInvalidationServiceProvider::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK_EQ(chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, type);
+ DCHECK(!is_shut_down_);
+ Profile* profile = content::Details<Profile>(details).ptr();
+ invalidation::ProfileInvalidationProvider* invalidation_provider =
+ invalidation::ProfileInvalidationProviderFactory::GetForProfile(profile);
+ if (!invalidation_provider) {
+ // If the Profile does not support invalidation (e.g. guest, incognito),
+ // ignore it.
+ return;
+ }
+ user_manager::User* user =
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
+ if (!user ||
+ g_browser_process->platform_part()->browser_policy_connector_chromeos()->
+ GetUserAffiliation(user->email()) != USER_AFFILIATION_MANAGED) {
+ // If the Profile belongs to a user who is not affiliated with the device's
+ // enrollment domain, ignore it.
+ return;
+ }
+
+ // Create a state observer for the user's invalidation service.
+ invalidation::InvalidationService* invalidation_service =
+ invalidation_provider->GetInvalidationService();
+ profile_invalidation_service_observers_.push_back(
+ new InvalidationServiceObserver(this, invalidation_service));
+
+ if (profile_invalidation_service_observers_.back()->IsServiceConnected()) {
+ // If the invalidation service is connected, check whether to switch to it.
+ OnInvalidationServiceConnected(invalidation_service);
+ }
+}
+
+void AffiliatedInvalidationServiceProvider::RegisterConsumer(
+ Consumer* consumer) {
+ if (consumers_.HasObserver(consumer) || is_shut_down_)
+ return;
+
+ consumers_.AddObserver(consumer);
+ ++consumer_count_;
+
+ if (invalidation_service_)
+ consumer->OnInvalidationServiceSet(invalidation_service_);
+ else if (consumer_count_ == 1)
+ FindConnectedInvalidationService();
+}
+
+void AffiliatedInvalidationServiceProvider::UnregisterConsumer(
+ Consumer* consumer) {
+ if (!consumers_.HasObserver(consumer))
+ return;
+
+ consumers_.RemoveObserver(consumer);
+ --consumer_count_;
+
+ if (invalidation_service_ && consumer_count_ == 0) {
+ invalidation_service_ = nullptr;
+ DestroyDeviceInvalidationService();
+ }
+}
+
+void AffiliatedInvalidationServiceProvider::Shutdown() {
+ is_shut_down_ = true;
+
+ registrar_.RemoveAll();
+ profile_invalidation_service_observers_.clear();
+ DestroyDeviceInvalidationService();
+
+ if (invalidation_service_) {
+ invalidation_service_ = nullptr;
+ // Explicitly notify consumers that the invalidation service they were using
+ // is no longer available.
+ SetInvalidationService(nullptr);
+ }
+}
+
+invalidation::TiclInvalidationService*
+AffiliatedInvalidationServiceProvider::
+ GetDeviceInvalidationServiceForTest() const {
+ return device_invalidation_service_.get();
+}
+
+void AffiliatedInvalidationServiceProvider::OnInvalidationServiceConnected(
+ invalidation::InvalidationService* invalidation_service) {
+ DCHECK(!is_shut_down_);
+
+ if (consumer_count_ == 0) {
+ // If there are no consumers, no invalidation service is required.
+ return;
+ }
+
+ if (!device_invalidation_service_) {
+ // The lack of a device-global invalidation service implies that another
+ // connected invalidation service is being made available to consumers
+ // already. There is no need to switch from that to the service which just
+ // connected.
+ return;
+ }
+
+ if (invalidation_service != device_invalidation_service_.get()) {
+ // If an invalidation service other than the device-global one connected,
+ // destroy the device-global service.
+ invalidation_service_ = nullptr;
+ DestroyDeviceInvalidationService();
+ }
+
+ // Make the invalidation service that just connected available to consumers.
+ SetInvalidationService(invalidation_service);
+}
+
+void AffiliatedInvalidationServiceProvider::OnInvalidationServiceDisconnected(
+ invalidation::InvalidationService* invalidation_service) {
+ DCHECK(!is_shut_down_);
+
+ if (invalidation_service != invalidation_service_) {
+ // If the invalidation service which disconnected was not being made
+ // available to consumers, return.
+ return;
+ }
+
+ // The invalidation service which disconnected was being made available to
+ // consumers. Stop making it available.
+ DCHECK(consumer_count_);
+ invalidation_service_ = nullptr;
+
+ // Try to make another invalidation service available to consumers.
+ FindConnectedInvalidationService();
+
+ // If no other connected invalidation service was found, explicitly notify
+ // consumers that the invalidation service they were using is no longer
+ // available.
+ if (!invalidation_service_)
+ SetInvalidationService(nullptr);
+}
+
+void AffiliatedInvalidationServiceProvider::FindConnectedInvalidationService() {
+ DCHECK(!invalidation_service_);
+ DCHECK(consumer_count_);
+ DCHECK(!is_shut_down_);
+
+ for (ScopedVector<InvalidationServiceObserver>::const_iterator it =
+ profile_invalidation_service_observers_.begin();
+ it != profile_invalidation_service_observers_.end(); ++it) {
+ if ((*it)->IsServiceConnected()) {
+ // If a connected invalidation service belonging to an affiliated
+ // logged-in user is found, make it available to consumers.
+ DestroyDeviceInvalidationService();
+ SetInvalidationService((*it)->GetInvalidationService());
+ return;
+ }
+ }
+
+ if (!device_invalidation_service_) {
+ // If no other connected invalidation service was found and no device-global
+ // invalidation service exists, create one.
+ device_invalidation_service_.reset(
+ new invalidation::TiclInvalidationService(
+ GetUserAgent(),
+ scoped_ptr<IdentityProvider>(new chromeos::DeviceIdentityProvider(
+ chromeos::DeviceOAuth2TokenServiceFactory::Get())),
+ scoped_ptr<invalidation::TiclSettingsProvider>(
+ new TiclDeviceSettingsProvider),
+ g_browser_process->gcm_driver(),
+ g_browser_process->system_request_context()));
+ device_invalidation_service_->Init(
+ scoped_ptr<syncer::InvalidationStateTracker>(
+ new invalidation::InvalidatorStorage(
+ g_browser_process->local_state())));
+ device_invalidation_service_observer_.reset(
+ new InvalidationServiceObserver(
+ this,
+ device_invalidation_service_.get()));
+ }
+
+ if (device_invalidation_service_observer_->IsServiceConnected()) {
+ // If the device-global invalidation service is connected already, make it
+ // available to consumers immediately. Otherwise, the invalidation service
+ // will be made available to clients when it successfully connects.
+ OnInvalidationServiceConnected(device_invalidation_service_.get());
+ }
+}
+
+void AffiliatedInvalidationServiceProvider::SetInvalidationService(
+ invalidation::InvalidationService* invalidation_service) {
+ DCHECK(!invalidation_service_);
+ invalidation_service_ = invalidation_service;
+ FOR_EACH_OBSERVER(Consumer,
+ consumers_,
+ OnInvalidationServiceSet(invalidation_service_));
+}
+
+void AffiliatedInvalidationServiceProvider::DestroyDeviceInvalidationService() {
+ device_invalidation_service_observer_.reset();
+ device_invalidation_service_.reset();
+}
+
+} // namespace policy
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.h b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.h
new file mode 100644
index 0000000..5484355
--- /dev/null
+++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.h
@@ -0,0 +1,140 @@
+// 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.
+
+#ifndef CHROME_BROWSER_CHROMEOS_POLICY_AFFILIATED_INVALIDATION_SERVICE_PROVIDER_H_
+#define CHROME_BROWSER_CHROMEOS_POLICY_AFFILIATED_INVALIDATION_SERVICE_PROVIDER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/observer_list.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace invalidation {
+class InvalidationService;
+class TiclInvalidationService;
+}
+
+namespace policy {
+
+// This class provides access to an |InvalidationService| that can be used to
+// subscribe to invalidations generated by the device's enrollment domain, e.g.
+// policy pushing and remote commands for:
+// * the device itself
+// * device-local accounts
+// * other users affiliated with the enrollment domain
+//
+// If an affiliated user with a connected invalidation service is logged in,
+// that invalidation service will be used to conserve server resources. If there
+// are no logged-in users matching these criteria, a device-global
+// |TiclInvalidationService| is spun up.
+// The class monitors the status of the invalidation services and switches
+// between them whenever the service currently in use disconnects or the
+// device-global invalidation service can be replaced with another service that
+// just connected.
+class AffiliatedInvalidationServiceProvider
+ : public content::NotificationObserver {
+ public:
+ class Consumer {
+ public:
+ // This method is called when the invalidation service that the consumer
+ // should use changes:
+ // * If |invalidation_service| is a nullptr, no invalidation service is
+ // currently available for use.
+ // * Otherwise, |invalidation_service| is the invalidation service that the
+ // consumer should use. It is guaranteed to be connected. Any previously
+ // provided invalidation services must no longer be used.
+ virtual void OnInvalidationServiceSet(
+ invalidation::InvalidationService* invalidation_service) = 0;
+
+ protected:
+ virtual ~Consumer();
+ };
+
+ AffiliatedInvalidationServiceProvider();
+ ~AffiliatedInvalidationServiceProvider() override;
+
+ // content::NotificationObserver:
+ void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) override;
+
+ // Indicates that |consumer| is interested in using the shared
+ // |InvalidationService|. The consumer's OnInvalidationServiceSet() method
+ // will be called back when a connected invalidation service becomes
+ // available. If an invalidation service is available already, the callback
+ // will occur synchronously. The |consumer| must be unregistered before |this|
+ // is destroyed.
+ void RegisterConsumer(Consumer* consumer);
+
+ // Indicates that |consumer| is no longer interested in using the
+ // shared |InvalidationService|.
+ void UnregisterConsumer(Consumer* consumer);
+
+ // Shuts down the provider. Once the provider is shut down, it no longer makes
+ // any invalidation service available to consumers, no longer observes any
+ // per-profile invalidation services and no longer maintains a device-global
+ // invalidation service.
+ void Shutdown();
+
+ invalidation::TiclInvalidationService*
+ GetDeviceInvalidationServiceForTest() const;
+
+ private:
+ // Helper that monitors the status of a single |InvalidationService|.
+ class InvalidationServiceObserver;
+
+ // Status updates received from |InvalidationServiceObserver|s.
+ void OnInvalidationServiceConnected(
+ invalidation::InvalidationService* invalidation_service);
+ void OnInvalidationServiceDisconnected(
+ invalidation::InvalidationService* invalidation_service);
+
+ // Checks whether a connected |InvalidationService| affiliated with the
+ // device's enrollment domain is available. If so, notifies the consumers.
+ // Otherwise, consumers will be notified once such an invalidation service
+ // becomes available.
+ // Further ensures that a device-global invalidation service is running iff
+ // there is no other connected service available for use and there is at least
+ // one registered consumer.
+ void FindConnectedInvalidationService();
+
+ // Choose |invalidation_service| as the shared invalidation service and notify
+ // consumers.
+ void SetInvalidationService(
+ invalidation::InvalidationService* invalidation_service);
+
+ // Destroy the device-global invalidation service, if any.
+ void DestroyDeviceInvalidationService();
+
+ content::NotificationRegistrar registrar_;
+
+ // Device-global invalidation service.
+ scoped_ptr<invalidation::TiclInvalidationService>
+ device_invalidation_service_;
+
+ // State observer for the device-global invalidation service.
+ scoped_ptr<InvalidationServiceObserver> device_invalidation_service_observer_;
+
+ // State observers for logged-in users' invalidation services.
+ ScopedVector<InvalidationServiceObserver>
+ profile_invalidation_service_observers_;
+
+ // The invalidation service currently used by consumers. nullptr if there are
+ // no registered consumers or no connected invalidation service is available
+ // for use.
+ invalidation::InvalidationService* invalidation_service_;
+
+ ObserverList<Consumer, true> consumers_;
+ int consumer_count_;
+
+ bool is_shut_down_;
+
+ DISALLOW_COPY_AND_ASSIGN(AffiliatedInvalidationServiceProvider);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_CHROMEOS_POLICY_AFFILIATED_INVALIDATION_SERVICE_PROVIDER_H_
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_unittest.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_unittest.cc
new file mode 100644
index 0000000..5c1cb60
--- /dev/null
+++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_unittest.cc
@@ -0,0 +1,627 @@
+// 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.h"
+
+#include <string>
+
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/users/fake_user_manager.h"
+#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
+#include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.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/invalidation/fake_invalidation_service.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/invalidation_service.h"
+#include "components/invalidation/invalidator_state.h"
+#include "components/invalidation/profile_invalidation_provider.h"
+#include "components/invalidation/ticl_invalidation_service.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/policy/core/common/cloud/cloud_policy_constants.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 "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Mock;
+using testing::StrictMock;
+
+namespace policy {
+
+namespace {
+
+const char kAffiliatedUserID1[] = "test_1@example.com";
+const char kAffiliatedUserID2[] = "test_2@example.com";
+const char kUnaffiliatedUserID[] = "test@other_domain.test";
+
+KeyedService* BuildProfileInvalidationProvider(
+ content::BrowserContext* context) {
+ scoped_ptr<invalidation::FakeInvalidationService> invalidation_service(
+ new invalidation::FakeInvalidationService);
+ invalidation_service->SetInvalidatorState(
+ syncer::TRANSIENT_INVALIDATION_ERROR);
+ return new invalidation::ProfileInvalidationProvider(
+ invalidation_service.Pass());
+}
+
+} // namespace
+
+class MockConsumer : public AffiliatedInvalidationServiceProvider::Consumer {
+ public:
+ MockConsumer();
+ ~MockConsumer() override;
+
+ MOCK_METHOD1(OnInvalidationServiceSet,
+ void(invalidation::InvalidationService*));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockConsumer);
+};
+
+class AffiliatedInvalidationServiceProviderTest : public testing::Test {
+ public:
+ AffiliatedInvalidationServiceProviderTest();
+
+ // testing::Test:
+ virtual void SetUp() override;
+ virtual void TearDown() override;
+
+ // Ownership is not passed. The Profile is owned by the global ProfileManager.
+ Profile* LogInAndReturnProfile(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:
+ scoped_ptr<AffiliatedInvalidationServiceProvider> provider_;
+ StrictMock<MockConsumer> consumer_;
+ invalidation::TiclInvalidationService* device_invalidation_service_;
+ invalidation::FakeInvalidationService* profile_invalidation_service_;
+
+ private:
+ content::TestBrowserThreadBundle thread_bundle_;
+ chromeos::FakeUserManager* fake_user_manager_;
+ chromeos::ScopedUserManagerEnabler user_manager_enabler_;
+ ScopedStubEnterpriseInstallAttributes install_attributes_;
+ scoped_ptr<chromeos::ScopedTestDeviceSettingsService>
+ test_device_settings_service_;
+ scoped_ptr<chromeos::ScopedTestCrosSettings> test_cros_settings_;
+ TestingProfileManager profile_manager_;
+};
+
+MockConsumer::MockConsumer() {
+}
+
+MockConsumer::~MockConsumer() {
+}
+
+AffiliatedInvalidationServiceProviderTest::
+AffiliatedInvalidationServiceProviderTest()
+ : device_invalidation_service_(nullptr),
+ profile_invalidation_service_(nullptr),
+ fake_user_manager_(new chromeos::FakeUserManager),
+ user_manager_enabler_(fake_user_manager_),
+ install_attributes_("example.com",
+ "user@example.com",
+ "device_id",
+ DEVICE_MODE_ENTERPRISE),
+ profile_manager_(TestingBrowserProcess::GetGlobal()) {
+}
+
+void AffiliatedInvalidationServiceProviderTest::SetUp() {
+ chromeos::SystemSaltGetter::Initialize();
+ chromeos::DBusThreadManager::Initialize();
+ chromeos::DeviceOAuth2TokenServiceFactory::Initialize();
+ ASSERT_TRUE(profile_manager_.SetUp());
+
+ test_device_settings_service_.reset(new
+ chromeos::ScopedTestDeviceSettingsService);
+ test_cros_settings_.reset(new chromeos::ScopedTestCrosSettings);
+
+ invalidation::ProfileInvalidationProviderFactory::GetInstance()->
+ RegisterTestingFactory(BuildProfileInvalidationProvider);
+
+ provider_.reset(new AffiliatedInvalidationServiceProvider);
+}
+
+void AffiliatedInvalidationServiceProviderTest::TearDown() {
+ provider_->Shutdown();
+ provider_.reset();
+
+ invalidation::ProfileInvalidationProviderFactory::GetInstance()->
+ RegisterTestingFactory(nullptr);
+ chromeos::DeviceOAuth2TokenServiceFactory::Shutdown();
+ chromeos::DBusThreadManager::Shutdown();
+ chromeos::SystemSaltGetter::Shutdown();
+}
+
+Profile* AffiliatedInvalidationServiceProviderTest::LogInAndReturnProfile(
+ const std::string& user_id) {
+ fake_user_manager_->AddUser(user_id);
+ 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 AffiliatedInvalidationServiceProviderTest::
+ LogInAsAffiliatedUserAndConnectInvalidationService() {
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // Log in as an affiliated user.
+ Profile* profile = LogInAndReturnProfile(kAffiliatedUserID1);
+ EXPECT_TRUE(profile);
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // 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_CALL(consumer_,
+ OnInvalidationServiceSet(profile_invalidation_service_)).Times(1);
+ profile_invalidation_service_->SetInvalidatorState(
+ syncer::INVALIDATIONS_ENABLED);
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // Verify that the device-global invalidation service has been destroyed.
+ EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
+
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+void AffiliatedInvalidationServiceProviderTest::
+ LogInAsUnaffiliatedUserAndConnectInvalidationService() {
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // Log in as an unaffiliated user.
+ Profile* profile = LogInAndReturnProfile(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);
+
+ // Verify that the device-global invalidation service still exists.
+ EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
+
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+void AffiliatedInvalidationServiceProviderTest::
+ ConnectDeviceGlobalInvalidationService() {
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // 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_CALL(consumer_, OnInvalidationServiceSet(device_invalidation_service_))
+ .Times(1);
+ device_invalidation_service_->OnInvalidatorStateChange(
+ syncer::INVALIDATIONS_ENABLED);
+
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+void AffiliatedInvalidationServiceProviderTest::
+ DisconnectPerProfileInvalidationService() {
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ ASSERT_TRUE(profile_invalidation_service_);
+
+ // Indicate that the per-profile invalidation service has disconnected. Verify
+ // that the consumer is informed about this.
+ EXPECT_CALL(consumer_, OnInvalidationServiceSet(nullptr)).Times(1);
+ profile_invalidation_service_->SetInvalidatorState(
+ syncer::INVALIDATION_CREDENTIALS_REJECTED);
+
+ // Verify that a device-global invalidation service has been created.
+ EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
+
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+invalidation::FakeInvalidationService*
+AffiliatedInvalidationServiceProviderTest::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 AffiliatedInvalidationServiceProvider.
+// Verifies that no device-global invalidation service is created, whether an
+// affiliated user is logged in or not.
+TEST_F(AffiliatedInvalidationServiceProviderTest, NoConsumers) {
+ // Verify that no device-global invalidation service has been created.
+ EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
+
+ // Log in as an affiliated user.
+ EXPECT_TRUE(LogInAndReturnProfile(kAffiliatedUserID1));
+
+ // Verify that no device-global invalidation service has been created.
+ EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider.
+// 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(AffiliatedInvalidationServiceProviderTest,
+ UseDeviceInvalidationService) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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_CALL(consumer_, OnInvalidationServiceSet(nullptr)).Times(1);
+ device_invalidation_service_->OnInvalidatorStateChange(
+ syncer::INVALIDATION_CREDENTIALS_REJECTED);
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // Verify that the device-global invalidation service still exists.
+ EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider.
+// Verifies that when a per-profile invalidation service belonging to an
+// affiliated user connects, it is made available to the consumer.
+TEST_F(AffiliatedInvalidationServiceProviderTest,
+ UseAffiliatedProfileInvalidationService) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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();
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider.
+// Verifies that when a per-profile invalidation service belonging to an
+// unaffiliated user connects, it is ignored.
+TEST_F(AffiliatedInvalidationServiceProviderTest,
+ DoNotUseUnaffiliatedProfileInvalidationService) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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();
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider. 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(AffiliatedInvalidationServiceProviderTest,
+ SwitchToAffiliatedProfileInvalidationService) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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();
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider. 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(AffiliatedInvalidationServiceProviderTest,
+ DoNotSwitchToUnaffiliatedProfileInvalidationService) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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();
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider. 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(AffiliatedInvalidationServiceProviderTest,
+ SwitchToDeviceInvalidationService) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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();
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider. 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(AffiliatedInvalidationServiceProviderTest,
+ SwitchBetweenAffiliatedProfileInvalidationServices) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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 = LogInAndReturnProfile(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);
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // 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_CALL(consumer_,
+ OnInvalidationServiceSet(second_profile_invalidation_service))
+ .Times(1);
+ profile_invalidation_service_->SetInvalidatorState(
+ syncer::INVALIDATION_CREDENTIALS_REJECTED);
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // Verify that the device-global invalidation service still does not exist.
+ EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider. 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(AffiliatedInvalidationServiceProviderTest, MultipleConsumers) {
+ // Register a first consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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.
+ StrictMock<MockConsumer> second_consumer;
+ EXPECT_CALL(second_consumer,
+ OnInvalidationServiceSet(device_invalidation_service_)).Times(1);
+ provider_->RegisterConsumer(&second_consumer);
+ Mock::VerifyAndClearExpectations(&second_consumer);
+
+ // Unregister the first consumer.
+ provider_->UnregisterConsumer(&consumer_);
+
+ // Verify that the device-global invalidation service still exists.
+ EXPECT_TRUE(provider_->GetDeviceInvalidationServiceForTest());
+
+ // Unregister the second consumer.
+ provider_->UnregisterConsumer(&second_consumer);
+
+ // Verify that the device-global invalidation service has been destroyed.
+ EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
+ Mock::VerifyAndClearExpectations(&consumer_);
+ Mock::VerifyAndClearExpectations(&second_consumer);
+}
+
+// A consumer is registered with the AffiliatedInvalidationServiceProvider. 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(AffiliatedInvalidationServiceProviderTest, NoServiceAfterShutdown) {
+ // Register a consumer. Verify that the consumer is not called back
+ // immediately as no connected invalidation service exists yet.
+ provider_->RegisterConsumer(&consumer_);
+
+ // 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_CALL(consumer_, OnInvalidationServiceSet(nullptr)).Times(1);
+ provider_->Shutdown();
+ Mock::VerifyAndClearExpectations(&consumer_);
+
+ // 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 = LogInAndReturnProfile(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);
+
+ // Verify that the device-global invalidation service still does not exist.
+ EXPECT_FALSE(provider_->GetDeviceInvalidationServiceForTest());
+
+ // Unregister the consumer.
+ provider_->UnregisterConsumer(&consumer_);
+ Mock::VerifyAndClearExpectations(&consumer_);
+}
+
+} // namespace policy
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
index dd7dd53..9c91387 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -17,6 +17,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/chromeos/policy/affiliated_invalidation_service_provider.h"
#include "chrome/browser/chromeos/policy/consumer_management_service.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_initializer.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_invalidator.h"
@@ -152,6 +153,9 @@ void BrowserPolicyConnectorChromeOS::Init(
local_state_ = local_state;
ChromeBrowserPolicyConnector::Init(local_state, request_context);
+ affiliated_invalidation_service_provider_.reset(
+ new AffiliatedInvalidationServiceProvider);
+
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(chromeos::switches::kEnableConsumerManagement)) {
@@ -201,6 +205,13 @@ void BrowserPolicyConnectorChromeOS::Init(
}
void BrowserPolicyConnectorChromeOS::PreShutdown() {
+ // Let the |affiliated_invalidation_service_provider_| unregister itself as an
+ // observer of per-Profile InvalidationServices and the device-global
+ // invalidation::TiclInvalidationService it may have created as an observer of
+ // the DeviceOAuth2TokenService that is destroyed before Shutdown() is called.
+ if (affiliated_invalidation_service_provider_)
+ affiliated_invalidation_service_provider_->Shutdown();
+
// Let the |device_cloud_policy_invalidator_| unregister itself as an
// observer of per-Profile InvalidationServices and the device-global
// invalidation::TiclInvalidationService it may have created as an observer of
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
index 1917e53..cb3ec6f 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
@@ -24,6 +24,7 @@ class URLRequestContextGetter;
namespace policy {
+class AffiliatedInvalidationServiceProvider;
class ConsumerManagementService;
class DeviceCloudPolicyInitializer;
class DeviceCloudPolicyInvalidator;
@@ -150,6 +151,8 @@ class BrowserPolicyConnectorChromeOS
// Components of the device cloud policy implementation.
scoped_ptr<ServerBackedStateKeysBroker> state_keys_broker_;
scoped_ptr<EnterpriseInstallAttributes> install_attributes_;
+ scoped_ptr<AffiliatedInvalidationServiceProvider>
+ affiliated_invalidation_service_provider_;
scoped_ptr<ConsumerManagementService> consumer_management_service_;
DeviceCloudPolicyManagerChromeOS* device_cloud_policy_manager_;
PrefService* local_state_;
diff --git a/chrome/browser/invalidation/profile_invalidation_provider_factory.h b/chrome/browser/invalidation/profile_invalidation_provider_factory.h
index 49c5e84..2e45328 100644
--- a/chrome/browser/invalidation/profile_invalidation_provider_factory.h
+++ b/chrome/browser/invalidation/profile_invalidation_provider_factory.h
@@ -10,6 +10,7 @@
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace policy {
+class AffiliatedInvalidationServiceProviderTest;
class DeviceCloudPolicyInvalidatorTest;
}
@@ -48,6 +49,7 @@ class ProfileInvalidationProviderFactory
private:
friend class ProfileInvalidationProviderFactoryTestBase;
+ friend class policy::AffiliatedInvalidationServiceProviderTest;
friend class policy::DeviceCloudPolicyInvalidatorTest;
friend struct DefaultSingletonTraits<ProfileInvalidationProviderFactory>;
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index efcf2de..c751c02 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -727,6 +727,8 @@
'browser/chromeos/platform_keys/platform_keys_service.h',
'browser/chromeos/platform_keys/platform_keys_service_factory.cc',
'browser/chromeos/platform_keys/platform_keys_service_factory.h',
+ 'browser/chromeos/policy/affiliated_invalidation_service_provider.cc',
+ 'browser/chromeos/policy/affiliated_invalidation_service_provider.h',
'browser/chromeos/policy/auto_enrollment_client.cc',
'browser/chromeos/policy/auto_enrollment_client.h',
'browser/chromeos/policy/browser_policy_connector_chromeos.cc',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index a235300..e220c63 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -1244,6 +1244,7 @@
'browser/chromeos/ownership/fake_owner_settings_service.cc',
'browser/chromeos/ownership/fake_owner_settings_service.h',
'browser/chromeos/ownership/owner_settings_service_chromeos_unittest.cc',
+ 'browser/chromeos/policy/affiliated_invalidation_service_provider_unittest.cc',
'browser/chromeos/policy/auto_enrollment_client_unittest.cc',
'browser/chromeos/policy/cloud_external_data_manager_base_unittest.cc',
'browser/chromeos/policy/cloud_external_data_policy_observer_unittest.cc',