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#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_ 6#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_ 7 8#include "base/callback.h" 9#include "base/files/file_path.h" 10#include "base/memory/ref_counted.h" 11#include "base/memory/weak_ptr.h" 12#include "content/common/service_worker/service_worker_types.h" 13#include "net/base/completion_callback.h" 14#include "net/disk_cache/disk_cache.h" 15 16namespace net { 17class URLRequestContext; 18class IOBufferWithSize; 19} 20 21namespace storage { 22class BlobData; 23class BlobDataHandle; 24class BlobStorageContext; 25} 26 27namespace content { 28class ChromeBlobStorageContext; 29class ServiceWorkerRequestResponseHeaders; 30 31// TODO(jkarlin): Unload cache backend from memory once the cache object is no 32// longer referenced in javascript. 33 34// Represents a ServiceWorker Cache as seen in 35// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html. 36// InitializeIfNeeded must be called before calling the other public members. 37class CONTENT_EXPORT ServiceWorkerCache 38 : public base::RefCounted<ServiceWorkerCache> { 39 public: 40 enum ErrorType { 41 ErrorTypeOK = 0, 42 ErrorTypeExists, 43 ErrorTypeStorage, 44 ErrorTypeNotFound 45 }; 46 enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY }; 47 typedef base::Callback<void(ErrorType)> ErrorCallback; 48 typedef base::Callback<void(ErrorType, 49 scoped_ptr<ServiceWorkerResponse>, 50 scoped_ptr<storage::BlobDataHandle>)> 51 ResponseCallback; 52 typedef std::vector<ServiceWorkerFetchRequest> Requests; 53 typedef base::Callback<void(ErrorType, scoped_ptr<Requests>)> 54 RequestsCallback; 55 56 static scoped_refptr<ServiceWorkerCache> CreateMemoryCache( 57 net::URLRequestContext* request_context, 58 base::WeakPtr<storage::BlobStorageContext> blob_context); 59 static scoped_refptr<ServiceWorkerCache> CreatePersistentCache( 60 const base::FilePath& path, 61 net::URLRequestContext* request_context, 62 base::WeakPtr<storage::BlobStorageContext> blob_context); 63 64 // Returns ErrorTypeNotFound if not found. The callback will always be called. 65 void Match(scoped_ptr<ServiceWorkerFetchRequest> request, 66 const ResponseCallback& callback); 67 68 // Puts the request and response object in the cache. The response body (if 69 // present) is stored in the cache, but not the request body. Returns 70 // ErrorTypeOK on success. The callback will always be called. 71 void Put(scoped_ptr<ServiceWorkerFetchRequest> request, 72 scoped_ptr<ServiceWorkerResponse> response, 73 const ErrorCallback& callback); 74 75 // Returns ErrorNotFound if not found. Otherwise deletes and returns 76 // ErrorTypeOK. The callback will always be called. 77 void Delete(scoped_ptr<ServiceWorkerFetchRequest> request, 78 const ErrorCallback& callback); 79 80 // TODO(jkarlin): Have keys take an optional ServiceWorkerFetchRequest. 81 // Returns ErrorTypeOK and a vector of requests if there are no errors. The 82 // callback will always be called. 83 void Keys(const RequestsCallback& callback); 84 85 // Prevent further operations on this object and delete the backend. 86 void Close(); 87 88 void set_backend(scoped_ptr<disk_cache::Backend> backend) { 89 backend_ = backend.Pass(); 90 } 91 92 base::WeakPtr<ServiceWorkerCache> AsWeakPtr(); 93 94 private: 95 friend class base::RefCounted<ServiceWorkerCache>; 96 97 struct KeysContext; 98 typedef std::vector<disk_cache::Entry*> Entries; 99 100 ServiceWorkerCache(const base::FilePath& path, 101 net::URLRequestContext* request_context, 102 base::WeakPtr<storage::BlobStorageContext> blob_context); 103 104 // Operations in progress will complete after the cache is deleted but pending 105 // operations (those operations waiting for init to finish) won't. 106 virtual ~ServiceWorkerCache(); 107 108 void PutImpl(scoped_ptr<ServiceWorkerFetchRequest> request, 109 scoped_ptr<ServiceWorkerResponse> response, 110 scoped_ptr<storage::BlobDataHandle> blob_data_handle, 111 const ErrorCallback& callback); 112 113 // Static callbacks for the Keys function. 114 static void KeysDidOpenNextEntry(scoped_ptr<KeysContext> keys_context, 115 int rv); 116 static void KeysProcessNextEntry(scoped_ptr<KeysContext> keys_context, 117 const Entries::iterator& iter); 118 static void KeysDidReadHeaders( 119 scoped_ptr<KeysContext> keys_context, 120 const Entries::iterator& iter, 121 scoped_ptr<ServiceWorkerRequestResponseHeaders> headers); 122 123 // Loads the backend and calls the callback with the result (true for 124 // success). The callback will always be called. 125 void CreateBackend(const ErrorCallback& callback); 126 127 void Init(const base::Closure& callback); 128 void InitDone(ErrorType error); 129 130 // The backend can be deleted via the Close function at any time so always 131 // check for its existence before use. 132 scoped_ptr<disk_cache::Backend> backend_; 133 base::FilePath path_; 134 net::URLRequestContext* request_context_; 135 base::WeakPtr<storage::BlobStorageContext> blob_storage_context_; 136 bool initialized_; 137 std::vector<base::Closure> init_callbacks_; 138 139 base::WeakPtrFactory<ServiceWorkerCache> weak_ptr_factory_; 140 141 DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCache); 142}; 143 144} // namespace content 145 146#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_ 147