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 "content/renderer/service_worker/service_worker_cache_storage_dispatcher.h"
6
7#include <map>
8#include <string>
9#include <utility>
10
11#include "base/logging.h"
12#include "base/strings/utf_string_conversions.h"
13#include "content/common/service_worker/service_worker_messages.h"
14#include "content/public/renderer/render_thread.h"
15#include "content/renderer/service_worker/service_worker_script_context.h"
16#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
17#include "third_party/WebKit/public/platform/WebServiceWorkerCache.h"
18#include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
19#include "third_party/WebKit/public/platform/WebServiceWorkerResponse.h"
20
21namespace content {
22
23using blink::WebServiceWorkerCacheError;
24using blink::WebServiceWorkerRequest;
25
26namespace {
27
28class HeaderVisitor : public blink::WebHTTPHeaderVisitor {
29 public:
30  HeaderVisitor(ServiceWorkerHeaderMap* headers) : headers_(headers) {}
31  virtual ~HeaderVisitor() {}
32
33  virtual void visitHeader(const blink::WebString& name,
34                           const blink::WebString& value) {
35    headers_->insert(ServiceWorkerHeaderMap::value_type(
36        base::UTF16ToASCII(name), base::UTF16ToASCII(value)));
37  }
38
39 private:
40  ServiceWorkerHeaderMap* headers_;
41};
42
43scoped_ptr<HeaderVisitor> MakeHeaderVisitor(ServiceWorkerHeaderMap* headers) {
44  return scoped_ptr<HeaderVisitor>(new HeaderVisitor(headers)).Pass();
45}
46
47ServiceWorkerFetchRequest FetchRequestFromWebRequest(
48    const blink::WebServiceWorkerRequest& web_request) {
49  ServiceWorkerHeaderMap headers;
50  web_request.visitHTTPHeaderFields(MakeHeaderVisitor(&headers).get());
51
52  return ServiceWorkerFetchRequest(web_request.url(),
53                                   base::UTF16ToASCII(web_request.method()),
54                                   headers, web_request.referrerUrl(),
55                                   web_request.isReload());
56}
57
58void PopulateWebRequestFromFetchRequest(
59    const ServiceWorkerFetchRequest& request,
60    blink::WebServiceWorkerRequest* web_request) {
61  web_request->setURL(request.url);
62  web_request->setMethod(base::ASCIIToUTF16(request.method));
63  for (ServiceWorkerHeaderMap::const_iterator i = request.headers.begin(),
64                                            end = request.headers.end();
65       i != end; ++i) {
66    web_request->setHeader(base::ASCIIToUTF16(i->first),
67                           base::ASCIIToUTF16(i->second));
68  }
69  web_request->setReferrer(base::ASCIIToUTF16(request.referrer.spec()),
70                           blink::WebReferrerPolicy::WebReferrerPolicyNever);
71  web_request->setIsReload(request.is_reload);
72}
73
74blink::WebVector<blink::WebServiceWorkerRequest> WebRequestsFromRequests(
75    const std::vector<ServiceWorkerFetchRequest>& requests) {
76  blink::WebVector<blink::WebServiceWorkerRequest>
77      web_requests(requests.size());
78  for (size_t i = 0; i < requests.size(); ++i)
79    PopulateWebRequestFromFetchRequest(requests[i], &(web_requests[i]));
80  return web_requests;
81}
82
83ServiceWorkerResponse ResponseFromWebResponse(
84    const blink::WebServiceWorkerResponse& web_response) {
85  ServiceWorkerHeaderMap headers;
86  web_response.visitHTTPHeaderFields(MakeHeaderVisitor(&headers).get());
87
88  return ServiceWorkerResponse(
89      web_response.url(), web_response.status(),
90      base::UTF16ToASCII(web_response.statusText()), headers,
91      base::UTF16ToASCII(web_response.blobUUID()));
92}
93
94void PopulateWebResponseFromResponse(
95    const ServiceWorkerResponse& response,
96    blink::WebServiceWorkerResponse* web_response) {
97  web_response->setURL(response.url);
98  web_response->setStatus(response.status_code);
99  web_response->setStatusText(base::ASCIIToUTF16(response.status_text));
100  for (ServiceWorkerHeaderMap::const_iterator i = response.headers.begin(),
101                                            end = response.headers.end();
102       i != end; ++i) {
103    web_response->setHeader(base::ASCIIToUTF16(i->first),
104                            base::ASCIIToUTF16(i->second));
105  }
106  // TODO(gavinp): set blob here.
107}
108
109blink::WebVector<blink::WebServiceWorkerResponse> WebResponsesFromResponses(
110    const std::vector<ServiceWorkerResponse>& responses) {
111  blink::WebVector<blink::WebServiceWorkerResponse>
112      web_responses(responses.size());
113  for (size_t i = 0; i < responses.size(); ++i)
114    PopulateWebResponseFromResponse(responses[i], &(web_responses[i]));
115  return web_responses;
116}
117
118ServiceWorkerCacheQueryParams QueryParamsFromWebQueryParams(
119    const blink::WebServiceWorkerCache::QueryParams& web_query_params) {
120  ServiceWorkerCacheQueryParams query_params;
121  query_params.ignore_search = web_query_params.ignoreSearch;
122  query_params.ignore_method = web_query_params.ignoreMethod;
123  query_params.ignore_vary = web_query_params.ignoreVary;
124  query_params.prefix_match = web_query_params.prefixMatch;
125
126  return query_params;
127}
128
129ServiceWorkerCacheOperationType CacheOperationTypeFromWebCacheOperationType(
130    blink::WebServiceWorkerCache::OperationType operation_type) {
131  switch (operation_type) {
132    case blink::WebServiceWorkerCache::OperationTypePut:
133      return SERVICE_WORKER_CACHE_OPERATION_TYPE_PUT;
134    case blink::WebServiceWorkerCache::OperationTypeDelete:
135      return SERVICE_WORKER_CACHE_OPERATION_TYPE_DELETE;
136    default:
137      return SERVICE_WORKER_CACHE_OPERATION_TYPE_UNDEFINED;
138  }
139}
140
141ServiceWorkerBatchOperation BatchOperationFromWebBatchOperation(
142    const blink::WebServiceWorkerCache::BatchOperation& web_operation) {
143  ServiceWorkerBatchOperation operation;
144  operation.operation_type =
145      CacheOperationTypeFromWebCacheOperationType(web_operation.operationType);
146  operation.request = FetchRequestFromWebRequest(web_operation.request);
147  operation.response = ResponseFromWebResponse(web_operation.response);
148  operation.match_params =
149      QueryParamsFromWebQueryParams(web_operation.matchParams);
150  return operation;
151}
152
153template<typename T>
154void ClearCallbacksMapWithErrors(T* callbacks_map) {
155  typename T::iterator iter(callbacks_map);
156  while (!iter.IsAtEnd()) {
157    blink::WebServiceWorkerCacheError reason =
158        blink::WebServiceWorkerCacheErrorNotFound;
159    iter.GetCurrentValue()->onError(&reason);
160    callbacks_map->Remove(iter.GetCurrentKey());
161    iter.Advance();
162  }
163}
164
165}  // namespace
166
167// The WebCache object is the Chromium side implementation of the Blink
168// WebServiceWorkerCache API. Most of its methods delegate directly to the
169// ServiceWorkerStorage object, which is able to assign unique IDs as well
170// as have a lifetime longer than the requests.
171class ServiceWorkerCacheStorageDispatcher::WebCache
172    : public blink::WebServiceWorkerCache {
173 public:
174  WebCache(base::WeakPtr<ServiceWorkerCacheStorageDispatcher> dispatcher,
175           int cache_id)
176      : dispatcher_(dispatcher),
177        cache_id_(cache_id) {}
178
179  virtual ~WebCache() {
180    if (dispatcher_)
181      dispatcher_->OnWebCacheDestruction(cache_id_);
182  }
183
184  // From blink::WebServiceWorkerCache:
185  virtual void dispatchMatch(CacheMatchCallbacks* callbacks,
186                             const blink::WebServiceWorkerRequest& request,
187                             const QueryParams& query_params) {
188    if (!dispatcher_)
189      return;
190    dispatcher_->dispatchMatchForCache(cache_id_, callbacks, request,
191                                       query_params);
192  }
193  virtual void dispatchMatchAll(CacheWithResponsesCallbacks* callbacks,
194                                const blink::WebServiceWorkerRequest& request,
195                                const QueryParams& query_params) {
196    if (!dispatcher_)
197      return;
198    dispatcher_->dispatchMatchAllForCache(cache_id_, callbacks, request,
199                                          query_params);
200  }
201  virtual void dispatchKeys(CacheWithRequestsCallbacks* callbacks,
202                            const blink::WebServiceWorkerRequest* request,
203                            const QueryParams& query_params) {
204    if (!dispatcher_)
205      return;
206    dispatcher_->dispatchKeysForCache(cache_id_, callbacks, request,
207                                      query_params);
208  }
209  virtual void dispatchBatch(
210      CacheWithResponsesCallbacks* callbacks,
211      const blink::WebVector<BatchOperation>& batch_operations) {
212    if (!dispatcher_)
213      return;
214    dispatcher_->dispatchBatchForCache(cache_id_, callbacks, batch_operations);
215  }
216
217 private:
218  const base::WeakPtr<ServiceWorkerCacheStorageDispatcher> dispatcher_;
219  const int cache_id_;
220};
221
222ServiceWorkerCacheStorageDispatcher::ServiceWorkerCacheStorageDispatcher(
223    ServiceWorkerScriptContext* script_context)
224    : script_context_(script_context),
225      weak_factory_(this) {}
226
227ServiceWorkerCacheStorageDispatcher::~ServiceWorkerCacheStorageDispatcher() {
228  ClearCallbacksMapWithErrors(&get_callbacks_);
229  ClearCallbacksMapWithErrors(&has_callbacks_);
230  ClearCallbacksMapWithErrors(&create_callbacks_);
231  ClearCallbacksMapWithErrors(&delete_callbacks_);
232  ClearCallbacksMapWithErrors(&keys_callbacks_);
233
234  ClearCallbacksMapWithErrors(&cache_match_callbacks_);
235  ClearCallbacksMapWithErrors(&cache_match_all_callbacks_);
236  ClearCallbacksMapWithErrors(&cache_keys_callbacks_);
237  ClearCallbacksMapWithErrors(&cache_batch_callbacks_);
238}
239
240bool ServiceWorkerCacheStorageDispatcher::OnMessageReceived(
241    const IPC::Message& message)  {
242  bool handled = true;
243  IPC_BEGIN_MESSAGE_MAP(ServiceWorkerCacheStorageDispatcher, message)
244      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageGetSuccess,
245                          OnCacheStorageGetSuccess)
246      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageHasSuccess,
247                          OnCacheStorageHasSuccess)
248      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageCreateSuccess,
249                          OnCacheStorageCreateSuccess)
250      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageDeleteSuccess,
251                          OnCacheStorageDeleteSuccess)
252      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageKeysSuccess,
253                          OnCacheStorageKeysSuccess)
254      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageGetError,
255                          OnCacheStorageGetError)
256      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageHasError,
257                          OnCacheStorageHasError)
258      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageCreateError,
259                          OnCacheStorageCreateError)
260      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageDeleteError,
261                          OnCacheStorageDeleteError)
262      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageKeysError,
263                          OnCacheStorageKeysError)
264      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchSuccess,
265                          OnCacheMatchSuccess)
266      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchAllSuccess,
267                          OnCacheMatchAllSuccess)
268      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheKeysSuccess,
269                          OnCacheKeysSuccess)
270      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheBatchSuccess,
271                          OnCacheBatchSuccess)
272      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchError,
273                          OnCacheMatchError)
274      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchAllError,
275                          OnCacheMatchAllError)
276      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheKeysError,
277                          OnCacheKeysError)
278      IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheBatchError,
279                          OnCacheBatchError)
280     IPC_MESSAGE_UNHANDLED(handled = false)
281  IPC_END_MESSAGE_MAP()
282
283  return handled;
284}
285
286void ServiceWorkerCacheStorageDispatcher::OnCacheStorageGetSuccess(
287    int request_id,
288    int cache_id) {
289  WebCache* web_cache = new WebCache(weak_factory_.GetWeakPtr(), cache_id);
290  web_caches_.AddWithID(web_cache, cache_id);
291  CacheStorageWithCacheCallbacks* callbacks = get_callbacks_.Lookup(request_id);
292  callbacks->onSuccess(web_cache);
293  get_callbacks_.Remove(request_id);
294}
295
296void ServiceWorkerCacheStorageDispatcher::OnCacheStorageHasSuccess(
297    int request_id) {
298  CacheStorageCallbacks* callbacks = has_callbacks_.Lookup(request_id);
299  callbacks->onSuccess();
300  has_callbacks_.Remove(request_id);
301}
302
303void ServiceWorkerCacheStorageDispatcher::OnCacheStorageCreateSuccess(
304    int request_id,
305    int cache_id) {
306  WebCache* web_cache = new WebCache(weak_factory_.GetWeakPtr(), cache_id);
307  web_caches_.AddWithID(web_cache, cache_id);
308  CacheStorageWithCacheCallbacks* callbacks =
309      create_callbacks_.Lookup(request_id);
310  callbacks->onSuccess(web_cache);
311  create_callbacks_.Remove(request_id);
312}
313
314void ServiceWorkerCacheStorageDispatcher::OnCacheStorageDeleteSuccess(
315    int request_id) {
316  CacheStorageCallbacks* callbacks = delete_callbacks_.Lookup(request_id);
317  callbacks->onSuccess();
318  delete_callbacks_.Remove(request_id);
319}
320
321void ServiceWorkerCacheStorageDispatcher::OnCacheStorageKeysSuccess(
322    int request_id,
323    const std::vector<base::string16>& keys) {
324  CacheStorageKeysCallbacks* callbacks = keys_callbacks_.Lookup(request_id);
325  blink::WebVector<blink::WebString> webKeys(keys.size());
326  for (size_t i = 0; i < keys.size(); ++i)
327    webKeys[i] = keys[i];
328
329  callbacks->onSuccess(&webKeys);
330  keys_callbacks_.Remove(request_id);
331}
332
333void ServiceWorkerCacheStorageDispatcher::OnCacheStorageGetError(
334      int request_id,
335      blink::WebServiceWorkerCacheError reason) {
336  CacheStorageWithCacheCallbacks* callbacks =
337      get_callbacks_.Lookup(request_id);
338  callbacks->onError(&reason);
339  get_callbacks_.Remove(request_id);
340}
341
342void ServiceWorkerCacheStorageDispatcher::OnCacheStorageHasError(
343      int request_id,
344      blink::WebServiceWorkerCacheError reason) {
345  CacheStorageCallbacks* callbacks = has_callbacks_.Lookup(request_id);
346  callbacks->onError(&reason);
347  has_callbacks_.Remove(request_id);
348}
349
350void ServiceWorkerCacheStorageDispatcher::OnCacheStorageCreateError(
351    int request_id,
352    blink::WebServiceWorkerCacheError reason) {
353  CacheStorageWithCacheCallbacks* callbacks =
354      create_callbacks_.Lookup(request_id);
355  callbacks->onError(&reason);
356  create_callbacks_.Remove(request_id);
357}
358
359void ServiceWorkerCacheStorageDispatcher::OnCacheStorageDeleteError(
360      int request_id,
361      blink::WebServiceWorkerCacheError reason) {
362  CacheStorageCallbacks* callbacks = delete_callbacks_.Lookup(request_id);
363  callbacks->onError(&reason);
364  delete_callbacks_.Remove(request_id);
365}
366
367void ServiceWorkerCacheStorageDispatcher::OnCacheStorageKeysError(
368      int request_id,
369      blink::WebServiceWorkerCacheError reason) {
370  CacheStorageKeysCallbacks* callbacks = keys_callbacks_.Lookup(request_id);
371  callbacks->onError(&reason);
372  keys_callbacks_.Remove(request_id);
373}
374
375void ServiceWorkerCacheStorageDispatcher::OnCacheMatchSuccess(
376    int request_id,
377    const ServiceWorkerResponse& response) {
378  blink::WebServiceWorkerCache::CacheMatchCallbacks* callbacks =
379      cache_match_callbacks_.Lookup(request_id);
380
381  blink::WebServiceWorkerResponse web_response;
382  PopulateWebResponseFromResponse(response, &web_response);
383  callbacks->onSuccess(&web_response);
384  cache_match_callbacks_.Remove(request_id);
385}
386
387void ServiceWorkerCacheStorageDispatcher::OnCacheMatchAllSuccess(
388    int request_id,
389    const std::vector<ServiceWorkerResponse>& responses) {
390  blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
391      cache_match_all_callbacks_.Lookup(request_id);
392
393  blink::WebVector<blink::WebServiceWorkerResponse>
394      web_responses = WebResponsesFromResponses(responses);
395  callbacks->onSuccess(&web_responses);
396  cache_match_all_callbacks_.Remove(request_id);
397}
398
399void ServiceWorkerCacheStorageDispatcher::OnCacheKeysSuccess(
400
401    int request_id,
402    const std::vector<ServiceWorkerFetchRequest>& requests) {
403  blink::WebServiceWorkerCache::CacheWithRequestsCallbacks* callbacks =
404      cache_keys_callbacks_.Lookup(request_id);
405
406  blink::WebVector<blink::WebServiceWorkerRequest>
407      web_requests = WebRequestsFromRequests(requests);
408  callbacks->onSuccess(&web_requests);
409  cache_keys_callbacks_.Remove(request_id);
410}
411
412void ServiceWorkerCacheStorageDispatcher::OnCacheBatchSuccess(
413    int request_id,
414    const std::vector<ServiceWorkerResponse>& responses) {
415  blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
416      cache_batch_callbacks_.Lookup(request_id);
417
418  blink::WebVector<blink::WebServiceWorkerResponse>
419      web_responses = WebResponsesFromResponses(responses);
420  callbacks->onSuccess(&web_responses);
421  cache_batch_callbacks_.Remove(request_id);
422}
423
424void ServiceWorkerCacheStorageDispatcher::OnCacheMatchError(
425    int request_id,
426    blink::WebServiceWorkerCacheError reason) {
427  blink::WebServiceWorkerCache::CacheMatchCallbacks* callbacks =
428      cache_match_callbacks_.Lookup(request_id);
429  callbacks->onError(&reason);
430  cache_match_callbacks_.Remove(request_id);
431}
432
433void ServiceWorkerCacheStorageDispatcher::OnCacheMatchAllError(
434    int request_id,
435    blink::WebServiceWorkerCacheError reason) {
436  blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
437      cache_match_all_callbacks_.Lookup(request_id);
438  callbacks->onError(&reason);
439  cache_match_all_callbacks_.Remove(request_id);
440}
441
442void ServiceWorkerCacheStorageDispatcher::OnCacheKeysError(
443    int request_id,
444    blink::WebServiceWorkerCacheError reason) {
445  blink::WebServiceWorkerCache::CacheWithRequestsCallbacks* callbacks =
446      cache_keys_callbacks_.Lookup(request_id);
447  callbacks->onError(&reason);
448  cache_keys_callbacks_.Remove(request_id);
449}
450
451void ServiceWorkerCacheStorageDispatcher::OnCacheBatchError(
452    int request_id,
453    blink::WebServiceWorkerCacheError reason) {
454  blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
455      cache_batch_callbacks_.Lookup(request_id);
456  callbacks->onError(&reason);
457  cache_batch_callbacks_.Remove(request_id);
458}
459
460void ServiceWorkerCacheStorageDispatcher::dispatchGet(
461    CacheStorageWithCacheCallbacks* callbacks,
462    const blink::WebString& cacheName) {
463  int request_id = get_callbacks_.Add(callbacks);
464  script_context_->Send(new ServiceWorkerHostMsg_CacheStorageGet(
465      script_context_->GetRoutingID(), request_id, cacheName));
466}
467
468void ServiceWorkerCacheStorageDispatcher::dispatchHas(
469    CacheStorageCallbacks* callbacks,
470    const blink::WebString& cacheName) {
471  int request_id = has_callbacks_.Add(callbacks);
472  script_context_->Send(new ServiceWorkerHostMsg_CacheStorageHas(
473      script_context_->GetRoutingID(), request_id, cacheName));
474}
475
476void ServiceWorkerCacheStorageDispatcher::dispatchCreate(
477    CacheStorageWithCacheCallbacks* callbacks,
478    const blink::WebString& cacheName) {
479  int request_id = create_callbacks_.Add(callbacks);
480  script_context_->Send(new ServiceWorkerHostMsg_CacheStorageCreate(
481      script_context_->GetRoutingID(), request_id, cacheName));
482}
483
484void ServiceWorkerCacheStorageDispatcher::dispatchDelete(
485    CacheStorageCallbacks* callbacks,
486    const blink::WebString& cacheName) {
487  int request_id = delete_callbacks_.Add(callbacks);
488  script_context_->Send(new ServiceWorkerHostMsg_CacheStorageDelete(
489      script_context_->GetRoutingID(), request_id, cacheName));
490}
491
492void ServiceWorkerCacheStorageDispatcher::dispatchKeys(
493    CacheStorageKeysCallbacks* callbacks) {
494  int request_id = keys_callbacks_.Add(callbacks);
495  script_context_->Send(new ServiceWorkerHostMsg_CacheStorageKeys(
496      script_context_->GetRoutingID(), request_id));
497}
498
499void ServiceWorkerCacheStorageDispatcher::dispatchMatchForCache(
500    int cache_id,
501    blink::WebServiceWorkerCache::CacheMatchCallbacks* callbacks,
502    const blink::WebServiceWorkerRequest& request,
503    const blink::WebServiceWorkerCache::QueryParams& query_params) {
504  int request_id = cache_match_callbacks_.Add(callbacks);
505
506  script_context_->Send(new ServiceWorkerHostMsg_CacheMatch(
507      script_context_->GetRoutingID(), request_id, cache_id,
508      FetchRequestFromWebRequest(request),
509      QueryParamsFromWebQueryParams(query_params)));
510}
511
512void ServiceWorkerCacheStorageDispatcher::dispatchMatchAllForCache(
513    int cache_id,
514    blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks,
515    const blink::WebServiceWorkerRequest& request,
516    const blink::WebServiceWorkerCache::QueryParams& query_params) {
517  int request_id = cache_match_all_callbacks_.Add(callbacks);
518
519  script_context_->Send(new ServiceWorkerHostMsg_CacheMatchAll(
520      script_context_->GetRoutingID(), request_id, cache_id,
521      FetchRequestFromWebRequest(request),
522      QueryParamsFromWebQueryParams(query_params)));
523}
524
525void ServiceWorkerCacheStorageDispatcher::dispatchKeysForCache(
526    int cache_id,
527    blink::WebServiceWorkerCache::CacheWithRequestsCallbacks* callbacks,
528    const blink::WebServiceWorkerRequest* request,
529    const blink::WebServiceWorkerCache::QueryParams& query_params) {
530  int request_id = cache_keys_callbacks_.Add(callbacks);
531
532  script_context_->Send(new ServiceWorkerHostMsg_CacheKeys(
533      script_context_->GetRoutingID(), request_id, cache_id,
534      request ? FetchRequestFromWebRequest(*request)
535              : ServiceWorkerFetchRequest(),
536      QueryParamsFromWebQueryParams(query_params)));
537}
538
539void ServiceWorkerCacheStorageDispatcher::dispatchBatchForCache(
540    int cache_id,
541    blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks,
542    const blink::WebVector<
543        blink::WebServiceWorkerCache::BatchOperation>& web_operations) {
544  int request_id = cache_batch_callbacks_.Add(callbacks);
545
546  std::vector<ServiceWorkerBatchOperation> operations;
547  operations.reserve(web_operations.size());
548  for (size_t i = 0; i < web_operations.size(); ++i) {
549    operations.push_back(
550        BatchOperationFromWebBatchOperation(web_operations[i]));
551  }
552
553  script_context_->Send(new ServiceWorkerHostMsg_CacheBatch(
554      script_context_->GetRoutingID(), request_id, cache_id, operations));
555}
556
557void ServiceWorkerCacheStorageDispatcher::OnWebCacheDestruction(int cache_id) {
558  web_caches_.Remove(cache_id);
559  script_context_->Send(new ServiceWorkerHostMsg_CacheClosed(
560      script_context_->GetRoutingID(), cache_id));
561}
562
563}  // namespace content
564