Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5026)

Unified Diff: chrome/browser/policy/cloud/component_cloud_policy_service.cc

Issue 72793003: ComponentCloudPolicyService tracks the signin state. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/policy/cloud/component_cloud_policy_service.cc
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_service.cc b/chrome/browser/policy/cloud/component_cloud_policy_service.cc
index 295c67074ae3d584f88eaac9bf6b70f20da52a83..78ea295f7e5e6418b61b840e82e01c35db8dd818 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_service.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_service.cc
@@ -12,8 +12,8 @@
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/sequenced_task_runner.h"
-#include "base/time/time.h"
#include "chrome/browser/policy/cloud/cloud_policy_constants.h"
+#include "chrome/browser/policy/cloud/cloud_policy_refresh_scheduler.h"
#include "chrome/browser/policy/cloud/component_cloud_policy_store.h"
#include "chrome/browser/policy/cloud/component_cloud_policy_updater.h"
#include "chrome/browser/policy/cloud/external_policy_data_fetcher.h"
@@ -130,7 +130,12 @@ ComponentCloudPolicyService::Backend::~Backend() {}
void ComponentCloudPolicyService::Backend::SetCredentials(
const std::string& username,
const std::string& dm_token) {
- store_.SetCredentials(username, dm_token);
+ if (username.empty() || dm_token.empty()) {
+ // No sign-in credentials, so drop any cached policy.
+ store_.Clear();
+ } else {
+ store_.SetCredentials(username, dm_token);
+ }
}
void ComponentCloudPolicyService::Backend::Init(
@@ -164,7 +169,7 @@ void ComponentCloudPolicyService::Backend::UpdateExternalPolicy(
void ComponentCloudPolicyService::Backend::
OnComponentCloudPolicyStoreUpdated() {
if (!schema_map_) {
- // Ignore notifications triggered by the initial Purge.
+ // Ignore notifications triggered by the initial Purge or Clear.
return;
}
@@ -202,27 +207,21 @@ void ComponentCloudPolicyService::Backend::OnSchemasUpdated(
ComponentCloudPolicyService::ComponentCloudPolicyService(
Delegate* delegate,
SchemaRegistry* schema_registry,
- CloudPolicyStore* store,
+ CloudPolicyCore* core,
scoped_ptr<ResourceCache> cache,
- CloudPolicyClient* client,
scoped_refptr<net::URLRequestContextGetter> request_context,
scoped_refptr<base::SequencedTaskRunner> backend_task_runner,
scoped_refptr<base::SequencedTaskRunner> io_task_runner)
: delegate_(delegate),
schema_registry_(schema_registry),
- store_(store),
- client_(client),
+ core_(core),
request_context_(request_context),
backend_task_runner_(backend_task_runner),
io_task_runner_(io_task_runner),
current_schema_map_(new SchemaMap),
- is_initialized_(false),
- has_credentials_(false),
+ loaded_initial_policy_(false),
+ is_registered_for_cloud_policy_(false),
weak_ptr_factory_(this) {
- schema_registry_->AddObserver(this);
- store_->AddObserver(this);
- client_->AddObserver(this);
-
external_policy_data_fetcher_backend_.reset(
new ExternalPolicyDataFetcherBackend(io_task_runner_, request_context));
@@ -234,22 +233,25 @@ ComponentCloudPolicyService::ComponentCloudPolicyService(
external_policy_data_fetcher_backend_->CreateFrontend(
backend_task_runner_)));
- if (store_->is_initialized())
- OnStoreLoaded(store_);
+ schema_registry_->AddObserver(this);
+ core_->store()->AddObserver(this);
+
+ // Wait for the store and the schema registry to become ready before
+ // initializing the backend, so that it can get the initial list of
+ // components and the cached credentials (if any) to validate the cached
+ // policies.
+ if (core_->store()->is_initialized())
+ OnStoreLoaded(core_->store());
}
ComponentCloudPolicyService::~ComponentCloudPolicyService() {
DCHECK(CalledOnValidThread());
+
schema_registry_->RemoveObserver(this);
- store_->RemoveObserver(this);
- client_->RemoveObserver(this);
-
- // Remove all the namespaces from |client_| but don't send this empty schema
- // to the backend, to avoid dropping the caches.
- if (is_initialized()) {
- scoped_refptr<SchemaMap> empty(new SchemaMap);
- SetCurrentSchema(empty, false);
- }
+ core_->store()->RemoveObserver(this);
+ core_->RemoveObserver(this);
+ if (core_->client())
+ OnCoreDisconnecting(core_);
io_task_runner_->DeleteSoon(FROM_HERE,
external_policy_data_fetcher_backend_.release());
@@ -261,16 +263,129 @@ bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) {
return ComponentCloudPolicyStore::SupportsDomain(domain);
}
+void ComponentCloudPolicyService::OnSchemaRegistryReady() {
+ DCHECK(CalledOnValidThread());
+ InitializeIfReady();
+}
+
+void ComponentCloudPolicyService::OnSchemaRegistryUpdated(
+ bool has_new_schemas) {
+ DCHECK(CalledOnValidThread());
+
+ // Ignore schema updates until the backend is initialized.
+ // OnBackendInitialized() will send the current schema to the backend again,
+ // in case it was updated before the backend initialized.
+ if (!loaded_initial_policy_)
+ return;
+
+ SetCurrentSchema();
+}
+
+void ComponentCloudPolicyService::OnCoreConnected(CloudPolicyCore* core) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(core_, core);
+
+ core_->client()->AddObserver(this);
+
+ // Immediately load any PolicyFetchResponses that the client may already
+ // have.
+ OnPolicyFetched(core_->client());
+
+ // Register the current namespaces at the client.
+ current_schema_map_ = new SchemaMap();
+ SetCurrentSchema();
+}
+
+void ComponentCloudPolicyService::OnCoreDisconnecting(CloudPolicyCore* core) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(core_, core);
+
+ core_->client()->RemoveObserver(this);
+
+ // Remove all the namespaces from the client.
+ scoped_refptr<SchemaMap> empty = new SchemaMap();
+ PolicyNamespaceList removed;
+ PolicyNamespaceList added;
+ empty->GetChanges(current_schema_map_, &removed, &added);
+ for (size_t i = 0; i < removed.size(); ++i) {
+ PolicyNamespaceKey key;
+ if (ToPolicyNamespaceKey(removed[i], &key))
+ core_->client()->RemoveNamespaceToFetch(key);
+ }
+}
+
+void ComponentCloudPolicyService::OnRefreshSchedulerStarted(
+ CloudPolicyCore* core) {
+ // Ignored.
+}
+
+void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(core_->store(), store);
+
+ const bool was_registered_before = is_registered_for_cloud_policy_;
+
+ // Send the current credentials to the backend; do this whenever the store
+ // updates, to handle the case of the user registering for policy after the
+ // session starts, or the user signing out.
+ const em::PolicyData* policy = core_->store()->policy();
+ std::string username;
+ std::string request_token;
+ if (policy && policy->has_username() && policy->has_request_token()) {
+ is_registered_for_cloud_policy_ = true;
+ username = policy->username();
+ request_token = policy->request_token();
+ } else {
+ is_registered_for_cloud_policy_ = false;
+ }
+
+ // Empty credentials will wipe the cache.
+ backend_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&Backend::SetCredentials,
+ base::Unretained(backend_.get()),
+ username,
+ request_token));
+
+ if (!loaded_initial_policy_) {
+ // This is the initial load; check if we're ready to initialize the
+ // backend, regardless of the signin state.
+ InitializeIfReady();
+ } else if (!was_registered_before && is_registered_for_cloud_policy_) {
+ // We are already initialized, but just sent credentials to the backend for
+ // the first time; this means that the user was not registered for cloud
+ // policy on startup but registered during the session.
+ //
+ // When that happens, OnPolicyFetched() is sent to observers before the
+ // CloudPolicyStore gets a chance to verify the user policy. In those cases,
+ // the backend gets the PolicyFetchResponses before it has the credentials
+ // and therefore the validation of those responses fails.
+ // Reload any PolicyFetchResponses that the client may have now so that
+ // validation is retried with the credentials in place.
+ if (core_->client())
+ OnPolicyFetched(core_->client());
+ }
+}
+
+void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) {
+ DCHECK(CalledOnValidThread());
+ OnStoreLoaded(store);
+}
+
void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) {
DCHECK(CalledOnValidThread());
- DCHECK_EQ(client_, client);
+ DCHECK_EQ(core_->client(), client);
- if (!is_initialized() || !has_credentials_)
+ if (!is_registered_for_cloud_policy_) {
+ // Trying to load any policies now will fail validation. An OnStoreLoaded()
+ // notification should follow soon, after the main user policy has been
+ // validated and stored.
return;
+ }
// Pass each PolicyFetchResponse whose policy type is registered to the
// Backend.
- const CloudPolicyClient::ResponseMap& responses = client_->responses();
+ const CloudPolicyClient::ResponseMap& responses =
+ core_->client()->responses();
for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin();
it != responses.end(); ++it) {
PolicyNamespace ns;
@@ -290,7 +405,8 @@ void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) {
void ComponentCloudPolicyService::OnRegistrationStateChanged(
CloudPolicyClient* client) {
DCHECK(CalledOnValidThread());
- // Ignored.
+ // Ignored; the registration state is tracked by looking at the
+ // CloudPolicyStore instead.
}
void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) {
@@ -298,77 +414,12 @@ void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) {
// Ignored.
}
-void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(store_, store);
-
- if (!store_->is_initialized())
- return;
-
- const em::PolicyData* policy = store_->policy();
- if (!has_credentials_ && policy && policy->has_username() &&
- policy->has_request_token()) {
- // Send the current credentials to the backend, if they haven't been sent
- // before. Usually this happens at startup if the user already had a cached
- // cloud policy; otherwise it happens right after the initial registration
- // for cloud policy.
- backend_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Backend::SetCredentials,
- base::Unretained(backend_.get()),
- policy->username(),
- policy->request_token()));
- has_credentials_ = true;
- if (is_initialized()) {
- // This was the first policy fetch for this client. Process any
- // PolicyFetchResponses that the client may have now; processing them
- // before the credentials were sent to the backend would fail validation.
- OnPolicyFetched(client_);
- }
- }
-
- if (!is_initialized())
- InitializeIfReady();
-}
-
-void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) {
- DCHECK(CalledOnValidThread());
- OnStoreLoaded(store);
-}
-
-void ComponentCloudPolicyService::OnSchemaRegistryReady() {
- DCHECK(CalledOnValidThread());
- InitializeIfReady();
-}
-
-void ComponentCloudPolicyService::OnSchemaRegistryUpdated(
- bool has_new_schemas) {
- DCHECK(CalledOnValidThread());
-
- if (!is_initialized())
- return;
-
- // When an extension is reloaded or updated, it triggers an unregister quickly
- // followed by a register in the SchemaRegistry. If the intermediate version
- // of the SchemaMap is passed to the backend then it will drop the cached
- // policy for that extension and will trigger a new policy fetch soon after.
- // Delaying the schema update here coalesces both updates into one, and the
- // new schema will equal the older version in case of extension updates.
- //
- // TODO(joaodasilva): Increase this delay to 10 seconds. For now it's
- // immediate so that tests don't get delayed.
- schema_update_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromSeconds(0),
- base::Bind(&ComponentCloudPolicyService::SetCurrentSchema,
- base::Unretained(this),
- schema_registry_->schema_map(),
- true));
-}
-
void ComponentCloudPolicyService::InitializeIfReady() {
DCHECK(CalledOnValidThread());
- if (!schema_registry_->IsReady() || !store_->is_initialized())
+ if (!schema_registry_->IsReady() || !core_->store()->is_initialized())
return;
+ // The initial list of components is ready. Initialize the backend now, which
+ // will call back to OnBackendInitialized.
backend_task_runner_->PostTask(FROM_HERE,
base::Bind(&Backend::Init,
base::Unretained(backend_.get()),
@@ -379,57 +430,60 @@ void ComponentCloudPolicyService::OnBackendInitialized(
scoped_ptr<PolicyBundle> initial_policy) {
DCHECK(CalledOnValidThread());
- is_initialized_ = true;
+ loaded_initial_policy_ = true;
- // Send the current schema to the backend, in case it has changed while the
- // backend was initializing.
- SetCurrentSchema(schema_registry_->schema_map(), true);
+ // We're now ready to serve the initial policy; notify the policy observers.
+ OnPolicyUpdated(initial_policy.Pass());
- // Process any PolicyFetchResponses that the client may already have, or that
- // may have been received while the backend was initializing.
- OnPolicyFetched(client_);
+ // Start observing the core and tracking the state of the client.
+ core_->AddObserver(this);
- // Finally tell the Delegate that the initial policy is available.
- OnPolicyUpdated(initial_policy.Pass());
+ if (core_->client()) {
+ OnCoreConnected(core_);
+ } else {
+ // Send the current schema to the backend, in case it has changed while the
+ // backend was initializing. OnCoreConnected() also does this if a client is
+ // already connected.
+ SetCurrentSchema();
+ }
}
-void ComponentCloudPolicyService::SetCurrentSchema(
- const scoped_refptr<SchemaMap>& new_schema_map,
- bool send_to_backend) {
+void ComponentCloudPolicyService::SetCurrentSchema() {
DCHECK(CalledOnValidThread());
- DCHECK(is_initialized());
scoped_ptr<PolicyNamespaceList> removed(new PolicyNamespaceList);
PolicyNamespaceList added;
+ const scoped_refptr<SchemaMap>& new_schema_map =
+ schema_registry_->schema_map();
new_schema_map->GetChanges(current_schema_map_, removed.get(), &added);
current_schema_map_ = new_schema_map;
- for (size_t i = 0; i < removed->size(); ++i) {
- PolicyNamespaceKey key;
- if (ToPolicyNamespaceKey((*removed)[i], &key))
- client_->RemoveNamespaceToFetch(key);
- }
-
- bool added_namespaces_to_client = false;
- for (size_t i = 0; i < added.size(); ++i) {
- PolicyNamespaceKey key;
- if (ToPolicyNamespaceKey(added[i], &key)) {
- client_->AddNamespaceToFetch(key);
- added_namespaces_to_client = true;
+ if (core_->client()) {
+ for (size_t i = 0; i < removed->size(); ++i) {
+ PolicyNamespaceKey key;
+ if (ToPolicyNamespaceKey((*removed)[i], &key))
+ core_->client()->RemoveNamespaceToFetch(key);
}
- }
- if (added_namespaces_to_client)
- delegate_->OnComponentCloudPolicyRefreshNeeded();
+ bool added_namespaces_to_client = false;
+ for (size_t i = 0; i < added.size(); ++i) {
+ PolicyNamespaceKey key;
+ if (ToPolicyNamespaceKey(added[i], &key)) {
+ core_->client()->AddNamespaceToFetch(key);
+ added_namespaces_to_client = true;
+ }
+ }
- if (send_to_backend) {
- backend_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Backend::OnSchemasUpdated,
- base::Unretained(backend_.get()),
- current_schema_map_,
- base::Passed(&removed)));
+ if (added_namespaces_to_client)
+ core_->RefreshSoon();
}
+
+ backend_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&Backend::OnSchemasUpdated,
+ base::Unretained(backend_.get()),
+ current_schema_map_,
+ base::Passed(&removed)));
}
void ComponentCloudPolicyService::OnPolicyUpdated(

Powered by Google App Engine
This is Rietveld 408576698