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