OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "components/policy/core/common/cloud/cloud_policy_client.h" | 5 #include "components/policy/core/common/cloud/cloud_policy_client.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/guid.h" | 8 #include "base/guid.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 } | 72 } |
73 | 73 |
74 void CloudPolicyClient::SetupRegistration(const std::string& dm_token, | 74 void CloudPolicyClient::SetupRegistration(const std::string& dm_token, |
75 const std::string& client_id) { | 75 const std::string& client_id) { |
76 DCHECK(!dm_token.empty()); | 76 DCHECK(!dm_token.empty()); |
77 DCHECK(!client_id.empty()); | 77 DCHECK(!client_id.empty()); |
78 DCHECK(!is_registered()); | 78 DCHECK(!is_registered()); |
79 | 79 |
80 dm_token_ = dm_token; | 80 dm_token_ = dm_token; |
81 client_id_ = client_id; | 81 client_id_ = client_id; |
82 request_job_.reset(); | 82 request_jobs_.clear(); |
| 83 policy_fetch_request_job_.reset(); |
83 STLDeleteValues(&responses_); | 84 STLDeleteValues(&responses_); |
84 | 85 |
85 NotifyRegistrationStateChanged(); | 86 NotifyRegistrationStateChanged(); |
86 } | 87 } |
87 | 88 |
88 void CloudPolicyClient::Register(em::DeviceRegisterRequest::Type type, | 89 void CloudPolicyClient::Register(em::DeviceRegisterRequest::Type type, |
89 em::DeviceRegisterRequest::Flavor flavor, | 90 em::DeviceRegisterRequest::Flavor flavor, |
90 const std::string& auth_token, | 91 const std::string& auth_token, |
91 const std::string& client_id, | 92 const std::string& client_id, |
92 const std::string& requisition, | 93 const std::string& requisition, |
93 const std::string& current_state_key) { | 94 const std::string& current_state_key) { |
94 DCHECK(service_); | 95 DCHECK(service_); |
95 DCHECK(!auth_token.empty()); | 96 DCHECK(!auth_token.empty()); |
96 DCHECK(!is_registered()); | 97 DCHECK(!is_registered()); |
97 | 98 |
98 if (client_id.empty()) { | 99 if (client_id.empty()) { |
99 // Generate a new client ID. This is intentionally done on each new | 100 // Generate a new client ID. This is intentionally done on each new |
100 // registration request in order to preserve privacy. Reusing IDs would mean | 101 // registration request in order to preserve privacy. Reusing IDs would mean |
101 // the server could track clients by their registration attempts. | 102 // the server could track clients by their registration attempts. |
102 client_id_ = base::GenerateGUID(); | 103 client_id_ = base::GenerateGUID(); |
103 } else { | 104 } else { |
104 client_id_ = client_id; | 105 client_id_ = client_id; |
105 } | 106 } |
106 | 107 |
107 request_job_.reset( | 108 policy_fetch_request_job_.reset( |
108 service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION, | 109 service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION, |
109 GetRequestContext())); | 110 GetRequestContext())); |
110 request_job_->SetOAuthToken(auth_token); | 111 policy_fetch_request_job_->SetOAuthToken(auth_token); |
111 request_job_->SetClientID(client_id_); | 112 policy_fetch_request_job_->SetClientID(client_id_); |
112 | 113 |
113 em::DeviceRegisterRequest* request = | 114 em::DeviceRegisterRequest* request = |
114 request_job_->GetRequest()->mutable_register_request(); | 115 policy_fetch_request_job_->GetRequest()->mutable_register_request(); |
115 if (!client_id.empty()) | 116 if (!client_id.empty()) |
116 request->set_reregister(true); | 117 request->set_reregister(true); |
117 request->set_type(type); | 118 request->set_type(type); |
118 if (!machine_id_.empty()) | 119 if (!machine_id_.empty()) |
119 request->set_machine_id(machine_id_); | 120 request->set_machine_id(machine_id_); |
120 if (!machine_model_.empty()) | 121 if (!machine_model_.empty()) |
121 request->set_machine_model(machine_model_); | 122 request->set_machine_model(machine_model_); |
122 if (!requisition.empty()) | 123 if (!requisition.empty()) |
123 request->set_requisition(requisition); | 124 request->set_requisition(requisition); |
124 if (!current_state_key.empty()) | 125 if (!current_state_key.empty()) |
125 request->set_server_backed_state_key(current_state_key); | 126 request->set_server_backed_state_key(current_state_key); |
126 request->set_flavor(flavor); | 127 request->set_flavor(flavor); |
127 | 128 |
128 request_job_->SetRetryCallback( | 129 policy_fetch_request_job_->SetRetryCallback( |
129 base::Bind(&CloudPolicyClient::OnRetryRegister, base::Unretained(this))); | 130 base::Bind(&CloudPolicyClient::OnRetryRegister, base::Unretained(this))); |
130 | 131 |
131 request_job_->Start(base::Bind(&CloudPolicyClient::OnRegisterCompleted, | 132 policy_fetch_request_job_->Start( |
132 base::Unretained(this))); | 133 base::Bind(&CloudPolicyClient::OnRegisterCompleted, |
| 134 base::Unretained(this))); |
133 } | 135 } |
134 | 136 |
135 void CloudPolicyClient::SetInvalidationInfo( | 137 void CloudPolicyClient::SetInvalidationInfo( |
136 int64 version, | 138 int64 version, |
137 const std::string& payload) { | 139 const std::string& payload) { |
138 invalidation_version_ = version; | 140 invalidation_version_ = version; |
139 invalidation_payload_ = payload; | 141 invalidation_payload_ = payload; |
140 } | 142 } |
141 | 143 |
142 void CloudPolicyClient::FetchPolicy() { | 144 void CloudPolicyClient::FetchPolicy() { |
143 CHECK(is_registered()); | 145 CHECK(is_registered()); |
144 CHECK(!types_to_fetch_.empty()); | 146 CHECK(!types_to_fetch_.empty()); |
145 | 147 |
146 request_job_.reset( | 148 policy_fetch_request_job_.reset( |
147 service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH, | 149 service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH, |
148 GetRequestContext())); | 150 GetRequestContext())); |
149 request_job_->SetDMToken(dm_token_); | 151 policy_fetch_request_job_->SetDMToken(dm_token_); |
150 request_job_->SetClientID(client_id_); | 152 policy_fetch_request_job_->SetClientID(client_id_); |
151 request_job_->SetUserAffiliation(user_affiliation_); | 153 policy_fetch_request_job_->SetUserAffiliation(user_affiliation_); |
152 | 154 |
153 em::DeviceManagementRequest* request = request_job_->GetRequest(); | 155 em::DeviceManagementRequest* request = |
| 156 policy_fetch_request_job_->GetRequest(); |
154 | 157 |
155 // Build policy fetch requests. | 158 // Build policy fetch requests. |
156 em::DevicePolicyRequest* policy_request = request->mutable_policy_request(); | 159 em::DevicePolicyRequest* policy_request = request->mutable_policy_request(); |
157 for (const auto& type_to_fetch : types_to_fetch_) { | 160 for (const auto& type_to_fetch : types_to_fetch_) { |
158 em::PolicyFetchRequest* fetch_request = policy_request->add_request(); | 161 em::PolicyFetchRequest* fetch_request = policy_request->add_request(); |
159 fetch_request->set_policy_type(type_to_fetch.first); | 162 fetch_request->set_policy_type(type_to_fetch.first); |
160 if (!type_to_fetch.second.empty()) | 163 if (!type_to_fetch.second.empty()) |
161 fetch_request->set_settings_entity_id(type_to_fetch.second); | 164 fetch_request->set_settings_entity_id(type_to_fetch.second); |
162 | 165 |
163 // Request signed policy blobs to help prevent tampering on the client. | 166 // Request signed policy blobs to help prevent tampering on the client. |
(...skipping 30 matching lines...) Expand all Loading... |
194 ++key) { | 197 ++key) { |
195 key_update_request->add_server_backed_state_key(*key); | 198 key_update_request->add_server_backed_state_key(*key); |
196 } | 199 } |
197 } | 200 } |
198 | 201 |
199 // Set the fetched invalidation version to the latest invalidation version | 202 // Set the fetched invalidation version to the latest invalidation version |
200 // since it is now the invalidation version used for the latest fetch. | 203 // since it is now the invalidation version used for the latest fetch. |
201 fetched_invalidation_version_ = invalidation_version_; | 204 fetched_invalidation_version_ = invalidation_version_; |
202 | 205 |
203 // Fire the job. | 206 // Fire the job. |
204 request_job_->Start(base::Bind(&CloudPolicyClient::OnPolicyFetchCompleted, | 207 policy_fetch_request_job_->Start( |
205 base::Unretained(this))); | 208 base::Bind(&CloudPolicyClient::OnPolicyFetchCompleted, |
| 209 base::Unretained(this))); |
206 } | 210 } |
207 | 211 |
208 void CloudPolicyClient::FetchRobotAuthCodes(const std::string& auth_token) { | 212 void CloudPolicyClient::FetchRobotAuthCodes(const std::string& auth_token) { |
209 CHECK(is_registered()); | 213 CHECK(is_registered()); |
210 DCHECK(!auth_token.empty()); | 214 DCHECK(!auth_token.empty()); |
211 | 215 |
212 request_job_.reset(service_->CreateJob( | 216 policy_fetch_request_job_.reset(service_->CreateJob( |
213 DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH, | 217 DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH, |
214 GetRequestContext())); | 218 GetRequestContext())); |
215 // The credentials of a domain user are needed in order to mint a new OAuth2 | 219 // The credentials of a domain user are needed in order to mint a new OAuth2 |
216 // authorization token for the robot account. | 220 // authorization token for the robot account. |
217 request_job_->SetOAuthToken(auth_token); | 221 policy_fetch_request_job_->SetOAuthToken(auth_token); |
218 request_job_->SetDMToken(dm_token_); | 222 policy_fetch_request_job_->SetDMToken(dm_token_); |
219 request_job_->SetClientID(client_id_); | 223 policy_fetch_request_job_->SetClientID(client_id_); |
220 | 224 |
221 em::DeviceServiceApiAccessRequest* request = | 225 em::DeviceServiceApiAccessRequest* request = |
222 request_job_->GetRequest()->mutable_service_api_access_request(); | 226 policy_fetch_request_job_->GetRequest()-> |
| 227 mutable_service_api_access_request(); |
223 request->set_oauth2_client_id( | 228 request->set_oauth2_client_id( |
224 GaiaUrls::GetInstance()->oauth2_chrome_client_id()); | 229 GaiaUrls::GetInstance()->oauth2_chrome_client_id()); |
225 request->add_auth_scope(GaiaConstants::kAnyApiOAuth2Scope); | 230 request->add_auth_scope(GaiaConstants::kAnyApiOAuth2Scope); |
226 | 231 |
227 request_job_->Start( | 232 policy_fetch_request_job_->Start( |
228 base::Bind(&CloudPolicyClient::OnFetchRobotAuthCodesCompleted, | 233 base::Bind(&CloudPolicyClient::OnFetchRobotAuthCodesCompleted, |
229 base::Unretained(this))); | 234 base::Unretained(this))); |
230 } | 235 } |
231 | 236 |
232 void CloudPolicyClient::Unregister() { | 237 void CloudPolicyClient::Unregister() { |
233 DCHECK(service_); | 238 DCHECK(service_); |
234 request_job_.reset( | 239 policy_fetch_request_job_.reset( |
235 service_->CreateJob(DeviceManagementRequestJob::TYPE_UNREGISTRATION, | 240 service_->CreateJob(DeviceManagementRequestJob::TYPE_UNREGISTRATION, |
236 GetRequestContext())); | 241 GetRequestContext())); |
237 request_job_->SetDMToken(dm_token_); | 242 policy_fetch_request_job_->SetDMToken(dm_token_); |
238 request_job_->SetClientID(client_id_); | 243 policy_fetch_request_job_->SetClientID(client_id_); |
239 request_job_->GetRequest()->mutable_unregister_request(); | 244 policy_fetch_request_job_->GetRequest()->mutable_unregister_request(); |
240 request_job_->Start(base::Bind(&CloudPolicyClient::OnUnregisterCompleted, | 245 policy_fetch_request_job_->Start( |
241 base::Unretained(this))); | 246 base::Bind(&CloudPolicyClient::OnUnregisterCompleted, |
| 247 base::Unretained(this))); |
242 } | 248 } |
243 | 249 |
244 void CloudPolicyClient::UploadCertificate( | 250 void CloudPolicyClient::UploadCertificate( |
245 const std::string& certificate_data, | 251 const std::string& certificate_data, |
246 const CloudPolicyClient::StatusCallback& callback) { | 252 const CloudPolicyClient::StatusCallback& callback) { |
247 CHECK(is_registered()); | 253 CHECK(is_registered()); |
248 request_job_.reset( | 254 scoped_ptr<DeviceManagementRequestJob> request_job( |
249 service_->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE, | 255 service_->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE, |
250 GetRequestContext())); | 256 GetRequestContext())); |
251 request_job_->SetDMToken(dm_token_); | 257 request_job->SetDMToken(dm_token_); |
252 request_job_->SetClientID(client_id_); | 258 request_job->SetClientID(client_id_); |
253 | 259 |
254 em::DeviceManagementRequest* request = request_job_->GetRequest(); | 260 em::DeviceManagementRequest* request = request_job->GetRequest(); |
255 request->mutable_cert_upload_request()->set_device_certificate( | 261 request->mutable_cert_upload_request()->set_device_certificate( |
256 certificate_data); | 262 certificate_data); |
257 | 263 |
258 DeviceManagementRequestJob::Callback job_callback = base::Bind( | 264 DeviceManagementRequestJob::Callback job_callback = base::Bind( |
259 &CloudPolicyClient::OnCertificateUploadCompleted, | 265 &CloudPolicyClient::OnCertificateUploadCompleted, |
260 base::Unretained(this), | 266 base::Unretained(this), |
| 267 request_job.get(), |
261 callback); | 268 callback); |
262 request_job_->Start(job_callback); | 269 request_jobs_.push_back(request_job.Pass()); |
| 270 request_jobs_.back()->Start(job_callback); |
263 } | 271 } |
264 | 272 |
265 void CloudPolicyClient::UploadDeviceStatus( | 273 void CloudPolicyClient::UploadDeviceStatus( |
266 const em::DeviceStatusReportRequest* device_status, | 274 const em::DeviceStatusReportRequest* device_status, |
267 const em::SessionStatusReportRequest* session_status, | 275 const em::SessionStatusReportRequest* session_status, |
268 const CloudPolicyClient::StatusCallback& callback) { | 276 const CloudPolicyClient::StatusCallback& callback) { |
269 CHECK(is_registered()); | 277 CHECK(is_registered()); |
270 // Should pass in at least one type of status. | 278 // Should pass in at least one type of status. |
271 DCHECK(device_status || session_status); | 279 DCHECK(device_status || session_status); |
272 request_job_.reset( | 280 scoped_ptr<DeviceManagementRequestJob> request_job( |
273 service_->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_STATUS, | 281 service_->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_STATUS, |
274 GetRequestContext())); | 282 GetRequestContext())); |
275 request_job_->SetDMToken(dm_token_); | 283 request_job->SetDMToken(dm_token_); |
276 request_job_->SetClientID(client_id_); | 284 request_job->SetClientID(client_id_); |
277 | 285 |
278 em::DeviceManagementRequest* request = request_job_->GetRequest(); | 286 em::DeviceManagementRequest* request = request_job->GetRequest(); |
279 if (device_status) | 287 if (device_status) |
280 *request->mutable_device_status_report_request() = *device_status; | 288 *request->mutable_device_status_report_request() = *device_status; |
281 if (session_status) | 289 if (session_status) |
282 *request->mutable_session_status_report_request() = *session_status; | 290 *request->mutable_session_status_report_request() = *session_status; |
283 | 291 |
284 DeviceManagementRequestJob::Callback job_callback = base::Bind( | 292 DeviceManagementRequestJob::Callback job_callback = base::Bind( |
285 &CloudPolicyClient::OnStatusUploadCompleted, | 293 &CloudPolicyClient::OnStatusUploadCompleted, |
286 base::Unretained(this), | 294 base::Unretained(this), |
| 295 request_job.get(), |
287 callback); | 296 callback); |
288 | 297 |
289 // TODO(atwilson): Change CloudPolicyClient to support multiple requests in | 298 request_jobs_.push_back(request_job.Pass()); |
290 // parallel, so status upload requests don't get cancelled by things like | 299 request_jobs_.back()->Start(job_callback); |
291 // policy fetches (http://crbug.com/452563). | |
292 request_job_->Start(job_callback); | |
293 } | 300 } |
294 | 301 |
295 void CloudPolicyClient::AddObserver(Observer* observer) { | 302 void CloudPolicyClient::AddObserver(Observer* observer) { |
296 observers_.AddObserver(observer); | 303 observers_.AddObserver(observer); |
297 } | 304 } |
298 | 305 |
299 void CloudPolicyClient::RemoveObserver(Observer* observer) { | 306 void CloudPolicyClient::RemoveObserver(Observer* observer) { |
300 observers_.RemoveObserver(observer); | 307 observers_.RemoveObserver(observer); |
301 } | 308 } |
302 | 309 |
(...skipping 20 matching lines...) Expand all Loading... |
323 ResponseMap::const_iterator it = | 330 ResponseMap::const_iterator it = |
324 responses_.find(std::make_pair(policy_type, settings_entity_id)); | 331 responses_.find(std::make_pair(policy_type, settings_entity_id)); |
325 return it == responses_.end() ? nullptr : it->second; | 332 return it == responses_.end() ? nullptr : it->second; |
326 } | 333 } |
327 | 334 |
328 scoped_refptr<net::URLRequestContextGetter> | 335 scoped_refptr<net::URLRequestContextGetter> |
329 CloudPolicyClient::GetRequestContext() { | 336 CloudPolicyClient::GetRequestContext() { |
330 return request_context_; | 337 return request_context_; |
331 } | 338 } |
332 | 339 |
| 340 int CloudPolicyClient::GetActiveRequestCountForTest() const { |
| 341 return request_jobs_.size(); |
| 342 } |
| 343 |
333 void CloudPolicyClient::OnRetryRegister(DeviceManagementRequestJob* job) { | 344 void CloudPolicyClient::OnRetryRegister(DeviceManagementRequestJob* job) { |
334 DCHECK_EQ(request_job_.get(), job); | 345 DCHECK_EQ(policy_fetch_request_job_.get(), job); |
335 // If the initial request managed to get to the server but the response didn't | 346 // If the initial request managed to get to the server but the response didn't |
336 // arrive at the client then retrying with the same client ID will fail. | 347 // arrive at the client then retrying with the same client ID will fail. |
337 // Set the re-registration flag so that the server accepts it. | 348 // Set the re-registration flag so that the server accepts it. |
338 // If the server hasn't seen the client ID before then it will also accept | 349 // If the server hasn't seen the client ID before then it will also accept |
339 // the re-registration. | 350 // the re-registration. |
340 job->GetRequest()->mutable_register_request()->set_reregister(true); | 351 job->GetRequest()->mutable_register_request()->set_reregister(true); |
341 } | 352 } |
342 | 353 |
343 void CloudPolicyClient::OnRegisterCompleted( | 354 void CloudPolicyClient::OnRegisterCompleted( |
344 DeviceManagementStatus status, | 355 DeviceManagementStatus status, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 int net_error, | 454 int net_error, |
444 const em::DeviceManagementResponse& response) { | 455 const em::DeviceManagementResponse& response) { |
445 if (status == DM_STATUS_SUCCESS && !response.has_unregister_response()) { | 456 if (status == DM_STATUS_SUCCESS && !response.has_unregister_response()) { |
446 // Assume unregistration has succeeded either way. | 457 // Assume unregistration has succeeded either way. |
447 LOG(WARNING) << "Empty unregistration response."; | 458 LOG(WARNING) << "Empty unregistration response."; |
448 } | 459 } |
449 | 460 |
450 status_ = status; | 461 status_ = status; |
451 if (status == DM_STATUS_SUCCESS) { | 462 if (status == DM_STATUS_SUCCESS) { |
452 dm_token_.clear(); | 463 dm_token_.clear(); |
| 464 // Cancel all outstanding jobs. |
| 465 request_jobs_.clear(); |
453 NotifyRegistrationStateChanged(); | 466 NotifyRegistrationStateChanged(); |
454 } else { | 467 } else { |
455 NotifyClientError(); | 468 NotifyClientError(); |
456 } | 469 } |
457 } | 470 } |
458 | 471 |
459 void CloudPolicyClient::OnCertificateUploadCompleted( | 472 void CloudPolicyClient::OnCertificateUploadCompleted( |
| 473 const DeviceManagementRequestJob* job, |
460 const CloudPolicyClient::StatusCallback& callback, | 474 const CloudPolicyClient::StatusCallback& callback, |
461 DeviceManagementStatus status, | 475 DeviceManagementStatus status, |
462 int net_error, | 476 int net_error, |
463 const enterprise_management::DeviceManagementResponse& response) { | 477 const enterprise_management::DeviceManagementResponse& response) { |
464 if (status == DM_STATUS_SUCCESS && !response.has_cert_upload_response()) { | 478 bool success = true; |
465 LOG(WARNING) << "Empty upload certificate response."; | |
466 callback.Run(false); | |
467 return; | |
468 } | |
469 | |
470 status_ = status; | 479 status_ = status; |
471 if (status != DM_STATUS_SUCCESS) { | 480 if (status != DM_STATUS_SUCCESS) { |
| 481 success = false; |
472 NotifyClientError(); | 482 NotifyClientError(); |
473 callback.Run(false); | 483 } else if (!response.has_cert_upload_response()) { |
474 return; | 484 LOG(WARNING) << "Empty upload certificate response."; |
| 485 success = false; |
475 } | 486 } |
476 callback.Run(true); | 487 callback.Run(success); |
| 488 // Must call RemoveJob() last, because it frees |callback|. |
| 489 RemoveJob(job); |
| 490 } |
| 491 |
| 492 void CloudPolicyClient::RemoveJob(const DeviceManagementRequestJob* job) { |
| 493 for (auto it = request_jobs_.begin(); it != request_jobs_.end(); ++it) { |
| 494 if (*it == job) { |
| 495 request_jobs_.erase(it); |
| 496 return; |
| 497 } |
| 498 } |
| 499 // This job was already deleted from our list, somehow. This shouldn't |
| 500 // happen since deleting the job should cancel the callback. |
| 501 NOTREACHED(); |
477 } | 502 } |
478 | 503 |
479 void CloudPolicyClient::OnStatusUploadCompleted( | 504 void CloudPolicyClient::OnStatusUploadCompleted( |
| 505 const DeviceManagementRequestJob* job, |
480 const CloudPolicyClient::StatusCallback& callback, | 506 const CloudPolicyClient::StatusCallback& callback, |
481 DeviceManagementStatus status, | 507 DeviceManagementStatus status, |
482 int net_error, | 508 int net_error, |
483 const enterprise_management::DeviceManagementResponse& response) { | 509 const enterprise_management::DeviceManagementResponse& response) { |
484 status_ = status; | 510 status_ = status; |
485 if (status != DM_STATUS_SUCCESS) | 511 if (status != DM_STATUS_SUCCESS) |
486 NotifyClientError(); | 512 NotifyClientError(); |
487 | 513 |
488 callback.Run(status == DM_STATUS_SUCCESS); | 514 callback.Run(status == DM_STATUS_SUCCESS); |
| 515 // Must call RemoveJob() last, because it frees |callback|. |
| 516 RemoveJob(job); |
489 } | 517 } |
490 | 518 |
491 void CloudPolicyClient::NotifyPolicyFetched() { | 519 void CloudPolicyClient::NotifyPolicyFetched() { |
492 FOR_EACH_OBSERVER(Observer, observers_, OnPolicyFetched(this)); | 520 FOR_EACH_OBSERVER(Observer, observers_, OnPolicyFetched(this)); |
493 } | 521 } |
494 | 522 |
495 void CloudPolicyClient::NotifyRegistrationStateChanged() { | 523 void CloudPolicyClient::NotifyRegistrationStateChanged() { |
496 FOR_EACH_OBSERVER(Observer, observers_, OnRegistrationStateChanged(this)); | 524 FOR_EACH_OBSERVER(Observer, observers_, OnRegistrationStateChanged(this)); |
497 } | 525 } |
498 | 526 |
499 void CloudPolicyClient::NotifyRobotAuthCodesFetched() { | 527 void CloudPolicyClient::NotifyRobotAuthCodesFetched() { |
500 FOR_EACH_OBSERVER(Observer, observers_, OnRobotAuthCodesFetched(this)); | 528 FOR_EACH_OBSERVER(Observer, observers_, OnRobotAuthCodesFetched(this)); |
501 } | 529 } |
502 | 530 |
503 void CloudPolicyClient::NotifyClientError() { | 531 void CloudPolicyClient::NotifyClientError() { |
504 FOR_EACH_OBSERVER(Observer, observers_, OnClientError(this)); | 532 FOR_EACH_OBSERVER(Observer, observers_, OnClientError(this)); |
505 } | 533 } |
506 | 534 |
507 } // namespace policy | 535 } // namespace policy |
OLD | NEW |