// Copyright 2014 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/service_worker/service_worker_cache_listener.h"

#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/cache_storage_context_impl.h"
#include "content/browser/service_worker/service_worker_cache.h"
#include "content/browser/service_worker/service_worker_cache_storage_manager.h"
#include "content/common/service_worker/cache_storage_messages.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerCacheError.h"

namespace content {

using blink::WebServiceWorkerCacheError;

namespace {

WebServiceWorkerCacheError ToWebServiceWorkerCacheError(
    ServiceWorkerCacheStorage::CacheStorageError err) {
  switch (err) {
    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR:
      NOTREACHED();
      return blink::WebServiceWorkerCacheErrorNotImplemented;
    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_IMPLEMENTED:
      return blink::WebServiceWorkerCacheErrorNotImplemented;
    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND:
      return blink::WebServiceWorkerCacheErrorNotFound;
    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_EXISTS:
      return blink::WebServiceWorkerCacheErrorExists;
    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_STORAGE:
      // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's
      // added.
      return blink::WebServiceWorkerCacheErrorNotFound;
    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_CLOSING:
      // TODO(jkarlin): Update this to CACHE_STORAGE_ERROR_CLOSING once that's
      // added.
      return blink::WebServiceWorkerCacheErrorNotFound;
  }
  NOTREACHED();
  return blink::WebServiceWorkerCacheErrorNotImplemented;
}

// TODO(jkarlin): ServiceWorkerCache and ServiceWorkerCacheStorage should share
// an error enum type.
WebServiceWorkerCacheError CacheErrorToWebServiceWorkerCacheError(
    ServiceWorkerCache::ErrorType err) {
  switch (err) {
    case ServiceWorkerCache::ERROR_TYPE_OK:
      NOTREACHED();
      return blink::WebServiceWorkerCacheErrorNotImplemented;
    case ServiceWorkerCache::ERROR_TYPE_EXISTS:
      return blink::WebServiceWorkerCacheErrorExists;
    case ServiceWorkerCache::ERROR_TYPE_STORAGE:
      // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's
      // added.
      return blink::WebServiceWorkerCacheErrorNotFound;
    case ServiceWorkerCache::ERROR_TYPE_NOT_FOUND:
      return blink::WebServiceWorkerCacheErrorNotFound;
  }
  NOTREACHED();
  return blink::WebServiceWorkerCacheErrorNotImplemented;
}

}  // namespace

ServiceWorkerCacheListener::ServiceWorkerCacheListener(
    CacheStorageDispatcherHost* dispatcher,
    CacheStorageContextImpl* context)
    : dispatcher_(dispatcher), context_(context), weak_factory_(this) {
}

ServiceWorkerCacheListener::~ServiceWorkerCacheListener() {
}

bool ServiceWorkerCacheListener::OnMessageReceived(
    const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(ServiceWorkerCacheListener, message)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageHas,
                        OnCacheStorageHas)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageOpen,
                        OnCacheStorageOpen)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageDelete,
                        OnCacheStorageDelete)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageKeys,
                        OnCacheStorageKeys)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageMatch,
                        OnCacheStorageMatch)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheMatch,
                        OnCacheMatch)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheMatchAll,
                        OnCacheMatchAll)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheKeys,
                        OnCacheKeys)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheBatch,
                        OnCacheBatch)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheClosed,
                        OnCacheClosed)
    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_BlobDataHandled, OnBlobDataHandled)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void ServiceWorkerCacheListener::OnCacheStorageHas(
    int thread_id,
    int request_id,
    const GURL& origin,
    const base::string16& cache_name) {
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerCacheListener::OnCacheStorageHas");
  context_->cache_manager()->HasCache(
      origin, base::UTF16ToUTF8(cache_name),
      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageHasCallback,
                 weak_factory_.GetWeakPtr(), thread_id, request_id));
}

void ServiceWorkerCacheListener::OnCacheStorageOpen(
    int thread_id,
    int request_id,
    const GURL& origin,
    const base::string16& cache_name) {
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerCacheListener::OnCacheStorageOpen");
  context_->cache_manager()->OpenCache(
      origin, base::UTF16ToUTF8(cache_name),
      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageOpenCallback,
                 weak_factory_.GetWeakPtr(), thread_id, request_id));
}

void ServiceWorkerCacheListener::OnCacheStorageDelete(
    int thread_id,
    int request_id,
    const GURL& origin,
    const base::string16& cache_name) {
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerCacheListener::OnCacheStorageDelete");
  context_->cache_manager()->DeleteCache(
      origin, base::UTF16ToUTF8(cache_name),
      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageDeleteCallback,
                 weak_factory_.GetWeakPtr(), thread_id, request_id));
}

void ServiceWorkerCacheListener::OnCacheStorageKeys(int thread_id,
                                                    int request_id,
                                                    const GURL& origin) {
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerCacheListener::OnCacheStorageKeys");
  context_->cache_manager()->EnumerateCaches(
      origin,
      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageKeysCallback,
                 weak_factory_.GetWeakPtr(), thread_id, request_id));
}

void ServiceWorkerCacheListener::OnCacheStorageMatch(
    int thread_id,
    int request_id,
    const GURL& origin,
    const ServiceWorkerFetchRequest& request,
    const ServiceWorkerCacheQueryParams& match_params) {
  TRACE_EVENT0("ServiceWorker",
               "ServiceWorkerCacheListener::OnCacheStorageMatch");

  scoped_ptr<ServiceWorkerFetchRequest> scoped_request(
      new ServiceWorkerFetchRequest(request.url, request.method,
                                    request.headers, request.referrer,
                                    request.is_reload));

  if (match_params.cache_name.empty()) {
    context_->cache_manager()->MatchAllCaches(
        origin, scoped_request.Pass(),
        base::Bind(&ServiceWorkerCacheListener::OnCacheStorageMatchCallback,
                   weak_factory_.GetWeakPtr(), thread_id, request_id));
    return;
  }
  context_->cache_manager()->MatchCache(
      origin, base::UTF16ToUTF8(match_params.cache_name), scoped_request.Pass(),
      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageMatchCallback,
                 weak_factory_.GetWeakPtr(), thread_id, request_id));
}

void ServiceWorkerCacheListener::OnCacheMatch(
    int thread_id,
    int request_id,
    int cache_id,
    const ServiceWorkerFetchRequest& request,
    const ServiceWorkerCacheQueryParams& match_params) {
  IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
  if (it == id_to_cache_map_.end()) {
    Send(new ServiceWorkerMsg_CacheMatchError(
        thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
    return;
  }

  scoped_refptr<ServiceWorkerCache> cache = it->second;
  scoped_ptr<ServiceWorkerFetchRequest> scoped_request(
      new ServiceWorkerFetchRequest(request.url,
                                    request.method,
                                    request.headers,
                                    request.referrer,
                                    request.is_reload));
  cache->Match(
      scoped_request.Pass(),
      base::Bind(&ServiceWorkerCacheListener::OnCacheMatchCallback,
                 weak_factory_.GetWeakPtr(), thread_id, request_id, cache));
}

void ServiceWorkerCacheListener::OnCacheMatchAll(
    int thread_id,
    int request_id,
    int cache_id,
    const ServiceWorkerFetchRequest& request,
    const ServiceWorkerCacheQueryParams& match_params) {
  // TODO(gavinp,jkarlin): Implement this method.
  Send(new ServiceWorkerMsg_CacheMatchAllError(
      thread_id, request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
}

void ServiceWorkerCacheListener::OnCacheKeys(
    int thread_id,
    int request_id,
    int cache_id,
    const ServiceWorkerFetchRequest& request,
    const ServiceWorkerCacheQueryParams& match_params) {
  IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
  if (it == id_to_cache_map_.end()) {
    Send(new ServiceWorkerMsg_CacheKeysError(
        thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
    return;
  }

  scoped_refptr<ServiceWorkerCache> cache = it->second;

  cache->Keys(base::Bind(&ServiceWorkerCacheListener::OnCacheKeysCallback,
                         weak_factory_.GetWeakPtr(), thread_id, request_id,
                         cache));
}

void ServiceWorkerCacheListener::OnCacheBatch(
    int thread_id,
    int request_id,
    int cache_id,
    const std::vector<ServiceWorkerBatchOperation>& operations) {
  if (operations.size() != 1u) {
    Send(new ServiceWorkerMsg_CacheBatchError(
        thread_id, request_id,
        blink::WebServiceWorkerCacheErrorNotImplemented));
    return;
  }

  IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
  if (it == id_to_cache_map_.end()) {
    Send(new ServiceWorkerMsg_CacheBatchError(
        thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
    return;
  }

  const ServiceWorkerBatchOperation& operation = operations[0];

  scoped_refptr<ServiceWorkerCache> cache = it->second;
  scoped_ptr<ServiceWorkerFetchRequest> scoped_request(
      new ServiceWorkerFetchRequest(operation.request.url,
                                    operation.request.method,
                                    operation.request.headers,
                                    operation.request.referrer,
                                    operation.request.is_reload));

  if (operation.operation_type == SERVICE_WORKER_CACHE_OPERATION_TYPE_DELETE) {
    cache->Delete(
        scoped_request.Pass(),
        base::Bind(&ServiceWorkerCacheListener::OnCacheDeleteCallback,
                   weak_factory_.GetWeakPtr(), thread_id, request_id, cache));
    return;
  }

  if (operation.operation_type == SERVICE_WORKER_CACHE_OPERATION_TYPE_PUT) {
    // We don't support streaming for cache.
    DCHECK(operation.response.stream_url.is_empty());
    scoped_ptr<ServiceWorkerResponse> scoped_response(
        new ServiceWorkerResponse(operation.response.url,
                                  operation.response.status_code,
                                  operation.response.status_text,
                                  operation.response.response_type,
                                  operation.response.headers,
                                  operation.response.blob_uuid,
                                  operation.response.blob_size,
                                  operation.response.stream_url));
    cache->Put(
        scoped_request.Pass(), scoped_response.Pass(),
        base::Bind(&ServiceWorkerCacheListener::OnCachePutCallback,
                   weak_factory_.GetWeakPtr(), thread_id, request_id, cache));

    return;
  }

  Send(new ServiceWorkerMsg_CacheBatchError(
      thread_id, request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
}

void ServiceWorkerCacheListener::OnCacheClosed(int cache_id) {
  DropCacheReference(cache_id);
}

void ServiceWorkerCacheListener::OnBlobDataHandled(const std::string& uuid) {
  DropBlobDataHandle(uuid);
}

void ServiceWorkerCacheListener::Send(IPC::Message* message) {
  dispatcher_->Send(message);
}

void ServiceWorkerCacheListener::OnCacheStorageHasCallback(
    int thread_id,
    int request_id,
    bool has_cache,
    ServiceWorkerCacheStorage::CacheStorageError error) {
  if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
    Send(new ServiceWorkerMsg_CacheStorageHasError(
        thread_id, request_id, ToWebServiceWorkerCacheError(error)));
    return;
  }
  if (!has_cache) {
    Send(new ServiceWorkerMsg_CacheStorageHasError(
        thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound));
    return;
  }
  Send(new ServiceWorkerMsg_CacheStorageHasSuccess(thread_id, request_id));
}

void ServiceWorkerCacheListener::OnCacheStorageOpenCallback(
    int thread_id,
    int request_id,
    const scoped_refptr<ServiceWorkerCache>& cache,
    ServiceWorkerCacheStorage::CacheStorageError error) {
  if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
    Send(new ServiceWorkerMsg_CacheStorageOpenError(
        thread_id, request_id, ToWebServiceWorkerCacheError(error)));
    return;
  }
  CacheID cache_id = StoreCacheReference(cache);
  Send(new ServiceWorkerMsg_CacheStorageOpenSuccess(thread_id, request_id,
                                                    cache_id));
}

void ServiceWorkerCacheListener::OnCacheStorageDeleteCallback(
    int thread_id,
    int request_id,
    bool deleted,
    ServiceWorkerCacheStorage::CacheStorageError error) {
  if (!deleted ||
      error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
    Send(new ServiceWorkerMsg_CacheStorageDeleteError(
        thread_id, request_id, ToWebServiceWorkerCacheError(error)));
    return;
  }
  Send(new ServiceWorkerMsg_CacheStorageDeleteSuccess(thread_id, request_id));
}

void ServiceWorkerCacheListener::OnCacheStorageKeysCallback(
    int thread_id,
    int request_id,
    const std::vector<std::string>& strings,
    ServiceWorkerCacheStorage::CacheStorageError error) {
  if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
    Send(new ServiceWorkerMsg_CacheStorageKeysError(
        thread_id, request_id, ToWebServiceWorkerCacheError(error)));
    return;
  }

  std::vector<base::string16> string16s;
  for (size_t i = 0, max = strings.size(); i < max; ++i) {
    string16s.push_back(base::UTF8ToUTF16(strings[i]));
  }
  Send(new ServiceWorkerMsg_CacheStorageKeysSuccess(thread_id, request_id,
                                                    string16s));
}

void ServiceWorkerCacheListener::OnCacheStorageMatchCallback(
    int thread_id,
    int request_id,
    ServiceWorkerCache::ErrorType error,
    scoped_ptr<ServiceWorkerResponse> response,
    scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
  if (error != ServiceWorkerCache::ERROR_TYPE_OK) {
    Send(new ServiceWorkerMsg_CacheStorageMatchError(
        thread_id, request_id, CacheErrorToWebServiceWorkerCacheError(error)));
    return;
  }

  if (blob_data_handle)
    StoreBlobDataHandle(blob_data_handle.Pass());

  Send(new ServiceWorkerMsg_CacheStorageMatchSuccess(thread_id, request_id,
                                                     *response));
}

void ServiceWorkerCacheListener::OnCacheMatchCallback(
    int thread_id,
    int request_id,
    const scoped_refptr<ServiceWorkerCache>& cache,
    ServiceWorkerCache::ErrorType error,
    scoped_ptr<ServiceWorkerResponse> response,
    scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
  if (error != ServiceWorkerCache::ERROR_TYPE_OK) {
    Send(new ServiceWorkerMsg_CacheMatchError(
        thread_id, request_id, CacheErrorToWebServiceWorkerCacheError(error)));
    return;
  }

  if (blob_data_handle)
    StoreBlobDataHandle(blob_data_handle.Pass());

  Send(
      new ServiceWorkerMsg_CacheMatchSuccess(thread_id, request_id, *response));
}

void ServiceWorkerCacheListener::OnCacheKeysCallback(
    int thread_id,
    int request_id,
    const scoped_refptr<ServiceWorkerCache>& cache,
    ServiceWorkerCache::ErrorType error,
    scoped_ptr<ServiceWorkerCache::Requests> requests) {
  if (error != ServiceWorkerCache::ERROR_TYPE_OK) {
    Send(new ServiceWorkerMsg_CacheKeysError(
        thread_id, request_id, CacheErrorToWebServiceWorkerCacheError(error)));
    return;
  }

  ServiceWorkerCache::Requests out;

  for (ServiceWorkerCache::Requests::const_iterator it = requests->begin();
       it != requests->end();
       ++it) {
    ServiceWorkerFetchRequest request(
        it->url, it->method, it->headers, it->referrer, it->is_reload);
    out.push_back(request);
  }

  Send(new ServiceWorkerMsg_CacheKeysSuccess(thread_id, request_id, out));
}

void ServiceWorkerCacheListener::OnCacheDeleteCallback(
    int thread_id,
    int request_id,
    const scoped_refptr<ServiceWorkerCache>& cache,
    ServiceWorkerCache::ErrorType error) {
  if (error != ServiceWorkerCache::ERROR_TYPE_OK) {
    Send(new ServiceWorkerMsg_CacheBatchError(
        thread_id, request_id, CacheErrorToWebServiceWorkerCacheError(error)));
    return;
  }

  Send(new ServiceWorkerMsg_CacheBatchSuccess(
      thread_id, request_id, std::vector<ServiceWorkerResponse>()));
}

void ServiceWorkerCacheListener::OnCachePutCallback(
    int thread_id,
    int request_id,
    const scoped_refptr<ServiceWorkerCache>& cache,
    ServiceWorkerCache::ErrorType error,
    scoped_ptr<ServiceWorkerResponse> response,
    scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
  if (error != ServiceWorkerCache::ERROR_TYPE_OK) {
    Send(new ServiceWorkerMsg_CacheBatchError(
        thread_id, request_id, CacheErrorToWebServiceWorkerCacheError(error)));
    return;
  }

  if (blob_data_handle)
    StoreBlobDataHandle(blob_data_handle.Pass());

  std::vector<ServiceWorkerResponse> responses;
  responses.push_back(*response);
  Send(
      new ServiceWorkerMsg_CacheBatchSuccess(thread_id, request_id, responses));
}

ServiceWorkerCacheListener::CacheID
ServiceWorkerCacheListener::StoreCacheReference(
    const scoped_refptr<ServiceWorkerCache>& cache) {
  int cache_id = next_cache_id_++;
  id_to_cache_map_[cache_id] = cache;
  return cache_id;
}

void ServiceWorkerCacheListener::DropCacheReference(CacheID cache_id) {
  id_to_cache_map_.erase(cache_id);
}

void ServiceWorkerCacheListener::StoreBlobDataHandle(
    scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
  DCHECK(blob_data_handle);
  std::pair<UUIDToBlobDataHandleList::iterator, bool> rv =
      blob_handle_store_.insert(std::make_pair(
          blob_data_handle->uuid(), std::list<storage::BlobDataHandle>()));
  rv.first->second.push_front(storage::BlobDataHandle(*blob_data_handle));
}

void ServiceWorkerCacheListener::DropBlobDataHandle(std::string uuid) {
  UUIDToBlobDataHandleList::iterator it = blob_handle_store_.find(uuid);
  if (it == blob_handle_store_.end())
    return;
  DCHECK(!it->second.empty());
  it->second.pop_front();
  if (it->second.empty())
    blob_handle_store_.erase(it);
}

}  // namespace content
