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

#include "content/browser/media/webrtc_identity_store.h"

#include <map>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/threading/worker_pool.h"
#include "content/browser/media/webrtc_identity_store_backend.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/rsa_private_key.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_util.h"
#include "url/gurl.h"

namespace content {

struct WebRTCIdentityRequestResult {
  WebRTCIdentityRequestResult(int error,
                              const std::string& certificate,
                              const std::string& private_key)
      : error(error), certificate(certificate), private_key(private_key) {}

  int error;
  std::string certificate;
  std::string private_key;
};

// Generates a new identity using |common_name| and returns the result in
// |result|.
static void GenerateIdentityWorker(const std::string& common_name,
                                   WebRTCIdentityRequestResult* result) {
  result->error = net::OK;
  int serial_number = base::RandInt(0, std::numeric_limits<int>::max());

  scoped_ptr<crypto::RSAPrivateKey> key(crypto::RSAPrivateKey::Create(1024));
  if (!key.get()) {
    DLOG(ERROR) << "Unable to create key pair for client";
    result->error = net::ERR_KEY_GENERATION_FAILED;
    return;
  }

  base::Time now = base::Time::Now();
  bool success =
      net::x509_util::CreateSelfSignedCert(key.get(),
                                          "CN=" + common_name,
                                          serial_number,
                                          now,
                                          now + base::TimeDelta::FromDays(30),
                                          &result->certificate);
  if (!success) {
    DLOG(ERROR) << "Unable to create x509 cert for client";
    result->error = net::ERR_SELF_SIGNED_CERT_GENERATION_FAILED;
    return;
  }

  std::vector<uint8> private_key_info;
  if (!key->ExportPrivateKey(&private_key_info)) {
    DLOG(ERROR) << "Unable to export private key";
    result->error = net::ERR_PRIVATE_KEY_EXPORT_FAILED;
    return;
  }

  result->private_key =
      std::string(private_key_info.begin(), private_key_info.end());
}

class WebRTCIdentityRequestHandle;

// The class represents an identity request internal to WebRTCIdentityStore.
// It has a one-to-many mapping to the external version of the request,
// WebRTCIdentityRequestHandle, i.e. multiple identical external requests are
// combined into one internal request.
// It's deleted automatically when the request is completed.
class WebRTCIdentityRequest {
 public:
  WebRTCIdentityRequest(const GURL& origin,
                        const std::string& identity_name,
                        const std::string& common_name)
      : origin_(origin),
        identity_name_(identity_name),
        common_name_(common_name) {}

  void Cancel(WebRTCIdentityRequestHandle* handle) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    if (callbacks_.find(handle) == callbacks_.end())
      return;
    callbacks_.erase(handle);
  }

 private:
  friend class WebRTCIdentityStore;

  void AddCallback(WebRTCIdentityRequestHandle* handle,
                   const WebRTCIdentityStore::CompletionCallback& callback) {
    DCHECK(callbacks_.find(handle) == callbacks_.end());
    callbacks_[handle] = callback;
  }

  // This method deletes "this" and no one should access it after the request
  // completes.
  // We do not use base::Owned to tie its lifetime to the callback for
  // WebRTCIdentityStoreBackend::FindIdentity, because it needs to live longer
  // than that if the identity does not exist in DB.
  void Post(const WebRTCIdentityRequestResult& result) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    for (CallbackMap::iterator it = callbacks_.begin(); it != callbacks_.end();
         ++it)
      it->second.Run(result.error, result.certificate, result.private_key);
    delete this;
  }

  GURL origin_;
  std::string identity_name_;
  std::string common_name_;
  typedef std::map<WebRTCIdentityRequestHandle*,
                   WebRTCIdentityStore::CompletionCallback> CallbackMap;
  CallbackMap callbacks_;
};

// The class represents an identity request which calls back to the external
// client when the request completes.
// Its lifetime is tied with the Callback held by the corresponding
// WebRTCIdentityRequest.
class WebRTCIdentityRequestHandle {
 public:
  WebRTCIdentityRequestHandle(
      WebRTCIdentityStore* store,
      const WebRTCIdentityStore::CompletionCallback& callback)
      : store_(store), request_(NULL), callback_(callback) {}

 private:
  friend class WebRTCIdentityStore;

  // Cancel the request.  Does nothing if the request finished or was already
  // cancelled.
  void Cancel() {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    if (!request_)
      return;

    callback_.Reset();
    WebRTCIdentityRequest* request = request_;
    request_ = NULL;
    // "this" will be deleted after the following call, because "this" is
    // owned by the Callback held by |request|.
    request->Cancel(this);
  }

  void OnRequestStarted(WebRTCIdentityRequest* request) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    DCHECK(request);
    request_ = request;
  }

  void OnRequestComplete(int error,
                         const std::string& certificate,
                         const std::string& private_key) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    DCHECK(request_);
    request_ = NULL;
    base::ResetAndReturn(&callback_).Run(error, certificate, private_key);
  }

  WebRTCIdentityStore* store_;
  WebRTCIdentityRequest* request_;
  WebRTCIdentityStore::CompletionCallback callback_;

  DISALLOW_COPY_AND_ASSIGN(WebRTCIdentityRequestHandle);
};

WebRTCIdentityStore::WebRTCIdentityStore(const base::FilePath& path,
                                         quota::SpecialStoragePolicy* policy)
    : task_runner_(base::WorkerPool::GetTaskRunner(true)),
      backend_(new WebRTCIdentityStoreBackend(path, policy)) {}

WebRTCIdentityStore::~WebRTCIdentityStore() { backend_->Close(); }

base::Closure WebRTCIdentityStore::RequestIdentity(
    const GURL& origin,
    const std::string& identity_name,
    const std::string& common_name,
    const CompletionCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  WebRTCIdentityRequestHandle* handle =
      new WebRTCIdentityRequestHandle(this, callback);

  WebRTCIdentityRequest* request =
      FindRequest(origin, identity_name, common_name);

  // If there is no identical request in flight, create a new one, queue it,
  // and make the backend request.
  if (!request) {
    request = new WebRTCIdentityRequest(origin, identity_name, common_name);

    if (!backend_->FindIdentity(
            origin,
            identity_name,
            common_name,
            base::Bind(
                &WebRTCIdentityStore::BackendFindCallback, this, request))) {
      delete request;
      return base::Closure();
    }
    in_flight_requests_.push_back(request);
  }

  request->AddCallback(
      handle,
      base::Bind(&WebRTCIdentityRequestHandle::OnRequestComplete,
                 base::Owned(handle)));
  handle->OnRequestStarted(request);
  return base::Bind(&WebRTCIdentityRequestHandle::Cancel,
                    base::Unretained(handle));
}

void WebRTCIdentityStore::DeleteBetween(base::Time delete_begin,
                                        base::Time delete_end,
                                        const base::Closure& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  backend_->DeleteBetween(delete_begin, delete_end, callback);
}

void WebRTCIdentityStore::SetTaskRunnerForTesting(
    const scoped_refptr<base::TaskRunner>& task_runner) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  task_runner_ = task_runner;
}

void WebRTCIdentityStore::BackendFindCallback(WebRTCIdentityRequest* request,
                                              int error,
                                              const std::string& certificate,
                                              const std::string& private_key) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (error == net::OK) {
    DVLOG(2) << "Identity found in DB.";
    WebRTCIdentityRequestResult result(error, certificate, private_key);
    PostRequestResult(request, result);
    return;
  }
  // Generate a new identity if not found in the DB.
  WebRTCIdentityRequestResult* result =
      new WebRTCIdentityRequestResult(0, "", "");
  if (!task_runner_->PostTaskAndReply(
          FROM_HERE,
          base::Bind(&GenerateIdentityWorker, request->common_name_, result),
          base::Bind(&WebRTCIdentityStore::GenerateIdentityCallback,
                     this,
                     request,
                     base::Owned(result)))) {
    // Completes the request with error if failed to post the task.
    WebRTCIdentityRequestResult result(net::ERR_UNEXPECTED, "", "");
    PostRequestResult(request, result);
  }
}

void WebRTCIdentityStore::GenerateIdentityCallback(
    WebRTCIdentityRequest* request,
    WebRTCIdentityRequestResult* result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (result->error == net::OK) {
    DVLOG(2) << "New identity generated and added to the backend.";
    backend_->AddIdentity(request->origin_,
                          request->identity_name_,
                          request->common_name_,
                          result->certificate,
                          result->private_key);
  }
  PostRequestResult(request, *result);
}

void WebRTCIdentityStore::PostRequestResult(
    WebRTCIdentityRequest* request,
    const WebRTCIdentityRequestResult& result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  // Removes the in flight request from the queue.
  for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
    if (in_flight_requests_[i] == request) {
      in_flight_requests_.erase(in_flight_requests_.begin() + i);
      break;
    }
  }
  // |request| will be deleted after this call.
  request->Post(result);
}

// Find an identical request from the in flight requests.
WebRTCIdentityRequest* WebRTCIdentityStore::FindRequest(
    const GURL& origin,
    const std::string& identity_name,
    const std::string& common_name) {
  for (size_t i = 0; i < in_flight_requests_.size(); ++i) {
    if (in_flight_requests_[i]->origin_ == origin &&
        in_flight_requests_[i]->identity_name_ == identity_name &&
        in_flight_requests_[i]->common_name_ == common_name) {
      return in_flight_requests_[i];
    }
  }
  return NULL;
}

}  // namespace content
