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

Side by Side Diff: chrome/browser/policy/cloud/component_cloud_policy_service.cc

Issue 70863002: Refactored the ComponentCloudPolicyService. (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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <map>
8 #include <string> 7 #include <string>
9 #include <utility>
10 8
11 #include "base/bind.h" 9 #include "base/bind.h"
12 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
13 #include "base/location.h" 11 #include "base/location.h"
14 #include "base/logging.h" 12 #include "base/logging.h"
15 #include "base/message_loop/message_loop_proxy.h" 13 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/pickle.h"
17 #include "base/sequenced_task_runner.h" 14 #include "base/sequenced_task_runner.h"
18 #include "base/stl_util.h" 15 #include "base/time/time.h"
16 #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
19 #include "chrome/browser/policy/cloud/component_cloud_policy_store.h" 17 #include "chrome/browser/policy/cloud/component_cloud_policy_store.h"
20 #include "chrome/browser/policy/cloud/component_cloud_policy_updater.h" 18 #include "chrome/browser/policy/cloud/component_cloud_policy_updater.h"
21 #include "chrome/browser/policy/cloud/external_policy_data_fetcher.h" 19 #include "chrome/browser/policy/cloud/external_policy_data_fetcher.h"
22 #include "chrome/browser/policy/cloud/resource_cache.h" 20 #include "chrome/browser/policy/cloud/resource_cache.h"
23 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 21 #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
24 #include "chrome/browser/policy/schema_map.h" 22 #include "chrome/browser/policy/schema_map.h"
25 #include "components/policy/core/common/schema.h" 23 #include "components/policy/core/common/schema.h"
26 #include "net/url_request/url_request_context_getter.h" 24 #include "net/url_request/url_request_context_getter.h"
27 25
28 namespace em = enterprise_management; 26 namespace em = enterprise_management;
29 27
30 namespace policy { 28 namespace policy {
31 29
32 const char ComponentCloudPolicyService::kComponentNamespaceCache[] =
33 "component-namespace-cache";
34
35 namespace { 30 namespace {
36 31
37 bool NotInSchemaMap(const scoped_refptr<SchemaMap> schema_map, 32 bool NotInSchemaMap(const scoped_refptr<SchemaMap> schema_map,
38 PolicyDomain domain, 33 PolicyDomain domain,
39 const std::string& component_id) { 34 const std::string& component_id) {
40 return schema_map->GetSchema(PolicyNamespace(domain, component_id)) == NULL; 35 return schema_map->GetSchema(PolicyNamespace(domain, component_id)) == NULL;
41 } 36 }
42 37
38 bool ToPolicyNamespaceKey(const PolicyNamespace& ns, PolicyNamespaceKey* key) {
39 if (!ComponentCloudPolicyStore::GetPolicyType(ns.domain, &key->first))
40 return false;
41 key->second = ns.component_id;
42 return true;
43 }
44
45 bool ToPolicyNamespace(const PolicyNamespaceKey& key, PolicyNamespace* ns) {
46 if (!ComponentCloudPolicyStore::GetPolicyDomain(key.first, &ns->domain))
47 return false;
48 ns->component_id = key.second;
49 return true;
50 }
51
43 } // namespace 52 } // namespace
44 53
45 ComponentCloudPolicyService::Delegate::~Delegate() {} 54 ComponentCloudPolicyService::Delegate::~Delegate() {}
46 55
47 // Owns the objects that live on the background thread, and posts back to the 56 // Owns the objects that live on the background thread, and posts back to the
48 // thread that the ComponentCloudPolicyService runs on whenever the policy 57 // thread that the ComponentCloudPolicyService runs on whenever the policy
49 // changes. 58 // changes.
50 class ComponentCloudPolicyService::Backend 59 class ComponentCloudPolicyService::Backend
51 : public ComponentCloudPolicyStore::Delegate { 60 : public ComponentCloudPolicyStore::Delegate {
52 public: 61 public:
53 // This class can be instantiated on any thread but from then on, may be 62 // This class can be instantiated on any thread but from then on, may be
54 // accessed via the |task_runner_| only. Policy changes are posted to the 63 // accessed via the |task_runner_| only. Policy changes are posted to the
55 // |service| via the |service_task_runner|. The |cache| is used to load and 64 // |service| via the |service_task_runner|. The |cache| is used to load and
56 // store local copies of the downloaded policies. 65 // store local copies of the downloaded policies.
57 Backend(base::WeakPtr<ComponentCloudPolicyService> service, 66 Backend(base::WeakPtr<ComponentCloudPolicyService> service,
58 scoped_refptr<base::SequencedTaskRunner> task_runner, 67 scoped_refptr<base::SequencedTaskRunner> task_runner,
59 scoped_refptr<base::SequencedTaskRunner> service_task_runner, 68 scoped_refptr<base::SequencedTaskRunner> service_task_runner,
60 scoped_ptr<ResourceCache> cache); 69 scoped_ptr<ResourceCache> cache,
70 scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher);
71
61 virtual ~Backend(); 72 virtual ~Backend();
62 73
63 // This is invoked right after the constructor but on the background thread. 74 // |username| and |dm_token| will be used to validate the cached policies.
64 // Used to create the store on the right thread. 75 void SetCredentials(const std::string& username, const std::string& dm_token);
65 void Init();
66 76
67 // Reads the initial list of components and the initial policy. 77 // Loads the |store_| and starts downloading updates.
68 void FinalizeInit(); 78 void Init(scoped_refptr<SchemaMap> schema_map);
69
70 // Allows downloading of external data via the |external_policy_data_fetcher|.
71 void Connect(
72 scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher);
73
74 // Stops updating remote data. Cached policies are still served.
75 void Disconnect();
76
77 // Loads the initial policies from the store. |username| and |dm_token| are
78 // used to validate the cached policies.
79 void SetCredentials(const std::string& username, const std::string& dm_token);
80 79
81 // Passes a policy protobuf to the backend, to start its validation and 80 // Passes a policy protobuf to the backend, to start its validation and
82 // eventual download of the policy data on the background thread. 81 // eventual download of the policy data on the background thread.
83 // This is ignored if the backend isn't connected.
84 void UpdateExternalPolicy(scoped_ptr<em::PolicyFetchResponse> response); 82 void UpdateExternalPolicy(scoped_ptr<em::PolicyFetchResponse> response);
85 83
86 // ComponentCloudPolicyStore::Delegate implementation: 84 // ComponentCloudPolicyStore::Delegate implementation:
87 virtual void OnComponentCloudPolicyStoreUpdated() OVERRIDE; 85 virtual void OnComponentCloudPolicyStoreUpdated() OVERRIDE;
88 86
89 // Passes the current SchemaMap so that the disk cache can purge components 87 // Passes the current SchemaMap so that the disk cache can purge components
90 // that aren't being tracked anymore. 88 // that aren't being tracked anymore.
91 void OnSchemasUpdated(scoped_refptr<SchemaMap> schema_map); 89 // |removed| is a list of namespaces that were present in the previous
90 // schema and have been removed in the updated version.
91 void OnSchemasUpdated(scoped_refptr<SchemaMap> schema_map,
92 scoped_ptr<PolicyNamespaceList> removed);
92 93
93 private: 94 private:
94 scoped_ptr<PolicyNamespaceKeys> ReadCachedComponents();
95
96 // The ComponentCloudPolicyService that owns |this|. Used to inform the 95 // The ComponentCloudPolicyService that owns |this|. Used to inform the
97 // |service_| when policy changes. 96 // |service_| when policy changes.
98 base::WeakPtr<ComponentCloudPolicyService> service_; 97 base::WeakPtr<ComponentCloudPolicyService> service_;
99 98
100 // The thread that |this| runs on. Used to post tasks to be run by |this|. 99 // The thread that |this| runs on. Used to post tasks to be run by |this|.
101 scoped_refptr<base::SequencedTaskRunner> task_runner_; 100 scoped_refptr<base::SequencedTaskRunner> task_runner_;
102 101
103 // The thread that the |service_| runs on. Used to post policy changes to the 102 // The thread that the |service_| runs on. Used to post policy changes to the
104 // right thread. 103 // right thread.
105 scoped_refptr<base::SequencedTaskRunner> service_task_runner_; 104 scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
106 105
107 scoped_ptr<ResourceCache> cache_; 106 scoped_ptr<ResourceCache> cache_;
108 scoped_ptr<ComponentCloudPolicyStore> store_; 107 scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher_;
108 ComponentCloudPolicyStore store_;
109 scoped_ptr<ComponentCloudPolicyUpdater> updater_; 109 scoped_ptr<ComponentCloudPolicyUpdater> updater_;
110 scoped_refptr<SchemaMap> schema_map_; 110 scoped_refptr<SchemaMap> schema_map_;
111 111
112 DISALLOW_COPY_AND_ASSIGN(Backend); 112 DISALLOW_COPY_AND_ASSIGN(Backend);
113 }; 113 };
114 114
115 ComponentCloudPolicyService::Backend::Backend( 115 ComponentCloudPolicyService::Backend::Backend(
116 base::WeakPtr<ComponentCloudPolicyService> service, 116 base::WeakPtr<ComponentCloudPolicyService> service,
117 scoped_refptr<base::SequencedTaskRunner> task_runner, 117 scoped_refptr<base::SequencedTaskRunner> task_runner,
118 scoped_refptr<base::SequencedTaskRunner> service_task_runner, 118 scoped_refptr<base::SequencedTaskRunner> service_task_runner,
119 scoped_ptr<ResourceCache> cache) 119 scoped_ptr<ResourceCache> cache,
120 scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher)
120 : service_(service), 121 : service_(service),
121 task_runner_(task_runner), 122 task_runner_(task_runner),
122 service_task_runner_(service_task_runner), 123 service_task_runner_(service_task_runner),
123 cache_(cache.Pass()) {} 124 cache_(cache.Pass()),
125 external_policy_data_fetcher_(external_policy_data_fetcher.Pass()),
126 store_(this, cache_.get()) {}
124 127
125 ComponentCloudPolicyService::Backend::~Backend() {} 128 ComponentCloudPolicyService::Backend::~Backend() {}
126 129
127 void ComponentCloudPolicyService::Backend::Init() { 130 void ComponentCloudPolicyService::Backend::SetCredentials(
128 DCHECK(!store_); 131 const std::string& username,
129 store_.reset(new ComponentCloudPolicyStore(this, cache_.get())); 132 const std::string& dm_token) {
133 store_.SetCredentials(username, dm_token);
130 } 134 }
131 135
132 void ComponentCloudPolicyService::Backend::FinalizeInit() { 136 void ComponentCloudPolicyService::Backend::Init(
133 // Read the components that were cached in the last OnSchemasUpdated() call. 137 scoped_refptr<SchemaMap> schema_map) {
134 scoped_ptr<PolicyNamespaceKeys> components = ReadCachedComponents(); 138 DCHECK(!schema_map_);
135 139
136 // Read the initial policy. 140 OnSchemasUpdated(schema_map, scoped_ptr<PolicyNamespaceList>());
137 store_->Load(); 141
138 scoped_ptr<PolicyBundle> policy(new PolicyBundle); 142 // Read the initial policy. Note that this does not trigger notifications
139 policy->CopyFrom(store_->policy()); 143 // through OnComponentCloudPolicyStoreUpdated.
144 store_.Load();
145 scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
146 bundle->CopyFrom(store_.policy());
147
148 // Start downloading any pending data.
149 updater_.reset(new ComponentCloudPolicyUpdater(
150 task_runner_, external_policy_data_fetcher_.Pass(), &store_));
140 151
141 service_task_runner_->PostTask( 152 service_task_runner_->PostTask(
142 FROM_HERE, 153 FROM_HERE,
143 base::Bind(&ComponentCloudPolicyService::OnBackendInitialized, 154 base::Bind(&ComponentCloudPolicyService::OnBackendInitialized,
144 service_, 155 service_,
145 base::Passed(&components), 156 base::Passed(&bundle)));
146 base::Passed(&policy)));
147 }
148
149 void ComponentCloudPolicyService::Backend::SetCredentials(
150 const std::string& username,
151 const std::string& dm_token) {
152 store_->SetCredentials(username, dm_token);
153 }
154
155 void ComponentCloudPolicyService::Backend::Connect(
156 scoped_ptr<ExternalPolicyDataFetcher> external_policy_data_fetcher) {
157 updater_.reset(new ComponentCloudPolicyUpdater(
158 task_runner_,
159 external_policy_data_fetcher.Pass(),
160 store_.get()));
161 }
162
163 void ComponentCloudPolicyService::Backend::Disconnect() {
164 updater_.reset();
165 } 157 }
166 158
167 void ComponentCloudPolicyService::Backend::UpdateExternalPolicy( 159 void ComponentCloudPolicyService::Backend::UpdateExternalPolicy(
168 scoped_ptr<em::PolicyFetchResponse> response) { 160 scoped_ptr<em::PolicyFetchResponse> response) {
169 if (updater_) 161 updater_->UpdateExternalPolicy(response.Pass());
170 updater_->UpdateExternalPolicy(response.Pass());
171 } 162 }
172 163
173 void ComponentCloudPolicyService::Backend:: 164 void ComponentCloudPolicyService::Backend::
174 OnComponentCloudPolicyStoreUpdated() { 165 OnComponentCloudPolicyStoreUpdated() {
175 if (!schema_map_) { 166 if (!schema_map_) {
176 // No schemas have been registered yet, so keep serving the initial policy 167 // Ignore notifications triggered by the initial Purge.
177 // obtained from FinalizeInit().
178 return; 168 return;
179 } 169 }
180 170
181 scoped_ptr<PolicyBundle> bundle(new PolicyBundle); 171 scoped_ptr<PolicyBundle> bundle(new PolicyBundle);
182 bundle->CopyFrom(store_->policy()); 172 bundle->CopyFrom(store_.policy());
183 schema_map_->FilterBundle(bundle.get()); 173 schema_map_->FilterBundle(bundle.get());
184 service_task_runner_->PostTask( 174 service_task_runner_->PostTask(
185 FROM_HERE, 175 FROM_HERE,
186 base::Bind(&ComponentCloudPolicyService::OnPolicyUpdated, 176 base::Bind(&ComponentCloudPolicyService::OnPolicyUpdated,
187 service_, 177 service_,
188 base::Passed(&bundle))); 178 base::Passed(&bundle)));
189 } 179 }
190 180
191 void ComponentCloudPolicyService::Backend::OnSchemasUpdated( 181 void ComponentCloudPolicyService::Backend::OnSchemasUpdated(
192 scoped_refptr<SchemaMap> schema_map) { 182 scoped_refptr<SchemaMap> schema_map,
193 // Store the current list of components in the cache. 183 scoped_ptr<PolicyNamespaceList> removed) {
184 // Purge any components that have been removed.
194 const DomainMap& domains = schema_map->GetDomains(); 185 const DomainMap& domains = schema_map->GetDomains();
195 for (DomainMap::const_iterator domain = domains.begin(); 186 for (DomainMap::const_iterator domain = domains.begin();
196 domain != domains.end(); ++domain) { 187 domain != domains.end(); ++domain) {
197 std::string domain_policy_type; 188 store_.Purge(domain->first,
198 if (!ComponentCloudPolicyStore::GetPolicyType(domain->first, 189 base::Bind(&NotInSchemaMap, schema_map, domain->first));
199 &domain_policy_type)) {
200 continue;
201 }
202 Pickle pickle;
203 const ComponentMap& components = domain->second;
204 for (ComponentMap::const_iterator comp = components.begin();
205 comp != components.end(); ++comp) {
206 pickle.WriteString(comp->first);
207 }
208 std::string data(reinterpret_cast<const char*>(pickle.data()),
209 pickle.size());
210 cache_->Store(kComponentNamespaceCache, domain_policy_type, data);
211
212 // Purge any components that have been removed.
213 if (store_) {
214 store_->Purge(domain->first,
215 base::Bind(&NotInSchemaMap, schema_map, domain->first));
216 }
217 } 190 }
218 191
219 // Serve policies that may have updated while the backend was waiting for 192 // Set |schema_map_| after purging so that the notifications from the store
220 // the schema_map. 193 // are ignored on the first OnSchemasUpdated() call from Init().
221 const bool trigger_update = !schema_map_;
222 schema_map_ = schema_map; 194 schema_map_ = schema_map;
223 if (trigger_update)
224 OnComponentCloudPolicyStoreUpdated();
225 }
226 195
227 scoped_ptr<ComponentCloudPolicyService::PolicyNamespaceKeys> 196 if (removed) {
228 ComponentCloudPolicyService::Backend::ReadCachedComponents() { 197 for (size_t i = 0; i < removed->size(); ++i)
229 scoped_ptr<PolicyNamespaceKeys> keys(new PolicyNamespaceKeys); 198 updater_->CancelUpdate((*removed)[i]);
230 std::map<std::string, std::string> contents;
231 cache_->LoadAllSubkeys(kComponentNamespaceCache, &contents);
232 for (std::map<std::string, std::string>::iterator it = contents.begin();
233 it != contents.end(); ++it) {
234 PolicyDomain domain;
235 if (ComponentCloudPolicyStore::GetPolicyDomain(it->first, &domain)) {
236 const Pickle pickle(it->second.data(), it->second.size());
237 PickleIterator pickit(pickle);
238 std::string id;
239 while (pickit.ReadString(&id))
240 keys->insert(std::make_pair(it->first, id));
241 } else {
242 cache_->Delete(kComponentNamespaceCache, it->first);
243 }
244 } 199 }
245 return keys.Pass();
246 } 200 }
247 201
248 ComponentCloudPolicyService::ComponentCloudPolicyService( 202 ComponentCloudPolicyService::ComponentCloudPolicyService(
249 Delegate* delegate, 203 Delegate* delegate,
204 SchemaRegistry* schema_registry,
250 CloudPolicyStore* store, 205 CloudPolicyStore* store,
251 scoped_ptr<ResourceCache> cache, 206 scoped_ptr<ResourceCache> cache,
207 CloudPolicyClient* client,
208 scoped_refptr<net::URLRequestContextGetter> request_context,
252 scoped_refptr<base::SequencedTaskRunner> backend_task_runner, 209 scoped_refptr<base::SequencedTaskRunner> backend_task_runner,
253 scoped_refptr<base::SequencedTaskRunner> io_task_runner) 210 scoped_refptr<base::SequencedTaskRunner> io_task_runner)
254 : delegate_(delegate), 211 : delegate_(delegate),
212 schema_registry_(schema_registry),
213 store_(store),
214 client_(client),
215 request_context_(request_context),
255 backend_task_runner_(backend_task_runner), 216 backend_task_runner_(backend_task_runner),
256 io_task_runner_(io_task_runner), 217 io_task_runner_(io_task_runner),
257 client_(NULL), 218 current_schema_map_(new SchemaMap),
258 store_(store),
259 is_initialized_(false), 219 is_initialized_(false),
260 has_initial_keys_(false), 220 has_credentials_(false),
261 weak_ptr_factory_(this) { 221 weak_ptr_factory_(this) {
222 schema_registry_->AddObserver(this);
262 store_->AddObserver(this); 223 store_->AddObserver(this);
224 client_->AddObserver(this);
263 225
264 backend_.reset(new Backend(weak_ptr_factory_.GetWeakPtr(), 226 external_policy_data_fetcher_backend_.reset(
265 backend_task_runner_, 227 new ExternalPolicyDataFetcherBackend(io_task_runner_, request_context));
266 base::MessageLoopProxy::current(), 228
267 cache.Pass())); 229 backend_.reset(
268 backend_task_runner_->PostTask( 230 new Backend(weak_ptr_factory_.GetWeakPtr(),
269 FROM_HERE, base::Bind(&Backend::Init, base::Unretained(backend_.get()))); 231 backend_task_runner_,
232 base::MessageLoopProxy::current(),
233 cache.Pass(),
234 external_policy_data_fetcher_backend_->CreateFrontend(
235 backend_task_runner_)));
270 236
271 if (store_->is_initialized()) 237 if (store_->is_initialized())
272 InitializeBackend(); 238 OnStoreLoaded(store_);
273 } 239 }
274 240
275 ComponentCloudPolicyService::~ComponentCloudPolicyService() { 241 ComponentCloudPolicyService::~ComponentCloudPolicyService() {
276 DCHECK(CalledOnValidThread()); 242 DCHECK(CalledOnValidThread());
243 schema_registry_->RemoveObserver(this);
277 store_->RemoveObserver(this); 244 store_->RemoveObserver(this);
278 if (client_) 245 client_->RemoveObserver(this);
279 client_->RemoveObserver(this); 246
247 // Remove all the namespaces from |client_| but don't send this empty schema
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
280 io_task_runner_->DeleteSoon(FROM_HERE, 254 io_task_runner_->DeleteSoon(FROM_HERE,
281 external_policy_data_fetcher_backend_.release()); 255 external_policy_data_fetcher_backend_.release());
282 backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release()); 256 backend_task_runner_->DeleteSoon(FROM_HERE, backend_.release());
283 } 257 }
284 258
285 // static 259 // static
286 bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) { 260 bool ComponentCloudPolicyService::SupportsDomain(PolicyDomain domain) {
287 return ComponentCloudPolicyStore::SupportsDomain(domain); 261 return ComponentCloudPolicyStore::SupportsDomain(domain);
288 } 262 }
289 263
290 void ComponentCloudPolicyService::Connect(
291 CloudPolicyClient* client,
292 scoped_refptr<net::URLRequestContextGetter> request_context) {
293 DCHECK(CalledOnValidThread());
294 DCHECK(!client_);
295 client_ = client;
296 client_->AddObserver(this);
297 DCHECK(!external_policy_data_fetcher_backend_);
298 external_policy_data_fetcher_backend_.reset(
299 new ExternalPolicyDataFetcherBackend(io_task_runner_,
300 request_context));
301 // Create the updater in the backend.
302 backend_task_runner_->PostTask(FROM_HERE, base::Bind(
303 &Backend::Connect,
304 base::Unretained(backend_.get()),
305 base::Passed(external_policy_data_fetcher_backend_->CreateFrontend(
306 backend_task_runner_))));
307 if (is_initialized())
308 InitializeClient();
309 }
310
311 void ComponentCloudPolicyService::Disconnect() {
312 DCHECK(CalledOnValidThread());
313 if (client_) {
314 // Unregister all the current components.
315 RemoveNamespacesToFetch(keys_);
316
317 client_->RemoveObserver(this);
318 client_ = NULL;
319
320 io_task_runner_->DeleteSoon(
321 FROM_HERE, external_policy_data_fetcher_backend_.release());
322 backend_task_runner_->PostTask(
323 FROM_HERE,
324 base::Bind(&Backend::Disconnect, base::Unretained(backend_.get())));
325 }
326 }
327
328 void ComponentCloudPolicyService::OnSchemasUpdated(
329 const scoped_refptr<SchemaMap>& schema_map) {
330 DCHECK(CalledOnValidThread());
331
332 // Send the new schemas to the backend, to purge the cache.
333 backend_task_runner_->PostTask(FROM_HERE,
334 base::Bind(&Backend::OnSchemasUpdated,
335 base::Unretained(backend_.get()),
336 schema_map));
337
338 // Register the current list of components for supported domains at the
339 // |client_|.
340 PolicyNamespaceKeys new_keys;
341 const DomainMap& domains = schema_map->GetDomains();
342 for (DomainMap::const_iterator domain = domains.begin();
343 domain != domains.end(); ++domain) {
344 std::string domain_policy_type;
345 if (!ComponentCloudPolicyStore::GetPolicyType(domain->first,
346 &domain_policy_type)) {
347 continue;
348 }
349 const ComponentMap& components = domain->second;
350 for (ComponentMap::const_iterator comp = components.begin();
351 comp != components.end(); ++comp) {
352 new_keys.insert(std::make_pair(domain_policy_type, comp->first));
353 }
354 }
355
356 if (client_ && is_initialized() && UpdateClientNamespaces(keys_, new_keys))
357 delegate_->OnComponentCloudPolicyRefreshNeeded();
358
359 keys_.swap(new_keys);
360 has_initial_keys_ = true;
361 }
362
363 void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) { 264 void ComponentCloudPolicyService::OnPolicyFetched(CloudPolicyClient* client) {
364 DCHECK(CalledOnValidThread()); 265 DCHECK(CalledOnValidThread());
365 DCHECK_EQ(client_, client); 266 DCHECK_EQ(client_, client);
267
268 if (!is_initialized() || !has_credentials_)
269 return;
270
366 // Pass each PolicyFetchResponse whose policy type is registered to the 271 // Pass each PolicyFetchResponse whose policy type is registered to the
367 // Backend. 272 // Backend.
368 const CloudPolicyClient::ResponseMap& responses = client_->responses(); 273 const CloudPolicyClient::ResponseMap& responses = client_->responses();
369 for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin(); 274 for (CloudPolicyClient::ResponseMap::const_iterator it = responses.begin();
370 it != responses.end(); ++it) { 275 it != responses.end(); ++it) {
371 const PolicyNamespaceKey& key(it->first); 276 PolicyNamespace ns;
372 if (ContainsKey(keys_, key)) { 277 if (ToPolicyNamespace(it->first, &ns) &&
278 current_schema_map_->GetSchema(ns)) {
373 scoped_ptr<em::PolicyFetchResponse> response( 279 scoped_ptr<em::PolicyFetchResponse> response(
374 new em::PolicyFetchResponse(*it->second)); 280 new em::PolicyFetchResponse(*it->second));
375 backend_task_runner_->PostTask( 281 backend_task_runner_->PostTask(
376 FROM_HERE, 282 FROM_HERE,
377 base::Bind(&Backend::UpdateExternalPolicy, 283 base::Bind(&Backend::UpdateExternalPolicy,
378 base::Unretained(backend_.get()), 284 base::Unretained(backend_.get()),
379 base::Passed(&response))); 285 base::Passed(&response)));
380 } 286 }
381 } 287 }
382 } 288 }
383 289
384 void ComponentCloudPolicyService::OnRegistrationStateChanged( 290 void ComponentCloudPolicyService::OnRegistrationStateChanged(
385 CloudPolicyClient* client) { 291 CloudPolicyClient* client) {
386 DCHECK(CalledOnValidThread()); 292 DCHECK(CalledOnValidThread());
387 // Ignored. 293 // Ignored.
388 } 294 }
389 295
390 void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) { 296 void ComponentCloudPolicyService::OnClientError(CloudPolicyClient* client) {
391 DCHECK(CalledOnValidThread()); 297 DCHECK(CalledOnValidThread());
392 // Ignored. 298 // Ignored.
393 } 299 }
394 300
395 void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) { 301 void ComponentCloudPolicyService::OnStoreLoaded(CloudPolicyStore* store) {
396 DCHECK(CalledOnValidThread()); 302 DCHECK(CalledOnValidThread());
397 DCHECK_EQ(store_, store); 303 DCHECK_EQ(store_, store);
398 if (store_->is_initialized()) { 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;
399 if (is_initialized()) { 321 if (is_initialized()) {
400 // The backend is already initialized; update the credentials, in case 322 // This was the first policy fetch for this client. Process any
401 // a new dmtoken or server key became available. 323 // PolicyFetchResponses that the client may have now; processing them
402 SetCredentialsAndReloadClient(); 324 // before the credentials were sent to the backend would fail validation.
403 } else { 325 OnPolicyFetched(client_);
404 // The |store_| just became ready; initialize the backend now.
405 InitializeBackend();
406 } 326 }
407 } 327 }
328
329 if (!is_initialized())
330 InitializeIfReady();
408 } 331 }
409 332
410 void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) { 333 void ComponentCloudPolicyService::OnStoreError(CloudPolicyStore* store) {
411 DCHECK(CalledOnValidThread()); 334 DCHECK(CalledOnValidThread());
412 OnStoreLoaded(store); 335 OnStoreLoaded(store);
413 } 336 }
414 337
415 void ComponentCloudPolicyService::InitializeBackend() { 338 void ComponentCloudPolicyService::OnSchemaRegistryReady() {
416 DCHECK(CalledOnValidThread()); 339 DCHECK(CalledOnValidThread());
417 DCHECK(!is_initialized()); 340 InitializeIfReady();
418 DCHECK(store_->is_initialized()); 341 }
419 342
420 // Set the credentials for the initial policy load, if available. 343 void ComponentCloudPolicyService::OnSchemaRegistryUpdated(
421 SetCredentialsAndReloadClient(); 344 bool has_new_schemas) {
345 DCHECK(CalledOnValidThread());
422 346
423 backend_task_runner_->PostTask( 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(
424 FROM_HERE, 360 FROM_HERE,
425 base::Bind(&Backend::FinalizeInit, base::Unretained(backend_.get()))); 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() {
369 DCHECK(CalledOnValidThread());
370 if (!schema_registry_->IsReady() || !store_->is_initialized())
371 return;
372 backend_task_runner_->PostTask(FROM_HERE,
373 base::Bind(&Backend::Init,
374 base::Unretained(backend_.get()),
375 schema_registry_->schema_map()));
426 } 376 }
427 377
428 void ComponentCloudPolicyService::OnBackendInitialized( 378 void ComponentCloudPolicyService::OnBackendInitialized(
429 scoped_ptr<PolicyNamespaceKeys> initial_keys,
430 scoped_ptr<PolicyBundle> initial_policy) { 379 scoped_ptr<PolicyBundle> initial_policy) {
431 DCHECK(CalledOnValidThread()); 380 DCHECK(CalledOnValidThread());
432 // InitializeBackend() may be called multiple times if the |store_| fires
433 // events while the backend is loading.
434 if (is_initialized())
435 return;
436 381
437 // OnSchemasUpdated() may have been called while the backend was initializing; 382 is_initialized_ = true;
438 // in that case ignore the cached keys.
439 if (!has_initial_keys_)
440 keys_.swap(*initial_keys);
441 383
442 // A client may have already connected while the backend was initializing. 384 // Send the current schema to the backend, in case it has changed while the
443 if (client_) 385 // backend was initializing.
444 InitializeClient(); 386 SetCurrentSchema(schema_registry_->schema_map(), true);
445 387
446 // Set the initial policy, and send the initial update callback. 388 // Process any PolicyFetchResponses that the client may already have, or that
447 is_initialized_ = true; 389 // may have been received while the backend was initializing.
390 OnPolicyFetched(client_);
391
392 // Finally tell the Delegate that the initial policy is available.
448 OnPolicyUpdated(initial_policy.Pass()); 393 OnPolicyUpdated(initial_policy.Pass());
449 } 394 }
450 395
451 void ComponentCloudPolicyService::InitializeClient() { 396 void ComponentCloudPolicyService::SetCurrentSchema(
397 const scoped_refptr<SchemaMap>& new_schema_map,
398 bool send_to_backend) {
452 DCHECK(CalledOnValidThread()); 399 DCHECK(CalledOnValidThread());
453 // Register all the current components. 400 DCHECK(is_initialized());
454 AddNamespacesToFetch(keys_); 401
455 // The client may already have PolicyFetchResponses for registered components; 402 scoped_ptr<PolicyNamespaceList> removed(new PolicyNamespaceList);
456 // load them now. 403 PolicyNamespaceList added;
457 OnPolicyFetched(client_); 404 new_schema_map->GetChanges(current_schema_map_, removed.get(), &added);
458 if (!keys_.empty() && is_initialized()) 405
406 current_schema_map_ = new_schema_map;
407
408 for (size_t i = 0; i < removed->size(); ++i) {
409 PolicyNamespaceKey key;
410 if (ToPolicyNamespaceKey((*removed)[i], &key))
411 client_->RemoveNamespaceToFetch(key);
412 }
413
414 bool added_namespaces_to_client = false;
415 for (size_t i = 0; i < added.size(); ++i) {
416 PolicyNamespaceKey key;
417 if (ToPolicyNamespaceKey(added[i], &key)) {
418 client_->AddNamespaceToFetch(key);
419 added_namespaces_to_client = true;
420 }
421 }
422
423 if (added_namespaces_to_client)
459 delegate_->OnComponentCloudPolicyRefreshNeeded(); 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 }
460 } 433 }
461 434
462 void ComponentCloudPolicyService::OnPolicyUpdated( 435 void ComponentCloudPolicyService::OnPolicyUpdated(
463 scoped_ptr<PolicyBundle> policy) { 436 scoped_ptr<PolicyBundle> policy) {
464 DCHECK(CalledOnValidThread()); 437 DCHECK(CalledOnValidThread());
465 policy_.Swap(policy.get()); 438 policy_.Swap(policy.get());
466 // Don't propagate updates until the initial store Load() has been done. 439 delegate_->OnComponentCloudPolicyUpdated();
467 if (is_initialized())
468 delegate_->OnComponentCloudPolicyUpdated();
469 }
470
471 void ComponentCloudPolicyService::SetCredentialsAndReloadClient() {
472 DCHECK(CalledOnValidThread());
473 const em::PolicyData* policy = store_->policy();
474 if (!policy || !policy->has_username() || !policy->has_request_token())
475 return;
476 backend_task_runner_->PostTask(FROM_HERE,
477 base::Bind(&Backend::SetCredentials,
478 base::Unretained(backend_.get()),
479 policy->username(),
480 policy->request_token()));
481 // If this was the initial register, or if the signing key changed, then the
482 // previous OnPolicyFetched() call had its PolicyFetchResponses rejected
483 // because the credentials weren't updated yet. Reload all the responses in
484 // the client now to handle those cases; if those responses have already been
485 // validated then they will be ignored.
486 if (client_)
487 OnPolicyFetched(client_);
488 }
489
490 bool ComponentCloudPolicyService::UpdateClientNamespaces(
491 const PolicyNamespaceKeys& old_keys,
492 const PolicyNamespaceKeys& new_keys) {
493 DCHECK(CalledOnValidThread());
494 PolicyNamespaceKeys added =
495 base::STLSetDifference<PolicyNamespaceKeys>(new_keys, old_keys);
496 PolicyNamespaceKeys removed =
497 base::STLSetDifference<PolicyNamespaceKeys>(old_keys, new_keys);
498 AddNamespacesToFetch(added);
499 RemoveNamespacesToFetch(removed);
500 return !added.empty();
501 }
502
503 void ComponentCloudPolicyService::AddNamespacesToFetch(
504 const PolicyNamespaceKeys& keys) {
505 DCHECK(CalledOnValidThread());
506 for (PolicyNamespaceKeys::const_iterator it = keys.begin();
507 it != keys.end(); ++it) {
508 client_->AddNamespaceToFetch(*it);
509 }
510 }
511
512 void ComponentCloudPolicyService::RemoveNamespacesToFetch(
513 const PolicyNamespaceKeys& keys) {
514 DCHECK(CalledOnValidThread());
515 for (PolicyNamespaceKeys::const_iterator it = keys.begin();
516 it != keys.end(); ++it) {
517 client_->RemoveNamespaceToFetch(*it);
518 }
519 } 440 }
520 441
521 } // namespace policy 442 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698