#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/service_worker/service_worker_cache.h"
#include "content/browser/service_worker/service_worker_cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerCacheError.h"
namespace content {
case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_EXISTS:
return blink::WebServiceWorkerCacheErrorExists;
case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_STORAGE:
- // TODO(jkarlin): Changethis to CACHE_STORAGE_ERROR_STORAGE once that's
+ // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's
// added.
return blink::WebServiceWorkerCacheErrorNotFound;
case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_CLOSING:
return blink::WebServiceWorkerCacheErrorNotImplemented;
}
+// TODO(jkarlin): ServiceWorkerCache and ServiceWorkerCacheStorage should share
+// an error enum type.
+WebServiceWorkerCacheError CacheErrorToWebServiceWorkerCacheError(
+ ServiceWorkerCache::ErrorType err) {
+ switch (err) {
+ case ServiceWorkerCache::ErrorTypeOK:
+ NOTREACHED();
+ return blink::WebServiceWorkerCacheErrorNotImplemented;
+ case ServiceWorkerCache::ErrorTypeExists:
+ return blink::WebServiceWorkerCacheErrorExists;
+ case ServiceWorkerCache::ErrorTypeStorage:
+ // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's
+ // added.
+ return blink::WebServiceWorkerCacheErrorNotFound;
+ case ServiceWorkerCache::ErrorTypeNotFound:
+ return blink::WebServiceWorkerCacheErrorNotFound;
+ }
+ NOTREACHED();
+ return blink::WebServiceWorkerCacheErrorNotImplemented;
+}
+
} // namespace
ServiceWorkerCacheListener::ServiceWorkerCacheListener(
context_(context),
next_cache_id_(0),
weak_factory_(this) {
+ version_->embedded_worker()->AddListener(this);
}
ServiceWorkerCacheListener::~ServiceWorkerCacheListener() {
+ version_->embedded_worker()->RemoveListener(this);
}
bool ServiceWorkerCacheListener::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerCacheListener, message)
- IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageGet,
- OnCacheStorageGet)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageHas,
OnCacheStorageHas)
- IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageCreate,
- OnCacheStorageCreate)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageOpen,
+ OnCacheStorageOpen)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageDelete,
OnCacheStorageDelete)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageKeys,
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::OnCacheStorageGet(
- int request_id,
- const base::string16& cache_name) {
- TRACE_EVENT0("ServiceWorker",
- "ServiceWorkerCacheListener::OnCacheStorageGet");
- context_->cache_manager()->GetCache(
- version_->scope().GetOrigin(),
- base::UTF16ToUTF8(cache_name),
- base::Bind(&ServiceWorkerCacheListener::OnCacheStorageGetCallback,
- weak_factory_.GetWeakPtr(),
- request_id));
-}
-
void ServiceWorkerCacheListener::OnCacheStorageHas(
int request_id,
const base::string16& cache_name) {
request_id));
}
-void ServiceWorkerCacheListener::OnCacheStorageCreate(
+void ServiceWorkerCacheListener::OnCacheStorageOpen(
int request_id,
const base::string16& cache_name) {
TRACE_EVENT0("ServiceWorker",
- "ServiceWorkerCacheListener::OnCacheStorageCreate");
- context_->cache_manager()->CreateCache(
+ "ServiceWorkerCacheListener::OnCacheStorageOpen");
+ context_->cache_manager()->OpenCache(
version_->scope().GetOrigin(),
base::UTF16ToUTF8(cache_name),
- base::Bind(&ServiceWorkerCacheListener::OnCacheStorageCreateCallback,
+ base::Bind(&ServiceWorkerCacheListener::OnCacheStorageOpenCallback,
weak_factory_.GetWeakPtr(),
request_id));
}
int cache_id,
const ServiceWorkerFetchRequest& request,
const ServiceWorkerCacheQueryParams& match_params) {
- // TODO(gavinp,jkarlin): Implement this method.
- Send(ServiceWorkerMsg_CacheMatchError(
- request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
+ IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
+ if (it == id_to_cache_map_.end()) {
+ Send(ServiceWorkerMsg_CacheMatchError(
+ 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(),
+ request_id,
+ cache));
}
void ServiceWorkerCacheListener::OnCacheMatchAll(
int cache_id,
const ServiceWorkerFetchRequest& request,
const ServiceWorkerCacheQueryParams& match_params) {
- // TODO(gavinp,jkarlin): Implement this method.
- Send(ServiceWorkerMsg_CacheKeysError(
- request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
+ IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
+ if (it == id_to_cache_map_.end()) {
+ Send(ServiceWorkerMsg_CacheKeysError(
+ request_id, blink::WebServiceWorkerCacheErrorNotFound));
+ return;
+ }
+
+ scoped_refptr<ServiceWorkerCache> cache = it->second;
+
+ cache->Keys(base::Bind(&ServiceWorkerCacheListener::OnCacheKeysCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ cache));
}
void ServiceWorkerCacheListener::OnCacheBatch(
int request_id,
int cache_id,
const std::vector<ServiceWorkerBatchOperation>& operations) {
- // TODO(gavinp,jkarlin): Implement this method.
+ if (operations.size() != 1u) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
+ return;
+ }
+
+ IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
+ if (it == id_to_cache_map_.end()) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ 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(),
+ request_id,
+ cache));
+ return;
+ }
+
+ if (operation.operation_type == SERVICE_WORKER_CACHE_OPERATION_TYPE_PUT) {
+ 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));
+ cache->Put(scoped_request.Pass(),
+ scoped_response.Pass(),
+ base::Bind(&ServiceWorkerCacheListener::OnCachePutCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ cache));
+
+ return;
+ }
+
Send(ServiceWorkerMsg_CacheBatchError(
request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
}
void ServiceWorkerCacheListener::OnCacheClosed(int cache_id) {
- // TODO(gavinp,jkarlin): Implement this method.
+ DropCacheReference(cache_id);
}
-void ServiceWorkerCacheListener::Send(const IPC::Message& message) {
- version_->embedded_worker()->SendMessage(message);
+void ServiceWorkerCacheListener::OnBlobDataHandled(const std::string& uuid) {
+ DropBlobDataHandle(uuid);
}
-void ServiceWorkerCacheListener::OnCacheStorageGetCallback(
- int request_id,
- const scoped_refptr<ServiceWorkerCache>& cache,
- ServiceWorkerCacheStorage::CacheStorageError error) {
- if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
- Send(ServiceWorkerMsg_CacheStorageGetError(
- request_id, ToWebServiceWorkerCacheError(error)));
- return;
- }
-
- CacheID cache_id = StoreCacheReference(cache);
- Send(ServiceWorkerMsg_CacheStorageGetSuccess(request_id, cache_id));
+void ServiceWorkerCacheListener::Send(const IPC::Message& message) {
+ version_->embedded_worker()->SendMessage(message);
}
void ServiceWorkerCacheListener::OnCacheStorageHasCallback(
Send(ServiceWorkerMsg_CacheStorageHasSuccess(request_id));
}
-void ServiceWorkerCacheListener::OnCacheStorageCreateCallback(
+void ServiceWorkerCacheListener::OnCacheStorageOpenCallback(
int request_id,
const scoped_refptr<ServiceWorkerCache>& cache,
ServiceWorkerCacheStorage::CacheStorageError error) {
if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
- Send(ServiceWorkerMsg_CacheStorageCreateError(
+ Send(ServiceWorkerMsg_CacheStorageOpenError(
request_id, ToWebServiceWorkerCacheError(error)));
return;
}
CacheID cache_id = StoreCacheReference(cache);
- Send(ServiceWorkerMsg_CacheStorageCreateSuccess(request_id, cache_id));
+ Send(ServiceWorkerMsg_CacheStorageOpenSuccess(request_id, cache_id));
}
void ServiceWorkerCacheListener::OnCacheStorageDeleteCallback(
Send(ServiceWorkerMsg_CacheStorageKeysSuccess(request_id, string16s));
}
+void ServiceWorkerCacheListener::OnCacheMatchCallback(
+ 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::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheMatchError(
+ request_id, CacheErrorToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ if (blob_data_handle)
+ StoreBlobDataHandle(blob_data_handle.Pass());
+
+ Send(ServiceWorkerMsg_CacheMatchSuccess(request_id, *response));
+}
+
+void ServiceWorkerCacheListener::OnCacheKeysCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerCache::Requests> requests) {
+ if (error != ServiceWorkerCache::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheKeysError(
+ 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(ServiceWorkerMsg_CacheKeysSuccess(request_id, out));
+}
+
+void ServiceWorkerCacheListener::OnCacheDeleteCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error) {
+ if (error != ServiceWorkerCache::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, CacheErrorToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ Send(ServiceWorkerMsg_CacheBatchSuccess(
+ request_id, std::vector<ServiceWorkerResponse>()));
+}
+
+void ServiceWorkerCacheListener::OnCachePutCallback(
+ 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::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, CacheErrorToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ if (blob_data_handle)
+ StoreBlobDataHandle(blob_data_handle.Pass());
+
+ std::vector<ServiceWorkerResponse> responses;
+ responses.push_back(*response);
+ Send(ServiceWorkerMsg_CacheBatchSuccess(request_id, responses));
+}
+
ServiceWorkerCacheListener::CacheID
ServiceWorkerCacheListener::StoreCacheReference(
const scoped_refptr<ServiceWorkerCache>& cache) {
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