Commit 15430739 authored by nhiroki@chromium.org's avatar nhiroki@chromium.org

CacheStorage: Enable Cache::putImpl to receive multiple requests/responses

This CL enables Cache::putImpl to receive multiple requests and responses for
supporting addAll() in a subsequent CL. This should not change behavior of put()
and add().

BUG=427652

Review URL: https://codereview.chromium.org/1210873004

git-svn-id: svn://svn.chromium.org/blink/trunk@197958 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 777e6e7b
......@@ -153,7 +153,7 @@ public:
ScriptValue call(ScriptValue value) override
{
Response* response = V8Response::toImplWithTypeCheck(scriptState()->isolate(), value.v8Value());
ScriptPromise putPromise = m_cache->putImpl(scriptState(), m_request, response);
ScriptPromise putPromise = m_cache->putImpl(scriptState(), HeapVector<Member<Request>>(1, m_request), HeapVector<Member<Response>>(1, response));
return ScriptValue(scriptState(), putPromise.v8Value());
}
......@@ -176,49 +176,88 @@ private:
Member<Request> m_request;
};
class Cache::AsyncPutBatch final : public BodyStreamBuffer::BlobHandleCreatorClient {
class Cache::BarrierCallbackForPut final : public GarbageCollectedFinalized<BarrierCallbackForPut> {
public:
AsyncPutBatch(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver, Cache* cache, Request* request, Response* response)
: m_resolver(resolver)
BarrierCallbackForPut(int numberOfOperations, Cache* cache, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver)
: m_numberOfRemainingOperations(numberOfOperations)
, m_cache(cache)
, m_resolver(resolver)
{
request->populateWebServiceWorkerRequest(m_webRequest);
response->populateWebServiceWorkerResponse(m_webResponse);
ASSERT(0 < m_numberOfRemainingOperations);
m_batchOperations.resize(numberOfOperations);
}
~AsyncPutBatch() override { }
void didCreateBlobHandle(PassRefPtr<BlobDataHandle> handle) override
void onSuccess(size_t index, const WebServiceWorkerCache::BatchOperation& batchOperation)
{
WebVector<WebServiceWorkerCache::BatchOperation> batchOperations(size_t(1));
batchOperations[0].operationType = WebServiceWorkerCache::OperationTypePut;
batchOperations[0].request = m_webRequest;
batchOperations[0].response = m_webResponse;
batchOperations[0].response.setBlobDataHandle(handle);
m_cache->webCache()->dispatchBatch(new CallbackPromiseAdapter<void, CacheStorageError>(m_resolver.get()), batchOperations);
cleanup();
ASSERT(index < m_batchOperations.size());
if (m_completed)
return;
m_batchOperations[index] = batchOperation;
if (--m_numberOfRemainingOperations != 0)
return;
m_cache->webCache()->dispatchBatch(new CallbackPromiseAdapter<void, CacheStorageError>(m_resolver), m_batchOperations);
}
void didFail(DOMException* exception) override
void onError(DOMException* exception)
{
if (m_completed)
return;
m_completed = true;
ScriptState* state = m_resolver->scriptState();
ScriptState::Scope scope(state);
m_resolver->reject(V8ThrowException::createTypeError(state->isolate(), exception->toString()));
cleanup();
}
DEFINE_INLINE_VIRTUAL_TRACE()
{
visitor->trace(m_resolver);
visitor->trace(m_cache);
BlobHandleCreatorClient::trace(visitor);
}
private:
void cleanup()
bool m_completed = false;
int m_numberOfRemainingOperations;
Member<Cache> m_cache;
RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver;
Vector<WebServiceWorkerCache::BatchOperation> m_batchOperations;
};
class Cache::BlobHandleCallbackForPut final : public BodyStreamBuffer::BlobHandleCreatorClient {
public:
BlobHandleCallbackForPut(size_t index, BarrierCallbackForPut* barrierCallback, Request* request, Response* response)
: m_index(index)
, m_barrierCallback(barrierCallback)
{
m_resolver = nullptr;
m_cache = nullptr;
request->populateWebServiceWorkerRequest(m_webRequest);
response->populateWebServiceWorkerResponse(m_webResponse);
}
RefPtrWillBeMember<ScriptPromiseResolver> m_resolver;
Member<Cache> m_cache;
~BlobHandleCallbackForPut() override { }
void didCreateBlobHandle(PassRefPtr<BlobDataHandle> handle) override
{
WebServiceWorkerCache::BatchOperation batchOperation;
batchOperation.operationType = WebServiceWorkerCache::OperationTypePut;
batchOperation.request = m_webRequest;
batchOperation.response = m_webResponse;
batchOperation.response.setBlobDataHandle(handle);
m_barrierCallback->onSuccess(m_index, batchOperation);
}
void didFail(DOMException* exception) override
{
m_barrierCallback->onError(exception);
}
DEFINE_INLINE_VIRTUAL_TRACE()
{
visitor->trace(m_barrierCallback);
BlobHandleCreatorClient::trace(visitor);
}
private:
const size_t m_index;
Member<BarrierCallbackForPut> m_barrierCallback;
WebServiceWorkerRequest m_webRequest;
WebServiceWorkerResponse m_webResponse;
};
......@@ -289,11 +328,11 @@ ScriptPromise Cache::put(ScriptState* scriptState, const RequestInfo& request, R
{
ASSERT(!request.isNull());
if (request.isRequest())
return putImpl(scriptState, request.getAsRequest(), response);
return putImpl(scriptState, HeapVector<Member<Request>>(1, request.getAsRequest()), HeapVector<Member<Response>>(1, response));
Request* newRequest = Request::create(scriptState, request.getAsUSVString(), exceptionState);
if (exceptionState.hadException())
return ScriptPromise();
return putImpl(scriptState, newRequest, response);
return putImpl(scriptState, HeapVector<Member<Request>>(1, newRequest), HeapVector<Member<Response>>(1, response));
}
ScriptPromise Cache::keys(ScriptState* scriptState, ExceptionState&)
......@@ -381,39 +420,44 @@ ScriptPromise Cache::deleteImpl(ScriptState* scriptState, const Request* request
return promise;
}
ScriptPromise Cache::putImpl(ScriptState* scriptState, Request* request, Response* response)
ScriptPromise Cache::putImpl(ScriptState* scriptState, const HeapVector<Member<Request>>& requests, const HeapVector<Member<Response>>& responses)
{
KURL url(KURL(), request->url());
RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
const ScriptPromise promise = resolver->promise();
BarrierCallbackForPut* barrierCallback = new BarrierCallbackForPut(requests.size(), this, resolver.get());
for (size_t i = 0; i < requests.size(); ++i) {
KURL url(KURL(), requests[i]->url());
if (!url.protocolIsInHTTPFamily())
return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Request scheme '" + url.protocol() + "' is unsupported"));
if (request->method() != "GET")
return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Request method '" + request->method() + "' is unsupported"));
if (request->hasBody() && request->bodyUsed())
if (requests[i]->method() != "GET")
return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Request method '" + requests[i]->method() + "' is unsupported"));
if (requests[i]->hasBody() && requests[i]->bodyUsed())
return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Request body is already used"));
if (response->hasBody() && response->bodyUsed())
if (responses[i]->hasBody() && responses[i]->bodyUsed())
return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Response body is already used"));
if (request->hasBody())
request->lockBody(Body::PassBody);
if (response->hasBody())
response->lockBody(Body::PassBody);
if (requests[i]->hasBody())
requests[i]->lockBody(Body::PassBody);
if (responses[i]->hasBody())
responses[i]->lockBody(Body::PassBody);
if (BodyStreamBuffer* buffer = responses[i]->internalBuffer()) {
if (buffer == responses[i]->buffer() && responses[i]->isBodyConsumed())
buffer = responses[i]->createDrainingStream();
// If the response body type is stream, read the all data and create
// the blob handle and dispatch the put batch asynchronously.
buffer->readAllAndCreateBlobHandle(responses[i]->internalMIMEType(), new BlobHandleCallbackForPut(i, barrierCallback, requests[i], responses[i]));
continue;
}
RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
const ScriptPromise promise = resolver->promise();
if (BodyStreamBuffer* buffer = response->internalBuffer()) {
if (buffer == response->buffer() && response->isBodyConsumed())
buffer = response->createDrainingStream();
// If the response body type is stream, read the all data and create the
// blob handle and dispatch the put batch asynchronously.
buffer->readAllAndCreateBlobHandle(response->internalMIMEType(), new AsyncPutBatch(resolver, this, request, response));
return promise;
WebServiceWorkerCache::BatchOperation batchOperation;
batchOperation.operationType = WebServiceWorkerCache::OperationTypePut;
requests[i]->populateWebServiceWorkerRequest(batchOperation.request);
responses[i]->populateWebServiceWorkerResponse(batchOperation.response);
barrierCallback->onSuccess(i, batchOperation);
}
WebVector<WebServiceWorkerCache::BatchOperation> batchOperations(size_t(1));
batchOperations[0].operationType = WebServiceWorkerCache::OperationTypePut;
request->populateWebServiceWorkerRequest(batchOperations[0].request);
response->populateWebServiceWorkerResponse(batchOperations[0].response);
m_webCache->dispatchBatch(new CallbackPromiseAdapter<void, CacheStorageError>(resolver), batchOperations);
return promise;
}
......
......@@ -49,8 +49,9 @@ public:
DEFINE_INLINE_TRACE() { }
private:
class BarrierCallbackForPut;
class BlobHandleCallbackForPut;
class FetchResolvedForAdd;
class AsyncPutBatch;
friend class FetchResolvedForAdd;
Cache(WeakPtr<GlobalFetch::ScopedFetcher>, WebServiceWorkerCache*);
......@@ -58,7 +59,7 @@ private:
ScriptPromise matchAllImpl(ScriptState*, const Request*, const CacheQueryOptions&);
ScriptPromise addAllImpl(ScriptState*, const Vector<Request*>&, ExceptionState&);
ScriptPromise deleteImpl(ScriptState*, const Request*, const CacheQueryOptions&);
ScriptPromise putImpl(ScriptState*, Request*, Response*);
ScriptPromise putImpl(ScriptState*, const HeapVector<Member<Request>>&, const HeapVector<Member<Response>>&);
ScriptPromise keysImpl(ScriptState*);
ScriptPromise keysImpl(ScriptState*, const Request*, const CacheQueryOptions&);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment