OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "modules/cachestorage/Cache.h" | 6 #include "modules/cachestorage/Cache.h" |
7 | 7 |
8 #include "bindings/core/v8/CallbackPromiseAdapter.h" | 8 #include "bindings/core/v8/CallbackPromiseAdapter.h" |
9 #include "bindings/core/v8/ExceptionState.h" | 9 #include "bindings/core/v8/ExceptionState.h" |
10 #include "bindings/core/v8/ScriptPromiseResolver.h" | 10 #include "bindings/core/v8/ScriptPromiseResolver.h" |
11 #include "bindings/core/v8/ScriptState.h" | 11 #include "bindings/core/v8/ScriptState.h" |
| 12 #include "bindings/core/v8/V8Binding.h" |
12 #include "bindings/core/v8/V8ThrowException.h" | 13 #include "bindings/core/v8/V8ThrowException.h" |
13 #include "bindings/modules/v8/V8Response.h" | 14 #include "bindings/modules/v8/V8Response.h" |
14 #include "core/dom/DOMException.h" | 15 #include "core/dom/DOMException.h" |
15 #include "modules/cachestorage/CacheStorageError.h" | 16 #include "modules/cachestorage/CacheStorageError.h" |
16 #include "modules/fetch/BodyStreamBuffer.h" | 17 #include "modules/fetch/BodyStreamBuffer.h" |
17 #include "modules/fetch/GlobalFetch.h" | 18 #include "modules/fetch/GlobalFetch.h" |
18 #include "modules/fetch/Request.h" | 19 #include "modules/fetch/Request.h" |
19 #include "modules/fetch/Response.h" | 20 #include "modules/fetch/Response.h" |
20 #include "public/platform/WebServiceWorkerCache.h" | 21 #include "public/platform/WebServiceWorkerCache.h" |
21 | 22 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 { | 129 { |
129 OwnPtr<WebServiceWorkerCacheError> reason = adoptPtr(rawReason); | 130 OwnPtr<WebServiceWorkerCacheError> reason = adoptPtr(rawReason); |
130 m_resolver->reject(CacheStorageError::createException(*reason)); | 131 m_resolver->reject(CacheStorageError::createException(*reason)); |
131 m_resolver.clear(); | 132 m_resolver.clear(); |
132 } | 133 } |
133 | 134 |
134 private: | 135 private: |
135 RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; | 136 RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
136 }; | 137 }; |
137 | 138 |
138 ScriptPromise rejectAsNotImplemented(ScriptState* scriptState) | 139 // This class provides Promise.all() for ScriptPromise. |
139 { | 140 // TODO(nhiroki): Move this somewhere else so that other components can reuse. |
140 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::crea
te(NotSupportedError, "Cache is not implemented")); | 141 // TODO(nhiroki): Unfortunately, we have to go through V8 to wait for the fetch |
141 } | 142 // promise. It should be better to achieve this only within C++ world. |
| 143 class CacheStoragePromiseAll final : public GarbageCollectedFinalized<CacheStora
gePromiseAll> { |
| 144 public: |
| 145 CacheStoragePromiseAll(Vector<ScriptPromise> promises, PassRefPtrWillBeRawPt
r<ScriptPromiseResolver> resolver) |
| 146 : m_numberOfPendingPromises(promises.size()) |
| 147 , m_resolver(resolver) |
| 148 { |
| 149 m_values.resize(promises.size()); |
| 150 for (size_t i = 0; i < promises.size(); ++i) |
| 151 promises[i].then(createFulfillFunction(i), createRejectFunction()); |
| 152 } |
| 153 |
| 154 void onFulfilled(size_t index, const ScriptValue& value) |
| 155 { |
| 156 ASSERT(index < m_values.size()); |
| 157 if (m_isSettled) |
| 158 return; |
| 159 m_values[index] = value; |
| 160 if (--m_numberOfPendingPromises > 0) |
| 161 return; |
| 162 m_isSettled = true; |
| 163 m_resolver->resolve(m_values); |
| 164 } |
| 165 |
| 166 void onRejected(const ScriptValue& value) |
| 167 { |
| 168 if (m_isSettled) |
| 169 return; |
| 170 m_isSettled = true; |
| 171 m_resolver->reject(value); |
| 172 } |
| 173 |
| 174 ScriptPromise promise() { return m_resolver->promise(); } |
| 175 |
| 176 DEFINE_INLINE_VIRTUAL_TRACE() |
| 177 { |
| 178 visitor->trace(m_resolver); |
| 179 visitor->trace(m_values); |
| 180 } |
| 181 |
| 182 private: |
| 183 class AdapterFunction : public ScriptFunction { |
| 184 public: |
| 185 enum ResolveType { |
| 186 Fulfilled, |
| 187 Rejected, |
| 188 }; |
| 189 |
| 190 static v8::Local<v8::Function> create(ScriptState* scriptState, ResolveT
ype resolveType, size_t index, CacheStoragePromiseAll* promiseAll) |
| 191 { |
| 192 AdapterFunction* self = new AdapterFunction(scriptState, resolveType
, index, promiseAll); |
| 193 return self->bindToV8Function(); |
| 194 } |
| 195 |
| 196 DEFINE_INLINE_VIRTUAL_TRACE() |
| 197 { |
| 198 visitor->trace(m_promiseAll); |
| 199 ScriptFunction::trace(visitor); |
| 200 } |
| 201 |
| 202 private: |
| 203 AdapterFunction(ScriptState* scriptState, ResolveType resolveType, size_
t index, CacheStoragePromiseAll* promiseAll) |
| 204 : ScriptFunction(scriptState) |
| 205 , m_resolveType(resolveType) |
| 206 , m_index(index) |
| 207 , m_promiseAll(promiseAll) { } |
| 208 |
| 209 ScriptValue call(ScriptValue value) override |
| 210 { |
| 211 if (m_resolveType == Fulfilled) |
| 212 m_promiseAll->onFulfilled(m_index, value); |
| 213 else |
| 214 m_promiseAll->onRejected(value); |
| 215 return ScriptValue(scriptState(), m_promiseAll->promise().v8Value())
; |
| 216 } |
| 217 |
| 218 const ResolveType m_resolveType; |
| 219 const size_t m_index; |
| 220 Member<CacheStoragePromiseAll> m_promiseAll; |
| 221 }; |
| 222 |
| 223 v8::Local<v8::Function> createFulfillFunction(size_t index) |
| 224 { |
| 225 return AdapterFunction::create(m_resolver->scriptState(), AdapterFunctio
n::Fulfilled, index, this); |
| 226 } |
| 227 |
| 228 v8::Local<v8::Function> createRejectFunction() |
| 229 { |
| 230 return AdapterFunction::create(m_resolver->scriptState(), AdapterFunctio
n::Rejected, 0, this); |
| 231 } |
| 232 |
| 233 size_t m_numberOfPendingPromises; |
| 234 RefPtrWillBeMember<ScriptPromiseResolver> m_resolver; |
| 235 bool m_isSettled = false; |
| 236 Vector<ScriptValue> m_values; |
| 237 }; |
142 | 238 |
143 } // namespace | 239 } // namespace |
144 | 240 |
145 class Cache::FetchResolvedForAdd final : public ScriptFunction { | 241 class Cache::FetchResolvedForAdd final : public ScriptFunction { |
146 public: | 242 public: |
147 static v8::Local<v8::Function> create(ScriptState* scriptState, Cache* cache
, Request* request) | 243 static v8::Local<v8::Function> create(ScriptState* scriptState, Cache* cache
, const HeapVector<Member<Request>>& requests) |
148 { | 244 { |
149 FetchResolvedForAdd* self = new FetchResolvedForAdd(scriptState, cache,
request); | 245 FetchResolvedForAdd* self = new FetchResolvedForAdd(scriptState, cache,
requests); |
150 return self->bindToV8Function(); | 246 return self->bindToV8Function(); |
151 } | 247 } |
152 | 248 |
153 ScriptValue call(ScriptValue value) override | 249 ScriptValue call(ScriptValue value) override |
154 { | 250 { |
155 Response* response = V8Response::toImplWithTypeCheck(scriptState()->isol
ate(), value.v8Value()); | 251 NonThrowableExceptionState exceptionState; |
156 ScriptPromise putPromise = m_cache->putImpl(scriptState(), HeapVector<Me
mber<Request>>(1, m_request), HeapVector<Member<Response>>(1, response)); | 252 HeapVector<Member<Response>> responses = toMemberNativeArray<Response, V
8Response>(value.v8Value(), m_requests.size(), scriptState()->isolate(), excepti
onState); |
| 253 ScriptPromise putPromise = m_cache->putImpl(scriptState(), m_requests, r
esponses); |
157 return ScriptValue(scriptState(), putPromise.v8Value()); | 254 return ScriptValue(scriptState(), putPromise.v8Value()); |
158 } | 255 } |
159 | 256 |
160 DEFINE_INLINE_VIRTUAL_TRACE() | 257 DEFINE_INLINE_VIRTUAL_TRACE() |
161 { | 258 { |
162 visitor->trace(m_cache); | 259 visitor->trace(m_cache); |
163 visitor->trace(m_request); | 260 visitor->trace(m_requests); |
164 ScriptFunction::trace(visitor); | 261 ScriptFunction::trace(visitor); |
165 } | 262 } |
166 | 263 |
167 private: | 264 private: |
168 FetchResolvedForAdd(ScriptState* scriptState, Cache* cache, Request* request
) | 265 FetchResolvedForAdd(ScriptState* scriptState, Cache* cache, const HeapVector
<Member<Request>>& requests) |
169 : ScriptFunction(scriptState) | 266 : ScriptFunction(scriptState) |
170 , m_cache(cache) | 267 , m_cache(cache) |
171 , m_request(request) | 268 , m_requests(requests) |
172 { | 269 { |
173 } | 270 } |
174 | 271 |
175 Member<Cache> m_cache; | 272 Member<Cache> m_cache; |
176 Member<Request> m_request; | 273 HeapVector<Member<Request>> m_requests; |
177 }; | 274 }; |
178 | 275 |
179 class Cache::BarrierCallbackForPut final : public GarbageCollectedFinalized<Barr
ierCallbackForPut> { | 276 class Cache::BarrierCallbackForPut final : public GarbageCollectedFinalized<Barr
ierCallbackForPut> { |
180 public: | 277 public: |
181 BarrierCallbackForPut(int numberOfOperations, Cache* cache, PassRefPtrWillBe
RawPtr<ScriptPromiseResolver> resolver) | 278 BarrierCallbackForPut(int numberOfOperations, Cache* cache, PassRefPtrWillBe
RawPtr<ScriptPromiseResolver> resolver) |
182 : m_numberOfRemainingOperations(numberOfOperations) | 279 : m_numberOfRemainingOperations(numberOfOperations) |
183 , m_cache(cache) | 280 , m_cache(cache) |
184 , m_resolver(resolver) | 281 , m_resolver(resolver) |
185 { | 282 { |
186 ASSERT(0 < m_numberOfRemainingOperations); | 283 ASSERT(0 < m_numberOfRemainingOperations); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 return matchAllImpl(scriptState, request.getAsRequest(), options); | 388 return matchAllImpl(scriptState, request.getAsRequest(), options); |
292 Request* newRequest = Request::create(scriptState, request.getAsUSVString(),
exceptionState); | 389 Request* newRequest = Request::create(scriptState, request.getAsUSVString(),
exceptionState); |
293 if (exceptionState.hadException()) | 390 if (exceptionState.hadException()) |
294 return ScriptPromise(); | 391 return ScriptPromise(); |
295 return matchAllImpl(scriptState, newRequest, options); | 392 return matchAllImpl(scriptState, newRequest, options); |
296 } | 393 } |
297 | 394 |
298 ScriptPromise Cache::add(ScriptState* scriptState, const RequestInfo& request, E
xceptionState& exceptionState) | 395 ScriptPromise Cache::add(ScriptState* scriptState, const RequestInfo& request, E
xceptionState& exceptionState) |
299 { | 396 { |
300 ASSERT(!request.isNull()); | 397 ASSERT(!request.isNull()); |
301 Request* newRequest; | 398 HeapVector<Member<Request>> requests; |
302 if (request.isRequest()) { | 399 if (request.isRequest()) { |
303 newRequest = request.getAsRequest(); | 400 requests.append(request.getAsRequest()); |
304 } else { | 401 } else { |
305 newRequest = Request::create(scriptState, request.getAsUSVString(), exce
ptionState); | 402 requests.append(Request::create(scriptState, request.getAsUSVString(), e
xceptionState)); |
306 | |
307 if (exceptionState.hadException()) | 403 if (exceptionState.hadException()) |
308 return ScriptPromise(); | 404 return ScriptPromise(); |
309 } | 405 } |
310 | 406 |
311 Vector<Request*> requestVector; | 407 return addAllImpl(scriptState, requests, exceptionState); |
312 requestVector.append(newRequest); | |
313 return addAllImpl(scriptState, requestVector, exceptionState); | |
314 } | 408 } |
315 | 409 |
316 ScriptPromise Cache::addAll(ScriptState* scriptState, const Vector<ScriptValue>&
rawRequests) | 410 ScriptPromise Cache::addAll(ScriptState* scriptState, const HeapVector<RequestIn
fo>& rawRequests, ExceptionState& exceptionState) |
317 { | 411 { |
318 // FIXME: Implement this. | 412 HeapVector<Member<Request>> requests; |
319 return rejectAsNotImplemented(scriptState); | 413 for (RequestInfo request : rawRequests) { |
| 414 if (request.isRequest()) { |
| 415 requests.append(request.getAsRequest()); |
| 416 } else { |
| 417 requests.append(Request::create(scriptState, request.getAsUSVString(
), exceptionState)); |
| 418 if (exceptionState.hadException()) |
| 419 return ScriptPromise(); |
| 420 } |
| 421 } |
| 422 |
| 423 return addAllImpl(scriptState, requests, exceptionState); |
320 } | 424 } |
321 | 425 |
322 ScriptPromise Cache::deleteFunction(ScriptState* scriptState, const RequestInfo&
request, const CacheQueryOptions& options, ExceptionState& exceptionState) | 426 ScriptPromise Cache::deleteFunction(ScriptState* scriptState, const RequestInfo&
request, const CacheQueryOptions& options, ExceptionState& exceptionState) |
323 { | 427 { |
324 ASSERT(!request.isNull()); | 428 ASSERT(!request.isNull()); |
325 if (request.isRequest()) | 429 if (request.isRequest()) |
326 return deleteImpl(scriptState, request.getAsRequest(), options); | 430 return deleteImpl(scriptState, request.getAsRequest(), options); |
327 Request* newRequest = Request::create(scriptState, request.getAsUSVString(),
exceptionState); | 431 Request* newRequest = Request::create(scriptState, request.getAsUSVString(),
exceptionState); |
328 if (exceptionState.hadException()) | 432 if (exceptionState.hadException()) |
329 return ScriptPromise(); | 433 return ScriptPromise(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 { | 491 { |
388 WebServiceWorkerRequest webRequest; | 492 WebServiceWorkerRequest webRequest; |
389 request->populateWebServiceWorkerRequest(webRequest); | 493 request->populateWebServiceWorkerRequest(webRequest); |
390 | 494 |
391 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); | 495 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); |
392 const ScriptPromise promise = resolver->promise(); | 496 const ScriptPromise promise = resolver->promise(); |
393 m_webCache->dispatchMatchAll(new CacheWithResponsesCallbacks(resolver), webR
equest, toWebQueryParams(options)); | 497 m_webCache->dispatchMatchAll(new CacheWithResponsesCallbacks(resolver), webR
equest, toWebQueryParams(options)); |
394 return promise; | 498 return promise; |
395 } | 499 } |
396 | 500 |
397 ScriptPromise Cache::addAllImpl(ScriptState* scriptState, const Vector<Request*>
& requests, ExceptionState& exceptionState) | 501 ScriptPromise Cache::addAllImpl(ScriptState* scriptState, const HeapVector<Membe
r<Request>>& requests, ExceptionState& exceptionState) |
398 { | 502 { |
399 // TODO(gavinp,nhiroki): Implement addAll for more than one element. | |
400 ASSERT(requests.size() == 1); | |
401 | |
402 Vector<RequestInfo> requestInfos; | 503 Vector<RequestInfo> requestInfos; |
403 requestInfos.resize(requests.size()); | 504 requestInfos.resize(requests.size()); |
| 505 Vector<ScriptPromise> promises; |
| 506 promises.resize(requests.size()); |
404 for (size_t i = 0; i < requests.size(); ++i) { | 507 for (size_t i = 0; i < requests.size(); ++i) { |
405 if (!requests[i]->url().protocolIsInHTTPFamily()) | 508 if (!requests[i]->url().protocolIsInHTTPFamily()) |
406 return ScriptPromise::reject(scriptState, V8ThrowException::createTy
peError(scriptState->isolate(), "Add/AddAll does not support schemes other than
\"http\" or \"https\"")); | 509 return ScriptPromise::reject(scriptState, V8ThrowException::createTy
peError(scriptState->isolate(), "Add/AddAll does not support schemes other than
\"http\" or \"https\"")); |
407 if (requests[i]->method() != "GET") | 510 if (requests[i]->method() != "GET") |
408 return ScriptPromise::reject(scriptState, V8ThrowException::createTy
peError(scriptState->isolate(), "Add/AddAll only supports the GET request method
.")); | 511 return ScriptPromise::reject(scriptState, V8ThrowException::createTy
peError(scriptState->isolate(), "Add/AddAll only supports the GET request method
.")); |
409 requestInfos[i].setRequest(requests[i]); | 512 requestInfos[i].setRequest(requests[i]); |
| 513 |
| 514 promises[i] = m_scopedFetcher->fetch(scriptState, requestInfos[i], Dicti
onary(), exceptionState); |
410 } | 515 } |
411 | 516 |
412 ScriptPromise fetchPromise = m_scopedFetcher->fetch(scriptState, requestInfo
s[0], Dictionary(), exceptionState); | 517 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); |
413 return fetchPromise.then(FetchResolvedForAdd::create(scriptState, this, requ
ests[0])); | 518 CacheStoragePromiseAll* promiseAll = new CacheStoragePromiseAll(promises, re
solver.get()); |
| 519 return promiseAll->promise().then(FetchResolvedForAdd::create(scriptState, t
his, requests)); |
414 } | 520 } |
415 | 521 |
416 ScriptPromise Cache::deleteImpl(ScriptState* scriptState, const Request* request
, const CacheQueryOptions& options) | 522 ScriptPromise Cache::deleteImpl(ScriptState* scriptState, const Request* request
, const CacheQueryOptions& options) |
417 { | 523 { |
418 WebVector<WebServiceWorkerCache::BatchOperation> batchOperations(size_t(1)); | 524 WebVector<WebServiceWorkerCache::BatchOperation> batchOperations(size_t(1)); |
419 batchOperations[0].operationType = WebServiceWorkerCache::OperationTypeDelet
e; | 525 batchOperations[0].operationType = WebServiceWorkerCache::OperationTypeDelet
e; |
420 request->populateWebServiceWorkerRequest(batchOperations[0].request); | 526 request->populateWebServiceWorkerRequest(batchOperations[0].request); |
421 batchOperations[0].matchParams = toWebQueryParams(options); | 527 batchOperations[0].matchParams = toWebQueryParams(options); |
422 | 528 |
423 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); | 529 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::
create(scriptState); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 m_webCache->dispatchKeys(new CacheWithRequestsCallbacks(resolver), 0, toWebQ
ueryParams(options)); | 599 m_webCache->dispatchKeys(new CacheWithRequestsCallbacks(resolver), 0, toWebQ
ueryParams(options)); |
494 return promise; | 600 return promise; |
495 } | 601 } |
496 | 602 |
497 WebServiceWorkerCache* Cache::webCache() const | 603 WebServiceWorkerCache* Cache::webCache() const |
498 { | 604 { |
499 return m_webCache.get(); | 605 return m_webCache.get(); |
500 } | 606 } |
501 | 607 |
502 } // namespace blink | 608 } // namespace blink |
OLD | NEW |