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/browser/service_worker/service_worker_cache_listener.h"
6
7#include "base/bind.h"
8#include "base/debug/trace_event.h"
9#include "base/strings/utf_string_conversions.h"
10#include "content/browser/service_worker/service_worker_cache_storage_manager.h"
11#include "content/browser/service_worker/service_worker_context_core.h"
12#include "content/browser/service_worker/service_worker_version.h"
13#include "content/common/service_worker/service_worker_messages.h"
14#include "third_party/WebKit/public/platform/WebServiceWorkerCacheError.h"
15
16namespace content {
17
18using blink::WebServiceWorkerCacheError;
19
20namespace {
21
22WebServiceWorkerCacheError ToWebServiceWorkerCacheError(
23    ServiceWorkerCacheStorage::CacheStorageError err) {
24  switch (err) {
25    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR:
26      NOTREACHED();
27      return blink::WebServiceWorkerCacheErrorNotImplemented;
28    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_IMPLEMENTED:
29      return blink::WebServiceWorkerCacheErrorNotImplemented;
30    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND:
31      return blink::WebServiceWorkerCacheErrorNotFound;
32    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_EXISTS:
33      return blink::WebServiceWorkerCacheErrorExists;
34    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_STORAGE:
35      // TODO(jkarlin): Changethis to CACHE_STORAGE_ERROR_STORAGE once that's
36      // added.
37      return blink::WebServiceWorkerCacheErrorNotFound;
38    case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_CLOSING:
39      // TODO(jkarlin): Update this to CACHE_STORAGE_ERROR_CLOSING once that's
40      // added.
41      return blink::WebServiceWorkerCacheErrorNotFound;
42  }
43  NOTREACHED();
44  return blink::WebServiceWorkerCacheErrorNotImplemented;
45}
46
47}  // namespace
48
49ServiceWorkerCacheListener::ServiceWorkerCacheListener(
50    ServiceWorkerVersion* version,
51    base::WeakPtr<ServiceWorkerContextCore> context)
52    : version_(version),
53      context_(context),
54      next_cache_id_(0),
55      weak_factory_(this) {
56}
57
58ServiceWorkerCacheListener::~ServiceWorkerCacheListener() {
59}
60
61bool ServiceWorkerCacheListener::OnMessageReceived(
62    const IPC::Message& message) {
63  bool handled = true;
64  IPC_BEGIN_MESSAGE_MAP(ServiceWorkerCacheListener, message)
65    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageGet,
66                        OnCacheStorageGet)
67    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageHas,
68                        OnCacheStorageHas)
69    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageCreate,
70                        OnCacheStorageCreate)
71    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageDelete,
72                        OnCacheStorageDelete)
73    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageKeys,
74                        OnCacheStorageKeys)
75    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheMatch,
76                        OnCacheMatch)
77    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheMatchAll,
78                        OnCacheMatchAll)
79    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheKeys,
80                        OnCacheKeys)
81    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheBatch,
82                        OnCacheBatch)
83    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheClosed,
84                        OnCacheClosed)
85    IPC_MESSAGE_UNHANDLED(handled = false)
86  IPC_END_MESSAGE_MAP()
87
88  return handled;
89}
90
91void ServiceWorkerCacheListener::OnCacheStorageGet(
92    int request_id,
93    const base::string16& cache_name) {
94  TRACE_EVENT0("ServiceWorker",
95               "ServiceWorkerCacheListener::OnCacheStorageGet");
96  context_->cache_manager()->GetCache(
97      version_->scope().GetOrigin(),
98      base::UTF16ToUTF8(cache_name),
99      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageGetCallback,
100                 weak_factory_.GetWeakPtr(),
101                 request_id));
102}
103
104void ServiceWorkerCacheListener::OnCacheStorageHas(
105    int request_id,
106    const base::string16& cache_name) {
107  TRACE_EVENT0("ServiceWorker",
108               "ServiceWorkerCacheListener::OnCacheStorageHas");
109  context_->cache_manager()->HasCache(
110      version_->scope().GetOrigin(),
111      base::UTF16ToUTF8(cache_name),
112      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageHasCallback,
113                 weak_factory_.GetWeakPtr(),
114                 request_id));
115}
116
117void ServiceWorkerCacheListener::OnCacheStorageCreate(
118    int request_id,
119    const base::string16& cache_name) {
120  TRACE_EVENT0("ServiceWorker",
121               "ServiceWorkerCacheListener::OnCacheStorageCreate");
122  context_->cache_manager()->CreateCache(
123      version_->scope().GetOrigin(),
124      base::UTF16ToUTF8(cache_name),
125      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageCreateCallback,
126                 weak_factory_.GetWeakPtr(),
127                 request_id));
128}
129
130void ServiceWorkerCacheListener::OnCacheStorageDelete(
131    int request_id,
132    const base::string16& cache_name) {
133  TRACE_EVENT0("ServiceWorker",
134               "ServiceWorkerCacheListener::OnCacheStorageDelete");
135  context_->cache_manager()->DeleteCache(
136      version_->scope().GetOrigin(),
137      base::UTF16ToUTF8(cache_name),
138      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageDeleteCallback,
139                 weak_factory_.GetWeakPtr(),
140                 request_id));
141}
142
143void ServiceWorkerCacheListener::OnCacheStorageKeys(int request_id) {
144  TRACE_EVENT0("ServiceWorker",
145               "ServiceWorkerCacheListener::OnCacheStorageKeys");
146  context_->cache_manager()->EnumerateCaches(
147      version_->scope().GetOrigin(),
148      base::Bind(&ServiceWorkerCacheListener::OnCacheStorageKeysCallback,
149                 weak_factory_.GetWeakPtr(),
150                 request_id));
151}
152
153void ServiceWorkerCacheListener::OnCacheMatch(
154    int request_id,
155    int cache_id,
156    const ServiceWorkerFetchRequest& request,
157    const ServiceWorkerCacheQueryParams& match_params) {
158  // TODO(gavinp,jkarlin): Implement this method.
159  Send(ServiceWorkerMsg_CacheMatchError(
160      request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
161}
162
163void ServiceWorkerCacheListener::OnCacheMatchAll(
164    int request_id,
165    int cache_id,
166    const ServiceWorkerFetchRequest& request,
167    const ServiceWorkerCacheQueryParams& match_params) {
168  // TODO(gavinp,jkarlin): Implement this method.
169  Send(ServiceWorkerMsg_CacheMatchAllError(
170      request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
171}
172
173void ServiceWorkerCacheListener::OnCacheKeys(
174    int request_id,
175    int cache_id,
176    const ServiceWorkerFetchRequest& request,
177    const ServiceWorkerCacheQueryParams& match_params) {
178  // TODO(gavinp,jkarlin): Implement this method.
179  Send(ServiceWorkerMsg_CacheKeysError(
180      request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
181}
182
183void ServiceWorkerCacheListener::OnCacheBatch(
184    int request_id,
185    int cache_id,
186    const std::vector<ServiceWorkerBatchOperation>& operations) {
187  // TODO(gavinp,jkarlin): Implement this method.
188  Send(ServiceWorkerMsg_CacheBatchError(
189      request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
190}
191
192void ServiceWorkerCacheListener::OnCacheClosed(int cache_id) {
193  // TODO(gavinp,jkarlin): Implement this method.
194}
195
196void ServiceWorkerCacheListener::Send(const IPC::Message& message) {
197  version_->embedded_worker()->SendMessage(message);
198}
199
200void ServiceWorkerCacheListener::OnCacheStorageGetCallback(
201    int request_id,
202    const scoped_refptr<ServiceWorkerCache>& cache,
203    ServiceWorkerCacheStorage::CacheStorageError error) {
204  if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
205    Send(ServiceWorkerMsg_CacheStorageGetError(
206        request_id, ToWebServiceWorkerCacheError(error)));
207    return;
208  }
209
210  CacheID cache_id = StoreCacheReference(cache);
211  Send(ServiceWorkerMsg_CacheStorageGetSuccess(request_id, cache_id));
212}
213
214void ServiceWorkerCacheListener::OnCacheStorageHasCallback(
215    int request_id,
216    bool has_cache,
217    ServiceWorkerCacheStorage::CacheStorageError error) {
218  if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
219    Send(ServiceWorkerMsg_CacheStorageHasError(
220        request_id, ToWebServiceWorkerCacheError(error)));
221    return;
222  }
223  if (!has_cache) {
224    Send(ServiceWorkerMsg_CacheStorageHasError(
225        request_id,
226        blink::WebServiceWorkerCacheErrorNotFound));
227    return;
228  }
229  Send(ServiceWorkerMsg_CacheStorageHasSuccess(request_id));
230}
231
232void ServiceWorkerCacheListener::OnCacheStorageCreateCallback(
233    int request_id,
234    const scoped_refptr<ServiceWorkerCache>& cache,
235    ServiceWorkerCacheStorage::CacheStorageError error) {
236  if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
237    Send(ServiceWorkerMsg_CacheStorageCreateError(
238        request_id, ToWebServiceWorkerCacheError(error)));
239    return;
240  }
241  CacheID cache_id = StoreCacheReference(cache);
242  Send(ServiceWorkerMsg_CacheStorageCreateSuccess(request_id, cache_id));
243}
244
245void ServiceWorkerCacheListener::OnCacheStorageDeleteCallback(
246    int request_id,
247    bool deleted,
248    ServiceWorkerCacheStorage::CacheStorageError error) {
249  if (!deleted ||
250      error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
251    Send(ServiceWorkerMsg_CacheStorageDeleteError(
252        request_id, ToWebServiceWorkerCacheError(error)));
253    return;
254  }
255  Send(ServiceWorkerMsg_CacheStorageDeleteSuccess(request_id));
256}
257
258void ServiceWorkerCacheListener::OnCacheStorageKeysCallback(
259    int request_id,
260    const std::vector<std::string>& strings,
261    ServiceWorkerCacheStorage::CacheStorageError error) {
262  if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
263    Send(ServiceWorkerMsg_CacheStorageKeysError(
264        request_id, ToWebServiceWorkerCacheError(error)));
265    return;
266  }
267
268  std::vector<base::string16> string16s;
269  for (size_t i = 0, max = strings.size(); i < max; ++i) {
270    string16s.push_back(base::UTF8ToUTF16(strings[i]));
271  }
272  Send(ServiceWorkerMsg_CacheStorageKeysSuccess(request_id, string16s));
273}
274
275ServiceWorkerCacheListener::CacheID
276ServiceWorkerCacheListener::StoreCacheReference(
277    const scoped_refptr<ServiceWorkerCache>& cache) {
278  int cache_id = next_cache_id_++;
279  id_to_cache_map_[cache_id] = cache;
280  return cache_id;
281}
282
283void ServiceWorkerCacheListener::DropCacheReference(CacheID cache_id) {
284  id_to_cache_map_.erase(cache_id);
285}
286
287}  // namespace content
288