1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_CHROMEOS_POLICY_AUTO_ENROLLMENT_CLIENT_H_
6#define CHROME_BROWSER_CHROMEOS_POLICY_AUTO_ENROLLMENT_CLIENT_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "base/callback.h"
12#include "base/compiler_specific.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/time/time.h"
15#include "components/policy/core/common/cloud/cloud_policy_constants.h"
16#include "net/base/network_change_notifier.h"
17#include "third_party/protobuf/src/google/protobuf/repeated_field.h"
18
19class PrefRegistrySimple;
20class PrefService;
21
22namespace enterprise_management {
23class DeviceManagementResponse;
24}
25
26namespace net {
27class URLRequestContextGetter;
28}
29
30namespace policy {
31
32class DeviceManagementRequestJob;
33class DeviceManagementService;
34
35// Indicates the current state of the auto-enrollment check.
36enum AutoEnrollmentState {
37  // Not yet started.
38  AUTO_ENROLLMENT_STATE_IDLE,
39  // Working, another event will be fired eventually.
40  AUTO_ENROLLMENT_STATE_PENDING,
41  // Failed to connect to DMServer.
42  AUTO_ENROLLMENT_STATE_CONNECTION_ERROR,
43  // Connection successful, but the server failed to generate a valid reply.
44  AUTO_ENROLLMENT_STATE_SERVER_ERROR,
45  // Check completed successfully, enrollment should be triggered.
46  AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT,
47  // Check completed successfully, enrollment not applicable.
48  AUTO_ENROLLMENT_STATE_NO_ENROLLMENT,
49};
50
51// Interacts with the device management service and determines whether this
52// machine should automatically enter the Enterprise Enrollment screen during
53// OOBE.
54class AutoEnrollmentClient
55    : public net::NetworkChangeNotifier::NetworkChangeObserver {
56 public:
57  // The modulus value is sent in an int64 field in the protobuf, whose maximum
58  // value is 2^63-1. So 2^64 and 2^63 can't be represented as moduli and the
59  // max is 2^62 (when the moduli are restricted to powers-of-2).
60  static const int kMaximumPower = 62;
61
62  // Used for signaling progress to a consumer.
63  typedef base::Callback<void(AutoEnrollmentState)> ProgressCallback;
64
65  // |progress_callback| will be invoked whenever some significant event happens
66  // as part of the protocol, after Start() is invoked.
67  // The result of the protocol will be cached in |local_state|.
68  // |power_initial| and |power_limit| are exponents of power-of-2 values which
69  // will be the initial modulus and the maximum modulus used by this client.
70  AutoEnrollmentClient(
71      const ProgressCallback& progress_callback,
72      DeviceManagementService* device_management_service,
73      PrefService* local_state,
74      scoped_refptr<net::URLRequestContextGetter> system_request_context,
75      const std::string& server_backed_state_key,
76      bool retrieve_device_state,
77      int power_initial,
78      int power_limit);
79  virtual ~AutoEnrollmentClient();
80
81  // Registers preferences in local state.
82  static void RegisterPrefs(PrefRegistrySimple* registry);
83
84  // Cancels auto-enrollment.
85  // This function does not interrupt a running auto-enrollment check. It only
86  // stores a pref in |local_state| that prevents the client from entering
87  // auto-enrollment mode for the future.
88  static void CancelAutoEnrollment();
89
90  // Starts the auto-enrollment check protocol with the device management
91  // service. Subsequent calls drop any previous requests. Notice that this
92  // call can invoke the |progress_callback_| if errors occur.
93  void Start();
94
95  // Triggers a retry of the currently pending step. This is intended to be
96  // called by consumers when they become aware of environment changes (such as
97  // captive portal setup being complete).
98  void Retry();
99
100  // Cancels any pending requests. |progress_callback_| will not be invoked.
101  // |this| will delete itself.
102  void CancelAndDeleteSoon();
103
104  // Returns the device_id randomly generated for the auto-enrollment requests.
105  // It can be reused for subsequent requests to the device management service.
106  std::string device_id() const { return device_id_; }
107
108  // Current state.
109  AutoEnrollmentState state() const { return state_; }
110
111  // Implementation of net::NetworkChangeNotifier::NetworkChangeObserver:
112  virtual void OnNetworkChanged(
113      net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
114
115 private:
116  typedef bool (AutoEnrollmentClient::*RequestCompletionHandler)(
117      DeviceManagementStatus,
118      int,
119      const enterprise_management::DeviceManagementResponse&);
120
121  // Tries to load the result of a previous execution of the protocol from
122  // local state. Returns true if that decision has been made and is valid.
123  bool GetCachedDecision();
124
125  // Kicks protocol processing, restarting the current step if applicable.
126  // Returns true if progress has been made, false if the protocol is done.
127  bool RetryStep();
128
129  // Cleans up and invokes |progress_callback_|.
130  void ReportProgress(AutoEnrollmentState state);
131
132  // Calls RetryStep() to make progress or determine that all is done. In the
133  // latter case, calls ReportProgress().
134  void NextStep();
135
136  // Sends an auto-enrollment check request to the device management service.
137  bool SendBucketDownloadRequest();
138
139  // Sends a device state download request to the device management service.
140  bool SendDeviceStateRequest();
141
142  // Runs the response handler for device management requests and calls
143  // NextStep().
144  void HandleRequestCompletion(
145      RequestCompletionHandler handler,
146      DeviceManagementStatus status,
147      int net_error,
148      const enterprise_management::DeviceManagementResponse& response);
149
150  // Parses the server response to a bucket download request.
151  bool OnBucketDownloadRequestCompletion(
152      DeviceManagementStatus status,
153      int net_error,
154      const enterprise_management::DeviceManagementResponse& response);
155
156  // Parses the server response to a device state request.
157  bool OnDeviceStateRequestCompletion(
158      DeviceManagementStatus status,
159      int net_error,
160      const enterprise_management::DeviceManagementResponse& response);
161
162  // Returns true if |server_backed_state_key_hash_| is contained in |hashes|.
163  bool IsIdHashInProtobuf(
164      const google::protobuf::RepeatedPtrField<std::string>& hashes);
165
166  // Updates UMA histograms for bucket download timings.
167  void UpdateBucketDownloadTimingHistograms();
168
169  // Callback to invoke when the protocol generates a relevant event. This can
170  // be either successful completion or an error that requires external action.
171  ProgressCallback progress_callback_;
172
173  // Current state.
174  AutoEnrollmentState state_;
175
176  // Whether the hash bucket check succeeded, indicating that the server knows
177  // this device and might have keep state for it.
178  bool has_server_state_;
179
180  // Whether the download of server-kept device state completed successfully.
181  bool device_state_available_;
182
183  // Randomly generated device id for the auto-enrollment requests.
184  std::string device_id_;
185
186  // Stable state key and its SHA-256 digest.
187  std::string server_backed_state_key_;
188  std::string server_backed_state_key_hash_;
189
190  // Whether device state should be retrieved from the server.
191  bool retrieve_device_state_;
192
193  // Power-of-2 modulus to try next.
194  int current_power_;
195
196  // Power of the maximum power-of-2 modulus that this client will accept from
197  // a retry response from the server.
198  int power_limit_;
199
200  // Number of requests for a different modulus received from the server.
201  // Used to determine if the server keeps asking for different moduli.
202  int modulus_updates_received_;
203
204  // Used to communicate with the device management service.
205  DeviceManagementService* device_management_service_;
206  scoped_ptr<DeviceManagementRequestJob> request_job_;
207
208  // PrefService where the protocol's results are cached.
209  PrefService* local_state_;
210
211  // The request context to use to perform the auto enrollment request.
212  scoped_refptr<net::URLRequestContextGetter> request_context_;
213
214  // Times used to determine the duration of the protocol, and the extra time
215  // needed to complete after the signin was complete.
216  // If |time_start_| is not null, the protocol is still running.
217  // If |time_extra_start_| is not null, the protocol is still running but our
218  // owner has relinquished ownership.
219  base::Time time_start_;
220  base::Time time_extra_start_;
221
222  DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClient);
223};
224
225}  // namespace policy
226
227#endif  // CHROME_BROWSER_CHROMEOS_POLICY_AUTO_ENROLLMENT_CLIENT_H_
228