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" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/url_request_context_getter.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace em = enterprise_management; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPostContentType[] = "application/protobuf"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kServiceTokenAuthHeader[] = "Authorization: GoogleLogin auth="; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDMTokenAuthHeader[] = "Authorization: GoogleDMToken token="; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Number of times to retry on ERR_NETWORK_CHANGED errors. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxNetworkChangedRetries = 3; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HTTP Error Codes of the DM Server with their concrete meanings in the context 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the DM Server communication. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSuccess = 200; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidArgument = 400; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidAuthCookieOrDMToken = 401; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMissingLicenses = 402; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDeviceManagementNotAllowed = 403; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidURL = 404; // This error is not coming from the GFE. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInvalidSerialNumber = 405; 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst int kDomainMismatch = 406; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDeviceIdConflict = 409; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDeviceNotFound = 410; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPendingApproval = 412; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kInternalServerError = 500; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kServiceUnavailable = 503; 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kPolicyNotFound = 902; 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kDeprovisioned = 903; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsProxyError(const net::URLRequestStatus status) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status.error()) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_PROXY_CONNECTION_FAILED: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_TUNNEL_CONNECTION_FAILED: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_PROXY_AUTH_UNSUPPORTED: 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_HTTPS_PROXY_TUNNEL_RESPONSE: 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_PROXY_CERTIFICATE_INVALID: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_SOCKS_CONNECTION_FAILED: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case net::ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsProtobufMimeType(const net::URLFetcher* fetcher) { 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return fetcher->GetResponseHeaders()->HasHeaderValue( 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "content-type", "application/x-protobuffer"); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FailedWithProxy(const net::URLFetcher* fetcher) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((fetcher->GetLoadFlags() & net::LOAD_BYPASS_PROXY) != 0) { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The request didn't use a proxy. 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fetcher->GetStatus().is_success() && 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsProxyError(fetcher->GetStatus())) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Proxy failed while contacting dmserver."; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fetcher->GetStatus().is_success() && 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->GetResponseCode() == kSuccess && 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->WasFetchedViaProxy() && 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !IsProtobufMimeType(fetcher)) { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The proxy server can be misconfigured but pointing to an existing 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // server that replies to requests. Try to recover if a successful 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // request that went through a proxy returns an unexpected mime type. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Got bad mime-type in response from dmserver that was " 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "fetched via a proxy."; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* UserAffiliationToString(UserAffiliation affiliation) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (affiliation) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USER_AFFILIATION_MANAGED: 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueUserAffiliationManaged; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case USER_AFFILIATION_NONE: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueUserAffiliationNone; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Invalid user affiliation " << affiliation; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueUserAffiliationNone; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* JobTypeToRequestType(DeviceManagementRequestJob::JobType type) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_AUTO_ENROLLMENT: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestAutoEnrollment; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_REGISTRATION: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestRegister; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_POLICY_FETCH: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestPolicy; 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DeviceManagementRequestJob::TYPE_API_AUTH_CODE_FETCH: 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return dm_protocol::kValueRequestApiAuthorization; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_UNREGISTRATION: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dm_protocol::kValueRequestUnregister; 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DeviceManagementRequestJob::TYPE_UPLOAD_CERTIFICATE: 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return dm_protocol::kValueRequestUploadCertificate; 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL: 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return dm_protocol::kValueRequestDeviceStateRetrieval; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Invalid job type " << type; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ""; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Request job implementation used with DeviceManagementService. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeviceManagementRequestJobImpl : public DeviceManagementRequestJob { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementRequestJobImpl( 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) JobType type, 140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& agent_parameter, 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& platform_parameter, 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementService* service, 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<net::URLRequestContextGetter>& request_context); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DeviceManagementRequestJobImpl(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handles the URL request response. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleResponse(const net::URLRequestStatus& status, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets the URL to contact. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL GetURL(const std::string& server_url); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Configures the fetcher, setting up payload and headers. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ConfigureRequest(net::URLFetcher* fetcher); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns true if this job should be retried. |fetcher| has just completed, 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and can be inspected to determine if the request failed and should be 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // retried. 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool ShouldRetry(const net::URLFetcher* fetcher); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Invoked right before retrying this job. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void PrepareRetry(); 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeviceManagementRequestJob: 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Invokes the callback with the given error code. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReportError(DeviceManagementStatus code); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pointer to the service this job is associated with. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceManagementService* service_; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Whether the BYPASS_PROXY flag should be set by ConfigureRequest(). 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool bypass_proxy_; 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Number of times that this job has been retried due to ERR_NETWORK_CHANGED. 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int retries_count_; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The request context to use for this job. 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<net::URLRequestContextGetter> request_context_; 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DeviceManagementRequestJobImpl); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJobImpl::DeviceManagementRequestJobImpl( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JobType type, 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& agent_parameter, 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& platform_parameter, 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementService* service, 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<net::URLRequestContextGetter>& request_context) 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : DeviceManagementRequestJob(type, agent_parameter, platform_parameter), 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) service_(service), 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bypass_proxy_(false), 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) retries_count_(0), 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci request_context_(request_context) { 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJobImpl::~DeviceManagementRequestJobImpl() { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->RemoveJob(this); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::Run() { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) service_->AddJob(this); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::HandleResponse( 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLRequestStatus& status, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int response_code, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::ResponseCookies& cookies, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& data) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status.status() != net::URLRequestStatus::SUCCESS) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "DMServer request failed, status: " << status.status() 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", error: " << status.error(); 218b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) em::DeviceManagementResponse dummy_response; 219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) callback_.Run(DM_STATUS_REQUEST_FAILED, status.error(), dummy_response); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_code != kSuccess) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "DMServer sent an error response: " << response_code; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (response_code) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kSuccess: { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) em::DeviceManagementResponse response; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!response.ParseFromString(data)) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_RESPONSE_DECODING_ERROR); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 233b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) callback_.Run(DM_STATUS_SUCCESS, net::OK, response); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidArgument: 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_REQUEST_INVALID); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidAuthCookieOrDMToken: 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kMissingLicenses: 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_MISSING_LICENSES); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kDeviceManagementNotAllowed: 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kPendingApproval: 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_ACTIVATION_PENDING); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidURL: 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInternalServerError: 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kServiceUnavailable: 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kDeviceNotFound: 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_DEVICE_NOT_FOUND); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kPolicyNotFound: 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_POLICY_NOT_FOUND); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kInvalidSerialNumber: 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case kDomainMismatch: 266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ReportError(DM_STATUS_SERVICE_DOMAIN_MISMATCH); 267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case kDeprovisioned: 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_DEPROVISIONED); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kDeviceIdConflict: 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_SERVICE_DEVICE_ID_CONFLICT); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle all unknown 5xx HTTP error codes as temporary and any other 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unknown error as one that needs more time to recover. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (response_code >= 500 && response_code <= 599) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_TEMPORARY_UNAVAILABLE); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReportError(DM_STATUS_HTTP_STATUS_ERROR); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL DeviceManagementRequestJobImpl::GetURL( 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& server_url) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string result(server_url); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += '?'; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ParameterMap::const_iterator entry(query_params_.begin()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry != query_params_.end(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++entry) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry != query_params_.begin()) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += '&'; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += net::EscapeQueryParamValue(entry->first, true); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += '='; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += net::EscapeQueryParamValue(entry->second, true); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GURL(result); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::ConfigureRequest( 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher* fetcher) { 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(dcheng): It might make sense to make this take a const 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // scoped_refptr<T>& too eventually. 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fetcher->SetRequestContext(request_context_.get()); 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::LOAD_DO_NOT_SAVE_COOKIES | 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::LOAD_DISABLE_CACHE | 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (bypass_proxy_ ? net::LOAD_BYPASS_PROXY : 0)); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string payload; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(request_.SerializeToString(&payload)); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->SetUploadData(kPostContentType, payload); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string extra_headers; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gaia_token_.empty()) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_headers += kServiceTokenAuthHeader + gaia_token_ + "\n"; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dm_token_.empty()) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_headers += kDMTokenAuthHeader + dm_token_ + "\n"; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->SetExtraRequestHeaders(extra_headers); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DeviceManagementRequestJobImpl::ShouldRetry( 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const net::URLFetcher* fetcher) { 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (FailedWithProxy(fetcher) && !bypass_proxy_) { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Retry the job if it failed due to a broken proxy, by bypassing the 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // proxy on the next try. 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bypass_proxy_ = true; 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Early device policy fetches on ChromeOS and Auto-Enrollment checks are 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // often interrupted during ChromeOS startup when network change notifications 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // are sent. Allowing the fetcher to retry once after that is enough to 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // recover; allow it to retry up to 3 times just in case. 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fetcher->GetStatus().error() == net::ERR_NETWORK_CHANGED && 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retries_count_ < kMaxNetworkChangedRetries) { 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++retries_count_; 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The request didn't fail, or the limit of retry attempts has been reached; 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // forward the result to the job owner. 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceManagementRequestJobImpl::PrepareRetry() { 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!retry_callback_.is_null()) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_callback_.Run(this); 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJobImpl::ReportError(DeviceManagementStatus code) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) em::DeviceManagementResponse dummy_response; 352b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) callback_.Run(code, net::OK, dummy_response); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJob::~DeviceManagementRequestJob() {} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetGaiaToken(const std::string& gaia_token) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gaia_token_ = gaia_token; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetOAuthToken(const std::string& oauth_token) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamOAuthToken, oauth_token); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetUserAffiliation( 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserAffiliation user_affiliation) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamUserAffiliation, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserAffiliationToString(user_affiliation)); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetDMToken(const std::string& dm_token) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dm_token_ = dm_token; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::SetClientID(const std::string& client_id) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamDeviceID, client_id); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)em::DeviceManagementRequest* DeviceManagementRequestJob::GetRequest() { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &request_; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DeviceManagementRequestJob::DeviceManagementRequestJob( 3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) JobType type, 3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& agent_parameter, 3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& platform_parameter) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamRequest, JobTypeToRequestType(type)); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamDeviceType, dm_protocol::kValueDeviceType); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddParameter(dm_protocol::kParamAppType, dm_protocol::kValueAppType); 3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddParameter(dm_protocol::kParamAgent, agent_parameter); 3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AddParameter(dm_protocol::kParamPlatform, platform_parameter); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceManagementRequestJob::SetRetryCallback( 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const RetryCallback& retry_callback) { 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_callback_ = retry_callback; 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::Start(const Callback& callback) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_ = callback; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Run(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementRequestJob::AddParameter(const std::string& name, 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& value) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query_params_.push_back(std::make_pair(name, value)); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A random value that other fetchers won't likely use. 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int DeviceManagementService::kURLFetcherID = 0xde71ce1d; 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementService::~DeviceManagementService() { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All running jobs should have been cancelled by now. 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pending_jobs_.empty()); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(queued_jobs_.empty()); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementRequestJob* DeviceManagementService::CreateJob( 419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DeviceManagementRequestJob::JobType type, 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const scoped_refptr<net::URLRequestContextGetter>& request_context) { 4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return new DeviceManagementRequestJobImpl( 4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) type, 4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) configuration_->GetAgentParameter(), 4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) configuration_->GetPlatformParameter(), 425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this, 426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) request_context); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::ScheduleInitialization(int64 delay_milliseconds) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&DeviceManagementService::Initialize, 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(delay_milliseconds)); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::Initialize() { 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = true; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!queued_jobs_.empty()) { 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartJob(queued_jobs_.front()); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.pop_front(); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::Shutdown() { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (JobFetcherMap::iterator job(pending_jobs_.begin()); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job != pending_jobs_.end(); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++job) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete job->first; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.push_back(job->second); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_.clear(); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DeviceManagementService::DeviceManagementService( 461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<Configuration> configuration) 4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : configuration_(configuration.Pass()), 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_(false), 464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(configuration_); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeviceManagementService::StartJob(DeviceManagementRequestJobImpl* job) { 469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string server_url = GetServerUrl(); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLFetcher* fetcher = net::URLFetcher::Create( 4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kURLFetcherID, job->GetURL(server_url), net::URLFetcher::POST, this); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->ConfigureRequest(fetcher); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_[fetcher] = job; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetcher->Start(); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string DeviceManagementService::GetServerUrl() { 478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return configuration_->GetServerUrl(); 479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::OnURLFetchComplete( 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::URLFetcher* source) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JobFetcherMap::iterator entry(pending_jobs_.find(source)); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry == pending_jobs_.end()) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Callback from foreign URL fetcher"; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceManagementRequestJobImpl* job = entry->second; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_.erase(entry); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (job->ShouldRetry(source)) { 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) VLOG(1) << "Retrying dmserver request."; 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) job->PrepareRetry(); 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartJob(job); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetResponseAsString(&data); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job->HandleResponse(source->GetStatus(), source->GetResponseCode(), 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetCookies(), data); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete source; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::AddJob(DeviceManagementRequestJobImpl* job) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartJob(job); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.push_back(job); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeviceManagementService::RemoveJob(DeviceManagementRequestJobImpl* job) { 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (JobFetcherMap::iterator entry(pending_jobs_.begin()); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry != pending_jobs_.end(); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++entry) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->second == job) { 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete entry->first; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_jobs_.erase(entry); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const JobQueue::iterator elem = 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::find(queued_jobs_.begin(), queued_jobs_.end(), job); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (elem != queued_jobs_.end()) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queued_jobs_.erase(elem); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 530