text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_CLIENT_H_
  #define CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_CLIENT_H_
  
  #include <map>
  #include <set>
  #include <string>
  
  #include "base/basictypes.h"
  #include "base/callback.h"
  #include "base/memory/scoped_ptr.h"
  #include "base/observer_list.h"
  #include "base/time.h"
  #include "chrome/browser/policy/cloud/cloud_policy_constants.h"
  #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h"
  
  namespace policy {
  
  class DeviceManagementRequestJob;
  class DeviceManagementService;
  
  // Implements the core logic required to talk to the device management service.
  // Also keeps track of the current state of the association with the service,
  // such as whether there is a valid registration (DMToken is present in that
  // case) and whether and what errors occurred in the latest request.
  //
  // Note that CloudPolicyClient doesn't do any validation of policy responses
  // such as signature and time stamp checks. These happen once the policy gets
  // installed in the cloud policy cache.
  class CloudPolicyClient {
   public:
    // Maps a PolicyNamespaceKey to its corresponding PolicyFetchResponse.
    typedef std::map<PolicyNamespaceKey,
                     enterprise_management::PolicyFetchResponse*> ResponseMap;
  
    // A callback which receives boolean status of an operation.  If the operation
    // succeeded, |status| is true.
    typedef base::Callback<void(bool status)> StatusCallback;
  
    // Observer interface for state and policy changes.
    class Observer {
     public:
      virtual ~Observer();
  
      // Called when a policy fetch completes successfully. If a policy fetch
      // triggers an error, OnClientError() will fire.
      virtual void OnPolicyFetched(CloudPolicyClient* client) = 0;
  
      // Called upon registration state changes. This callback is invoked for
      // successful completion of registration and unregistration requests.
      virtual void OnRegistrationStateChanged(CloudPolicyClient* client) = 0;
  
      // Called when a request for device robot OAuth2 authorization tokens
      // returns successfully. Only occurs during enrollment. Optional
      // (default implementation is a noop).
      virtual void OnRobotAuthCodesFetched(CloudPolicyClient* client);
  
      // Indicates there's been an error in a previously-issued request.
      virtual void OnClientError(CloudPolicyClient* client) = 0;
    };
  
    // Delegate interface for supplying status information to upload to the server
    // as part of the policy fetch request.
    class StatusProvider {
     public:
      virtual ~StatusProvider();
  
      // Retrieves status information to send with the next policy fetch.
      // Implementations must return true if status information was filled in.
      virtual bool GetDeviceStatus(
          enterprise_management::DeviceStatusReportRequest* status) = 0;
      virtual bool GetSessionStatus(
          enterprise_management::SessionStatusReportRequest* status) = 0;
  
      // Called after the status information has successfully been submitted to
      // the server.
      virtual void OnSubmittedSuccessfully() = 0;
    };
  
    // |provider| and |service| are weak pointers and it's the caller's
    // responsibility to keep them valid for the lifetime of CloudPolicyClient.
    CloudPolicyClient(const std::string& machine_id,
                      const std::string& machine_model,
                      UserAffiliation user_affiliation,
                      StatusProvider* provider,
                      DeviceManagementService* service);
    virtual ~CloudPolicyClient();
  
    // Sets the DMToken, thereby establishing a registration with the server. A
    // policy fetch is not automatically issued but can be requested by calling
    // FetchPolicy().
    virtual void SetupRegistration(const std::string& dm_token,
                                   const std::string& client_id);
  
    // Attempts to register with the device management service. Results in a
    // registration change or error notification.
    virtual void Register(
        enterprise_management::DeviceRegisterRequest::Type registration_type,
        const std::string& auth_token,
        const std::string& client_id,
        bool is_auto_enrollment);
  
    // Requests a policy fetch. The client being registered is a prerequisite to
    // this operation and this call will CHECK if the client is not in registered
    // state. FetchPolicy() triggers a policy fetch from the cloud. A policy
    // change notification is reported to the observers and the new policy blob
    // can be retrieved once the policy fetch operation completes. In case of
    // multiple requests to fetch policy, new requests will cancel any pending
    // requests and the latest request will eventually trigger notifications.
    virtual void FetchPolicy();
  
    // Requests OAuth2 auth codes for the device robot account. The client being
    // registered is a prerequisite to this operation and this call will CHECK if
    // the client is not in registered state.
    virtual void FetchRobotAuthCodes(const std::string& auth_token);
  
    // Sends an unregistration request to the server.
    virtual void Unregister();
  
    // Upload a device certificate to the server.  Like FetchPolicy, this method
    // requires that the client is in a registered state.  |certificate_data| must
    // hold the X.509 certificate data to be sent to the server.  The |callback|
    // will be called when the operation completes.
    virtual void UploadCertificate(const std::string& certificate_data,
                                   const StatusCallback& callback);
  
    // Adds an observer to be called back upon policy and state changes.
    void AddObserver(Observer* observer);
  
    // Removes the specified observer.
    void RemoveObserver(Observer* observer);
  
    void set_submit_machine_id(bool submit_machine_id) {
      submit_machine_id_ = submit_machine_id;
    }
  
    void set_last_policy_timestamp(const base::Time& timestamp) {
      last_policy_timestamp_ = timestamp;
    }
  
    void set_public_key_version(int public_key_version) {
      public_key_version_ = public_key_version;
      public_key_version_valid_ = true;
    }
  
    void clear_public_key_version() {
      public_key_version_valid_ = false;
    }
  
    // FetchPolicy() calls will request this policy namespace.
    void AddNamespaceToFetch(const PolicyNamespaceKey& policy_ns_key);
  
    // FetchPolicy() calls won't request the given policy namespace anymore.
    void RemoveNamespaceToFetch(const PolicyNamespaceKey& policy_ns_key);
  
    // Whether the client is registered with the device management service.
    bool is_registered() const { return !dm_token_.empty(); }
  
    const std::string& dm_token() const { return dm_token_; }
  
    // The device mode as received in the registration request.
    DeviceMode device_mode() const { return device_mode_; }
  
    // The policy responses as obtained by the last request to the cloud. These
    // policies haven't gone through verification, so their contents cannot be
    // trusted. Use CloudPolicyStore::policy() and CloudPolicyStore::policy_map()
    // instead for making policy decisions.
    const ResponseMap& responses() const {
      return responses_;
    }
  
    // Returns the policy response for |policy_ns_key|, if found in |responses()|;
    // otherwise returns NULL.
    const enterprise_management::PolicyFetchResponse* GetPolicyFor(
        const PolicyNamespaceKey& policy_ns_key) const;
  
    DeviceManagementStatus status() const {
      return status_;
    }
  
    const std::string& robot_api_auth_code() const {
      return robot_api_auth_code_;
    }
  
   protected:
    // A set of PolicyNamespaceKeys to fetch.
    typedef std::set<PolicyNamespaceKey> NamespaceSet;
  
    // Callback for retries of registration requests.
    void OnRetryRegister(DeviceManagementRequestJob* job);
  
    // Callback for registration requests.
    void OnRegisterCompleted(
        DeviceManagementStatus status,
        const enterprise_management::DeviceManagementResponse& response);
  
    // Callback for policy fetch requests.
    void OnPolicyFetchCompleted(
        DeviceManagementStatus status,
        const enterprise_management::DeviceManagementResponse& response);
  
    // Callback for robot account api authorization requests.
    void OnFetchRobotAuthCodesCompleted(
        DeviceManagementStatus status,
        const enterprise_management::DeviceManagementResponse& response);
  
    // Callback for unregistration requests.
    void OnUnregisterCompleted(
        DeviceManagementStatus status,
        const enterprise_management::DeviceManagementResponse& response);
  
    // Callback for certificate upload requests.
    void OnCertificateUploadCompleted(
        const StatusCallback& callback,
        DeviceManagementStatus status,
        const enterprise_management::DeviceManagementResponse& response);
  
    // Observer notification helpers.
    void NotifyPolicyFetched();
    void NotifyRegistrationStateChanged();
    void NotifyRobotAuthCodesFetched();
    void NotifyClientError();
  
    // Data necessary for constructing policy requests.
    const std::string machine_id_;
    const std::string machine_model_;
    const UserAffiliation user_affiliation_;
    NamespaceSet namespaces_to_fetch_;
  
    std::string dm_token_;
    DeviceMode device_mode_;
    std::string client_id_;
    bool submit_machine_id_;
    base::Time last_policy_timestamp_;
    int public_key_version_;
    bool public_key_version_valid_;
    std::string robot_api_auth_code_;
  
    // Used for issuing requests to the cloud.
    DeviceManagementService* service_;
    scoped_ptr<DeviceManagementRequestJob> request_job_;
  
    // Status upload data is produced by |status_provider_|.
    StatusProvider* status_provider_;
  
    // The policy responses returned by the last policy fetch operation.
    ResponseMap responses_;
    DeviceManagementStatus status_;
  
    ObserverList<Observer, true> observers_;
  
   private:
    DISALLOW_COPY_AND_ASSIGN(CloudPolicyClient);
  };
  
  }  // namespace policy
  
  #endif  // CHROME_BROWSER_POLICY_CLOUD_CLOUD_POLICY_CLIENT_H_
  