File: device_management_service.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (428 lines) | stat: -rw-r--r-- 15,977 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_POLICY_CORE_COMMON_CLOUD_DEVICE_MANAGEMENT_SERVICE_H_
#define COMPONENTS_POLICY_CORE_COMMON_CLOUD_DEVICE_MANAGEMENT_SERVICE_H_

#include <stdint.h>

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/dm_auth.h"
#include "components/policy/policy_export.h"
#include "services/network/public/cpp/simple_url_loader.h"

namespace base {
class SequencedTaskRunner;
}

namespace network {
class SharedURLLoaderFactory;
}

namespace policy {

// Used in the Enterprise.DMServerRequestSuccess histogram, shows how many
// retries we had to do to execute the DeviceManagementRequestJob.
enum class DMServerRequestSuccess {
  // No retries happened, the request succeeded for the first try.
  kRequestNoRetry = 0,

  // 1..kMaxRetries: number of retries. kMaxRetries is the maximum number of
  // retries allowed, defined in the .cc file.

  // The request failed (too many retries or non-retryable error).
  kRequestFailed = 10,
  // The server responded with an error.
  kRequestError = 11,

  kMaxValue = kRequestError,
};

// The device management service is responsible for everything related to
// communication with the device management server. It creates the backends
// objects that the device management policy provider and friends use to issue
// requests.
class POLICY_EXPORT DeviceManagementService {
 public:
  // HTTP Error Codes of the DM Server with their concrete meanings in the
  // context of the DM Server communication.
  static constexpr int kSuccess = 200;
  static constexpr int kInvalidArgument = 400;
  static constexpr int kInvalidAuthCookieOrDMToken = 401;
  static constexpr int kMissingLicenses = 402;
  static constexpr int kDeviceManagementNotAllowed = 403;
  static constexpr int kInvalidURL =
      404;  // This error is not coming from the GFE.
  static constexpr int kInvalidSerialNumber = 405;
  static constexpr int kDomainMismatch = 406;
  static constexpr int kDeviceIdConflict = 409;
  static constexpr int kDeviceNotFound = 410;
  static constexpr int kPendingApproval = 412;
  static constexpr int kRequestTooLarge = 413;
  static constexpr int kConsumerAccountWithPackagedLicense = 417;
  static constexpr int kInvalidPackagedDeviceForKiosk = 418;
  static constexpr int kOrgUnitEnrollmentLimitExceeded = 419;
  static constexpr int kTooManyRequests = 429;
  static constexpr int kInternalServerError = 500;
  static constexpr int kServiceUnavailable = 503;
  static constexpr int kPolicyNotFound = 902;
  static constexpr int kDeprovisioned = 903;
  static constexpr int kArcDisabled = 904;
  static constexpr int kInvalidDomainlessCustomer = 905;
  static constexpr int kTosHasNotBeenAccepted = 906;
  static constexpr int kIllegalAccountForPackagedEDULicense = 907;

  // Number of times to retry on ERR_NETWORK_CHANGED errors.
  static const int kMaxRetries = 3;

  // Obtains the parameters used to contact the server.
  // This allows creating the DeviceManagementService early and getting these
  // parameters later. Passing the parameters directly in the ctor isn't
  // possible because some aren't ready during startup. http://crbug.com/302798
  class POLICY_EXPORT Configuration {
   public:
    virtual ~Configuration() = default;

    // Server at which to contact the service (DMServer).
    virtual std::string GetDMServerUrl() const = 0;

    // Agent reported in the "agent" query parameter.
    virtual std::string GetAgentParameter() const = 0;

    // The platform reported in the "platform" query parameter.
    virtual std::string GetPlatformParameter() const = 0;

    // Server at which to contact the real time reporting service.
    virtual std::string GetRealtimeReportingServerUrl() const = 0;

    // Server endpoint for encrypted events.
    virtual std::string GetEncryptedReportingServerUrl() const = 0;
  };

  // A DeviceManagementService job manages network requests to the device
  // management and real-time reporting services. Jobs are created by calling
  // CreateJob() and specifying a JobConfiguration. Jobs can be canceled by
  // deleting the returned Job object.
  //
  // If network requests fail, the Job will retry them.
  //
  // JobConfiguration is the interface used by callers to specify parameters
  // of network requests.  This object is not immutable and may be changed after
  // a call to OnBeforeRetry().  DeviceManagementService calls the GetXXX
  // methods again to create a new network request for each retry.

  class JobConfiguration;

  class POLICY_EXPORT Job {
   public:
    enum RetryMethod {
      // No retry required for this request.
      NO_RETRY,
      // Should retry immediately (no delay).
      RETRY_IMMEDIATELY,
      // Should retry after a delay.
      RETRY_WITH_DELAY
    };

    virtual ~Job() = default;
  };

  class JobImpl;

  // JobForTesting is a test API to access jobs.
  // See also |FakeDeviceManagementService|.
  class POLICY_EXPORT JobForTesting {
   public:
    JobForTesting();
    explicit JobForTesting(JobImpl* job_impl);
    JobForTesting(const JobForTesting&);
    JobForTesting(JobForTesting&&) noexcept;
    JobForTesting& operator=(const JobForTesting&);
    JobForTesting& operator=(JobForTesting&&) noexcept;
    ~JobForTesting();

    bool IsActive() const;
    void Deactivate();

    // TODO(rbock) make return type const.
    JobConfiguration* GetConfigurationForTesting() const;

    Job::RetryMethod SetResponseForTesting(
        // TODO(rbock) change type to net::Error
        int net_error,
        int response_code,
        const std::string& response_body,
        const std::string& mime_type,
        bool was_fetched_via_proxy);

   private:
    base::WeakPtr<JobImpl> job_impl_;
  };

  class POLICY_EXPORT JobConfiguration {
   public:
    // Describes the job type.  (Integer values are stated explicitly to
    // facilitate reading of logs.)
    // TYPE_INVALID is used only in tests so that they can EXPECT the correct
    // job type has been used.  Otherwise, tests would need to initially set
    // the type to something like TYPE_AUTO_ENROLLMENT, and then it would not
    // be possible to EXPECT the job type in auto enrollment tests.
    enum JobType {
      TYPE_INVALID = -1,
      TYPE_AUTO_ENROLLMENT = 0,
      TYPE_REGISTRATION = 1,
      TYPE_API_AUTH_CODE_FETCH = 2,
      TYPE_POLICY_FETCH = 3,
      TYPE_UNREGISTRATION = 4,
      TYPE_UPLOAD_CERTIFICATE = 5,
      TYPE_DEVICE_STATE_RETRIEVAL = 6,
      TYPE_UPLOAD_STATUS = 7,
      TYPE_REMOTE_COMMANDS = 8,
      TYPE_ATTRIBUTE_UPDATE_PERMISSION = 9,
      TYPE_ATTRIBUTE_UPDATE = 10,
      TYPE_GCM_ID_UPDATE = 11,
      TYPE_ANDROID_MANAGEMENT_CHECK = 12,
      TYPE_CERT_BASED_REGISTRATION = 13,
      TYPE_ACTIVE_DIRECTORY_ENROLL_PLAY_USER = 14,
      TYPE_ACTIVE_DIRECTORY_PLAY_ACTIVITY = 15,
      /* TYPE_REQUEST_LICENSE_TYPES = 16, */
      /*Deprecated, CloudPolicyClient no longer uses it.
        TYPE_UPLOAD_APP_INSTALL_REPORT = 17,*/
      TYPE_BROWSER_REGISTRATION = 18,
      TYPE_CHROME_DESKTOP_REPORT = 19,
      TYPE_INITIAL_ENROLLMENT_STATE_RETRIEVAL = 20,
      TYPE_UPLOAD_POLICY_VALIDATION_REPORT = 21,
      TYPE_UPLOAD_REAL_TIME_REPORT = 22,
      TYPE_REQUEST_SAML_URL = 23,
      TYPE_CHROME_OS_USER_REPORT = 24,
      TYPE_CERT_PROVISIONING_REQUEST = 25,
      TYPE_PSM_HAS_DEVICE_STATE_REQUEST = 26,
      TYPE_UPLOAD_ENCRYPTED_REPORT = 27,
      TYPE_CHECK_USER_ACCOUNT = 28,
      TYPE_UPLOAD_EUICC_INFO = 29,
      TYPE_BROWSER_UPLOAD_PUBLIC_KEY = 30,
      TYPE_CHROME_PROFILE_REPORT = 31,
      TYPE_OIDC_REGISTRATION = 32,
      TYPE_TOKEN_BASED_DEVICE_REGISTRATION = 33,
      TYPE_UPLOAD_FM_REGISTRATION_TOKEN = 34,
      TYPE_POLICY_AGENT_REGISTRATION = 35,
      TYPE_DETERMINE_PROMOTION_ELIGIBILITY = 36,
    };

    // The set of HTTP query parameters of the request.
    using ParameterMap = std::map<std::string, std::string>;

    // Convert the job type into a string.
    static std::string GetJobTypeAsString(JobType type);

    virtual ~JobConfiguration() = default;

    virtual JobType GetType() = 0;

    virtual const DMAuth& GetAuth() const = 0;

    virtual const ParameterMap& GetQueryParams() = 0;

    // Gets the factory to create URL fetchers for requests.
    virtual scoped_refptr<network::SharedURLLoaderFactory>
    GetUrlLoaderFactory() = 0;

    // Gets the payload to send in requests.
    virtual std::string GetPayload() = 0;

    // The content type of the payload.
    virtual std::string GetContentType() = 0;

    // Whether the request will forward user cookies or not.
    virtual bool AreCookiesUsed() = 0;

    // Returns the network annotation to assign to requests.
    virtual net::NetworkTrafficAnnotationTag GetTrafficAnnotationTag() = 0;

    // Returns a properly initialized resource for requests.
    virtual std::unique_ptr<network::ResourceRequest> GetResourceRequest(
        bool bypass_proxy,
        int last_error) = 0;

    // Returns whether UMA histograms should be recorded. If this is false
    // then GetUmaName() is invalid.
    virtual bool ShouldRecordUma() const = 0;
    // Returns the the UMA histogram to record stats about the network request.
    virtual std::string GetUmaName() = 0;

    // Returns the RetryMethod the configuration considers appropriate given the
    // response from the server. The response_code is the http response, and the
    // response_body is the response returned by the server (it may be empty
    // depending on the response_code).
    // Note this method will not be called on a net_error, because the
    // assumption is that this configuration is deciding to retry based on a
    // server response, and there is no server response in that case.
    virtual Job::RetryMethod ShouldRetry(int response_code,
                                         const std::string& response_body) = 0;

    // Prepare this job for a network request retry.
    virtual void OnBeforeRetry(int response_code,
                               const std::string& response_body) = 0;

    // Called when a result is available for the request (possibly after
    // retries). If |net_error| is net::OK, |response_code| will be set to the
    // HTTP response code.
    virtual void OnURLLoadComplete(Job* job,
                                   int net_error,
                                   int response_code,
                                   const std::string& response_body) = 0;

    virtual std::optional<base::TimeDelta> GetTimeoutDuration() = 0;
  };

  explicit DeviceManagementService(
      std::unique_ptr<Configuration> configuration);
  DeviceManagementService(const DeviceManagementService&) = delete;
  DeviceManagementService& operator=(const DeviceManagementService&) = delete;
  virtual ~DeviceManagementService();

  // Creates and queues/starts a new Job.
  virtual std::unique_ptr<Job> CreateJob(
      std::unique_ptr<JobConfiguration> config);

  // Schedules a task to run |Initialize| after |delay_milliseconds| had passed.
  void ScheduleInitialization(int64_t delay_milliseconds);

  // Makes the service stop all requests.
  void Shutdown();

  const Configuration* configuration() const { return configuration_.get(); }

  // Sets the retry delay to a shorter time to prevent browser tests from
  // timing out.
  static void SetRetryDelayForTesting(long retryDelayMs);

 protected:
  // Creates a new Job without starting it.
  // Used by `FakeDeviceManagementService` to avoid queueing/starting of
  // jobs in tests.
  std::pair<std::unique_ptr<Job>, JobForTesting> CreateJobForTesting(
      std::unique_ptr<JobConfiguration> config);

  const scoped_refptr<base::SequencedTaskRunner> GetTaskRunnerForTesting() {
    return task_runner_;
  }

 private:
  using JobQueue = std::vector<base::WeakPtr<JobImpl>>;

  // Starts processing any queued jobs.
  void Initialize();

  // If called before |Initialize| this queues job.
  // Otherwise it starts the job.
  void AddJob(JobImpl* job);

  base::WeakPtr<DeviceManagementService> GetWeakPtr();

  // Moves jobs from the queued state to the pending state and starts them.
  // This should only be called when DeviceManagementService is already
  // initialized.
  void StartQueuedJobs();

  // A Configuration implementation that is used to obtain various parameters
  // used to talk to the device management server.
  std::unique_ptr<Configuration> configuration_;

  // Jobs that are added, but not started yet.
  JobQueue queued_jobs_;

  // If this service is initialized, incoming requests get started instantly.
  // If it is not initialized, incoming requests are queued.
  bool initialized_;

  // TaskRunner used to schedule retry attempts.
  const scoped_refptr<base::SequencedTaskRunner> task_runner_;

  SEQUENCE_CHECKER(sequence_checker_);

  // Used to run delayed tasks (e.g. |Initialize()|).
  base::WeakPtrFactory<DeviceManagementService> weak_ptr_factory_{this};
};

// Base class used to implement job configurations.
class POLICY_EXPORT JobConfigurationBase
    : public DeviceManagementService::JobConfiguration {
 public:
  JobConfigurationBase(const JobConfigurationBase&) = delete;
  JobConfigurationBase& operator=(const JobConfigurationBase&) = delete;

  // DeviceManagementService::JobConfiguration:
  JobType GetType() override;
  const ParameterMap& GetQueryParams() override;
  scoped_refptr<network::SharedURLLoaderFactory> GetUrlLoaderFactory() override;
  net::NetworkTrafficAnnotationTag GetTrafficAnnotationTag() override;
  std::unique_ptr<network::ResourceRequest> GetResourceRequest(
      bool bypass_proxy,
      int last_error) override;
  bool ShouldRecordUma() const override;
  DeviceManagementService::Job::RetryMethod ShouldRetry(
      int response_code,
      const std::string& response_body) override;
  std::optional<base::TimeDelta> GetTimeoutDuration() override;
  std::string GetContentType() override;
  bool AreCookiesUsed() override;

  void set_use_cookies(bool use_cookies) { use_cookies_ = use_cookies; }

 protected:
  JobConfigurationBase(JobType type,
                       DMAuth auth_data,
                       std::optional<std::string> oauth_token,
                       bool use_cookies,
                       scoped_refptr<network::SharedURLLoaderFactory> factory);
  ~JobConfigurationBase() override;

  // Adds the query parameter to the network request's URL.  If the parameter
  // already exists its value is replaced.
  void AddParameter(const std::string& name, const std::string& value);

  const DMAuth& GetAuth() const override;

  // Derived classes should return the base URL for the request.
  virtual GURL GetURL(int last_error) const = 0;

  // Timeout for job request
  std::optional<base::TimeDelta> timeout_;

 private:
  JobType type_;
  scoped_refptr<network::SharedURLLoaderFactory> factory_;

  // Auth data that will be passed as 'Authorization' header. Both |auth_data_|
  // and |oauth_token_| can be specified for one request.
  DMAuth auth_data_;

  // OAuth token that will be passed as a query parameter. Both |auth_data_|
  // and |oauth_token_| can be specified for one request.
  std::optional<std::string> oauth_token_;

  // Will allow using cookies as part of the request when true. Cookies can
  // be used in combination with other auth models, the order of precedence
  // will be determined server-side.
  bool use_cookies_;

  // Query parameters for the network request.
  ParameterMap query_params_;
};

}  // namespace policy

#endif  // COMPONENTS_POLICY_CORE_COMMON_CLOUD_DEVICE_MANAGEMENT_SERVICE_H_