16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// found in the LICENSE file.
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/browser/service_worker/service_worker_cache.h"
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <string>
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/files/file_path.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/guid.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/message_loop/message_loop_proxy.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/strings/string_util.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/service_worker/service_worker_cache.pb.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/browser_thread.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/io_buffer.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/net_errors.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/disk_cache/disk_cache.h"
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/url_request/url_request_context.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_data_handle.h"
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_storage_context.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/blob/blob_url_request_job_factory.h"
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace content {
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr;
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef base::Callback<void(bool)> BoolCallback;
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EntryBoolCallback;
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef base::Callback<void(scoped_ptr<ServiceWorkerRequestResponseHeaders>)>
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    HeadersCallback;
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccienum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY };
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The maximum size of an individual cache. Ultimately cache size is controlled
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// per-origin.
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kMaxCacheBytes = 512 * 1024 * 1024;
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Buffer size for cache and blob reading/writing.
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kBufferSize = 1024 * 512;
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct ResponseReadContext {
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ResponseReadContext(scoped_refptr<net::IOBufferWithSize> buff,
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      scoped_refptr<storage::BlobData> blob)
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : buffer(buff), blob_data(blob), total_bytes_read(0) {}
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<net::IOBufferWithSize> buffer;
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<storage::BlobData> blob_data;
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int total_bytes_read;
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(ResponseReadContext);
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Streams data from a blob and writes it to a given disk_cache::Entry.
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass BlobReader : public net::URLRequest::Delegate {
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      EntryBoolCallback;
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BlobReader(disk_cache::ScopedEntryPtr entry)
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : cache_entry_offset_(0),
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        buffer_(new net::IOBufferWithSize(kBufferSize)),
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        weak_ptr_factory_(this) {
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(entry);
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    entry_ = entry.Pass();
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void StreamBlobToCache(net::URLRequestContext* request_context,
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         scoped_ptr<storage::BlobDataHandle> blob_data_handle,
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         const EntryBoolCallback& callback) {
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback_ = callback;
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest(
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        blob_data_handle.Pass(), request_context, this);
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    blob_request_->Start();
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // net::URLRequest::Delegate overrides for reading blobs.
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnReceivedRedirect(net::URLRequest* request,
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  const net::RedirectInfo& redirect_info,
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  bool* defer_redirect) OVERRIDE {
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NOTREACHED();
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnAuthRequired(net::URLRequest* request,
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              net::AuthChallengeInfo* auth_info) OVERRIDE {
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NOTREACHED();
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnCertificateRequested(
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::URLRequest* request,
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::SSLCertRequestInfo* cert_request_info) OVERRIDE {
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NOTREACHED();
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnSSLCertificateError(net::URLRequest* request,
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     const net::SSLInfo& ssl_info,
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     bool fatal) OVERRIDE {
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NOTREACHED();
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnBeforeNetworkStart(net::URLRequest* request,
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                    bool* defer) OVERRIDE {
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    NOTREACHED();
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!request->status().is_success()) {
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback_.Run(entry_.Pass(), false);
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReadFromBlob();
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void ReadFromBlob() {
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int bytes_read = 0;
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool done =
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read);
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (done)
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      OnReadCompleted(blob_request_.get(), bytes_read);
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnReadCompleted(net::URLRequest* request,
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               int bytes_read) OVERRIDE {
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!request->status().is_success()) {
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback_.Run(entry_.Pass(), false);
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (bytes_read == 0) {
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback_.Run(entry_.Pass(), true);
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::CompletionCallback cache_write_callback =
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&BlobReader::DidWriteDataToEntry,
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   weak_ptr_factory_.GetWeakPtr(),
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   bytes_read);
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int rv = entry_->WriteData(INDEX_RESPONSE_BODY,
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               cache_entry_offset_,
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               buffer_.get(),
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               bytes_read,
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               cache_write_callback,
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               true /* truncate */);
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (rv != net::ERR_IO_PENDING)
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cache_write_callback.Run(rv);
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void DidWriteDataToEntry(int expected_bytes, int rv) {
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (rv != expected_bytes) {
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback_.Run(entry_.Pass(), false);
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cache_entry_offset_ += rv;
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ReadFromBlob();
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int cache_entry_offset_;
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::ScopedEntryPtr entry_;
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<net::URLRequest> blob_request_;
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EntryBoolCallback callback_;
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<net::IOBufferWithSize> buffer_;
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WeakPtrFactory<BlobReader> weak_ptr_factory_;
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Put callbacks
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PutDidCreateEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<ServiceWorkerResponse> response,
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       const ServiceWorkerCache::ErrorCallback& callback,
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<disk_cache::Entry*> entryptr,
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<storage::BlobDataHandle> blob_data_handle,
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       net::URLRequestContext* request_context,
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       int rv);
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PutDidWriteHeaders(scoped_ptr<ServiceWorkerResponse> response,
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        const ServiceWorkerCache::ErrorCallback& callback,
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        disk_cache::ScopedEntryPtr entry,
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        scoped_ptr<storage::BlobDataHandle> blob_data_handle,
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        net::URLRequestContext* request_context,
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        int expected_bytes,
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        int rv);
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PutDidWriteBlobToCache(const ServiceWorkerCache::ErrorCallback& callback,
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            scoped_ptr<BlobReader> blob_reader,
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            disk_cache::ScopedEntryPtr entry,
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            bool success);
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Match callbacks
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       const ServiceWorkerCache::ResponseCallback& callback,
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       base::WeakPtr<storage::BlobStorageContext> blob_storage,
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<disk_cache::Entry*> entryptr,
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       int rv);
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDidReadHeaderData(
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerFetchRequest> request,
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ServiceWorkerCache::ResponseCallback& callback,
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::WeakPtr<storage::BlobStorageContext> blob_storage,
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    disk_cache::ScopedEntryPtr entry,
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerRequestResponseHeaders> headers);
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDidReadResponseBodyData(
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerFetchRequest> request,
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ServiceWorkerCache::ResponseCallback& callback,
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::WeakPtr<storage::BlobStorageContext> blob_storage,
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    disk_cache::ScopedEntryPtr entry,
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerResponse> response,
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ResponseReadContext> response_context,
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int rv);
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDoneWithBody(scoped_ptr<ServiceWorkerFetchRequest> request,
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       const ServiceWorkerCache::ResponseCallback& callback,
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       base::WeakPtr<storage::BlobStorageContext> blob_storage,
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<ServiceWorkerResponse> response,
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<ResponseReadContext> response_context);
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Delete callbacks
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DeleteDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        const ServiceWorkerCache::ErrorCallback& callback,
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        scoped_ptr<disk_cache::Entry*> entryptr,
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        int rv);
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copy headers out of a cache entry and into a protobuf. The callback is
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// guaranteed to be run.
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ReadHeaders(disk_cache::Entry* entry, const HeadersCallback& callback);
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ReadHeadersDidReadHeaderData(
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    disk_cache::Entry* entry,
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const HeadersCallback& callback,
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<net::IOBufferWithSize>& buffer,
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int rv);
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// CreateBackend callbacks
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            scoped_ptr<ScopedBackendPtr> backend_ptr,
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            base::WeakPtr<ServiceWorkerCache> cache,
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            int rv);
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PutDidCreateEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<ServiceWorkerResponse> response,
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       const ServiceWorkerCache::ErrorCallback& callback,
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<disk_cache::Entry*> entryptr,
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<storage::BlobDataHandle> blob_data_handle,
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       net::URLRequestContext* request_context,
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       int rv) {
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::OK) {
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeExists);
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(entryptr);
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::ScopedEntryPtr entry(*entryptr);
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerRequestResponseHeaders headers;
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  headers.set_method(request->method);
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  headers.set_status_code(response->status_code);
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  headers.set_status_text(response->status_text);
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (ServiceWorkerHeaderMap::const_iterator it = request->headers.begin();
2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != request->headers.end();
2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        headers.add_request_headers();
2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    header_map->set_name(it->first);
2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    header_map->set_value(it->second);
2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (ServiceWorkerHeaderMap::const_iterator it = response->headers.begin();
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != response->headers.end();
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerRequestResponseHeaders::HeaderMap* header_map =
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        headers.add_response_headers();
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    header_map->set_name(it->first);
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    header_map->set_value(it->second);
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<std::string> serialized(new std::string());
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!headers.SerializeToString(serialized.get())) {
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage);
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<net::StringIOBuffer> buffer(
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new net::StringIOBuffer(serialized.Pass()));
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Get a temporary copy of the entry pointer before passing it in base::Bind.
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry* tmp_entry_ptr = entry.get();
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback write_headers_callback =
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(PutDidWriteHeaders,
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(response.Pass()),
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(entry.Pass()),
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(blob_data_handle.Pass()),
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 request_context,
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 buffer->size());
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  rv = tmp_entry_ptr->WriteData(INDEX_HEADERS,
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                0 /* offset */,
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                buffer.get(),
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                buffer->size(),
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                write_headers_callback,
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                true /* truncate */);
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::ERR_IO_PENDING)
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    write_headers_callback.Run(rv);
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PutDidWriteHeaders(scoped_ptr<ServiceWorkerResponse> response,
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        const ServiceWorkerCache::ErrorCallback& callback,
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        disk_cache::ScopedEntryPtr entry,
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        scoped_ptr<storage::BlobDataHandle> blob_data_handle,
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        net::URLRequestContext* request_context,
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        int expected_bytes,
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        int rv) {
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != expected_bytes) {
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    entry->Doom();
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage);
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The metadata is written, now for the response content. The data is streamed
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // from the blob into the cache entry.
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (response->blob_uuid.empty()) {
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeOK);
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(blob_data_handle);
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<BlobReader> reader(new BlobReader(entry.Pass()));
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BlobReader* reader_ptr = reader.get();
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  reader_ptr->StreamBlobToCache(
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_context,
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      blob_data_handle.Pass(),
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          PutDidWriteBlobToCache, callback, base::Passed(reader.Pass())));
3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PutDidWriteBlobToCache(const ServiceWorkerCache::ErrorCallback& callback,
3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            scoped_ptr<BlobReader> blob_reader,
3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            disk_cache::ScopedEntryPtr entry,
3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            bool success) {
3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!success) {
3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    entry->Doom();
3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage);
3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(ServiceWorkerCache::ErrorTypeOK);
3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       const ServiceWorkerCache::ResponseCallback& callback,
3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       base::WeakPtr<storage::BlobStorageContext> blob_storage,
3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<disk_cache::Entry*> entryptr,
3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       int rv) {
3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::OK) {
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<ServiceWorkerResponse>(),
3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(entryptr);
3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::ScopedEntryPtr entry(*entryptr);
3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Copy the entry pointer before passing it in base::Bind.
3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry* tmp_entry_ptr = entry.get();
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  HeadersCallback headers_callback = base::Bind(MatchDidReadHeaderData,
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                base::Passed(request.Pass()),
3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                callback,
3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                blob_storage,
3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                base::Passed(entry.Pass()));
3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReadHeaders(tmp_entry_ptr, headers_callback);
3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool VaryMatches(const ServiceWorkerHeaderMap& request,
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 const ServiceWorkerHeaderMap& cached_request,
3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 const ServiceWorkerHeaderMap& response) {
3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerHeaderMap::const_iterator vary_iter = response.find("vary");
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (vary_iter == response.end())
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return true;
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<std::string> vary_keys;
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Tokenize(vary_iter->second, ",", &vary_keys);
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (std::vector<std::string>::const_iterator it = vary_keys.begin();
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != vary_keys.end();
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string trimmed;
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::TrimWhitespaceASCII(*it, base::TRIM_ALL, &trimmed);
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (trimmed == "*")
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerHeaderMap::const_iterator request_iter = request.find(trimmed);
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerHeaderMap::const_iterator cached_request_iter =
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        cached_request.find(trimmed);
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the header exists in one but not the other, no match.
3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if ((request_iter == request.end()) !=
3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        (cached_request_iter == cached_request.end()))
3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // If the header exists in one, it exists in both. Verify that the values
4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // are equal.
4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (request_iter != request.end() &&
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        request_iter->second != cached_request_iter->second)
4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDidReadHeaderData(
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerFetchRequest> request,
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ServiceWorkerCache::ResponseCallback& callback,
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::WeakPtr<storage::BlobStorageContext> blob_storage,
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    disk_cache::ScopedEntryPtr entry,
4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) {
4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!headers) {
4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage,
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<ServiceWorkerResponse>(),
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ServiceWorkerResponse> response(
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new ServiceWorkerResponse(request->url,
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                headers->status_code(),
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                headers->status_text(),
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ServiceWorkerHeaderMap(),
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                ""));
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (int i = 0; i < headers->response_headers_size(); ++i) {
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ServiceWorkerRequestResponseHeaders::HeaderMap header =
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        headers->response_headers(i);
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    response->headers.insert(std::make_pair(header.name(), header.value()));
4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerHeaderMap cached_request_headers;
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (int i = 0; i < headers->request_headers_size(); ++i) {
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ServiceWorkerRequestResponseHeaders::HeaderMap header =
4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        headers->request_headers(i);
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cached_request_headers[header.name()] = header.value();
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!VaryMatches(
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          request->headers, cached_request_headers, response->headers)) {
4461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
4471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<ServiceWorkerResponse>(),
4481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
4491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
4501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeOK,
4541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 response.Pass(),
4551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
4561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
4571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Stream the response body into a blob.
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!blob_storage) {
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage,
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<ServiceWorkerResponse>(),
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  response->blob_uuid = base::GenerateGUID();
4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<storage::BlobData> blob_data =
4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new storage::BlobData(response->blob_uuid);
4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<net::IOBufferWithSize> response_body_buffer(
4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new net::IOBufferWithSize(kBufferSize));
4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ResponseReadContext> read_context(
4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new ResponseReadContext(response_body_buffer, blob_data));
4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Copy the entry pointer before passing it in base::Bind.
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry* tmp_entry_ptr = entry.get();
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback read_callback =
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(MatchDidReadResponseBodyData,
4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(request.Pass()),
4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 blob_storage,
4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(entry.Pass()),
4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(response.Pass()),
4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(read_context.Pass()));
4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        0,
4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        response_body_buffer.get(),
4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        response_body_buffer->size(),
4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        read_callback);
4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (read_rv != net::ERR_IO_PENDING)
4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    read_callback.Run(read_rv);
4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDidReadResponseBodyData(
5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerFetchRequest> request,
5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ServiceWorkerCache::ResponseCallback& callback,
5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::WeakPtr<storage::BlobStorageContext> blob_storage,
5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    disk_cache::ScopedEntryPtr entry,
5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerResponse> response,
5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ResponseReadContext> response_context,
5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int rv) {
5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv < 0) {
5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage,
5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<ServiceWorkerResponse>(),
5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv == 0) {
5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    MatchDoneWithBody(request.Pass(),
5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      callback,
5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      blob_storage,
5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      response.Pass(),
5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                      response_context.Pass());
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(jkarlin): This copying of the the entire cache response into memory is
5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // awful. Create a new interface around SimpleCache that provides access the
5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // data directly from the file. See bug http://crbug.com/403493.
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  response_context->blob_data->AppendData(response_context->buffer->data(), rv);
5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  response_context->total_bytes_read += rv;
5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int total_bytes_read = response_context->total_bytes_read;
5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Grab some pointers before passing them in bind.
5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::IOBufferWithSize* buffer = response_context->buffer.get();
5321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry* tmp_entry_ptr = entry.get();
5331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback read_callback =
5351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(MatchDidReadResponseBodyData,
5361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(request.Pass()),
5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
5381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 blob_storage,
5391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(entry.Pass()),
5401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(response.Pass()),
5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(response_context.Pass()));
5421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
5441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        total_bytes_read,
5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        buffer,
5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        buffer->size(),
5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        read_callback);
5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (read_rv != net::ERR_IO_PENDING)
5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    read_callback.Run(read_rv);
5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MatchDoneWithBody(scoped_ptr<ServiceWorkerFetchRequest> request,
5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       const ServiceWorkerCache::ResponseCallback& callback,
5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       base::WeakPtr<storage::BlobStorageContext> blob_storage,
5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<ServiceWorkerResponse> response,
5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       scoped_ptr<ResponseReadContext> response_context) {
5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!blob_storage) {
5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage,
5601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<ServiceWorkerResponse>(),
5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<storage::BlobDataHandle> blob_data_handle(
5661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      blob_storage->AddFinishedBlob(response_context->blob_data.get()));
5671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(ServiceWorkerCache::ErrorTypeOK,
5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               response.Pass(),
5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               blob_data_handle.Pass());
5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DeleteDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        const ServiceWorkerCache::ErrorCallback& callback,
5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        scoped_ptr<disk_cache::Entry*> entryptr,
5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                        int rv) {
5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::OK) {
5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeNotFound);
5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(entryptr);
5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::ScopedEntryPtr entry(*entryptr);
5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  entry->Doom();
5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(ServiceWorkerCache::ErrorTypeOK);
5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ReadHeaders(disk_cache::Entry* entry, const HeadersCallback& callback) {
5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(entry);
5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<net::IOBufferWithSize> buffer(
5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback read_header_callback =
5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(ReadHeadersDidReadHeaderData, entry, callback, buffer);
5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int read_rv = entry->ReadData(
5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback);
6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (read_rv != net::ERR_IO_PENDING)
6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    read_header_callback.Run(read_rv);
6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ReadHeadersDidReadHeaderData(
6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    disk_cache::Entry* entry,
6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const HeadersCallback& callback,
6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const scoped_refptr<net::IOBufferWithSize>& buffer,
6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int rv) {
6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != buffer->size()) {
6111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(scoped_ptr<ServiceWorkerRequestResponseHeaders>());
6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
6131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ServiceWorkerRequestResponseHeaders> headers(
6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new ServiceWorkerRequestResponseHeaders());
6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!headers->ParseFromArray(buffer->data(), buffer->size())) {
6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(scoped_ptr<ServiceWorkerRequestResponseHeaders>());
6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(headers.Pass());
6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            scoped_ptr<ScopedBackendPtr> backend_ptr,
6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            base::WeakPtr<ServiceWorkerCache> cache,
6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                            int rv) {
6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::OK || !cache) {
6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ServiceWorkerCache::ErrorTypeStorage);
6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  cache->set_backend(backend_ptr->Pass());
6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  callback.Run(ServiceWorkerCache::ErrorTypeOK);
6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
6381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
6401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// The state needed to pass between ServiceWorkerCache::Keys callbacks.
6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct ServiceWorkerCache::KeysContext {
6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  KeysContext(const ServiceWorkerCache::RequestsCallback& callback,
6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              base::WeakPtr<ServiceWorkerCache> cache)
6451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : original_callback(callback),
6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        cache(cache),
6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        out_keys(new ServiceWorkerCache::Requests()),
6481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        enumerated_entry(NULL) {}
6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ~KeysContext() {
6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (size_t i = 0, max = entries.size(); i < max; ++i)
6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      entries[i]->Close();
6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (enumerated_entry)
6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      enumerated_entry->Close();
6551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The callback passed to the Keys() function.
6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerCache::RequestsCallback original_callback;
6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The ServiceWorkerCache that Keys was called on.
6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WeakPtr<ServiceWorkerCache> cache;
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The vector of open entries in the backend.
6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  Entries entries;
6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The output of the Keys function.
6671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ServiceWorkerCache::Requests> out_keys;
6681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Used for enumerating cache entries.
6701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<disk_cache::Backend::Iterator> backend_iterator;
6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry* enumerated_entry;
6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static
6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache(
6766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    net::URLRequestContext* request_context,
67703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtr<storage::BlobStorageContext> blob_context) {
6781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return make_scoped_refptr(
6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new ServiceWorkerCache(base::FilePath(), request_context, blob_context));
6806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static
6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache(
6846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const base::FilePath& path,
6856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    net::URLRequestContext* request_context,
68603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtr<storage::BlobStorageContext> blob_context) {
6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return make_scoped_refptr(
6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new ServiceWorkerCache(path, request_context, blob_context));
6896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciServiceWorkerCache::~ServiceWorkerCache() {
6926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() {
6956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return weak_ptr_factory_.GetWeakPtr();
6966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
6976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
6981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request,
6991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             scoped_ptr<ServiceWorkerResponse> response,
7001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             const ErrorCallback& callback) {
7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<storage::BlobDataHandle> blob_data_handle;
7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!response->blob_uuid.empty()) {
7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!blob_storage_context_) {
7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback.Run(ErrorTypeStorage);
7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
7071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
7081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    blob_data_handle =
7091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!blob_data_handle) {
7111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      callback.Run(ErrorTypeStorage);
7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return;
7131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
7141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::Closure continuation = base::Bind(&ServiceWorkerCache::PutImpl,
7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          weak_ptr_factory_.GetWeakPtr(),
7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          base::Passed(request.Pass()),
7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          base::Passed(response.Pass()),
7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          base::Passed(blob_data_handle.Pass()),
7211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          callback);
7221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!initialized_) {
7241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Init(continuation);
7251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
7261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  continuation.Run();
7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request,
7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               const ResponseCallback& callback) {
7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!initialized_) {
7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Init(base::Bind(&ServiceWorkerCache::Match,
7351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    weak_ptr_factory_.GetWeakPtr(),
7361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    base::Passed(request.Pass()),
7371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    callback));
7381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
7391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!backend_) {
7411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ErrorTypeStorage,
7421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<ServiceWorkerResponse>(),
7431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 scoped_ptr<storage::BlobDataHandle>());
7441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
7451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
7481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry** entry_ptr = entry.get();
7501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerFetchRequest* request_ptr = request.get();
7521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback open_entry_callback =
7541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(MatchDidOpenEntry,
7551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(request.Pass()),
7561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
7571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 blob_storage_context_,
7581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(entry.Pass()));
7591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int rv = backend_->OpenEntry(
7611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_ptr->url.spec(), entry_ptr, open_entry_callback);
7621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::ERR_IO_PENDING)
7631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    open_entry_callback.Run(rv);
7641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request,
7671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                const ErrorCallback& callback) {
7681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!initialized_) {
7691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Init(base::Bind(&ServiceWorkerCache::Delete,
7701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    weak_ptr_factory_.GetWeakPtr(),
7711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    base::Passed(request.Pass()),
7721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    callback));
7731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
7741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!backend_) {
7761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ErrorTypeStorage);
7771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
7781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
7791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
7811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry** entry_ptr = entry.get();
7831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerFetchRequest* request_ptr = request.get();
7851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback open_entry_callback =
7871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(DeleteDidOpenEntry,
7881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(request.Pass()),
7891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
7901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(entry.Pass()));
7911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int rv = backend_->OpenEntry(
7931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_ptr->url.spec(), entry_ptr, open_entry_callback);
7941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::ERR_IO_PENDING)
7951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    open_entry_callback.Run(rv);
7961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
7971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
7981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::Keys(const RequestsCallback& callback) {
7991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!initialized_) {
8001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Init(base::Bind(
8011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        &ServiceWorkerCache::Keys, weak_ptr_factory_.GetWeakPtr(), callback));
8021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
8031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
8041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!backend_) {
8051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ErrorTypeStorage, scoped_ptr<Requests>());
8061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
8071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
8081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // 1. Iterate through all of the entries, open them, and add them to a vector.
8101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // 2. For each open entry:
8111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //  2.1. Read the headers into a protobuf.
8121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //  2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key").
8131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //  2.3. Push the response into a vector of requests to be returned.
8141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // 3. Return the vector of requests (keys).
8151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The entries have to be loaded into a vector first because enumeration loops
8171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // forever if you read data from a cache entry while enumerating.
8181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<KeysContext> keys_context(
8201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new KeysContext(callback, weak_ptr_factory_.GetWeakPtr()));
8211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  keys_context->backend_iterator = backend_->CreateIterator();
8231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator;
8241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry;
8251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback open_entry_callback =
8271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass()));
8281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback);
8301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::ERR_IO_PENDING)
8321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    open_entry_callback.Run(rv);
8331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
8341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::Close() {
8361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  backend_.reset();
8371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
8381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ServiceWorkerCache::ServiceWorkerCache(
8406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const base::FilePath& path,
8416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    net::URLRequestContext* request_context,
84203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    base::WeakPtr<storage::BlobStorageContext> blob_context)
8436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : path_(path),
8446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      request_context_(request_context),
8456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      blob_storage_context_(blob_context),
8461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      initialized_(false),
8476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      weak_ptr_factory_(this) {
8486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
8496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
8501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::PutImpl(
8511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerFetchRequest> request,
8521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerResponse> response,
8531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<storage::BlobDataHandle> blob_data_handle,
8541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const ErrorCallback& callback) {
8551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!backend_) {
8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    callback.Run(ErrorTypeStorage);
8571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
8581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
8591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
8611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry** entry_ptr = entry.get();
8631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerFetchRequest* request_ptr = request.get();
8651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback create_entry_callback =
8671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(PutDidCreateEntry,
8681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(request.Pass()),
8691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(response.Pass()),
8701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
8711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(entry.Pass()),
8721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(blob_data_handle.Pass()),
8731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 request_context_);
8741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int rv = backend_->CreateEntry(
8761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request_ptr->url.spec(), entry_ptr, create_entry_callback);
8771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::ERR_IO_PENDING)
8791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    create_entry_callback.Run(rv);
8801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
8811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
8831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::KeysDidOpenNextEntry(
8841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<KeysContext> keys_context,
8851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    int rv) {
8861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv == net::ERR_FAILED) {
8871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(!keys_context->enumerated_entry);
8881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Enumeration is complete, extract the requests from the entries.
8891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Entries::iterator iter = keys_context->entries.begin();
8901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    KeysProcessNextEntry(keys_context.Pass(), iter);
8911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
8921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
8931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WeakPtr<ServiceWorkerCache> cache = keys_context->cache;
8951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv < 0 || !cache) {
8961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    keys_context->original_callback.Run(ErrorTypeStorage,
8971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        scoped_ptr<Requests>());
8981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
8991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
9001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!cache->backend_) {
9021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    keys_context->original_callback.Run(ErrorTypeNotFound,
9031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        scoped_ptr<Requests>());
9041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
9051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
9061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Store the entry.
9081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  keys_context->entries.push_back(keys_context->enumerated_entry);
9091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  keys_context->enumerated_entry = NULL;
9101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Enumerate the next entry.
9121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator;
9131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry;
9141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback open_entry_callback =
9151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass()));
9161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback);
9181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::ERR_IO_PENDING)
9201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    open_entry_callback.Run(rv);
9211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
9221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
9241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::KeysProcessNextEntry(
9251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<KeysContext> keys_context,
9261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const Entries::iterator& iter) {
9271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (iter == keys_context->entries.end()) {
9281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // All done. Return all of the keys.
9291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    keys_context->original_callback.Run(ErrorTypeOK,
9301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        keys_context->out_keys.Pass());
9311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
9321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
9331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReadHeaders(
9351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      *iter,
9361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(KeysDidReadHeaders, base::Passed(keys_context.Pass()), iter));
9371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
9381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static
9401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::KeysDidReadHeaders(
9411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<KeysContext> keys_context,
9421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const Entries::iterator& iter,
9431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<ServiceWorkerRequestResponseHeaders> headers) {
9441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  disk_cache::Entry* entry = *iter;
9451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (headers) {
9471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    keys_context->out_keys->push_back(
9481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        ServiceWorkerFetchRequest(GURL(entry->GetKey()),
9491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  headers->method(),
9501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  ServiceWorkerHeaderMap(),
9511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  GURL(),
9521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                  false));
9531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ServiceWorkerHeaderMap& req_headers =
9551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        keys_context->out_keys->back().headers;
9561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (int i = 0; i < headers->request_headers_size(); ++i) {
9581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const ServiceWorkerRequestResponseHeaders::HeaderMap header =
9591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          headers->request_headers(i);
9601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      req_headers.insert(std::make_pair(header.name(), header.value()));
9611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
9621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
9631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    entry->Doom();
9641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
9651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  KeysProcessNextEntry(keys_context.Pass(), iter + 1);
9671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
9681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) {
9701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!backend_);
9711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction.
9731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CacheType cache_type =
9741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      path_.empty() ? net::MEMORY_CACHE : net::APP_CACHE;
9751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr());
9771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Temporary pointer so that backend_ptr can be Pass()'d in Bind below.
9791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedBackendPtr* backend = backend_ptr.get();
9801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::CompletionCallback create_cache_callback =
9821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(CreateBackendDidCreate,
9831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 callback,
9841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Passed(backend_ptr.Pass()),
9851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 weak_ptr_factory_.GetWeakPtr());
9861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
9871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore
9881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // has for disk caches.
9891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int rv = disk_cache::CreateCacheBackend(
9901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      cache_type,
9911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::CACHE_BACKEND_SIMPLE,
9921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      path_,
9931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      kMaxCacheBytes,
9941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      false, /* force */
9951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(),
9961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NULL,
9971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      backend,
9981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      create_cache_callback);
9991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (rv != net::ERR_IO_PENDING)
10001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    create_cache_callback.Run(rv);
10011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
10021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::Init(const base::Closure& callback) {
10041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  init_callbacks_.push_back(callback);
10051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If this isn't the first call to Init then return as the initialization
10071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // has already started.
10081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (init_callbacks_.size() > 1u)
10091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
10101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CreateBackend(base::Bind(&ServiceWorkerCache::InitDone,
10121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                           weak_ptr_factory_.GetWeakPtr()));
10131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
10141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid ServiceWorkerCache::InitDone(ErrorType error) {
10161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  initialized_ = true;
10171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
10181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       it != init_callbacks_.end();
10191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci       ++it) {
10201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    it->Run();
10211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
10221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  init_callbacks_.clear();
10236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
10246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
10256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace content
1026