// 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.

#include "chaps/chaps_factory_impl.h"

#include <memory>
#include <string>

#include <base/check.h>
#include <base/logging.h>

#include "chaps/object_impl.h"
#include "chaps/object_policy_cert.h"
#include "chaps/object_policy_common.h"
#include "chaps/object_policy_data.h"
#include "chaps/object_policy_private_key.h"
#include "chaps/object_policy_public_key.h"
#include "chaps/object_policy_secret_key.h"
#include "chaps/object_pool_impl.h"
#include "chaps/object_store_fake.h"
#include "chaps/object_store_impl.h"
#include "chaps/opencryptoki_importer.h"
#include "chaps/session_impl.h"
#include "chaps/slot_policy_default.h"
#include "chaps/slot_policy_shared_slot.h"

using base::FilePath;
using std::string;

namespace chaps {

Session* ChapsFactoryImpl::CreateSession(int slot_id,
                                         ObjectPool* token_object_pool,
                                         TPMUtility* tpm_utility,
                                         HandleGenerator* handle_generator,
                                         bool is_read_only) {
  return new SessionImpl(slot_id, token_object_pool, tpm_utility, this,
                         handle_generator, is_read_only);
}

ObjectPool* ChapsFactoryImpl::CreateObjectPool(
    HandleGenerator* handle_generator,
    SlotPolicy* slot_policy,
    ObjectStore* object_store,
    ObjectImporter* object_importer) {
  std::unique_ptr<ObjectPoolImpl> pool(new ObjectPoolImpl(
      this, handle_generator, slot_policy, object_store, object_importer));
  CHECK(pool.get());
  if (!pool->Init())
    return NULL;
  return pool.release();
}

ObjectStore* ChapsFactoryImpl::CreateObjectStore(const FilePath& file_name) {
  std::unique_ptr<ObjectStoreImpl> store(new ObjectStoreImpl());
  if (!store->Init(file_name)) {
    // The approach here is to limp along without a persistent object store so
    // crypto services do not become unavailable. The side-effect is that all
    // objects will disappear when the token is removed (e.g. at logout).
    LOG(WARNING)
        << "Object store initialization failed, proceeding with fake store.";
    return new ObjectStoreFake();
  }
  return store.release();
}

Object* ChapsFactoryImpl::CreateObject() {
  return new ObjectImpl(this);
}

ObjectPolicy* ChapsFactoryImpl::CreateObjectPolicy(CK_OBJECT_CLASS type) {
  return ChapsFactoryImpl::GetObjectPolicyForType(type);
}

ObjectImporter* ChapsFactoryImpl::CreateObjectImporter(
    int slot_id, const FilePath& path, TPMUtility* tpm_utility) {
  if (!tpm_utility->IsTPMAvailable()) {
    return NULL;
  }
  return new OpencryptokiImporter(slot_id, path, tpm_utility, this);
}

SlotPolicy* ChapsFactoryImpl::CreateSlotPolicy(bool is_shared_slot) {
  if (is_shared_slot) {
    return new SlotPolicySharedSlot();
  }
  return new SlotPolicyDefault();
}

ObjectPolicy* ChapsFactoryImpl::GetObjectPolicyForType(CK_OBJECT_CLASS type) {
  switch (type) {
    case CKO_DATA:
      return new ObjectPolicyData();
    case CKO_CERTIFICATE:
      return new ObjectPolicyCert();
    case CKO_PUBLIC_KEY:
      return new ObjectPolicyPublicKey();
    case CKO_PRIVATE_KEY:
      return new ObjectPolicyPrivateKey();
    case CKO_SECRET_KEY:
      return new ObjectPolicySecretKey();
  }
  return new ObjectPolicyCommon();
}

}  // namespace chaps
