// Copyright (c) 2011 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/child/quota_dispatcher.h"

#include "base/basictypes.h"
#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
#include "content/child/child_thread.h"
#include "content/child/quota_message_filter.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/quota_messages.h"
#include "third_party/WebKit/public/web/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/web/WebStorageQuotaType.h"
#include "url/gurl.h"

using quota::QuotaStatusCode;
using quota::StorageType;

using WebKit::WebStorageQuotaCallbacks;
using WebKit::WebStorageQuotaError;
using WebKit::WebStorageQuotaType;

using webkit_glue::WorkerTaskRunner;

namespace content {

static base::LazyInstance<base::ThreadLocalPointer<QuotaDispatcher> >::Leaky
    g_quota_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;

namespace {

// QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
 public:
  WebStorageQuotaDispatcherCallback(WebKit::WebStorageQuotaCallbacks* callback)
      : callbacks_(callback) {
    DCHECK(callbacks_);
  }
  virtual ~WebStorageQuotaDispatcherCallback() {}
  virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
    callbacks_->didQueryStorageUsageAndQuota(usage, quota);
  }
  virtual void DidGrantStorageQuota(int64 granted_quota) OVERRIDE {
    callbacks_->didGrantStorageQuota(granted_quota);
  }
  virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
    callbacks_->didFail(static_cast<WebStorageQuotaError>(error));
  }

 private:
  // Not owned (self-destructed).
  WebKit::WebStorageQuotaCallbacks* callbacks_;
};

int CurrentWorkerId() {
  return WorkerTaskRunner::Instance()->CurrentWorkerId();
}

}  // namespace

QuotaDispatcher::QuotaDispatcher(ThreadSafeSender* thread_safe_sender,
                                 QuotaMessageFilter* quota_message_filter)
    : thread_safe_sender_(thread_safe_sender),
      quota_message_filter_(quota_message_filter) {
  g_quota_dispatcher_tls.Pointer()->Set(this);
}

QuotaDispatcher::~QuotaDispatcher() {
  IDMap<Callback, IDMapOwnPointer>::iterator iter(&pending_quota_callbacks_);
  while (!iter.IsAtEnd()) {
    iter.GetCurrentValue()->DidFail(quota::kQuotaErrorAbort);
    iter.Advance();
  }

  g_quota_dispatcher_tls.Pointer()->Set(NULL);
}

QuotaDispatcher* QuotaDispatcher::ThreadSpecificInstance(
    ThreadSafeSender* thread_safe_sender,
    QuotaMessageFilter* quota_message_filter) {
  if (g_quota_dispatcher_tls.Pointer()->Get())
    return g_quota_dispatcher_tls.Pointer()->Get();

  QuotaDispatcher* dispatcher = new QuotaDispatcher(
      thread_safe_sender, quota_message_filter);
  if (WorkerTaskRunner::Instance()->CurrentWorkerId())
    WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
  return dispatcher;
}

void QuotaDispatcher::OnWorkerRunLoopStopped() {
  delete this;
}

void QuotaDispatcher::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(QuotaDispatcher, msg)
    IPC_MESSAGE_HANDLER(QuotaMsg_DidGrantStorageQuota,
                        DidGrantStorageQuota)
    IPC_MESSAGE_HANDLER(QuotaMsg_DidQueryStorageUsageAndQuota,
                        DidQueryStorageUsageAndQuota);
    IPC_MESSAGE_HANDLER(QuotaMsg_DidFail, DidFail);
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  DCHECK(handled) << "Unhandled message:" << msg.type();
}

void QuotaDispatcher::QueryStorageUsageAndQuota(
    const GURL& origin_url,
    StorageType type,
    Callback* callback) {
  DCHECK(callback);
  int request_id = pending_quota_callbacks_.Add(callback);
  quota_message_filter_->RegisterRequestID(request_id, CurrentWorkerId());
  thread_safe_sender_->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
      request_id, origin_url, type));
}

void QuotaDispatcher::RequestStorageQuota(
    int render_view_id,
    const GURL& origin_url,
    StorageType type,
    int64 requested_size,
    Callback* callback) {
  DCHECK(callback);
  DCHECK(CurrentWorkerId() == 0);
  int request_id = pending_quota_callbacks_.Add(callback);
  quota_message_filter_->RegisterRequestID(request_id, CurrentWorkerId());
  thread_safe_sender_->Send(new QuotaHostMsg_RequestStorageQuota(
      render_view_id, request_id, origin_url, type, requested_size));
}

// static
QuotaDispatcher::Callback*
QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
    WebKit::WebStorageQuotaCallbacks* callbacks) {
  return new WebStorageQuotaDispatcherCallback(callbacks);
}

void QuotaDispatcher::DidGrantStorageQuota(
    int request_id,
    int64 granted_quota) {
  Callback* callback = pending_quota_callbacks_.Lookup(request_id);
  DCHECK(callback);
  callback->DidGrantStorageQuota(granted_quota);
  pending_quota_callbacks_.Remove(request_id);
}

void QuotaDispatcher::DidQueryStorageUsageAndQuota(
    int request_id,
    int64 current_usage,
    int64 current_quota) {
  Callback* callback = pending_quota_callbacks_.Lookup(request_id);
  DCHECK(callback);
  callback->DidQueryStorageUsageAndQuota(current_usage, current_quota);
  pending_quota_callbacks_.Remove(request_id);
}

void QuotaDispatcher::DidFail(
    int request_id,
    QuotaStatusCode error) {
  Callback* callback = pending_quota_callbacks_.Lookup(request_id);
  DCHECK(callback);
  callback->DidFail(error);
  pending_quota_callbacks_.Remove(request_id);
}

COMPILE_ASSERT(int(WebKit::WebStorageQuotaTypeTemporary) == \
               int(quota::kStorageTypeTemporary), mismatching_enums);
COMPILE_ASSERT(int(WebKit::WebStorageQuotaTypePersistent) == \
               int(quota::kStorageTypePersistent), mismatching_enums);

COMPILE_ASSERT(int(WebKit::WebStorageQuotaErrorNotSupported) == \
               int(quota::kQuotaErrorNotSupported), mismatching_enums);
COMPILE_ASSERT(int(WebKit::WebStorageQuotaErrorAbort) == \
               int(quota::kQuotaErrorAbort), mismatching_enums);

}  // namespace content
