[Android] Allow multiple --install in bb_device_steps.py.
[chromium-blink-merge.git] / chrome / browser / chromeos / policy / device_cloud_policy_invalidator.cc
blob0f62250173b13889f551af53cc4c1fa1090c4cd6
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/policy/device_cloud_policy_invalidator.h"
7 #include <string>
8 #include <vector>
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/time/clock.h"
13 #include "base/time/default_clock.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browser_process_platform_part_chromeos.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
18 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
19 #include "chrome/browser/chromeos/policy/ticl_device_settings_provider.h"
20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
21 #include "chrome/browser/chromeos/settings/device_identity_provider.h"
22 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
23 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
24 #include "chrome/browser/policy/cloud/cloud_policy_invalidator.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/common/chrome_content_client.h"
27 #include "components/invalidation/invalidation_handler.h"
28 #include "components/invalidation/invalidation_service.h"
29 #include "components/invalidation/invalidation_state_tracker.h"
30 #include "components/invalidation/invalidator_state.h"
31 #include "components/invalidation/invalidator_storage.h"
32 #include "components/invalidation/profile_invalidation_provider.h"
33 #include "components/invalidation/ticl_invalidation_service.h"
34 #include "components/invalidation/ticl_settings_provider.h"
35 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
36 #include "components/user_manager/user.h"
37 #include "content/public/browser/notification_details.h"
38 #include "content/public/browser/notification_service.h"
39 #include "google_apis/gaia/identity_provider.h"
40 #include "net/url_request/url_request_context_getter.h"
41 #include "policy/proto/device_management_backend.pb.h"
43 class Profile;
45 namespace policy {
47 class DeviceCloudPolicyInvalidator::InvalidationServiceObserver
48 : public syncer::InvalidationHandler {
49 public:
50 explicit InvalidationServiceObserver(
51 DeviceCloudPolicyInvalidator* parent,
52 invalidation::InvalidationService* invalidation_service);
53 virtual ~InvalidationServiceObserver();
55 invalidation::InvalidationService* GetInvalidationService();
56 bool IsServiceConnected() const;
58 // public syncer::InvalidationHandler:
59 virtual void OnInvalidatorStateChange(
60 syncer::InvalidatorState state) override;
61 virtual void OnIncomingInvalidation(
62 const syncer::ObjectIdInvalidationMap& invalidation_map) override;
63 virtual std::string GetOwnerName() const override;
65 private:
66 DeviceCloudPolicyInvalidator* parent_;
67 invalidation::InvalidationService* invalidation_service_;
68 bool is_service_connected_;
70 DISALLOW_COPY_AND_ASSIGN(InvalidationServiceObserver);
73 DeviceCloudPolicyInvalidator::InvalidationServiceObserver::
74 InvalidationServiceObserver(
75 DeviceCloudPolicyInvalidator* parent,
76 invalidation::InvalidationService* invalidation_service)
77 : parent_(parent),
78 invalidation_service_(invalidation_service),
79 is_service_connected_(invalidation_service->GetInvalidatorState() ==
80 syncer::INVALIDATIONS_ENABLED) {
81 invalidation_service_->RegisterInvalidationHandler(this);
84 DeviceCloudPolicyInvalidator::InvalidationServiceObserver::
85 ~InvalidationServiceObserver() {
86 invalidation_service_->UnregisterInvalidationHandler(this);
89 invalidation::InvalidationService*
90 DeviceCloudPolicyInvalidator::InvalidationServiceObserver::
91 GetInvalidationService() {
92 return invalidation_service_;
95 bool DeviceCloudPolicyInvalidator::InvalidationServiceObserver::
96 IsServiceConnected() const {
97 return is_service_connected_;
100 void DeviceCloudPolicyInvalidator::InvalidationServiceObserver::
101 OnInvalidatorStateChange(syncer::InvalidatorState state) {
102 const bool is_service_connected = (state == syncer::INVALIDATIONS_ENABLED);
103 if (is_service_connected == is_service_connected_)
104 return;
106 is_service_connected_ = is_service_connected;
107 if (is_service_connected_)
108 parent_->OnInvalidationServiceConnected(invalidation_service_);
109 else
110 parent_->OnInvalidationServiceDisconnected(invalidation_service_);
113 void DeviceCloudPolicyInvalidator::InvalidationServiceObserver::
114 OnIncomingInvalidation(
115 const syncer::ObjectIdInvalidationMap& invalidation_map) {
118 std::string DeviceCloudPolicyInvalidator::InvalidationServiceObserver::
119 GetOwnerName() const {
120 return "DevicePolicy";
123 DeviceCloudPolicyInvalidator::DeviceCloudPolicyInvalidator()
124 : invalidation_service_(NULL),
125 highest_handled_invalidation_version_(0) {
126 // The DeviceCloudPolicyInvalidator should be created before any user
127 // Profiles.
128 DCHECK(g_browser_process->profile_manager()->GetLoadedProfiles().empty());
130 // Subscribe to notification about new user profiles becoming available.
131 registrar_.Add(this,
132 chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED,
133 content::NotificationService::AllSources());
135 TryToCreateInvalidator();
138 DeviceCloudPolicyInvalidator::~DeviceCloudPolicyInvalidator() {
139 DestroyInvalidator();
142 void DeviceCloudPolicyInvalidator::Observe(
143 int type,
144 const content::NotificationSource& source,
145 const content::NotificationDetails& details) {
146 DCHECK_EQ(chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, type);
147 Profile* profile = content::Details<Profile>(details).ptr();
148 invalidation::ProfileInvalidationProvider* invalidation_provider =
149 invalidation::ProfileInvalidationProviderFactory::GetForProfile(profile);
150 if (!invalidation_provider) {
151 // If the Profile does not support invalidation (e.g. guest, incognito),
152 // ignore it.
153 return;
155 user_manager::User* user =
156 chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
157 if (!user ||
158 g_browser_process->platform_part()->browser_policy_connector_chromeos()->
159 GetUserAffiliation(user->email()) != USER_AFFILIATION_MANAGED) {
160 // If the Profile belongs to a user who is not affiliated with the domain
161 // the device is enrolled into, ignore it.
162 return;
164 // Create a state observer for the user's invalidation service.
165 profile_invalidation_service_observers_.push_back(
166 new InvalidationServiceObserver(
167 this,
168 invalidation_provider->GetInvalidationService()));
170 TryToCreateInvalidator();
173 void DeviceCloudPolicyInvalidator::OnInvalidationServiceConnected(
174 invalidation::InvalidationService* invalidation_service) {
175 if (!device_invalidation_service_) {
176 // The lack of a device-global invalidation service implies that a
177 // |CloudPolicyInvalidator| backed by another connected service exists
178 // already. There is no need to switch from that to the service which just
179 // connected.
180 return;
183 if (invalidation_service != device_invalidation_service_.get()) {
184 // If an invalidation service other than the device-global one connected,
185 // destroy the device-global service and the |CloudPolicyInvalidator| backed
186 // by it, if any.
187 DestroyInvalidator();
188 DestroyDeviceInvalidationService();
191 // Create a |CloudPolicyInvalidator| backed by the invalidation service which
192 // just connected.
193 CreateInvalidator(invalidation_service);
196 void DeviceCloudPolicyInvalidator::OnInvalidationServiceDisconnected(
197 invalidation::InvalidationService* invalidation_service) {
198 if (invalidation_service != invalidation_service_) {
199 // If the invalidation service which disconnected is not backing the current
200 // |CloudPolicyInvalidator|, return.
201 return;
204 // Destroy the |CloudPolicyInvalidator| backed by the invalidation service
205 // which just disconnected.
206 DestroyInvalidator();
208 // Try to create a |CloudPolicyInvalidator| backed by another invalidation
209 // service.
210 TryToCreateInvalidator();
213 void DeviceCloudPolicyInvalidator::TryToCreateInvalidator() {
214 if (invalidator_) {
215 // If a |CloudPolicyInvalidator| exists already, return.
216 return;
219 for (ScopedVector<InvalidationServiceObserver>::const_iterator it =
220 profile_invalidation_service_observers_.begin();
221 it != profile_invalidation_service_observers_.end(); ++it) {
222 if ((*it)->IsServiceConnected()) {
223 // If a connected invalidation service belonging to an affiliated
224 // logged-in user is found, create a |CloudPolicyInvalidator| backed by
225 // that service and destroy the device-global service, if any.
226 DestroyDeviceInvalidationService();
227 CreateInvalidator((*it)->GetInvalidationService());
228 return;
232 if (!device_invalidation_service_) {
233 // If no other connected invalidation service was found, ensure that a
234 // device-global service is running.
235 device_invalidation_service_.reset(
236 new invalidation::TiclInvalidationService(
237 GetUserAgent(),
238 scoped_ptr<IdentityProvider>(new chromeos::DeviceIdentityProvider(
239 chromeos::DeviceOAuth2TokenServiceFactory::Get())),
240 scoped_ptr<invalidation::TiclSettingsProvider>(
241 new TiclDeviceSettingsProvider),
242 g_browser_process->gcm_driver(),
243 g_browser_process->system_request_context()));
244 device_invalidation_service_->Init(
245 scoped_ptr<syncer::InvalidationStateTracker>(
246 new invalidation::InvalidatorStorage(
247 g_browser_process->local_state())));
248 device_invalidation_service_observer_.reset(
249 new InvalidationServiceObserver(
250 this,
251 device_invalidation_service_.get()));
254 if (device_invalidation_service_observer_->IsServiceConnected()) {
255 // If the device-global invalidation service is connected, create a
256 // |CloudPolicyInvalidator| backed by it. Otherwise, a
257 // |CloudPolicyInvalidator| will be created later when a connected service
258 // becomes available.
259 CreateInvalidator(device_invalidation_service_.get());
263 void DeviceCloudPolicyInvalidator::CreateInvalidator(
264 invalidation::InvalidationService* invalidation_service) {
265 invalidation_service_ = invalidation_service;
266 DCHECK(!invalidator_);
267 invalidator_.reset(new CloudPolicyInvalidator(
268 enterprise_management::DeviceRegisterRequest::DEVICE,
269 g_browser_process->platform_part()->browser_policy_connector_chromeos()->
270 GetDeviceCloudPolicyManager()->core(),
271 base::MessageLoopProxy::current(),
272 scoped_ptr<base::Clock>(new base::DefaultClock()),
273 highest_handled_invalidation_version_));
274 invalidator_->Initialize(invalidation_service);
277 void DeviceCloudPolicyInvalidator::DestroyInvalidator() {
278 if (invalidator_) {
279 highest_handled_invalidation_version_ =
280 invalidator_->highest_handled_invalidation_version();
281 invalidator_->Shutdown();
283 invalidator_.reset();
284 invalidation_service_ = NULL;
287 void DeviceCloudPolicyInvalidator::DestroyDeviceInvalidationService() {
288 device_invalidation_service_observer_.reset();
289 device_invalidation_service_.reset();
292 } // namespace policy