| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/policy/cloud/component_cloud_policy_service.h" | 5 #include "chrome/browser/policy/cloud/component_cloud_policy_service.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop_proxy.h" | 13 #include "base/message_loop/message_loop_proxy.h" |
| 14 #include "base/sequenced_task_runner.h" | 14 #include "base/sequenced_task_runner.h" |
| 15 #include "base/time/time.h" | |
| 16 #include "chrome/browser/policy/cloud/cloud_policy_constants.h" | 15 #include "chrome/browser/policy/cloud/cloud_policy_constants.h" |
| 16 #include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h" |
| 17 #include "chrome/browser/policy/cloud/component_cloud_policy_store.h" | 17 #include "chrome/browser/policy/cloud/component_cloud_policy_store.h" |
| 18 #include "chrome/browser/policy/cloud/component_cloud_policy_updater.h" | 18 #include "chrome/browser/policy/cloud/component_cloud_policy_updater.h" |
| 19 #include "chrome/browser/policy/cloud/external_policy_data_fetcher.h" | 19 #include "chrome/browser/policy/cloud/external_policy_data_fetcher.h" |
| 20 #include "chrome/browser/policy/cloud/resource_cache.h" | 20 #include "chrome/browser/policy/cloud/resource_cache.h" |
| 21 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" | 21 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" |
| 22 #include "chrome/browser/policy/schema_map.h" | 22 #include "chrome/browser/policy/schema_map.h" |
| 23 #include "components/policy/core/common/schema.h" | 23 #include "components/policy/core/common/schema.h" |
| 24 #include "net/url_request/url_request_context_getter.h" | 24 #include "net/url_request/url_request_context_getter.h" |
| 25 | 25 |
| 26 namespace em = enterprise_management; | 26 namespace em = enterprise_management; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 service_task_runner_(service_task_runner), | 123 service_task_runner_(service_task_runner), |
| 124 cache_(cache.Pass()), | 124 cache_(cache.Pass()), |
| 125 external_policy_data_fetcher_(external_policy_data_fetcher.Pass()), | 125 external_policy_data_fetcher_(external_policy_data_fetcher.Pass()), |
| 126 store_(this, cache_.get()) {} | 126 store_(this, cache_.get()) {} |
| 127 | 127 |
| 128 ComponentCloudPolicyService::Backend::~Backend() {} | 128 ComponentCloudPolicyService::Backend::~Backend() {} |
| 129 | 129 |
| 130 void ComponentCloudPolicyService::Backend::SetCredentials( | 130 void ComponentCloudPolicyService::Backend::SetCredentials( |
| 131 const std::string& username, | 131 const std::string& username, |
| 132 const std::string& dm_token) { | 132 const std::string& dm_token) { |
| 133 store_.SetCredentials(username, dm_token); | 133 if (username.empty() || dm_token.empty()) { |
| 134 // No sign-in credentials, so drop any cached policy. |
| 135 store_.Clear(); |
| 136 } else { |
| 137 store_.SetCredentials(username, dm_token); |
| 138 } |
| 134 } | 139 } |
| 135 | 140 |
| 136 void ComponentCloudPolicyService::Backend::Init( | 141 void ComponentCloudPolicyService::Backend::Init( |
| 137 scoped_refptr<SchemaMap> schema_map) { | 142 scoped_refptr<SchemaMap> schema_map) { |
| 138 DCHECK(!schema_map_); | 143 DCHECK(!schema_map_); |
| 139 | 144 |
| 140 OnSchemasUpdated(schema_map, scoped_ptr<PolicyNamespaceList>()); | 145 OnSchemasUpdated(schema_map, scoped_ptr<PolicyNamespaceList>()); |
| 141 | 146 |
| 142 // Read the initial policy. Note that this does not trigger notifications | 147 // Read the initial policy. Note that this does not trigger notifications |
| 143 // through OnComponentCloudPolicyStoreUpdated. | 148 // through OnComponentCloudPolicyStoreUpdated. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 157 } | 162 } |
| 158 | 163 |
| 159 void ComponentCloudPolicyService::Backend::UpdateExternalPolicy( | 164 void ComponentCloudPolicyService::Backend::UpdateExternalPolicy( |
| 160 scoped_ptr<em::PolicyFetchResponse> response) { | 165 scoped_ptr<em::PolicyFetchResponse> response) { |
| 161 updater_->UpdateExternalPolicy(response.Pass()); | 166 updater_->UpdateExternalPolicy(response.Pass()); |
| 162 } | 167 } |
| 163 | 168 |
| 164 void ComponentCloudPolicyService::Backend:: | 169 void ComponentCloudPolicyService::Backend:: |
| 165 OnComponentCloudPolicyStoreUpdated() { | 170 OnComponentCloudPolicyStoreUpdated() { |
| 166 if (!schema_map_) { | 171 if (!schema_map_) { |
| 167 // Ignore notifications triggered by the initial Purge. | 172 // Ignore notifications triggered by the initial Purge or Clear. |
| 168 return; | 173 return; |
| 169 } | 174 } |
| 170 | 175 |
| 171 scoped_ptr<PolicyBundle> bundle(new PolicyBundle); | 176 scoped_ptr<PolicyBundle> bundle(new PolicyBundle); |
| 172 bundle->CopyFrom(store_.policy()); | 177 bundle->CopyFrom(store_.policy()); |
| 173 schema_map_->FilterBundle(bundle.get()); | 178 schema_map_->FilterBundle(bundle.get()); |
| 174 service_task_runner_->PostTask( | 179 service_task_runner_->PostTask( |
| 175 FROM_HERE, | 180 FROM_HERE, |
| 176 base::Bind(&ComponentCloudPolicyService::OnPolicyUpdated, | 181 base::Bind(&ComponentCloudPolicyService::OnPolicyUpdated, |
| 177 service_, | 182 service_, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 195 | 200 |
| 196 if (removed) { | 201 if (removed) { |
| 197 for (size_t i = 0; i < removed->size(); ++i) | 202 for (size_t i = 0; i < removed->size(); ++i) |
| 198 updater_->CancelUpdate((*removed)[i]); | 203 updater_->CancelUpdate((*removed)[i]); |
| 199 } | 204 } |
| 200 } | 205 } |
| 201 | 206 |
| 202 ComponentCloudPolicyService::ComponentCloudPolicyService( | 207 ComponentCloudPolicyService::ComponentCloudPolicyService( |
| 203 Delegate* delegate, | 208 Delegate* delegate, |
| 204 SchemaRegistry* schema_registry, | 209 SchemaRegistry* schema_registry, |
| 205 CloudPolicyStore* store, | 210 CloudPolicyCore* core, |
| 206 scoped_ptr<ResourceCache> cache, | 211 scoped_ptr<ResourceCache> cache, |
| 207 CloudPolicyClient* client, | |
| 208 scoped_refptr<net::URLRequestContextGetter> request_context, | 212 scoped_refptr<net::URLRequestContextGetter> request_context, |
| 209 scoped_refptr<base::SequencedTaskRunner> backend_task_runner, | 213 scoped_refptr<base::SequencedTaskRunner> backend_task_runner, |
| 210 scoped_refptr<base::SequencedTaskRunner> io_task_runner) | 214 scoped_refptr<base::SequencedTaskRunner> io_task_runner) |
| 211 : delegate_(delegate), | 215 : delegate_(delegate), |
| 212 schema_registry_(schema_registry), | 216 schema_registry_(schema_registry), |
| 213 store_(store), | 217 core_(core), |
| 214 client_(client), | |
| 215 request_context_(request_context), | 218 request_context_(request_context), |
| 216 backend_task_runner_(backend_task_runner), | 219 backend_task_runner_(backend_task_runner), |
| 217 io_task_runner_(io_task_runner), | 220 io_task_runner_(io_task_runner), |
| 218 current_schema_map_(new SchemaMap), | 221 current_schema_map_(new SchemaMap), |
| 219 is_initialized_(false), | 222 loaded_initial_policy_(false), |
| 220 has_credentials_(false), | 223 is_registered_for_cloud_policy_(false), |
| 221 weak_ptr_factory_(this) { | 224 weak_ptr_factory_(this) { |
| 222 schema_registry_->AddObserver(this); | |
| 223 store_->AddObserver(this); | |
| 224 client_->AddObserver(this); | |
| 225 | |
| 226 external_policy_data_fetcher_backend_.reset( | 225 external_policy_data_fetcher_backend_.reset( |
| 227 new ExternalPolicyDataFetcherBackend(io_task_runner_, request_context)); | 226 new ExternalPolicyDataFetcherBackend(io_task_runner_, request_context)); |
| 228 | 227 |
| 229 backend_.reset( | 228 backend_.reset( |
| 230 new Backend(weak_ptr_factory_.GetWeakPtr(), | 229 new Backend(weak_ptr_factory_.GetWeakPtr(), |
| 231 backend_task_runner_, | 230 backend_task_runner_, |
| 232 base::MessageLoopProxy::current(), | 231 base::MessageLoopProxy::current(), |
| 233 cache.Pass(), | 232 cache.Pass(), |
| 234 external_policy_data_fetcher_backend_->CreateFrontend( | 233 external_policy_data_fetcher_backend_->CreateFrontend( |
| 235 backend_task_runner_))); | 234 backend_task_runner_))); |
| 236 | 235 |
| 237 if (store_->is_initialized()) | 236 schema_registry_->AddObserver(this); |
| 238 OnStoreLoaded(store_); | 237 core_->store()->AddObserver(this); |
| 238 |
| 239 // Wait for the store and the schema registry to become ready before |
| 240 // initializing the backend, so that it can get the initial list of |
| 241 // components and the cached credentials (if any) to validate the cached |
| 242 // policies. |
| 243 if (core_->store()->is_initialized()) |
| 244 OnStoreLoaded(core_->store()); |
| 239 } | 245 } |
| 240 | 246 |
| 241 ComponentCloudPolicyService::~ComponentCloudPolicyService() { | 247 ComponentCloudPolicyService::~ComponentCloudPolicyService() { |
| 242 DCHECK(CalledOnValidThread()); | 248 DCHECK(CalledOnValidThread()); |
| 249 |
| 243 schema_registry_->RemoveObserver(this); | 250 schema_registry_->RemoveObserver(this); |
| 244 store_->RemoveObserver(this); | 251 core_->store()->RemoveObserver(this); |
| 245 client_->RemoveObserver(this); | 252 core_->RemoveObserver(this); |
| 246 | 253 if (core_->client()) |
| 247 // Remove all the namespaces from |client_| but don't send this empty schema | 254 OnCoreDisconnecting(core_); |
| 248 // to the backend, to avoid dropping the caches. | |
| 249 if (is_initialized()) { | |
| 250 scoped_refptr<SchemaMap> empty(new SchemaMap); | |
| 251 SetCurrentSchema(empty, false); | |
| 252 } | |
| 253 | 255 |
| 254 io_task_runner_->DeleteSoon(FROM_HERE, | 256 io_task_runner_->DeleteSoon(FROM_HERE, |
| 255 external_policy_data_fetcher_backend_.release()); | 257 external_policy_data_fetcher_backend_.release()); |
| 256 backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release()); | 258 backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release()); |
| 257 } | 259 } |
| 258 | 260 |
| 259 // static | 261 // static |
| 260 bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) { | 262 bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) { |
| 261 return ComponentCloudPolicyStore::SupportsDomain(domain); | 263 return ComponentCloudPolicyStore::SupportsDomain(domain); |
| 262 } | 264 } |
| 263 | 265 |
| 266 void ComponentCloudPolicyService::OnSchemaRegistryReady() { |
| 267 DCHECK(CalledOnValidThread()); |
| 268 InitializeIfReady(); |
| 269 } |
| 270 |
| 271 void ComponentCloudPolicyService::OnSchemaRegistryUpdated( |
| 272 bool has_new_schemas) { |
| 273 DCHECK(CalledOnValidThread()); |
| 274 |
| 275 // Ignore schema updates until the backend is initialized. |
| 276 // OnBackendInitialized() will send the current schema to the backend again, |
| 277 // in case it was updated before the backend initialized. |
| 278 if (!loaded_initial_policy_) |
| 279 return; |
| 280 |
| 281 SetCurrentSchema(); |
| 282 } |
| 283 |
| 284 void ComponentCloudPolicyService::OnCoreConnected(CloudPolicyCore* core) { |
| 285 DCHECK(CalledOnValidThread()); |
| 286 DCHECK_EQ(core_, core); |
| 287 |
| 288 core_->client()->AddObserver(this); |
| 289 |
| 290 // Immediately load any PolicyFetchResponses that the client may already |
| 291 // have. |
| 292 OnPolicyFetched(core_->client()); |
| 293 |
| 294 // Register the current namespaces at the client. |
| 295 current_schema_map_ = new SchemaMap(); |
| 296 SetCurrentSchema(); |
| 297 } |
| 298 |
| 299 void ComponentCloudPolicyService::OnCoreDisconnecting(CloudPolicyCore* core) { |
| 300 DCHECK(CalledOnValidThread()); |
| 301 DCHECK_EQ(core_, core); |
| 302 |
| 303 core_->client()->RemoveObserver(this); |
| 304 |
| 305 // Remove all the namespaces from the client. |
| 306 scoped_refptr<SchemaMap> empty = new SchemaMap(); |
| 307 PolicyNamespaceList removed; |
| 308 PolicyNamespaceList added; |
| 309 empty->GetChanges(current_schema_map_, &removed, &added); |
| 310 for (size_t i = 0; i < removed.size(); ++i) { |
| 311 PolicyNamespaceKey key; |
| 312 if (ToPolicyNamespaceKey(removed[i], &key)) |
| 313 core_->client()->RemoveNamespaceToFetch(key); |
| 314 } |
| 315 } |
| 316 |
| 317 void ComponentCloudPolicyService::OnRefreshSchedulerStarted( |
| 318 CloudPolicyCore* core) { |
| 319 // Ignored. |
| 320 } |
| 321 |
| 322 void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) { |
| 323 DCHECK(CalledOnValidThread()); |
| 324 DCHECK_EQ(core_->store(), store); |
| 325 |
| 326 const bool was_registered_before = is_registered_for_cloud_policy_; |
| 327 |
| 328 // Send the current credentials to the backend; do this whenever the store |
| 329 // updates, to handle the case of the user registering for policy after the |
| 330 // session starts, or the user signing out. |
| 331 const em::PolicyData* policy = core_->store()->policy(); |
| 332 std::string username; |
| 333 std::string request_token; |
| 334 if (policy && policy->has_username() && policy->has_request_token()) { |
| 335 is_registered_for_cloud_policy_ = true; |
| 336 username = policy->username(); |
| 337 request_token = policy->request_token(); |
| 338 } else { |
| 339 is_registered_for_cloud_policy_ = false; |
| 340 } |
| 341 |
| 342 // Empty credentials will wipe the cache. |
| 343 backend_task_runner_->PostTask(FROM_HERE, |
| 344 base::Bind(&Backend::SetCredentials, |
| 345 base::Unretained(backend_.get()), |
| 346 username, |
| 347 request_token)); |
| 348 |
| 349 if (!loaded_initial_policy_) { |
| 350 // This is the initial load; check if we're ready to initialize the |
| 351 // backend, regardless of the signin state. |
| 352 InitializeIfReady(); |
| 353 } else if (!was_registered_before && is_registered_for_cloud_policy_) { |
| 354 // We are already initialized, but just sent credentials to the backend for |
| 355 // the first time; this means that the user was not registered for cloud |
| 356 // policy on startup but registered during the session. |
| 357 // |
| 358 // When that happens, OnPolicyFetched() is sent to observers before the |
| 359 // CloudPolicyStore gets a chance to verify the user policy. In those cases, |
| 360 // the backend gets the PolicyFetchResponses before it has the credentials |
| 361 // and therefore the validation of those responses fails. |
| 362 // Reload any PolicyFetchResponses that the client may have now so that |
| 363 // validation is retried with the credentials in place. |
| 364 if (core_->client()) |
| 365 OnPolicyFetched(core_->client()); |
| 366 } |
| 367 } |
| 368 |
| 369 void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) { |
| 370 DCHECK(CalledOnValidThread()); |
| 371 OnStoreLoaded(store); |
| 372 } |
| 373 |
| 264 void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) { | 374 void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) { |
| 265 DCHECK(CalledOnValidThread()); | 375 DCHECK(CalledOnValidThread()); |
| 266 DCHECK_EQ(client_, client); | 376 DCHECK_EQ(core_->client(), client); |
| 267 | 377 |
| 268 if (!is_initialized() || !has_credentials_) | 378 if (!is_registered_for_cloud_policy_) { |
| 379 // Trying to load any policies now will fail validation. An OnStoreLoaded() |
| 380 // notification should follow soon, after the main user policy has been |
| 381 // validated and stored. |
| 269 return; | 382 return; |
| 383 } |
| 270 | 384 |
| 271 // Pass each PolicyFetchResponse whose policy type is registered to the | 385 // Pass each PolicyFetchResponse whose policy type is registered to the |
| 272 // Backend. | 386 // Backend. |
| 273 const CloudPolicyClient::ResponseMap& responses = client_->responses(); | 387 const CloudPolicyClient::ResponseMap& responses = |
| 388 core_->client()->responses(); |
| 274 for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin(); | 389 for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin(); |
| 275 it != responses.end(); ++it) { | 390 it != responses.end(); ++it) { |
| 276 PolicyNamespace ns; | 391 PolicyNamespace ns; |
| 277 if (ToPolicyNamespace(it->first, &ns) && | 392 if (ToPolicyNamespace(it->first, &ns) && |
| 278 current_schema_map_->GetSchema(ns)) { | 393 current_schema_map_->GetSchema(ns)) { |
| 279 scoped_ptr<em::PolicyFetchResponse> response( | 394 scoped_ptr<em::PolicyFetchResponse> response( |
| 280 new em::PolicyFetchResponse(*it->second)); | 395 new em::PolicyFetchResponse(*it->second)); |
| 281 backend_task_runner_->PostTask( | 396 backend_task_runner_->PostTask( |
| 282 FROM_HERE, | 397 FROM_HERE, |
| 283 base::Bind(&Backend::UpdateExternalPolicy, | 398 base::Bind(&Backend::UpdateExternalPolicy, |
| 284 base::Unretained(backend_.get()), | 399 base::Unretained(backend_.get()), |
| 285 base::Passed(&response))); | 400 base::Passed(&response))); |
| 286 } | 401 } |
| 287 } | 402 } |
| 288 } | 403 } |
| 289 | 404 |
| 290 void ComponentCloudPolicyService::OnRegistrationStateChanged( | 405 void ComponentCloudPolicyService::OnRegistrationStateChanged( |
| 291 CloudPolicyClient* client) { | 406 CloudPolicyClient* client) { |
| 292 DCHECK(CalledOnValidThread()); | 407 DCHECK(CalledOnValidThread()); |
| 293 // Ignored. | 408 // Ignored; the registration state is tracked by looking at the |
| 409 // CloudPolicyStore instead. |
| 294 } | 410 } |
| 295 | 411 |
| 296 void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) { | 412 void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) { |
| 297 DCHECK(CalledOnValidThread()); | 413 DCHECK(CalledOnValidThread()); |
| 298 // Ignored. | 414 // Ignored. |
| 299 } | 415 } |
| 300 | 416 |
| 301 void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) { | |
| 302 DCHECK(CalledOnValidThread()); | |
| 303 DCHECK_EQ(store_, store); | |
| 304 | |
| 305 if (!store_->is_initialized()) | |
| 306 return; | |
| 307 | |
| 308 const em::PolicyData* policy = store_->policy(); | |
| 309 if (!has_credentials_ && policy && policy->has_username() && | |
| 310 policy->has_request_token()) { | |
| 311 // Send the current credentials to the backend, if they haven't been sent | |
| 312 // before. Usually this happens at startup if the user already had a cached | |
| 313 // cloud policy; otherwise it happens right after the initial registration | |
| 314 // for cloud policy. | |
| 315 backend_task_runner_->PostTask(FROM_HERE, | |
| 316 base::Bind(&Backend::SetCredentials, | |
| 317 base::Unretained(backend_.get()), | |
| 318 policy->username(), | |
| 319 policy->request_token())); | |
| 320 has_credentials_ = true; | |
| 321 if (is_initialized()) { | |
| 322 // This was the first policy fetch for this client. Process any | |
| 323 // PolicyFetchResponses that the client may have now; processing them | |
| 324 // before the credentials were sent to the backend would fail validation. | |
| 325 OnPolicyFetched(client_); | |
| 326 } | |
| 327 } | |
| 328 | |
| 329 if (!is_initialized()) | |
| 330 InitializeIfReady(); | |
| 331 } | |
| 332 | |
| 333 void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) { | |
| 334 DCHECK(CalledOnValidThread()); | |
| 335 OnStoreLoaded(store); | |
| 336 } | |
| 337 | |
| 338 void ComponentCloudPolicyService::OnSchemaRegistryReady() { | |
| 339 DCHECK(CalledOnValidThread()); | |
| 340 InitializeIfReady(); | |
| 341 } | |
| 342 | |
| 343 void ComponentCloudPolicyService::OnSchemaRegistryUpdated( | |
| 344 bool has_new_schemas) { | |
| 345 DCHECK(CalledOnValidThread()); | |
| 346 | |
| 347 if (!is_initialized()) | |
| 348 return; | |
| 349 | |
| 350 // When an extension is reloaded or updated, it triggers an unregister quickly | |
| 351 // followed by a register in the SchemaRegistry. If the intermediate version | |
| 352 // of the SchemaMap is passed to the backend then it will drop the cached | |
| 353 // policy for that extension and will trigger a new policy fetch soon after. | |
| 354 // Delaying the schema update here coalesces both updates into one, and the | |
| 355 // new schema will equal the older version in case of extension updates. | |
| 356 // | |
| 357 // TODO(joaodasilva): Increase this delay to 10 seconds. For now it's | |
| 358 // immediate so that tests don't get delayed. | |
| 359 schema_update_timer_.Start( | |
| 360 FROM_HERE, | |
| 361 base::TimeDelta::FromSeconds(0), | |
| 362 base::Bind(&ComponentCloudPolicyService::SetCurrentSchema, | |
| 363 base::Unretained(this), | |
| 364 schema_registry_->schema_map(), | |
| 365 true)); | |
| 366 } | |
| 367 | |
| 368 void ComponentCloudPolicyService::InitializeIfReady() { | 417 void ComponentCloudPolicyService::InitializeIfReady() { |
| 369 DCHECK(CalledOnValidThread()); | 418 DCHECK(CalledOnValidThread()); |
| 370 if (!schema_registry_->IsReady() || !store_->is_initialized()) | 419 if (!schema_registry_->IsReady() || !core_->store()->is_initialized()) |
| 371 return; | 420 return; |
| 421 // The initial list of components is ready. Initialize the backend now, which |
| 422 // will call back to OnBackendInitialized. |
| 372 backend_task_runner_->PostTask(FROM_HERE, | 423 backend_task_runner_->PostTask(FROM_HERE, |
| 373 base::Bind(&Backend::Init, | 424 base::Bind(&Backend::Init, |
| 374 base::Unretained(backend_.get()), | 425 base::Unretained(backend_.get()), |
| 375 schema_registry_->schema_map())); | 426 schema_registry_->schema_map())); |
| 376 } | 427 } |
| 377 | 428 |
| 378 void ComponentCloudPolicyService::OnBackendInitialized( | 429 void ComponentCloudPolicyService::OnBackendInitialized( |
| 379 scoped_ptr<PolicyBundle> initial_policy) { | 430 scoped_ptr<PolicyBundle> initial_policy) { |
| 380 DCHECK(CalledOnValidThread()); | 431 DCHECK(CalledOnValidThread()); |
| 381 | 432 |
| 382 is_initialized_ = true; | 433 loaded_initial_policy_ = true; |
| 383 | 434 |
| 384 // Send the current schema to the backend, in case it has changed while the | 435 // We're now ready to serve the initial policy; notify the policy observers. |
| 385 // backend was initializing. | 436 OnPolicyUpdated(initial_policy.Pass()); |
| 386 SetCurrentSchema(schema_registry_->schema_map(), true); | |
| 387 | 437 |
| 388 // Process any PolicyFetchResponses that the client may already have, or that | 438 // Start observing the core and tracking the state of the client. |
| 389 // may have been received while the backend was initializing. | 439 core_->AddObserver(this); |
| 390 OnPolicyFetched(client_); | |
| 391 | 440 |
| 392 // Finally tell the Delegate that the initial policy is available. | 441 if (core_->client()) { |
| 393 OnPolicyUpdated(initial_policy.Pass()); | 442 OnCoreConnected(core_); |
| 443 } else { |
| 444 // Send the current schema to the backend, in case it has changed while the |
| 445 // backend was initializing. OnCoreConnected() also does this if a client is |
| 446 // already connected. |
| 447 SetCurrentSchema(); |
| 448 } |
| 394 } | 449 } |
| 395 | 450 |
| 396 void ComponentCloudPolicyService::SetCurrentSchema( | 451 void ComponentCloudPolicyService::SetCurrentSchema() { |
| 397 const scoped_refptr<SchemaMap>& new_schema_map, | |
| 398 bool send_to_backend) { | |
| 399 DCHECK(CalledOnValidThread()); | 452 DCHECK(CalledOnValidThread()); |
| 400 DCHECK(is_initialized()); | |
| 401 | 453 |
| 402 scoped_ptr<PolicyNamespaceList> removed(new PolicyNamespaceList); | 454 scoped_ptr<PolicyNamespaceList> removed(new PolicyNamespaceList); |
| 403 PolicyNamespaceList added; | 455 PolicyNamespaceList added; |
| 456 const scoped_refptr<SchemaMap>& new_schema_map = |
| 457 schema_registry_->schema_map(); |
| 404 new_schema_map->GetChanges(current_schema_map_, removed.get(), &added); | 458 new_schema_map->GetChanges(current_schema_map_, removed.get(), &added); |
| 405 | 459 |
| 406 current_schema_map_ = new_schema_map; | 460 current_schema_map_ = new_schema_map; |
| 407 | 461 |
| 408 for (size_t i = 0; i < removed->size(); ++i) { | 462 if (core_->client()) { |
| 409 PolicyNamespaceKey key; | 463 for (size_t i = 0; i < removed->size(); ++i) { |
| 410 if (ToPolicyNamespaceKey((*removed)[i], &key)) | 464 PolicyNamespaceKey key; |
| 411 client_->RemoveNamespaceToFetch(key); | 465 if (ToPolicyNamespaceKey((*removed)[i], &key)) |
| 466 core_->client()->RemoveNamespaceToFetch(key); |
| 467 } |
| 468 |
| 469 bool added_namespaces_to_client = false; |
| 470 for (size_t i = 0; i < added.size(); ++i) { |
| 471 PolicyNamespaceKey key; |
| 472 if (ToPolicyNamespaceKey(added[i], &key)) { |
| 473 core_->client()->AddNamespaceToFetch(key); |
| 474 added_namespaces_to_client = true; |
| 475 } |
| 476 } |
| 477 |
| 478 if (added_namespaces_to_client) |
| 479 core_->RefreshSoon(); |
| 412 } | 480 } |
| 413 | 481 |
| 414 bool added_namespaces_to_client = false; | 482 backend_task_runner_->PostTask(FROM_HERE, |
| 415 for (size_t i = 0; i < added.size(); ++i) { | 483 base::Bind(&Backend::OnSchemasUpdated, |
| 416 PolicyNamespaceKey key; | 484 base::Unretained(backend_.get()), |
| 417 if (ToPolicyNamespaceKey(added[i], &key)) { | 485 current_schema_map_, |
| 418 client_->AddNamespaceToFetch(key); | 486 base::Passed(&removed))); |
| 419 added_namespaces_to_client = true; | |
| 420 } | |
| 421 } | |
| 422 | |
| 423 if (added_namespaces_to_client) | |
| 424 delegate_->OnComponentCloudPolicyRefreshNeeded(); | |
| 425 | |
| 426 if (send_to_backend) { | |
| 427 backend_task_runner_->PostTask(FROM_HERE, | |
| 428 base::Bind(&Backend::OnSchemasUpdated, | |
| 429 base::Unretained(backend_.get()), | |
| 430 current_schema_map_, | |
| 431 base::Passed(&removed))); | |
| 432 } | |
| 433 } | 487 } |
| 434 | 488 |
| 435 void ComponentCloudPolicyService::OnPolicyUpdated( | 489 void ComponentCloudPolicyService::OnPolicyUpdated( |
| 436 scoped_ptr<PolicyBundle> policy) { | 490 scoped_ptr<PolicyBundle> policy) { |
| 437 DCHECK(CalledOnValidThread()); | 491 DCHECK(CalledOnValidThread()); |
| 438 policy_.Swap(policy.get()); | 492 policy_.Swap(policy.get()); |
| 439 delegate_->OnComponentCloudPolicyUpdated(); | 493 delegate_->OnComponentCloudPolicyUpdated(); |
| 440 } | 494 } |
| 441 | 495 |
| 442 } // namespace policy | 496 } // namespace policy |
| OLD | NEW |