Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / serviceworkers / Cache.cpp
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
3 // found in the LICENSE file.
4
5 #include "config.h"
6 #include "modules/serviceworkers/Cache.h"
7
8 #include "bindings/core/v8/ScriptPromiseResolver.h"
9 #include "bindings/core/v8/ScriptState.h"
10 #include "bindings/core/v8/V8ThrowException.h"
11 #include "core/dom/DOMException.h"
12 #include "modules/serviceworkers/Request.h"
13 #include "modules/serviceworkers/Response.h"
14 #include "public/platform/WebServiceWorkerCache.h"
15
16 namespace blink {
17
18 namespace {
19
20 WebServiceWorkerCache::QueryParams toWebQueryParams(const QueryParams& queryParams)
21 {
22     WebServiceWorkerCache::QueryParams webQueryParams;
23     // FIXME: The queryParams.hasXXXX() calls can be removed if defaults are
24     // added to the IDL. https://github.com/slightlyoff/ServiceWorker/issues/466
25     webQueryParams.ignoreSearch = queryParams.hasIgnoreSearch() && queryParams.ignoreSearch();
26     webQueryParams.ignoreMethod = queryParams.hasIgnoreMethod() && queryParams.ignoreMethod();
27     webQueryParams.ignoreVary = queryParams.hasIgnoreVary() && queryParams.ignoreVary();
28     webQueryParams.prefixMatch = queryParams.hasPrefixMatch() && queryParams.prefixMatch();
29     webQueryParams.cacheName = queryParams.cacheName();
30     return webQueryParams;
31 }
32
33 // FIXME: Consider using CallbackPromiseAdapter.
34 class CacheMatchCallbacks : public WebServiceWorkerCache::CacheMatchCallbacks {
35     WTF_MAKE_NONCOPYABLE(CacheMatchCallbacks);
36 public:
37     CacheMatchCallbacks(PassRefPtr<ScriptPromiseResolver> resolver)
38         : m_resolver(resolver) { }
39
40     virtual void onSuccess(WebServiceWorkerResponse* webResponse) OVERRIDE
41     {
42         m_resolver->resolve(Response::create(m_resolver->scriptState()->executionContext(), *webResponse));
43         m_resolver.clear();
44     }
45
46     virtual void onError(WebServiceWorkerCacheError* reason) OVERRIDE
47     {
48         m_resolver->reject(Cache::domExceptionForCacheError(*reason));
49         m_resolver.clear();
50     }
51
52 private:
53     RefPtr<ScriptPromiseResolver> m_resolver;
54 };
55
56 // FIXME: Consider using CallbackPromiseAdapter.
57 class CacheWithResponsesCallbacks : public WebServiceWorkerCache::CacheWithResponsesCallbacks {
58     WTF_MAKE_NONCOPYABLE(CacheWithResponsesCallbacks);
59 public:
60     CacheWithResponsesCallbacks(PassRefPtr<ScriptPromiseResolver> resolver)
61         : m_resolver(resolver) { }
62
63     virtual void onSuccess(WebVector<WebServiceWorkerResponse>* webResponses) OVERRIDE
64     {
65         HeapVector<Member<Response> > responses;
66         for (size_t i = 0; i < webResponses->size(); ++i)
67             responses.append(Response::create(m_resolver->scriptState()->executionContext(), (*webResponses)[i]));
68         m_resolver->resolve(responses);
69         m_resolver.clear();
70     }
71
72     virtual void onError(WebServiceWorkerCacheError* reason) OVERRIDE
73     {
74         m_resolver->reject(Cache::domExceptionForCacheError(*reason));
75         m_resolver.clear();
76     }
77
78 private:
79     RefPtr<ScriptPromiseResolver> m_resolver;
80 };
81
82 // FIXME: Consider using CallbackPromiseAdapter.
83 class CacheWithRequestsCallbacks : public WebServiceWorkerCache::CacheWithRequestsCallbacks {
84     WTF_MAKE_NONCOPYABLE(CacheWithRequestsCallbacks);
85 public:
86     CacheWithRequestsCallbacks(PassRefPtr<ScriptPromiseResolver> resolver)
87         : m_resolver(resolver) { }
88
89     virtual void onSuccess(WebVector<WebServiceWorkerRequest>* webRequests) OVERRIDE
90     {
91         HeapVector<Member<Request> > requests;
92         for (size_t i = 0; i < webRequests->size(); ++i)
93             requests.append(Request::create(m_resolver->scriptState()->executionContext(), (*webRequests)[i]));
94         m_resolver->resolve(requests);
95         m_resolver.clear();
96     }
97
98     virtual void onError(WebServiceWorkerCacheError* reason) OVERRIDE
99     {
100         m_resolver->reject(Cache::domExceptionForCacheError(*reason));
101         m_resolver.clear();
102     }
103
104 private:
105     RefPtr<ScriptPromiseResolver> m_resolver;
106 };
107
108 ScriptPromise rejectForCacheError(ScriptState* scriptState, WebServiceWorkerCacheError error)
109 {
110     return ScriptPromise::rejectWithDOMException(scriptState, Cache::domExceptionForCacheError(error));
111 }
112
113 ScriptPromise rejectAsNotImplemented(ScriptState* scriptState)
114 {
115     return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError, "Cache is not implemented"));
116 }
117
118 } // namespace
119
120 Cache* Cache::create(WebServiceWorkerCache* webCache)
121 {
122     return new Cache(webCache);
123 }
124
125 ScriptPromise Cache::match(ScriptState* scriptState, Request* originalRequest, const QueryParams& queryParams)
126 {
127     TrackExceptionState exceptionState;
128     Request* request = Request::create(scriptState->executionContext(), originalRequest, exceptionState);
129     if (exceptionState.hadException()) {
130         // FIXME: We should throw the caught error.
131         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
132     }
133     return matchImpl(scriptState, request, queryParams);
134 }
135
136 ScriptPromise Cache::match(ScriptState* scriptState, const String& requestString, const QueryParams& queryParams)
137 {
138     TrackExceptionState exceptionState;
139     Request* request = Request::create(scriptState->executionContext(), requestString, exceptionState);
140     if (exceptionState.hadException()) {
141         // FIXME: We should throw the caught error.
142         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
143     }
144     return matchImpl(scriptState, request, queryParams);
145 }
146
147 ScriptPromise Cache::matchAll(ScriptState* scriptState, Request* originalRequest, const QueryParams& queryParams)
148 {
149     TrackExceptionState exceptionState;
150     Request* request = Request::create(scriptState->executionContext(), originalRequest, exceptionState);
151     if (exceptionState.hadException()) {
152         // FIXME: We should throw the caught error.
153         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
154     }
155     return matchAllImpl(scriptState, request, queryParams);
156 }
157
158 ScriptPromise Cache::matchAll(ScriptState* scriptState, const String& requestString, const QueryParams& queryParams)
159 {
160     TrackExceptionState exceptionState;
161     Request* request = Request::create(scriptState->executionContext(), requestString, exceptionState);
162     if (exceptionState.hadException()) {
163         // FIXME: We should throw the caught error.
164         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
165     }
166     return matchAllImpl(scriptState, request, queryParams);
167 }
168
169 ScriptPromise Cache::add(ScriptState* scriptState, Request* originalRequest)
170 {
171     TrackExceptionState exceptionState;
172     Request* request = Request::create(scriptState->executionContext(), originalRequest, exceptionState);
173     if (exceptionState.hadException()) {
174         // FIXME: We should throw the caught error.
175         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
176     }
177     return addImpl(scriptState, request);
178 }
179
180 ScriptPromise Cache::add(ScriptState* scriptState, const String& requestString)
181 {
182     TrackExceptionState exceptionState;
183     Request* request = Request::create(scriptState->executionContext(), requestString, exceptionState);
184     if (exceptionState.hadException()) {
185         // FIXME: We should throw the caught error.
186         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
187     }
188     return addImpl(scriptState, request);
189 }
190
191 ScriptPromise Cache::addAll(ScriptState* scriptState, const Vector<ScriptValue>& rawRequests)
192 {
193     // FIXME: Implement this.
194     return rejectAsNotImplemented(scriptState);
195 }
196
197 ScriptPromise Cache::deleteFunction(ScriptState* scriptState, Request* originalRequest, const QueryParams& queryParams)
198 {
199     TrackExceptionState exceptionState;
200     Request* request = Request::create(scriptState->executionContext(), originalRequest, exceptionState);
201     if (exceptionState.hadException()) {
202         // FIXME: We should throw the caught error.
203         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
204     }
205     return deleteImpl(scriptState, request, queryParams);
206 }
207
208 ScriptPromise Cache::deleteFunction(ScriptState* scriptState, const String& requestString, const QueryParams& queryParams)
209 {
210     TrackExceptionState exceptionState;
211     Request* request = Request::create(scriptState->executionContext(), requestString, exceptionState);
212     if (exceptionState.hadException()) {
213         // FIXME: We should throw the caught error.
214         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
215     }
216     return deleteImpl(scriptState, request, queryParams);
217 }
218
219 ScriptPromise Cache::put(ScriptState* scriptState, Request* originalRequest, Response* response)
220 {
221     TrackExceptionState exceptionState;
222     Request* request = Request::create(scriptState->executionContext(), originalRequest, exceptionState);
223     if (exceptionState.hadException()) {
224         // FIXME: We should throw the caught error.
225         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
226     }
227     return putImpl(scriptState, request, response);
228 }
229
230 ScriptPromise Cache::put(ScriptState* scriptState, const String& requestString, Response* response)
231 {
232     TrackExceptionState exceptionState;
233     Request* request = Request::create(scriptState->executionContext(), requestString, exceptionState);
234     if (exceptionState.hadException()) {
235         // FIXME: We should throw the caught error.
236         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
237     }
238     return putImpl(scriptState, request, response);
239 }
240
241 ScriptPromise Cache::keys(ScriptState* scriptState)
242 {
243     return keysImpl(scriptState);
244 }
245
246 ScriptPromise Cache::keys(ScriptState* scriptState, Request* originalRequest, const QueryParams& queryParams)
247 {
248     TrackExceptionState exceptionState;
249     Request* request = Request::create(scriptState->executionContext(), originalRequest, exceptionState);
250     if (exceptionState.hadException()) {
251         // FIXME: We should throw the caught error.
252         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
253     }
254     return keysImpl(scriptState, request, queryParams);
255 }
256
257 ScriptPromise Cache::keys(ScriptState* scriptState, const String& requestString, const QueryParams& queryParams)
258 {
259     TrackExceptionState exceptionState;
260     Request* request = Request::create(scriptState->executionContext(), requestString, exceptionState);
261     if (exceptionState.hadException()) {
262         // FIXME: We should throw the caught error.
263         return rejectForCacheError(scriptState, WebServiceWorkerCacheErrorNotFound);
264     }
265     return keysImpl(scriptState, request, queryParams);
266 }
267
268 Cache::Cache(WebServiceWorkerCache* webCache)
269     : m_webCache(adoptPtr(webCache)) { }
270
271 ScriptPromise Cache::matchImpl(ScriptState* scriptState, Request* request, const QueryParams& queryParams)
272 {
273     WebServiceWorkerRequest webRequest;
274     request->populateWebServiceWorkerRequest(webRequest);
275
276     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
277     const ScriptPromise promise = resolver->promise();
278     m_webCache->dispatchMatch(new CacheMatchCallbacks(resolver), webRequest, toWebQueryParams(queryParams));
279     return promise;
280 }
281
282 ScriptPromise Cache::matchAllImpl(ScriptState* scriptState, Request* request, const QueryParams& queryParams)
283 {
284     WebServiceWorkerRequest webRequest;
285     request->populateWebServiceWorkerRequest(webRequest);
286
287     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
288     const ScriptPromise promise = resolver->promise();
289     m_webCache->dispatchMatchAll(new CacheWithResponsesCallbacks(resolver), webRequest, toWebQueryParams(queryParams));
290     return promise;
291 }
292
293 ScriptPromise Cache::addImpl(ScriptState* scriptState, Request*)
294 {
295     // FIXME: Implement this.
296     return rejectAsNotImplemented(scriptState);
297 }
298
299 ScriptPromise Cache::addAllImpl(ScriptState* scriptState, Vector<Request*>)
300 {
301     // FIXME: Implement this.
302     return rejectAsNotImplemented(scriptState);
303 }
304
305 PassRefPtrWillBeRawPtr<DOMException> Cache::domExceptionForCacheError(WebServiceWorkerCacheError reason)
306 {
307     switch (reason) {
308     case WebServiceWorkerCacheErrorNotImplemented:
309         return DOMException::create(NotSupportedError, "Method is not implemented.");
310     case WebServiceWorkerCacheErrorNotFound:
311         return DOMException::create(NotFoundError, "Entry was not found.");
312     case WebServiceWorkerCacheErrorExists:
313         return DOMException::create(InvalidAccessError, "Entry already exists.");
314     default:
315         ASSERT_NOT_REACHED();
316         return DOMException::create(NotSupportedError, "Unknown error.");
317     }
318 }
319
320 ScriptPromise Cache::deleteImpl(ScriptState* scriptState, Request* request, const QueryParams& queryParams)
321 {
322     WebVector<WebServiceWorkerCache::BatchOperation> batchOperations(size_t(1));
323     batchOperations[0].operationType = WebServiceWorkerCache::OperationTypeDelete;
324     request->populateWebServiceWorkerRequest(batchOperations[0].request);
325     batchOperations[0].matchParams = toWebQueryParams(queryParams);
326
327     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
328     const ScriptPromise promise = resolver->promise();
329     m_webCache->dispatchBatch(new CacheWithResponsesCallbacks(resolver), batchOperations);
330     return promise;
331 }
332
333 ScriptPromise Cache::putImpl(ScriptState* scriptState, Request* request, Response* response)
334 {
335     WebVector<WebServiceWorkerCache::BatchOperation> batchOperations(size_t(1));
336     batchOperations[0].operationType = WebServiceWorkerCache::OperationTypePut;
337     request->populateWebServiceWorkerRequest(batchOperations[0].request);
338     response->populateWebServiceWorkerResponse(batchOperations[0].response);
339
340     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
341     const ScriptPromise promise = resolver->promise();
342     m_webCache->dispatchBatch(new CacheWithResponsesCallbacks(resolver), batchOperations);
343     return promise;
344 }
345
346 ScriptPromise Cache::keysImpl(ScriptState* scriptState)
347 {
348     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
349     const ScriptPromise promise = resolver->promise();
350     m_webCache->dispatchKeys(new CacheWithRequestsCallbacks(resolver), 0, WebServiceWorkerCache::QueryParams());
351     return promise;
352 }
353
354 ScriptPromise Cache::keysImpl(ScriptState* scriptState, Request* request, const QueryParams& queryParams)
355 {
356     WebServiceWorkerRequest webRequest;
357     request->populateWebServiceWorkerRequest(webRequest);
358
359     RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
360     const ScriptPromise promise = resolver->promise();
361     m_webCache->dispatchKeys(new CacheWithRequestsCallbacks(resolver), 0, toWebQueryParams(queryParams));
362     return promise;
363 }
364
365 } // namespace blink