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
3 // found in the LICENSE file.
5 #include "components/policy/core/common/cloud/cloud_policy_client.h"
8 #include "base/bind_helpers.h"
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "components/policy/core/common/cloud/device_management_service.h"
13 #include "google_apis/gaia/gaia_constants.h"
14 #include "google_apis/gaia/gaia_urls.h"
15 #include "net/url_request/url_request_context_getter.h"
17 namespace em
= enterprise_management
;
23 // Translates the DeviceRegisterResponse::DeviceMode |mode| to the enum used
24 // internally to represent different device modes.
25 DeviceMode
TranslateProtobufDeviceMode(
26 em::DeviceRegisterResponse::DeviceMode mode
) {
28 case em::DeviceRegisterResponse::ENTERPRISE
:
29 return DEVICE_MODE_ENTERPRISE
;
30 case em::DeviceRegisterResponse::RETAIL
:
31 return DEVICE_MODE_LEGACY_RETAIL_MODE
;
33 LOG(ERROR
) << "Unknown enrollment mode in registration response: " << mode
;
34 return DEVICE_MODE_NOT_SET
;
37 bool IsChromePolicy(const std::string
& type
) {
38 return type
== dm_protocol::kChromeDevicePolicyType
||
39 type
== dm_protocol::kChromeUserPolicyType
;
44 CloudPolicyClient::Observer::~Observer() {}
46 void CloudPolicyClient::Observer::OnRobotAuthCodesFetched(
47 CloudPolicyClient
* client
) {}
49 CloudPolicyClient::CloudPolicyClient(
50 const std::string
& machine_id
,
51 const std::string
& machine_model
,
52 const std::string
& verification_key_hash
,
53 DeviceManagementService
* service
,
54 scoped_refptr
<net::URLRequestContextGetter
> request_context
)
55 : machine_id_(machine_id
),
56 machine_model_(machine_model
),
57 verification_key_hash_(verification_key_hash
),
58 device_mode_(DEVICE_MODE_NOT_SET
),
59 submit_machine_id_(false),
60 public_key_version_(-1),
61 public_key_version_valid_(false),
62 invalidation_version_(0),
63 fetched_invalidation_version_(0),
64 service_(service
), // Can be null for unit tests.
65 status_(DM_STATUS_SUCCESS
),
66 request_context_(request_context
) {
69 CloudPolicyClient::~CloudPolicyClient() {
70 STLDeleteValues(&responses_
);
73 void CloudPolicyClient::SetupRegistration(const std::string
& dm_token
,
74 const std::string
& client_id
) {
75 DCHECK(!dm_token
.empty());
76 DCHECK(!client_id
.empty());
77 DCHECK(!is_registered());
80 client_id_
= client_id
;
81 request_jobs_
.clear();
82 policy_fetch_request_job_
.reset();
83 STLDeleteValues(&responses_
);
85 NotifyRegistrationStateChanged();
88 void CloudPolicyClient::Register(em::DeviceRegisterRequest::Type type
,
89 em::DeviceRegisterRequest::Flavor flavor
,
90 const std::string
& auth_token
,
91 const std::string
& client_id
,
92 const std::string
& requisition
,
93 const std::string
& current_state_key
) {
95 DCHECK(!auth_token
.empty());
96 DCHECK(!is_registered());
98 if (client_id
.empty()) {
99 // 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 // the server could track clients by their registration attempts.
102 client_id_
= base::GenerateGUID();
104 client_id_
= client_id
;
107 policy_fetch_request_job_
.reset(
108 service_
->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION
,
109 GetRequestContext()));
110 policy_fetch_request_job_
->SetOAuthToken(auth_token
);
111 policy_fetch_request_job_
->SetClientID(client_id_
);
113 em::DeviceRegisterRequest
* request
=
114 policy_fetch_request_job_
->GetRequest()->mutable_register_request();
115 if (!client_id
.empty())
116 request
->set_reregister(true);
117 request
->set_type(type
);
118 if (!machine_id_
.empty())
119 request
->set_machine_id(machine_id_
);
120 if (!machine_model_
.empty())
121 request
->set_machine_model(machine_model_
);
122 if (!requisition
.empty())
123 request
->set_requisition(requisition
);
124 if (!current_state_key
.empty())
125 request
->set_server_backed_state_key(current_state_key
);
126 request
->set_flavor(flavor
);
128 policy_fetch_request_job_
->SetRetryCallback(
129 base::Bind(&CloudPolicyClient::OnRetryRegister
, base::Unretained(this)));
131 policy_fetch_request_job_
->Start(
132 base::Bind(&CloudPolicyClient::OnRegisterCompleted
,
133 base::Unretained(this)));
136 void CloudPolicyClient::SetInvalidationInfo(
138 const std::string
& payload
) {
139 invalidation_version_
= version
;
140 invalidation_payload_
= payload
;
143 void CloudPolicyClient::FetchPolicy() {
144 CHECK(is_registered());
145 CHECK(!types_to_fetch_
.empty());
147 policy_fetch_request_job_
.reset(
148 service_
->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH
,
149 GetRequestContext()));
150 policy_fetch_request_job_
->SetDMToken(dm_token_
);
151 policy_fetch_request_job_
->SetClientID(client_id_
);
153 em::DeviceManagementRequest
* request
=
154 policy_fetch_request_job_
->GetRequest();
156 // Build policy fetch requests.
157 em::DevicePolicyRequest
* policy_request
= request
->mutable_policy_request();
158 for (const auto& type_to_fetch
: types_to_fetch_
) {
159 em::PolicyFetchRequest
* fetch_request
= policy_request
->add_request();
160 fetch_request
->set_policy_type(type_to_fetch
.first
);
161 if (!type_to_fetch
.second
.empty())
162 fetch_request
->set_settings_entity_id(type_to_fetch
.second
);
164 // Request signed policy blobs to help prevent tampering on the client.
165 fetch_request
->set_signature_type(em::PolicyFetchRequest::SHA1_RSA
);
166 if (public_key_version_valid_
)
167 fetch_request
->set_public_key_version(public_key_version_
);
169 if (!verification_key_hash_
.empty())
170 fetch_request
->set_verification_key_hash(verification_key_hash_
);
172 // These fields are included only in requests for chrome policy.
173 if (IsChromePolicy(type_to_fetch
.first
)) {
174 if (submit_machine_id_
&& !machine_id_
.empty())
175 fetch_request
->set_machine_id(machine_id_
);
176 if (!last_policy_timestamp_
.is_null()) {
177 base::TimeDelta
timestamp(
178 last_policy_timestamp_
- base::Time::UnixEpoch());
179 fetch_request
->set_timestamp(timestamp
.InMilliseconds());
181 if (!invalidation_payload_
.empty()) {
182 fetch_request
->set_invalidation_version(invalidation_version_
);
183 fetch_request
->set_invalidation_payload(invalidation_payload_
);
188 // Add device state keys.
189 if (!state_keys_to_upload_
.empty()) {
190 em::DeviceStateKeyUpdateRequest
* key_update_request
=
191 request
->mutable_device_state_key_update_request();
192 for (std::vector
<std::string
>::const_iterator
key(
193 state_keys_to_upload_
.begin());
194 key
!= state_keys_to_upload_
.end();
196 key_update_request
->add_server_backed_state_key(*key
);
200 // Set the fetched invalidation version to the latest invalidation version
201 // since it is now the invalidation version used for the latest fetch.
202 fetched_invalidation_version_
= invalidation_version_
;
205 policy_fetch_request_job_
->Start(
206 base::Bind(&CloudPolicyClient::OnPolicyFetchCompleted
,
207 base::Unretained(this)));
210 void CloudPolicyClient::FetchRobotAuthCodes(const std::string
& auth_token
) {
211 CHECK(is_registered());
212 DCHECK(!auth_token
.empty());
214 policy_fetch_request_job_
.reset(service_
->CreateJob(
215 DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH
,
216 GetRequestContext()));
217 // The credentials of a domain user are needed in order to mint a new OAuth2
218 // authorization token for the robot account.
219 policy_fetch_request_job_
->SetOAuthToken(auth_token
);
220 policy_fetch_request_job_
->SetDMToken(dm_token_
);
221 policy_fetch_request_job_
->SetClientID(client_id_
);
223 em::DeviceServiceApiAccessRequest
* request
=
224 policy_fetch_request_job_
->GetRequest()->
225 mutable_service_api_access_request();
226 request
->set_oauth2_client_id(
227 GaiaUrls::GetInstance()->oauth2_chrome_client_id());
228 request
->add_auth_scope(GaiaConstants::kAnyApiOAuth2Scope
);
230 policy_fetch_request_job_
->Start(
231 base::Bind(&CloudPolicyClient::OnFetchRobotAuthCodesCompleted
,
232 base::Unretained(this)));
235 void CloudPolicyClient::Unregister() {
237 policy_fetch_request_job_
.reset(
238 service_
->CreateJob(DeviceManagementRequestJob::TYPE_UNREGISTRATION
,
239 GetRequestContext()));
240 policy_fetch_request_job_
->SetDMToken(dm_token_
);
241 policy_fetch_request_job_
->SetClientID(client_id_
);
242 policy_fetch_request_job_
->GetRequest()->mutable_unregister_request();
243 policy_fetch_request_job_
->Start(
244 base::Bind(&CloudPolicyClient::OnUnregisterCompleted
,
245 base::Unretained(this)));
248 void CloudPolicyClient::UploadCertificate(
249 const std::string
& certificate_data
,
250 const CloudPolicyClient::StatusCallback
& callback
) {
251 CHECK(is_registered());
252 scoped_ptr
<DeviceManagementRequestJob
> request_job(
253 service_
->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE
,
254 GetRequestContext()));
255 request_job
->SetDMToken(dm_token_
);
256 request_job
->SetClientID(client_id_
);
258 em::DeviceManagementRequest
* request
= request_job
->GetRequest();
259 request
->mutable_cert_upload_request()->set_device_certificate(
262 const DeviceManagementRequestJob::Callback job_callback
=
263 base::Bind(&CloudPolicyClient::OnCertificateUploadCompleted
,
264 base::Unretained(this), request_job
.get(), callback
);
266 request_jobs_
.push_back(request_job
.Pass());
267 request_jobs_
.back()->Start(job_callback
);
270 void CloudPolicyClient::UploadDeviceStatus(
271 const em::DeviceStatusReportRequest
* device_status
,
272 const em::SessionStatusReportRequest
* session_status
,
273 const CloudPolicyClient::StatusCallback
& callback
) {
274 CHECK(is_registered());
275 // Should pass in at least one type of status.
276 DCHECK(device_status
|| session_status
);
277 scoped_ptr
<DeviceManagementRequestJob
> request_job(
278 service_
->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_STATUS
,
279 GetRequestContext()));
280 request_job
->SetDMToken(dm_token_
);
281 request_job
->SetClientID(client_id_
);
283 em::DeviceManagementRequest
* request
= request_job
->GetRequest();
285 *request
->mutable_device_status_report_request() = *device_status
;
287 *request
->mutable_session_status_report_request() = *session_status
;
289 const DeviceManagementRequestJob::Callback job_callback
=
290 base::Bind(&CloudPolicyClient::OnStatusUploadCompleted
,
291 base::Unretained(this), request_job
.get(), callback
);
293 request_jobs_
.push_back(request_job
.Pass());
294 request_jobs_
.back()->Start(job_callback
);
297 void CloudPolicyClient::FetchRemoteCommands(
298 scoped_ptr
<RemoteCommandJob::UniqueIDType
> last_command_id
,
299 const std::vector
<em::RemoteCommandResult
>& command_results
,
300 const RemoteCommandCallback
& callback
) {
301 CHECK(is_registered());
302 scoped_ptr
<DeviceManagementRequestJob
> request_job(service_
->CreateJob(
303 DeviceManagementRequestJob::TYPE_REMOTE_COMMANDS
, GetRequestContext()));
305 request_job
->SetDMToken(dm_token_
);
306 request_job
->SetClientID(client_id_
);
308 em::DeviceRemoteCommandRequest
* const request
=
309 request_job
->GetRequest()->mutable_remote_command_request();
312 request
->set_last_command_unique_id(*last_command_id
);
314 for (const auto& command_result
: command_results
)
315 *request
->add_command_results() = command_result
;
317 const DeviceManagementRequestJob::Callback job_callback
=
318 base::Bind(&CloudPolicyClient::OnRemoteCommandsFetched
,
319 base::Unretained(this), request_job
.get(), callback
);
321 request_jobs_
.push_back(request_job
.Pass());
322 request_jobs_
.back()->Start(job_callback
);
325 void CloudPolicyClient::GetDeviceAttributeUpdatePermission(
326 const std::string
&auth_token
,
327 const CloudPolicyClient::StatusCallback
& callback
) {
328 CHECK(is_registered());
329 DCHECK(!auth_token
.empty());
331 scoped_ptr
<DeviceManagementRequestJob
> request_job(
333 DeviceManagementRequestJob::TYPE_ATTRIBUTE_UPDATE_PERMISSION
,
334 GetRequestContext()));
336 request_job
->SetOAuthToken(auth_token
);
337 request_job
->SetClientID(client_id_
);
339 request_job
->GetRequest()->
340 mutable_device_attribute_update_permission_request();
342 const DeviceManagementRequestJob::Callback job_callback
=
343 base::Bind(&CloudPolicyClient::OnDeviceAttributeUpdatePermissionCompleted
,
344 base::Unretained(this), request_job
.get(), callback
);
346 request_jobs_
.push_back(request_job
.Pass());
347 request_jobs_
.back()->Start(job_callback
);
350 void CloudPolicyClient::UpdateDeviceAttributes(
351 const std::string
& auth_token
,
352 const std::string
& asset_id
,
353 const std::string
& location
,
354 const CloudPolicyClient::StatusCallback
& callback
) {
355 CHECK(is_registered());
356 DCHECK(!auth_token
.empty());
358 scoped_ptr
<DeviceManagementRequestJob
> request_job(
360 DeviceManagementRequestJob::TYPE_ATTRIBUTE_UPDATE
,
361 GetRequestContext()));
363 request_job
->SetOAuthToken(auth_token
);
364 request_job
->SetClientID(client_id_
);
366 em::DeviceAttributeUpdateRequest
* request
=
367 request_job
->GetRequest()->mutable_device_attribute_update_request();
369 request
->set_asset_id(asset_id
);
370 request
->set_location(location
);
372 const DeviceManagementRequestJob::Callback job_callback
=
373 base::Bind(&CloudPolicyClient::OnDeviceAttributeUpdated
,
374 base::Unretained(this), request_job
.get(), callback
);
376 request_jobs_
.push_back(request_job
.Pass());
377 request_jobs_
.back()->Start(job_callback
);
380 void CloudPolicyClient::UpdateGcmId(
381 const std::string
& gcm_id
,
382 const CloudPolicyClient::StatusCallback
& callback
) {
383 CHECK(is_registered());
385 scoped_ptr
<DeviceManagementRequestJob
> request_job(service_
->CreateJob(
386 DeviceManagementRequestJob::TYPE_GCM_ID_UPDATE
, GetRequestContext()));
388 request_job
->SetDMToken(dm_token_
);
389 request_job
->SetClientID(client_id_
);
391 em::GcmIdUpdateRequest
* const request
=
392 request_job
->GetRequest()->mutable_gcm_id_update_request();
394 request
->set_gcm_id(gcm_id
);
396 const DeviceManagementRequestJob::Callback job_callback
=
397 base::Bind(&CloudPolicyClient::OnGcmIdUpdated
, base::Unretained(this),
398 request_job
.get(), callback
);
400 request_jobs_
.push_back(request_job
.Pass());
401 request_jobs_
.back()->Start(job_callback
);
404 void CloudPolicyClient::AddObserver(Observer
* observer
) {
405 observers_
.AddObserver(observer
);
408 void CloudPolicyClient::RemoveObserver(Observer
* observer
) {
409 observers_
.RemoveObserver(observer
);
412 void CloudPolicyClient::AddPolicyTypeToFetch(
413 const std::string
& policy_type
,
414 const std::string
& settings_entity_id
) {
415 types_to_fetch_
.insert(std::make_pair(policy_type
, settings_entity_id
));
418 void CloudPolicyClient::RemovePolicyTypeToFetch(
419 const std::string
& policy_type
,
420 const std::string
& settings_entity_id
) {
421 types_to_fetch_
.erase(std::make_pair(policy_type
, settings_entity_id
));
424 void CloudPolicyClient::SetStateKeysToUpload(
425 const std::vector
<std::string
>& keys
) {
426 state_keys_to_upload_
= keys
;
429 const em::PolicyFetchResponse
* CloudPolicyClient::GetPolicyFor(
430 const std::string
& policy_type
,
431 const std::string
& settings_entity_id
) const {
432 ResponseMap::const_iterator it
=
433 responses_
.find(std::make_pair(policy_type
, settings_entity_id
));
434 return it
== responses_
.end() ? nullptr : it
->second
;
437 scoped_refptr
<net::URLRequestContextGetter
>
438 CloudPolicyClient::GetRequestContext() {
439 return request_context_
;
442 int CloudPolicyClient::GetActiveRequestCountForTest() const {
443 return request_jobs_
.size();
446 void CloudPolicyClient::OnRetryRegister(DeviceManagementRequestJob
* job
) {
447 DCHECK_EQ(policy_fetch_request_job_
.get(), job
);
448 // If the initial request managed to get to the server but the response didn't
449 // arrive at the client then retrying with the same client ID will fail.
450 // Set the re-registration flag so that the server accepts it.
451 // If the server hasn't seen the client ID before then it will also accept
452 // the re-registration.
453 job
->GetRequest()->mutable_register_request()->set_reregister(true);
456 void CloudPolicyClient::OnRegisterCompleted(
457 DeviceManagementStatus status
,
459 const em::DeviceManagementResponse
& response
) {
460 if (status
== DM_STATUS_SUCCESS
&&
461 (!response
.has_register_response() ||
462 !response
.register_response().has_device_management_token())) {
463 LOG(WARNING
) << "Invalid registration response.";
464 status
= DM_STATUS_RESPONSE_DECODING_ERROR
;
468 if (status
== DM_STATUS_SUCCESS
) {
469 dm_token_
= response
.register_response().device_management_token();
470 DVLOG(1) << "Client registration complete - DMToken = " << dm_token_
;
472 // Device mode is only relevant for device policy really, it's the
473 // responsibility of the consumer of the field to check validity.
474 device_mode_
= DEVICE_MODE_NOT_SET
;
475 if (response
.register_response().has_enrollment_type()) {
476 device_mode_
= TranslateProtobufDeviceMode(
477 response
.register_response().enrollment_type());
480 NotifyRegistrationStateChanged();
486 void CloudPolicyClient::OnFetchRobotAuthCodesCompleted(
487 DeviceManagementStatus status
,
489 const em::DeviceManagementResponse
& response
) {
490 if (status
== DM_STATUS_SUCCESS
&&
491 (!response
.has_service_api_access_response())) {
492 LOG(WARNING
) << "Invalid service api access response.";
493 status
= DM_STATUS_RESPONSE_DECODING_ERROR
;
497 if (status
== DM_STATUS_SUCCESS
) {
498 robot_api_auth_code_
= response
.service_api_access_response().auth_code();
499 DVLOG(1) << "Device robot account auth code fetch complete - code = "
500 << robot_api_auth_code_
;
502 NotifyRobotAuthCodesFetched();
508 void CloudPolicyClient::OnPolicyFetchCompleted(
509 DeviceManagementStatus status
,
511 const em::DeviceManagementResponse
& response
) {
512 if (status
== DM_STATUS_SUCCESS
) {
513 if (!response
.has_policy_response() ||
514 response
.policy_response().response_size() == 0) {
515 LOG(WARNING
) << "Empty policy response.";
516 status
= DM_STATUS_RESPONSE_DECODING_ERROR
;
521 if (status
== DM_STATUS_SUCCESS
) {
522 const em::DevicePolicyResponse
& policy_response
=
523 response
.policy_response();
524 STLDeleteValues(&responses_
);
525 for (int i
= 0; i
< policy_response
.response_size(); ++i
) {
526 const em::PolicyFetchResponse
& response
= policy_response
.response(i
);
527 em::PolicyData policy_data
;
528 if (!policy_data
.ParseFromString(response
.policy_data()) ||
529 !policy_data
.IsInitialized() ||
530 !policy_data
.has_policy_type()) {
531 LOG(WARNING
) << "Invalid PolicyData received, ignoring";
534 const std::string
& type
= policy_data
.policy_type();
535 std::string entity_id
;
536 if (policy_data
.has_settings_entity_id())
537 entity_id
= policy_data
.settings_entity_id();
538 std::pair
<std::string
, std::string
> key(type
, entity_id
);
539 if (ContainsKey(responses_
, key
)) {
540 LOG(WARNING
) << "Duplicate PolicyFetchResponse for type: "
541 << type
<< ", entity: " << entity_id
<< ", ignoring";
544 responses_
[key
] = new em::PolicyFetchResponse(response
);
546 state_keys_to_upload_
.clear();
547 NotifyPolicyFetched();
553 void CloudPolicyClient::OnUnregisterCompleted(
554 DeviceManagementStatus status
,
556 const em::DeviceManagementResponse
& response
) {
557 if (status
== DM_STATUS_SUCCESS
&& !response
.has_unregister_response()) {
558 // Assume unregistration has succeeded either way.
559 LOG(WARNING
) << "Empty unregistration response.";
563 if (status
== DM_STATUS_SUCCESS
) {
565 // Cancel all outstanding jobs.
566 request_jobs_
.clear();
567 NotifyRegistrationStateChanged();
573 void CloudPolicyClient::OnCertificateUploadCompleted(
574 const DeviceManagementRequestJob
* job
,
575 const CloudPolicyClient::StatusCallback
& callback
,
576 DeviceManagementStatus status
,
578 const enterprise_management::DeviceManagementResponse
& response
) {
581 if (status
!= DM_STATUS_SUCCESS
) {
584 } else if (!response
.has_cert_upload_response()) {
585 LOG(WARNING
) << "Empty upload certificate response.";
588 callback
.Run(success
);
589 // Must call RemoveJob() last, because it frees |callback|.
593 void CloudPolicyClient::OnDeviceAttributeUpdatePermissionCompleted(
594 const DeviceManagementRequestJob
* job
,
595 const CloudPolicyClient::StatusCallback
& callback
,
596 DeviceManagementStatus status
,
598 const em::DeviceManagementResponse
& response
) {
599 bool success
= false;
601 if (status
== DM_STATUS_SUCCESS
&&
602 !response
.has_device_attribute_update_permission_response()) {
603 LOG(WARNING
) << "Invalid device attribute update permission response.";
604 status
= DM_STATUS_RESPONSE_DECODING_ERROR
;
608 if (status
== DM_STATUS_SUCCESS
&&
609 response
.device_attribute_update_permission_response().has_result() &&
610 response
.device_attribute_update_permission_response().result() ==
611 em::DeviceAttributeUpdatePermissionResponse::ATTRIBUTE_UPDATE_ALLOWED
) {
615 callback
.Run(success
);
619 void CloudPolicyClient::OnDeviceAttributeUpdated(
620 const DeviceManagementRequestJob
* job
,
621 const CloudPolicyClient::StatusCallback
& callback
,
622 DeviceManagementStatus status
,
624 const em::DeviceManagementResponse
& response
) {
625 bool success
= false;
627 if (status
== DM_STATUS_SUCCESS
&&
628 !response
.has_device_attribute_update_response()) {
629 LOG(WARNING
) << "Invalid device attribute update response.";
630 status
= DM_STATUS_RESPONSE_DECODING_ERROR
;
634 if (status
== DM_STATUS_SUCCESS
&&
635 response
.device_attribute_update_response().has_result() &&
636 response
.device_attribute_update_response().result() ==
637 em::DeviceAttributeUpdateResponse::ATTRIBUTE_UPDATE_SUCCESS
) {
641 callback
.Run(success
);
645 void CloudPolicyClient::RemoveJob(const DeviceManagementRequestJob
* job
) {
646 for (auto it
= request_jobs_
.begin(); it
!= request_jobs_
.end(); ++it
) {
648 request_jobs_
.erase(it
);
652 // This job was already deleted from our list, somehow. This shouldn't
653 // happen since deleting the job should cancel the callback.
657 void CloudPolicyClient::OnStatusUploadCompleted(
658 const DeviceManagementRequestJob
* job
,
659 const CloudPolicyClient::StatusCallback
& callback
,
660 DeviceManagementStatus status
,
662 const enterprise_management::DeviceManagementResponse
& response
) {
664 if (status
!= DM_STATUS_SUCCESS
)
667 callback
.Run(status
== DM_STATUS_SUCCESS
);
668 // Must call RemoveJob() last, because it frees |callback|.
672 void CloudPolicyClient::OnRemoteCommandsFetched(
673 const DeviceManagementRequestJob
* job
,
674 const RemoteCommandCallback
& callback
,
675 DeviceManagementStatus status
,
677 const enterprise_management::DeviceManagementResponse
& response
) {
678 std::vector
<enterprise_management::RemoteCommand
> commands
;
679 if (status
== DM_STATUS_SUCCESS
) {
680 if (response
.has_remote_command_response()) {
681 for (const auto& command
: response
.remote_command_response().commands())
682 commands
.push_back(command
);
684 status
= DM_STATUS_RESPONSE_DECODING_ERROR
;
687 callback
.Run(status
, commands
);
688 // Must call RemoveJob() last, because it frees |callback|.
692 void CloudPolicyClient::OnGcmIdUpdated(
693 const DeviceManagementRequestJob
* job
,
694 const StatusCallback
& callback
,
695 DeviceManagementStatus status
,
697 const enterprise_management::DeviceManagementResponse
& response
) {
699 if (status
!= DM_STATUS_SUCCESS
)
702 callback
.Run(status
== DM_STATUS_SUCCESS
);
706 void CloudPolicyClient::NotifyPolicyFetched() {
707 FOR_EACH_OBSERVER(Observer
, observers_
, OnPolicyFetched(this));
710 void CloudPolicyClient::NotifyRegistrationStateChanged() {
711 FOR_EACH_OBSERVER(Observer
, observers_
, OnRegistrationStateChanged(this));
714 void CloudPolicyClient::NotifyRobotAuthCodesFetched() {
715 FOR_EACH_OBSERVER(Observer
, observers_
, OnRobotAuthCodesFetched(this));
718 void CloudPolicyClient::NotifyClientError() {
719 FOR_EACH_OBSERVER(Observer
, observers_
, OnClientError(this));
722 } // namespace policy