1 // Copyright 2015 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.
5 #include "content/browser/cache_storage/cache_storage_dispatcher_host.h"
8 #include "base/logging.h"
9 #include "base/strings/string16.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/trace_event/trace_event.h"
12 #include "content/browser/bad_message.h"
13 #include "content/browser/cache_storage/cache_storage_cache.h"
14 #include "content/browser/cache_storage/cache_storage_context_impl.h"
15 #include "content/browser/cache_storage/cache_storage_manager.h"
16 #include "content/common/cache_storage/cache_storage_messages.h"
17 #include "content/public/browser/content_browser_client.h"
18 #include "content/public/common/origin_util.h"
19 #include "storage/browser/blob/blob_data_handle.h"
20 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheError.h"
26 const uint32 kFilteredMessageClasses
[] = {CacheStorageMsgStart
};
28 blink::WebServiceWorkerCacheError
ToWebServiceWorkerCacheError(
29 CacheStorageError err
) {
31 case CACHE_STORAGE_OK
:
33 return blink::WebServiceWorkerCacheErrorNotImplemented
;
34 case CACHE_STORAGE_ERROR_EXISTS
:
35 return blink::WebServiceWorkerCacheErrorExists
;
36 case CACHE_STORAGE_ERROR_STORAGE
:
37 // TODO(nhiroki): Add WebServiceWorkerCacheError equivalent to
38 // CACHE_STORAGE_ERROR_STORAGE.
39 return blink::WebServiceWorkerCacheErrorNotFound
;
40 case CACHE_STORAGE_ERROR_NOT_FOUND
:
41 return blink::WebServiceWorkerCacheErrorNotFound
;
44 return blink::WebServiceWorkerCacheErrorNotImplemented
;
47 bool OriginCanAccessCacheStorage(const GURL
& url
) {
48 return IsOriginSecure(url
);
53 CacheStorageDispatcherHost::CacheStorageDispatcherHost()
54 : BrowserMessageFilter(kFilteredMessageClasses
,
55 arraysize(kFilteredMessageClasses
)) {
58 CacheStorageDispatcherHost::~CacheStorageDispatcherHost() {
61 void CacheStorageDispatcherHost::Init(CacheStorageContextImpl
* context
) {
62 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
63 BrowserThread::PostTask(
64 BrowserThread::IO
, FROM_HERE
,
65 base::Bind(&CacheStorageDispatcherHost::CreateCacheListener
, this,
66 make_scoped_refptr(context
)));
69 void CacheStorageDispatcherHost::OnDestruct() const {
70 BrowserThread::DeleteOnIOThread::Destruct(this);
73 bool CacheStorageDispatcherHost::OnMessageReceived(
74 const IPC::Message
& message
) {
75 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
78 IPC_BEGIN_MESSAGE_MAP(CacheStorageDispatcherHost
, message
)
79 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageHas
, OnCacheStorageHas
)
80 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageOpen
, OnCacheStorageOpen
)
81 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageDelete
,
83 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageKeys
, OnCacheStorageKeys
)
84 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageMatch
,
86 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheMatch
, OnCacheMatch
)
87 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheMatchAll
, OnCacheMatchAll
)
88 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheKeys
, OnCacheKeys
)
89 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheBatch
, OnCacheBatch
)
90 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheClosed
, OnCacheClosed
)
91 IPC_MESSAGE_HANDLER(CacheStorageHostMsg_BlobDataHandled
, OnBlobDataHandled
)
92 IPC_MESSAGE_UNHANDLED(handled
= false)
96 bad_message::ReceivedBadMessage(this, bad_message::CSDH_NOT_RECOGNIZED
);
100 void CacheStorageDispatcherHost::CreateCacheListener(
101 CacheStorageContextImpl
* context
) {
102 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
106 void CacheStorageDispatcherHost::OnCacheStorageHas(
110 const base::string16
& cache_name
) {
111 TRACE_EVENT0("CacheStorage", "CacheStorageDispatcherHost::OnCacheStorageHas");
112 if (!OriginCanAccessCacheStorage(origin
)) {
113 bad_message::ReceivedBadMessage(this, bad_message::CSDH_INVALID_ORIGIN
);
116 context_
->cache_manager()->HasCache(
117 origin
, base::UTF16ToUTF8(cache_name
),
118 base::Bind(&CacheStorageDispatcherHost::OnCacheStorageHasCallback
, this,
119 thread_id
, request_id
));
122 void CacheStorageDispatcherHost::OnCacheStorageOpen(
126 const base::string16
& cache_name
) {
127 TRACE_EVENT0("CacheStorage",
128 "CacheStorageDispatcherHost::OnCacheStorageOpen");
129 if (!OriginCanAccessCacheStorage(origin
)) {
130 bad_message::ReceivedBadMessage(this, bad_message::CSDH_INVALID_ORIGIN
);
133 context_
->cache_manager()->OpenCache(
134 origin
, base::UTF16ToUTF8(cache_name
),
135 base::Bind(&CacheStorageDispatcherHost::OnCacheStorageOpenCallback
, this,
136 thread_id
, request_id
));
139 void CacheStorageDispatcherHost::OnCacheStorageDelete(
143 const base::string16
& cache_name
) {
144 TRACE_EVENT0("CacheStorage",
145 "CacheStorageDispatcherHost::OnCacheStorageDelete");
146 if (!OriginCanAccessCacheStorage(origin
)) {
147 bad_message::ReceivedBadMessage(this, bad_message::CSDH_INVALID_ORIGIN
);
150 context_
->cache_manager()->DeleteCache(
151 origin
, base::UTF16ToUTF8(cache_name
),
152 base::Bind(&CacheStorageDispatcherHost::OnCacheStorageDeleteCallback
,
153 this, thread_id
, request_id
));
156 void CacheStorageDispatcherHost::OnCacheStorageKeys(int thread_id
,
158 const GURL
& origin
) {
159 TRACE_EVENT0("CacheStorage",
160 "CacheStorageDispatcherHost::OnCacheStorageKeys");
161 if (!OriginCanAccessCacheStorage(origin
)) {
162 bad_message::ReceivedBadMessage(this, bad_message::CSDH_INVALID_ORIGIN
);
165 context_
->cache_manager()->EnumerateCaches(
167 base::Bind(&CacheStorageDispatcherHost::OnCacheStorageKeysCallback
, this,
168 thread_id
, request_id
));
171 void CacheStorageDispatcherHost::OnCacheStorageMatch(
175 const ServiceWorkerFetchRequest
& request
,
176 const CacheStorageCacheQueryParams
& match_params
) {
177 TRACE_EVENT0("CacheStorage",
178 "CacheStorageDispatcherHost::OnCacheStorageMatch");
179 if (!OriginCanAccessCacheStorage(origin
)) {
180 bad_message::ReceivedBadMessage(this, bad_message::CSDH_INVALID_ORIGIN
);
183 scoped_ptr
<ServiceWorkerFetchRequest
> scoped_request(
184 new ServiceWorkerFetchRequest(request
.url
, request
.method
,
185 request
.headers
, request
.referrer
,
188 if (match_params
.cache_name
.empty()) {
189 context_
->cache_manager()->MatchAllCaches(
190 origin
, scoped_request
.Pass(),
191 base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback
,
192 this, thread_id
, request_id
));
195 context_
->cache_manager()->MatchCache(
196 origin
, base::UTF16ToUTF8(match_params
.cache_name
), scoped_request
.Pass(),
197 base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback
, this,
198 thread_id
, request_id
));
201 void CacheStorageDispatcherHost::OnCacheMatch(
205 const ServiceWorkerFetchRequest
& request
,
206 const CacheStorageCacheQueryParams
& match_params
) {
207 IDToCacheMap::iterator it
= id_to_cache_map_
.find(cache_id
);
208 if (it
== id_to_cache_map_
.end()) {
209 Send(new CacheStorageMsg_CacheMatchError(
210 thread_id
, request_id
, blink::WebServiceWorkerCacheErrorNotFound
));
214 scoped_refptr
<CacheStorageCache
> cache
= it
->second
;
215 scoped_ptr
<ServiceWorkerFetchRequest
> scoped_request(
216 new ServiceWorkerFetchRequest(request
.url
, request
.method
,
217 request
.headers
, request
.referrer
,
219 cache
->Match(scoped_request
.Pass(),
220 base::Bind(&CacheStorageDispatcherHost::OnCacheMatchCallback
,
221 this, thread_id
, request_id
, cache
));
224 void CacheStorageDispatcherHost::OnCacheMatchAll(
228 const ServiceWorkerFetchRequest
& request
,
229 const CacheStorageCacheQueryParams
& match_params
) {
230 IDToCacheMap::iterator it
= id_to_cache_map_
.find(cache_id
);
231 if (it
== id_to_cache_map_
.end()) {
232 Send(new CacheStorageMsg_CacheMatchError(
233 thread_id
, request_id
, blink::WebServiceWorkerCacheErrorNotFound
));
237 scoped_refptr
<CacheStorageCache
> cache
= it
->second
;
238 if (request
.url
.is_empty()) {
240 base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallback
, this,
241 thread_id
, request_id
, cache
));
245 scoped_ptr
<ServiceWorkerFetchRequest
> scoped_request(
246 new ServiceWorkerFetchRequest(request
.url
, request
.method
,
247 request
.headers
, request
.referrer
,
250 scoped_request
.Pass(),
251 base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter
,
252 this, thread_id
, request_id
, cache
));
255 void CacheStorageDispatcherHost::OnCacheKeys(
259 const ServiceWorkerFetchRequest
& request
,
260 const CacheStorageCacheQueryParams
& match_params
) {
261 IDToCacheMap::iterator it
= id_to_cache_map_
.find(cache_id
);
262 if (it
== id_to_cache_map_
.end()) {
263 Send(new CacheStorageMsg_CacheKeysError(
264 thread_id
, request_id
, blink::WebServiceWorkerCacheErrorNotFound
));
268 scoped_refptr
<CacheStorageCache
> cache
= it
->second
;
270 cache
->Keys(base::Bind(&CacheStorageDispatcherHost::OnCacheKeysCallback
, this,
271 thread_id
, request_id
, cache
));
274 void CacheStorageDispatcherHost::OnCacheBatch(
278 const std::vector
<CacheStorageBatchOperation
>& operations
) {
279 IDToCacheMap::iterator it
= id_to_cache_map_
.find(cache_id
);
280 if (it
== id_to_cache_map_
.end()) {
281 Send(new CacheStorageMsg_CacheBatchError(
282 thread_id
, request_id
, blink::WebServiceWorkerCacheErrorNotFound
));
285 scoped_refptr
<CacheStorageCache
> cache
= it
->second
;
286 cache
->BatchOperation(
287 operations
, base::Bind(&CacheStorageDispatcherHost::OnCacheBatchCallback
,
288 this, thread_id
, request_id
, cache
));
291 void CacheStorageDispatcherHost::OnCacheClosed(int cache_id
) {
292 DropCacheReference(cache_id
);
295 void CacheStorageDispatcherHost::OnBlobDataHandled(const std::string
& uuid
) {
296 DropBlobDataHandle(uuid
);
299 void CacheStorageDispatcherHost::OnCacheStorageHasCallback(
303 CacheStorageError error
) {
304 if (error
!= CACHE_STORAGE_OK
) {
305 Send(new CacheStorageMsg_CacheStorageHasError(
306 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
310 Send(new CacheStorageMsg_CacheStorageHasError(
311 thread_id
, request_id
, blink::WebServiceWorkerCacheErrorNotFound
));
314 Send(new CacheStorageMsg_CacheStorageHasSuccess(thread_id
, request_id
));
317 void CacheStorageDispatcherHost::OnCacheStorageOpenCallback(
320 const scoped_refptr
<CacheStorageCache
>& cache
,
321 CacheStorageError error
) {
322 if (error
!= CACHE_STORAGE_OK
) {
323 Send(new CacheStorageMsg_CacheStorageOpenError(
324 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
327 CacheID cache_id
= StoreCacheReference(cache
);
328 Send(new CacheStorageMsg_CacheStorageOpenSuccess(thread_id
, request_id
,
332 void CacheStorageDispatcherHost::OnCacheStorageDeleteCallback(
336 CacheStorageError error
) {
337 if (!deleted
|| error
!= CACHE_STORAGE_OK
) {
338 Send(new CacheStorageMsg_CacheStorageDeleteError(
339 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
342 Send(new CacheStorageMsg_CacheStorageDeleteSuccess(thread_id
, request_id
));
345 void CacheStorageDispatcherHost::OnCacheStorageKeysCallback(
348 const std::vector
<std::string
>& strings
,
349 CacheStorageError error
) {
350 if (error
!= CACHE_STORAGE_OK
) {
351 Send(new CacheStorageMsg_CacheStorageKeysError(
352 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
356 std::vector
<base::string16
> string16s
;
357 for (size_t i
= 0, max
= strings
.size(); i
< max
; ++i
) {
358 string16s
.push_back(base::UTF8ToUTF16(strings
[i
]));
360 Send(new CacheStorageMsg_CacheStorageKeysSuccess(thread_id
, request_id
,
364 void CacheStorageDispatcherHost::OnCacheStorageMatchCallback(
367 CacheStorageError error
,
368 scoped_ptr
<ServiceWorkerResponse
> response
,
369 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
370 if (error
!= CACHE_STORAGE_OK
) {
371 Send(new CacheStorageMsg_CacheStorageMatchError(
372 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
376 if (blob_data_handle
)
377 StoreBlobDataHandle(*blob_data_handle
);
379 Send(new CacheStorageMsg_CacheStorageMatchSuccess(thread_id
, request_id
,
383 void CacheStorageDispatcherHost::OnCacheMatchCallback(
386 const scoped_refptr
<CacheStorageCache
>& cache
,
387 CacheStorageError error
,
388 scoped_ptr
<ServiceWorkerResponse
> response
,
389 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
390 if (error
!= CACHE_STORAGE_OK
) {
391 Send(new CacheStorageMsg_CacheMatchError(
392 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
396 if (blob_data_handle
)
397 StoreBlobDataHandle(*blob_data_handle
);
399 Send(new CacheStorageMsg_CacheMatchSuccess(thread_id
, request_id
, *response
));
402 void CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter(
405 const scoped_refptr
<CacheStorageCache
>& cache
,
406 CacheStorageError error
,
407 scoped_ptr
<ServiceWorkerResponse
> response
,
408 scoped_ptr
<storage::BlobDataHandle
> blob_data_handle
) {
409 scoped_ptr
<CacheStorageCache::Responses
> responses(
410 new CacheStorageCache::Responses
);
411 scoped_ptr
<CacheStorageCache::BlobDataHandles
> blob_data_handles(
412 new CacheStorageCache::BlobDataHandles
);
413 if (error
== CACHE_STORAGE_OK
) {
415 responses
->push_back(*response
);
416 if (blob_data_handle
)
417 blob_data_handles
->push_back(*blob_data_handle
);
419 OnCacheMatchAllCallback(thread_id
, request_id
, cache
, error
, responses
.Pass(),
420 blob_data_handles
.Pass());
423 void CacheStorageDispatcherHost::OnCacheMatchAllCallback(
426 const scoped_refptr
<CacheStorageCache
>& cache
,
427 CacheStorageError error
,
428 scoped_ptr
<CacheStorageCache::Responses
> responses
,
429 scoped_ptr
<CacheStorageCache::BlobDataHandles
> blob_data_handles
) {
430 if (error
!= CACHE_STORAGE_OK
&& error
!= CACHE_STORAGE_ERROR_NOT_FOUND
) {
431 Send(new CacheStorageMsg_CacheMatchAllError(
432 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
436 for (const storage::BlobDataHandle
& handle
: *blob_data_handles
)
437 StoreBlobDataHandle(handle
);
439 Send(new CacheStorageMsg_CacheMatchAllSuccess(thread_id
, request_id
,
443 void CacheStorageDispatcherHost::OnCacheKeysCallback(
446 const scoped_refptr
<CacheStorageCache
>& cache
,
447 CacheStorageError error
,
448 scoped_ptr
<CacheStorageCache::Requests
> requests
) {
449 if (error
!= CACHE_STORAGE_OK
) {
450 Send(new CacheStorageMsg_CacheKeysError(
451 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
455 CacheStorageCache::Requests out
;
457 for (CacheStorageCache::Requests::const_iterator it
= requests
->begin();
458 it
!= requests
->end(); ++it
) {
459 ServiceWorkerFetchRequest
request(it
->url
, it
->method
, it
->headers
,
460 it
->referrer
, it
->is_reload
);
461 out
.push_back(request
);
464 Send(new CacheStorageMsg_CacheKeysSuccess(thread_id
, request_id
, out
));
467 void CacheStorageDispatcherHost::OnCacheBatchCallback(
470 const scoped_refptr
<CacheStorageCache
>& cache
,
471 CacheStorageError error
) {
472 if (error
!= CACHE_STORAGE_OK
) {
473 Send(new CacheStorageMsg_CacheBatchError(
474 thread_id
, request_id
, ToWebServiceWorkerCacheError(error
)));
478 Send(new CacheStorageMsg_CacheBatchSuccess(thread_id
, request_id
));
481 CacheStorageDispatcherHost::CacheID
482 CacheStorageDispatcherHost::StoreCacheReference(
483 const scoped_refptr
<CacheStorageCache
>& cache
) {
484 int cache_id
= next_cache_id_
++;
485 id_to_cache_map_
[cache_id
] = cache
;
489 void CacheStorageDispatcherHost::DropCacheReference(CacheID cache_id
) {
490 id_to_cache_map_
.erase(cache_id
);
493 void CacheStorageDispatcherHost::StoreBlobDataHandle(
494 const storage::BlobDataHandle
& blob_data_handle
) {
495 std::pair
<UUIDToBlobDataHandleList::iterator
, bool> rv
=
496 blob_handle_store_
.insert(std::make_pair(
497 blob_data_handle
.uuid(), std::list
<storage::BlobDataHandle
>()));
498 rv
.first
->second
.push_front(storage::BlobDataHandle(blob_data_handle
));
501 void CacheStorageDispatcherHost::DropBlobDataHandle(const std::string
& uuid
) {
502 UUIDToBlobDataHandleList::iterator it
= blob_handle_store_
.find(uuid
);
503 if (it
== blob_handle_store_
.end())
505 DCHECK(!it
->second
.empty());
506 it
->second
.pop_front();
507 if (it
->second
.empty())
508 blob_handle_store_
.erase(it
);
511 } // namespace content