Include all dupe types (event when value is zero) in scan stats.
[chromium-blink-merge.git] / components / policy / core / common / cloud / cloud_policy_client.cc
blob6a5d101a9d62aa34004a7598a72d764aa307dddf
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"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/guid.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;
19 namespace policy {
21 namespace {
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) {
27 switch (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 == GetChromeUserPolicyType();
42 } // namespace
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 UserAffiliation user_affiliation,
54 DeviceManagementService* service,
55 scoped_refptr<net::URLRequestContextGetter> request_context)
56 : machine_id_(machine_id),
57 machine_model_(machine_model),
58 verification_key_hash_(verification_key_hash),
59 user_affiliation_(user_affiliation),
60 device_mode_(DEVICE_MODE_NOT_SET),
61 submit_machine_id_(false),
62 public_key_version_(-1),
63 public_key_version_valid_(false),
64 invalidation_version_(0),
65 fetched_invalidation_version_(0),
66 service_(service), // Can be null for unit tests.
67 status_(DM_STATUS_SUCCESS),
68 request_context_(request_context) {
71 CloudPolicyClient::~CloudPolicyClient() {
72 STLDeleteValues(&responses_);
75 void CloudPolicyClient::SetupRegistration(const std::string& dm_token,
76 const std::string& client_id) {
77 DCHECK(!dm_token.empty());
78 DCHECK(!client_id.empty());
79 DCHECK(!is_registered());
81 dm_token_ = dm_token;
82 client_id_ = client_id;
83 request_jobs_.clear();
84 policy_fetch_request_job_.reset();
85 STLDeleteValues(&responses_);
87 NotifyRegistrationStateChanged();
90 void CloudPolicyClient::Register(em::DeviceRegisterRequest::Type type,
91 em::DeviceRegisterRequest::Flavor flavor,
92 const std::string& auth_token,
93 const std::string& client_id,
94 const std::string& requisition,
95 const std::string& current_state_key) {
96 DCHECK(service_);
97 DCHECK(!auth_token.empty());
98 DCHECK(!is_registered());
100 if (client_id.empty()) {
101 // Generate a new client ID. This is intentionally done on each new
102 // registration request in order to preserve privacy. Reusing IDs would mean
103 // the server could track clients by their registration attempts.
104 client_id_ = base::GenerateGUID();
105 } else {
106 client_id_ = client_id;
109 policy_fetch_request_job_.reset(
110 service_->CreateJob(DeviceManagementRequestJob::TYPE_REGISTRATION,
111 GetRequestContext()));
112 policy_fetch_request_job_->SetOAuthToken(auth_token);
113 policy_fetch_request_job_->SetClientID(client_id_);
115 em::DeviceRegisterRequest* request =
116 policy_fetch_request_job_->GetRequest()->mutable_register_request();
117 if (!client_id.empty())
118 request->set_reregister(true);
119 request->set_type(type);
120 if (!machine_id_.empty())
121 request->set_machine_id(machine_id_);
122 if (!machine_model_.empty())
123 request->set_machine_model(machine_model_);
124 if (!requisition.empty())
125 request->set_requisition(requisition);
126 if (!current_state_key.empty())
127 request->set_server_backed_state_key(current_state_key);
128 request->set_flavor(flavor);
130 policy_fetch_request_job_->SetRetryCallback(
131 base::Bind(&CloudPolicyClient::OnRetryRegister, base::Unretained(this)));
133 policy_fetch_request_job_->Start(
134 base::Bind(&CloudPolicyClient::OnRegisterCompleted,
135 base::Unretained(this)));
138 void CloudPolicyClient::SetInvalidationInfo(
139 int64 version,
140 const std::string& payload) {
141 invalidation_version_ = version;
142 invalidation_payload_ = payload;
145 void CloudPolicyClient::FetchPolicy() {
146 CHECK(is_registered());
147 CHECK(!types_to_fetch_.empty());
149 policy_fetch_request_job_.reset(
150 service_->CreateJob(DeviceManagementRequestJob::TYPE_POLICY_FETCH,
151 GetRequestContext()));
152 policy_fetch_request_job_->SetDMToken(dm_token_);
153 policy_fetch_request_job_->SetClientID(client_id_);
154 policy_fetch_request_job_->SetUserAffiliation(user_affiliation_);
156 em::DeviceManagementRequest* request =
157 policy_fetch_request_job_->GetRequest();
159 // Build policy fetch requests.
160 em::DevicePolicyRequest* policy_request = request->mutable_policy_request();
161 for (const auto& type_to_fetch : types_to_fetch_) {
162 em::PolicyFetchRequest* fetch_request = policy_request->add_request();
163 fetch_request->set_policy_type(type_to_fetch.first);
164 if (!type_to_fetch.second.empty())
165 fetch_request->set_settings_entity_id(type_to_fetch.second);
167 // Request signed policy blobs to help prevent tampering on the client.
168 fetch_request->set_signature_type(em::PolicyFetchRequest::SHA1_RSA);
169 if (public_key_version_valid_)
170 fetch_request->set_public_key_version(public_key_version_);
172 if (!verification_key_hash_.empty())
173 fetch_request->set_verification_key_hash(verification_key_hash_);
175 // These fields are included only in requests for chrome policy.
176 if (IsChromePolicy(type_to_fetch.first)) {
177 if (submit_machine_id_ && !machine_id_.empty())
178 fetch_request->set_machine_id(machine_id_);
179 if (!last_policy_timestamp_.is_null()) {
180 base::TimeDelta timestamp(
181 last_policy_timestamp_ - base::Time::UnixEpoch());
182 fetch_request->set_timestamp(timestamp.InMilliseconds());
184 if (!invalidation_payload_.empty()) {
185 fetch_request->set_invalidation_version(invalidation_version_);
186 fetch_request->set_invalidation_payload(invalidation_payload_);
191 // Add device state keys.
192 if (!state_keys_to_upload_.empty()) {
193 em::DeviceStateKeyUpdateRequest* key_update_request =
194 request->mutable_device_state_key_update_request();
195 for (std::vector<std::string>::const_iterator key(
196 state_keys_to_upload_.begin());
197 key != state_keys_to_upload_.end();
198 ++key) {
199 key_update_request->add_server_backed_state_key(*key);
203 // Set the fetched invalidation version to the latest invalidation version
204 // since it is now the invalidation version used for the latest fetch.
205 fetched_invalidation_version_ = invalidation_version_;
207 // Fire the job.
208 policy_fetch_request_job_->Start(
209 base::Bind(&CloudPolicyClient::OnPolicyFetchCompleted,
210 base::Unretained(this)));
213 void CloudPolicyClient::FetchRobotAuthCodes(const std::string& auth_token) {
214 CHECK(is_registered());
215 DCHECK(!auth_token.empty());
217 policy_fetch_request_job_.reset(service_->CreateJob(
218 DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH,
219 GetRequestContext()));
220 // The credentials of a domain user are needed in order to mint a new OAuth2
221 // authorization token for the robot account.
222 policy_fetch_request_job_->SetOAuthToken(auth_token);
223 policy_fetch_request_job_->SetDMToken(dm_token_);
224 policy_fetch_request_job_->SetClientID(client_id_);
226 em::DeviceServiceApiAccessRequest* request =
227 policy_fetch_request_job_->GetRequest()->
228 mutable_service_api_access_request();
229 request->set_oauth2_client_id(
230 GaiaUrls::GetInstance()->oauth2_chrome_client_id());
231 request->add_auth_scope(GaiaConstants::kAnyApiOAuth2Scope);
233 policy_fetch_request_job_->Start(
234 base::Bind(&CloudPolicyClient::OnFetchRobotAuthCodesCompleted,
235 base::Unretained(this)));
238 void CloudPolicyClient::Unregister() {
239 DCHECK(service_);
240 policy_fetch_request_job_.reset(
241 service_->CreateJob(DeviceManagementRequestJob::TYPE_UNREGISTRATION,
242 GetRequestContext()));
243 policy_fetch_request_job_->SetDMToken(dm_token_);
244 policy_fetch_request_job_->SetClientID(client_id_);
245 policy_fetch_request_job_->GetRequest()->mutable_unregister_request();
246 policy_fetch_request_job_->Start(
247 base::Bind(&CloudPolicyClient::OnUnregisterCompleted,
248 base::Unretained(this)));
251 void CloudPolicyClient::UploadCertificate(
252 const std::string& certificate_data,
253 const CloudPolicyClient::StatusCallback& callback) {
254 CHECK(is_registered());
255 scoped_ptr<DeviceManagementRequestJob> request_job(
256 service_->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE,
257 GetRequestContext()));
258 request_job->SetDMToken(dm_token_);
259 request_job->SetClientID(client_id_);
261 em::DeviceManagementRequest* request = request_job->GetRequest();
262 request->mutable_cert_upload_request()->set_device_certificate(
263 certificate_data);
265 const DeviceManagementRequestJob::Callback job_callback =
266 base::Bind(&CloudPolicyClient::OnCertificateUploadCompleted,
267 base::Unretained(this), request_job.get(), callback);
269 request_jobs_.push_back(request_job.Pass());
270 request_jobs_.back()->Start(job_callback);
273 void CloudPolicyClient::UploadDeviceStatus(
274 const em::DeviceStatusReportRequest* device_status,
275 const em::SessionStatusReportRequest* session_status,
276 const CloudPolicyClient::StatusCallback& callback) {
277 CHECK(is_registered());
278 // Should pass in at least one type of status.
279 DCHECK(device_status || session_status);
280 scoped_ptr<DeviceManagementRequestJob> request_job(
281 service_->CreateJob(DeviceManagementRequestJob::TYPE_UPLOAD_STATUS,
282 GetRequestContext()));
283 request_job->SetDMToken(dm_token_);
284 request_job->SetClientID(client_id_);
286 em::DeviceManagementRequest* request = request_job->GetRequest();
287 if (device_status)
288 *request->mutable_device_status_report_request() = *device_status;
289 if (session_status)
290 *request->mutable_session_status_report_request() = *session_status;
292 const DeviceManagementRequestJob::Callback job_callback =
293 base::Bind(&CloudPolicyClient::OnStatusUploadCompleted,
294 base::Unretained(this), request_job.get(), callback);
296 request_jobs_.push_back(request_job.Pass());
297 request_jobs_.back()->Start(job_callback);
300 void CloudPolicyClient::FetchRemoteCommands(
301 scoped_ptr<RemoteCommandJob::UniqueIDType> last_command_id,
302 const std::vector<em::RemoteCommandResult>& command_results,
303 const RemoteCommandCallback& callback) {
304 CHECK(is_registered());
305 scoped_ptr<DeviceManagementRequestJob> request_job(service_->CreateJob(
306 DeviceManagementRequestJob::TYPE_REMOTE_COMMANDS, GetRequestContext()));
308 request_job->SetDMToken(dm_token_);
309 request_job->SetClientID(client_id_);
311 em::DeviceRemoteCommandRequest* const request =
312 request_job->GetRequest()->mutable_remote_command_request();
314 if (last_command_id)
315 request->set_last_command_unique_id(*last_command_id);
317 for (const auto& command_result : command_results)
318 *request->add_command_results() = command_result;
320 const DeviceManagementRequestJob::Callback job_callback =
321 base::Bind(&CloudPolicyClient::OnRemoteCommandsFetched,
322 base::Unretained(this), request_job.get(), callback);
324 request_jobs_.push_back(request_job.Pass());
325 request_jobs_.back()->Start(job_callback);
328 void CloudPolicyClient::GetDeviceAttributeUpdatePermission(
329 const std::string &auth_token,
330 const CloudPolicyClient::StatusCallback& callback) {
331 CHECK(is_registered());
332 DCHECK(!auth_token.empty());
334 scoped_ptr<DeviceManagementRequestJob> request_job(
335 service_->CreateJob(
336 DeviceManagementRequestJob::TYPE_ATTRIBUTE_UPDATE_PERMISSION,
337 GetRequestContext()));
339 request_job->SetOAuthToken(auth_token);
340 request_job->SetClientID(client_id_);
342 request_job->GetRequest()->
343 mutable_device_attribute_update_permission_request();
345 const DeviceManagementRequestJob::Callback job_callback =
346 base::Bind(&CloudPolicyClient::OnDeviceAttributeUpdatePermissionCompleted,
347 base::Unretained(this), request_job.get(), callback);
349 request_jobs_.push_back(request_job.Pass());
350 request_jobs_.back()->Start(job_callback);
353 void CloudPolicyClient::UpdateDeviceAttributes(
354 const std::string& auth_token,
355 const std::string& asset_id,
356 const std::string& location,
357 const CloudPolicyClient::StatusCallback& callback) {
358 CHECK(is_registered());
359 DCHECK(!auth_token.empty());
361 scoped_ptr<DeviceManagementRequestJob> request_job(
362 service_->CreateJob(
363 DeviceManagementRequestJob::TYPE_ATTRIBUTE_UPDATE,
364 GetRequestContext()));
366 request_job->SetOAuthToken(auth_token);
367 request_job->SetClientID(client_id_);
369 em::DeviceAttributeUpdateRequest* request =
370 request_job->GetRequest()->mutable_device_attribute_update_request();
372 request->set_asset_id(asset_id);
373 request->set_location(location);
375 const DeviceManagementRequestJob::Callback job_callback =
376 base::Bind(&CloudPolicyClient::OnDeviceAttributeUpdated,
377 base::Unretained(this), request_job.get(), callback);
379 request_jobs_.push_back(request_job.Pass());
380 request_jobs_.back()->Start(job_callback);
383 void CloudPolicyClient::AddObserver(Observer* observer) {
384 observers_.AddObserver(observer);
387 void CloudPolicyClient::RemoveObserver(Observer* observer) {
388 observers_.RemoveObserver(observer);
391 void CloudPolicyClient::AddPolicyTypeToFetch(
392 const std::string& policy_type,
393 const std::string& settings_entity_id) {
394 types_to_fetch_.insert(std::make_pair(policy_type, settings_entity_id));
397 void CloudPolicyClient::RemovePolicyTypeToFetch(
398 const std::string& policy_type,
399 const std::string& settings_entity_id) {
400 types_to_fetch_.erase(std::make_pair(policy_type, settings_entity_id));
403 void CloudPolicyClient::SetStateKeysToUpload(
404 const std::vector<std::string>& keys) {
405 state_keys_to_upload_ = keys;
408 const em::PolicyFetchResponse* CloudPolicyClient::GetPolicyFor(
409 const std::string& policy_type,
410 const std::string& settings_entity_id) const {
411 ResponseMap::const_iterator it =
412 responses_.find(std::make_pair(policy_type, settings_entity_id));
413 return it == responses_.end() ? nullptr : it->second;
416 scoped_refptr<net::URLRequestContextGetter>
417 CloudPolicyClient::GetRequestContext() {
418 return request_context_;
421 int CloudPolicyClient::GetActiveRequestCountForTest() const {
422 return request_jobs_.size();
425 void CloudPolicyClient::OnRetryRegister(DeviceManagementRequestJob* job) {
426 DCHECK_EQ(policy_fetch_request_job_.get(), job);
427 // If the initial request managed to get to the server but the response didn't
428 // arrive at the client then retrying with the same client ID will fail.
429 // Set the re-registration flag so that the server accepts it.
430 // If the server hasn't seen the client ID before then it will also accept
431 // the re-registration.
432 job->GetRequest()->mutable_register_request()->set_reregister(true);
435 void CloudPolicyClient::OnRegisterCompleted(
436 DeviceManagementStatus status,
437 int net_error,
438 const em::DeviceManagementResponse& response) {
439 if (status == DM_STATUS_SUCCESS &&
440 (!response.has_register_response() ||
441 !response.register_response().has_device_management_token())) {
442 LOG(WARNING) << "Invalid registration response.";
443 status = DM_STATUS_RESPONSE_DECODING_ERROR;
446 status_ = status;
447 if (status == DM_STATUS_SUCCESS) {
448 dm_token_ = response.register_response().device_management_token();
449 DVLOG(1) << "Client registration complete - DMToken = " << dm_token_;
451 // Device mode is only relevant for device policy really, it's the
452 // responsibility of the consumer of the field to check validity.
453 device_mode_ = DEVICE_MODE_NOT_SET;
454 if (response.register_response().has_enrollment_type()) {
455 device_mode_ = TranslateProtobufDeviceMode(
456 response.register_response().enrollment_type());
459 NotifyRegistrationStateChanged();
460 } else {
461 NotifyClientError();
465 void CloudPolicyClient::OnFetchRobotAuthCodesCompleted(
466 DeviceManagementStatus status,
467 int net_error,
468 const em::DeviceManagementResponse& response) {
469 if (status == DM_STATUS_SUCCESS &&
470 (!response.has_service_api_access_response() ||
471 response.service_api_access_response().auth_code().empty())) {
472 LOG(WARNING) << "Invalid service api access response.";
473 status = DM_STATUS_RESPONSE_DECODING_ERROR;
476 status_ = status;
477 if (status == DM_STATUS_SUCCESS) {
478 robot_api_auth_code_ = response.service_api_access_response().auth_code();
479 DVLOG(1) << "Device robot account auth code fetch complete - code = "
480 << robot_api_auth_code_;
482 NotifyRobotAuthCodesFetched();
483 } else {
484 NotifyClientError();
488 void CloudPolicyClient::OnPolicyFetchCompleted(
489 DeviceManagementStatus status,
490 int net_error,
491 const em::DeviceManagementResponse& response) {
492 if (status == DM_STATUS_SUCCESS) {
493 if (!response.has_policy_response() ||
494 response.policy_response().response_size() == 0) {
495 LOG(WARNING) << "Empty policy response.";
496 status = DM_STATUS_RESPONSE_DECODING_ERROR;
500 status_ = status;
501 if (status == DM_STATUS_SUCCESS) {
502 const em::DevicePolicyResponse& policy_response =
503 response.policy_response();
504 STLDeleteValues(&responses_);
505 for (int i = 0; i < policy_response.response_size(); ++i) {
506 const em::PolicyFetchResponse& response = policy_response.response(i);
507 em::PolicyData policy_data;
508 if (!policy_data.ParseFromString(response.policy_data()) ||
509 !policy_data.IsInitialized() ||
510 !policy_data.has_policy_type()) {
511 LOG(WARNING) << "Invalid PolicyData received, ignoring";
512 continue;
514 const std::string& type = policy_data.policy_type();
515 std::string entity_id;
516 if (policy_data.has_settings_entity_id())
517 entity_id = policy_data.settings_entity_id();
518 std::pair<std::string, std::string> key(type, entity_id);
519 if (ContainsKey(responses_, key)) {
520 LOG(WARNING) << "Duplicate PolicyFetchResponse for type: "
521 << type << ", entity: " << entity_id << ", ignoring";
522 continue;
524 responses_[key] = new em::PolicyFetchResponse(response);
526 state_keys_to_upload_.clear();
527 NotifyPolicyFetched();
528 } else {
529 NotifyClientError();
533 void CloudPolicyClient::OnUnregisterCompleted(
534 DeviceManagementStatus status,
535 int net_error,
536 const em::DeviceManagementResponse& response) {
537 if (status == DM_STATUS_SUCCESS && !response.has_unregister_response()) {
538 // Assume unregistration has succeeded either way.
539 LOG(WARNING) << "Empty unregistration response.";
542 status_ = status;
543 if (status == DM_STATUS_SUCCESS) {
544 dm_token_.clear();
545 // Cancel all outstanding jobs.
546 request_jobs_.clear();
547 NotifyRegistrationStateChanged();
548 } else {
549 NotifyClientError();
553 void CloudPolicyClient::OnCertificateUploadCompleted(
554 const DeviceManagementRequestJob* job,
555 const CloudPolicyClient::StatusCallback& callback,
556 DeviceManagementStatus status,
557 int net_error,
558 const enterprise_management::DeviceManagementResponse& response) {
559 bool success = true;
560 status_ = status;
561 if (status != DM_STATUS_SUCCESS) {
562 success = false;
563 NotifyClientError();
564 } else if (!response.has_cert_upload_response()) {
565 LOG(WARNING) << "Empty upload certificate response.";
566 success = false;
568 callback.Run(success);
569 // Must call RemoveJob() last, because it frees |callback|.
570 RemoveJob(job);
573 void CloudPolicyClient::OnDeviceAttributeUpdatePermissionCompleted(
574 const DeviceManagementRequestJob* job,
575 const CloudPolicyClient::StatusCallback& callback,
576 DeviceManagementStatus status,
577 int net_error,
578 const em::DeviceManagementResponse& response) {
579 bool success = false;
581 if (status == DM_STATUS_SUCCESS &&
582 !response.has_device_attribute_update_permission_response()) {
583 LOG(WARNING) << "Invalid device attribute update permission response.";
584 status = DM_STATUS_RESPONSE_DECODING_ERROR;
587 status_ = status;
588 if (status == DM_STATUS_SUCCESS &&
589 response.device_attribute_update_permission_response().has_result() &&
590 response.device_attribute_update_permission_response().result() ==
591 em::DeviceAttributeUpdatePermissionResponse::ATTRIBUTE_UPDATE_ALLOWED) {
592 success = true;
595 callback.Run(success);
596 RemoveJob(job);
599 void CloudPolicyClient::OnDeviceAttributeUpdated(
600 const DeviceManagementRequestJob* job,
601 const CloudPolicyClient::StatusCallback& callback,
602 DeviceManagementStatus status,
603 int net_error,
604 const em::DeviceManagementResponse& response) {
605 bool success = false;
607 if (status == DM_STATUS_SUCCESS &&
608 !response.has_device_attribute_update_response()) {
609 LOG(WARNING) << "Invalid device attribute update response.";
610 status = DM_STATUS_RESPONSE_DECODING_ERROR;
613 status_ = status;
614 if (status == DM_STATUS_SUCCESS &&
615 response.device_attribute_update_response().has_result() &&
616 response.device_attribute_update_response().result() ==
617 em::DeviceAttributeUpdateResponse::ATTRIBUTE_UPDATE_SUCCESS) {
618 success = true;
621 callback.Run(success);
622 RemoveJob(job);
625 void CloudPolicyClient::RemoveJob(const DeviceManagementRequestJob* job) {
626 for (auto it = request_jobs_.begin(); it != request_jobs_.end(); ++it) {
627 if (*it == job) {
628 request_jobs_.erase(it);
629 return;
632 // This job was already deleted from our list, somehow. This shouldn't
633 // happen since deleting the job should cancel the callback.
634 NOTREACHED();
637 void CloudPolicyClient::OnStatusUploadCompleted(
638 const DeviceManagementRequestJob* job,
639 const CloudPolicyClient::StatusCallback& callback,
640 DeviceManagementStatus status,
641 int net_error,
642 const enterprise_management::DeviceManagementResponse& response) {
643 status_ = status;
644 if (status != DM_STATUS_SUCCESS)
645 NotifyClientError();
647 callback.Run(status == DM_STATUS_SUCCESS);
648 // Must call RemoveJob() last, because it frees |callback|.
649 RemoveJob(job);
652 void CloudPolicyClient::OnRemoteCommandsFetched(
653 const DeviceManagementRequestJob* job,
654 const RemoteCommandCallback& callback,
655 DeviceManagementStatus status,
656 int net_error,
657 const enterprise_management::DeviceManagementResponse& response) {
658 std::vector<enterprise_management::RemoteCommand> commands;
659 if (status == DM_STATUS_SUCCESS) {
660 if (response.has_remote_command_response()) {
661 for (const auto& command : response.remote_command_response().commands())
662 commands.push_back(command);
663 } else {
664 status = DM_STATUS_RESPONSE_DECODING_ERROR;
667 callback.Run(status, commands);
668 // Must call RemoveJob() last, because it frees |callback|.
669 RemoveJob(job);
672 void CloudPolicyClient::NotifyPolicyFetched() {
673 FOR_EACH_OBSERVER(Observer, observers_, OnPolicyFetched(this));
676 void CloudPolicyClient::NotifyRegistrationStateChanged() {
677 FOR_EACH_OBSERVER(Observer, observers_, OnRegistrationStateChanged(this));
680 void CloudPolicyClient::NotifyRobotAuthCodesFetched() {
681 FOR_EACH_OBSERVER(Observer, observers_, OnRobotAuthCodesFetched(this));
684 void CloudPolicyClient::NotifyClientError() {
685 FOR_EACH_OBSERVER(Observer, observers_, OnClientError(this));
688 } // namespace policy