Chromium Code Reviews| Index: Source/modules/cachestorage/Cache.cpp |
| diff --git a/Source/modules/cachestorage/Cache.cpp b/Source/modules/cachestorage/Cache.cpp |
| index bbe9c75e7693d29c83e60a08481562561573c82e..8a6d65ea6132c018f2bb19007a4ce6b435da63f5 100644 |
| --- a/Source/modules/cachestorage/Cache.cpp |
| +++ b/Source/modules/cachestorage/Cache.cpp |
| @@ -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); |
|
sof
2015/06/30 09:46:46
Where is m_resolver resolved or cleared?
nhiroki
2015/07/01 02:02:20
m_resolver is resolved in CallbackPromiseAdapter<v
|
| } |
| - 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()); |
| - 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()) |
| - return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Request body is already used")); |
| - if (response->hasBody() && response->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); |
| - |
| 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; |
| + 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 (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 (responses[i]->hasBody() && responses[i]->bodyUsed()) |
| + return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Response body is already used")); |
| + |
| + 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; |
| + } |
| + |
| + 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; |
| } |