// Copyright (c) 2012 The Chromium OS 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 LOGIN_MANAGER_POLICY_SERVICE_H_
#define LOGIN_MANAGER_POLICY_SERVICE_H_

#include <string>
#include <vector>

#include <base/basictypes.h>
#include <base/files/file_path.h>
#include <base/memory/ref_counted.h>
#include <base/memory/scoped_ptr.h>
#include <base/memory/weak_ptr.h>
#include <chromeos/dbus/service_constants.h>

namespace enterprise_management {
class PolicyFetchResponse;
}

namespace base {
class MessageLoopProxy;
class WaitableEvent;
}  // namespace base

namespace login_manager {

class PolicyKey;
class PolicyStore;

// Manages policy storage and retrieval from an underlying PolicyStore, thereby
// enforcing policy signatures against a given policy key. Also handles key
// rotations in case a new policy payload comes with an updated policy key.
class PolicyService {
 public:
  // Flags determining what do to with new keys in Store().
  enum KeyInstallFlags {
    KEY_ROTATE = 1,       // Existing key may be rotated.
    KEY_INSTALL_NEW = 2,  // Allow to install a key if none is present.
    KEY_CLOBBER = 4,      // OK to replace the existing key without any checks.
  };

  // Wraps a policy service error with code and message.
  class Error {
   public:
    Error();
    Error(const std::string& code, const std::string& message);

    // Sets new error code and message.
    void Set(const std::string& code, const std::string& message);

    const std::string& code() const { return code_; }
    const std::string& message() const { return message_; }

   private:
    std::string code_;
    std::string message_;

    DISALLOW_COPY_AND_ASSIGN(Error);
  };

  // Callback interface for asynchronous completion of a Store operation.
  class Completion {
   public:
    virtual ~Completion();
    virtual void ReportSuccess() = 0;
    virtual void ReportFailure(const Error& error) = 0;
  };

  // Delegate for notifications about key and policy getting persisted.
  class Delegate {
   public:
    virtual ~Delegate();
    virtual void OnPolicyPersisted(bool success) = 0;
    virtual void OnKeyPersisted(bool success) = 0;
  };

  PolicyService(scoped_ptr<PolicyStore> policy_store,
                PolicyKey* policy_key,
                const scoped_refptr<base::MessageLoopProxy>& main_loop);
  virtual ~PolicyService();

  // Stores a new policy. Verifies the passed-in policy blob against the policy
  // key if it exists, takes care of key rotation if required and persists
  // everything to disk. The |flags| parameter determines what to do with a
  // new key present in the policy. See KeyInstallFlags for possible values.
  //
  // Returns false on immediate errors. Otherwise, returns true and reports the
  // status of the operation through |completion|.
  virtual bool Store(const uint8* policy_blob,
                     uint32 len,
                     Completion* completion,
                     int flags);

  // Retrieves the current policy blob. Returns true if successful, false
  // otherwise.
  virtual bool Retrieve(std::vector<uint8>* policy_blob);

  // Policy is persisted to disk on the IO loop. The current thread waits for
  // completion and reports back the status afterwards.
  virtual bool PersistPolicySync();

  // Accessors for the delegate. PolicyService doesn't own the delegate, thus
  // client code must make sure that the delegate pointer stays valid.
  void set_delegate(Delegate* delegate) { delegate_ = delegate; }
  Delegate* delegate() { return delegate_; }

 protected:
  friend class PolicyServiceTest;

  PolicyStore* store() { return policy_store_.get(); }
  PolicyKey* key() { return policy_key_; }
  const scoped_refptr<base::MessageLoopProxy>& main_loop() {
    return main_loop_;
  }

  // Schedules the key to be persisted.
  void PersistKey();

  // Schedules the policy to be persisted.
  void PersistPolicy();

  // Triggers persisting the policy to disk and reports the result to the given
  // completion context.
  void PersistPolicyWithCompletion(Completion* completion);

  // Store a policy blob. This does the heavy lifting for Store(), making the
  // signature checks, taking care of key changes and persisting policy and key
  // data to disk.
  bool StorePolicy(const enterprise_management::PolicyFetchResponse& policy,
                   Completion* completion,
                   int flags);

  // Completes a key storage operation on the UI thread, reporting the result to
  // the delegate.
  virtual void OnKeyPersisted(bool status);

 private:
  // Takes care of persisting the policy key to disk.
  void PersistKeyOnLoop();

  // Persists policy to disk on the main thread. If |completion| is non-NULL
  // it will be signaled when done.
  void PersistPolicyOnLoop(Completion* completion);

  // Finishes persisting policy with |status|, notifying the delegate and
  // reporting the status through |completion|.
  void OnPolicyPersisted(Completion* completion, bool status);

 private:
  scoped_ptr<PolicyStore> policy_store_;
  PolicyKey* policy_key_;
  scoped_refptr<base::MessageLoopProxy> main_loop_;
  Delegate* delegate_;

  base::WeakPtrFactory<PolicyService> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(PolicyService);
};

}  // namespace login_manager

#endif  // LOGIN_MANAGER_POLICY_SERVICE_H_
