15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/device_management_service.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPostContentType[] = "application/protobuf"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth="; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token="; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Number of times to retry on ERR_NETWORK_CHANGED errors. 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxNetworkChangedRetries = 3; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HTTP Error Codes of the DM Server with their concrete meanings in the context 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the DM Server communication. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSuccess = 200; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidArgument = 400; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidAuthCookieOrDMToken = 401; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMissingLicenses = 402; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDeviceManagementNotAllowed = 403; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidURL = 404; // This error is not coming from the GFE. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidSerialNumber = 405; 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst int kDomainMismatch = 406; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDeviceIdConflict = 409; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDeviceNotFound = 410; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPendingApproval = 412; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInternalServerError = 500; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kServiceUnavailable = 503; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kPolicyNotFound = 902; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kDeprovisioned = 903; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsProxyError(const net::URLRequestStatus status) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status.error()) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_PROXY_CONNECTION_FAILED: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_TUNNEL_CONNECTION_FAILED: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_PROXY_AUTH_UNSUPPORTED: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE: 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_PROXY_CERTIFICATE_INVALID: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_SOCKS_CONNECTION_FAILED: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsProtobufMimeType(const net::URLFetcher* fetcher) { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return fetcher->GetResponseHeaders()->HasHeaderValue( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "content-type", "application/x-protobuffer"); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FailedWithProxy(const net::URLFetcher* fetcher) { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY) != 0) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The request didn't use a proxy. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fetcher->GetStatus().is_success() && 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsProxyError(fetcher->GetStatus())) { 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Proxy failed while contacting dmserver."; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fetcher->GetStatus().is_success() && 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->GetResponseCode() == kSuccess && 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->WasFetchedViaProxy() && 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !IsProtobufMimeType(fetcher)) { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The proxy server can be misconfigured but pointing to an existing 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // server that replies to requests. Try to recover if a successful 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // request that went through a proxy returns an unexpected mime type. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Got bad mime-type in response from dmserver that was " 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "fetched via a proxy."; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* UserAffiliationToString(UserAffiliation affiliation) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (affiliation) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USER_AFFILIATION_MANAGED: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueUserAffiliationManaged; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USER_AFFILIATION_NONE: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueUserAffiliationNone; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Invalid user affiliation " << affiliation; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueUserAffiliationNone; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* JobTypeToRequestType(DeviceManagementRequestJob::JobType type) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestAutoEnrollment; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_REGISTRATION: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestRegister; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_POLICY_FETCH: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestPolicy; 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH: 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return dm_protocol::kValueRequestApiAuthorization; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_UNREGISTRATION: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestUnregister; 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE: 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return dm_protocol::kValueRequestUploadCertificate; 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL: 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return dm_protocol::kValueRequestDeviceStateRetrieval; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Invalid job type " << type; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ""; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Request job implementation used with DeviceManagementService. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeviceManagementRequestJobImpl : public DeviceManagementRequestJob { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementRequestJobImpl( 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) JobType type, 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& agent_parameter, 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& platform_parameter, 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementService* service, 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) net::URLRequestContextGetter* request_context); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DeviceManagementRequestJobImpl(); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handles the URL request response. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleResponse(const net::URLRequestStatus& status, 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the URL to contact. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL GetURL(const std::string& server_url); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Configures the fetcher, setting up payload and headers. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ConfigureRequest(net::URLFetcher* fetcher); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns true if this job should be retried. |fetcher| has just completed, 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and can be inspected to determine if the request failed and should be 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // retried. 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool ShouldRetry(const net::URLFetcher* fetcher); 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invoked right before retrying this job. 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PrepareRetry(); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeviceManagementRequestJob: 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invokes the callback with the given error code. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReportError(DeviceManagementStatus code); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pointer to the service this job is associated with. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceManagementService* service_; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Whether the BYPASS_PROXY flag should be set by ConfigureRequest(). 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bypass_proxy_; 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Number of times that this job has been retried due to ERR_NETWORK_CHANGED. 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int retries_count_; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The request context to use for this job. 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) net::URLRequestContextGetter* request_context_; 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DeviceManagementRequestJobImpl); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJobImpl::DeviceManagementRequestJobImpl( 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JobType type, 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& agent_parameter, 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& platform_parameter, 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementService* service, 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) net::URLRequestContextGetter* request_context) 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : DeviceManagementRequestJob(type, agent_parameter, platform_parameter), 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_(service), 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bypass_proxy_(false), 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) retries_count_(0), 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_context_(request_context) {} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJobImpl::~DeviceManagementRequestJobImpl() { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->RemoveJob(this); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::Run() { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->AddJob(this); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::HandleResponse( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.status() != net::URLRequestStatus::SUCCESS) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "DMServer request failed, status: " << status.status() 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", error: " << status.error(); 216b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) em::DeviceManagementResponse dummy_response; 217b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) callback_.Run(DM_STATUS_REQUEST_FAILED, status.error(), dummy_response); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_code != kSuccess) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "DMServer sent an error response: " << response_code; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (response_code) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kSuccess: { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) em::DeviceManagementResponse response; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response.ParseFromString(data)) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_RESPONSE_DECODING_ERROR); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 231b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) callback_.Run(DM_STATUS_SUCCESS, net::OK, response); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidArgument: 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_REQUEST_INVALID); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidAuthCookieOrDMToken: 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kMissingLicenses: 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_MISSING_LICENSES); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kDeviceManagementNotAllowed: 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kPendingApproval: 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_ACTIVATION_PENDING); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidURL: 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInternalServerError: 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kServiceUnavailable: 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kDeviceNotFound: 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_DEVICE_NOT_FOUND); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kPolicyNotFound: 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_POLICY_NOT_FOUND); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidSerialNumber: 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case kDomainMismatch: 264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ReportError(DM_STATUS_SERVICE_DOMAIN_MISMATCH); 265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case kDeprovisioned: 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_DEPROVISIONED); 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kDeviceIdConflict: 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_DEVICE_ID_CONFLICT); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle all unknown 5xx HTTP error codes as temporary and any other 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unknown error as one that needs more time to recover. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_code >= 500 && response_code <= 599) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_HTTP_STATUS_ERROR); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL DeviceManagementRequestJobImpl::GetURL( 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& server_url) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string result(server_url); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += '?'; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ParameterMap::const_iterator entry(query_params_.begin()); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry != query_params_.end(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++entry) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry != query_params_.begin()) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += '&'; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += net::EscapeQueryParamValue(entry->first, true); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += '='; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += net::EscapeQueryParamValue(entry->second, true); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GURL(result); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::ConfigureRequest( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher* fetcher) { 301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fetcher->SetRequestContext(request_context_); 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::LOAD_DO_NOT_SAVE_COOKIES | 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::LOAD_DISABLE_CACHE | 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (bypass_proxy_ ? net::LOAD_BYPASS_PROXY : 0)); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string payload; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(request_.SerializeToString(&payload)); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->SetUploadData(kPostContentType, payload); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extra_headers; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_token_.empty()) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_headers += kServiceTokenAuthHeader + gaia_token_ + "\n"; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dm_token_.empty()) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_headers += kDMTokenAuthHeader + dm_token_ + "\n"; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->SetExtraRequestHeaders(extra_headers); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DeviceManagementRequestJobImpl::ShouldRetry( 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::URLFetcher* fetcher) { 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FailedWithProxy(fetcher) && !bypass_proxy_) { 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Retry the job if it failed due to a broken proxy, by bypassing the 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // proxy on the next try. 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bypass_proxy_ = true; 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Early device policy fetches on ChromeOS and Auto-Enrollment checks are 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // often interrupted during ChromeOS startup when network change notifications 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // are sent. Allowing the fetcher to retry once after that is enough to 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // recover; allow it to retry up to 3 times just in case. 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fetcher->GetStatus().error() == net::ERR_NETWORK_CHANGED && 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retries_count_ < kMaxNetworkChangedRetries) { 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++retries_count_; 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The request didn't fail, or the limit of retry attempts has been reached; 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // forward the result to the job owner. 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceManagementRequestJobImpl::PrepareRetry() { 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!retry_callback_.is_null()) 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_callback_.Run(this); 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::ReportError(DeviceManagementStatus code) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) em::DeviceManagementResponse dummy_response; 348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) callback_.Run(code, net::OK, dummy_response); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJob::~DeviceManagementRequestJob() {} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetGaiaToken(const std::string& gaia_token) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gaia_token_ = gaia_token; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetOAuthToken(const std::string& oauth_token) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamOAuthToken, oauth_token); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetUserAffiliation( 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserAffiliation user_affiliation) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamUserAffiliation, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserAffiliationToString(user_affiliation)); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetDMToken(const std::string& dm_token) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dm_token_ = dm_token; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetClientID(const std::string& client_id) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamDeviceID, client_id); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)em::DeviceManagementRequest* DeviceManagementRequestJob::GetRequest() { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &request_; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DeviceManagementRequestJob::DeviceManagementRequestJob( 3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) JobType type, 3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& agent_parameter, 3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& platform_parameter) { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamRequest, JobTypeToRequestType(type)); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamDeviceType, dm_protocol::kValueDeviceType); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamAppType, dm_protocol::kValueAppType); 3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddParameter(dm_protocol::kParamAgent, agent_parameter); 3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddParameter(dm_protocol::kParamPlatform, platform_parameter); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceManagementRequestJob::SetRetryCallback( 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const RetryCallback& retry_callback) { 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_callback_ = retry_callback; 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::Start(const Callback& callback) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Run(); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::AddParameter(const std::string& name, 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& value) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query_params_.push_back(std::make_pair(name, value)); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A random value that other fetchers won't likely use. 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int DeviceManagementService::kURLFetcherID = 0xde71ce1d; 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementService::~DeviceManagementService() { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All running jobs should have been cancelled by now. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pending_jobs_.empty()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(queued_jobs_.empty()); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJob* DeviceManagementService::CreateJob( 415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementRequestJob::JobType type, 416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) net::URLRequestContextGetter* request_context) { 4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return new DeviceManagementRequestJobImpl( 4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) type, 4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) configuration_->GetAgentParameter(), 4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) configuration_->GetPlatformParameter(), 421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this, 422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_context); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::ScheduleInitialization(int64 delay_milliseconds) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&DeviceManagementService::Initialize, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(delay_milliseconds)); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::Initialize() { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = true; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!queued_jobs_.empty()) { 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartJob(queued_jobs_.front()); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.pop_front(); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::Shutdown() { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (JobFetcherMap::iterator job(pending_jobs_.begin()); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job != pending_jobs_.end(); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++job) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete job->first; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.push_back(job->second); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_.clear(); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementService::DeviceManagementService( 457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<Configuration> configuration) 4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : configuration_(configuration.Pass()), 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_(false), 460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(configuration_); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceManagementService::StartJob(DeviceManagementRequestJobImpl* job) { 465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string server_url = GetServerUrl(); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher* fetcher = net::URLFetcher::Create( 4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kURLFetcherID, job->GetURL(server_url), net::URLFetcher::POST, this); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->ConfigureRequest(fetcher); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_[fetcher] = job; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->Start(); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string DeviceManagementService::GetServerUrl() { 474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return configuration_->GetServerUrl(); 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::OnURLFetchComplete( 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLFetcher* source) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JobFetcherMap::iterator entry(pending_jobs_.find(source)); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry == pending_jobs_.end()) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Callback from foreign URL fetcher"; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceManagementRequestJobImpl* job = entry->second; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_.erase(entry); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (job->ShouldRetry(source)) { 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Retrying dmserver request."; 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) job->PrepareRetry(); 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartJob(job); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetResponseAsString(&data); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->HandleResponse(source->GetStatus(), source->GetResponseCode(), 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetCookies(), data); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete source; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::AddJob(DeviceManagementRequestJobImpl* job) { 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartJob(job); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.push_back(job); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::RemoveJob(DeviceManagementRequestJobImpl* job) { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (JobFetcherMap::iterator entry(pending_jobs_.begin()); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry != pending_jobs_.end(); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++entry) { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->second == job) { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete entry->first; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_.erase(entry); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const JobQueue::iterator elem = 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(queued_jobs_.begin(), queued_jobs_.end(), job); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (elem != queued_jobs_.end()) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.erase(elem); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 526