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